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 }