plumbing: transport, add git-upload-archive support#1986
Conversation
| // AllowUnreachable when true disables the default security restrictions | ||
| // and allows clients to use arbitrary SHA-1 expressions. By default, | ||
| // only direct ref targets (e.g. v1.0, main) and ref:path sub-tree | ||
| // syntax (e.g. v1.0:Documentation) are allowed. | ||
| // | ||
| // This serves as the default value. When the repository-level config | ||
| // uploadArchive.allowUnreachable is explicitly set, it always overrides | ||
| // this value (both true → false and false → true). | ||
| // See https://git-scm.com/docs/git-upload-archive | ||
| AllowUnreachable bool |
There was a problem hiding this comment.
This is usually derived from global/system config then overridden by repository config. Alternatively, we'd use config.LoadConfig.
cc/ @pjbgf
There was a problem hiding this comment.
Let's start with the current cfg, err := st.Config() which is already in place. As that's the safest approach to start with.
There was a problem hiding this comment.
Cool, I will drop this option and add a comment to investigate this later and derive it from global/system config before repository config.
pjbgf
left a comment
There was a problem hiding this comment.
@aymanbagabas thanks for looking into this, here's some feedback:
| // AllowUnreachable when true disables the default security restrictions | ||
| // and allows clients to use arbitrary SHA-1 expressions. By default, | ||
| // only direct ref targets (e.g. v1.0, main) and ref:path sub-tree | ||
| // syntax (e.g. v1.0:Documentation) are allowed. | ||
| // | ||
| // This serves as the default value. When the repository-level config | ||
| // uploadArchive.allowUnreachable is explicitly set, it always overrides | ||
| // this value (both true → false and false → true). | ||
| // See https://git-scm.com/docs/git-upload-archive | ||
| AllowUnreachable bool |
There was a problem hiding this comment.
Let's start with the current cfg, err := st.Config() which is already in place. As that's the safest approach to start with.
| return (mode | 0o777) &^ defaultUmask | ||
| } | ||
|
|
||
| func writeTarArchive(st storage.Storer, w io.Writer, tree *object.Tree, prefix string, pathFilter []string, modTime time.Time) error { |
There was a problem hiding this comment.
I think we are missing this:
Additionally the commit ID is stored in a global extended pax header if the tar format is used; it can be extracted using git get-tar-commit-id. In ZIP files it is stored as a file comment.
73b8fc0 to
174aa08
Compare
5ef59da to
cebfcdd
Compare
8106cd2 to
6fa62ef
Compare
Add git-upload-archive service support to transport layer. This allows fetching archives (tarballs) from remote git repositories over various transports (SSH, HTTP, and local file). Expose new Archivable interface via transport.Session and implement: - ArchiveRequest type for archive configuration (format, compression, prefix) - UploadArchiveRequest/UploadArchive types for wire protocol - Support for archive filters (tree and commit filters) - Backend dispatch for SSH/TCP/Unix transports - Tests for file, git, and SSH transports HTTP backend support left for future protocol-v2 work.
The previous implementation was losing file permission details by converting all files to either 0o644 or 0o755, discarding the actual git mode bits including group-writable. Added applyUmask() functions that extract Unix permission bits from the git mode and apply the default umask (0o002) following canonical git's tar.umask behavior. This preserves the original file permissions from the tree being archived. Also added tests to verify file permissions are correctly preserved in both tar and zip archives.
… position for paths
…at rely on shared fixture state
Signed-off-by: Paulo Gomes <[email protected]>
Signed-off-by: Paulo Gomes <[email protected]>
Signed-off-by: Paulo Gomes <[email protected]>
Signed-off-by: Paulo Gomes <[email protected]>
Signed-off-by: Paulo Gomes <[email protected]>
Signed-off-by: Paulo Gomes <[email protected]>
6fa62ef to
4928734
Compare
Signed-off-by: Paulo Gomes <[email protected]>
pjbgf
left a comment
There was a problem hiding this comment.
@aymanbagabas thanks for the great effort putting this together. 🙇🙇🙇
This PR adds support for the
git-upload-archiveservice to the transport layer, allowing fetching of archives from remote git repositories over SSH, HTTP, and local file transports.Background
The
git-upload-archiveprotocol command is used bygit archive --remoteto fetch archives from remote repositories without cloning them. This is useful for CI/CD pipelines, release automation, and tools that need specific files from a repo.Changes
Client-Side Types
Archiver interface - Sessions that implement this can perform archive operations:
ArchiveRequest - Client archive request:
Args []string: arguments sent as "argument " pkt-lines (format, prefix, tree-ish, paths)Progress sideband.Progress: optional progress callback for status messagesServer-Side Types
UploadArchiveRequest - Server archive request configuration:
AllowUnreachable bool: disables security restrictions allowing arbitrary refsUploadArchive function - Server-side handler for the git-upload-archive protocol.
Backend Support
SSH/TCP/Unix transports - Backend now dispatches to
UploadArchive:HTTP - Left for future protocol-v2 work (HTTP archive requires command-based protocol)
Wire Protocol
Implements the git-upload-archive protocol:
Supported Formats
Supported formats parsed from args:
tar,tar.gz,tgz,zip--prefix=path/adds prefix to archive entries--listlists available archivesTesting
TestArchive_Tar,TestArchive_TarGz,TestArchive_Zip(file transport)TestGitTransport_Archive(git daemon transport)TestSSHTransport_Archive(SSH transport)All tests verify archive contents against git's output.
Security
The
uploadArchive.allowUnreachableconfig option controls whether arbitrary SHA-1 expressions are allowed. By default, only ref targets (e.g.,v1.0,main) andref:pathsub-tree syntax are allowed.Follow-up Work
A future PR will add porcelain-level support:
git.Archive()convenience methodArchiveOptionswith parametrized fields:Format: tar, tar.gz, zipPrefix: prefix path for archive entriesRemote: tree-ish reference to archivePaths: optional path filtergit archive --remoteflagsUsage Example
Supersedes: #1985