github.com/atlassian/git-lob@v0.0.0-20150806085256-2386a5ed291a/providers/smart/transport.go (about)

     1  package smart
     2  
     3  import (
     4  	"io"
     5  	"net/url"
     6  )
     7  
     8  type TransportProgressCallback func(bytesDone, totalBytes int64)
     9  
    10  // The transport interface abstracts away how the smart provider talks to the server
    11  // It might do this over a persistent SSH connection, sending data across in/out streams,
    12  // or it might process each request as a discrete request/response pair over REST
    13  // Note each transport instance is stateful and associated with a server/connection, see SmartTransportFactory for how they are created
    14  type Transport interface {
    15  	// Release any resources associated with this transport (including closing any persistent connections)
    16  	Release()
    17  	// Ask the server for a list of capabilities
    18  	QueryCaps() ([]string, error)
    19  	// Request that the server enable capabilities for this exchange (note, non-persistent transports can store & send this with every request)
    20  	SetEnabledCaps(caps []string) error
    21  
    22  	// Return whether LOB metadata exists on the server (also returns size)
    23  	MetadataExists(lobsha string) (ex bool, sz int64, e error)
    24  	// Return whether LOB chunk content exists on the server
    25  	ChunkExists(lobsha string, chunk int) (ex bool, sz int64, e error)
    26  	// Return whether LOB chunk content exists on the server, and is of a specific size
    27  	ChunkExistsAndIsOfSize(lobsha string, chunk int, sz int64) (bool, error)
    28  	// Entire LOB exists? Also returns entire content size
    29  	LOBExists(lobsha string) (ex bool, sz int64, e error)
    30  
    31  	// Upload metadata for a LOB (from a stream); no progress callback as very small
    32  	UploadMetadata(lobsha string, sz int64, data io.Reader) error
    33  	// Upload chunk content for a LOB (from a stream); must call back progress
    34  	UploadChunk(lobsha string, chunk int, sz int64, data io.Reader, callback TransportProgressCallback) error
    35  	// Download metadata for a LOB (to a stream); no progress callback as very small
    36  	DownloadMetadata(lobsha string, out io.Writer) error
    37  	// Download chunk content for a LOB (from a stream); must call back progress
    38  	// This is a non-delta download operation, just provide entire chunk content
    39  	DownloadChunk(lobsha string, chunk int, out io.Writer, callback TransportProgressCallback) error
    40  
    41  	// Return the LOB which the server has a complete copy of, from a list of candidates
    42  	// Server must test in the order provided & return the earliest one which is complete on the server
    43  	// Server doesn't have to test full integrity of LOB, just completeness (check size against meta)
    44  	// Return a blank string if none are available
    45  	GetFirstCompleteLOBFromList(candidateSHAs []string) (string, error)
    46  	// Upload a binary delta to apply against a LOB the server already has, to generate a new LOB
    47  	// Deltas apply to whole LOB content and are not per-chunk
    48  	// Returns a boolean to determine whether the upload was accepted or not (server may prefer not to accept, not an error)
    49  	// In the case of false return, client will fall back to non-delta upload.
    50  	// On true, server must return nil error only after data is fully received, applied, saved as targetSHA and the
    51  	// integrity confirmed by recalculating the SHA of the final patched data.
    52  	UploadDelta(baseSHA, targetSHA string, deltaSize int64, data io.Reader, callback TransportProgressCallback) (bool, error)
    53  	// Prepare a binary delta between 2 LOBs and report the size
    54  	DownloadDeltaPrepare(baseSHA, targetSHA string) (int64, error)
    55  	// Generate (if not already cached) and download a binary delta that the client can apply locally to generate a new LOB
    56  	// Deltas apply to whole LOB content and are not per-chunk
    57  	// The server should respect sizeLimit and if the delta is larger than that, abandon the process
    58  	// Return a bool to indicate whether the delta went ahead or not (client will fall back to non-delta on false)
    59  	DownloadDelta(baseSHA, targetSHA string, sizeLimit int64, out io.Writer, callback TransportProgressCallback) (bool, error)
    60  }
    61  
    62  // Interface for a factory which creates persistent transports for use by SmartSyncProvider
    63  type TransportFactory interface {
    64  	// Does this factory want to handle the URL passed in?
    65  	WillHandleUrl(u *url.URL) bool
    66  	// Provide a new, connected (may not be persistent, but if not test connection/auth) transport for given URL
    67  	Connect(u *url.URL) (Transport, error)
    68  }
    69  
    70  var (
    71  	transportFactories []TransportFactory
    72  )
    73  
    74  // Registers an instance of a SmartTransportFactory for creating connections
    75  // Must only be called from the main thread, not thread safe
    76  // Later factories registered will take precedence over earlier ones (including core)
    77  func RegisterTransportFactory(f TransportFactory) {
    78  	transportFactories = append(transportFactories, f)
    79  }
    80  
    81  // Retrieve the best ConnectionFactory for a given URL (or nil)
    82  func GetTransportFactory(u *url.URL) TransportFactory {
    83  	// Iterate in reverse order
    84  	for i := len(transportFactories) - 1; i >= 0; i-- {
    85  		if transportFactories[i].WillHandleUrl(u) {
    86  			return transportFactories[i]
    87  		}
    88  	}
    89  	return nil
    90  }