ObjectsToPush computes the set of objects that need to be sent to the target. A fetch with target refs as haves prunes the source pack server-side, so objects reachable from a have are intentionally absent from the local store. Both top-level wants and transitive references encountered during the w
(store storer.EncodedObjectStorer, wants []plumbing.Hash, targetRefs map[plumbing.ReferenceName]plumbing.Hash)
| 459 | // receive-pack accepts ref updates referencing such objects because it |
| 460 | // already has them under one of its existing refs. |
| 461 | func ObjectsToPush(store storer.EncodedObjectStorer, wants []plumbing.Hash, targetRefs map[plumbing.ReferenceName]plumbing.Hash) ([]plumbing.Hash, error) { |
| 462 | haveSet := make(map[plumbing.Hash]struct{}) |
| 463 | for _, h := range targetRefs { |
| 464 | if !h.IsZero() { |
| 465 | haveSet[h] = struct{}{} |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | filteredWants := make([]plumbing.Hash, 0, len(wants)) |
| 470 | for _, h := range wants { |
| 471 | if _, ok := haveSet[h]; !ok { |
| 472 | filteredWants = append(filteredWants, h) |
| 473 | } |
| 474 | } |
| 475 | if len(filteredWants) == 0 { |
| 476 | return nil, nil |
| 477 | } |
| 478 | |
| 479 | seen := make(map[plumbing.Hash]bool, len(filteredWants)*4) |
| 480 | objects := make([]plumbing.Hash, 0, len(filteredWants)*16) |
| 481 | for _, h := range filteredWants { |
| 482 | if err := collectObjects(store, h, haveSet, seen, &objects); err != nil { |
| 483 | return nil, err |
| 484 | } |
| 485 | } |
| 486 | return objects, nil |
| 487 | } |
| 488 | |
| 489 | func collectObjects( |
| 490 | store storer.EncodedObjectStorer, |