Apply the difference to the target.
(output io.Writer, target io.ReadSeeker, op Operation)
| 273 | |
| 274 | // Apply the difference to the target. |
| 275 | func (r *rsync) ApplyDelta(output io.Writer, target io.ReadSeeker, op Operation) error { |
| 276 | var err error |
| 277 | var n int |
| 278 | var block []byte |
| 279 | |
| 280 | r.set_buffer_to_size(r.BlockSize) |
| 281 | buffer := r.buffer |
| 282 | if r.checksummer == nil { |
| 283 | r.checksummer = r.checksummer_constructor() |
| 284 | } |
| 285 | |
| 286 | write := func(b []byte) (err error) { |
| 287 | if _, err = r.checksummer.Write(b); err == nil { |
| 288 | _, err = output.Write(b) |
| 289 | } |
| 290 | return err |
| 291 | } |
| 292 | write_block := func(op Operation) (err error) { |
| 293 | if _, err = target.Seek(int64(r.BlockSize*int(op.BlockIndex)), io.SeekStart); err != nil { |
| 294 | return err |
| 295 | } |
| 296 | if n, err = io.ReadAtLeast(target, buffer, r.BlockSize); err != nil && err != io.ErrUnexpectedEOF { |
| 297 | return err |
| 298 | } |
| 299 | block = buffer[:n] |
| 300 | return write(block) |
| 301 | } |
| 302 | |
| 303 | switch op.Type { |
| 304 | case OpBlockRange: |
| 305 | for i := op.BlockIndex; i <= op.BlockIndexEnd; i++ { |
| 306 | if err = write_block(Operation{ |
| 307 | Type: OpBlock, |
| 308 | BlockIndex: i, |
| 309 | }); err != nil { |
| 310 | return err |
| 311 | } |
| 312 | } |
| 313 | case OpBlock: |
| 314 | return write_block(op) |
| 315 | case OpData: |
| 316 | return write(op.Data) |
| 317 | case OpHash: |
| 318 | actual := r.checksummer.Sum(nil) |
| 319 | if !bytes.Equal(actual, op.Data) { |
| 320 | return fmt.Errorf("Failed to verify overall file checksum actual: %s != expected: %s. This usually happens if some data was corrupted in transit or one of the involved files was altered while the transfer was in progress.", hex.EncodeToString(actual), hex.EncodeToString(op.Data)) |
| 321 | } |
| 322 | r.checksum_done = true |
| 323 | } |
| 324 | return nil |
| 325 | } |
| 326 | |
| 327 | func (r *rsync) set_buffer_to_size(sz int) { |
| 328 | if cap(r.buffer) < sz { |