Skip to content

Instantly share code, notes, and snippets.

@aymanbagabas
Last active June 8, 2024 20:06
Show Gist options
  • Save aymanbagabas/1b5ccc265ee62dd574c62d378b4b57bb to your computer and use it in GitHub Desktop.
Save aymanbagabas/1b5ccc265ee62dd574c62d378b4b57bb to your computer and use it in GitHub Desktop.
Go-git transport API
package transport
// Transport is an interface for creating Git protocol transfer sessions.
type Transport interface {
// SupportedProtocols returns a list of supported Git protocol versions by
// the transport client.
SupportedProtocols() []protocol.Version
// NewSession creates a new Git service session using the given storer and
// endpoint.
NewSession(st storage.Storer, ep *Endpoint, auth AuthMethod) (Session, error)
}
// Service represents a Git transport service.
// All services are prefixed with "git-".
type Service string
// String returns the string representation of the service.
func (s Service) String() string {
return string(s)
}
// Name returns the name of the service without the "git-" prefix.
func (s Service) Name() string {
return string(s)[4:]
}
// Git service names.
const (
UploadPackService Service = "git-upload-pack"
ReceivePackService Service = "git-receive-pack"
)
// Session is a Git protocol transfer session.
// This is used by all protocols.
type Session interface {
// Handshake starts the connection with the remote to get version and
// capabilities of the server.
// Params are the optional extra parameters to be sent to the server. Use
// this to send the protocol version of the client and any other extra parameters.
Handshake(ctx context.Context, service Service, params ...string) (Connection, error)
// Archive requests an archive from the remote using git-upload-archive. This
// is only supported by transports that use the pack-protocol, http transport is
// not supported.
// TODO: TBD
// Archive(ctx context.Context, req *ArchiveRequest, params ...string) (*ArchiveResponse, error)
}
// Connection represents a session endpoint connection.
type Connection interface {
// io.ReadWriter support?
// Close closes the connection.
Close() error
// Capabilities returns the list of capabilities supported by the server.
Capabilities() *capability.List
// Version returns the Git protocol version the server supports.
Version() protocol.Version
// IsStatelessRPC indicates that the connection is a half-duplex connection
// and should operate in half-duplex mode i.e. performs a single read-write
// cycle. This fits with the HTTP POST request process where session may
// read the request, write a response, and exit.
IsStatelessRPC() bool
// GetRemoteRefs returns the references advertised by the remote.
// Using protocol v0 or v1, this returns the references advertised by the
// remote during the handshake. Using protocol v2, this runs the ls-refs
// command on the remote.
// This will error if the session is not already established using
// Handshake.
GetRemoteRefs(ctx context.Context) (map[string]plumbing.Hash, error)
// Fetch sends a fetch-pack request to the server.
Fetch(ctx context.Context, req *FetchRequest) error
// Push sends a send-pack request to the server.
Push(ctx context.Context, req *PushRequest) error
// Command execute protocol v2 command.
// TODO: TBD
// Command(ctx context.Context, req CommandRequest) (CommandResponse, error)
}
// FetchRequest contains the parameters for a fetch-pack request.
// This is used during the pack negotiation phase of the fetch operation.
// See https://git-scm.com/docs/pack-protocol#_packfile_negotiation
type FetchRequest struct {
// Progress is the progress sideband.
Progress sideband.Progress
// Wants is the list of references to fetch.
Wants []plumbing.Hash
// Haves is the list of references the client already has.
Haves []plumbing.Hash
// Depth is the depth of the fetch.
Depth int
// IncludeTags indicates whether tags should be fetched.
IncludeTags bool
}
// PushRequest contains the parameters for a push request.
type PushRequest struct {
// Packfile is the packfile reader.
Packfile io.ReadCloser
// Commands is the list of push commands to be sent to the server.
Commands []*packp.Command
// Progress is the progress sideband.
Progress sideband.Progress
// Options is a set of push-options to be sent to the server during push.
Options map[string]string
// Atomic indicates an atomic push.
// If the server supports atomic push, it will update the refs in one
// atomic transaction. Either all refs are updated or none.
Atomic bool
}
@aymanbagabas
Copy link
Author

I like the pragmatism of the approach, my only challenge is that we can't extent this without breaking backwards compatibility. Would you oppose to having a new type that (i.e. enum-like) so that we have the two types we require for now, but also can expand if needed in the future if needed?

Fair enough. I think this will come handy when we implement git-upload-archive and possibly when we add support to LFS and git-lfs-transfer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment