silk.git.remote.
List the branches, tags, and other references of a remote Git repository over HTTP or HTTPS,
like git ls-remote.
When to use#
Call GitRemote.listRefs with the URL of a repository, such as
https://github.com/silk-lang/silk.git, to get its references as a RefList from
silk.git.refs. Then look up a branch or a tag, or find the default branch with
RefList.head. Narrow the list with ListOptions.prefix, such as refs/tags/, which large
repositories answer much faster. The request goes through the Http service of
silk.http.client, so tests can give a fake server.
Details#
It speaks the smart HTTP protocol of Git. By default it asks for protocol version 2 and sends an
ls-refs command with the prefixes, so the server filters the list. A server that answers with
version 0 sends all references in its first response, and the list is filtered on the client.
A dumb HTTP server, which serves the info/refs file, is read too. For each annotated tag the
result has the peeled object, and HEAD has the default branch as its target when the server
reports it. Redirects of the first request are followed, and the second request goes to the
URL that the first one ended at.
The functions GitRemote.parseAdvertisement, GitRemote.parseLsRefs, and
GitRemote.parseDumbRefs read a response body that you got another way.
Errors#
GitRefErrorfromsilk.git.refsif the response is not a reference advertisement, is malformed, or is anERRpacket from the server.HttpErrorfromsilk.http.clientif the request fails or the status is not from 200 to 299. A private repository without credentials usually answers 401 or 404.OutOfMemoryErrorif theAllocatorfails.
Gotchas#
The URL is used as given, so it must be the repository URL that git clone accepts, without
/info/refs. Only HTTP and HTTPS URLs work, not SSH or git://. For a private repository, set
the Authorization header with ListOptions.authorization, such as Basic with a token.
Examples#
List the tags of a repository from a fake server#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.collections.list { List }
import silk.core.option { Option }
import silk.core.result { Result }
import silk.git.refs { GitRefError, Ref }
import silk.git.remote { GitRemote, ListOptions }
import silk.http.client { Http, HttpError, Request, Response }
struct DumbServer {}
impl Http for DumbServer {
effect fn sendAll(self: &mut Self, requests: List<Request<'_>>) -> List<Result<Response, HttpError>>
! OutOfMemoryError
? &mut Allocator {
return run Http.sendEach(move requests) |> Effect.provideMut<Http>(&mut self.*)
}
effect fn send(self: &mut Self, request: Request<'_>) -> Response
! HttpError | OutOfMemoryError
? &mut Allocator {
return run Response.make(200, b"95d09f2b10159347eece71399a7e2e907ea3df4f\trefs/tags/v1.0.0\n")
}
}
effect fn tagged() -> bool ! GitRefError | HttpError | OutOfMemoryError ? &mut Http | &mut Allocator {
let mut options = ListOptions.make()
run options.prefix("refs/tags/")
let refs = run GitRemote.listRefs("https://git.example.com/app.git", &options)
return match refs.resolve("v1.0.0") {
Option<&Ref>.Some { value } => value.isTag()
Option<&Ref>.None => false
}
}
pub effect fn main() -> i32 ! GitRefError | HttpError | OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let mut server = DumbServer {}
let found = run tagged() |> Effect.provideMut<Http>(&mut server)
|> Effect.provideMut<Allocator>(&mut allocator)
if found {
return 0
}
return 1
}Import as GitRemote with import silk.git.remote { GitRemote }.
Public declarations: 4.
DEFAULT_MAX_BODY_BYTES#
pub const DEFAULT_MAX_BODY_BYTES: usizeThe default limit of each response body, in bytes: 64 MiB.
GitProtocol#
pub enum GitProtocolThe Git protocol version that GitRemote.listRefs asks for.
Version2#
Version2Ask for version 2, and fall back to version 0 when the server does not speak it. The server filters the references by prefix. This is the default.
Version0#
Version0Ask for version 0 only. The server sends all references in one response, and the client filters them.
Implementation Debug for GitProtocol#
impl Debug for GitProtocolOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant, such as Version2.
ListOptions#
pub struct ListOptionsWhat GitRemote.listRefs asks for: the prefixes of the names to list, the credentials, the
protocol, and the body limit.
Details#
ListOptions.make lists every reference with protocol version 2, no credentials, and a limit
of DEFAULT_MAX_BODY_BYTES for each response body. A reference is listed when its full name
starts with one of the prefixes, or always when there are none. So refs/tags/ lists the tags
and refs/heads/ the branches. HEAD is listed only with no prefixes or with a prefix that it
starts with, such as HEAD.
Implementation ListOptions#
impl ListOptionsAssociated function make#
pub fn make() -> ListOptionsReturns the options that list every reference with protocol version 2, no credentials, and a
limit of DEFAULT_MAX_BODY_BYTES for each response body. It does not allocate.
Method prefix#
pub effect fn prefix(self: &mut Self, prefix: string) -> ()
! OutOfMemoryError
? &mut AllocatorAdds prefix to the prefixes of the names to list, such as refs/tags/ or refs/heads/.
Details#
A reference is listed when its full name starts with any of the prefixes. The comparison is of
bytes, so refs/heads/v also matches refs/heads/v2-dev.
Errors#
OutOfMemoryErrorif theAllocatorcannot supply the copy ofprefix.
Method authorization#
pub effect fn authorization(self: &mut Self, value: string) -> ()
! OutOfMemoryError
? &mut AllocatorSets the value of the Authorization header of each request, such as Basic and the Base64
of user:token, or Bearer and a token.
Errors#
OutOfMemoryErrorif theAllocatorcannot supply the copy ofvalue.
Gotchas#
The Http provider does not send the header to another origin after a redirect.
Method protocol#
pub fn protocol(self: Self, protocol: GitProtocol) -> ListOptionsReturns the options with the protocol version protocol.
Method maxBodyBytes#
pub fn maxBodyBytes(self: Self, limit: usize) -> ListOptionsReturns the options with the limit of each response body set to limit bytes.
Method prefixes#
pub fn prefixes(self: &Self) -> &[String]Returns the prefixes of the names to list, in the order they were added.
GitRemote#
pub struct GitRemoteFunctions that list the references of a remote repository.
Implementation GitRemote#
impl GitRemoteAssociated function listRefs#
pub effect fn listRefs(url: string, options: &ListOptions) -> RefList
! GitRefError | HttpError | OutOfMemoryError
? &mut Http | &mut AllocatorReturns the references of the repository at url that options selects, like
git ls-remote.
Details#
It sends GET <url>/info/refs?service=git-upload-pack. With protocol version 2, it asks for
version 2 in the Git-Protocol header. When the server answers with version 2, it then sends
POST <url>/git-upload-pack with an ls-refs command that has the prefixes and asks for
peeled tags and symbolic targets. A server that answers with version 0 or 1 lists all
references in its first answer, and they are filtered here. A dumb server answers with the
plain info/refs file, which has no HEAD.
A trailing / of url is removed. When the first request is redirected, the second goes to
the URL where the first one ended. The references are in the order of the server: HEAD
first, then by name.
Errors#
GitRefError.NotGitRepositoryif the answer is not a reference advertisement.GitRefError.Malformedif the advertisement is broken.GitRefError.ServerErrorif the server answers with anERRpacket.GitRefError.Unsupportedif a version 2 server does not offerls-refs.HttpErrorif a request fails, or the status is not from 200 to 299.OutOfMemoryErrorif theAllocatorfails.
Associated function parseAdvertisement#
pub effect fn parseAdvertisement(body: &[u8], prefixes: &[String]) -> RefList
! GitRefError | OutOfMemoryError
? &mut AllocatorReturns the references of a version 0 or version 1 advertisement in body whose names start
with one of prefixes, or all of them when prefixes is empty.
Details#
body is the answer to GET <url>/info/refs?service=git-upload-pack or the start of the
output of git-upload-pack: an optional # service= packet and flush, an optional
version 1 packet, then one packet for each reference, and a flush. The first reference has
the capabilities after a NUL byte. A symref=HEAD:<target> capability sets the target of
HEAD, and a line <id> <name>^{} sets the peeled object of the reference before it. An
empty repository advertises no references, and the result then has only an unborn HEAD when
the server reports its target.
Errors#
GitRefError.Malformedif a packet or a line is broken.GitRefError.ServerErrorif the body has anERRpacket.OutOfMemoryErrorif theAllocatorfails.
Associated function parseLsRefs#
pub effect fn parseLsRefs(body: &[u8], prefixes: &[String]) -> RefList
! GitRefError | OutOfMemoryError
? &mut AllocatorReturns the references in body, the answer of a version 2 server to an ls-refs command,
whose names start with one of prefixes, or all of them when prefixes is empty.
Details#
Each packet is <id> <name>, then optional symref-target:<target> and peeled:<id>
attributes, and a flush ends the list. A line that starts with unborn instead of an id is a
symbolic reference whose target does not exist yet, so its id is None.
Errors#
GitRefError.Malformedif a packet or a line is broken.GitRefError.ServerErrorif the body has anERRpacket.OutOfMemoryErrorif theAllocatorfails.
Associated function parseDumbRefs#
pub effect fn parseDumbRefs(body: &[u8], prefixes: &[String]) -> RefList
! GitRefError | OutOfMemoryError
? &mut AllocatorReturns the references in body, the info/refs file of a dumb HTTP server, whose names
start with one of prefixes, or all of them when prefixes is empty.
Details#
Each line is <id>, a tab, and the name, and ends with LF. A line whose name ends with ^{}
sets the peeled object of the reference before it. The file has no HEAD.
Errors#
GitRefError.NotGitRepositoryif a line is not an id, a tab, and a name, for example in an HTML page.OutOfMemoryErrorif theAllocatorfails.
Category: Version control.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.