(ctx context.Context, opts PruneOptions, repo *Repository, indexPack map[restic.ID]packInfo, stats *PruneStats, printer progress.Printer)
| 360 | } |
| 361 | |
| 362 | func decidePackAction(ctx context.Context, opts PruneOptions, repo *Repository, indexPack map[restic.ID]packInfo, stats *PruneStats, printer progress.Printer) (PrunePlan, error) { |
| 363 | removePacksFirst := restic.NewIDSet() |
| 364 | removePacks := restic.NewIDSet() |
| 365 | repackPacks := restic.NewIDSet() |
| 366 | |
| 367 | var repackCandidates []packInfoWithID |
| 368 | var repackSmallCandidates []packInfoWithID |
| 369 | repoVersion := repo.Config().Version |
| 370 | |
| 371 | targetPackSize := calculateTargetPacksize(opts, indexPack) |
| 372 | // loop over all packs and decide what to do |
| 373 | bar := printer.NewCounter("packs processed") |
| 374 | bar.SetMax(uint64(len(indexPack))) |
| 375 | err := repo.List(ctx, restic.PackFile, func(id restic.ID, packSize int64) error { |
| 376 | p, ok := indexPack[id] |
| 377 | if !ok { |
| 378 | // Pack was not referenced in index and is not used => immediately remove! |
| 379 | printer.V("will remove pack %v as it is unused and not indexed", id.Str()) |
| 380 | removePacksFirst.Insert(id) |
| 381 | stats.Size.Unref += uint64(packSize) |
| 382 | return nil |
| 383 | } |
| 384 | |
| 385 | if p.unusedSize+p.usedSize != uint64(packSize) && p.usedBlobs != 0 { |
| 386 | // Pack size does not fit and pack is needed => error |
| 387 | // If the pack is not needed, this is no error, the pack can |
| 388 | // and will be simply removed, see below. |
| 389 | printer.E("pack %s: calculated size %d does not match real size %d\nRun 'restic repair index'", |
| 390 | id.Str(), p.unusedSize+p.usedSize, packSize) |
| 391 | return ErrSizeNotMatching |
| 392 | } |
| 393 | |
| 394 | // statistics |
| 395 | switch { |
| 396 | case p.usedBlobs == 0: |
| 397 | stats.Packs.Unused++ |
| 398 | case p.unusedBlobs == 0: |
| 399 | stats.Packs.Used++ |
| 400 | default: |
| 401 | stats.Packs.PartlyUsed++ |
| 402 | } |
| 403 | |
| 404 | if p.uncompressed { |
| 405 | stats.Size.Uncompressed += p.unusedSize + p.usedSize |
| 406 | } |
| 407 | mustCompress := false |
| 408 | if repoVersion >= 2 { |
| 409 | // repo v2: always repack tree blobs if uncompressed |
| 410 | // compress data blobs if requested |
| 411 | mustCompress = (p.tpe == restic.TreeBlob || opts.RepackUncompressed) && p.uncompressed |
| 412 | } |
| 413 | |
| 414 | // decide what to do |
| 415 | switch { |
| 416 | case p.usedBlobs == 0: |
| 417 | // All blobs in pack are no longer used => remove pack! |
| 418 | removePacks.Insert(id) |
| 419 | stats.Blobs.Remove += p.unusedBlobs |
no test coverage detected