| 301 | } |
| 302 | |
| 303 | func readSeedFile(zs *zsync.Syncer, filename string, noProgress bool) error { |
| 304 | if !noProgress { |
| 305 | fmt.Fprintf(os.Stderr, "reading seed file %s:\n", filename) |
| 306 | } |
| 307 | f, err := os.Open(filename) |
| 308 | if err != nil { |
| 309 | return fmt.Errorf("could not open seed file %s: %w", filename, err) |
| 310 | } |
| 311 | var fileLength int64 |
| 312 | if fi, err := f.Stat(); err == nil { |
| 313 | fileLength = fi.Size() |
| 314 | } // else leave fileLength = 0 and we disable progress reporting further down. |
| 315 | |
| 316 | var offsetAtLastProgress int64 |
| 317 | startTime := time.Now() |
| 318 | |
| 319 | pf := func(offset int64) { |
| 320 | if offset/(fileLength/200) > offsetAtLastProgress/(fileLength/200) { |
| 321 | bytesObtained, _ := zs.Progress() |
| 322 | useFraction := float64(bytesObtained) / float64(offset) |
| 323 | elapsed := time.Since(startTime) |
| 324 | fmt.Fprintf(os.Stderr, "%s %3.1fMBps %.1f%% processed; %.1f%% useful \r", elapsed.Truncate(time.Millisecond*100).String(), float64(offset)/elapsed.Seconds()/1000000.0, 100.0*float64(offset)/float64(fileLength), 100.0*useFraction) |
| 325 | offsetAtLastProgress = offset |
| 326 | } |
| 327 | } |
| 328 | if noProgress || fileLength == 0 { |
| 329 | pf = nil |
| 330 | } |
| 331 | |
| 332 | seedSink := zs.NewSeedSink(pf) |
| 333 | _, err = seedSink.ReadFrom(f) |
| 334 | if err != nil { |
| 335 | return err |
| 336 | } |
| 337 | fmt.Fprintf(os.Stderr, " \r") |
| 338 | if closeErr := f.Close(); closeErr != nil { |
| 339 | return fmt.Errorf("failed to close seed file: %w", closeErr) |
| 340 | } |
| 341 | return nil |
| 342 | } |
| 343 | |
| 344 | type progressReporter struct { |
| 345 | zs *zsync.Syncer |