Documentation ¶
Overview ¶
Package api provides the interface for querying LFS servers (metadata) NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
NOTE: Subject to change, do not rely on this package from outside git-lfs source
Index ¶
- Constants
- Variables
- func DoBatchRequest(req *http.Request) (*http.Response, *batchResponse, error)
- func DoRequest(req *http.Request, useCreds bool) (*http.Response, error)
- func NewBatchRequest(operation string) (*http.Request, error)
- func NewRequest(method, oid string) (*http.Request, error)
- func ObjectUrl(endpoint config.Endpoint, oid string) (*url.URL, error)
- func VerifyUpload(obj *ObjectResource) error
- type Client
- type Committer
- type EndpointSource
- type Filter
- type HttpLifecycle
- type HttpResponse
- type Lifecycle
- type LinkRelation
- type Lock
- type LockList
- type LockRequest
- type LockResponse
- type LockSearchRequest
- type LockService
- type ObjectError
- type ObjectResource
- func Batch(objects []*ObjectResource, operation string, transferAdapters []string) (objs []*ObjectResource, transferAdapter string, e error)
- func BatchOrLegacy(objects []*ObjectResource, operation string, transferAdapters []string) (objs []*ObjectResource, transferAdapter string, e error)
- func BatchOrLegacySingle(inobj *ObjectResource, operation string, transferAdapters []string) (obj *ObjectResource, transferAdapter string, e error)
- func DoLegacyRequest(req *http.Request) (*http.Response, *ObjectResource, error)
- func DownloadCheck(oid string) (*ObjectResource, error)
- func Legacy(objects []*ObjectResource, operation string) ([]*ObjectResource, error)
- func UploadCheck(oid string, size int64) (*ObjectResource, error)
- type Operation
- type RequestSchema
- type Response
- type UnlockRequest
- type UnlockResponse
Constants ¶
const (
MediaType = "application/vnd.git-lfs+json; charset=utf-8"
)
Variables ¶
var ( // ErrNoOperationGiven is an error which is returned when no operation // is provided in a RequestSchema object. ErrNoOperationGiven = errors.New("lfs/api: no operation provided in schema") )
Functions ¶
func DoBatchRequest ¶
doApiBatchRequest runs the request to the LFS batch API. If the API returns a 401, the repo will be marked as having private access and the request will be re-run. When the repo is marked as having private access, credentials will be retrieved.
func DoRequest ¶
DoRequest runs a request to the LFS API, without parsing the response body. If the API returns a 401, the repo will be marked as having private access and the request will be re-run. When the repo is marked as having private access, credentials will be retrieved.
func VerifyUpload ¶
func VerifyUpload(obj *ObjectResource) error
VerifyUpload calls the "verify" API link relation on obj if it exists
Types ¶
type Client ¶
type Client struct { // Locks is the LockService used to interact with the Git LFS file- // locking API. Locks LockService // contains filtered or unexported fields }
Client exposes the LFS API to callers through a multitude of different services and transport mechanisms. Callers can make a *RequestSchema using any service that is attached to the Client, and then execute a request based on that schema using the `Do()` method.
A prototypical example follows: ```
apiResponse, schema := client.Locks.Lock(request) resp, err := client.Do(schema) if err != nil { handleErr(err) } fmt.Println(apiResponse.Lock)
```
func NewClient ¶
NewClient instantiates and returns a new instance of *Client, with the given lifecycle.
If no lifecycle is given, a HttpLifecycle is used by default.
func (*Client) Do ¶
func (c *Client) Do(schema *RequestSchema) (Response, error)
Do preforms the request assosicated with the given *RequestSchema by delegating into the Lifecycle in use.
If any error was encountered while either building, executing or cleaning up the request, then it will be returned immediately, and the request can be treated as invalid.
If no error occured, an api.Response will be returned, along with a `nil` error. At this point, the body of the response has been serialized into `schema.Into`, and the body has been closed.
type Committer ¶
type Committer struct { // Name is the name of the individual who would like to obtain the // lock, for instance: "Rick Olson". Name string `json:"name"` // Email is the email assopsicated with the individual who would // like to obtain the lock, for instance: "rick@github.com". Email string `json:"email"` }
Committer represents a "First Last <email@domain.com>" pair.
func CurrentCommitter ¶
func CurrentCommitter() Committer
CurrentCommitter returns a Committer instance populated with the same credentials as would be used to author a commit. In particular, the "user.name" and "user.email" configuration values are used from the config.Config singleton.
type EndpointSource ¶
type EndpointSource interface { // Endpoint returns the `config.Endpoint` assosciated with a given // operation. Endpoint(operation string) config.Endpoint }
EndpointSource is an interface which encapsulates the behavior of returning `config.Endpoint`s based on a particular operation.
type Filter ¶
type Filter struct {
// Property is the property to search against.
// Value is the value that the property must take.
Property, Value string
}
Filter represents a single qualifier to apply against a set of locks.
type HttpLifecycle ¶
type HttpLifecycle struct {
// contains filtered or unexported fields
}
HttpLifecycle serves as the default implementation of the Lifecycle interface for HTTP requests. Internally, it leverages the *http.Client type to execute HTTP requests against a root *url.URL, as given in `NewHttpLifecycle`.
func NewHttpLifecycle ¶
func NewHttpLifecycle(endpoints EndpointSource) *HttpLifecycle
NewHttpLifecycle initializes a new instance of the *HttpLifecycle type with a new *http.Client, and the given root (see above).
func (*HttpLifecycle) Build ¶
func (l *HttpLifecycle) Build(schema *RequestSchema) (*http.Request, error)
Build implements the Lifecycle.Build function.
HttpLifecycle in particular, builds an absolute path by parsing and then relativizing the `schema.Path` with respsect to the `HttpLifecycle.root`. If there was an error in determining this URL, then that error will be returned,
After this is complete, a body is attached to the request if the schema contained one. If a body was present, and there an error occurred while serializing it into JSON, then that error will be returned and the *http.Request will not be generated.
In all cases, credentials are attached to the HTTP request as described in the `auth` package (see github.com/github/git-lfs/auth#GetCreds).
Finally, all of these components are combined together and the resulting request is returned.
func (*HttpLifecycle) Cleanup ¶
func (l *HttpLifecycle) Cleanup(resp Response) error
Cleanup implements the Lifecycle.Cleanup function by closing the Body attached to the response.
func (*HttpLifecycle) Execute ¶
func (l *HttpLifecycle) Execute(req *http.Request, into interface{}) (Response, error)
Execute implements the Lifecycle.Execute function.
Internally, the *http.Client is used to execute the underlying *http.Request. If the client returned an error corresponding to a failure to make the request, then that error will be returned immediately, and the response is guaranteed not to be serialized.
Once the response has been gathered from the server, it is unmarshled into the given `into interface{}` which is identical to the one provided in the original RequestSchema. If an error occured while decoding, then that error is returned.
Otherwise, the api.Response is returned, along with no error, signaling that the request completed successfully.
type HttpResponse ¶
type HttpResponse struct {
// contains filtered or unexported fields
}
HttpResponse is an implementation of the Response interface capable of handling HTTP responses. At its core, it works by wrapping an *http.Response.
func WrapHttpResponse ¶
func WrapHttpResponse(r *http.Response) *HttpResponse
WrapHttpResponse returns a wrapped *HttpResponse implementing the Repsonse type by using the given *http.Response.
func (*HttpResponse) Body ¶
func (h *HttpResponse) Body() io.ReadCloser
Body implements the Response.Body function, and returns the body as given by the underlying *http.Response.
func (*HttpResponse) Header ¶
func (h *HttpResponse) Header() http.Header
Header returns the underlying *http.Response's header.
func (*HttpResponse) Proto ¶
func (h *HttpResponse) Proto() string
Proto implements the Response.Proto function, and returns the proto given by the underlying *http.Response.
func (*HttpResponse) Status ¶
func (h *HttpResponse) Status() string
Status implements the Response.Status function, and returns the status given by the underlying *http.Response.
func (*HttpResponse) StatusCode ¶
func (h *HttpResponse) StatusCode() int
StatusCode implements the Response.StatusCode function, and returns the status code given by the underlying *http.Response.
type Lifecycle ¶
type Lifecycle interface { // Build creates a sendable request by using the given RequestSchema as // a model. Build(req *RequestSchema) (*http.Request, error) // Execute transforms generated request into a wrapped repsonse, (and // optionally an error, if the request failed), and serializes the // response into the `into interface{}`, if one was provided. Execute(req *http.Request, into interface{}) (Response, error) // Cleanup is called after the request has been completed and its // response has been processed. It is meant to preform any post-request // actions necessary, like closing or resetting the connection. If an // error was encountered in doing this operation, it should be returned // from this method, otherwise nil. Cleanup(resp Response) error }
A Lifecycle represents and encapsulates the behavior on an API request from inception to cleanup.
At a high level, it turns an *api.RequestSchema into an api.Response (and optionally an error). Lifecycle does so by providing several more fine-grained methods that are used by the client to manage the lifecycle of a request in a platform-agnostic fashion.
type LinkRelation ¶
type Lock ¶
type Lock struct { // Id is the unique identifier corresponding to this particular Lock. It // must be consistent with the local copy, and the server's copy. Id string `json:"id"` // Path is an absolute path to the file that is locked as a part of this // lock. Path string `json:"path"` // Committer is the author who initiated this lock. Committer Committer `json:"committer"` // CommitSHA is the commit that this Lock was created against. It is // strictly equal to the SHA of the minimum commit negotiated in order // to create this lock. CommitSHA string `json:"commit_sha"` // LockedAt is a required parameter that represents the instant in time // that this lock was created. For most server implementations, this // should be set to the instant at which the lock was initially // received. LockedAt time.Time `json:"locked_at"` // ExpiresAt is an optional parameter that represents the instant in // time that the lock stopped being active. If the lock is still active, // the server can either a) not send this field, or b) send the // zero-value of time.Time. UnlockedAt time.Time `json:"unlocked_at,omitempty"` }
Lock represents a single lock that against a particular path.
Locks returned from the API may or may not be currently active, according to the Expired flag.
type LockList ¶
type LockList struct { // Locks is the set of locks returned back, typically matching the query // parameters sent in the LockListRequest call. If no locks were matched // from a given query, then `Locks` will be represented as an empty // array. Locks []Lock `json:"locks"` // NextCursor returns the Id of the Lock the client should update its // cursor to, if there are multiple pages of results for a particular // `LockListRequest`. NextCursor string `json:"next_cursor,omitempty"` // Err populates any error that was encountered during the search. If no // error was encountered and the operation was succesful, then a value // of nil will be passed here. Err string `json:"error,omitempty"` }
LockList encapsulates a set of Locks.
type LockRequest ¶
type LockRequest struct { // Path is the path that the client would like to obtain a lock against. Path string `json:"path"` // LatestRemoteCommit is the SHA of the last known commit from the // remote that we are trying to create the lock against, as found in // `.git/refs/origin/<name>`. LatestRemoteCommit string `json:"latest_remote_commit"` // Committer is the individual that wishes to obtain the lock. Committer Committer `json:"committer"` }
LockRequest encapsulates the payload sent across the API when a client would like to obtain a lock against a particular path on a given remote.
type LockResponse ¶
type LockResponse struct { // Lock is the Lock that was optionally created in response to the // payload that was sent (see above). If the lock already exists, then // the existing lock is sent in this field instead, and the author of // that lock remains the same, meaning that the client failed to obtain // that lock. An HTTP status of "409 - Conflict" is used here. // // If the lock was unable to be created, this field will hold the // zero-value of Lock and the Err field will provide a more detailed set // of information. // // If an error was experienced in creating this lock, then the // zero-value of Lock should be sent here instead. Lock *Lock `json:"lock"` // CommitNeeded holds the minimum commit SHA that client must have to // obtain the lock. CommitNeeded string `json:"commit_needed,omitempty"` // Err is the optional error that was encountered while trying to create // the above lock. Err string `json:"error,omitempty"` }
LockResponse encapsulates the information sent over the API in response to a `LockRequest`.
type LockSearchRequest ¶
type LockSearchRequest struct { // Filters is the set of filters to query against. If the client wishes // to obtain a list of all locks, an empty array should be passed here. Filters []Filter // Cursor is an optional field used to tell the server which lock was // seen last, if scanning through multiple pages of results. // // Servers must return a list of locks sorted in reverse chronological // order, so the Cursor provides a consistent method of viewing all // locks, even if more were created between two requests. Cursor string // Limit is the maximum number of locks to return in a single page. Limit int }
LockSearchRequest encapsulates the request sent to the server when the client would like a list of locks that match the given criteria.
type LockService ¶
type LockService struct{}
LockService is an API service which encapsulates the Git LFS Locking API.
func (*LockService) Lock ¶
func (s *LockService) Lock(req *LockRequest) (*RequestSchema, *LockResponse)
Lock generates a *RequestSchema that is used to preform the "attempt lock" API method.
If a lock is already present, or if the server was unable to generate the lock, the Err field of the LockResponse type will be populated with a more detailed error describing the situation.
If the caller does not have the minimum commit necessary to obtain the lock on that file, then the CommitNeeded field will be populated in the LockResponse, signaling that more commits are needed.
In the successful case, a new Lock will be returned and granted to the caller.
func (*LockService) Search ¶
func (s *LockService) Search(req *LockSearchRequest) (*RequestSchema, *LockList)
Search generates a *RequestSchema that is used to preform the "search for locks" API method.
Searches can be scoped to match specific parameters by using the Filters field in the given LockSearchRequest. If no matching Locks were found, then the Locks field of the response will be empty.
If the client expects that the server will return many locks, then the client can choose to paginate that response. Pagination is preformed by limiting the amount of results per page, and the server will inform the client of the ID of the last returned lock. Since the server is guaranteed to return results in reverse chronological order, the client simply sends the last ID it processed along with the next request, and the server will continue where it left off.
If the server was unable to process the lock search request, then the Error field will be populated in the response.
In the successful case, one or more locks will be returned as a part of the response.
func (*LockService) Unlock ¶
func (s *LockService) Unlock(id string, force bool) (*RequestSchema, *UnlockResponse)
Unlock generates a *RequestSchema that is used to preform the "unlock" API method, against a particular lock potentially with --force.
This method's corresponding response type will either contain a reference to the lock that was unlocked, or an error that was experienced by the server in unlocking it.
type ObjectError ¶
func (*ObjectError) Error ¶
func (e *ObjectError) Error() string
type ObjectResource ¶
type ObjectResource struct { Oid string `json:"oid,omitempty"` Size int64 `json:"size"` Actions map[string]*LinkRelation `json:"actions,omitempty"` Links map[string]*LinkRelation `json:"_links,omitempty"` Error *ObjectError `json:"error,omitempty"` }
func Batch ¶
func Batch(objects []*ObjectResource, operation string, transferAdapters []string) (objs []*ObjectResource, transferAdapter string, e error)
Batch calls the batch API and returns object results
func BatchOrLegacy ¶
func BatchOrLegacy(objects []*ObjectResource, operation string, transferAdapters []string) (objs []*ObjectResource, transferAdapter string, e error)
BatchOrLegacy calls the Batch API and falls back on the Legacy API This is for simplicity, legacy route is not most optimal (serial) TODO LEGACY API: remove when legacy API removed
func BatchOrLegacySingle ¶
func BatchOrLegacySingle(inobj *ObjectResource, operation string, transferAdapters []string) (obj *ObjectResource, transferAdapter string, e error)
func DoLegacyRequest ¶
doLegacyApiRequest runs the request to the LFS legacy API.
func DownloadCheck ¶
func DownloadCheck(oid string) (*ObjectResource, error)
TODO LEGACY API: remove when legacy API removed
func Legacy ¶
func Legacy(objects []*ObjectResource, operation string) ([]*ObjectResource, error)
Legacy calls the legacy API serially and returns ObjectResources TODO LEGACY API: remove when legacy API removed
func UploadCheck ¶
func UploadCheck(oid string, size int64) (*ObjectResource, error)
TODO LEGACY API: remove when legacy API removed
func (*ObjectResource) IsExpired ¶
func (o *ObjectResource) IsExpired(now time.Time) bool
IsExpired returns true if any of the actions in this object resource have an ExpiresAt field that is after the given instant "now".
If the object contains no actions, or none of the actions it does contain have non-zero ExpiresAt fields, the object is not expired.
func (*ObjectResource) NewRequest ¶
func (o *ObjectResource) NewRequest(relation, method string) (*http.Request, error)
TODO LEGACY API: remove when legacy API removed
func (*ObjectResource) Rel ¶
func (o *ObjectResource) Rel(name string) (*LinkRelation, bool)
type RequestSchema ¶
type RequestSchema struct { // Method is the method that should be used when making a particular API // call. Method string // Path is the relative path that this API call should be made against. Path string // Operation is the operation used to determine which endpoint to make // the request against (see github.com/github/git-lfs/config). Operation Operation // Query is the query parameters used in the request URI. Query map[string]string // Body is the body of the request. Body interface{} // Into is an optional field used to represent the data structure into // which a response should be serialized. Into interface{} }
RequestSchema provides a schema from which to generate sendable requests.
type Response ¶
type Response interface { // Status is a human-readable string representing the status the // response was returned with. Status() string // StatusCode is the numeric code associated with a particular status. StatusCode() int // Proto is the protocol with which the response was delivered. Proto() string // Body returns an io.ReadCloser containg the contents of the response's // body. Body() io.ReadCloser }
Response is an interface that represents a response returned as a result of executing an API call. It is designed to represent itself across multiple response type, be it HTTP, SSH, or something else.
The Response interface is meant to be small enough such that it can be sufficiently general, but is easily accessible if a caller needs more information specific to a particular protocol.
type UnlockRequest ¶
type UnlockRequest struct { // Id is the Id of the lock that the user wishes to unlock. Id string `json:"id"` // Force determines whether or not the lock should be "forcibly" // unlocked; that is to say whether or not a given individual should be // able to break a different individual's lock. Force bool `json:"force"` }
UnlockRequest encapsulates the data sent in an API request to remove a lock.
type UnlockResponse ¶
type UnlockResponse struct { // Lock is the lock corresponding to the asked-about lock in the // `UnlockPayload` (see above). If no matching lock was found, this // field will take the zero-value of Lock, and Err will be non-nil. Lock *Lock `json:"lock"` // Err is an optional field which holds any error that was experienced // while removing the lock. Err string `json:"error,omitempty"` }
UnlockResponse is the result sent back from the API when asked to remove a lock.