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

Re: RFC: git cat-file --follow-symlinks?

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Apr 30, 2015, 08:10 UTC
Message-ID
<5541E36D.1010606@alum.mit.edu>
In-Reply-To
<1430341032.14907.9.camel@ubuntu>
On 04/29/2015 10:57 PM, David Turner wrote:
Show 10 quoted lines
> I recently had a situation where I was using git cat-file (--batch) to
> read files and directories out of the repository -- basically, todo the
> equivalent of open, opendir, etc, on an arbitrary revision.
> Unfortunately, I had to do a lot of gymnastics to handle symlinks in the
> repository.  Instead of just doing echo $SHA:foo/bar/baz | git cat-file
> --batch, I would have to first check if foo was a symlink, and if so,
> follow it, and then check bar, and so on.
> 
> Instead, it would be cool if cat-file had a mode in which it would
> follow symlinks.

I guess it's obvious, but I haven't seen it discussed in this thread, so I wanted to point out that this feature has some limitations related to how its arguments are constructed.

In the examples discussed,
    git cat-file --follow-symlinks $committish:foo/bar/baz

, we know the root of a tree and we know the relative path where the symlink was located, so all is well (modulo a policy for handling symlinks that point outside of the repo). But the following, which would naively seem to be identical, cannot work:

    oid=$(git rev-parse $committish:foo/bar/baz)
    git cat-file --follow-symlinks $sha1

The problem is that `$oid` is the name of a blob, and `cat-file` can't know whether the blob represents the contents of a symlink or the contents of a file. (And even if it knew, it would have no idea what tree the symlink paths should be interpreted relative to.) What if we pass `cat-file` a tree and a relative path instead?:

    tree=$(git rev-parse $committish:foo/bar)
    git cat-file --follow-symlinks $tree:baz

Now it can work, but only if the symlink chain never rises above the level of `$tree`. So for example, if `foo/bar/baz` points at `../xyzzy`, then the very first example would succeed, whereas the last one would have to fail. Please note that there is no possible way to avoid failure by reading files from the filesystem outside of the repository, because in this case `cat-file` can have no idea where to look.

Show 7 quoted lines
> The major wrinkle is that symlinks can point outside the repository --
> either because they are absolute paths, or because they are relative
> paths with enough ../ in them.  For this case, I propose that
> --follow-symlinks should output [sha] "symlink" [target] instead of the
> usual [sha] "blob" [bytes].  Since --follow-symlinks is new, this format
> change will not break any existing code.
> [...]

I don't think this is doable in the general case, because it is not only the last component of the path that can point outside of the repository. Suppose we have

    foo -> ../plugh
and I run
    git cat-file --follow-symlinks HEAD:foo/bar/baz

The lookup of `foo` already falls outside of the repository, and `bar/baz` is relative to *it*, so in this case it would have to return

    ???? "symlink" ../plugh/bar/baz

The question is, what SHA-1 should be output in place of the question marks? The only SHA-1 we have handy is the SHA-1 of `foo`, but that doesn't seem especially useful.

Michael
-- 
Michael Haggerty
mhagger@alum.mit.edu
Previous: David Turner
Message 43 of 43 in “RFC: git cat-file --follow-symlinks?”
  1. David TurnerApr 29, 2015
  2. Jonathan NiederApr 29, 2015
  3. David TurnerApr 29, 2015
  4. Junio C HamanoApr 29, 2015
  5. David TurnerApr 29, 2015
  6. Jeff KingApr 29, 2015
  7. Jonathan NiederApr 29, 2015
  8. Jeff KingApr 29, 2015
  9. David TurnerApr 29, 2015
  10. Jeff KingApr 29, 2015
  11. Jeff KingApr 30, 2015
  12. David TurnerApr 30, 2015
  13. Jeff KingApr 30, 2015
  14. Junio C HamanoApr 30, 2015
  15. Jeff KingApr 30, 2015
  16. David TurnerApr 30, 2015
  17. Jeff KingApr 30, 2015
  18. Junio C HamanoApr 30, 2015
  19. Michael HaggertyApr 30, 2015
  20. David TurnerApr 30, 2015
  21. Junio C HamanoApr 30, 2015
  22. David TurnerApr 30, 2015
  23. Jeff KingApr 30, 2015
  24. David TurnerApr 30, 2015
  25. Jeff KingApr 30, 2015
  26. David TurnerApr 30, 2015
  27. Jeff KingApr 30, 2015
  28. David TurnerApr 30, 2015
  29. Andreas SchwabApr 30, 2015
  30. Jeff KingApr 30, 2015
  31. Junio C HamanoApr 30, 2015
  32. David TurnerApr 30, 2015
  33. Junio C HamanoApr 30, 2015
  34. Jeff KingApr 30, 2015
  35. Junio C HamanoApr 30, 2015
  36. David TurnerMay 1, 2015
  37. Jeff KingMay 1, 2015
  38. David TurnerMay 1, 2015
  39. Jeff KingMay 1, 2015
  40. David TurnerMay 1, 2015
  41. Junio C HamanoApr 29, 2015
  42. David TurnerApr 29, 2015
  43. Michael HaggertyApr 30, 2015

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.