func fetchIndex(indexFileUrl string) (referenceFileIndex *index.ChecksumIndex, checksumLookup filechecksum.ChecksumLookup, fileSize int64, err error) { generator := filechecksum.NewFileChecksumGenerator(BLOCK_SIZE) _, referenceFileIndex, checksumLookup, err = indexbuilder.BuildIndexFromString(generator, REFERENCE) if err != nil { return } fileSize = int64(len([]byte(REFERENCE))) return }
func Example() { // due to short example strings, use a very small block size // using one this small in practice would increase your file transfer! const blockSize = 4 // This is the "file" as described by the authoritive version const reference = "The quick brown fox jumped over the lazy dog" // This is what we have locally. Not too far off, but not correct. const localVersion = "The qwik brown fox jumped 0v3r the lazy" generator := filechecksum.NewFileChecksumGenerator(blockSize) _, referenceFileIndex, _, err := indexbuilder.BuildIndexFromString( generator, reference, ) if err != nil { return } referenceAsBytes := []byte(reference) localVersionAsBytes := []byte(localVersion) blockCount := len(referenceAsBytes) / blockSize if len(referenceAsBytes)%blockSize != 0 { blockCount++ } inputFile := bytes.NewReader(localVersionAsBytes) patchedFile := bytes.NewBuffer(nil) // This is more complicated than usual, because we're using in-memory // "files" and sources. Normally you would use MakeRSync summary := &BasicSummary{ ChecksumIndex: referenceFileIndex, ChecksumLookup: nil, BlockCount: uint(blockCount), BlockSize: blockSize, FileSize: int64(len(referenceAsBytes)), } rsync := &RSync{ Input: inputFile, Output: patchedFile, Source: blocksources.NewReadSeekerBlockSource( bytes.NewReader(referenceAsBytes), blocksources.MakeNullFixedSizeResolver(uint64(blockSize)), ), Summary: summary, OnClose: nil, } if err := rsync.Patch(); err != nil { fmt.Printf("Error: %v", err) return } fmt.Printf("Patched result: \"%s\"\n", patchedFile.Bytes()) // Output: // Patched result: "The quick brown fox jumped over the lazy dog" }
// This is exceedingly similar to the module Example, but uses the http blocksource and a local http server func Example_httpBlockSource() { PORT := <-setupServer() LOCAL_URL := fmt.Sprintf("http://localhost:%v/content", PORT) generator := filechecksum.NewFileChecksumGenerator(BLOCK_SIZE) _, referenceFileIndex, checksumLookup, err := indexbuilder.BuildIndexFromString(generator, REFERENCE) if err != nil { return } fileSize := int64(len([]byte(REFERENCE))) // This would normally be saved in a file blockCount := fileSize / BLOCK_SIZE if fileSize%BLOCK_SIZE != 0 { blockCount++ } fs := &BasicSummary{ ChecksumIndex: referenceFileIndex, ChecksumLookup: checksumLookup, BlockCount: uint(blockCount), BlockSize: uint(BLOCK_SIZE), FileSize: fileSize, } /* // Normally, this would be: rsync, err := MakeRSync( "toPatch.file", "http://localhost/content", "out.file", fs, ) */ // Need to replace the output and the input inputFile := bytes.NewReader([]byte(LOCAL_VERSION)) patchedFile := bytes.NewBuffer(nil) resolver := blocksources.MakeFileSizedBlockResolver( uint64(fs.GetBlockSize()), fs.GetFileSize(), ) rsync := &RSync{ Input: inputFile, Output: patchedFile, Source: blocksources.NewHttpBlockSource( LOCAL_URL, 1, resolver, &filechecksum.HashVerifier{ Hash: md5.New(), BlockSize: fs.GetBlockSize(), BlockChecksumGetter: fs, }, ), Summary: fs, OnClose: nil, } err = rsync.Patch() if err != nil { fmt.Printf("Error: %v\n", err) return } err = rsync.Close() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Patched content: \"%v\"\n", patchedFile.String()) // Just for inspection remoteReferenceSource := rsync.Source.(*blocksources.BlockSourceBase) fmt.Printf("Downloaded Bytes: %v\n", remoteReferenceSource.ReadBytes()) // Output: // Patched content: "The quick brown fox jumped over the lazy dog" // Downloaded Bytes: 16 }