Add paths_only projection to the recursive tree JSON API

Adds ?paths_only=1 to the recursive tree listing, returning just the
blob path names and omitting the per-entry mode, type and object ID.
This is the payload a path-oriented client such as a file finder
needs; the existing listing carries several times more bytes than
such a client can use.

Measured against chromium/src at 506,237 blobs, ?recursive=1
transfers 17.1 MB gzipped while ?recursive=1&paths_only=1 transfers
3.4 MB.

The listing is deliberately unbounded. A caller cannot distinguish a
path omitted by a cap from a path that does not exist, so a partial
listing would be a correctness bug rather than a load mitigation. No
bound is needed in any case: this is a strict projection of
?recursive=1, which is itself unbounded and considerably more
expensive to serve.

Because it is unbounded it is also streamed rather than collected.
PathList.SOURCE_ADAPTER writes each path to the JsonWriter as the
TreeWalk yields it, so serializing a tree of any size costs constant
memory; buffering chromium/src first would have held roughly 65 MB of
transient strings per concurrent request. PathList itself remains the
declared response shape, and PathServletTest deserializes the
streamed bytes back into it, which is what holds the writer and the
shape in agreement. The existing ?recursive=1 listing still buffers
and is not touched here.

On chromium/src this moves time to first byte from 234 ms to 4 ms
with total response time unchanged at 0.38 s. The bytes are
identical: the full 43 MB response compares equal before and after,
as does the gzipped path.

The trade is that a mid-walk object store error now arrives as
truncated JSON rather than as an error status, because the response
is already partly written. Callers parse the body, so truncation
fails loudly rather than silently shortening the listing.

paths_only requires recursive=1 and rejects the request otherwise. A
non-tree target already yields 404 through WalkResult.recursivePath,
so it needs no separate type check of its own.

TAG=agy
CONV=0b3e4b30-d902-4587-8bb2-ce23109d6955
Change-Id: I010e8f8b1d8f6cd4bb28492375481653186bd44e
4 files changed
tree: 8569926167bab2a8a563d1884db5a660ccde7b87
  1. .settings/
  2. Documentation/
  3. java/
  4. javatests/
  5. lib/
  6. modules/
  7. resources/
  8. tools/
  9. .bazelignore
  10. .bazelrc
  11. .bazelversion
  12. .gitignore
  13. .gitmodules
  14. .mailmap
  15. .zuul.yaml
  16. BUILD
  17. COPYING
  18. external_deps.lock.json
  19. fake_pom_deploy.xml
  20. MODULE.bazel
  21. MODULE.bazel.lock
  22. navbar.md
  23. README.md
  24. version.bzl
README.md

Gitiles - A simple JGit repository browser

Gitiles is a simple repository browser for Git repositories, built on JGit. Its guiding principle is simplicity: it has no formal access controls, no write access, no fancy Javascript, etc.

Gitiles automatically renders *.md Markdown files into HTML for simplified documentation. Refer to the Markdown documentation for details.

Configuration

Gitiles is configurable in a git-style configuration file named gitiles.config. Refer to the configuration documentation for details.

Bugs

Use gerrit's issue tracker to file bugs.

Contributing to Gitiles

Please refer to the Developer Guide.