Currently, when a dir-diff is made with git-difftool the two revisions are stored in two temporary directories ".../left" and ".../right". Many difftools show these pathnames in ther UI and therefore it would be helpful for users, if actual reference names specified as progam arguments was used instead. Reference names might contain slash / characters which are not allowed to be part of a file name. These must therefore be encoded. Also, reference names that would could possibly "break out" of the temporary directory (e.g. "/foo", "foo/../bar" or "foo/././bar") must be sanitised. * Added a subroutine escape_reference_to_single_directory_name() which encodes a reference name to a valid single directory name. Any occurance of a slash / is replaced by two backslashes \\. Having a backslash \ in a reference name should be forbidden, but just to be save from collisions, any occurance of a backslash \ is replaced by a backslash followed by an underscore \_ at first. * Use this new function to construct the pathnames of the temporary directories for the two revisions in dir-diffs. Signed-off-by: Christoph Anton Mitterer <mail@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> diff --git a/git-difftool.perl b/git-difftool.perl index 12231fb..53e756d 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -83,6 +83,28 @@ sub exit_cleanup exit($status | ($status >> 8)); } +sub escape_reference_to_single_directory_name +{ + # Git allows reference names (see git-check-ref-format(1)) which cannot + # be directly mapped to a single directory name. + # + # This subroutines replaces any occurance of a slash / by two + # backslashes \\. + # Thereby, break-out attempts like "/foo", "foo/../bar" or "foo/././bar" + # are prevented, too. + # + # Having a backslash \ in a reference name should be forbidden, but just + # to be save from collisions, any occurance of a backslash \ is replaced + # by a backslash followed by an underscore \_ at first. + + my ($commit_name) = @_; + + $commit_name =~ s/\\/\\_/g; + $commit_name =~ s/\//\\\\/g; + + return $commit_name; +} + sub setup_dir_diff { my ($repo, $workdir, $symlinks) = @_; @@ -169,8 +191,13 @@ EOF # Setup temp directories my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1); - my $ldir = "$tmpdir/left"; - my $rdir = "$tmpdir/right"; + my $ldir = "$tmpdir/" . escape_reference_to_single_directory_name($ARGV[0]); + my $rdir = "$tmpdir/"; + if (@ARGV < 2) { + $rdir .= 'HEAD'; + } else { + $rdir .= escape_reference_to_single_directory_name($ARGV[1]); + } mkpath($ldir) or exit_cleanup($tmpdir, 1); mkpath($rdir) or exit_cleanup($tmpdir, 1);
<<attachment: smime.p7s>>