about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/PublicInbox/Admin.pm25
-rw-r--r--t/admin.t12
2 files changed, 33 insertions, 4 deletions
diff --git a/lib/PublicInbox/Admin.pm b/lib/PublicInbox/Admin.pm
index 893f4a1b..cc9d2171 100644
--- a/lib/PublicInbox/Admin.pm
+++ b/lib/PublicInbox/Admin.pm
@@ -63,15 +63,32 @@ sub resolve_inboxdir {
         $dir;
 }
 
+sub valid_pwd {
+        my $pwd = $ENV{PWD} // return;
+        my @st_pwd = stat $pwd or return;
+        my @st_cwd = stat '.' or die "stat(.): $!";
+        "@st_pwd[1,0]" eq "@st_cwd[1,0]" ? $pwd : undef;
+}
+
 sub resolve_git_dir {
-        my ($cd) = @_;
+        my ($cd) = @_; # cd may be `undef' for cwd
         # try v1 bare git dirs
+        my $pwd = valid_pwd();
+        my $env;
+        defined($pwd) && substr($cd // '/', 0, 1) ne '/' and
+                $env->{PWD} = "$pwd/$cd";
         my $cmd = [ qw(git rev-parse --git-dir) ];
-        my $dir = run_qx($cmd, undef, {-C => $cd});
+        my $dir = run_qx($cmd, $env, { -C => $cd });
         die "error in @$cmd (cwd:${\($cd // '.')}): $?\n" if $?;
         chomp $dir;
-        # --absolute-git-dir requires git v2.13.0+
-        $dir = rel2abs_collapsed($dir, $cd) if $dir !~ m!\A/!;
+        # --absolute-git-dir requires git v2.13.0+, and we want to
+        # respect symlinks when $ENV{PWD} if $ENV{PWD} ne abs_path('.')
+        # since we store absolute GIT_DIR paths in cindex.
+        if (substr($dir, 0, 1) ne '/') {
+                substr($cd // '/', 0, 1) eq '/' or
+                        $cd = File::Spec->rel2abs($cd, $pwd);
+                $dir = rel2abs_collapsed($dir, $cd);
+        }
         $dir;
 }
 
diff --git a/t/admin.t b/t/admin.t
index 20e3deb7..586938d0 100644
--- a/t/admin.t
+++ b/t/admin.t
@@ -6,6 +6,7 @@ use v5.10.1;
 use PublicInbox::TestCommon;
 use PublicInbox::Import;
 use_ok 'PublicInbox::Admin';
+use autodie;
 my $v1 = create_inbox 'v1', -no_gc => 1, sub {};
 my ($tmpdir, $for_destroy) = tmpdir();
 my $git_dir = $v1->{inboxdir};
@@ -23,6 +24,17 @@ SKIP: {
 };
 
 *resolve_inboxdir = \&PublicInbox::Admin::resolve_inboxdir;
+*resolve_git_dir = \&PublicInbox::Admin::resolve_git_dir;
+
+{
+        symlink $git_dir, my $sym = "$tmpdir/v1-symlink.git";
+        for my $d ('') { # TODO: should work inside $sym/objects
+                local $ENV{PWD} = $sym.$d;
+                chdir $sym.$d;
+                is resolve_git_dir('.'), $sym,
+                        "symlink preserved from {SYMLINKDIR}.git$d";
+        }
+}
 
 # v1
 is(resolve_inboxdir($git_dir), $git_dir, 'top-level GIT_DIR resolved');