git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] use refnames instead of "left"/"right" in dirdiffs

From
John Keeping <john@keeping.me.uk>
Date
Mar 27, 2013, 23:07 UTC
Message-ID
<20130327230715.GU2286@serenity.lan>
In-Reply-To
<1364422397.8091.1.camel@heisenberg.scientia.net>
On Wed, Mar 27, 2013 at 11:13:17PM +0100, Christoph Anton Mitterer wrote:
Show 40 quoted lines
> 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@christoph.anton.mitterer.name>
> 
> 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.

That's not going to work well on Windows, is it? Anything with two dots in is already forbidden so we don't need to worry about that; I'm not sure we need to remove forward slashes at all, until we consider the "commit containing" syntax ':/fix nasty bug' or 'master^{/fix bug}'.

I'm more concerned with specifiers containing '^', '@', '{', ':' - see 'SPECIFYING REVISIONS' in git-rev-parse(1) for the full details of what's acceptable. At some point I think it may be better to fall back to the SHA1 of the relevant commit.

Show 29 quoted lines
> +       #
> +       # 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]);
> +       }

I don't think this approach is general enough, since git-difftool accepts the same range of arguments that git-diff does.

We need to walk over @ARGV here, ignore anything starting with '-', stop when we reach '--' and handle the arguments found in there including the three acceptable range forms:

    <commit> <commit>
    <commit>..<commit>
    <commit>...<commit>
replacing missing commits with HEAD.
>         mkpath($ldir) or exit_cleanup($tmpdir, 1);
>         mkpath($rdir) or exit_cleanup($tmpdir, 1);
>  
> 
Previous: Christoph Anton MittererNext: Christoph Anton Mitterer
Message 2 of 5 in “use refnames instead of "left"/"right" in dirdiffs”
  1. use refnames instead of "left"/"right" in dirdiffsChristoph Anton Mitterer, Mar 27, 2013
  2. John KeepingMar 27, 2013
  3. Christoph Anton MittererMar 28, 2013
  4. John KeepingMar 28, 2013
  5. John KeepingMar 28, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.