Re: [PATCH v2 0/7] nd/worktree-move reboot

2018-03-03 Thread Eric Sunshine
On Mon, Feb 12, 2018 at 4:49 AM, Nguyễn Thái Ngọc Duy  wrote:
> v2 basically fixes lots of comments from Eric (many thanks!): memory
> leak, typos, document updates, tests, corner case fixes.
> Interdiff:

Thanks, I finally got around to doing a full re-read of the entire
series. v2 appears to address all issues raised in my review[1] of v1.

I did find a few minor issues in tests newly added and revised in v2.
However, since v2 already migrated to 'next', rather than pointing out
the issues as review comments, I instead sent a patch[2] (built atop
nd/worktree-move-reboot) to address them.

[1]: https://public-inbox.org/git/20180124095357.19645-1-pclo...@gmail.com/
[2]: 
https://public-inbox.org/git/20180304052647.26614-1-sunsh...@sunshineco.com/


[PATCH] t2028: fix minor error and issues in newly-added "worktree move" tests

2018-03-03 Thread Eric Sunshine
Recently-added "git worktree move" tests include a minor error and a few
small issues. Specifically:

* checking non-existence of wrong file ("source" instead of
  "destination")

* unneeded redirect (">empty")

* unused variable ("toplevel")

* restoring a worktree location by means of a separate test somewhat
  distant from the test which moved it rather than using
  test_when_finished() to restore it in a self-contained fashion

Signed-off-by: Eric Sunshine 
---

This patch is built atop nd/worktree-move-reboot in 'next'.

I didn't get around to doing a proper review of nd/worktree-move-reboot
v2 [1] until after it had graduated to 'next'. Although v2 fixed all the
issues identified in my review of v1 [2], it introduced a few minor
issues of its own. This patch addresses those issues.

[1]: https://public-inbox.org/git/20180212094940.23834-1-pclo...@gmail.com/
[2]: https://public-inbox.org/git/20180124095357.19645-1-pclo...@gmail.com/

 t/t2028-worktree-move.sh | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
index 082368d8c6..d70d13dabe 100755
--- a/t/t2028-worktree-move.sh
+++ b/t/t2028-worktree-move.sh
@@ -75,7 +75,7 @@ test_expect_success 'move worktree' '
git worktree move source destination &&
test_path_is_missing source &&
git worktree list --porcelain | grep "^worktree.*/destination" &&
-   ! git worktree list --porcelain | grep "^worktree.*/source" >empty &&
+   ! git worktree list --porcelain | grep "^worktree.*/source" &&
git -C destination log --format=%s >actual2 &&
echo init >expected2 &&
test_cmp expected2 actual2
@@ -86,10 +86,10 @@ test_expect_success 'move main worktree' '
 '
 
 test_expect_success 'move worktree to another dir' '
-   toplevel="$(pwd)" &&
mkdir some-dir &&
git worktree move destination some-dir &&
-   test_path_is_missing source &&
+   test_when_finished "git worktree move some-dir/destination destination" 
&&
+   test_path_is_missing destination &&
git worktree list --porcelain | grep "^worktree.*/some-dir/destination" 
&&
git -C some-dir/destination log --format=%s >actual2 &&
echo init >expected2 &&
@@ -100,10 +100,6 @@ test_expect_success 'remove main worktree' '
test_must_fail git worktree remove .
 '
 
-test_expect_success 'move some-dir/destination back' '
-   git worktree move some-dir/destination destination
-'
-
 test_expect_success 'remove locked worktree' '
git worktree lock destination &&
test_when_finished "git worktree unlock destination" &&
-- 
2.16.2.660.g709887971b



Re: [PATCH] git.el: handle default excludesfile properly

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 9:57 PM, Dorab Patel  wrote:
> Thanks for reviewing and locating the commits.
>
> OK, I'll re-roll and add the relevant commits. It may take some time.
>
> Should I just send the revised patch as a separate thread (with the
> relevant commits and history)?

That would work. You can use "git format-patch -v2 ..." to mark the
patch as "[PATCH v2]", and "git send-email
--in-reply-to=20180303034803.21589-1-dorabpa...@gmail.com ..." to tie
it back to this thread when you send it.

As a an aid to reviewers, it's a good idea to add commentary
explaining what changed since v1 and provide a link back to v1, like
this[1]. Place the commentary below the "---" line following your
sign-off.

(One more minor comment: etiquette on this list is to avoid top-posting [2].)

Thanks.

[1]: https://public-inbox.org/git/20180303034803.21589-1-dorabpa...@gmail.com/
[2]: https://lkml.org/lkml/2005/1/11/111


Re: [PATCH 13/44] pack: move approximate object count to object store

2018-03-03 Thread Duy Nguyen
On Sun, Mar 4, 2018 at 9:47 AM, Eric Sunshine  wrote:
> On Sat, Mar 3, 2018 at 6:36 AM, Nguyễn Thái Ngọc Duy  
> wrote:
>> The approximate_object_count() function maintains a rough count of
>> objects in a repository to estimate how long object name abbreviates
>> should be.  Object names are scoped to a repository and the
>> appropriate length may differ by repository, so the object count
>> should not be global.
>>
>> Signed-off-by: Stefan Beller 
>> Signed-off-by: Jonathan Nieder 
>> Signed-off-by: Nguyễn Thái Ngọc Duy 
>> ---
>> diff --git a/packfile.c b/packfile.c
>> @@ -813,8 +811,8 @@ static int approximate_object_count_valid;
>>  unsigned long approximate_object_count(void)
>>  {
>> -   static unsigned long count;
>> -   if (!approximate_object_count_valid) {
>> +   if (!the_repository->objects.approximate_object_count_valid) {
>> +   unsigned long count;
>> struct packed_git *p;
>>
>> prepare_packed_git();
>> @@ -824,8 +822,9 @@ unsigned long approximate_object_count(void)
>> continue;
>> count += p->num_objects;
>> }
>> +   the_repository->objects.approximate_object_count = count;
>> }
>> -   return count;
>> +   return the_repository->objects.approximate_object_count;
>>  }
>> @@ -900,7 +899,7 @@ void prepare_packed_git(void)
>>  void reprepare_packed_git(void)
>>  {
>> -   approximate_object_count_valid = 0;
>> +   the_repository->objects.approximate_object_count_valid = 0;
>
> Not an issue specific to this patch, but where, how, when does
> 'approximate_object_count_valid' ever get set to anything other than
> 0? Even in the existing code (without this patch), there doesn't seem
> to be anyplace which sets this to a non-zero value. Am I missing
> something obvious (or subtle)?

Probably related to this
https://public-inbox.org/git/20180226085508.ga30...@sigill.intra.peff.net/#t

-- 
Duy


Re: [PATCH 37/44] packfile: add repository argument to prepare_packed_git

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 6:36 AM, Nguyễn Thái Ngọc Duy  wrote:
> Add a repository argument to allow prepare_packed_git callers to
> be more specific about which repository to handle. See c28d027a52c
> (sha1_file: add repository argument to link_alt_odb_entry, 2018-02-20)
> for an explanation of the #define trick.

Object c28d027a52c doesn't exist. Most likely it was a reference to a
change existing only in 'pu' which got replaced by a later revision of
the series.

> Signed-off-by: Stefan Beller 
> Signed-off-by: Nguyễn Thái Ngọc Duy 


Re: [PATCH] git.el: handle default excludesfile properly

2018-03-03 Thread Dorab Patel
Thanks for reviewing and locating the commits.

OK, I'll re-roll and add the relevant commits. It may take some time.

Should I just send the revised patch as a separate thread (with the
relevant commits and history)?

On Sat, Mar 3, 2018 at 6:12 PM, Eric Sunshine  wrote:
> On Sat, Mar 3, 2018 at 8:36 PM, Dorab Patel  wrote:
>> Correct me if I'm wrong, but my understanding, from
>> https://git-scm.com/docs/gitignore, is that $HOME/.gitignore is used
>> only if it is specified as the value of core.excludesfile in
>> ~/.gitconfig. It is not used by default. If that is so, then the
>> proposed (and original) code works. The changes I am proposing handle
>> the default case, when core.excludesfile is not specified.
>
> You're right. I must have set core.excludesfile so long ago that I
> forgot about it and assumed $HOME/.gitignore was consulted by default.
>
>> Looking deeper into how the function git-get-exclude-files is used, I
>> see that it is only being called from git-run-ls-files-with-excludes.
>> So, perhaps, a better (or additional) fix might be to add the
>> parameter "--exclude-standard" in the call to git-run-ls-files from
>> within git-run-ls-files-with-excludes. And remove the need for
>> get-get-exclude-files altogether.  Presumably, "--exclude-standard"
>> handles the default case with/without XDG_CONFIG_HOME correctly. The
>> question I'd have then is: why didn't the original author use that
>> option? Either I'm missing something? Or the option was added later,
>> after the original code was written? Or something else?
>
> Using --exclude-standard rather than --exclude-from and retiring
> git-get-exclude-files() makes sense to me.
>
> As for why the original author didn't use --exclude-standard, project
> history tells us that. In particular, git-get-exclude-files() was
> implemented by 274e13e0e9 (git.el: Take into account the
> core.excludesfile config option., 2007-07-31), whereas
> --exclude-standard was introduced by 8e7b07c8a7 (git-ls-files: add
> --exclude-standard, 2007-11-15), three and a half months later.
>
> If you do re-roll to use --exclude-standard, then it would be good for
> your commit message to explain this history, citing the relevant
> commits.
>
> Thanks.


Re: [PATCH 13/44] pack: move approximate object count to object store

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 6:36 AM, Nguyễn Thái Ngọc Duy  wrote:
> The approximate_object_count() function maintains a rough count of
> objects in a repository to estimate how long object name abbreviates
> should be.  Object names are scoped to a repository and the
> appropriate length may differ by repository, so the object count
> should not be global.
>
> Signed-off-by: Stefan Beller 
> Signed-off-by: Jonathan Nieder 
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
> diff --git a/packfile.c b/packfile.c
> @@ -813,8 +811,8 @@ static int approximate_object_count_valid;
>  unsigned long approximate_object_count(void)
>  {
> -   static unsigned long count;
> -   if (!approximate_object_count_valid) {
> +   if (!the_repository->objects.approximate_object_count_valid) {
> +   unsigned long count;
> struct packed_git *p;
>
> prepare_packed_git();
> @@ -824,8 +822,9 @@ unsigned long approximate_object_count(void)
> continue;
> count += p->num_objects;
> }
> +   the_repository->objects.approximate_object_count = count;
> }
> -   return count;
> +   return the_repository->objects.approximate_object_count;
>  }
> @@ -900,7 +899,7 @@ void prepare_packed_git(void)
>  void reprepare_packed_git(void)
>  {
> -   approximate_object_count_valid = 0;
> +   the_repository->objects.approximate_object_count_valid = 0;

Not an issue specific to this patch, but where, how, when does
'approximate_object_count_valid' ever get set to anything other than
0? Even in the existing code (without this patch), there doesn't seem
to be anyplace which sets this to a non-zero value. Am I missing
something obvious (or subtle)?


Re: [PATCH 09/44] object-store: free alt_odb_list

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 6:36 AM, Nguyễn Thái Ngọc Duy  wrote:
> Free the memory and reset alt_odb_{list, tail} to NULL.
>
> Signed-off-by: Stefan Beller 
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
> diff --git a/object.c b/object.c
> @@ -450,8 +450,26 @@ void raw_object_store_init(struct raw_object_store *o)
> +static void free_alt_odb(struct alternate_object_database *alt)
> +{
> +   strbuf_release(>scratch);
> +   oid_array_clear(>loose_objects_cache);
> +}

This doesn't free the 'struct alternate_object_database' entry itself, right?

Is that intentional? Isn't the idea that this should free the entries too?

> +static void free_alt_odbs(struct raw_object_store *o)
> +{
> +   while (o->alt_odb_list) {
> +   free_alt_odb(o->alt_odb_list);
> +   o->alt_odb_list = o->alt_odb_list->next;
> +   }
> +}

Accessing an entry's 'next' member after invoking free_alt_odb() works
because the entry itself hasn't been freed (as noted above).

Is leaking the entries themselves intentional?

>  void raw_object_store_clear(struct raw_object_store *o)
>  {
> FREE_AND_NULL(o->objectdir);
> FREE_AND_NULL(o->alternate_db);
> +
> +   free_alt_odbs(o);
> +   o->alt_odb_tail = NULL;
>  }

The commit message talks about freeing memory and resetting
alt_odb_list and alt_odb_tail, but this code only resets alt_odb_tail.


Re: [PATCH 06/44] repository: introduce raw object store field

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 6:35 AM, Nguyễn Thái Ngọc Duy  wrote:
> The raw object store field will contain any objects needed for
> access to objects in a given repository.
>
> This patch introduces the raw object store and populates it with the
> `objectdir`, which used to be part of the repository struct.
>
> As the struct gains members, we'll also populate the function to clear
> the memory for these members.
>
> In a later we'll introduce a struct object_parser, that will complement

s/In a later/Later,/

> the object parsing in a repository struct: The raw object parser is the
> layer that will provide access to raw object content, while the higher
> level object parser code will parse raw objects and keeps track of
> parenthood and other object relationships using 'struct object'.
> For now only add the lower level to the repository struct.
>
> Signed-off-by: Stefan Beller 
> Signed-off-by: Jonathan Nieder 
> Signed-off-by: Nguyễn Thái Ngọc Duy 


Re: [PATCH] git.el: handle default excludesfile properly

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 8:36 PM, Dorab Patel  wrote:
> Correct me if I'm wrong, but my understanding, from
> https://git-scm.com/docs/gitignore, is that $HOME/.gitignore is used
> only if it is specified as the value of core.excludesfile in
> ~/.gitconfig. It is not used by default. If that is so, then the
> proposed (and original) code works. The changes I am proposing handle
> the default case, when core.excludesfile is not specified.

You're right. I must have set core.excludesfile so long ago that I
forgot about it and assumed $HOME/.gitignore was consulted by default.

> Looking deeper into how the function git-get-exclude-files is used, I
> see that it is only being called from git-run-ls-files-with-excludes.
> So, perhaps, a better (or additional) fix might be to add the
> parameter "--exclude-standard" in the call to git-run-ls-files from
> within git-run-ls-files-with-excludes. And remove the need for
> get-get-exclude-files altogether.  Presumably, "--exclude-standard"
> handles the default case with/without XDG_CONFIG_HOME correctly. The
> question I'd have then is: why didn't the original author use that
> option? Either I'm missing something? Or the option was added later,
> after the original code was written? Or something else?

Using --exclude-standard rather than --exclude-from and retiring
git-get-exclude-files() makes sense to me.

As for why the original author didn't use --exclude-standard, project
history tells us that. In particular, git-get-exclude-files() was
implemented by 274e13e0e9 (git.el: Take into account the
core.excludesfile config option., 2007-07-31), whereas
--exclude-standard was introduced by 8e7b07c8a7 (git-ls-files: add
--exclude-standard, 2007-11-15), three and a half months later.

If you do re-roll to use --exclude-standard, then it would be good for
your commit message to explain this history, citing the relevant
commits.

Thanks.


Re: [PATCH] git.el: handle default excludesfile properly

2018-03-03 Thread Dorab Patel
[[Pardon the duplicate. I forgot to send via text/plain and the
mailing list bounced it, so resending.]]

Thanks for the feedback.

Correct me if I'm wrong, but my understanding, from
https://git-scm.com/docs/gitignore, is that $HOME/.gitignore is used
only if it is specified as the value of core.excludesfile in
~/.gitconfig. It is not used by default. If that is so, then the
proposed (and original) code works. The changes I am proposing handle
the default case, when core.excludesfile is not specified.

Looking deeper into how the function git-get-exclude-files is used, I
see that it is only being called from git-run-ls-files-with-excludes.
So, perhaps, a better (or additional) fix might be to add the
parameter "--exclude-standard" in the call to git-run-ls-files from
within git-run-ls-files-with-excludes. And remove the need for
get-get-exclude-files altogether.  Presumably, "--exclude-standard"
handles the default case with/without XDG_CONFIG_HOME correctly. The
question I'd have then is: why didn't the original author use that
option? Either I'm missing something? Or the option was added later,
after the original code was written? Or something else?

Thoughts?

On Sat, Mar 3, 2018 at 12:42 AM, Eric Sunshine  wrote:
> On Fri, Mar 2, 2018 at 10:48 PM, Dorab Patel  wrote:
>> The previous version only looked at core.excludesfile for locating the
>> excludesfile.  So, when core.excludesfile was not defined, it did not
>> use the possible default locations.
>>
>> The current version uses either $XDG_CONFIG_HOME/git/ignore or
>> $HOME/.config/git/ignore for the default excludesfile location
>> depending on whether XDG_CONFIG_HOME is defined or not.  As per the
>> documentation of gitignore.
>
> Perhaps take $HOME/.gitignore into account too?
>
>> Signed-off-by: Dorab Patel 


[PATCH v3 2/2] send-email: Support separate Reply-To address

2018-03-03 Thread Christian Ludwig
In some projects contributions from groups are only accepted from a
common group email address. But every individual may want to receive
replies to her own personal address. That's what we have 'Reply-To'
headers for in SMTP. So introduce an optional '--reply-to' command
line option.

This patch re-uses the $reply_to variable. This could break
out-of-tree patches!

Signed-off-by: Christian Ludwig 
---
 Documentation/git-send-email.txt   |  5 +
 contrib/completion/git-completion.bash |  2 +-
 git-send-email.perl| 18 +-
 t/t9001-send-email.sh  |  2 ++
 4 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 8060ea35c..71ef97ba9 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -84,6 +84,11 @@ See the CONFIGURATION section for `sendemail.multiEdit`.
the value of GIT_AUTHOR_IDENT, or GIT_COMMITTER_IDENT if that is not
set, as returned by "git var -l".
 
+--reply-to=::
+   Specify the address where replies from recipients should go to.
+   Use this if replies to messages should go to another address than what
+   is specified with the --from parameter.
+
 --in-reply-to=::
Make the first mail (or all the mails with `--no-thread`) appear as a
reply to the given Message-Id, which avoids breaking threads to
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index c7d5c7af2..4805b92ba 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2081,7 +2081,7 @@ _git_send_email ()
--compose --confirm= --dry-run --envelope-sender
--from --identity
--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
-   --no-suppress-from --no-thread --quiet
+   --no-suppress-from --no-thread --quiet --reply-to
--signed-off-by-cc --smtp-pass --smtp-server
--smtp-server-port --smtp-encryption= --smtp-user
--subject --suppress-cc= --suppress-from --thread --to
diff --git a/git-send-email.perl b/git-send-email.perl
index 9eb12b5ba..707ec9eb7 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -57,6 +57,7 @@ git send-email --dump-aliases
 --[no-]cc * Email Cc:
 --[no-]bcc* Email Bcc:
 --subject * Email "Subject:"
+--reply-to* Email "Reply-To:"
 --in-reply-to * Email "In-Reply-To:"
 --[no-]xmailer * Add "X-Mailer:" header (default).
 --[no-]annotate* Review each patch that will be sent in an 
editor.
@@ -167,7 +168,7 @@ my $re_encoded_word = 
qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
 
 # Variables we fill in automatically, or via prompting:
 my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
-   $initial_in_reply_to,$initial_subject,@files,
+   $initial_in_reply_to,$reply_to,$initial_subject,@files,
$author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
 
 my $envelope_sender;
@@ -316,6 +317,7 @@ die __("--dump-aliases incompatible with other options\n")
 $rc = GetOptions(
"sender|from=s" => \$sender,
 "in-reply-to=s" => \$initial_in_reply_to,
+   "reply-to=s" => \$reply_to,
"subject=s" => \$initial_subject,
"to=s" => \@initial_to,
"to-cmd=s" => \$to_cmd,
@@ -678,6 +680,7 @@ if ($compose) {
my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
my $tpl_subject = $initial_subject || '';
my $tpl_in_reply_to = $initial_in_reply_to || '';
+   my $tpl_reply_to = $reply_to || '';
 
print $c <

git-send-email: Support for Reply-To

2018-03-03 Thread Christian Ludwig
Hi,

this is the third iteration of this series. There was a request to
rebase the changes on the refactoring patch b6049542 ("send-email:
extract email-parsing code into a subroutine", 2017-12-15). This is
the result.

The diffstat is the same compared to the last revision. It could be
made smaller by sacrificing readibility and breaking the scheme
introduced by the refactoring patch. But I do agree that send-email's
readability could benefit from slicing it into handy functions. And the
refactoring patch reduces the nesting of loops/conditionals.

But it's your code, you decide. I can re-send a fixed-up v2 without the
rebasing.


So long,


 - Christian


[PATCH v3 1/2] send-email: Rename variable for clarity

2018-03-03 Thread Christian Ludwig
The SMTP protocol has both, the 'Reply-To' and the 'In-Reply-To' header
fields. We only use the latter. To avoid confusion, rename the variable
for it.

Signed-off-by: Christian Ludwig 
---
 git-send-email.perl | 38 +++---
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index d0dcc6d7f..9eb12b5ba 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -167,13 +167,13 @@ my $re_encoded_word = 
qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
 
 # Variables we fill in automatically, or via prompting:
 my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
-   $initial_reply_to,$initial_subject,@files,
+   $initial_in_reply_to,$initial_subject,@files,
$author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
 
 my $envelope_sender;
 
 # Example reply to:
-#$initial_reply_to = ''; #<20050203173208.ga23...@foobar.com>';
+#$initial_in_reply_to = ''; #<20050203173208.ga23...@foobar.com>';
 
 my $repo = eval { Git->repository() };
 my @repo = $repo ? ($repo) : ();
@@ -315,7 +315,7 @@ die __("--dump-aliases incompatible with other options\n")
 if !$help and $dump_aliases and @ARGV;
 $rc = GetOptions(
"sender|from=s" => \$sender,
-"in-reply-to=s" => \$initial_reply_to,
+"in-reply-to=s" => \$initial_in_reply_to,
"subject=s" => \$initial_subject,
"to=s" => \@initial_to,
"to-cmd=s" => \$to_cmd,
@@ -677,7 +677,7 @@ if ($compose) {
 
my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
my $tpl_subject = $initial_subject || '';
-   my $tpl_reply_to = $initial_reply_to || '';
+   my $tpl_in_reply_to = $initial_in_reply_to || '';
 
print $c < "",
valid_re => qr/\@.*\./, confirm_only => 1);
 }
-if (defined $initial_reply_to) {
-   $initial_reply_to =~ s/^\s*?\s*$//;
-   $initial_reply_to = "<$initial_reply_to>" if $initial_reply_to ne '';
+if (defined $initial_in_reply_to) {
+   $initial_in_reply_to =~ s/^\s*?\s*$//;
+   $initial_in_reply_to = "<$initial_in_reply_to>" if $initial_in_reply_to 
ne '';
 }
 
 if (!defined $smtp_server) {
@@ -941,7 +941,7 @@ if ($compose && $compose > 0) {
 }
 
 # Variables we set as part of the loop over files
-our ($message_id, %mail, $subject, $reply_to, $references, $message,
+our ($message_id, %mail, $subject, $in_reply_to, $references, $message,
$needs_confirm, $message_num, $ask_default);
 
 sub extract_valid_address {
@@ -1350,9 +1350,9 @@ Message-Id: $message_id
if ($use_xmailer) {
$header .= "X-Mailer: git-send-email $gitversion\n";
}
-   if ($reply_to) {
+   if ($in_reply_to) {
 
-   $header .= "In-Reply-To: $reply_to\n";
+   $header .= "In-Reply-To: $in_reply_to\n";
$header .= "References: $references\n";
}
if (@xh) {
@@ -1529,8 +1529,8 @@ EOF
return 1;
 }
 
-$reply_to = $initial_reply_to;
-$references = $initial_reply_to || '';
+$in_reply_to = $initial_in_reply_to;
+$references = $initial_in_reply_to || '';
 $subject = $initial_subject;
 $message_num = 0;
 
@@ -1740,9 +1740,9 @@ foreach my $t (@files) {
 
# set up for the next message
if ($thread && $message_was_sent &&
-   ($chain_reply_to || !defined $reply_to || length($reply_to) == 
0 ||
+   ($chain_reply_to || !defined $in_reply_to || 
length($in_reply_to) == 0 ||
$message_num == 1)) {
-   $reply_to = $message_id;
+   $in_reply_to = $message_id;
if (length $references > 0) {

[PATCH] git-gui: workaround ttk:style theme use

2018-03-03 Thread Clemens Buchacher
Tk 8.5.7, which is the latest version on Centos 6, does not support
getting the current theme with [ttk::style theme use]. Use the existing
workaround for this in all places.

Signed-off-by: Clemens Buchacher 
---
 git-gui/lib/themed.tcl | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/git-gui/lib/themed.tcl b/git-gui/lib/themed.tcl
index 351a712..88b3119 100644
--- a/git-gui/lib/themed.tcl
+++ b/git-gui/lib/themed.tcl
@@ -1,6 +1,14 @@
 # Functions for supporting the use of themed Tk widgets in git-gui.
 # Copyright (C) 2009 Pat Thoyts 
 
+proc ttk_get_current_theme {} {
+   # Handle either current Tk or older versions of 8.5
+   if {[catch {set theme [ttk::style theme use]}]} {
+   set theme  $::ttk::currentTheme
+   }
+   return $theme
+}
+
 proc InitTheme {} {
# Create a color label style (bg can be overridden by widget option)
ttk::style layout Color.TLabel {
@@ -28,10 +36,7 @@ proc InitTheme {} {
}
}
 
-   # Handle either current Tk or older versions of 8.5
-   if {[catch {set theme [ttk::style theme use]}]} {
-   set theme  $::ttk::currentTheme
-   }
+   set theme [ttk_get_current_theme]
 
if {[lsearch -exact {default alt classic clam} $theme] != -1} {
# Simple override of standard ttk::entry to change the field
@@ -248,7 +253,7 @@ proc tspinbox {w args} {
 proc ttext {w args} {
global use_ttk
if {$use_ttk} {
-   switch -- [ttk::style theme use] {
+   switch -- [ttk_get_current_theme] {
"vista" - "xpnative" {
lappend args -highlightthickness 0 -borderwidth 0
}
-- 
2.7.4



[GSoC][PATCH v3] Make options that expect object ids less chatty if id is invalid

2018-03-03 Thread Paul-Sebastian Ungureanu
Usually, the usage should be shown only if the user does not know what
options are available. If the user specifies an invalid value, the user
is already aware of the available options. In this case, there is no
point in displaying the usage anymore.

This patch applies to "git tag --contains", "git branch --contains",
"git branch --points-at", "git for-each-ref --contains" and many more.

Signed-off-by: Paul-Sebastian Ungureanu 
---
 builtin/update-index.c|  2 +
 parse-options.c   | 13 +++--
 parse-options.h   |  1 +
 t/t0040-parse-options.sh  |  9 ++--
 t/t3404-rebase-interactive.sh |  2 +-
 t/t3502-cherry-pick-merge.sh  |  8 +--
 t/tcontains.sh| 92 +++
 7 files changed, 111 insertions(+), 16 deletions(-)
 create mode 100755 t/tcontains.sh

diff --git a/builtin/update-index.c b/builtin/update-index.c
index 58d1c2d28..1c170 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1060,6 +1060,8 @@ int cmd_update_index(int argc, const char **argv, const 
char *prefix)
switch (parseopt_state) {
case PARSE_OPT_HELP:
exit(129);
+   case PARSE_OPT_ERROR:
+   exit(1);
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_DONE:
{
diff --git a/parse-options.c b/parse-options.c
index d02eb8b01..eee401662 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -434,7 +434,6 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
   const char * const usagestr[])
 {
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
-   int err = 0;
 
/* we must reset ->opt, unknown short option leave it dangling */
ctx->opt = NULL;
@@ -459,7 +458,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
ctx->opt = arg + 1;
switch (parse_short_opt(ctx, options)) {
case -1:
-   goto show_usage_error;
+   return PARSE_OPT_ERROR;
case -2:
if (ctx->opt)
check_typos(arg + 1, options);
@@ -472,7 +471,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
while (ctx->opt) {
switch (parse_short_opt(ctx, options)) {
case -1:
-   goto show_usage_error;
+   return PARSE_OPT_ERROR;
case -2:
if (internal_help && *ctx->opt == 'h')
goto show_usage;
@@ -504,7 +503,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
goto show_usage;
switch (parse_long_opt(ctx, arg + 2, options)) {
case -1:
-   goto show_usage_error;
+   return PARSE_OPT_ERROR;
case -2:
goto unknown;
}
@@ -517,10 +516,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
}
return PARSE_OPT_DONE;
 
- show_usage_error:
-   err = 1;
  show_usage:
-   return usage_with_options_internal(ctx, usagestr, options, 0, err);
+   return usage_with_options_internal(ctx, usagestr, options, 0, 0);
 }
 
 int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -543,6 +540,8 @@ int parse_options(int argc, const char **argv, const char 
*prefix,
case PARSE_OPT_NON_OPTION:
case PARSE_OPT_DONE:
break;
+   case PARSE_OPT_ERROR:
+   exit(1);
default: /* PARSE_OPT_UNKNOWN */
if (ctx.argv[0][1] == '-') {
error("unknown option `%s'", ctx.argv[0] + 2);
diff --git a/parse-options.h b/parse-options.h
index af711227a..c77bb3b4f 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -188,6 +188,7 @@ enum {
PARSE_OPT_HELP = -1,
PARSE_OPT_DONE,
PARSE_OPT_NON_OPTION,
+   PARSE_OPT_ERROR,
PARSE_OPT_UNKNOWN
 };
 
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 0c2fc81d7..8af12e8a1 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -162,9 +162,9 @@ test_expect_success 'long options' '
 '
 
 test_expect_success 'missing required value' '
-   test_expect_code 129 test-parse-options -s &&
-   test_expect_code 129 test-parse-options --string &&
-   test_expect_code 129 test-parse-options --file
+   test_expect_code 1 test-parse-options -s &&
+   test_expect_code 1 test-parse-options --string &&
+   test_expect_code 1 test-parse-options --file
 '
 
 cat >expect <<\EOF
@@ -214,7 +214,7 @@ test_expect_success 'unambiguously abbreviated option 

RE

2018-03-03 Thread @Sheng Li Hung
I am Mr.Sheng Li Hung, from china I got your information while search for
a reliable person, I have a very profitable business proposition for you
and i can assure you that you will not regret been part of this mutual
beneficial transaction after completion. Kindly get back to me for more
details on this email id: shengl...@hotmail.com

Thanks
Mr Sheng Li Hung


Re: [RFC] Contributing to Git (on Windows)

2018-03-03 Thread Jonathan Nieder
Hi Dscho,

Johannes Schindelin wrote:
>> Jonathan Nieder  writes:
>>> Dereck Stolee wrote:

 +Test Your Changes on Linux
 +--
 +
 +It can be important to work directly on the [core Git
 codebase](https://github.com/git/git), +such as a recent commit into
 the `master` or `next` branch that has not been incorporated +into
 Git for Windows. Also, it can help to run functional and performance
 tests on your +code in Linux before submitting patches to the
 Linux-focused mailing list.
>>>
>>> I'm surprised at this advice.  Does it actually come up?
>
> Yes.
>
> I personally set up the automated builds on Windows, Linux and macOS for
> our team, and as a rule we always open an internal Pull Request on our
> topic branches as we develop them, and you would probably not believe the
> number of issues we caught before sending the patches to this list. Issues
> including
[nice list snipped]

Thanks for explaining.  I still am going to push back on the wording
here, and here is why:

 1. Approximately 1/2 of the differences you describe apply to Mac as
well as Windows.  The advice certainly does not apply on Mac.

You might object: Mac readers would not be reading this text!  But
that is not how humans work: if project documentation (e.g. the
CONTRIBUTING.md on GitHub!) says that the project is Linux-focused
and if you don't test on Linux then you might as well not bother,
then people are going to believe it.

 2. It is not unusual for Linux users to make portability mistakes that
are quickly pointed out on list.  If anything, the advice to test on
other platforms should apply to contributors on Linux even more.
This happens especially often to new contributors, who sometimes use
bashisms, etc that get quickly pointed out.

 3. I do not *want* Git to be a Linux-focused project; I want the code
to perform well on all popular platforms and for people not to be
afraid to make it so.

If the docs say that all we care about is Linux, then people are
likely to be too scared to do the necessary and valuable work of
making it work well on Mac, Windows, etc.  The actual mix of
contributors doesn't bear it out anyway: a large number of
contributors are already on Mac or Windows.

Fortunately this is pretty straightforward to fix in the doc: it could
say something like "to the multi-platform focused mailing list", for
example.

[...]
> To my chagrin, this idea of making most of the boring stuff (and I include
> formatting in that category, but I am probably special in that respect) as
> automatable, and as little of an issue for review as possible, leaving
> most brain cycles to work on the correctness of the patches instead, did
> not really receive a lot of traction on this mailing list.

Huh?  I'm confident that this is a pretty widely supported idea within
the Git project.

I get the feeling you must have misread something or misinterpreted a
different response.

[...]
> No, this advice comes straight from my personal observation that the
> reviewers on the Git mailing list are Linux-centric.

Hopefully the clarifications and suggestions higher in this message
help.  If they don't, then I'm nervous about our ability to understand
each other.

[...]
> Now, how reasonable do I think it is to ask those contributors to purchase
> an Apple machine to test their patches on macOS (you cannot just download
> an .iso nor would it be legal to run a macOS VM on anything but Apple
> hardware)? You probably guessed my answer: not at all.

Agreed, this is something that needs to be automated (and not via a
CONTRIBUTING.md file).  As a stopgap, having a section in the
contribution instructions about testing using Windows's Linux
subsystem is a valuable thing, and thanks for that; I never meant to
imply otherwise.

[...]
> On Fri, 2 Mar 2018, Junio C Hamano wrote:

>> In fact, portability issues in a patch originally written for a platform
>> is rather quickly discovered if the original platform is more minor than
>> the others, so while it is good advice to test your ware before you make
>> it public, singling out the portability issues may not add much value.
>> The fewer number of obvious bugs remaining, the fewer number of
>> iterations it would take for a series to get in a good shape.
[...]
> For you, Junio, however, the task *now* is to put yourself into the shoes
> of a Computer Science student in their 2nd year who wants to become an
> Open Source contributor and is a little afraid to talk directly to "the
> core committers", and quite scared what negative feedback they might
> receive.
>
> "What if they say my code is not good enough?"

Sure, though there is something implied in what is Junio is saying
that is useful for such people.

It is patience.  It is the message that if you miss a portability bug,
we won't be disappointed in you, and it in fact happens all the time
to the best 

Re: [RFC] Contributing to Git (on Windows)

2018-03-03 Thread Johannes Schindelin
Hi,

On Fri, 2 Mar 2018, Junio C Hamano wrote:

> Jonathan Nieder  writes:
> 
> >> +Test Your Changes on Linux
> >> +--
> >> +
> >> +It can be important to work directly on the [core Git
> >> codebase](https://github.com/git/git), +such as a recent commit into
> >> the `master` or `next` branch that has not been incorporated +into
> >> Git for Windows. Also, it can help to run functional and performance
> >> tests on your +code in Linux before submitting patches to the
> >> Linux-focused mailing list.
> >
> > I'm surprised at this advice.  Does it actually come up?

Yes.

I personally set up the automated builds on Windows, Linux and macOS for
our team, and as a rule we always open an internal Pull Request on our
topic branches as we develop them, and you would probably not believe the
number of issues we caught before sending the patches to this list. Issues
including

- scripts not being marked executable (on Windows, we don't care, but you
  Linux folks do),

- use of symbols that are only available on Windows, but that were not
  guarded by appropriate `#ifdef`s,

- printf formats available only on Windows,

- EOL_NATIVE differences,

- differences between BSD and GNU tools, such as the white-space in the
  output of `wc`, the syntactic differences of `sed`'s `-i` option,
  different options of the `stat` utility to do the same thing, etc
  (granted, this would not be caught when only testing on Windows and
  Linux, as both development environments would only use the GNU variety)

Of course, these builds also catch problems by setting DEVELOPER=1 which
developers might have forgotten to specify when building locally (it
really is too easy to forget).

> > When I was on Mac I never worried about this, nor when I was on
> > Windows.

I commend your boldness.

Of course, you are an old-timer. These instructions are intended for
new-timers, even first-timers, who may very well be very scared of reviews
criticizing them for, say, not marking a new test script as executable.

If you ever spoke to potential contributors who decided not to contribute
after all, and you dig a little deeper, you might get the same impression
as I got: they are (rightfully) scared of receiving answers with tons of
comments what they did wrong.

Most contributors seem to prefer to be "criticized" by tools, preferably
even during the build process, where they can fix things before anybody
sees their patches.

This is, for example, the reason why the cURL project has this really nice
`lib/checksrc.pl` script that they recommend you run to verify that the
code you wrote abides by a few of their source code conventions they have.
Developers run it, see what is wrong, fix it, and no human judges them.
They submit the code, and the discussions revolve about how to improve the
patch to cover more cases or some such.

For that same reason, namely to make it less harsh for new contributors, I
also tried to set up an automated job that tries to reformat patches using
`clang-format` (without forcing any contributor to try to set up a
bleeding-edge CLang, which can get very involved, very quickly) and pushes
an updated topic branch if changes were needed. Sadly, this job is broken
because I seem to be unable to get the `apt-get` commands right to get
CLang's nightly builds (this job runs on Linux).

To my chagrin, this idea of making most of the boring stuff (and I include
formatting in that category, but I am probably special in that respect) as
automatable, and as little of an issue for review as possible, leaving
most brain cycles to work on the correctness of the patches instead, did
not really receive a lot of traction on this mailing list.

We still have no satisfactory automated way to check contributors' patches
against our (quite fuzzy) coding style. Until that happens, contributors
will be constantly faced with reviews about overly long lines, about
grammar issues, about commit messages missing Signed-off-by: lines, about
commit messages that are too short, etc. Those are all comments that
not exactly make contributors feel welcome. And that comments also
distract from more interesting use of reviewers' time (such as suggesting
helper functions or data structures that the contributor could use to
simplify the patches).

But one thing that we *can* recommend to contributors (in particular
Windows-based ones) is to verify that their patches work also on Linux, so
that they can avoid receiving comments about that class of avoidable
issues.

> > I'm personally happy to review patches that haven't been tested on
> > Linux, though it's of course even nicer if the patch author mentions
> > what platforms they've tested on.

Jonathan, I don't want this to sound harsh... but... this contributors'
guide cares a little more about the feelings of the contributors than
yours? ;-)

Seriously again, you might not mind pointing out that a newly-added test
case is not marked executable. The emotional 

Re: [RFC] Rebasing merges: a jorney to the ultimate solution(RoadClear)

2018-03-03 Thread Igor Djordjevic
On 02/03/2018 19:14, Igor Djordjevic wrote:
> 
> > > It is interesting to think what it means to faithfully rebase a '-s
> > > ours' merge. In your example the rebase does not introduce any new
> > > changes into branch B that it doesn't introduce to branch A. Had it
> > > added a fixup to branch B1 for example or if the topology was more
> > > complex so that B ended up with some other changes that the rebase did
> > > not introduce into A, then M' would contain those extra changes whereas
> > > '--recreate-merges' with '-s ours' (once it supports it) would not.
> >
> > Unless the method of merging was stored, I don't think we *can*
> > correctly automate resolving of "-s ours" because all we store is the
> > resulting content, and we don't know how or why the user generated it
> > as such. I believe the "correct" solution in any case would be to take
> > the content we DO know and then ask the user to stop for amendments.
>  
> I agree with Jake, and for the exact same reasons.
> 
> That said, I`d like to see what mentioned '--recreate-merges' with 
> '-s ours' does (or would do, once it supports it), would you have a 
> pointer for me where to look at?
> 
> But if that`s something yet to come, might be it`s still open for 
> discussion. I mean, even this topic started inside original 
> `--recreate-merges` one[1], and hopefully it can still bring 
> improvements there (sooner or later).
> 
> [1] 
> https://public-inbox.org/git/cover.1516225925.git.johannes.schinde...@gmx.de/

Ok, I went through mentioned `--recreate-merges` topic again, and I 
think I see one crucial merge commit handling difference.

In there, as it is at the moment, merge commits are really to be 
_recreated_... as the option name seems to imply ;)

In terms of interactive rebasing, it actually comes from "todo list" 
becoming much more powerful, gaining ability to create (new) merges, 
which is wonderful from the aspect of history rewriting (what rebase 
is all about).

But, I would argue it is a different concept from actually _rebasing_ 
existing merge commits, being what we`re discussing about here.

Yes, you can use merge commit (re)creation to "rebase" existing merge 
commit so the end result is the same, being what `--recreate-merges` 
now does, but that only goes for some (uninteresting?) merge commits 
where not knowing the deeper context of how the merge commit is 
originally created is not important as no content is to be lost (due 
to missing that deeper and utterly unknown context).

But as soon as you try to do that with more complex merge commits, 
like holding manual amendments and conflict resolutions, it doesn`t 
really work as expected - which I demonstrated in my original example 
script[1] in this topic, original merge commit amendment lost on 
rebase, and even worse - that happened silently.

Now, not to get misinterpreted to pick sides in "(re)create" vs 
"rebase" merge commit discussion, I just think these two (should) have 
a different purpose, and actually having both inside interactive rebase 
is what we should be aiming for.

And that`s what I think is important to understand before any further 
discussion - _(re)creating_ existing merge commits is not the same as 
_rebasing_ them, even though the former can sometimes be used to 
achieve the latter.

Regards, Buga

[1] https://public-inbox.org/git/bbe64321-4d3a-d3fe-8bb9-58b600fab...@gmail.com/


Re: git stash push -u always warns "pathspec '...' did not match any files"

2018-03-03 Thread Thomas Gummerer
On 03/03, Marc Strapetz wrote:
> Reproducible in a test repository with following steps:
> 
> $ touch untracked
> $ git stash push -u -- untracked
> Saved working directory and index state WIP on master: 0096475 init
> fatal: pathspec 'untracked' did not match any files
> error: unrecognized input
> 
> The file is stashed correctly, though.
> 
> Tested with Git 2.16.2 on Linux and Windows.

Thanks for the bug report and the reproduction recipe.  The following
patch should fix it:

--- >8 ---
Subject: [PATCH] stash push: avoid printing errors

Currently 'git stash push -u -- ' prints the following errors
if  only matches untracked files:

fatal: pathspec 'untracked' did not match any files
error: unrecognized input

This is because we first clean up the untracked files using 'git clean
', and then use a command chain involving 'git add -u
' and 'git apply' to clear the changes to files that are in
the index and were stashed.

As the  only includes untracked files that were already
removed by 'git clean', the 'git add' call will barf, and so will 'git
apply', as there are no changes that need to be applied.

Fix this by making sure to only call this command chain if there are
still files that match  after the call to 'git clean'.

Reported-by: Marc Strapetz 
Signed-off-by: Thomas Gummerer 
---
 git-stash.sh | 2 +-
 t/t3903-stash.sh | 7 +++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/git-stash.sh b/git-stash.sh
index fc8f8ae640..058ad0bed8 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -320,7 +320,7 @@ push_stash () {
git clean --force --quiet -d $CLEAN_X_OPTION -- "$@"
fi
 
-   if test $# != 0
+   if test $# != 0 && git ls-files --error-unmatch -- "$@" 
>/dev/null 2>/dev/null
then
git add -u -- "$@" |
git checkout-index -z --force --stdin
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index aefde7b172..506004aece 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -1096,4 +1096,11 @@ test_expect_success 'stash --  works with binary 
files' '
test_path_is_file subdir/untracked
 '
 
+test_expect_success 'stash --  doesnt print error' '
+   >untracked &&
+   git stash push -u -- untracked 2>actual&&
+   test_path_is_missing untracked &&
+   test_line_count = 0 actual
+'
+
 test_done
-- 
2.16.2.395.g2e18187dfd



[PATCH v3 12/13] Makefile: add NO_PERL_CPAN_FALLBACKS knob

2018-03-03 Thread Ævar Arnfjörð Bjarmason
From: Todd Zullinger 

We include some perl modules which are not part of the core perl
install, as a convenience.  This allows us to rely on those modules in
our perl-based tools and scripts without requiring users to install the
modules from CPAN or their operating system packages.

Users whose operating system provides these modules and packagers of Git
often don't want to ship or use these bundled modules.  Allow these
users to set NO_PERL_CPAN_FALLBACKS to avoid installing the bundled
modules.

Signed-off-by: Todd Zullinger 
Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 Makefile | 8 
 1 file changed, 8 insertions(+)

diff --git a/Makefile b/Makefile
index 026b9fb6d6..cbf0bc2344 100644
--- a/Makefile
+++ b/Makefile
@@ -296,6 +296,12 @@ all::
 #
 # Define NO_PERL if you do not want Perl scripts or libraries at all.
 #
+# Define NO_PERL_CPAN_FALLBACKS if you do not want to install bundled
+# copies of CPAN modules that serve as a fallback in case the modules
+# are not available on the system. This option is intended for
+# distributions that want to use their packaged versions of Perl
+# modules, instead of the fallbacks shipped with Git.
+#
 # Define PYTHON_PATH to the path of your Python binary (often /usr/bin/python
 # but /usr/bin/python2.7 on some platforms).
 #
@@ -2307,8 +2313,10 @@ LIB_CPAN_GEN := $(patsubst 
perl/%.pm,perl/build/lib/%.pm,$(LIB_CPAN))
 
 ifndef NO_PERL
 all:: $(LIB_PERL_GEN)
+ifndef NO_PERL_CPAN_FALLBACKS
 all:: $(LIB_CPAN_GEN)
 endif
+endif
 
 perl/build/lib/%.pm: perl/%.pm
$(QUIET_GEN)mkdir -p $(dir $@) && \
-- 
2.15.1.424.g9478a66081



[PATCH v3 09/13] perl: move CPAN loader wrappers to another namespace

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Move the Git::Error and Git::Mail::Address wrappers to the
Git::LoadCPAN::Loader::* namespace, e.g. Git::LoadCPAN::Error. That
module will then either load Error from CPAN (if installed on the OS),
or use Git::FromCPAN::Error.

When I added the Error wrapper in 20d2a30f8f ("Makefile: replace
perl/Makefile.PL with simple make rules", 2017-12-10) I didn't think
about how confusing it would be to have these modules sitting in the
same tree as our normal modules. Let's put these all into
Git::{Load,From}CPAN::* to clearly distinguish them from the rest.

This also makes things a bit less confusing since there was already a
Git::Error namespace ever since 8b9150e3e3 ("Git.pm: Handle failed
commands' output", 2006-06-24).

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 contrib/examples/git-difftool.perl  | 2 +-
 git-send-email.perl | 4 ++--
 perl/Git.pm | 2 +-
 perl/Git/{ => LoadCPAN}/Error.pm| 8 
 perl/Git/{ => LoadCPAN}/Mail/Address.pm | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)
 rename perl/Git/{ => LoadCPAN}/Error.pm (78%)
 rename perl/Git/{ => LoadCPAN}/Mail/Address.pm (69%)

diff --git a/contrib/examples/git-difftool.perl 
b/contrib/examples/git-difftool.perl
index fb0fd0b84b..b2ea80f9ed 100755
--- a/contrib/examples/git-difftool.perl
+++ b/contrib/examples/git-difftool.perl
@@ -13,7 +13,7 @@
 use 5.008;
 use strict;
 use warnings;
-use Git::Error qw(:try);
+use Git::LoadCPAN::Error qw(:try);
 use File::Basename qw(dirname);
 use File::Copy;
 use File::Find;
diff --git a/git-send-email.perl b/git-send-email.perl
index d5a4826a1c..1ec22c5ef3 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -26,13 +26,13 @@ use Text::ParseWords;
 use Term::ANSIColor;
 use File::Temp qw/ tempdir tempfile /;
 use File::Spec::Functions qw(catdir catfile);
-use Git::Error qw(:try);
+use Git::LoadCPAN::Error qw(:try);
 use Cwd qw(abs_path cwd);
 use Git;
 use Git::I18N;
-use Git::Mail::Address;
 use Net::Domain ();
 use Net::SMTP ();
+use Git::LoadCPAN::Mail::Address;
 
 Getopt::Long::Configure qw/ pass_through /;
 
diff --git a/perl/Git.pm b/perl/Git.pm
index 151b0e7144..9f246c7988 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -104,7 +104,7 @@ increase notwithstanding).
 
 
 use Carp qw(carp croak); # but croak is bad - throw instead
-use Git::Error qw(:try);
+use Git::LoadCPAN::Error qw(:try);
 use Cwd qw(abs_path cwd);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
diff --git a/perl/Git/Error.pm b/perl/Git/LoadCPAN/Error.pm
similarity index 78%
rename from perl/Git/Error.pm
rename to perl/Git/LoadCPAN/Error.pm
index 09bbc97390..3513fe745b 100644
--- a/perl/Git/Error.pm
+++ b/perl/Git/LoadCPAN/Error.pm
@@ -1,11 +1,11 @@
-package Git::Error;
+package Git::LoadCPAN::Error;
 use 5.008;
 use strict;
 use warnings;
 
 =head1 NAME
 
-Git::Error - Wrapper for the L module, in case it's not installed
+Git::LoadCPAN::Error - Wrapper for the L module, in case it's not 
installed
 
 =head1 DESCRIPTION
 
@@ -26,13 +26,13 @@ sub import {
 } or do {
my $error = $@ || "Zombie Error";
 
-   my $Git_Error_pm_path = $INC{"Git/Error.pm"} || die "BUG: Should have 
our own path from %INC!";
+   my $Git_Error_pm_path = $INC{"Git/LoadCPAN/Error.pm"} || die "BUG: 
Should have our own path from %INC!";
 
require File::Basename;
my $Git_Error_pm_root = File::Basename::dirname($Git_Error_pm_path) || 
die "BUG: Can't figure out lib/Git dirname from '$Git_Error_pm_path'!";
 
require File::Spec;
-   my $Git_pm_FromCPAN_root = File::Spec->catdir($Git_Error_pm_root, 
'FromCPAN');
+   my $Git_pm_FromCPAN_root = File::Spec->catdir($Git_Error_pm_root, '..', 
'FromCPAN');
die "BUG: '$Git_pm_FromCPAN_root' should be a directory!" unless -d 
$Git_pm_FromCPAN_root;
 
local @INC = ($Git_pm_FromCPAN_root, @INC);
diff --git a/perl/Git/Mail/Address.pm b/perl/Git/LoadCPAN/Mail/Address.pm
similarity index 69%
rename from perl/Git/Mail/Address.pm
rename to perl/Git/LoadCPAN/Mail/Address.pm
index 2ce3e84670..879c2f5cd1 100644
--- a/perl/Git/Mail/Address.pm
+++ b/perl/Git/LoadCPAN/Mail/Address.pm
@@ -1,11 +1,11 @@
-package Git::Mail::Address;
+package Git::LoadCPAN::Mail::Address;
 use 5.008;
 use strict;
 use warnings;
 
 =head1 NAME
 
-Git::Mail::Address - Wrapper for the L module, in case it's not 
installed
+Git::LoadCPAN::Mail::Address - Wrapper for the L module, in 
case it's not installed
 
 =head1 DESCRIPTION
 
-- 
2.15.1.424.g9478a66081



[PATCH v3 07/13] perl: update our ancient copy of Error.pm

2018-03-03 Thread Ævar Arnfjörð Bjarmason
The Error.pm shipped with Git as a fallback if there was no Error.pm
on the system was released in April 2006. There's been dozens of
releases since then, the latest at August 7, 2017. Let's update to
that.

I don't know of anything we need from this new release or which this
fixes. This change is simply a matter of keeping up with
upstream. Before this users who'd install git via their package system
would get an up-to-date Error.pm, but if it's installed from source
they'd get one more than a decade old.

This undoes a local hack we'd accumulated in 96bc4de85c ("Eliminate
Scalar::Util usage from private-Error.pm", 2006-07-26), it's been
redundant since my d48b284183 ("perl: bump the required Perl version
to 5.8 from 5.6.[21]", 2010-09-24).

This also undoes 3a51467b94 ("Typo fix: replacing it's -> its",
2013-04-13). This is the Nth time I find that some upstream code of
ours (in contrib/, in sha1dc/ and now in perl/ ...) has diverged from
upstream because of some tree-wide typo fixing. Let's not do those
fixes against upstream projects, it's more valuable that we have a 1=1
mapping to upstream than to fix typos in docs we never even generate
from this code. If someone wants to fix typos in them fine, but they
should do it with a patch to upstream which git.git can then
incorporate.

The upstream code doesn't cleanly pass a --check, so I'm adding a
.gitattributes file for similar reasons as done for sha1dc in
5d184f468e ("sha1dc: ignore indent-with-non-tab whitespace
violations", 2017-06-06).

The updated source was retrieved from
https://fastapi.metacpan.org/source/SHLOMIF/Error-0.17025/lib/Error.pm

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git/FromCPAN/.gitattributes |   1 +
 perl/Git/FromCPAN/Error.pm   | 296 +--
 2 files changed, 256 insertions(+), 41 deletions(-)
 create mode 100644 perl/Git/FromCPAN/.gitattributes

diff --git a/perl/Git/FromCPAN/.gitattributes b/perl/Git/FromCPAN/.gitattributes
new file mode 100644
index 00..8b64fc5e22
--- /dev/null
+++ b/perl/Git/FromCPAN/.gitattributes
@@ -0,0 +1 @@
+/Error.pm whitespace=-blank-at-eof
diff --git a/perl/Git/FromCPAN/Error.pm b/perl/Git/FromCPAN/Error.pm
index 6098135ae2..f9c36e9e98 100644
--- a/perl/Git/FromCPAN/Error.pm
+++ b/perl/Git/FromCPAN/Error.pm
@@ -12,10 +12,12 @@
 package Error;
 
 use strict;
+use warnings;
+
 use vars qw($VERSION);
 use 5.004;
 
-$VERSION = "0.15009";
+$VERSION = "0.17025";
 
 use overload (
'""'   =>   'stringify',
@@ -32,21 +34,35 @@ $Error::THROWN = undef; # last error thrown, a 
workaround until die $ref works
 my $LAST;  # Last error created
 my %ERROR; # Last error associated with package
 
-sub throw_Error_Simple
+sub _throw_Error_Simple
 {
 my $args = shift;
 return Error::Simple->new($args->{'text'});
 }
 
-$Error::ObjectifyCallback = \_Error_Simple;
+$Error::ObjectifyCallback = \&_throw_Error_Simple;
 
 
 # Exported subs are defined in Error::subs
 
+use Scalar::Util ();
+
 sub import {
 shift;
+my @tags = @_;
 local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
-Error::subs->import(@_);
+
+@tags = grep {
+   if( $_ eq ':warndie' ) {
+  Error::WarnDie->import();
+  0;
+   }
+   else {
+  1;
+   }
+} @tags;
+
+Error::subs->import(@tags);
 }
 
 # I really want to use last for the name of this method, but it is a keyword
@@ -107,10 +123,6 @@ sub stacktrace {
 $text;
 }
 
-# Allow error propagation, ie
-#
-# $ber->encode(...) or
-#return Error->prior($ber)->associate($ldap);
 
 sub associate {
 my $err = shift;
@@ -130,6 +142,7 @@ sub associate {
 return;
 }
 
+
 sub new {
 my $self = shift;
 my($pkg,$file,$line) = caller($Error::Depth);
@@ -246,6 +259,10 @@ sub value {
 
 package Error::Simple;
 
+use vars qw($VERSION);
+
+$VERSION = "0.17025";
+
 @Error::Simple::ISA = qw(Error);
 
 sub new {
@@ -288,14 +305,6 @@ use vars qw(@EXPORT_OK @ISA %EXPORT_TAGS);
 
 @ISA = qw(Exporter);
 
-
-sub blessed {
-   my $item = shift;
-   local $@; # don't kill an outer $@
-   ref $item and eval { $item->can('can') };
-}
-
-
 sub run_clauses ($$$\@) {
 my($clauses,$err,$wantarray,$result) = @_;
 my $code = undef;
@@ -314,16 +323,17 @@ sub run_clauses ($$$\@) {
my $pkg = $catch->[$i];
unless(defined $pkg) {
#except
-   splice(@$catch,$i,2,$catch->[$i+1]->());
+   splice(@$catch,$i,2,$catch->[$i+1]->($err));
$i -= 2;
next CATCHLOOP;
}
-   elsif(blessed($err) && $err->isa($pkg)) {
+   elsif(Scalar::Util::blessed($err) && $err->isa($pkg)) {
$code = $catch->[$i+1];
while(1) {
my $more = 0;
-   local($Error::THROWN);
+   

[PATCH v3 08/13] perl: update our copy of Mail::Address

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Update our copy of Mail::Address from 2.19 (Aug 22, 2017) to 2.20 (Jan
23, 2018). Like the preceding Error.pm update this is done simply to
keep up-to-date with upstream, and as can be shown from the diff
there's no functional changes.

The updated source was retrieved from
https://fastapi.metacpan.org/source/MARKOV/MailTools-2.20/lib/Mail/Address.pm

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git/FromCPAN/Mail/Address.pm | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/perl/Git/FromCPAN/Mail/Address.pm 
b/perl/Git/FromCPAN/Mail/Address.pm
index 13b2ff7d05..683d490b2b 100644
--- a/perl/Git/FromCPAN/Mail/Address.pm
+++ b/perl/Git/FromCPAN/Mail/Address.pm
@@ -1,10 +1,14 @@
-# Copyrights 1995-2017 by [Mark Overmeer ].
+# Copyrights 1995-2018 by [Mark Overmeer].
 #  For other contributors see ChangeLog.
 # See the manual pages for details on the licensing terms.
 # Pod stripped from pm file by OODoc 2.02.
+# This code is part of the bundle MailTools.  Meta-POD processed with
+# OODoc into POD and HTML manual-pages.  See README.md for Copyright.
+# Licensed under the same terms as Perl itself.
+
 package Mail::Address;
 use vars '$VERSION';
-$VERSION = '2.19';
+$VERSION = '2.20';
 
 use strict;
 
-- 
2.15.1.424.g9478a66081



[PATCH v3 10/13] perl: generalize the Git::LoadCPAN facility

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Change the two wrappers that load from CPAN (local OS) or our own copy
to do so via the same codepath.

I added the Error.pm wrapper in 20d2a30f8f ("Makefile: replace
perl/Makefile.PL with simple make rules", 2017-12-10), and shortly
afterwards Matthieu Moy added a wrapper for Mail::Address in
bd869f67b9 ("send-email: add and use a local copy of Mail::Address",
2018-01-05).

His loader was simpler since Mail::Address doesn't have an "import"
method, but didn't do the same sanity checking; For example, a missing
FromCPAN directory (which OS packages are likely not to have) wouldn't
be explicitly warned about as a "BUG: ...".

Update both to use a common implementation based on the previous
Error.pm loader. Which has been amended to take the module to load as
parameter, as well as whether or not that module has an import
method.

This loader should be generic enough to handle almost all CPAN modules
out there, some use some crazy loading magic and wouldn't like being
wrapped like this, but that would be immediately obvious, and we'd
find out right away since the module wouldn't work at all.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git/LoadCPAN.pm  | 74 +++
 perl/Git/LoadCPAN/Error.pm| 44 +++
 perl/Git/LoadCPAN/Mail/Address.pm | 22 +++-
 3 files changed, 82 insertions(+), 58 deletions(-)
 create mode 100644 perl/Git/LoadCPAN.pm

diff --git a/perl/Git/LoadCPAN.pm b/perl/Git/LoadCPAN.pm
new file mode 100644
index 00..1568c177fe
--- /dev/null
+++ b/perl/Git/LoadCPAN.pm
@@ -0,0 +1,74 @@
+package Git::LoadCPAN;
+use 5.008;
+use strict;
+use warnings;
+
+=head1 NAME
+
+Git::LoadCPAN - Wrapper for loading modules from the CPAN (OS) or Git's own 
copy
+
+=head1 DESCRIPTION
+
+The Perl code in Git depends on some modules from the CPAN, but we
+don't want to make those a hard requirement for anyone building from
+source.
+
+Therefore the L namespace shipped with Git contains
+wrapper modules like C that will first
+attempt to load C from the OS, and if that doesn't work
+will fall back on C shipped with Git
+itself.
+
+Usually distributors will not ship with Git's Git::FromCPAN tree at
+all, preferring to use their own packaging of CPAN modules instead.
+
+This module is only intended to be used for code shipping in the
+C repository. Use it for anything else at your peril!
+
+=cut
+
+sub import {
+   shift;
+   my $caller = caller;
+   my %args = @_;
+   my $module = exists $args{module} ? delete $args{module} : die "BUG: 
Expected 'module' parameter!";
+   my $import = exists $args{import} ? delete $args{import} : die "BUG: 
Expected 'import' parameter!";
+   die "BUG: Too many arguments!" if keys %args;
+
+   # Foo::Bar to Foo/Bar.pm
+   my $package_pm = $module;
+   $package_pm =~ s[::][/]g;
+   $package_pm .= '.pm';
+
+   eval {
+   require $package_pm;
+   1;
+   } or do {
+   my $error = $@ || "Zombie Error";
+
+   my $Git_LoadCPAN_pm_path = $INC{"Git/LoadCPAN.pm"} || die "BUG: 
Should have our own path from %INC!";
+
+   require File::Basename;
+   my $Git_LoadCPAN_pm_root = 
File::Basename::dirname($Git_LoadCPAN_pm_path) || die "BUG: Can't figure out 
lib/Git dirname from '$Git_LoadCPAN_pm_path'!";
+
+   require File::Spec;
+   my $Git_pm_FromCPAN_root = 
File::Spec->catdir($Git_LoadCPAN_pm_root, 'FromCPAN');
+   die "BUG: '$Git_pm_FromCPAN_root' should be a directory!" 
unless -d $Git_pm_FromCPAN_root;
+
+   local @INC = ($Git_pm_FromCPAN_root, @INC);
+   require $package_pm;
+   };
+
+   if ($import) {
+   no strict 'refs';
+   *{"${caller}::import"} = sub {
+   shift;
+   use strict 'refs';
+   unshift @_, $module;
+   goto &{"${module}::import"};
+   };
+   use strict 'refs';
+   }
+}
+
+1;
diff --git a/perl/Git/LoadCPAN/Error.pm b/perl/Git/LoadCPAN/Error.pm
index 3513fe745b..c6d2c45d80 100644
--- a/perl/Git/LoadCPAN/Error.pm
+++ b/perl/Git/LoadCPAN/Error.pm
@@ -2,45 +2,9 @@ package Git::LoadCPAN::Error;
 use 5.008;
 use strict;
 use warnings;
-
-=head1 NAME
-
-Git::LoadCPAN::Error - Wrapper for the L module, in case it's not 
installed
-
-=head1 DESCRIPTION
-
-Wraps the import function for the L module.
-
-This module is only intended to be used for code shipping in the
-C repository. Use it for anything else at your peril!
-
-=cut
-
-sub import {
-shift;
-my $caller = caller;
-
-eval {
-   require Error;
-   1;
-} or do {
-   my $error = $@ || "Zombie Error";
-
-   my $Git_Error_pm_path = $INC{"Git/LoadCPAN/Error.pm"} || die "BUG: 
Should have our own path from %INC!";
-
-   require File::Basename;
-   my $Git_Error_pm_root = 

[PATCH v3 13/13] perl Git::LoadCPAN: emit better errors under NO_PERL_CPAN_FALLBACKS

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Before my 20d2a30f8f ("Makefile: replace perl/Makefile.PL with simple
make rules", 2017-12-10) on an OS package that removed the
private-Error.pm copy we carried around manually removing the OS's
Error.pm would yield:

$ git add -p
Can't locate Error.pm in @INC (you may need to install the Error module) 
[...]

Now, before this change we'll instead emit this more cryptic error:

$ git add -p
BUG: '/usr/share/perl5/Git/FromCPAN' should be a directory! at 
/usr/share/perl5/Git/Error.pm line 36.

This is a confusing error. Now if the new NO_PERL_CPAN_FALLBACKS
option is specified and we can't find the module we'll instead emit:

$ /tmp/git/bin/git add -p
BUG: The 'Error' module is not here, but NO_PERL_CPAN_FALLBACKS was set!

[...]

Where [...] is the lengthy explanation seen in the change below, which
explains what the potential breakage is, and how to fix it.

The reason for checking @@NO_PERL_CPAN_FALLBACKS@@] against the empty
string in Perl is as opposed to checking for a boolean value is that
that's (as far as I can tell) make's idea of a string that's set, and
e.g. NO_PERL_CPAN_FALLBACKS=0 is enough to set NO_PERL_CPAN_FALLBACKS.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 INSTALL  | 11 ---
 Makefile |  5 -
 perl/Git/LoadCPAN.pm | 33 -
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/INSTALL b/INSTALL
index 808e07b659..60e515eaf7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -88,9 +88,9 @@ Issues of note:
export GIT_EXEC_PATH PATH GITPERLLIB
 
  - By default (unless NO_PERL is provided) Git will ship various perl
-   scripts & libraries it needs. However, for simplicity it doesn't
-   use the ExtUtils::MakeMaker toolchain to decide where to place the
-   perl libraries. Depending on the system this can result in the perl
+   scripts. However, for simplicity it doesn't use the
+   ExtUtils::MakeMaker toolchain to decide where to place the perl
+   libraries. Depending on the system this can result in the perl
libraries not being where you'd like them if they're expected to be
used by things other than Git itself.
 
@@ -102,6 +102,11 @@ Issues of note:
Will result in e.g. perllibdir=/usr/share/perl/5.26.1 on Debian,
perllibdir=/usr/share/perl5 (which we'd use by default) on CentOS.
 
+ - Unless NO_PERL is provided Git will ship various perl libraries it
+   needs. Distributors of Git will usually want to set
+   NO_PERL_CPAN_FALLBACKS if NO_PERL is not provided to use their own
+   copies of the CPAN modules Git needs.
+
  - Git is reasonably self-sufficient, but does depend on a few external
programs and libraries.  Git can be used without most of them by adding
the approriate "NO_=YesPlease" to the make command line or
diff --git a/Makefile b/Makefile
index cbf0bc2344..56fc2d6f08 100644
--- a/Makefile
+++ b/Makefile
@@ -2316,11 +2316,14 @@ all:: $(LIB_PERL_GEN)
 ifndef NO_PERL_CPAN_FALLBACKS
 all:: $(LIB_CPAN_GEN)
 endif
+NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
 endif
 
 perl/build/lib/%.pm: perl/%.pm
$(QUIET_GEN)mkdir -p $(dir $@) && \
-   sed -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' < $< > $@
+   sed -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
+   -e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
+   < $< > $@
 
 perl/build/man/man3/Git.3pm: perl/Git.pm
$(QUIET_GEN)mkdir -p $(dir $@) && \
diff --git a/perl/Git/LoadCPAN.pm b/perl/Git/LoadCPAN.pm
index 229c1ee87d..e5585e75e8 100644
--- a/perl/Git/LoadCPAN.pm
+++ b/perl/Git/LoadCPAN.pm
@@ -19,13 +19,25 @@ attempt to load C from the OS, and if that 
doesn't work
 will fall back on C shipped with Git itself.
 
 Usually distributors will not ship with Git's Git::FromCPAN tree at
-all, preferring to use their own packaging of CPAN modules instead.
+all via the C option, preferring to use their
+own packaging of CPAN modules instead.
 
 This module is only intended to be used for code shipping in the
 C repository. Use it for anything else at your peril!
 
 =cut
 
+# NO_PERL_CPAN_FALLBACKS_STR evades the sed search-replace from the
+# Makefile, and allows for detecting whether the module is loaded from
+# perl/Git as opposed to perl/build/Git, which is useful for one-off
+# testing without having Error.pm et al installed.
+use constant NO_PERL_CPAN_FALLBACKS_STR => '@@' . 'NO_PERL_CPAN_FALLBACKS' . 
'@@';
+use constant NO_PERL_CPAN_FALLBACKS => (
+   q[@@NO_PERL_CPAN_FALLBACKS@@] ne ''
+   and
+   q[@@NO_PERL_CPAN_FALLBACKS@@] ne NO_PERL_CPAN_FALLBACKS_STR
+);
+
 sub import {
shift;
my $caller = caller;
@@ -45,6 +57,25 @@ sub import {
} or do {
my $error = $@ || "Zombie Error";
 
+   if (NO_PERL_CPAN_FALLBACKS) {
+   chomp(my $error = sprintf <<'THEY_PROMISED', $module);
+BUG: The '%s' module is not here, but NO_PERL_CPAN_FALLBACKS was set!
+

[PATCH v3 11/13] perl: move the perl/Git/FromCPAN tree to perl/FromCPAN

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Move the CPAN modules that have lived under perl/Git/FromCPAN since my
20d2a30f8f ("Makefile: replace perl/Makefile.PL with simple make
rules", 2017-12-10) to perl/FromCPAN.

A subsequent change will teach the Makefile to only install these
copies of CPAN modules if a flag that distro packagers would like to
set isn't set. Due to how the wildcard globbing is being done it's
much easier to accomplish that if they're moved to their own
directory.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 Makefile| 3 +++
 perl/{Git => }/FromCPAN/.gitattributes  | 0
 perl/{Git => }/FromCPAN/Error.pm| 0
 perl/{Git => }/FromCPAN/Mail/Address.pm | 0
 perl/Git/LoadCPAN.pm| 5 ++---
 5 files changed, 5 insertions(+), 3 deletions(-)
 rename perl/{Git => }/FromCPAN/.gitattributes (100%)
 rename perl/{Git => }/FromCPAN/Error.pm (100%)
 rename perl/{Git => }/FromCPAN/Mail/Address.pm (100%)

diff --git a/Makefile b/Makefile
index 5ae9616e0a..026b9fb6d6 100644
--- a/Makefile
+++ b/Makefile
@@ -2302,9 +2302,12 @@ po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
 
 LIB_PERL := $(wildcard perl/Git.pm perl/Git/*.pm perl/Git/*/*.pm 
perl/Git/*/*/*.pm)
 LIB_PERL_GEN := $(patsubst perl/%.pm,perl/build/lib/%.pm,$(LIB_PERL))
+LIB_CPAN := $(wildcard perl/FromCPAN/*.pm perl/FromCPAN/*/*.pm)
+LIB_CPAN_GEN := $(patsubst perl/%.pm,perl/build/lib/%.pm,$(LIB_CPAN))
 
 ifndef NO_PERL
 all:: $(LIB_PERL_GEN)
+all:: $(LIB_CPAN_GEN)
 endif
 
 perl/build/lib/%.pm: perl/%.pm
diff --git a/perl/Git/FromCPAN/.gitattributes b/perl/FromCPAN/.gitattributes
similarity index 100%
rename from perl/Git/FromCPAN/.gitattributes
rename to perl/FromCPAN/.gitattributes
diff --git a/perl/Git/FromCPAN/Error.pm b/perl/FromCPAN/Error.pm
similarity index 100%
rename from perl/Git/FromCPAN/Error.pm
rename to perl/FromCPAN/Error.pm
diff --git a/perl/Git/FromCPAN/Mail/Address.pm b/perl/FromCPAN/Mail/Address.pm
similarity index 100%
rename from perl/Git/FromCPAN/Mail/Address.pm
rename to perl/FromCPAN/Mail/Address.pm
diff --git a/perl/Git/LoadCPAN.pm b/perl/Git/LoadCPAN.pm
index 1568c177fe..229c1ee87d 100644
--- a/perl/Git/LoadCPAN.pm
+++ b/perl/Git/LoadCPAN.pm
@@ -16,8 +16,7 @@ source.
 Therefore the L namespace shipped with Git contains
 wrapper modules like C that will first
 attempt to load C from the OS, and if that doesn't work
-will fall back on C shipped with Git
-itself.
+will fall back on C shipped with Git itself.
 
 Usually distributors will not ship with Git's Git::FromCPAN tree at
 all, preferring to use their own packaging of CPAN modules instead.
@@ -52,7 +51,7 @@ sub import {
my $Git_LoadCPAN_pm_root = 
File::Basename::dirname($Git_LoadCPAN_pm_path) || die "BUG: Can't figure out 
lib/Git dirname from '$Git_LoadCPAN_pm_path'!";
 
require File::Spec;
-   my $Git_pm_FromCPAN_root = 
File::Spec->catdir($Git_LoadCPAN_pm_root, 'FromCPAN');
+   my $Git_pm_FromCPAN_root = 
File::Spec->catdir($Git_LoadCPAN_pm_root, '..', 'FromCPAN');
die "BUG: '$Git_pm_FromCPAN_root' should be a directory!" 
unless -d $Git_pm_FromCPAN_root;
 
local @INC = ($Git_pm_FromCPAN_root, @INC);
-- 
2.15.1.424.g9478a66081



[PATCH v3 06/13] git-send-email: unconditionally use Net::{SMTP,Domain}

2018-03-03 Thread Ævar Arnfjörð Bjarmason
The Net::SMTP and Net::Domain were both first released with perl
v5.7.3[1], since my d48b284183 ("perl: bump the required Perl version
to 5.8 from 5.6.[21]", 2010-09-24) we've depended on 5.8, so there's
no reason to conditionally require them anymore.

This conditional loading was initially added in
87840620fd ("send-email: only 'require' instead of 'use' Net::SMTP",
2006-06-01) for Net::SMTP and 134550fe21 ("git-send-email.perl - try
to give real name of the calling host to HELO/EHLO", 2010-03-14) for
Net::Domain, both of which predate the hard dependency on 5.8.

Since they're guaranteed to be installed now let's "use" them
instead. The cost of loading them both is trivial given what
git-send-email does (~15ms on my system), and it's better to not defer
any potential loading errors until runtime.

This patch is better viewed with -w, which shows that the only change
in the last two hunks is removing the "if eval" wrapper block.

1. $ parallel 'corelist {}' ::: Net::{SMTP,Domain}
   Data for 2015-02-14
   Net::SMTP was first released with perl v5.7.3

   Data for 2015-02-14
   Net::Domain was first released with perl v5.7.3

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 git-send-email.perl | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index bbf4deaa0d..d5a4826a1c 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -31,6 +31,8 @@ use Cwd qw(abs_path cwd);
 use Git;
 use Git::I18N;
 use Git::Mail::Address;
+use Net::Domain ();
+use Net::SMTP ();
 
 Getopt::Long::Configure qw/ pass_through /;
 
@@ -1143,10 +1145,8 @@ sub valid_fqdn {
 sub maildomain_net {
my $maildomain;
 
-   if (eval { require Net::Domain; 1 }) {
-   my $domain = Net::Domain::domainname();
-   $maildomain = $domain if valid_fqdn($domain);
-   }
+   my $domain = Net::Domain::domainname();
+   $maildomain = $domain if valid_fqdn($domain);
 
return $maildomain;
 }
@@ -1154,17 +1154,15 @@ sub maildomain_net {
 sub maildomain_mta {
my $maildomain;
 
-   if (eval { require Net::SMTP; 1 }) {
-   for my $host (qw(mailhost localhost)) {
-   my $smtp = Net::SMTP->new($host);
-   if (defined $smtp) {
-   my $domain = $smtp->domain;
-   $smtp->quit;
+   for my $host (qw(mailhost localhost)) {
+   my $smtp = Net::SMTP->new($host);
+   if (defined $smtp) {
+   my $domain = $smtp->domain;
+   $smtp->quit;
 
-   $maildomain = $domain if valid_fqdn($domain);
+   $maildomain = $domain if valid_fqdn($domain);
 
-   last if $maildomain;
-   }
+   last if $maildomain;
}
}
 
-- 
2.15.1.424.g9478a66081



[PATCH v3 05/13] Git.pm: hard-depend on the File::{Temp,Spec} modules

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Since my d48b284183 ("perl: bump the required Perl version to 5.8 from
5.6.[21]", 2010-09-24), we've depended on 5.8, so there's no reason to
conditionally require File::Temp and File::Spec anymore. They were
first released with perl versions v5.6.1 and 5.00405, respectively.

This code was originally added in c14c8ceb13 ("Git.pm: Make File::Spec
and File::Temp requirement lazy", 2008-08-15), presumably to make
Git.pm work on 5.6.0.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git.pm | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 7ec16e6dde..151b0e7144 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -11,6 +11,8 @@ use 5.008;
 use strict;
 use warnings;
 
+use File::Temp ();
+use File::Spec ();
 
 BEGIN {
 
@@ -190,7 +192,6 @@ sub repository {
};
 
if ($dir) {
-   _verify_require();
File::Spec->file_name_is_absolute($dir) or $dir = 
$opts{Directory} . '/' . $dir;
$opts{Repository} = abs_path($dir);
 
@@ -1289,8 +1290,6 @@ sub temp_release {
 sub _temp_cache {
my ($self, $name) = _maybe_self(@_);
 
-   _verify_require();
-
my $temp_fd = \$TEMP_FILEMAP{$name};
if (defined $$temp_fd and $$temp_fd->opened) {
if ($TEMP_FILES{$$temp_fd}{locked}) {
@@ -1324,11 +1323,6 @@ sub _temp_cache {
$$temp_fd;
 }
 
-sub _verify_require {
-   eval { require File::Temp; require File::Spec; };
-   $@ and throw Error::Simple($@);
-}
-
 =item temp_reset ( FILEHANDLE )
 
 Truncates and resets the position of the C.
-- 
2.15.1.424.g9478a66081



[PATCH v3 04/13] gitweb: hard-depend on the Digest::MD5 5.8 module

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Since my d48b284183 ("perl: bump the required Perl version to 5.8 from
5.6.[21]", 2010-09-24), we've depended on 5.8, so there's no reason to
conditionally require Digest::MD5 anymore. It was released with perl
v5.7.3[1]

The initial introduction of the dependency in
e9fdd74e53 ("gitweb: (gr)avatar support", 2009-06-30) says as much,
this also undoes part of the later 2e9c8789b7 ("gitweb: Mention
optional Perl modules in INSTALL", 2011-02-04) since gitweb will
always be run on at least 5.8, so there's no need to mention
Digest::MD5 as a required module in the documentation, let's instead
say that we require perl 5.8.

1. $ corelist Digest::MD5
   Data for 2015-02-14
   Digest::MD5 was first released with perl v5.7.3

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 gitweb/INSTALL |  3 +--
 gitweb/gitweb.perl | 17 -
 2 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index 408f2859d3..a58e6b3c44 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -29,12 +29,11 @@ Requirements
 
 
  - Core git tools
- - Perl
+ - Perl 5.8
  - Perl modules: CGI, Encode, Fcntl, File::Find, File::Basename.
  - web server
 
 The following optional Perl modules are required for extra features
- - Digest::MD5 - for gravatar support
  - CGI::Fast and FCGI - for running gitweb as FastCGI script
  - HTML::TagCloud - for fancy tag cloud in project list view
  - HTTP::Date or Time::ParseDate - to support If-Modified-Since for feeds
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 2417057f2b..2594a4badb 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -20,6 +20,8 @@ use Fcntl ':mode';
 use File::Find qw();
 use File::Basename qw(basename);
 use Time::HiRes qw(gettimeofday tv_interval);
+use Digest::MD5 qw(md5_hex);
+
 binmode STDOUT, ':utf8';
 
 if (!defined($CGI::VERSION) || $CGI::VERSION < 4.08) {
@@ -490,7 +492,6 @@ our %feature = (
# Currently available providers are gravatar and picon.
# If an unknown provider is specified, the feature is disabled.
 
-   # Gravatar depends on Digest::MD5.
# Picon currently relies on the indiana.edu database.
 
# To enable system wide have in $GITWEB_CONFIG
@@ -1166,18 +1167,8 @@ sub configure_gitweb_features {
our @snapshot_fmts = gitweb_get_feature('snapshot');
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
 
-   # check that the avatar feature is set to a known provider name,
-   # and for each provider check if the dependencies are satisfied.
-   # if the provider name is invalid or the dependencies are not met,
-   # reset $git_avatar to the empty string.
our ($git_avatar) = gitweb_get_feature('avatar');
-   if ($git_avatar eq 'gravatar') {
-   $git_avatar = '' unless (eval { require Digest::MD5; 1; });
-   } elsif ($git_avatar eq 'picon') {
-   # no dependencies
-   } else {
-   $git_avatar = '';
-   }
+   $git_avatar = '' unless $git_avatar =~ /^(?:gravatar|picon)$/s;
 
our @extra_branch_refs = gitweb_get_feature('extra-branch-refs');
@extra_branch_refs = filter_and_validate_refs (@extra_branch_refs);
@@ -2167,7 +2158,7 @@ sub gravatar_url {
my $size = shift;
$avatar_cache{$email} ||=
"//www.gravatar.com/avatar/" .
-   Digest::MD5::md5_hex($email) . "?s=";
+   md5_hex($email) . "?s=";
return $avatar_cache{$email} . $size;
 }
 
-- 
2.15.1.424.g9478a66081



[PATCH v3 02/13] Git.pm: remove redundant "use strict" from sub-package

2018-03-03 Thread Ævar Arnfjörð Bjarmason
In Perl the "use strict/warnings" pragmas are lexical, thus there's no
reason to do:

package Foo;
use strict;
package Bar;
use strict;
$x = 5;

To satisfy the desire that the undeclared $x variable will be spotted
at compile-time. It's enough to include the first "use strict".

This functionally changes nothing, but makes a subsequent change where
"use warnings" will be added to Git.pm less confusing and less
verbose, since as with "strict" we'll only need to do that at the top
of the file.

Changes code initially added in a6065b548f ("Git.pm: Try to support
ActiveState output pipe", 2006-06-25).

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git.pm | 1 -
 1 file changed, 1 deletion(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 9d60d7948b..99e5d943af 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -1692,7 +1692,6 @@ sub DESTROY {
 # Pipe implementation for ActiveState Perl.
 
 package Git::activestate_pipe;
-use strict;
 
 sub TIEHANDLE {
my ($class, @params) = @_;
-- 
2.15.1.424.g9478a66081



[PATCH v3 03/13] Git.pm: add the "use warnings" pragma

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Amend Git.pm to load the "warnings" pragma like the rest of the code
in perl/ in addition to the existing "strict" pragma. This is
considered the bare minimum best practice in Perl.

Ever since this code was introduced in b1edc53d06 ("Introduce
Git.pm (v4)", 2006-06-24) it's only been using "strict", not
"warnings".

This leaves contrib/buildsystems/Generators/{QMake,VCproj}.pm and
contrib/mw-to-git/Git/Mediawiki.pm without "use warnings". Amending
those would be a sensible follow-up change, but I don't have an easy
way to test those so I'm not changing them.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/perl/Git.pm b/perl/Git.pm
index 99e5d943af..7ec16e6dde 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -9,6 +9,7 @@ package Git;
 
 use 5.008;
 use strict;
+use warnings;
 
 
 BEGIN {
-- 
2.15.1.424.g9478a66081



[PATCH v3 01/13] perl: *.pm files should not have the executable bit

2018-03-03 Thread Ævar Arnfjörð Bjarmason
The Git::Mail::Address file added in bd869f67b9 ("send-email: add and
use a local copy of Mail::Address", 2018-01-05) had the executable bit
set. That bit should not be set for *.pm files. It breaks nothing but
it is redundant and confusing as none of the other files have it and
these files are never executed as stand-alone programs.

Signed-off-by: Ævar Arnfjörð Bjarmason 
---
 perl/Git/Mail/Address.pm | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 mode change 100755 => 100644 perl/Git/Mail/Address.pm

diff --git a/perl/Git/Mail/Address.pm b/perl/Git/Mail/Address.pm
old mode 100755
new mode 100644
-- 
2.15.1.424.g9478a66081



[PATCH v3 00/13] various perl fixes

2018-03-03 Thread Ævar Arnfjörð Bjarmason
Same as v2 except rebased on master & a couple of commit message
fixes, thanks to Eric Sunshine (thanks!). tbdiff with v2:

 4: 0d67af28fb !  4: 8ad874c944 gitweb: hard-depend on the Digest::MD5 5.8 
module
@@ -14,9 +14,6 @@
 always be run on at least 5.8, so there's no need to mention
 Digest::MD5 as a required module in the documentation, let's instead
 say that we require perl 5.8.
-
-As with the preceding Net::{SMTP,Domain} change we now unconditionally
-"use" the module instead.
 
 1. $ corelist Digest::MD5
Data for 2015-02-14
 [...]
 6: 92429af3a3 !  6: 3f44312821 git-send-email: unconditionally use 
Net::{SMTP,Domain}
@@ -5,7 +5,7 @@
 The Net::SMTP and Net::Domain were both first released with perl
 v5.7.3[1], since my d48b284183 ("perl: bump the required Perl version
 to 5.8 from 5.6.[21]", 2010-09-24) we've depended on 5.8, so there's
-no reason to conditionally require this anymore.
+no reason to conditionally require them anymore.
 
 This conditional loading was initially added in
 87840620fd ("send-email: only 'require' instead of 'use' Net::SMTP",

Todd Zullinger (1):
  Makefile: add NO_PERL_CPAN_FALLBACKS knob

Ævar Arnfjörð Bjarmason (12):
  perl: *.pm files should not have the executable bit
  Git.pm: remove redundant "use strict" from sub-package
  Git.pm: add the "use warnings" pragma
  gitweb: hard-depend on the Digest::MD5 5.8 module
  Git.pm: hard-depend on the File::{Temp,Spec} modules
  git-send-email: unconditionally use Net::{SMTP,Domain}
  perl: update our ancient copy of Error.pm
  perl: update our copy of Mail::Address
  perl: move CPAN loader wrappers to another namespace
  perl: generalize the Git::LoadCPAN facility
  perl: move the perl/Git/FromCPAN tree to perl/FromCPAN
  perl Git::LoadCPAN: emit better errors under NO_PERL_CPAN_FALLBACKS

 INSTALL |  11 +-
 Makefile|  16 +-
 contrib/examples/git-difftool.perl  |   2 +-
 git-send-email.perl |  28 ++-
 gitweb/INSTALL  |   3 +-
 gitweb/gitweb.perl  |  17 +-
 perl/FromCPAN/.gitattributes|   1 +
 perl/{Git => }/FromCPAN/Error.pm| 296 +++-
 perl/{Git => }/FromCPAN/Mail/Address.pm |   8 +-
 perl/Git.pm |  14 +-
 perl/Git/Error.pm   |  46 -
 perl/Git/LoadCPAN.pm| 104 +++
 perl/Git/LoadCPAN/Error.pm  |  10 ++
 perl/Git/LoadCPAN/Mail/Address.pm   |  10 ++
 perl/Git/Mail/Address.pm|  24 ---
 15 files changed, 432 insertions(+), 158 deletions(-)
 create mode 100644 perl/FromCPAN/.gitattributes
 rename perl/{Git => }/FromCPAN/Error.pm (72%)
 rename perl/{Git => }/FromCPAN/Mail/Address.pm (96%)
 delete mode 100644 perl/Git/Error.pm
 create mode 100644 perl/Git/LoadCPAN.pm
 create mode 100644 perl/Git/LoadCPAN/Error.pm
 create mode 100644 perl/Git/LoadCPAN/Mail/Address.pm
 delete mode 100755 perl/Git/Mail/Address.pm

-- 
2.15.1.424.g9478a66081



Re: t006 broken under Mac OS

2018-03-03 Thread Jeff King
On Sat, Mar 03, 2018 at 01:52:05PM +0100, Torsten Bögershausen wrote:

> Beside that t1006 has a broken indentation (mixed spaces and TABs at
>  the beginning of the line, I get 4 errors here under Mac OS:
> 
> not ok 15 - Check %(refname) gives empty output
> not ok 36 - Check %(refname) gives empty output
> not ok 58 - Check %(refname) gives empty output
> not ok 89 - Check %(refname) gives empty output
> 
> 
> Running with debug and verbose shows that the empty files are not empty.
> The characters in the non-empty file are outside the ASCII range,
> so I copy  the stuff in here after running `od -c`  on the log file.
> And I don't have a clue, where this stuff comes from - but I get different
> "crap" with each run - seams as if there is a read behind a buffer ?

Yeah, I think the ref_array_item.refname flex-parameter is not valid.
This is the same issue Ramsay mentioned in:

  
https://public-inbox.org/git/58b2bdcd-d621-fd21-ab4d-6a9478319...@ramsayjones.plus.com/

Junio, I think it probably makes sense to eject ot/cat-batch-format from
pu for now. That series is on pause for a bit while Olga works on some
other refactoring, and it's causing problems for people who test pu
regularly.

-Peff


RE: [PATCH 0/3] git worktree prune improvements

2018-03-03 Thread Randall S. Becker
On March 2, 2018 10:39 PM, Nguy?n Thái Ng?c Duy wrote:
> This is something we could do to improve the situation when a user manually
> moves a worktree and not follow the update process (we have had the first
> reported case [1]). Plus a bit cleanup in gc.
> 
> I think this is something we should do until we somehow make the user
> aware that the worktree is broken as soon as they move a worktree
> manually. But there's some more work to get there.
> 
> [1] http://public-inbox.org/git/%3Caa98f187-4b1a-176d-2a1b-
> 826c99577...@aegee.org%3E

I wonder whether the OT thread discussion about branch annotation may have some 
value here. For some repositories I manage, I have received questions about 
whether there was some way to know that a branch in the clone was associated 
with a worktree "at any point in the past", which, once the worktree has been 
pruned, is not derivable in a formal computational sense - there may be 
specific conditions where it is. Perhaps, if that line of development moves 
forward, that we should considering annotating the worktree-created branch to 
help with our pruning process and to identify where the branch originated.

Just a thought.

Cheers,
Randall

-- Brief whoami:
  NonStop developer since approximately NonStop(2112884442)
  UNIX developer since approximately 421664400
-- In my real life, I talk too much.





Re: [PATCH 2/2] completion: simplify _git_notes

2018-03-03 Thread SZEDER Gábor
On Sat, Mar 3, 2018 at 10:23 AM, Nguyễn Thái Ngọc Duy  wrote:
> This also adds completion for 'git notes remove' with two options:
> --ignore-missing and --stdin.
>
> For some strange reason, 'git notes undefined --' completes --ref
> without even running --git-completion-helper. But since this is an error
> case (and we're not doing anything destructive, it's probably ok for now)
>
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  contrib/completion/git-completion.bash | 15 ++-
>  1 file changed, 2 insertions(+), 13 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash 
> b/contrib/completion/git-completion.bash
> index c310b241d3..ab80f4e6e8 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1836,19 +1836,8 @@ _git_notes ()
> add,--reedit-message=*|append,--reedit-message=*)
> __git_complete_refs --cur="${cur#*=}"
> ;;
> -   add,--*)
> -   __gitcomp_builtin notes_add
> -   ;;
> -   append,--*)
> -   __gitcomp_builtin notes_append
> -   ;;
> -   copy,--*)
> -   __gitcomp_builtin notes_copy
> -   ;;
> -   prune,--*)
> -   __gitcomp_builtin notes_prune
> -   ;;
> -   prune,*)

There is a minor behaviour change here, though.  This

  prune,*)
;;

case arm ensured that we don't list refs for 'git notes prune ',
because it doesn't accept them (and then we take our usual fallback and
let Bash complete filenames;  yeah, 'git notes prune' doesn't accept
filenames either, but, as I said, that's our usual fallback when we
can't offer anything for completion).

This patch removes that case arm, and refs will be offered for 'git
notes prune '.

> +   *,--*)
> +   __gitcomp_builtin notes_$subcommand
> ;;
> *)
> case "$prev" in
> --
> 2.16.1.435.g8f24da2e1a
>


t006 broken under Mac OS

2018-03-03 Thread Torsten Bögershausen
Hej,
Beside that t1006 has a broken indentation (mixed spaces and TABs at
 the beginning of the line, I get 4 errors here under Mac OS:

not ok 15 - Check %(refname) gives empty output
not ok 36 - Check %(refname) gives empty output
not ok 58 - Check %(refname) gives empty output
not ok 89 - Check %(refname) gives empty output


Running with debug and verbose shows that the empty files are not empty.
The characters in the non-empty file are outside the ASCII range,
so I copy  the stuff in here after running `od -c`  on the log file.
And I don't have a clue, where this stuff comes from - but I get different
"crap" with each run - seams as if there is a read behind a buffer ?



15:
00060000  \n   @   @   -   1   +   1   @   @  \n   -  \n
0006020+ 361   r   0 360 024 254  \n   n   o   t   o   k   1
00060405   -   C   h   e   c   k   %   (   r   e   f   n
0006060a   m   e   )   g   i   v   e   s   e   m   p   t   y
0006100o   u   t   p   u   t  \n   #  \t  \n   #  \t  \t   e   c


36:
0016220-   1   +   1   @   @  \n   -  \n   + 225   x   <   e
0016240  240   @  \n   n   o   t   o   k   3   6   -   C
0016260h   e   c   k   %   (   r   e   f   n   a   m   e   )
0016300g   i   v   e   s   e   m   p   t   y   o   u   t   p
0016320u   t  \n   #  \t  \n   #  \t  \t   e   c   h   o   "   $

58:
0027120   \n   @   @   -   1   +   1   @   @  \n   -  \n   +
0027140  302 206  \a   4 220 311  \n   n   o   t   o   k   5   8
0027160-   C   h   e   c   k   %   (   r   e   f   n   a
0027200m   e   )   g   i   v   e   s   e   m   p   t   y
0027220o   u   t   p   u   t  \n   #  \t  \n   #  \t  \t   e   c   h

89:
00431600   0   0  \n   @   @   -   1   +   1   @   @  \n
0043200-  \n   +   p 034 276 034   !   ;  \n   n   o   t   o   k
00432208   9   -   C   h   e   c   k   %   (   r   e
0043240f   n   a   m   e   )   g   i   v   e   s   e   m   p
0043260t   y   o   u   t   p   u   t  \n   #  \t  \n   #  \t  \t


Re: [PATCH 2/2] completion: simplify _git_notes

2018-03-03 Thread SZEDER Gábor
On Sat, Mar 3, 2018 at 10:23 AM, Nguyễn Thái Ngọc Duy  wrote:
> This also adds completion for 'git notes remove' with two options:
> --ignore-missing and --stdin.
>
> For some strange reason, 'git notes undefined --' completes --ref
> without even running --git-completion-helper.

There is nothing strange about it.  _git_notes() first looks for the
presence of any subcommands on the command line, and if it doesn't find
any, it will list 'git notes's subcommands and options for completion.
And it does so by running '__gitcomp "$subcommands --ref"'

> But since this is an error
> case (and we're not doing anything destructive, it's probably ok for now)

I agree; and it matches the behaviour before the patch.

> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  contrib/completion/git-completion.bash | 15 ++-
>  1 file changed, 2 insertions(+), 13 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash 
> b/contrib/completion/git-completion.bash
> index c310b241d3..ab80f4e6e8 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1836,19 +1836,8 @@ _git_notes ()
> add,--reedit-message=*|append,--reedit-message=*)
> __git_complete_refs --cur="${cur#*=}"
> ;;
> -   add,--*)
> -   __gitcomp_builtin notes_add
> -   ;;
> -   append,--*)
> -   __gitcomp_builtin notes_append
> -   ;;
> -   copy,--*)
> -   __gitcomp_builtin notes_copy
> -   ;;
> -   prune,--*)
> -   __gitcomp_builtin notes_prune
> -   ;;
> -   prune,*)
> +   *,--*)
> +   __gitcomp_builtin notes_$subcommand
> ;;
> *)
> case "$prev" in
> --
> 2.16.1.435.g8f24da2e1a
>


[PATCH 41/44] packfile: allow reprepare_packed_git to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 8 
 packfile.h | 3 +--
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/packfile.c b/packfile.c
index 2276e2ad26..fbf5d56754 100644
--- a/packfile.c
+++ b/packfile.c
@@ -897,11 +897,11 @@ void prepare_packed_git(struct repository *r)
r->objects.packed_git_initialized = 1;
 }
 
-void reprepare_packed_git_the_repository(void)
+void reprepare_packed_git(struct repository *r)
 {
-   the_repository->objects.approximate_object_count_valid = 0;
-   the_repository->objects.packed_git_initialized = 0;
-   prepare_packed_git(the_repository);
+   r->objects.approximate_object_count_valid = 0;
+   r->objects.packed_git_initialized = 0;
+   prepare_packed_git(r);
 }
 
 struct packed_git *get_packed_git(struct repository *r)
diff --git a/packfile.h b/packfile.h
index 3fd9092472..ee6da3a9ae 100644
--- a/packfile.h
+++ b/packfile.h
@@ -35,8 +35,7 @@ extern struct packed_git *parse_pack_index(unsigned char 
*sha1, const char *idx_
 extern void (*report_garbage)(unsigned seen_bits, const char *path);
 
 extern void prepare_packed_git(struct repository *r);
-#define reprepare_packed_git(r) reprepare_packed_git_##r()
-extern void reprepare_packed_git_the_repository(void);
+extern void reprepare_packed_git(struct repository *r);
 extern void install_packed_git(struct repository *r, struct packed_git *pack);
 
 struct packed_git *get_packed_git(struct repository *r);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 33/44] packfile: allow prepare_packed_git_mru to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

This conversion was done without the #define trick used in the earlier
series refactoring to have better repository access, because this function
is easy to review, as all lines are converted and it has only one caller

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/packfile.c b/packfile.c
index a0842521e5..0eaf5ee100 100644
--- a/packfile.c
+++ b/packfile.c
@@ -872,14 +872,14 @@ static void rearrange_packed_git(void)
set_next_packed_git, sort_pack);
 }
 
-static void prepare_packed_git_mru(void)
+static void prepare_packed_git_mru(struct repository *r)
 {
struct packed_git *p;
 
-   INIT_LIST_HEAD(_repository->objects.packed_git_mru);
+   INIT_LIST_HEAD(>objects.packed_git_mru);
 
-   for (p = the_repository->objects.packed_git; p; p = p->next)
-   list_add_tail(>mru, _repository->objects.packed_git_mru);
+   for (p = r->objects.packed_git; p; p = p->next)
+   list_add_tail(>mru, >objects.packed_git_mru);
 }
 
 void prepare_packed_git(void)
@@ -893,7 +893,7 @@ void prepare_packed_git(void)
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
prepare_packed_git_one(alt->path, 0);
rearrange_packed_git();
-   prepare_packed_git_mru();
+   prepare_packed_git_mru(the_repository);
the_repository->objects.packed_git_initialized = 1;
 }
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 42/44] packfile: add repository argument to find_pack_entry

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

While at it move the documentation to the header and mention which pack
files are searched.

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c  | 8 ++--
 packfile.h  | 7 ++-
 sha1_file.c | 6 +++---
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/packfile.c b/packfile.c
index fbf5d56754..7388debbb2 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1844,11 +1844,7 @@ static int fill_pack_entry(const unsigned char *sha1,
return 1;
 }
 
-/*
- * Iff a pack file contains the object named by sha1, return true and
- * store its location to e.
- */
-int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
+int find_pack_entry_the_repository(const unsigned char *sha1, struct 
pack_entry *e)
 {
struct list_head *pos;
 
@@ -1870,7 +1866,7 @@ int find_pack_entry(const unsigned char *sha1, struct 
pack_entry *e)
 int has_sha1_pack(const unsigned char *sha1)
 {
struct pack_entry e;
-   return find_pack_entry(sha1, );
+   return find_pack_entry(the_repository, sha1, );
 }
 
 int has_pack_index(const unsigned char *sha1)
diff --git a/packfile.h b/packfile.h
index ee6da3a9ae..e68f790ea7 100644
--- a/packfile.h
+++ b/packfile.h
@@ -123,7 +123,12 @@ extern int packed_object_info(struct packed_git *pack, 
off_t offset, struct obje
 extern void mark_bad_packed_object(struct packed_git *p, const unsigned char 
*sha1);
 extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1);
 
-extern int find_pack_entry(const unsigned char *sha1, struct pack_entry *e);
+/*
+ * Iff a pack file in the given repository contains the object named by sha1,
+ * return true and store its location to e.
+ */
+#define find_pack_entry(r, s, e) find_pack_entry_##r(s, e)
+extern int find_pack_entry_the_repository(const unsigned char *sha1, struct 
pack_entry *e);
 
 extern int has_sha1_pack(const unsigned char *sha1);
 
diff --git a/sha1_file.c b/sha1_file.c
index be84f84373..ba47963e63 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1266,7 +1266,7 @@ int sha1_object_info_extended(const unsigned char *sha1, 
struct object_info *oi,
}
 
while (1) {
-   if (find_pack_entry(real, ))
+   if (find_pack_entry(the_repository, real, ))
break;
 
/* Most likely it's a loose object. */
@@ -1275,7 +1275,7 @@ int sha1_object_info_extended(const unsigned char *sha1, 
struct object_info *oi,
 
/* Not a loose object; someone else may have just packed it. */
reprepare_packed_git(the_repository);
-   if (find_pack_entry(real, ))
+   if (find_pack_entry(the_repository, real, ))
break;
 
/* Check if it is a missing object */
@@ -1655,7 +1655,7 @@ static int freshen_loose_object(const unsigned char *sha1)
 static int freshen_packed_object(const unsigned char *sha1)
 {
struct pack_entry e;
-   if (!find_pack_entry(sha1, ))
+   if (!find_pack_entry(the_repository, sha1, ))
return 0;
if (e.p->freshened)
return 1;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 44/44] packfile: keep prepare_packed_git() private

2018-03-03 Thread Nguyễn Thái Ngọc Duy
The reason callers have to call this is to make sure either packed_git
or packed_git_mru pointers are initialized since we don't do that by
default. Sometimes it's hard to see this connection between where the
function is called and where packed_git pointer is used (sometimes in
separate functions).

Keep this dependency internal because now all access to packed_git and
packed_git_mru must go through get_xxx() wrappers.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/count-objects.c  | 3 +--
 builtin/fsck.c   | 2 --
 builtin/gc.c | 1 -
 builtin/pack-objects.c   | 1 -
 builtin/pack-redundant.c | 2 --
 fast-import.c| 1 -
 http-backend.c   | 1 -
 pack-bitmap.c| 1 -
 packfile.c   | 5 -
 packfile.h   | 1 -
 server-info.c| 1 -
 sha1_name.c  | 2 --
 12 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 2793c98ed3..ee6ae35244 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -121,8 +121,7 @@ int cmd_count_objects(int argc, const char **argv, const 
char *prefix)
struct strbuf loose_buf = STRBUF_INIT;
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
-   if (!get_packed_git(the_repository))
-   prepare_packed_git(the_repository);
+
for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 7a3e323e9e..9911c52bc8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -726,8 +726,6 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
uint32_t total = 0, count = 0;
struct progress *progress = NULL;
 
-   prepare_packed_git(the_repository);
-
if (show_progress) {
for (p = get_packed_git(the_repository); p;
 p = p->next) {
diff --git a/builtin/gc.c b/builtin/gc.c
index 560d58daec..be63bec09c 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -173,7 +173,6 @@ static int too_many_packs(void)
if (gc_auto_pack_limit <= 0)
return 0;
 
-   prepare_packed_git(the_repository);
for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 6020a7e230..435f091a69 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3151,7 +3151,6 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
if (progress && all_progress_implied)
progress = 2;
 
-   prepare_packed_git(the_repository);
if (ignore_packed_keep) {
struct packed_git *p;
for (p = get_packed_git(the_repository); p; p = p->next)
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index bf42e164eb..02b5f0becc 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -630,8 +630,6 @@ int cmd_pack_redundant(int argc, const char **argv, const 
char *prefix)
break;
}
 
-   prepare_packed_git(the_repository);
-
if (load_all_packs)
load_all();
else
diff --git a/fast-import.c b/fast-import.c
index 985eb2eccc..2298bfcdfd 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -3472,7 +3472,6 @@ int cmd_main(int argc, const char **argv)
rc_free[i].next = _free[i + 1];
rc_free[cmd_save - 1].next = NULL;
 
-   prepare_packed_git(the_repository);
start_packfile();
set_die_routine(die_nicely);
set_checkpoint_signal();
diff --git a/http-backend.c b/http-backend.c
index 659ddfb5f1..22d2e1668e 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -518,7 +518,6 @@ static void get_info_packs(struct strbuf *hdr, char *arg)
size_t cnt = 0;
 
select_getanyfile(hdr);
-   prepare_packed_git(the_repository);
for (p = get_packed_git(the_repository); p; p = p->next) {
if (p->pack_local)
cnt++;
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 01c9cd1642..2a007b5539 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -335,7 +335,6 @@ static int open_pack_bitmap(void)
 
assert(!bitmap_git.map && !bitmap_git.loaded);
 
-   prepare_packed_git(the_repository);
for (p = get_packed_git(the_repository); p; p = p->next) {
if (open_pack_bitmap_1(p) == 0)
ret = 0;
diff --git a/packfile.c b/packfile.c
index bafe81544d..773cd99a13 100644
--- a/packfile.c
+++ b/packfile.c
@@ -802,6 +802,7 @@ static void prepare_packed_git_one(struct repository *r, 
char 

[PATCH 39/44] packfile: allow prepare_packed_git_one to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/packfile.c b/packfile.c
index 53db240d0f..52febba932 100644
--- a/packfile.c
+++ b/packfile.c
@@ -734,8 +734,7 @@ static void report_pack_garbage(struct string_list *list)
report_helper(list, seen_bits, first, list->nr);
 }
 
-#define prepare_packed_git_one(r, o, l) prepare_packed_git_one_##r(o, l)
-static void prepare_packed_git_one_the_repository(char *objdir, int local)
+static void prepare_packed_git_one(struct repository *r, char *objdir, int 
local)
 {
struct strbuf path = STRBUF_INIT;
size_t dirnamelen;
@@ -768,7 +767,7 @@ static void prepare_packed_git_one_the_repository(char 
*objdir, int local)
base_len = path.len;
if (strip_suffix_mem(path.buf, _len, ".idx")) {
/* Don't reopen a pack we already have. */
-   for (p = the_repository->objects.packed_git; p;
+   for (p = r->objects.packed_git; p;
 p = p->next) {
size_t len;
if (strip_suffix(p->pack_name, ".pack", ) &&
@@ -782,7 +781,7 @@ static void prepare_packed_git_one_the_repository(char 
*objdir, int local)
 * corresponding .pack file that we can map.
 */
(p = add_packed_git(path.buf, path.len, local)) != 
NULL)
-   install_packed_git(the_repository, p);
+   install_packed_git(r, p);
}
 
if (!report_garbage)
-- 
2.16.1.435.g8f24da2e1a



[PATCH 40/44] packfile: allow prepare_packed_git to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 18 +-
 packfile.h |  3 +--
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/packfile.c b/packfile.c
index 52febba932..2276e2ad26 100644
--- a/packfile.c
+++ b/packfile.c
@@ -882,19 +882,19 @@ static void prepare_packed_git_mru(struct repository *r)
list_add_tail(>mru, >objects.packed_git_mru);
 }
 
-void prepare_packed_git_the_repository(void)
+void prepare_packed_git(struct repository *r)
 {
struct alternate_object_database *alt;
 
-   if (the_repository->objects.packed_git_initialized)
+   if (r->objects.packed_git_initialized)
return;
-   prepare_packed_git_one(the_repository, get_object_directory(), 1);
-   prepare_alt_odb(the_repository);
-   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
-   prepare_packed_git_one(the_repository, alt->path, 0);
-   rearrange_packed_git(the_repository);
-   prepare_packed_git_mru(the_repository);
-   the_repository->objects.packed_git_initialized = 1;
+   prepare_packed_git_one(r, get_object_directory(), 1);
+   prepare_alt_odb(r);
+   for (alt = r->objects.alt_odb_list; alt; alt = alt->next)
+   prepare_packed_git_one(r, alt->path, 0);
+   rearrange_packed_git(r);
+   prepare_packed_git_mru(r);
+   r->objects.packed_git_initialized = 1;
 }
 
 void reprepare_packed_git_the_repository(void)
diff --git a/packfile.h b/packfile.h
index ab5046938c..3fd9092472 100644
--- a/packfile.h
+++ b/packfile.h
@@ -34,8 +34,7 @@ extern struct packed_git *parse_pack_index(unsigned char 
*sha1, const char *idx_
 #define PACKDIR_FILE_GARBAGE 4
 extern void (*report_garbage)(unsigned seen_bits, const char *path);
 
-#define prepare_packed_git(r) prepare_packed_git_##r()
-extern void prepare_packed_git_the_repository(void);
+extern void prepare_packed_git(struct repository *r);
 #define reprepare_packed_git(r) reprepare_packed_git_##r()
 extern void reprepare_packed_git_the_repository(void);
 extern void install_packed_git(struct repository *r, struct packed_git *pack);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 37/44] packfile: add repository argument to prepare_packed_git

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow prepare_packed_git callers to
be more specific about which repository to handle. See c28d027a52c
(sha1_file: add repository argument to link_alt_odb_entry, 2018-02-20)
for an explanation of the #define trick.

Signed-off-by: Stefan Beller 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/count-objects.c  |  2 +-
 builtin/fsck.c   |  2 +-
 builtin/gc.c |  2 +-
 builtin/pack-objects.c   |  2 +-
 builtin/pack-redundant.c |  2 +-
 fast-import.c|  2 +-
 http-backend.c   |  2 +-
 pack-bitmap.c|  2 +-
 packfile.c   | 10 +-
 packfile.h   |  3 ++-
 server-info.c|  2 +-
 sha1_name.c  |  4 ++--
 12 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 5c7c3c6ae3..2793c98ed3 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -122,7 +122,7 @@ int cmd_count_objects(int argc, const char **argv, const 
char *prefix)
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
if (!get_packed_git(the_repository))
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index b0abba6e04..7a3e323e9e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -726,7 +726,7 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
uint32_t total = 0, count = 0;
struct progress *progress = NULL;
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
 
if (show_progress) {
for (p = get_packed_git(the_repository); p;
diff --git a/builtin/gc.c b/builtin/gc.c
index dd30067ac1..526f06173e 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -173,7 +173,7 @@ static int too_many_packs(void)
if (gc_auto_pack_limit <= 0)
return 0;
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 0e5fde1d6b..6020a7e230 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3151,7 +3151,7 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
if (progress && all_progress_implied)
progress = 2;
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
if (ignore_packed_keep) {
struct packed_git *p;
for (p = get_packed_git(the_repository); p; p = p->next)
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index d6d8a44959..bf42e164eb 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -630,7 +630,7 @@ int cmd_pack_redundant(int argc, const char **argv, const 
char *prefix)
break;
}
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
 
if (load_all_packs)
load_all();
diff --git a/fast-import.c b/fast-import.c
index ec78e8ff47..985eb2eccc 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -3472,7 +3472,7 @@ int cmd_main(int argc, const char **argv)
rc_free[i].next = _free[i + 1];
rc_free[cmd_save - 1].next = NULL;
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
start_packfile();
set_die_routine(die_nicely);
set_checkpoint_signal();
diff --git a/http-backend.c b/http-backend.c
index 22921d169a..659ddfb5f1 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -518,7 +518,7 @@ static void get_info_packs(struct strbuf *hdr, char *arg)
size_t cnt = 0;
 
select_getanyfile(hdr);
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
for (p = get_packed_git(the_repository); p; p = p->next) {
if (p->pack_local)
cnt++;
diff --git a/pack-bitmap.c b/pack-bitmap.c
index abed43cdb5..01c9cd1642 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -335,7 +335,7 @@ static int open_pack_bitmap(void)
 
assert(!bitmap_git.map && !bitmap_git.loaded);
 
-   prepare_packed_git();
+   prepare_packed_git(the_repository);
for (p = get_packed_git(the_repository); p; p = p->next) {
if (open_pack_bitmap_1(p) == 0)
ret = 0;
diff --git a/packfile.c b/packfile.c
index d7658e6c45..b5ad6838f8 100644
--- a/packfile.c
+++ 

[PATCH 43/44] packfile: allow find_pack_entry to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 11 +--
 packfile.h |  3 +--
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/packfile.c b/packfile.c
index 7388debbb2..bafe81544d 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1844,19 +1844,18 @@ static int fill_pack_entry(const unsigned char *sha1,
return 1;
 }
 
-int find_pack_entry_the_repository(const unsigned char *sha1, struct 
pack_entry *e)
+int find_pack_entry(struct repository *r, const unsigned char *sha1, struct 
pack_entry *e)
 {
struct list_head *pos;
 
-   prepare_packed_git(the_repository);
-   if (!the_repository->objects.packed_git)
+   prepare_packed_git(r);
+   if (!r->objects.packed_git)
return 0;
 
-   list_for_each(pos, _repository->objects.packed_git_mru) {
+   list_for_each(pos, >objects.packed_git_mru) {
struct packed_git *p = list_entry(pos, struct packed_git, mru);
if (fill_pack_entry(sha1, e, p)) {
-   list_move(>mru,
- _repository->objects.packed_git_mru);
+   list_move(>mru, >objects.packed_git_mru);
return 1;
}
}
diff --git a/packfile.h b/packfile.h
index e68f790ea7..fe1a6380e6 100644
--- a/packfile.h
+++ b/packfile.h
@@ -127,8 +127,7 @@ extern const struct packed_git *has_packed_and_bad(const 
unsigned char *sha1);
  * Iff a pack file in the given repository contains the object named by sha1,
  * return true and store its location to e.
  */
-#define find_pack_entry(r, s, e) find_pack_entry_##r(s, e)
-extern int find_pack_entry_the_repository(const unsigned char *sha1, struct 
pack_entry *e);
+extern int find_pack_entry(struct repository *r, const unsigned char *sha1, 
struct pack_entry *e);
 
 extern int has_sha1_pack(const unsigned char *sha1);
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 38/44] packfile: add repository argument to reprepare_packed_git

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

See previous patch for explanation.

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/gc.c   | 2 +-
 builtin/receive-pack.c | 3 ++-
 bulk-checkin.c | 3 ++-
 fetch-pack.c   | 3 ++-
 packfile.c | 2 +-
 packfile.h | 3 ++-
 sha1_file.c| 2 +-
 7 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index 526f06173e..560d58daec 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -477,7 +477,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
return error(FAILED_RUN, rerere.argv[0]);
 
report_garbage = report_pack_garbage;
-   reprepare_packed_git();
+   reprepare_packed_git(the_repository);
if (pack_garbage.nr > 0)
clean_pack_garbage();
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ac478b7b99..dfc69be1a2 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "repository.h"
 #include "config.h"
 #include "lockfile.h"
 #include "pack.h"
@@ -1777,7 +1778,7 @@ static const char *unpack(int err_fd, struct shallow_info 
*si)
status = finish_command();
if (status)
return "index-pack abnormal exit";
-   reprepare_packed_git();
+   reprepare_packed_git(the_repository);
}
return NULL;
 }
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 3310fd210a..eadc2d5172 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -3,6 +3,7 @@
  */
 #include "cache.h"
 #include "bulk-checkin.h"
+#include "repository.h"
 #include "csum-file.h"
 #include "pack.h"
 #include "strbuf.h"
@@ -57,7 +58,7 @@ static void finish_bulk_checkin(struct bulk_checkin_state 
*state)
 
strbuf_release();
/* Make objects we just wrote available to ourselves */
-   reprepare_packed_git();
+   reprepare_packed_git(the_repository);
 }
 
 static int already_written(struct bulk_checkin_state *state, unsigned char 
sha1[])
diff --git a/fetch-pack.c b/fetch-pack.c
index 8253d746e0..eac5928a27 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "repository.h"
 #include "config.h"
 #include "lockfile.h"
 #include "refs.h"
@@ -1192,7 +1193,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
prepare_shallow_info(, shallow);
ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
, pack_lockfile);
-   reprepare_packed_git();
+   reprepare_packed_git(the_repository);
update_shallow(args, sought, nr_sought, );
clear_shallow_info();
return ref_cpy;
diff --git a/packfile.c b/packfile.c
index b5ad6838f8..53db240d0f 100644
--- a/packfile.c
+++ b/packfile.c
@@ -898,7 +898,7 @@ void prepare_packed_git_the_repository(void)
the_repository->objects.packed_git_initialized = 1;
 }
 
-void reprepare_packed_git(void)
+void reprepare_packed_git_the_repository(void)
 {
the_repository->objects.approximate_object_count_valid = 0;
the_repository->objects.packed_git_initialized = 0;
diff --git a/packfile.h b/packfile.h
index 3f59456e7e..ab5046938c 100644
--- a/packfile.h
+++ b/packfile.h
@@ -36,7 +36,8 @@ extern void (*report_garbage)(unsigned seen_bits, const char 
*path);
 
 #define prepare_packed_git(r) prepare_packed_git_##r()
 extern void prepare_packed_git_the_repository(void);
-extern void reprepare_packed_git(void);
+#define reprepare_packed_git(r) reprepare_packed_git_##r()
+extern void reprepare_packed_git_the_repository(void);
 extern void install_packed_git(struct repository *r, struct packed_git *pack);
 
 struct packed_git *get_packed_git(struct repository *r);
diff --git a/sha1_file.c b/sha1_file.c
index 7066d4c9ce..be84f84373 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1274,7 +1274,7 @@ int sha1_object_info_extended(const unsigned char *sha1, 
struct object_info *oi,
return 0;
 
/* Not a loose object; someone else may have just packed it. */
-   reprepare_packed_git();
+   reprepare_packed_git(the_repository);
if (find_pack_entry(real, ))
break;
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 35/44] packfile: allow install_packed_git to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

This conversion was done without the #define trick used in the earlier
series refactoring to have better repository access, because this function
is easy to review, as it only has one caller and all lines but the first
two are converted.

We must not convert 'pack_open_fds' to be a repository specific variable,
as it is used to monitor resource usage of the machine that Git executes
on.

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 fast-import.c | 2 +-
 http.c| 2 +-
 packfile.c| 8 
 packfile.h| 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/fast-import.c b/fast-import.c
index 0dba555478..ec78e8ff47 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1037,7 +1037,7 @@ static void end_packfile(void)
if (!new_p)
die("core git rejected index %s", idx_name);
all_packs[pack_id] = new_p;
-   install_packed_git(new_p);
+   install_packed_git(the_repository, new_p);
free(idx_name);
 
/* Print the boundary */
diff --git a/http.c b/http.c
index df9dbea59c..649656b87c 100644
--- a/http.c
+++ b/http.c
@@ -2133,7 +2133,7 @@ int finish_http_pack_request(struct http_pack_request 
*preq)
return -1;
}
 
-   install_packed_git(p);
+   install_packed_git(the_repository, p);
free(tmp_idx);
return 0;
 }
diff --git a/packfile.c b/packfile.c
index 5356712717..ba185daec2 100644
--- a/packfile.c
+++ b/packfile.c
@@ -679,13 +679,13 @@ struct packed_git *add_packed_git(const char *path, 
size_t path_len, int local)
return p;
 }
 
-void install_packed_git(struct packed_git *pack)
+void install_packed_git(struct repository *r, struct packed_git *pack)
 {
if (pack->pack_fd != -1)
pack_open_fds++;
 
-   pack->next = the_repository->objects.packed_git;
-   the_repository->objects.packed_git = pack;
+   pack->next = r->objects.packed_git;
+   r->objects.packed_git = pack;
 }
 
 void (*report_garbage)(unsigned seen_bits, const char *path);
@@ -781,7 +781,7 @@ static void prepare_packed_git_one(char *objdir, int local)
 * corresponding .pack file that we can map.
 */
(p = add_packed_git(path.buf, path.len, local)) != 
NULL)
-   install_packed_git(p);
+   install_packed_git(the_repository, p);
}
 
if (!report_garbage)
diff --git a/packfile.h b/packfile.h
index 5b1ce00f84..77442172f0 100644
--- a/packfile.h
+++ b/packfile.h
@@ -36,7 +36,7 @@ extern void (*report_garbage)(unsigned seen_bits, const char 
*path);
 
 extern void prepare_packed_git(void);
 extern void reprepare_packed_git(void);
-extern void install_packed_git(struct packed_git *pack);
+extern void install_packed_git(struct repository *r, struct packed_git *pack);
 
 struct packed_git *get_packed_git(struct repository *r);
 struct list_head *get_packed_git_mru(struct repository *r);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 34/44] packfile: allow rearrange_packed_git to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/packfile.c b/packfile.c
index 0eaf5ee100..5356712717 100644
--- a/packfile.c
+++ b/packfile.c
@@ -865,10 +865,10 @@ static int sort_pack(const void *a_, const void *b_)
return -1;
 }
 
-static void rearrange_packed_git(void)
+static void rearrange_packed_git(struct repository *r)
 {
-   the_repository->objects.packed_git = llist_mergesort(
-   the_repository->objects.packed_git, get_next_packed_git,
+   r->objects.packed_git = llist_mergesort(
+   r->objects.packed_git, get_next_packed_git,
set_next_packed_git, sort_pack);
 }
 
@@ -892,7 +892,7 @@ void prepare_packed_git(void)
prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
prepare_packed_git_one(alt->path, 0);
-   rearrange_packed_git();
+   rearrange_packed_git(the_repository);
prepare_packed_git_mru(the_repository);
the_repository->objects.packed_git_initialized = 1;
 }
-- 
2.16.1.435.g8f24da2e1a



[PATCH 31/44] sha1_file: allow map_sha1_file to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h | 3 +--
 sha1_file.c| 5 +++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/object-store.h b/object-store.h
index 98622a2b98..521f5a1755 100644
--- a/object-store.h
+++ b/object-store.h
@@ -121,7 +121,6 @@ void raw_object_store_clear(struct raw_object_store *o);
  */
 void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned 
char *sha1);
 
-#define map_sha1_file(r, s, sz) map_sha1_file_##r(s, sz)
-void *map_sha1_file_the_repository(const unsigned char *sha1, unsigned long 
*size);
+void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned 
long *size);
 
 #endif /* OBJECT_STORE_H */
diff --git a/sha1_file.c b/sha1_file.c
index d4678f8162..c5a8b00aed 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -957,9 +957,10 @@ static void *map_sha1_file_1(struct repository *r, const 
char *path,
return map;
 }
 
-void *map_sha1_file_the_repository(const unsigned char *sha1, unsigned long 
*size)
+void *map_sha1_file(struct repository *r,
+   const unsigned char *sha1, unsigned long *size)
 {
-   return map_sha1_file_1(the_repository, NULL, sha1, size);
+   return map_sha1_file_1(r, NULL, sha1, size);
 }
 
 static int unpack_sha1_short_header(git_zstream *stream,
-- 
2.16.1.435.g8f24da2e1a



[PATCH 36/44] packfile: add repository argument to prepare_packed_git_one

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 packfile.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/packfile.c b/packfile.c
index ba185daec2..d7658e6c45 100644
--- a/packfile.c
+++ b/packfile.c
@@ -734,7 +734,8 @@ static void report_pack_garbage(struct string_list *list)
report_helper(list, seen_bits, first, list->nr);
 }
 
-static void prepare_packed_git_one(char *objdir, int local)
+#define prepare_packed_git_one(r, o, l) prepare_packed_git_one_##r(o, l)
+static void prepare_packed_git_one_the_repository(char *objdir, int local)
 {
struct strbuf path = STRBUF_INIT;
size_t dirnamelen;
@@ -888,10 +889,10 @@ void prepare_packed_git(void)
 
if (the_repository->objects.packed_git_initialized)
return;
-   prepare_packed_git_one(get_object_directory(), 1);
+   prepare_packed_git_one(the_repository, get_object_directory(), 1);
prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
-   prepare_packed_git_one(alt->path, 0);
+   prepare_packed_git_one(the_repository, alt->path, 0);
rearrange_packed_git(the_repository);
prepare_packed_git_mru(the_repository);
the_repository->objects.packed_git_initialized = 1;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 32/44] sha1_file: allow sha1_loose_object_info to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Jonathan Nieder 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index c5a8b00aed..7066d4c9ce 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1149,10 +1149,9 @@ int parse_sha1_header(const char *hdr, unsigned long 
*sizep)
return parse_sha1_header_extended(hdr, , 0);
 }
 
-#define sha1_loose_object_info(r, s, o, f) sha1_loose_object_info_##r(s, o, f)
-static int sha1_loose_object_info_the_repository(const unsigned char *sha1,
-struct object_info *oi,
-int flags)
+static int sha1_loose_object_info(struct repository *r,
+ const unsigned char *sha1,
+ struct object_info *oi, int flags)
 {
int status = 0;
unsigned long mapsize;
@@ -1176,14 +1175,14 @@ static int sha1_loose_object_info_the_repository(const 
unsigned char *sha1,
if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
const char *path;
struct stat st;
-   if (stat_sha1_file(the_repository, sha1, , ) < 0)
+   if (stat_sha1_file(r, sha1, , ) < 0)
return -1;
if (oi->disk_sizep)
*oi->disk_sizep = st.st_size;
return 0;
}
 
-   map = map_sha1_file(the_repository, sha1, );
+   map = map_sha1_file(r, sha1, );
if (!map)
return -1;
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 27/44] sha1_file: allow sha1_file_name to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h | 3 +--
 sha1_file.c| 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/object-store.h b/object-store.h
index ad4c7501d7..98622a2b98 100644
--- a/object-store.h
+++ b/object-store.h
@@ -119,8 +119,7 @@ void raw_object_store_clear(struct raw_object_store *o);
  * Put in `buf` the name of the file in the local object database that
  * would be used to store a loose object with the specified sha1.
  */
-#define sha1_file_name(r, b, s) sha1_file_name_##r(b, s)
-void sha1_file_name_the_repository(struct strbuf *buf, const unsigned char 
*sha1);
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned 
char *sha1);
 
 #define map_sha1_file(r, s, sz) map_sha1_file_##r(s, sz)
 void *map_sha1_file_the_repository(const unsigned char *sha1, unsigned long 
*size);
diff --git a/sha1_file.c b/sha1_file.c
index ecbf846f12..e04e0587c2 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -323,9 +323,9 @@ static void fill_sha1_path(struct strbuf *buf, const 
unsigned char *sha1)
}
 }
 
-void sha1_file_name_the_repository(struct strbuf *buf, const unsigned char 
*sha1)
+void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned 
char *sha1)
 {
-   strbuf_addstr(buf, get_object_directory());
+   strbuf_addstr(buf, r->objects.objectdir);
strbuf_addch(buf, '/');
fill_sha1_path(buf, sha1);
 }
-- 
2.16.1.435.g8f24da2e1a



[PATCH 29/44] sha1_file: allow open_sha1_file to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index f2533dd9e4..b3f7656c35 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -895,9 +895,8 @@ static int stat_sha1_file(struct repository *r, const 
unsigned char *sha1,
  * Like stat_sha1_file(), but actually open the object and return the
  * descriptor. See the caveats on the "path" parameter above.
  */
-#define open_sha1_file(r, s, p) open_sha1_file_##r(s, p)
-static int open_sha1_file_the_repository(const unsigned char *sha1,
-const char **path)
+static int open_sha1_file(struct repository *r,
+ const unsigned char *sha1, const char **path)
 {
int fd;
struct alternate_object_database *alt;
@@ -905,7 +904,7 @@ static int open_sha1_file_the_repository(const unsigned 
char *sha1,
static struct strbuf buf = STRBUF_INIT;
 
strbuf_reset();
-   sha1_file_name(the_repository, , sha1);
+   sha1_file_name(r, , sha1);
*path = buf.buf;
 
fd = git_open(*path);
@@ -913,8 +912,8 @@ static int open_sha1_file_the_repository(const unsigned 
char *sha1,
return fd;
most_interesting_errno = errno;
 
-   prepare_alt_odb(the_repository);
-   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
+   prepare_alt_odb(r);
+   for (alt = r->objects.alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
fd = git_open(*path);
if (fd >= 0)
-- 
2.16.1.435.g8f24da2e1a



[PATCH 30/44] sha1_file: allow map_sha1_file_1 to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Jonathan Nieder 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index b3f7656c35..d4678f8162 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -929,10 +929,8 @@ static int open_sha1_file(struct repository *r,
  * Map the loose object at "path" if it is not NULL, or the path found by
  * searching for a loose object named "sha1".
  */
-#define map_sha1_file_1(r, p, s, si) map_sha1_file_1_##r(p, s, si)
-static void *map_sha1_file_1_the_repository(const char *path,
-   const unsigned char *sha1,
-   unsigned long *size)
+static void *map_sha1_file_1(struct repository *r, const char *path,
+const unsigned char *sha1, unsigned long *size)
 {
void *map;
int fd;
@@ -940,7 +938,7 @@ static void *map_sha1_file_1_the_repository(const char 
*path,
if (path)
fd = git_open(path);
else
-   fd = open_sha1_file(the_repository, sha1, );
+   fd = open_sha1_file(r, sha1, );
map = NULL;
if (fd >= 0) {
struct stat st;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 28/44] sha1_file: allow stat_sha1_file to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index e04e0587c2..f2533dd9e4 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -867,23 +867,22 @@ int git_open_cloexec(const char *name, int flags)
  * Note that it may point to static storage and is only valid until another
  * call to sha1_file_name(), etc.
  */
-#define stat_sha1_file(r, s, st, p) stat_sha1_file_##r(s, st, p)
-static int stat_sha1_file_the_repository(const unsigned char *sha1,
-struct stat *st, const char **path)
+static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
+ struct stat *st, const char **path)
 {
struct alternate_object_database *alt;
static struct strbuf buf = STRBUF_INIT;
 
strbuf_reset();
-   sha1_file_name(the_repository, , sha1);
+   sha1_file_name(r, , sha1);
*path = buf.buf;
 
if (!lstat(*path, st))
return 0;
 
-   prepare_alt_odb(the_repository);
+   prepare_alt_odb(r);
errno = ENOENT;
-   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
+   for (alt = r->objects.alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
if (!lstat(*path, st))
return 0;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 25/44] sha1_file: add repository argument to map_sha1_file

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow map_sha1_file callers to be more
specific about which repository to handle. This is a small mechanical
change; it doesn't change the implementation to handle repositories
other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

While at it, move the declaration to object-store.h, where it should
be easier to find.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 cache.h| 1 -
 object-store.h | 3 +++
 sha1_file.c| 4 ++--
 streaming.c| 5 -
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index cbec0ecd23..720664e394 100644
--- a/cache.h
+++ b/cache.h
@@ -1242,7 +1242,6 @@ extern int pretend_sha1_file(void *, unsigned long, enum 
object_type, unsigned c
 extern int force_object_loose(const unsigned char *sha1, time_t mtime);
 extern int git_open_cloexec(const char *name, int flags);
 #define git_open(name) git_open_cloexec(name, O_RDONLY)
-extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
 extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, 
unsigned long mapsize, void *buffer, unsigned long bufsiz);
 extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
 
diff --git a/object-store.h b/object-store.h
index f09acfbf5b..ad4c7501d7 100644
--- a/object-store.h
+++ b/object-store.h
@@ -122,4 +122,7 @@ void raw_object_store_clear(struct raw_object_store *o);
 #define sha1_file_name(r, b, s) sha1_file_name_##r(b, s)
 void sha1_file_name_the_repository(struct strbuf *buf, const unsigned char 
*sha1);
 
+#define map_sha1_file(r, s, sz) map_sha1_file_##r(s, sz)
+void *map_sha1_file_the_repository(const unsigned char *sha1, unsigned long 
*size);
+
 #endif /* OBJECT_STORE_H */
diff --git a/sha1_file.c b/sha1_file.c
index 78d5ffe876..536c45589b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -961,7 +961,7 @@ static void *map_sha1_file_1_the_repository(const char 
*path,
return map;
 }
 
-void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
+void *map_sha1_file_the_repository(const unsigned char *sha1, unsigned long 
*size)
 {
return map_sha1_file_1(the_repository, NULL, sha1, size);
 }
@@ -1185,7 +1185,7 @@ static int sha1_loose_object_info(const unsigned char 
*sha1,
return 0;
}
 
-   map = map_sha1_file(sha1, );
+   map = map_sha1_file(the_repository, sha1, );
if (!map)
return -1;
 
diff --git a/streaming.c b/streaming.c
index 5892b50bd8..22d27df55e 100644
--- a/streaming.c
+++ b/streaming.c
@@ -3,6 +3,8 @@
  */
 #include "cache.h"
 #include "streaming.h"
+#include "repository.h"
+#include "object-store.h"
 #include "packfile.h"
 
 enum input_source {
@@ -335,7 +337,8 @@ static struct stream_vtbl loose_vtbl = {
 
 static open_method_decl(loose)
 {
-   st->u.loose.mapped = map_sha1_file(sha1, >u.loose.mapsize);
+   st->u.loose.mapped = map_sha1_file(the_repository,
+  sha1, >u.loose.mapsize);
if (!st->u.loose.mapped)
return -1;
if ((unpack_sha1_header(>z,
-- 
2.16.1.435.g8f24da2e1a



[PATCH 26/44] sha1_file: add repository argument to sha1_loose_object_info

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow the sha1_loose_object_info caller
to be more specific about which repository to act on. This is a small
mechanical change; it doesn't change the implementation to handle
repositories other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 536c45589b..ecbf846f12 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1152,9 +1152,10 @@ int parse_sha1_header(const char *hdr, unsigned long 
*sizep)
return parse_sha1_header_extended(hdr, , 0);
 }
 
-static int sha1_loose_object_info(const unsigned char *sha1,
- struct object_info *oi,
- int flags)
+#define sha1_loose_object_info(r, s, o, f) sha1_loose_object_info_##r(s, o, f)
+static int sha1_loose_object_info_the_repository(const unsigned char *sha1,
+struct object_info *oi,
+int flags)
 {
int status = 0;
unsigned long mapsize;
@@ -1273,7 +1274,7 @@ int sha1_object_info_extended(const unsigned char *sha1, 
struct object_info *oi,
break;
 
/* Most likely it's a loose object. */
-   if (!sha1_loose_object_info(real, oi, flags))
+   if (!sha1_loose_object_info(the_repository, real, oi, flags))
return 0;
 
/* Not a loose object; someone else may have just packed it. */
-- 
2.16.1.435.g8f24da2e1a



[PATCH 21/44] sha1_file: add repository argument to sha1_file_name

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow sha1_file_name callers to be more
specific about which repository to handle. This is a small mechanical
change; it doesn't change the implementation to handle repositories
other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

While at it, move the declaration to object-store.h, where it should
be easier to find.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 cache.h|  6 --
 http-walker.c  |  3 ++-
 http.c |  5 ++---
 object-store.h |  7 +++
 sha1_file.c| 10 +-
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/cache.h b/cache.h
index d3429a0d48..cbec0ecd23 100644
--- a/cache.h
+++ b/cache.h
@@ -961,12 +961,6 @@ extern void check_repository_format(void);
 #define DATA_CHANGED0x0020
 #define TYPE_CHANGED0x0040
 
-/*
- * Put in `buf` the name of the file in the local object database that
- * would be used to store a loose object with the specified sha1.
- */
-extern void sha1_file_name(struct strbuf *buf, const unsigned char *sha1);
-
 /*
  * Return an abbreviated sha1 unique within this repository's object database.
  * The result will be at least `len` characters long, and will be NUL
diff --git a/http-walker.c b/http-walker.c
index 07c2b1af82..2c33969123 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "repository.h"
 #include "commit.h"
 #include "walker.h"
 #include "http.h"
@@ -545,7 +546,7 @@ static int fetch_object(struct walker *walker, unsigned 
char *sha1)
ret = error("File %s has bad hash", hex);
} else if (req->rename < 0) {
struct strbuf buf = STRBUF_INIT;
-   sha1_file_name(, req->sha1);
+   sha1_file_name(the_repository, , req->sha1);
ret = error("unable to write sha1 filename %s", buf.buf);
strbuf_release();
}
diff --git a/http.c b/http.c
index 31755023a4..df9dbea59c 100644
--- a/http.c
+++ b/http.c
@@ -2246,7 +2246,7 @@ struct http_object_request *new_http_object_request(const 
char *base_url,
hashcpy(freq->sha1, sha1);
freq->localfile = -1;
 
-   sha1_file_name(, sha1);
+   sha1_file_name(the_repository, , sha1);
snprintf(freq->tmpfile, sizeof(freq->tmpfile),
 "%s.temp", filename.buf);
 
@@ -2395,8 +2395,7 @@ int finish_http_object_request(struct http_object_request 
*freq)
unlink_or_warn(freq->tmpfile);
return -1;
}
-
-   sha1_file_name(, freq->sha1);
+   sha1_file_name(the_repository, , freq->sha1);
freq->rename = finalize_object_file(freq->tmpfile, filename.buf);
strbuf_release();
 
diff --git a/object-store.h b/object-store.h
index 141455b5b2..f09acfbf5b 100644
--- a/object-store.h
+++ b/object-store.h
@@ -115,4 +115,11 @@ struct raw_object_store {
 void raw_object_store_init(struct raw_object_store *o);
 void raw_object_store_clear(struct raw_object_store *o);
 
+/*
+ * Put in `buf` the name of the file in the local object database that
+ * would be used to store a loose object with the specified sha1.
+ */
+#define sha1_file_name(r, b, s) sha1_file_name_##r(b, s)
+void sha1_file_name_the_repository(struct strbuf *buf, const unsigned char 
*sha1);
+
 #endif /* OBJECT_STORE_H */
diff --git a/sha1_file.c b/sha1_file.c
index a3e4ef4253..e06d62a451 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -323,7 +323,7 @@ static void fill_sha1_path(struct strbuf *buf, const 
unsigned char *sha1)
}
 }
 
-void sha1_file_name(struct strbuf *buf, const unsigned char *sha1)
+void sha1_file_name_the_repository(struct strbuf *buf, const unsigned char 
*sha1)
 {
strbuf_addstr(buf, get_object_directory());
strbuf_addch(buf, '/');
@@ -713,7 +713,7 @@ static int check_and_freshen_local(const unsigned char 
*sha1, int freshen)
static struct strbuf buf = STRBUF_INIT;
 
strbuf_reset();
-   sha1_file_name(, sha1);
+   sha1_file_name(the_repository, , sha1);
 
return check_and_freshen_file(buf.buf, freshen);
 }
@@ -874,7 +874,7 @@ static int stat_sha1_file(const unsigned char *sha1, struct 
stat *st,
static struct strbuf buf = STRBUF_INIT;
 
strbuf_reset();
-   sha1_file_name(, sha1);
+   sha1_file_name(the_repository, , sha1);
*path = buf.buf;
 
if (!lstat(*path, st))
@@ -903,7 +903,7 @@ static int open_sha1_file(const unsigned char *sha1, const 
char **path)
static struct strbuf buf = STRBUF_INIT;
 
strbuf_reset();
-   sha1_file_name(, sha1);
+   sha1_file_name(the_repository, , sha1);
*path = buf.buf;
 
fd = git_open(*path);
@@ 

[PATCH 14/44] sha1_file: add raw_object_store argument to alt_odb_usable

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a raw_object_store to alt_odb_usable to be more specific about which
repository to act on. The choice of the repository is delegated to its
only caller link_alt_odb_entry.

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 4c9635dada..77c099dadd 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -346,7 +346,9 @@ static const char *alt_sha1_path(struct 
alternate_object_database *alt,
 /*
  * Return non-zero iff the path is usable as an alternate object database.
  */
-static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
+static int alt_odb_usable(struct raw_object_store *o,
+ struct strbuf *path,
+ const char *normalized_objdir)
 {
struct alternate_object_database *alt;
 
@@ -362,7 +364,7 @@ static int alt_odb_usable(struct strbuf *path, const char 
*normalized_objdir)
 * Prevent the common mistake of listing the same
 * thing twice, or object directory itself.
 */
-   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
+   for (alt = o->alt_odb_list; alt; alt = alt->next) {
if (!fspathcmp(path->buf, alt->path))
return 0;
}
@@ -414,7 +416,7 @@ static int link_alt_odb_entry(const char *entry, const char 
*relative_base,
while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
strbuf_setlen(, pathbuf.len - 1);
 
-   if (!alt_odb_usable(, normalized_objdir)) {
+   if (!alt_odb_usable(_repository->objects, , 
normalized_objdir)) {
strbuf_release();
return -1;
}
-- 
2.16.1.435.g8f24da2e1a



[PATCH 23/44] sha1_file: add repository argument to open_sha1_file

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow the open_sha1_file caller to be
more specific about which repository to act on. This is a small
mechanical change; it doesn't change the implementation to handle
repositories other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 7b640cca28..d4298805e3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -896,7 +896,9 @@ static int stat_sha1_file_the_repository(const unsigned 
char *sha1,
  * Like stat_sha1_file(), but actually open the object and return the
  * descriptor. See the caveats on the "path" parameter above.
  */
-static int open_sha1_file(const unsigned char *sha1, const char **path)
+#define open_sha1_file(r, s, p) open_sha1_file_##r(s, p)
+static int open_sha1_file_the_repository(const unsigned char *sha1,
+const char **path)
 {
int fd;
struct alternate_object_database *alt;
@@ -939,7 +941,7 @@ static void *map_sha1_file_1(const char *path,
if (path)
fd = git_open(path);
else
-   fd = open_sha1_file(sha1, );
+   fd = open_sha1_file(the_repository, sha1, );
map = NULL;
if (fd >= 0) {
struct stat st;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 19/44] sha1_file: allow link_alt_odb_entries to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Actually this also allows read_info_alternates and link_alt_odb_entry to
handle arbitrary repositories, but link_alt_odb_entries is the most
interesting function in this set of functions, hence the commit subject.

These functions span a strongly connected component in the function
graph, i.e. the recursive call chain might look like

  -> link_alt_odb_entries
-> link_alt_odb_entry
  -> read_info_alternates
-> link_alt_odb_entries

That is why we need to convert all these functions at the same time.

Signed-off-by: Jonathan Nieder 
Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h |  4 
 sha1_file.c| 36 
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/object-store.h b/object-store.h
index 3d0f8a87cb..20ba136c1f 100644
--- a/object-store.h
+++ b/object-store.h
@@ -18,6 +18,10 @@ struct alternate_object_database {
char loose_objects_subdir_seen[256];
struct oid_array loose_objects_cache;
 
+   /*
+* Path to the alternative object store. If this is a relative path,
+* it is relative to the current working directory.
+*/
char path[FLEX_ARRAY];
 };
 #define prepare_alt_odb(r) prepare_alt_odb_##r()
diff --git a/sha1_file.c b/sha1_file.c
index 027e0f3741..f34eb69e39 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -390,11 +390,10 @@ static int alt_odb_usable(struct raw_object_store *o,
  * SHA1, an extra slash for the first level indirection, and the
  * terminating NUL.
  */
-#define read_info_alternates(r, rb, d) read_info_alternates_##r(rb, d)
-static void read_info_alternates_the_repository(const char *relative_base,
-   int depth);
-#define link_alt_odb_entry(r, e, rb, d, n) link_alt_odb_entry_##r(e, rb, d, n)
-static int link_alt_odb_entry_the_repository(const char *entry,
+static void read_info_alternates(struct repository *r,
+const char *relative_base,
+int depth);
+static int link_alt_odb_entry(struct repository *r, const char *entry,
const char *relative_base, int depth, const char *normalized_objdir)
 {
struct alternate_object_database *ent;
@@ -420,7 +419,7 @@ static int link_alt_odb_entry_the_repository(const char 
*entry,
while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
strbuf_setlen(, pathbuf.len - 1);
 
-   if (!alt_odb_usable(_repository->objects, , 
normalized_objdir)) {
+   if (!alt_odb_usable(>objects, , normalized_objdir)) {
strbuf_release();
return -1;
}
@@ -428,12 +427,12 @@ static int link_alt_odb_entry_the_repository(const char 
*entry,
ent = alloc_alt_odb(pathbuf.buf);
 
/* add the alternate entry */
-   *the_repository->objects.alt_odb_tail = ent;
-   the_repository->objects.alt_odb_tail = &(ent->next);
+   *r->objects.alt_odb_tail = ent;
+   r->objects.alt_odb_tail = &(ent->next);
ent->next = NULL;
 
/* recursively add alternates */
-   read_info_alternates(the_repository, pathbuf.buf, depth + 1);
+   read_info_alternates(r, pathbuf.buf, depth + 1);
 
strbuf_release();
return 0;
@@ -468,12 +467,8 @@ static const char *parse_alt_odb_entry(const char *string,
return end;
 }
 
-#define link_alt_odb_entries(r, a, s, rb, d) \
-   link_alt_odb_entries_##r(a, s, rb, d)
-static void link_alt_odb_entries_the_repository(const char *alt,
-   int sep,
-   const char *relative_base,
-   int depth)
+static void link_alt_odb_entries(struct repository *r, const char *alt,
+int sep, const char *relative_base, int depth)
 {
struct strbuf objdirbuf = STRBUF_INIT;
struct strbuf entry = STRBUF_INIT;
@@ -487,7 +482,7 @@ static void link_alt_odb_entries_the_repository(const char 
*alt,
return;
}
 
-   strbuf_add_absolute_path(, get_object_directory());
+   strbuf_add_absolute_path(, r->objects.objectdir);
if (strbuf_normalize_path() < 0)
die("unable to normalize object directory: %s",
objdirbuf.buf);
@@ -496,15 +491,16 @@ static void link_alt_odb_entries_the_repository(const 
char *alt,
alt = parse_alt_odb_entry(alt, sep, );
if (!entry.len)
continue;
-   link_alt_odb_entry(the_repository, entry.buf,
+   link_alt_odb_entry(r, entry.buf,
   relative_base, depth, objdirbuf.buf);
}
strbuf_release();
strbuf_release();
 }
 
-static 

[PATCH 15/44] sha1_file: add repository argument to link_alt_odb_entry

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow the link_alt_odb_entry caller to be
more specific about which repository to act on. This is a small
mechanical change; it doesn't change the implementation to handle
repositories other than the_repository yet.

Since the implementation does not yet work with other repositories,
use a wrapper macro to enforce that the caller passes in
the_repository as the first argument. It would be more appealing to
use BUILD_ASSERT_OR_ZERO to enforce this, but that doesn't work
because it requires a compile-time constant and common compilers like
gcc 4.8.4 do not consider "r == the_repository" a compile-time
constant.

This and the following three patches add repository arguments to
link_alt_odb_entry, read_info_alternates, link_alt_odb_entries
and prepare_alt_odb. Three out of the four functions are found
in a recursive call chain, calling each other, and one of them
accesses the repositories `objectdir` (which was migrated; it
was an obvious choice) and `ignore_env` (which we need to keep in
the repository struct for clarify); hence we will pass through the
repository unlike just the object store object + the ignore_env flag.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 77c099dadd..2ee5fe6ba3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -390,8 +390,9 @@ static int alt_odb_usable(struct raw_object_store *o,
  * terminating NUL.
  */
 static void read_info_alternates(const char * relative_base, int depth);
-static int link_alt_odb_entry(const char *entry, const char *relative_base,
-   int depth, const char *normalized_objdir)
+#define link_alt_odb_entry(r, e, rb, d, n) link_alt_odb_entry_##r(e, rb, d, n)
+static int link_alt_odb_entry_the_repository(const char *entry,
+   const char *relative_base, int depth, const char *normalized_objdir)
 {
struct alternate_object_database *ent;
struct strbuf pathbuf = STRBUF_INIT;
@@ -488,7 +489,8 @@ static void link_alt_odb_entries(const char *alt, int sep,
alt = parse_alt_odb_entry(alt, sep, );
if (!entry.len)
continue;
-   link_alt_odb_entry(entry.buf, relative_base, depth, 
objdirbuf.buf);
+   link_alt_odb_entry(the_repository, entry.buf,
+  relative_base, depth, objdirbuf.buf);
}
strbuf_release();
strbuf_release();
-- 
2.16.1.435.g8f24da2e1a



[PATCH 18/44] sha1_file: add repository argument to prepare_alt_odb

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

See previous patch for explanation.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/fsck.c |  2 +-
 object-store.h |  3 ++-
 packfile.c |  2 +-
 sha1_file.c| 13 +++--
 sha1_name.c|  2 +-
 5 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/builtin/fsck.c b/builtin/fsck.c
index 7aca9699f6..b0abba6e04 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -716,7 +716,7 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
} else {
fsck_object_dir(get_object_directory());
 
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list;
 alt; alt = alt->next)
fsck_object_dir(alt->path);
diff --git a/object-store.h b/object-store.h
index 56ed4bd9e9..3d0f8a87cb 100644
--- a/object-store.h
+++ b/object-store.h
@@ -20,7 +20,8 @@ struct alternate_object_database {
 
char path[FLEX_ARRAY];
 };
-void prepare_alt_odb(void);
+#define prepare_alt_odb(r) prepare_alt_odb_##r()
+void prepare_alt_odb_the_repository(void);
 char *compute_alternate_path(const char *path, struct strbuf *err);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 int foreach_alt_odb(alt_odb_fn, void*);
diff --git a/packfile.c b/packfile.c
index ce4cd7d5c9..a0842521e5 100644
--- a/packfile.c
+++ b/packfile.c
@@ -889,7 +889,7 @@ void prepare_packed_git(void)
if (the_repository->objects.packed_git_initialized)
return;
prepare_packed_git_one(get_object_directory(), 1);
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
prepare_packed_git_one(alt->path, 0);
rearrange_packed_git();
diff --git a/sha1_file.c b/sha1_file.c
index 4f9c07b547..027e0f3741 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -23,6 +23,7 @@
 #include "sha1-lookup.h"
 #include "bulk-checkin.h"
 #include "repository.h"
+#include "object-store.h"
 #include "streaming.h"
 #include "dir.h"
 #include "list.h"
@@ -581,7 +582,7 @@ void add_to_alternates_memory(const char *reference)
 * Make sure alternates are initialized, or else our entry may be
 * overwritten when they are.
 */
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
 
link_alt_odb_entries(the_repository, reference,
 '\n', NULL, 0);
@@ -667,7 +668,7 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
struct alternate_object_database *ent;
int r = 0;
 
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
for (ent = the_repository->objects.alt_odb_list; ent; ent = ent->next) {
r = fn(ent, cb);
if (r)
@@ -676,7 +677,7 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
return r;
 }
 
-void prepare_alt_odb(void)
+void prepare_alt_odb_the_repository(void)
 {
if (the_repository->objects.alt_odb_tail)
return;
@@ -726,7 +727,7 @@ static int check_and_freshen_local(const unsigned char 
*sha1, int freshen)
 static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)
 {
struct alternate_object_database *alt;
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
const char *path = alt_sha1_path(alt, sha1);
if (check_and_freshen_file(path, freshen))
@@ -885,7 +886,7 @@ static int stat_sha1_file(const unsigned char *sha1, struct 
stat *st,
if (!lstat(*path, st))
return 0;
 
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
errno = ENOENT;
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
@@ -916,7 +917,7 @@ static int open_sha1_file(const unsigned char *sha1, const 
char **path)
return fd;
most_interesting_errno = errno;
 
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
*path = alt_sha1_path(alt, sha1);
fd = git_open(*path);
diff --git a/sha1_name.c b/sha1_name.c
index bd4d7352ce..2065be90d2 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -353,7 +353,7 @@ static int init_object_disambiguation(const char *name, int 
len,
 
ds->len = len;
ds->hex_pfx[len] = '\0';
-   prepare_alt_odb();
+   prepare_alt_odb(the_repository);
return 0;
 }
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 17/44] sha1_file: add repository argument to link_alt_odb_entries

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

See previous patch for explanation.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 175ea58686..4f9c07b547 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -467,8 +467,12 @@ static const char *parse_alt_odb_entry(const char *string,
return end;
 }
 
-static void link_alt_odb_entries(const char *alt, int sep,
-const char *relative_base, int depth)
+#define link_alt_odb_entries(r, a, s, rb, d) \
+   link_alt_odb_entries_##r(a, s, rb, d)
+static void link_alt_odb_entries_the_repository(const char *alt,
+   int sep,
+   const char *relative_base,
+   int depth)
 {
struct strbuf objdirbuf = STRBUF_INIT;
struct strbuf entry = STRBUF_INIT;
@@ -511,7 +515,7 @@ static void read_info_alternates_the_repository(const char 
*relative_base,
return;
}
 
-   link_alt_odb_entries(buf.buf, '\n', relative_base, depth);
+   link_alt_odb_entries(the_repository, buf.buf, '\n', relative_base, 
depth);
strbuf_release();
free(path);
 }
@@ -565,7 +569,8 @@ void add_to_alternates_file(const char *reference)
if (commit_lock_file())
die_errno("unable to move new alternates file into 
place");
if (the_repository->objects.alt_odb_tail)
-   link_alt_odb_entries(reference, '\n', NULL, 0);
+   link_alt_odb_entries(the_repository, reference,
+'\n', NULL, 0);
}
free(alts);
 }
@@ -578,7 +583,8 @@ void add_to_alternates_memory(const char *reference)
 */
prepare_alt_odb();
 
-   link_alt_odb_entries(reference, '\n', NULL, 0);
+   link_alt_odb_entries(the_repository, reference,
+'\n', NULL, 0);
 }
 
 /*
@@ -677,7 +683,7 @@ void prepare_alt_odb(void)
 
the_repository->objects.alt_odb_tail =
_repository->objects.alt_odb_list;
-   link_alt_odb_entries(the_repository->objects.alternate_db,
+   link_alt_odb_entries(the_repository, 
the_repository->objects.alternate_db,
 PATH_SEP, NULL, 0);
 
read_info_alternates(the_repository, get_object_directory(), 0);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 22/44] sha1_file: add repository argument to stat_sha1_file

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow the stat_sha1_file caller to be
more specific about which repository to act on. This is a small
mechanical change; it doesn't change the implementation to handle
repositories other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index e06d62a451..7b640cca28 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -867,8 +867,9 @@ int git_open_cloexec(const char *name, int flags)
  * Note that it may point to static storage and is only valid until another
  * call to sha1_file_name(), etc.
  */
-static int stat_sha1_file(const unsigned char *sha1, struct stat *st,
- const char **path)
+#define stat_sha1_file(r, s, st, p) stat_sha1_file_##r(s, st, p)
+static int stat_sha1_file_the_repository(const unsigned char *sha1,
+struct stat *st, const char **path)
 {
struct alternate_object_database *alt;
static struct strbuf buf = STRBUF_INIT;
@@ -1174,7 +1175,7 @@ static int sha1_loose_object_info(const unsigned char 
*sha1,
if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
const char *path;
struct stat st;
-   if (stat_sha1_file(sha1, , ) < 0)
+   if (stat_sha1_file(the_repository, sha1, , ) < 0)
return -1;
if (oi->disk_sizep)
*oi->disk_sizep = st.st_size;
@@ -1388,7 +1389,7 @@ void *read_sha1_file_extended(const unsigned char *sha1,
die("replacement %s not found for %s",
sha1_to_hex(repl), sha1_to_hex(sha1));
 
-   if (!stat_sha1_file(repl, , ))
+   if (!stat_sha1_file(the_repository, repl, , ))
die("loose object %s (stored in %s) is corrupt",
sha1_to_hex(repl), path);
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 16/44] sha1_file: add repository argument to read_info_alternates

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

See previous patch for explanation.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 2ee5fe6ba3..175ea58686 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -389,7 +389,9 @@ static int alt_odb_usable(struct raw_object_store *o,
  * SHA1, an extra slash for the first level indirection, and the
  * terminating NUL.
  */
-static void read_info_alternates(const char * relative_base, int depth);
+#define read_info_alternates(r, rb, d) read_info_alternates_##r(rb, d)
+static void read_info_alternates_the_repository(const char *relative_base,
+   int depth);
 #define link_alt_odb_entry(r, e, rb, d, n) link_alt_odb_entry_##r(e, rb, d, n)
 static int link_alt_odb_entry_the_repository(const char *entry,
const char *relative_base, int depth, const char *normalized_objdir)
@@ -430,7 +432,7 @@ static int link_alt_odb_entry_the_repository(const char 
*entry,
ent->next = NULL;
 
/* recursively add alternates */
-   read_info_alternates(pathbuf.buf, depth + 1);
+   read_info_alternates(the_repository, pathbuf.buf, depth + 1);
 
strbuf_release();
return 0;
@@ -496,7 +498,8 @@ static void link_alt_odb_entries(const char *alt, int sep,
strbuf_release();
 }
 
-static void read_info_alternates(const char * relative_base, int depth)
+static void read_info_alternates_the_repository(const char *relative_base,
+   int depth)
 {
char *path;
struct strbuf buf = STRBUF_INIT;
@@ -677,7 +680,7 @@ void prepare_alt_odb(void)
link_alt_odb_entries(the_repository->objects.alternate_db,
 PATH_SEP, NULL, 0);
 
-   read_info_alternates(get_object_directory(), 0);
+   read_info_alternates(the_repository, get_object_directory(), 0);
 }
 
 /* Returns 1 if we have successfully freshened the file, 0 otherwise. */
-- 
2.16.1.435.g8f24da2e1a



[PATCH 20/44] sha1_file: allow prepare_alt_odb to handle arbitrary repositories

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h |  3 +--
 sha1_file.c| 12 +---
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/object-store.h b/object-store.h
index 20ba136c1f..141455b5b2 100644
--- a/object-store.h
+++ b/object-store.h
@@ -24,8 +24,7 @@ struct alternate_object_database {
 */
char path[FLEX_ARRAY];
 };
-#define prepare_alt_odb(r) prepare_alt_odb_##r()
-void prepare_alt_odb_the_repository(void);
+void prepare_alt_odb(struct repository *r);
 char *compute_alternate_path(const char *path, struct strbuf *err);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 int foreach_alt_odb(alt_odb_fn, void*);
diff --git a/sha1_file.c b/sha1_file.c
index f34eb69e39..a3e4ef4253 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -673,17 +673,15 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
return r;
 }
 
-void prepare_alt_odb_the_repository(void)
+void prepare_alt_odb(struct repository *r)
 {
-   if (the_repository->objects.alt_odb_tail)
+   if (r->objects.alt_odb_tail)
return;
 
-   the_repository->objects.alt_odb_tail =
-   _repository->objects.alt_odb_list;
-   link_alt_odb_entries(the_repository, 
the_repository->objects.alternate_db,
-PATH_SEP, NULL, 0);
+   r->objects.alt_odb_tail = >objects.alt_odb_list;
+   link_alt_odb_entries(r, r->objects.alternate_db, PATH_SEP, NULL, 0);
 
-   read_info_alternates(the_repository, get_object_directory(), 0);
+   read_info_alternates(r, r->objects.objectdir, 0);
 }
 
 /* Returns 1 if we have successfully freshened the file, 0 otherwise. */
-- 
2.16.1.435.g8f24da2e1a



[PATCH 24/44] sha1_file: add repository argument to map_sha1_file_1

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Add a repository argument to allow the map_sha1_file_1 caller to be
more specific about which repository to act on. This is a small
mechanical change; it doesn't change the implementation to handle
repositories other than the_repository yet.

As with the previous commits, use a macro to catch callers passing a
repository other than the_repository at compile time.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 sha1_file.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index d4298805e3..78d5ffe876 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -931,9 +931,10 @@ static int open_sha1_file_the_repository(const unsigned 
char *sha1,
  * Map the loose object at "path" if it is not NULL, or the path found by
  * searching for a loose object named "sha1".
  */
-static void *map_sha1_file_1(const char *path,
-const unsigned char *sha1,
-unsigned long *size)
+#define map_sha1_file_1(r, p, s, si) map_sha1_file_1_##r(p, s, si)
+static void *map_sha1_file_1_the_repository(const char *path,
+   const unsigned char *sha1,
+   unsigned long *size)
 {
void *map;
int fd;
@@ -962,7 +963,7 @@ static void *map_sha1_file_1(const char *path,
 
 void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
 {
-   return map_sha1_file_1(NULL, sha1, size);
+   return map_sha1_file_1(the_repository, NULL, sha1, size);
 }
 
 static int unpack_sha1_short_header(git_zstream *stream,
@@ -2192,7 +2193,7 @@ int read_loose_object(const char *path,
 
*contents = NULL;
 
-   map = map_sha1_file_1(path, NULL, );
+   map = map_sha1_file_1(the_repository, path, NULL, );
if (!map) {
error_errno("unable to mmap %s", path);
goto out;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 05/44] repository: delete ignore_env member

2018-03-03 Thread Nguyễn Thái Ngọc Duy
This variable was added because the repo_set_gitdir() was created to
cover both submodule and main repos, but these two are initialized a
bit differently so ignore_env == 0 means main repo, while ignore_env
!= 0 is submodules.

Since the difference part (env variables) has been moved out of
repo_set_gitdir(), this function works the same way for both repo
types and ignore_env is not needed anymore.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 repository.c | 2 --
 repository.h | 9 -
 2 files changed, 11 deletions(-)

diff --git a/repository.c b/repository.c
index 04d85a2869..62f52f47fc 100644
--- a/repository.c
+++ b/repository.c
@@ -140,8 +140,6 @@ static int repo_init(struct repository *repo,
struct repository_format format;
memset(repo, 0, sizeof(*repo));
 
-   repo->ignore_env = 1;
-
if (repo_init_gitdir(repo, gitdir))
goto error;
 
diff --git a/repository.h b/repository.h
index 2bfbf762f3..e7127baffb 100644
--- a/repository.h
+++ b/repository.h
@@ -75,15 +75,6 @@ struct repository {
const struct git_hash_algo *hash_algo;
 
/* Configurations */
-   /*
-* Bit used during initialization to indicate if repository state (like
-* the location of the 'objectdir') should be read from the
-* environment.  By default this bit will be set at the begining of
-* 'repo_init()' so that all repositories will ignore the environment.
-* The exception to this is 'the_repository', which doesn't go through
-* the normal 'repo_init()' process.
-*/
-   unsigned ignore_env:1;
 
/* Indicate if a repository has a different 'commondir' from 'gitdir' */
unsigned different_commondir:1;
-- 
2.16.1.435.g8f24da2e1a



[PATCH 04/44] sha1_file.c: move delayed getenv(altdb) back to setup_git_env()

2018-03-03 Thread Nguyễn Thái Ngọc Duy
getenv() is supposed to work on the main repository only. This delayed
getenv() code in sha1_file.c makes it more difficult to convert
sha1_file.c to a generic object store that could be used by both
submodule and main repositories.

Move the getenv() back in setup_git_env() where other env vars are
also fetched.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 environment.c | 1 +
 repository.c  | 3 +++
 repository.h  | 4 
 sha1_file.c   | 6 +-
 4 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/environment.c b/environment.c
index da3f7daa09..a5eaa97fb1 100644
--- a/environment.c
+++ b/environment.c
@@ -174,6 +174,7 @@ void setup_git_env(const char *git_dir)
args.object_dir = getenv_safe(_free, DB_ENVIRONMENT);
args.graft_file = getenv_safe(_free, GRAFT_ENVIRONMENT);
args.index_file = getenv_safe(_free, INDEX_ENVIRONMENT);
+   args.alternate_db = getenv_safe(_free, ALTERNATE_DB_ENVIRONMENT);
repo_set_gitdir(the_repository, git_dir, );
argv_array_clear(_free);
 
diff --git a/repository.c b/repository.c
index e65f4138a7..04d85a2869 100644
--- a/repository.c
+++ b/repository.c
@@ -60,6 +60,8 @@ void repo_set_gitdir(struct repository *repo,
repo_set_commondir(repo, o->commondir);
expand_base_dir(>objectdir, o->object_dir,
repo->commondir, "objects");
+   free(repo->alternate_db);
+   repo->alternate_db = xstrdup_or_null(o->alternate_db);
expand_base_dir(>graft_file, o->graft_file,
repo->commondir, "info/grafts");
expand_base_dir(>index_file, o->index_file,
@@ -215,6 +217,7 @@ void repo_clear(struct repository *repo)
FREE_AND_NULL(repo->gitdir);
FREE_AND_NULL(repo->commondir);
FREE_AND_NULL(repo->objectdir);
+   FREE_AND_NULL(repo->alternate_db);
FREE_AND_NULL(repo->graft_file);
FREE_AND_NULL(repo->index_file);
FREE_AND_NULL(repo->worktree);
diff --git a/repository.h b/repository.h
index 84aeac2825..2bfbf762f3 100644
--- a/repository.h
+++ b/repository.h
@@ -26,6 +26,9 @@ struct repository {
 */
char *objectdir;
 
+   /* Path to extra alternate object database if not NULL */
+   char *alternate_db;
+
/*
 * Path to the repository's graft file.
 * Cannot be NULL after initialization.
@@ -93,6 +96,7 @@ struct set_gitdir_args {
const char *object_dir;
const char *graft_file;
const char *index_file;
+   const char *alternate_db;
 };
 
 extern void repo_set_gitdir(struct repository *repo,
diff --git a/sha1_file.c b/sha1_file.c
index 831d9e7343..4af422e3cf 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -667,15 +667,11 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
 
 void prepare_alt_odb(void)
 {
-   const char *alt;
-
if (alt_odb_tail)
return;
 
-   alt = getenv(ALTERNATE_DB_ENVIRONMENT);
-
alt_odb_tail = _odb_list;
-   link_alt_odb_entries(alt, PATH_SEP, NULL, 0);
+   link_alt_odb_entries(the_repository->alternate_db, PATH_SEP, NULL, 0);
 
read_info_alternates(get_object_directory(), 0);
 }
-- 
2.16.1.435.g8f24da2e1a



[PATCH 10/44] object-store: move packed_git and packed_git_mru to object store

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

In a process with multiple repositories open, packfile accessors
should be associated to a single repository and not shared globally.
Move packed_git and packed_git_mru into the_repository and adjust
callers to reflect this.

[nd: while at there, wrap access to these two fields in get_packed_git()
and get_packed_git_mru(). This allows us to lazily initialize these
fields without caller doing that explicitly]

Patch generated by

 1. Moving the struct packed_git declaration to object-store.h
and packed_git, packed_git_mru globals to struct object_store.

 2. Apply the following semantic patch to adjust callers:
@@ @@
- packed_git
+ the_repository->objects.packed_git

@@ @@
- packed_git_mru
+ the_repository->objects.packed_git_mru

 3. Applying line wrapping fixes from "make style" to break the
resulting long lines.

 4. Adding missing #includes of repository.h where needed.

 5. As the packfiles are now owned by an objectstore, which is ephemeral
unlike globals, we introduce memory leaks. So address them in
raw_object_store_clear(). Defer freeing packed_git to the next
patch due to the size of this patch.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/count-objects.c  |  5 ++--
 builtin/fsck.c   |  6 +++--
 builtin/gc.c |  3 ++-
 builtin/pack-objects.c   | 20 
 builtin/pack-redundant.c |  5 ++--
 cache.h  | 29 
 fast-import.c|  7 --
 http-backend.c   |  5 ++--
 object-store.h   | 28 +++
 object.c |  7 ++
 pack-bitmap.c|  3 ++-
 packfile.c   | 49 
 packfile.h   |  3 +++
 server-info.c|  5 ++--
 sha1_name.c  |  5 ++--
 15 files changed, 107 insertions(+), 73 deletions(-)

diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 33343818c8..5c7c3c6ae3 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -7,6 +7,7 @@
 #include "cache.h"
 #include "config.h"
 #include "dir.h"
+#include "repository.h"
 #include "builtin.h"
 #include "parse-options.h"
 #include "quote.h"
@@ -120,9 +121,9 @@ int cmd_count_objects(int argc, const char **argv, const 
char *prefix)
struct strbuf loose_buf = STRBUF_INIT;
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
-   if (!packed_git)
+   if (!get_packed_git(the_repository))
prepare_packed_git();
-   for (p = packed_git; p; p = p->next) {
+   for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
if (open_pack_index(p))
diff --git a/builtin/fsck.c b/builtin/fsck.c
index b284a3a74e..7aca9699f6 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -729,7 +729,8 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
prepare_packed_git();
 
if (show_progress) {
-   for (p = packed_git; p; p = p->next) {
+   for (p = get_packed_git(the_repository); p;
+p = p->next) {
if (open_pack_index(p))
continue;
total += p->num_objects;
@@ -737,7 +738,8 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
 
progress = start_progress(_("Checking 
objects"), total);
}
-   for (p = packed_git; p; p = p->next) {
+   for (p = get_packed_git(the_repository); p;
+p = p->next) {
/* verify gives error messages itself */
if (verify_pack(p, fsck_obj_buffer,
progress, count))
diff --git a/builtin/gc.c b/builtin/gc.c
index 77fa720bd0..dd30067ac1 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -11,6 +11,7 @@
  */
 
 #include "builtin.h"
+#include "repository.h"
 #include "config.h"
 #include "tempfile.h"
 #include "lockfile.h"
@@ -173,7 +174,7 @@ static int too_many_packs(void)
return 0;
 
prepare_packed_git();
-   for (cnt = 0, p = packed_git; p; p = p->next) {
+   for (cnt = 0, p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
if (p->pack_keep)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 83dcbc9773..0e5fde1d6b 

[PATCH 02/44] repository.c: move env-related setup code back to environment.c

2018-03-03 Thread Nguyễn Thái Ngọc Duy
It does not make sense that generic repository code contains handling
of environment variables, which are specific for the main repository
only. Refactor repo_set_gitdir() function to take $GIT_DIR and
optionally _all_ other customizable paths. These optional paths can be
NULL and will be calculated according to the default directory layout.

Note that some dead functions are left behind to reduce diff
noise. They will be deleted in the next patch.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 cache.h   |  2 +-
 environment.c | 30 +++---
 repository.c  | 58 +++
 repository.h  | 11 +-
 setup.c   |  3 +--
 5 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/cache.h b/cache.h
index 9cac7bb518..41ba67cc16 100644
--- a/cache.h
+++ b/cache.h
@@ -484,7 +484,7 @@ static inline enum object_type object_type(unsigned int 
mode)
  */
 extern const char * const local_repo_env[];
 
-extern void setup_git_env(void);
+extern void setup_git_env(const char *git_dir);
 
 /*
  * Returns true iff we have a configured git repository (either via
diff --git a/environment.c b/environment.c
index de8431e01e..da3f7daa09 100644
--- a/environment.c
+++ b/environment.c
@@ -13,6 +13,7 @@
 #include "refs.h"
 #include "fmt-merge-msg.h"
 #include "commit.h"
+#include "argv-array.h"
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
@@ -147,10 +148,34 @@ static char *expand_namespace(const char *raw_namespace)
return strbuf_detach(, NULL);
 }
 
-void setup_git_env(void)
+/*
+ * Wrapper of getenv() that returns a strdup value. This value is kept
+ * in argv to be freed later.
+ */
+static const char *getenv_safe(struct argv_array *argv, const char *name)
+{
+   const char *value = getenv(name);
+
+   if (!value)
+   return NULL;
+
+   argv_array_push(argv, value);
+   return argv->argv[argv->argc - 1];
+}
+
+void setup_git_env(const char *git_dir)
 {
const char *shallow_file;
const char *replace_ref_base;
+   struct set_gitdir_args args = { NULL };
+   struct argv_array to_free = ARGV_ARRAY_INIT;
+
+   args.commondir = getenv_safe(_free, GIT_COMMON_DIR_ENVIRONMENT);
+   args.object_dir = getenv_safe(_free, DB_ENVIRONMENT);
+   args.graft_file = getenv_safe(_free, GRAFT_ENVIRONMENT);
+   args.index_file = getenv_safe(_free, INDEX_ENVIRONMENT);
+   repo_set_gitdir(the_repository, git_dir, );
+   argv_array_clear(_free);
 
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
check_replace_refs = 0;
@@ -300,8 +325,7 @@ int set_git_dir(const char *path)
 {
if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
return error("Could not set GIT_DIR to '%s'", path);
-   repo_set_gitdir(the_repository, path);
-   setup_git_env();
+   setup_git_env(path);
return 0;
 }
 
diff --git a/repository.c b/repository.c
index 0eddf28fcd..bb53b54b6d 100644
--- a/repository.c
+++ b/repository.c
@@ -40,34 +40,55 @@ static int find_common_dir(struct strbuf *sb, const char 
*gitdir, int fromenv)
return get_common_dir_noenv(sb, gitdir);
 }
 
-static void repo_setup_env(struct repository *repo)
+static void expand_base_dir(char **out, const char *in,
+   const char *base_dir, const char *def_in)
+{
+   free(*out);
+   if (in)
+   *out = xstrdup(in);
+   else
+   *out = xstrfmt("%s/%s", base_dir, def_in);
+}
+
+static void repo_set_commondir(struct repository *repo,
+  const char *commondir)
 {
struct strbuf sb = STRBUF_INIT;
 
-   repo->different_commondir = find_common_dir(, repo->gitdir,
-   !repo->ignore_env);
free(repo->commondir);
+
+   if (commondir) {
+   repo->different_commondir = 1;
+   repo->commondir = xstrdup(commondir);
+   return;
+   }
+
+   repo->different_commondir = get_common_dir_noenv(, repo->gitdir);
repo->commondir = strbuf_detach(, NULL);
-   free(repo->objectdir);
-   repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir,
-   "objects", !repo->ignore_env);
-   free(repo->graft_file);
-   repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir,
-"info/grafts", !repo->ignore_env);
-   free(repo->index_file);
-   repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir,
-"index", !repo->ignore_env);
 }
 
-void repo_set_gitdir(struct repository *repo, const char *path)
+void repo_set_gitdir(struct repository *repo,
+const char *root,
+const struct set_gitdir_args *o)
 {
-   const char *gitfile = read_gitfile(path);
+   const char *gitfile = 

[PATCH 13/44] pack: move approximate object count to object store

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

The approximate_object_count() function maintains a rough count of
objects in a repository to estimate how long object name abbreviates
should be.  Object names are scoped to a repository and the
appropriate length may differ by repository, so the object count
should not be global.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h |  8 
 packfile.c | 11 +--
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/object-store.h b/object-store.h
index b954396615..56ed4bd9e9 100644
--- a/object-store.h
+++ b/object-store.h
@@ -93,6 +93,14 @@ struct raw_object_store {
struct alternate_object_database *alt_odb_list;
struct alternate_object_database **alt_odb_tail;
 
+   /*
+* A fast, rough count of the number of objects in the repository.
+* These two fields are not meant for direct access. Use
+* approximate_object_count() instead.
+*/
+   unsigned long approximate_object_count;
+   unsigned approximate_object_count_valid : 1;
+
/*
 * Whether packed_git has already been populated with this repository's
 * packs.
diff --git a/packfile.c b/packfile.c
index caeab0f68c..ce4cd7d5c9 100644
--- a/packfile.c
+++ b/packfile.c
@@ -802,8 +802,6 @@ static void prepare_packed_git_one(char *objdir, int local)
strbuf_release();
 }
 
-static int approximate_object_count_valid;
-
 /*
  * Give a fast, rough count of the number of objects in the repository. This
  * ignores loose objects completely. If you have a lot of them, then either
@@ -813,8 +811,8 @@ static int approximate_object_count_valid;
  */
 unsigned long approximate_object_count(void)
 {
-   static unsigned long count;
-   if (!approximate_object_count_valid) {
+   if (!the_repository->objects.approximate_object_count_valid) {
+   unsigned long count;
struct packed_git *p;
 
prepare_packed_git();
@@ -824,8 +822,9 @@ unsigned long approximate_object_count(void)
continue;
count += p->num_objects;
}
+   the_repository->objects.approximate_object_count = count;
}
-   return count;
+   return the_repository->objects.approximate_object_count;
 }
 
 static void *get_next_packed_git(const void *p)
@@ -900,7 +899,7 @@ void prepare_packed_git(void)
 
 void reprepare_packed_git(void)
 {
-   approximate_object_count_valid = 0;
+   the_repository->objects.approximate_object_count_valid = 0;
the_repository->objects.packed_git_initialized = 0;
prepare_packed_git();
 }
-- 
2.16.1.435.g8f24da2e1a



[PATCH 09/44] object-store: free alt_odb_list

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Free the memory and reset alt_odb_{list, tail} to NULL.

Signed-off-by: Stefan Beller 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/object.c b/object.c
index e91711dd56..a71ab34e69 100644
--- a/object.c
+++ b/object.c
@@ -450,8 +450,26 @@ void raw_object_store_init(struct raw_object_store *o)
 {
memset(o, 0, sizeof(*o));
 }
+
+static void free_alt_odb(struct alternate_object_database *alt)
+{
+   strbuf_release(>scratch);
+   oid_array_clear(>loose_objects_cache);
+}
+
+static void free_alt_odbs(struct raw_object_store *o)
+{
+   while (o->alt_odb_list) {
+   free_alt_odb(o->alt_odb_list);
+   o->alt_odb_list = o->alt_odb_list->next;
+   }
+}
+
 void raw_object_store_clear(struct raw_object_store *o)
 {
FREE_AND_NULL(o->objectdir);
FREE_AND_NULL(o->alternate_db);
+
+   free_alt_odbs(o);
+   o->alt_odb_tail = NULL;
 }
-- 
2.16.1.435.g8f24da2e1a



[PATCH 12/44] pack: move prepare_packed_git_run_once to object store

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Each repository's object store can be initialized independently, so
they must not share a run_once variable.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 object-store.h | 6 ++
 packfile.c | 7 +++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/object-store.h b/object-store.h
index 1f3e66a3b8..b954396615 100644
--- a/object-store.h
+++ b/object-store.h
@@ -92,6 +92,12 @@ struct raw_object_store {
 
struct alternate_object_database *alt_odb_list;
struct alternate_object_database **alt_odb_tail;
+
+   /*
+* Whether packed_git has already been populated with this repository's
+* packs.
+*/
+   unsigned packed_git_initialized : 1;
 };
 
 void raw_object_store_init(struct raw_object_store *o);
diff --git a/packfile.c b/packfile.c
index 1e38334ba2..caeab0f68c 100644
--- a/packfile.c
+++ b/packfile.c
@@ -883,12 +883,11 @@ static void prepare_packed_git_mru(void)
list_add_tail(>mru, _repository->objects.packed_git_mru);
 }
 
-static int prepare_packed_git_run_once = 0;
 void prepare_packed_git(void)
 {
struct alternate_object_database *alt;
 
-   if (prepare_packed_git_run_once)
+   if (the_repository->objects.packed_git_initialized)
return;
prepare_packed_git_one(get_object_directory(), 1);
prepare_alt_odb();
@@ -896,13 +895,13 @@ void prepare_packed_git(void)
prepare_packed_git_one(alt->path, 0);
rearrange_packed_git();
prepare_packed_git_mru();
-   prepare_packed_git_run_once = 1;
+   the_repository->objects.packed_git_initialized = 1;
 }
 
 void reprepare_packed_git(void)
 {
approximate_object_count_valid = 0;
-   prepare_packed_git_run_once = 0;
+   the_repository->objects.packed_git_initialized = 0;
prepare_packed_git();
 }
 
-- 
2.16.1.435.g8f24da2e1a



[PATCH 11/44] object-store: close all packs upon clearing the object store

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/am.c   | 2 +-
 builtin/clone.c| 2 +-
 builtin/fetch.c| 2 +-
 builtin/merge.c| 2 +-
 builtin/receive-pack.c | 2 +-
 object.c   | 7 +++
 packfile.c | 4 ++--
 packfile.h | 2 +-
 8 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 5bdd2d7578..4762a702e3 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1859,7 +1859,7 @@ static void am_run(struct am_state *state, int resume)
 */
if (!state->rebasing) {
am_destroy(state);
-   close_all_packs();
+   close_all_packs(_repository->objects);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
 }
diff --git a/builtin/clone.c b/builtin/clone.c
index 101c27a593..13cfaa6488 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1217,7 +1217,7 @@ int cmd_clone(int argc, const char **argv, const char 
*prefix)
transport_disconnect(transport);
 
if (option_dissociate) {
-   close_all_packs();
+   close_all_packs(_repository->objects);
dissociate_from_references();
}
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8ee998ea2e..4d72efca78 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1478,7 +1478,7 @@ int cmd_fetch(int argc, const char **argv, const char 
*prefix)
 
string_list_clear(, 0);
 
-   close_all_packs();
+   close_all_packs(_repository->objects);
 
argv_array_pushl(_gc_auto, "gc", "--auto", NULL);
if (verbosity < 0)
diff --git a/builtin/merge.c b/builtin/merge.c
index 30264cfd7c..907ae44ab5 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -411,7 +411,7 @@ static void finish(struct commit *head_commit,
 * We ignore errors in 'gc --auto', since the
 * user should see them.
 */
-   close_all_packs();
+   close_all_packs(_repository->objects);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index b7ce7c7f52..ac478b7b99 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2026,7 +2026,7 @@ int cmd_receive_pack(int argc, const char **argv, const 
char *prefix)
proc.git_cmd = 1;
proc.argv = argv_gc_auto;
 
-   close_all_packs();
+   close_all_packs(_repository->objects);
if (!start_command()) {
if (use_sideband)
copy_to_sideband(proc.err, -1, NULL);
diff --git a/object.c b/object.c
index 83be6b1ecb..60ca76b285 100644
--- a/object.c
+++ b/object.c
@@ -4,6 +4,7 @@
 #include "tree.h"
 #include "commit.h"
 #include "tag.h"
+#include "packfile.h"
 
 static struct object **obj_hash;
 static int nr_objs, obj_hash_size;
@@ -475,8 +476,6 @@ void raw_object_store_clear(struct raw_object_store *o)
o->alt_odb_tail = NULL;
 
INIT_LIST_HEAD(>packed_git_mru);
-   /*
-* TODO: call close_all_packs once migrated to
-* take an object store argument
-*/
+   close_all_packs(o);
+   o->packed_git = NULL;
 }
diff --git a/packfile.c b/packfile.c
index d3c4a12ae0..1e38334ba2 100644
--- a/packfile.c
+++ b/packfile.c
@@ -310,11 +310,11 @@ static void close_pack(struct packed_git *p)
close_pack_index(p);
 }
 
-void close_all_packs(void)
+void close_all_packs(struct raw_object_store *o)
 {
struct packed_git *p;
 
-   for (p = the_repository->objects.packed_git; p; p = p->next)
+   for (p = o->packed_git; p; p = p->next)
if (p->do_not_close)
die("BUG: want to close pack marked 'do-not-close'");
else
diff --git a/packfile.h b/packfile.h
index 76496226bb..5b1ce00f84 100644
--- a/packfile.h
+++ b/packfile.h
@@ -66,7 +66,7 @@ extern void close_pack_index(struct packed_git *);
 
 extern unsigned char *use_pack(struct packed_git *, struct pack_window **, 
off_t, unsigned long *);
 extern void close_pack_windows(struct packed_git *);
-extern void close_all_packs(void);
+extern void close_all_packs(struct raw_object_store *o);
 extern void unuse_pack(struct pack_window **);
 extern void clear_delta_base_cache(void);
 extern struct packed_git *add_packed_git(const char *path, size_t path_len, 
int local);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 00/44] reroll nd/remove-ignore-env.. sb/object-store and sb/packfiles..

2018-03-03 Thread Nguyễn Thái Ngọc Duy
On Sat, Mar 3, 2018 at 9:54 AM, Duy Nguyen  wrote:
> On Thu, Mar 1, 2018 at 2:09 AM, Junio C Hamano  wrote:
>> Stefan Beller  writes:
>>
>>> On Wed, Feb 28, 2018 at 9:59 AM, Junio C Hamano  wrote:
 Duy Nguyen  writes:

> Looking at the full-series diff though, it makes me wonder if we
> should keep prepare_packed_git() private (i.e. how we initialize the
> object store, packfile included, is a private matter). How about
> something like this on top?

 Yup, that looks cleaner.
>>>
>>> I agree that it looks cleaner. So we plan on just putting
>>> it on top of that series?
>>
>> We tend to avoid "oops, that was wrong and here is a band aid on
>> top" for things that are still mushy, so it would be preferrable to
>> get it fixed inline, especially if there are more changes to the
>> other parts of the series coming.
>
> I agree with this. Stefan, if you're getting bored with rerolling
> refactor patches, I can update this series and send out v2.

Since Stefan is traveling, I take this opportunity to reroll it.
Unfortunately, I think the fix should go in 46cd557bd9 (object-store:
move packed_git and packed_git_mru to object store - 2018-02-23) where
we start removing the global "packed_git". But that's in
sb/object-store, so.. I'm rerolling all three

01/44 - 05/44: nd/remove-ignore-env-field

  This series is moved up top. After this the patch that touch
  alternate-db in sha1_file.c looks natural because no env is involved
  anymore

  I also take this opportunity to introduce a new patch 01/44 to avoid
  struct initialization that makes it hard to read and update. Later
  patches are also simplified thanks to this.

06/44 - 32/44: sb/object-store

  06/44 is updated to introduce raw_object_store_init() instead of
  RAW_OBJECT_STORE_INIT macro. This function is now used to initialize
  both main repo and submodule ones.

  10/44 (moving "packed_git") also introduces two new access wrapper
  get_packed_git() and get_packed_git_mru()

33/44 - 44/44: sb/packfiles-in-repository

  The only thing new here is 44/44 which makes prepare_packed_git()
  internal. get_packed_git() and get_packed_git_mru() introduced
  earlier will call prepare_packed_git() automatically.

The whole thing is also available at

https://github.com/pclouds/git/tree/ignore-env-object-store-packfiles

And interdiff of all three, compared to what is currently in 'pu'.
Looks pretty good in my opinon:

diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index d480301763..ee6ae35244 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -121,9 +121,8 @@ int cmd_count_objects(int argc, const char **argv, const 
char *prefix)
struct strbuf loose_buf = STRBUF_INIT;
struct strbuf pack_buf = STRBUF_INIT;
struct strbuf garbage_buf = STRBUF_INIT;
-   if (!the_repository->objects.packed_git)
-   prepare_packed_git(the_repository);
-   for (p = the_repository->objects.packed_git; p; p = p->next) {
+
+   for (p = get_packed_git(the_repository); p; p = p->next) {
if (!p->pack_local)
continue;
if (open_pack_index(p))
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 030c7fb7a0..9911c52bc8 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -726,10 +726,8 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
uint32_t total = 0, count = 0;
struct progress *progress = NULL;
 
-   prepare_packed_git(the_repository);
-
if (show_progress) {
-   for (p = the_repository->objects.packed_git; p;
+   for (p = get_packed_git(the_repository); p;
 p = p->next) {
if (open_pack_index(p))
continue;
@@ -738,7 +736,7 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
 
progress = start_progress(_("Checking 
objects"), total);
}
-   for (p = the_repository->objects.packed_git; p;
+   for (p = get_packed_git(the_repository); p;
 p = p->next) {
/* verify gives error messages itself */
if (verify_pack(p, fsck_obj_buffer,
diff --git a/builtin/gc.c b/builtin/gc.c
index 80d19c54d5..be63bec09c 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -173,8 +173,7 @@ static int too_many_packs(void)
if (gc_auto_pack_limit <= 0)
return 0;
 
-   prepare_packed_git(the_repository);
-   for (cnt = 0, p = the_repository->objects.packed_git; p; p = p->next) {

[PATCH 06/44] repository: introduce raw object store field

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

The raw object store field will contain any objects needed for
access to objects in a given repository.

This patch introduces the raw object store and populates it with the
`objectdir`, which used to be part of the repository struct.

As the struct gains members, we'll also populate the function to clear
the memory for these members.

In a later we'll introduce a struct object_parser, that will complement
the object parsing in a repository struct: The raw object parser is the
layer that will provide access to raw object content, while the higher
level object parser code will parse raw objects and keeps track of
parenthood and other object relationships using 'struct object'.
For now only add the lower level to the repository struct.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/grep.c |  2 +-
 environment.c  |  5 +++--
 object-store.h | 18 ++
 object.c   | 10 ++
 path.c |  2 +-
 repository.c   | 14 +-
 repository.h   | 10 --
 sha1_file.c|  3 ++-
 8 files changed, 48 insertions(+), 16 deletions(-)
 create mode 100644 object-store.h

diff --git a/builtin/grep.c b/builtin/grep.c
index 3ca4ac80d8..0f0c195705 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -432,7 +432,7 @@ static int grep_submodule(struct grep_opt *opt, struct 
repository *superproject,
 * object.
 */
grep_read_lock();
-   add_to_alternates_memory(submodule.objectdir);
+   add_to_alternates_memory(submodule.objects.objectdir);
grep_read_unlock();
 
if (oid) {
diff --git a/environment.c b/environment.c
index a5eaa97fb1..c05705e384 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@
 #include "fmt-merge-msg.h"
 #include "commit.h"
 #include "argv-array.h"
+#include "object-store.h"
 
 int trust_executable_bit = 1;
 int trust_ctime = 1;
@@ -270,9 +271,9 @@ const char *get_git_work_tree(void)
 
 char *get_object_directory(void)
 {
-   if (!the_repository->objectdir)
+   if (!the_repository->objects.objectdir)
BUG("git environment hasn't been setup");
-   return the_repository->objectdir;
+   return the_repository->objects.objectdir;
 }
 
 int odb_mkstemp(struct strbuf *template, const char *pattern)
diff --git a/object-store.h b/object-store.h
new file mode 100644
index 00..69bb5ac065
--- /dev/null
+++ b/object-store.h
@@ -0,0 +1,18 @@
+#ifndef OBJECT_STORE_H
+#define OBJECT_STORE_H
+
+struct raw_object_store {
+   /*
+* Path to the repository's object store.
+* Cannot be NULL after initialization.
+*/
+   char *objectdir;
+
+   /* Path to extra alternate object database if not NULL */
+   char *alternate_db;
+};
+
+void raw_object_store_init(struct raw_object_store *o);
+void raw_object_store_clear(struct raw_object_store *o);
+
+#endif /* OBJECT_STORE_H */
diff --git a/object.c b/object.c
index 9e6f9ff20b..e91711dd56 100644
--- a/object.c
+++ b/object.c
@@ -445,3 +445,13 @@ void clear_commit_marks_all(unsigned int flags)
obj->flags &= ~flags;
}
 }
+
+void raw_object_store_init(struct raw_object_store *o)
+{
+   memset(o, 0, sizeof(*o));
+}
+void raw_object_store_clear(struct raw_object_store *o)
+{
+   FREE_AND_NULL(o->objectdir);
+   FREE_AND_NULL(o->alternate_db);
+}
diff --git a/path.c b/path.c
index da8b655730..81a42d9115 100644
--- a/path.c
+++ b/path.c
@@ -382,7 +382,7 @@ static void adjust_git_path(const struct repository *repo,
strbuf_splice(buf, 0, buf->len,
  repo->index_file, strlen(repo->index_file));
else if (dir_prefix(base, "objects"))
-   replace_dir(buf, git_dir_len + 7, repo->objectdir);
+   replace_dir(buf, git_dir_len + 7, repo->objects.objectdir);
else if (git_hooks_path && dir_prefix(base, "hooks"))
replace_dir(buf, git_dir_len + 5, git_hooks_path);
else if (repo->different_commondir)
diff --git a/repository.c b/repository.c
index 62f52f47fc..34c0a7f180 100644
--- a/repository.c
+++ b/repository.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "repository.h"
+#include "object-store.h"
 #include "config.h"
 #include "submodule-config.h"
 
@@ -12,6 +13,7 @@ void initialize_the_repository(void)
the_repository = _repo;
 
the_repo.index = _index;
+   raw_object_store_init(_repo.objects);
repo_set_hash_algo(_repo, GIT_HASH_SHA1);
 }
 
@@ -58,10 +60,10 @@ void repo_set_gitdir(struct repository *repo,
free(old_gitdir);
 
repo_set_commondir(repo, o->commondir);
-   expand_base_dir(>objectdir, o->object_dir,
+   expand_base_dir(>objects.objectdir, o->object_dir,
repo->commondir, "objects");
-   free(repo->alternate_db);
-   

[PATCH 08/44] object-store: move alt_odb_list and alt_odb_tail to object store

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

In a process with multiple repositories open, alternates should be
associated to a single repository and not shared globally. Move
alt_odb_list and alt_odb_tail into the_repository and adjust callers
to reflect this.

Now that the alternative object data base is per repository, we're
leaking its memory upon freeing a repository. The next patch plugs
this hole.

No functional change intended.

Signed-off-by: Stefan Beller 
Signed-off-by: Jonathan Nieder 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/fsck.c |  4 +++-
 object-store.h |  7 +--
 packfile.c |  3 ++-
 sha1_file.c| 25 -
 sha1_name.c|  3 ++-
 5 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/builtin/fsck.c b/builtin/fsck.c
index 7a8a679d4f..b284a3a74e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "repository.h"
 #include "config.h"
 #include "commit.h"
 #include "tree.h"
@@ -716,7 +717,8 @@ int cmd_fsck(int argc, const char **argv, const char 
*prefix)
fsck_object_dir(get_object_directory());
 
prepare_alt_odb();
-   for (alt = alt_odb_list; alt; alt = alt->next)
+   for (alt = the_repository->objects.alt_odb_list;
+alt; alt = alt->next)
fsck_object_dir(alt->path);
 
if (check_full) {
diff --git a/object-store.h b/object-store.h
index 505f123976..0ca9233a85 100644
--- a/object-store.h
+++ b/object-store.h
@@ -1,7 +1,7 @@
 #ifndef OBJECT_STORE_H
 #define OBJECT_STORE_H
 
-extern struct alternate_object_database {
+struct alternate_object_database {
struct alternate_object_database *next;
 
/* see alt_scratch_buf() */
@@ -19,7 +19,7 @@ extern struct alternate_object_database {
struct oid_array loose_objects_cache;
 
char path[FLEX_ARRAY];
-} *alt_odb_list;
+};
 void prepare_alt_odb(void);
 char *compute_alternate_path(const char *path, struct strbuf *err);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
@@ -61,6 +61,9 @@ struct raw_object_store {
 
/* Path to extra alternate object database if not NULL */
char *alternate_db;
+
+   struct alternate_object_database *alt_odb_list;
+   struct alternate_object_database **alt_odb_tail;
 };
 
 void raw_object_store_init(struct raw_object_store *o);
diff --git a/packfile.c b/packfile.c
index 7dbe8739d1..216ea836ee 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "list.h"
 #include "pack.h"
+#include "repository.h"
 #include "dir.h"
 #include "mergesort.h"
 #include "packfile.h"
@@ -891,7 +892,7 @@ void prepare_packed_git(void)
return;
prepare_packed_git_one(get_object_directory(), 1);
prepare_alt_odb();
-   for (alt = alt_odb_list; alt; alt = alt->next)
+   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next)
prepare_packed_git_one(alt->path, 0);
rearrange_packed_git();
prepare_packed_git_mru();
diff --git a/sha1_file.c b/sha1_file.c
index 792bb21c15..4c9635dada 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -22,6 +22,7 @@
 #include "pack-revindex.h"
 #include "sha1-lookup.h"
 #include "bulk-checkin.h"
+#include "repository.h"
 #include "streaming.h"
 #include "dir.h"
 #include "list.h"
@@ -342,9 +343,6 @@ static const char *alt_sha1_path(struct 
alternate_object_database *alt,
return buf->buf;
 }
 
-struct alternate_object_database *alt_odb_list;
-static struct alternate_object_database **alt_odb_tail;
-
 /*
  * Return non-zero iff the path is usable as an alternate object database.
  */
@@ -364,7 +362,7 @@ static int alt_odb_usable(struct strbuf *path, const char 
*normalized_objdir)
 * Prevent the common mistake of listing the same
 * thing twice, or object directory itself.
 */
-   for (alt = alt_odb_list; alt; alt = alt->next) {
+   for (alt = the_repository->objects.alt_odb_list; alt; alt = alt->next) {
if (!fspathcmp(path->buf, alt->path))
return 0;
}
@@ -424,8 +422,8 @@ static int link_alt_odb_entry(const char *entry, const char 
*relative_base,
ent = alloc_alt_odb(pathbuf.buf);
 
/* add the alternate entry */
-   *alt_odb_tail = ent;
-   alt_odb_tail = &(ent->next);
+   *the_repository->objects.alt_odb_tail = ent;
+   the_repository->objects.alt_odb_tail = &(ent->next);
ent->next = NULL;
 
/* recursively add alternates */
@@ -559,7 +557,7 @@ void add_to_alternates_file(const char *reference)
fprintf_or_die(out, "%s\n", reference);
if (commit_lock_file())
die_errno("unable to move new alternates file into 
place");
-   if (alt_odb_tail)
+   if 

[PATCH 07/44] object-store: migrate alternates struct and functions from cache.h

2018-03-03 Thread Nguyễn Thái Ngọc Duy
From: Stefan Beller 

Migrate the struct alternate_object_database and all its related
functions to the object store as these functions are easier found in
that header. The migration is just a verbatim copy, no need to
include the object store header at any C file, because cache.h includes
repository.h which in turn includes the object-store.h

Signed-off-by: Stefan Beller 
Signed-off-by: Junio C Hamano 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 cache.h| 51 --
 object-store.h | 51 ++
 2 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/cache.h b/cache.h
index 41ba67cc16..41530d5d16 100644
--- a/cache.h
+++ b/cache.h
@@ -1576,57 +1576,6 @@ extern int has_dirs_only_path(const char *name, int len, 
int prefix_len);
 extern void schedule_dir_for_removal(const char *name, int len);
 extern void remove_scheduled_dirs(void);
 
-extern struct alternate_object_database {
-   struct alternate_object_database *next;
-
-   /* see alt_scratch_buf() */
-   struct strbuf scratch;
-   size_t base_len;
-
-   /*
-* Used to store the results of readdir(3) calls when searching
-* for unique abbreviated hashes.  This cache is never
-* invalidated, thus it's racy and not necessarily accurate.
-* That's fine for its purpose; don't use it for tasks requiring
-* greater accuracy!
-*/
-   char loose_objects_subdir_seen[256];
-   struct oid_array loose_objects_cache;
-
-   char path[FLEX_ARRAY];
-} *alt_odb_list;
-extern void prepare_alt_odb(void);
-extern char *compute_alternate_path(const char *path, struct strbuf *err);
-typedef int alt_odb_fn(struct alternate_object_database *, void *);
-extern int foreach_alt_odb(alt_odb_fn, void*);
-
-/*
- * Allocate a "struct alternate_object_database" but do _not_ actually
- * add it to the list of alternates.
- */
-struct alternate_object_database *alloc_alt_odb(const char *dir);
-
-/*
- * Add the directory to the on-disk alternates file; the new entry will also
- * take effect in the current process.
- */
-extern void add_to_alternates_file(const char *dir);
-
-/*
- * Add the directory to the in-memory list of alternates (along with any
- * recursive alternates it points to), but do not modify the on-disk alternates
- * file.
- */
-extern void add_to_alternates_memory(const char *dir);
-
-/*
- * Returns a scratch strbuf pre-filled with the alternate object directory,
- * including a trailing slash, which can be used to access paths in the
- * alternate. Always use this over direct access to alt->scratch, as it
- * cleans up any previous use of the scratch buffer.
- */
-extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
-
 struct pack_window {
struct pack_window *next;
unsigned char *base;
diff --git a/object-store.h b/object-store.h
index 69bb5ac065..505f123976 100644
--- a/object-store.h
+++ b/object-store.h
@@ -1,6 +1,57 @@
 #ifndef OBJECT_STORE_H
 #define OBJECT_STORE_H
 
+extern struct alternate_object_database {
+   struct alternate_object_database *next;
+
+   /* see alt_scratch_buf() */
+   struct strbuf scratch;
+   size_t base_len;
+
+   /*
+* Used to store the results of readdir(3) calls when searching
+* for unique abbreviated hashes.  This cache is never
+* invalidated, thus it's racy and not necessarily accurate.
+* That's fine for its purpose; don't use it for tasks requiring
+* greater accuracy!
+*/
+   char loose_objects_subdir_seen[256];
+   struct oid_array loose_objects_cache;
+
+   char path[FLEX_ARRAY];
+} *alt_odb_list;
+void prepare_alt_odb(void);
+char *compute_alternate_path(const char *path, struct strbuf *err);
+typedef int alt_odb_fn(struct alternate_object_database *, void *);
+int foreach_alt_odb(alt_odb_fn, void*);
+
+/*
+ * Allocate a "struct alternate_object_database" but do _not_ actually
+ * add it to the list of alternates.
+ */
+struct alternate_object_database *alloc_alt_odb(const char *dir);
+
+/*
+ * Add the directory to the on-disk alternates file; the new entry will also
+ * take effect in the current process.
+ */
+void add_to_alternates_file(const char *dir);
+
+/*
+ * Add the directory to the in-memory list of alternates (along with any
+ * recursive alternates it points to), but do not modify the on-disk alternates
+ * file.
+ */
+void add_to_alternates_memory(const char *dir);
+
+/*
+ * Returns a scratch strbuf pre-filled with the alternate object directory,
+ * including a trailing slash, which can be used to access paths in the
+ * alternate. Always use this over direct access to alt->scratch, as it
+ * cleans up any previous use of the scratch buffer.
+ */
+struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
+
 struct 

[PATCH 01/44] repository: initialize the_repository in main()

2018-03-03 Thread Nguyễn Thái Ngọc Duy
This simplifies initialization of struct repository and anything
inside. Easier to read. Easier to add/remove fields.

Everything will go through main() common-main.c so this should cover all
programs, including t/helper.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 common-main.c |  2 ++
 repository.c  | 18 +-
 repository.h  |  2 +-
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/common-main.c b/common-main.c
index 6a689007e7..7d716d5a54 100644
--- a/common-main.c
+++ b/common-main.c
@@ -34,6 +34,8 @@ int main(int argc, const char **argv)
 
git_setup_gettext();
 
+   initialize_the_repository();
+
attr_start();
 
git_extract_argv0_path(argv[0]);
diff --git a/repository.c b/repository.c
index 4ffbe9bc94..0eddf28fcd 100644
--- a/repository.c
+++ b/repository.c
@@ -4,10 +4,16 @@
 #include "submodule-config.h"
 
 /* The main repository */
-static struct repository the_repo = {
-   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _index, 
_algos[GIT_HASH_SHA1], 0, 0
-};
-struct repository *the_repository = _repo;
+static struct repository the_repo;
+struct repository *the_repository;
+
+void initialize_the_repository(void)
+{
+   the_repository = _repo;
+
+   the_repo.index = _index;
+   repo_set_hash_algo(_repo, GIT_HASH_SHA1);
+}
 
 static char *git_path_from_env(const char *envvar, const char *git_dir,
   const char *path, int fromenv)
@@ -128,7 +134,9 @@ static int read_and_verify_repository_format(struct 
repository_format *format,
  * Initialize 'repo' based on the provided 'gitdir'.
  * Return 0 upon success and a non-zero value upon failure.
  */
-int repo_init(struct repository *repo, const char *gitdir, const char 
*worktree)
+static int repo_init(struct repository *repo,
+const char *gitdir,
+const char *worktree)
 {
struct repository_format format;
memset(repo, 0, sizeof(*repo));
diff --git a/repository.h b/repository.h
index 0329e40c7f..40c1c81bdc 100644
--- a/repository.h
+++ b/repository.h
@@ -91,7 +91,7 @@ extern struct repository *the_repository;
 extern void repo_set_gitdir(struct repository *repo, const char *path);
 extern void repo_set_worktree(struct repository *repo, const char *path);
 extern void repo_set_hash_algo(struct repository *repo, int algo);
-extern int repo_init(struct repository *repo, const char *gitdir, const char 
*worktree);
+extern void initialize_the_repository(void);
 extern int repo_submodule_init(struct repository *submodule,
   struct repository *superproject,
   const char *path);
-- 
2.16.1.435.g8f24da2e1a



[PATCH 03/44] repository.c: delete dead functions

2018-03-03 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
Signed-off-by: Junio C Hamano 
---
 repository.c | 25 -
 1 file changed, 25 deletions(-)

diff --git a/repository.c b/repository.c
index bb53b54b6d..e65f4138a7 100644
--- a/repository.c
+++ b/repository.c
@@ -15,31 +15,6 @@ void initialize_the_repository(void)
repo_set_hash_algo(_repo, GIT_HASH_SHA1);
 }
 
-static char *git_path_from_env(const char *envvar, const char *git_dir,
-  const char *path, int fromenv)
-{
-   if (fromenv) {
-   const char *value = getenv(envvar);
-   if (value)
-   return xstrdup(value);
-   }
-
-   return xstrfmt("%s/%s", git_dir, path);
-}
-
-static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
-{
-   if (fromenv) {
-   const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
-   if (value) {
-   strbuf_addstr(sb, value);
-   return 1;
-   }
-   }
-
-   return get_common_dir_noenv(sb, gitdir);
-}
-
 static void expand_base_dir(char **out, const char *in,
const char *base_dir, const char *def_in)
 {
-- 
2.16.1.435.g8f24da2e1a



Re: Contributor Summit planning

2018-03-03 Thread Jeff King
On Sat, Mar 03, 2018 at 05:30:10AM -0500, Jeff King wrote:

> As in past years, I plan to run it like an unconference. Attendees are
> expected to bring topics for group discussion. Short presentations are
> also welcome. We'll put the topics on a whiteboard in the morning, and
> pick whichever ones people are interested in.
> 
> Feel free to reply to this thread if you want to make plans or discuss
> any proposed topics before the summit. Input or questions from
> non-attendees is welcome here.

I'll plan to offer two topics:

 - a round-up of the current state and past year's activities of Git as
   a member project of Software Freedom Conservancy

 - some updates on the state of the git-scm.com since my report last
   year

As with last year, I'll try to send a written report to the list for
those who aren't at the summit in person.

-Peff


Contributor Summit planning

2018-03-03 Thread Jeff King
The Git Merge Contributor Summit is scheduled for this coming Wednesday,
March 7th, in Barcelona.

If you're not registered, there are still one or two slots left for
last-minute attendees. Please email me if you're interested.

As in past years, I plan to run it like an unconference. Attendees are
expected to bring topics for group discussion. Short presentations are
also welcome. We'll put the topics on a whiteboard in the morning, and
pick whichever ones people are interested in.

Feel free to reply to this thread if you want to make plans or discuss
any proposed topics before the summit. Input or questions from
non-attendees is welcome here.

The rest of this email is all logistics for attendees, so if you're not
coming, you can stop reading. :)

There should be breakfast available in the contributor summit room
starting at 9am, so plan to get there around then, mingle and eat, and
then we'll start in earnest at 10am.

Registration is at the main Git Merge event space (Convent dels Àngels
at MACBA), and then our contributor summit space is across the street.
So go to the main registration first, and then signs and clueful staff
should be able to point you to the contributor summit room.

We have the space until 5pm, so we'll go until then or until we run out
of stuff to say, whichever comes first. Lunch will be served in the
room, and we'll probably take a few informal breaks during the day.

After we finish for the day, there are a few other events. Bitbucket is
hosting drinks and discussion from 5:30-7:30pm, open to all Git Merge
attendees (not just contributor summit people). Details and RSVP at:

  
https://www.bevylabs.com/events/details/bevy-beers-with-bitbucket-presents-beers-with-bitbucket#/

Microsoft is sponsoring a dinner that evening at 8pm for just
contributor summit attendees. Details will be provided at the summit.

I look forward to seeing everybody there!

-Peff


Re: Worktree silently deleted on git fetch/gc/log

2018-03-03 Thread Eric Sunshine
On Fri, Mar 2, 2018 at 6:53 AM, Duy Nguyen  wrote:
> I'm going to improve it a bit in this case either way, I think I have
> some idea: (mostly to Eric) since worktree B is alive and kicking, it
> should keep at least HEAD or index updated often. We can delay
> deleting a worktree until both of these are past expire time.

Make sense.

> Also Eric (and this is getting off topic), I wonder if the decision to
> store absolute path in worktrees/../gitdir and .git files is a bad one
> (and is my bad).

Your original implementation of worktrees was able to recover
automatically when a worktree was moved (via 'mv', for instance). That
feature pretty much required recording an absolute path in the
worktree's .git file. When the automatic-recovery feature was dropped,
I suppose the need for absolute path in the .git file disappeared, as
well.

I can't presently think of a reason why gitdir needed/used an absolute
or normalized path. Was it because there was some need to compare such
paths?

> If we stored relative path in ".git" file at least, the worktree would
> immediately fail after the user moves either the linked checkout, or
> the main one. This should send a loud and clear signal to the user
> "something has gone horribly" and hopefully make them connect it to
> the last rename and undo that. "git gc" would have near zero chance to
> kick in and destroy stale worktrees.

It would detect if the main or linked worktree moved up or down one or
more directory levels or elsewhere.

It would not detect if the worktree directory was merely renamed.

Still, detecting some cases of breakage early may be better than not
detecting breakage at all.

Another idea may be to store the worktree's own normalized/absolute
path as a second line in its .git file. It could then immediately
detect any manual movement or renaming of itself. A minor concern,
though, is if there are any external tools reading that file directly
since they could be confused by the second line. Of course, such tools
hopefully would be using "git rev-parse --git-dir", so maybe it
wouldn't be a big deal. On the other hand, older versions of Git
itself would be confused by the second line, so perhaps the idea isn't
viable.

> Another bad thing about absolute paths, if you backup both main and
> linked worktrees in a tar file, restoring from the backup won't work
> unless you restore at the exact same place.
> Hmm?

Yep, that's an issue. An even simpler case is the somewhat common
usage pattern of creating worktrees within the main worktree (Dscho
has a number of times mentioned working like this, and I've done it
myself). In such a case, even just moving or renaming the main
worktree breaks the linked ones when absolute paths are in play.

So, yes, these issue argue for use of relative paths.


Re: [PATCH] smart-http: document flush after "# service" line

2018-03-03 Thread Jeff King
On Sat, Mar 03, 2018 at 03:28:47AM -0500, Eric Sunshine wrote:

> On Sat, Mar 3, 2018 at 12:27 AM, Jeff King  wrote:
> > Subject: smart-http: document flush after "# service" line
> >
> > The http-protocol.txt spec fails to mention that a flush
> > packet comes in the smart server response after sending any
> > the "service" header.
> 
> "any the"?

Oops, should just be "the".

-Peff


git stash push -u always warns "pathspec '...' did not match any files"

2018-03-03 Thread Marc Strapetz

Reproducible in a test repository with following steps:

$ touch untracked
$ git stash push -u -- untracked
Saved working directory and index state WIP on master: 0096475 init
fatal: pathspec 'untracked' did not match any files
error: unrecognized input

The file is stashed correctly, though.

Tested with Git 2.16.2 on Linux and Windows.

-Marc




Re: [PATCH 1/2] completion: don't set PARSE_OPT_NOCOMPLETE on --rerere-autoupdate

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 4:23 AM, Nguyễn Thái Ngọc Duy  wrote:
> There is not a strong reason to hide this option, and git-merge already
> completes this one. Let's allow to complete this for all commands (and
> let git-completion.bash do the suppressing if neede).

s/neede/needed/

> This makes --rerere-autoupdate completable for am, cherry-pick and
> revert.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy 


Re: [PATCH 3/3] worktree prune: improve prune logic when worktree is moved

2018-03-03 Thread Eric Sunshine
On Fri, Mar 2, 2018 at 10:39 PM, Nguyễn Thái Ngọc Duy  wrote:
> Worktree manual move support is actually gone in 618244e160 (worktree:
> stop supporting moving worktrees manually - 2016-01-22). Before that,
> this gitdir could be updated often when the worktree is accessed. That
> keeps the worktree from being pruned by this logic.

I had a bit of trouble digesting this paragraph. Possible rewrite:

Automatic detection of worktree relocation by a user (via 'mv',
for instance) was removed by 618244e160 (worktree: stop supporting
moving worktrees manually - 2016-01-22). Prior to that,
.git/worktrees//gitdir was updated whenever the worktree was
accessed in order to let the pruning logic know that the worktree
was "active" even if it disappeared for a while (due to being
located on removable media, for instance).

> "git worktree move" is coming so we don't really need this, but since
> it's easy to do, perhaps we could keep supporting manual worktree move a
> bit longer. Notice that when a worktree is active, the "index" file
> should be updated pretty often in common case. The logic is updated to
> check for index mtime to see if the worktree is alive.

Seems like a reasonable approximation of the pre-618244e160 way things worked.

> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> @@ -101,6 +101,9 @@ static int prune_worktree(const char *id, struct strbuf 
> *reason)
> if (!file_exists(path)) {
> free(path);
> if (st.st_mtime <= expire) {

This st.st_mtime is that of 'gitdir'...

> +   if (!stat(git_path("worktrees/%s/index", id), ) &&
> +   st.st_mtime > expire)

...and this st.st_mtime is of 'index'.

I wonder if it the 'gitdir' mtime check is really that useful anymore
considering that 'index' mtime will almost certainly be more recent.

> +   return 0;
> strbuf_addf(reason, _("Removing worktrees/%s: gitdir 
> file points to non-existent location"), id);
> return 1;


[PATCH 0/2] nd/parseopt-completion fixups

2018-03-03 Thread Nguyễn Thái Ngọc Duy
This addresses some comments from v3 [1]. Since the series has been
merged to 'next', we do incremental updates instead:

- --rerere-autoupdate is completable on am, revert and cherry-pick
- simplification in _git_notes which leads to completion in 'git notes
  remove'

[1] https://public-inbox.org/git/20180209110221.27224-1-pclo...@gmail.com/

Nguyễn Thái Ngọc Duy (2):
  completion: don't set PARSE_OPT_NOCOMPLETE on --rerere-autoupdate
  completion: simplify _git_notes

 contrib/completion/git-completion.bash | 18 +++---
 parse-options.h|  4 ++--
 rerere.h   |  3 +--
 3 files changed, 6 insertions(+), 19 deletions(-)

-- 
2.16.1.435.g8f24da2e1a



[PATCH 2/2] completion: simplify _git_notes

2018-03-03 Thread Nguyễn Thái Ngọc Duy
This also adds completion for 'git notes remove' with two options:
--ignore-missing and --stdin.

For some strange reason, 'git notes undefined --' completes --ref
without even running --git-completion-helper. But since this is an error
case (and we're not doing anything destructive, it's probably ok for now)

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 contrib/completion/git-completion.bash | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index c310b241d3..ab80f4e6e8 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1836,19 +1836,8 @@ _git_notes ()
add,--reedit-message=*|append,--reedit-message=*)
__git_complete_refs --cur="${cur#*=}"
;;
-   add,--*)
-   __gitcomp_builtin notes_add
-   ;;
-   append,--*)
-   __gitcomp_builtin notes_append
-   ;;
-   copy,--*)
-   __gitcomp_builtin notes_copy
-   ;;
-   prune,--*)
-   __gitcomp_builtin notes_prune
-   ;;
-   prune,*)
+   *,--*)
+   __gitcomp_builtin notes_$subcommand
;;
*)
case "$prev" in
-- 
2.16.1.435.g8f24da2e1a



[PATCH 1/2] completion: don't set PARSE_OPT_NOCOMPLETE on --rerere-autoupdate

2018-03-03 Thread Nguyễn Thái Ngọc Duy
There is not a strong reason to hide this option, and git-merge already
completes this one. Let's allow to complete this for all commands (and
let git-completion.bash do the suppressing if neede).

This makes --rerere-autoupdate completable for am, cherry-pick and
revert.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 contrib/completion/git-completion.bash | 3 +--
 parse-options.h| 4 ++--
 rerere.h   | 3 +--
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 0ddf40063b..c310b241d3 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1754,8 +1754,7 @@ _git_merge ()
 
case "$cur" in
--*)
-   __gitcomp_builtin merge "--rerere-autoupdate
-   --no-rerere-autoupdate
+   __gitcomp_builtin merge "--no-rerere-autoupdate
--no-commit --no-edit --no-ff
--no-log --no-progress
--no-squash --no-stat
diff --git a/parse-options.h b/parse-options.h
index 0ba08691e6..ab1cc362bf 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -148,8 +148,8 @@ struct option {
 #define OPT_STRING_LIST(s, l, v, a, h) \
{ OPTION_CALLBACK, (s), (l), (v), (a), \
  (h), 0, _opt_string_list }
-#define OPT_UYN(s, l, v, h, f)  { OPTION_CALLBACK, (s), (l), (v), NULL, \
- (h), PARSE_OPT_NOARG|(f), 
_opt_tertiary }
+#define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \
+ (h), PARSE_OPT_NOARG, _opt_tertiary 
}
 #define OPT_DATE(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0,\
  parse_opt_approxidate_cb }
diff --git a/rerere.h b/rerere.h
index 5e5a312e4c..c2961feaaa 100644
--- a/rerere.h
+++ b/rerere.h
@@ -37,7 +37,6 @@ extern void rerere_clear(struct string_list *);
 extern void rerere_gc(struct string_list *);
 
 #define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
-   N_("update the index with reused conflict resolution if possible"), \
-   PARSE_OPT_NOCOMPLETE)
+   N_("update the index with reused conflict resolution if possible"))
 
 #endif
-- 
2.16.1.435.g8f24da2e1a



Re: [PATCH 1/3] gc.txt: more details about what gc does

2018-03-03 Thread Eric Sunshine
On Fri, Mar 2, 2018 at 10:39 PM, Nguyễn Thái Ngọc Duy  wrote:
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
> diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
> @@ -15,8 +15,9 @@ DESCRIPTION
>  ---
>  Runs a number of housekeeping tasks within the current repository,
>  such as compressing file revisions (to reduce disk space and increase
> -performance) and removing unreachable objects which may have been
> -created from prior invocations of 'git add'.
> +performance), removing unreachable objects which may have been
> +created from prior invocations of 'git add', packing refs, pruning
> +reflog, rerere or stale working trees.

s/rerere/& metadata/

>  Users are encouraged to run this task on a regular basis within
>  each repository to maintain good disk space utilization and good
> @@ -59,6 +60,10 @@ then existing packs (except those marked with a `.keep` 
> file)
>  are consolidated into a single pack by using the `-A` option of
>  'git repack'. Setting `gc.autoPackLimit` to 0 disables
>  automatic consolidation of packs.
> ++
> +If `git gc --auto` goes ahead because of either too loose objects or
> +packs, all other housekeeping tasks (e.g. rerere, working trees,
> +reflog...) will also be be performed.

s/be be/be/

Perhaps this new paragraph should be moved up by one paragraph; the
result feels a bit more cohesive.

Minor rewrite:

If `git gc --auto` finds that housekeeping is required due to too
many loose objects or packs, all other housekeeping tasks (e.g.
rerere, working trees, reflog...) will be performed, as well.

> @@ -133,6 +138,9 @@ The optional configuration variable `gc.pruneExpire` 
> controls how old
>  the unreferenced loose objects have to be before they are pruned.  The
>  default is "2 weeks ago".
>
> +The optional gc.worktreePruneExpire controls how old a stale working
> +tree before `git worktree prune` deletes it. The default is "3 months
> +ago".
>
>  Notes
>  -

Missing backticks around "gc.worktreePruneExpire".

s/tree before/tree should be before/

You lost a blank line before the "Notes" section.

With minor fixes:

Optional configuration variable `gc.worktreePruneExpire` controls
how old a stale working tree should be before `git worktree prune`
deletes it. Default is "3 months ago".


Re: [PATCH] git.el: handle default excludesfile properly

2018-03-03 Thread Eric Sunshine
On Fri, Mar 2, 2018 at 10:48 PM, Dorab Patel  wrote:
> The previous version only looked at core.excludesfile for locating the
> excludesfile.  So, when core.excludesfile was not defined, it did not
> use the possible default locations.
>
> The current version uses either $XDG_CONFIG_HOME/git/ignore or
> $HOME/.config/git/ignore for the default excludesfile location
> depending on whether XDG_CONFIG_HOME is defined or not.  As per the
> documentation of gitignore.

Perhaps take $HOME/.gitignore into account too?

> Signed-off-by: Dorab Patel 


Re: [PATCH] smart-http: document flush after "# service" line

2018-03-03 Thread Eric Sunshine
On Sat, Mar 3, 2018 at 12:27 AM, Jeff King  wrote:
> Subject: smart-http: document flush after "# service" line
>
> The http-protocol.txt spec fails to mention that a flush
> packet comes in the smart server response after sending any
> the "service" header.

"any the"?

> Technically the client code is actually ready to receive an
> arbitrary number of headers here, but since we haven't
> introduced any other headers in the past decade (and the
> client would just throw them away), let's not mention it in
> the spec.
>
> This fixes both BNF and the example. While we're fixing the
> latter, let's also add the missing flush after the ref list.
>
> Reported-by: Dorian Taylor 
> Signed-off-by: Jeff King