// MakeRSync creates an RSync object using string paths, // inferring most of the configuration func MakeRSync( InputFile, Source, OutFile string, Summary FileSummary, ) (r *RSync, err error) { useTempFile := false if useTempFile, err = IsSameFile(InputFile, OutFile); err != nil { return nil, err } inputFile, err := os.Open(InputFile) if err != nil { return } var out io.WriteCloser var outFilename = OutFile var copier closer if useTempFile { out, outFilename, err = getTempFile() if err != nil { return } copier = &fileCopyCloser{ from: outFilename, to: OutFile, } } else { out, err = getOutFile(OutFile) if err != nil { return } copier = nullCloser{} } // blocksource var source *blocksources.BlockSourceBase resolver := blocksources.MakeFileSizedBlockResolver( uint64(Summary.GetBlockSize()), Summary.GetFileSize(), ) source = blocksources.NewHttpBlockSource( Source, DefaultConcurrency, resolver, &filechecksum.HashVerifier{ Hash: md5.New(), BlockSize: Summary.GetBlockSize(), BlockChecksumGetter: Summary, }, ) r = &RSync{ Input: inputFile, Output: out, Source: source, Summary: Summary, OnClose: []closer{ &fileCloser{inputFile, InputFile}, &fileCloser{out, outFilename}, copier, }, } return }
// 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 }