From: Junio C Hamano Date: Tue, 27 Dec 2016 08:11:43 +0000 (-0800) Subject: Merge branch 'jk/difftool-in-subdir' X-Git-Tag: v2.12.0-rc0~101 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/5a5d3f1f1255559080f754fb202887f1566d8db3?ds=inline;hp=-c Merge branch 'jk/difftool-in-subdir' Even though an fix was attempted in Git 2.9.3 days, but running "git difftool --dir-diff" from a subdirectory never worked. This has been fixed. * jk/difftool-in-subdir: difftool: rename variables for consistency difftool: chdir as early as possible difftool: sanitize $workdir as early as possible difftool: fix dir-diff index creation when in a subdirectory --- 5a5d3f1f1255559080f754fb202887f1566d8db3 diff --combined git-difftool.perl index 674828de39,4e4f5d8138..df59bdfe97 --- a/git-difftool.perl +++ b/git-difftool.perl @@@ -22,7 -22,6 +22,7 @@@ use File::Path qw(mkpath rmtree) use File::Temp qw(tempdir); use Getopt::Long qw(:config pass_through); use Git; +use Git::I18N; sub usage { @@@ -60,14 -59,14 +60,14 @@@ sub exit_cleanu sub use_wt_file { - my ($workdir, $file, $sha1) = @_; + my ($file, $sha1) = @_; my $null_sha1 = '0' x 40; - if (-l "$workdir/$file" || ! -e _) { + if (-l $file || ! -e _) { return (0, $null_sha1); } - my $wt_sha1 = Git::command_oneline('hash-object', "$workdir/$file"); + my $wt_sha1 = Git::command_oneline('hash-object', $file); my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1); return ($use, $wt_sha1); } @@@ -101,11 -100,17 +101,17 @@@ sub changed_file sub setup_dir_diff { - my ($workdir, $symlinks) = @_; + my ($worktree, $symlinks) = @_; my @gitargs = ('diff', '--raw', '--no-abbrev', '-z', @ARGV); my $diffrtn = Git::command_oneline(@gitargs); exit(0) unless defined($diffrtn); + # Go to the root of the worktree now that we've captured the list of + # changed files. The paths returned by diff --raw are relative to the + # top-level of the repository, but we defer changing directories so + # that @ARGV can perform pathspec limiting in the current directory. + chdir($worktree); + # Build index info for left and right sides of the diff my $submodule_mode = '160000'; my $symlink_mode = '120000'; @@@ -116,14 -121,14 +122,14 @@@ my $wtindex = ''; my %submodule; my %symlink; - my @working_tree = (); + my @files = (); my %working_tree_dups = (); my @rawdiff = split('\0', $diffrtn); my $i = 0; while ($i < $#rawdiff) { if ($rawdiff[$i] =~ /^::/) { - warn << 'EOF'; + warn __ <<'EOF'; Combined diff formats ('-c' and '--cc') are not supported in directory diff mode ('-d' and '--dir-diff'). EOF @@@ -168,14 -173,14 +174,14 @@@ } if ($rmode ne $null_mode) { - # Avoid duplicate working_tree entries + # Avoid duplicate entries if ($working_tree_dups{$dst_path}++) { next; } my ($use, $wt_sha1) = - use_wt_file($workdir, $dst_path, $rsha1); + use_wt_file($dst_path, $rsha1); if ($use) { - push @working_tree, $dst_path; + push @files, $dst_path; $wtindex .= "$rmode $wt_sha1\t$dst_path\0"; } else { $rindex .= "$rmode $rsha1\t$dst_path\0"; @@@ -183,10 -188,6 +189,10 @@@ } } + # Go to the root of the worktree so that the left index files + # are properly setup -- the index is toplevel-relative. - chdir($workdir); ++ chdir($worktree); + # Setup temp directories my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1); my $ldir = "$tmpdir/left"; @@@ -225,23 -226,21 +231,21 @@@ delete($ENV{GIT_INDEX_FILE}); # Changes in the working tree need special treatment since they are - # not part of the index. Remove any trailing slash from $workdir - # before starting to avoid double slashes in symlink targets. - $workdir =~ s|/$||; - for my $file (@working_tree) { + # not part of the index. + for my $file (@files) { my $dir = dirname($file); unless (-d "$rdir/$dir") { mkpath("$rdir/$dir") or exit_cleanup($tmpdir, 1); } if ($symlinks) { - symlink("$workdir/$file", "$rdir/$file") or + symlink("$worktree/$file", "$rdir/$file") or exit_cleanup($tmpdir, 1); } else { - copy("$workdir/$file", "$rdir/$file") or + copy($file, "$rdir/$file") or exit_cleanup($tmpdir, 1); - my $mode = stat("$workdir/$file")->mode; + my $mode = stat($file)->mode; chmod($mode, "$rdir/$file") or exit_cleanup($tmpdir, 1); } @@@ -279,7 -278,7 +283,7 @@@ exit_cleanup($tmpdir, 1) if not $ok; } - return ($ldir, $rdir, $tmpdir, @working_tree); + return ($ldir, $rdir, $tmpdir, @files); } sub write_to_file @@@ -343,7 -342,7 +347,7 @@@ sub mai if (length($opts{difftool_cmd}) > 0) { $ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd}; } else { - print "No given for --tool=\n"; + print __("No given for --tool=\n"); usage(1); } } @@@ -351,7 -350,7 +355,7 @@@ if (length($opts{extcmd}) > 0) { $ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd}; } else { - print "No given for --extcmd=\n"; + print __("No given for --extcmd=\n"); usage(1); } } @@@ -389,8 -388,9 +393,9 @@@ sub dir_dif my $error = 0; my $repo = Git->repository(); my $repo_path = $repo->repo_path(); - my $workdir = $repo->wc_path(); - my ($a, $b, $tmpdir, @worktree) = setup_dir_diff($workdir, $symlinks); + my $worktree = $repo->wc_path(); + $worktree =~ s|/$||; # Avoid double slashes in symlink targets + my ($a, $b, $tmpdir, @files) = setup_dir_diff($worktree, $symlinks); if (defined($extcmd)) { $rc = system($extcmd, $a, $b); @@@ -411,38 -411,37 +416,38 @@@ my %tmp_modified; my $indices_loaded = 0; - for my $file (@worktree) { + for my $file (@files) { next if $symlinks && -l "$b/$file"; next if ! -f "$b/$file"; if (!$indices_loaded) { %wt_modified = changed_files( - $repo_path, "$tmpdir/wtindex", $workdir); + $repo_path, "$tmpdir/wtindex", $worktree); %tmp_modified = changed_files( $repo_path, "$tmpdir/wtindex", $b); $indices_loaded = 1; } if (exists $wt_modified{$file} and exists $tmp_modified{$file}) { - my $errmsg = "warning: Both files modified: "; - $errmsg .= "'$worktree/$file' and '$b/$file'.\n"; - $errmsg .= "warning: Working tree file has been left.\n"; - $errmsg .= "warning:\n"; - warn $errmsg; + warn sprintf(__( + "warning: Both files modified:\n" . + "'%s/%s' and '%s/%s'.\n" . + "warning: Working tree file has been left.\n" . - "warning:\n"), $workdir, $file, $b, $file); ++ "warning:\n"), $worktree, $file, $b, $file); $error = 1; } elsif (exists $tmp_modified{$file}) { my $mode = stat("$b/$file")->mode; - copy("$b/$file", "$workdir/$file") or + copy("$b/$file", $file) or exit_cleanup($tmpdir, 1); - chmod($mode, "$workdir/$file") or + chmod($mode, $file) or exit_cleanup($tmpdir, 1); } } if ($error) { - warn "warning: Temporary files exist in '$tmpdir'.\n"; - warn "warning: You may want to cleanup or recover these.\n"; + warn sprintf(__( + "warning: Temporary files exist in '%s'.\n" . + "warning: You may want to cleanup or recover these.\n"), $tmpdir); exit(1); } else { exit_cleanup($tmpdir, $rc);