about summary refs log tree commit homepage
path: root/lib/PublicInbox/Admin.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2023-11-28 14:56:25 +0000
committerEric Wong <e@80x24.org>2023-11-29 02:13:25 +0000
commitbeb39f037ee439c02f1c4a8e7b1e19ce7acca100 (patch)
treea8aafb83115adeebe1713e43ac31fe3d73421f8c /lib/PublicInbox/Admin.pm
parent56f844218d0a7ed2e10952715902572c28313517 (diff)
downloadpublic-inbox-beb39f037ee439c02f1c4a8e7b1e19ce7acca100.tar.gz
Absolute pathnames of git coderepos are stored in the cindex,
but we should favor paths relative to $ENV{PWD} since it
respects symlinks in the heirarchy.

Respecting symlinks makes it easier to migrate cindex to
new storage as old storage wears out and to relocate the
storage device onto another machine.
Diffstat (limited to 'lib/PublicInbox/Admin.pm')
-rw-r--r--lib/PublicInbox/Admin.pm25
1 files changed, 21 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;
 }