difftool: chdir as early as possible

Make difftool chdir to the top-level of the repository as soon as it can so that we can simplify how paths are handled. Replace construction of absolute paths via string concatenation with relative paths wherever possible. The bulk of the code no longer needs to use absolute paths. Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Dec 9, 2016 at 00:58 UTC f242a03d7330a68baf0748e595c0b2290d3a05a5
1 file changed +14 -12
git-difftool.perl
+14 -12
@@ -59,14 +59,14 @@ sub exit_cleanup
59
60 sub use_wt_file
61 {
62 - my ($workdir, $file, $sha1) = @_;
62 + my ($file, $sha1) = @_;
63 my $null_sha1 = '0' x 40;
64
65 - if (-l "$workdir/$file" || ! -e _) {
65 + if (-l $file || ! -e _) {
66 return (0, $null_sha1);
67 }
68
69 - my $wt_sha1 = Git::command_oneline('hash-object', "$workdir/$file");
69 + my $wt_sha1 = Git::command_oneline('hash-object', $file);
70 my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
71 return ($use, $wt_sha1);
72 }
@@ -105,6 +105,12 @@ sub setup_dir_diff
105 my $diffrtn = Git::command_oneline(@gitargs);
106 exit(0) unless defined($diffrtn);
107
108 + # Go to the root of the worktree now that we've captured the list of
109 + # changed files. The paths returned by diff --raw are relative to the
110 + # top-level of the repository, but we defer changing directories so
111 + # that @ARGV can perform pathspec limiting in the current directory.
112 + chdir($workdir);
113 +
114 # Build index info for left and right sides of the diff
115 my $submodule_mode = '160000';
116 my $symlink_mode = '120000';
@@ -172,7 +178,7 @@ EOF
178 next;
179 }
180 my ($use, $wt_sha1) =
175 - use_wt_file($workdir, $dst_path, $rsha1);
181 + use_wt_file($dst_path, $rsha1);
182 if ($use) {
183 push @working_tree, $dst_path;
184 $wtindex .= "$rmode $wt_sha1\t$dst_path\0";
@@ -182,10 +188,6 @@ EOF
188 }
189 }
190
185 - # Go to the root of the worktree so that the left index files
186 - # are properly setup -- the index is toplevel-relative.
187 - chdir($workdir);
188 -
191 # Setup temp directories
192 my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1);
193 my $ldir = "$tmpdir/left";
@@ -235,10 +237,10 @@ EOF
237 symlink("$workdir/$file", "$rdir/$file") or
238 exit_cleanup($tmpdir, 1);
239 } else {
238 - copy("$workdir/$file", "$rdir/$file") or
240 + copy($file, "$rdir/$file") or
241 exit_cleanup($tmpdir, 1);
242
241 - my $mode = stat("$workdir/$file")->mode;
243 + my $mode = stat($file)->mode;
244 chmod($mode, "$rdir/$file") or
245 exit_cleanup($tmpdir, 1);
246 }
@@ -430,10 +432,10 @@ sub dir_diff
432 $error = 1;
433 } elsif (exists $tmp_modified{$file}) {
434 my $mode = stat("$b/$file")->mode;
433 - copy("$b/$file", "$workdir/$file") or
435 + copy("$b/$file", $file) or
436 exit_cleanup($tmpdir, 1);
437
436 - chmod($mode, "$workdir/$file") or
438 + chmod($mode, $file) or
439 exit_cleanup($tmpdir, 1);
440 }
441 }