]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Git.pm: fix bare repository search with Directory option
authorJeff King <peff@peff.net>
Thu, 12 Sep 2024 22:36:04 +0000 (18:36 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 13 Sep 2024 17:42:19 +0000 (10:42 -0700)
When opening a bare repository like:

  Git->repository(Directory => '/path/to/bare.git');

we will incorrectly point the repository object at the _current_
directory, not the one specified by the option.

The bug was introduced by 20da61f25f (Git.pm: trust rev-parse to find
bare repositories, 2022-10-22). Before then, we'd ask "rev-parse
--git-dir" if it was a Git repo, and if it returned anything, we'd
correctly convert that result to an absolute path using File::Spec and
Cwd::abs_path(). If it didn't, we'd guess it might be a bare repository
and find it ourselves, which was wrong (rev-parse should find even a
bare repo, and our search circumvented some of its rules).

That commit dropped most of the custom bare-repo search code in favor of
using "rev-parse --is-bare-repository" and trusting the "--git-dir" it
returned. But it mistakenly left some of the bare-repo code path in
place, which was now broken. That code calls Cwd::abs_path($dir); prior
to 20da61f25f $dir contained the "Directory" option the user passed in.
But afterwards, it contains the output of "rev-parse --git-dir". And
since our tentative rev-parse command is invoked after changing
directory, it will always be the relative path "."! So we'll end up with
the absolute path of the process's current directory, not the Directory
option the caller asked for.

So the non-bare case is correct, but the bare one is broken. Our tests
only check the non-bare one, so we didn't notice. We can fix this by
running the same absolute-path fixup code for both sides.

Helped-by: Rodrigo <rodrigolive@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
perl/Git.pm
t/t9700-perl-git.sh
t/t9700/test.pl

index 117765dc73c4a8c30bfbcf9b3b37bad6b26a9ede..f67ec766d22f95986a17f5f1ce2c0cd956f4cf58 100644 (file)
@@ -197,11 +197,11 @@ sub repository {
                my ($bare, $dir) = split /\n/, $out, 2;
 
                require Cwd;
-               if ($bare ne 'true') {
-                       require File::Spec;
-                       File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
-                       $opts{Repository} = Cwd::abs_path($dir);
+               require File::Spec;
+               File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
+               $opts{Repository} = Cwd::abs_path($dir);
 
+               if ($bare ne 'true') {
                        # If --git-dir went ok, this shouldn't die either.
                        my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
                        $dir = Cwd::abs_path($opts{Directory}) . '/';
@@ -214,8 +214,6 @@ sub repository {
                        $opts{WorkingCopy} = $dir;
                        $opts{WorkingSubdir} = $prefix;
 
-               } else {
-                       $opts{Repository} = Cwd::abs_path($dir);
                }
 
                delete $opts{Directory};
index ccc8212d732e22170ed74ada1510a72a71d7aaf7..44316971224bc4cd6d510cd2cc31bb934e799ea8 100755 (executable)
@@ -45,7 +45,8 @@ test_expect_success 'set up test repository' '
 '
 
 test_expect_success 'set up bare repository' '
-       git init --bare bare.git
+       git init --bare bare.git &&
+       git -C bare.git --work-tree=. commit --allow-empty -m "bare commit"
 '
 
 test_expect_success 'use t9700/test.pl to test Git.pm' '
index 6d753708d2acb6c7bcf47e5a057d99845c1006a3..72e958739e2a93667c973f4962c44835d977284a 100755 (executable)
@@ -147,6 +147,11 @@ close TEMPFILE3;
 unlink $tmpfile3;
 chdir($abs_repo_dir);
 
+# open alternate bare repo
+my $r4 = Git->repository(Directory => "$abs_repo_dir/bare.git");
+is($r4->command_oneline(qw(log --format=%s)), "bare commit",
+       "log of bare repo works");
+
 # unquoting paths
 is(Git::unquote_path('abc'), 'abc', 'unquote unquoted path');
 is(Git::unquote_path('"abc def"'), 'abc def', 'unquote simple quoted path');