Subject: Re: [PATCH v4 3/3] cat-file: add --follow-symlinks to --batch

From: Junio C Hamano <[email-masked]>
Date: Mon, 11 May 2015 13:21:16 -0700

[email-masked] writes:

> +--follow-symlinks::
> +	Follow symlinks inside the repository.  Instead of providing
> +	output about the link itself, provide output about the linked-to
> +	object.  This option requires --batch or --batch-check.  In the
> +	event of a symlink loop (or more than 40 symlinks in a symlink
> +	resolution chain), the file will be treated as missing.  If a
> +	symlink points outside the repository (e.g. a link to /foo or a
> +	root-level link to ../foo), the portion of the link which is
> +	outside the repository will be printed.  Follow-symlinks will
> +	be silently turned off if <object> specifies an object in the
> +	index rather than one in the object database.

One thing that I found is missing from the above and other places in
the documents updated by this patch, when I pretend that I am an
end-user who never saw the discussion for the problem definition and
design of the solution on the list, is what "symlink" this refers
to and how I am expected to use this feature.

Such an end-user in me without inside knowledge naively expects that
the command invocation would be like this:

	$ git cat-file --batch-check --follow-symlinks <<\EOF
	e156455ea49124c140a67623f22a393db62d5d98
	55aeb4d32091e0e6062759958c30d316f77a570e
        e50885caa1043665dfe2d995e0a2f7a7a7bb51ca
	EOF

where the last one is output from "git rev-parse v2.0.0:RelNotes"
(the second one is v2.0.0^{tree}).

As somebody who is familiar with how the implementation works, I
_know_ that such an expectation is wrong.  At least the command
would need a hint that lets it realize that the blob sits inside a
tree with mode bits that says it is a symlink, e.g.

	$ git cat-file --batch-check --follow-symlinks <<\EOF
	55aeb4d32091e0e6062759958c30d316f77a570e:RelNotes
	EOF

But that requirement is not hinted in the documentation, so there is
no way for a new user to discover how useful this feature is and how
to use it.

The above description mentions "points outside the repository", but
that also may need some clarification to such an end-user in me
without inside knowledge.

For example, if I had a tree T that records a subtree T:sub, in
which a symbolic link sub/link that points at "../target", i.e. with
this setup (8fb753 is T):

    $ git rev-parse 8fb7535cc62fd9a0a804f21389667f9505299fb4:sub
    13056eb35d037f4af8be37e6a1ba983235bd7613
    $ git ls-tree 13056eb35d037f4af8be37e6a1ba983235bd7613 link
    120000 blob 78bc33729bacb569b76aaef40fec807af2ec1274    link
    $ git cat-file blob 78bc33729ba
    ../target
    $ git ls-tree 8fb7535cc62 target
    100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    target

These behave differently

    $ git cat-file --batch-check --follow-symlinks <<\EOF
    8fb7535cc62f:sub/link
    13056eb35d03:link
    EOF

and that is correct for obvious reasons, but is the reason obvious
enough to an end-user in me without inside knowledge?  The symlink
points inside the repository, but it is outside the starting object
of the extended SHA-1 expression that was used to name the object.

So in short, the description above should mention that this feature
is about asking for the object with extended SHA-1 expression that
begins with a tree-ish, colon and a path to in the tree.  And it
needs to rephrase "outside the repository" with something like
"outside the tree-ish on the left hand side of the colon in the
extended SHA-1 expression" or something.

Others better at phrasing may be able to offer a better wording than
my clumsy attempt above, though ;-)

> +If --follow-symlinks is used, and a symlink in the repository points
> +outside the repository, then `cat-file` will ignore any custom format
> +and print:
> +
> +------------
> +symlink SP <size> LF <symlink> LF
> +------------

A symlink contain LF, obviously, and we should use some quoting
convention.  Perhaps quote_c_style() on a string that needs it is
sufficient---most sane people do not put LF or literally '\' 'n' or
'"' in their symbolic links, so the ugly output is not visible for
them, and it is far better to be able to say "If you have funny
characters in your symlinks, they will be quoted" than "If you have
funny characters in your symlinks, you are SOL".

Thanks.