TestObjectsToPushTransitiveMissing simulates the materialized-fallback failure where a fetch with target-refs as haves prunes the source pack: objects reachable from a have aren't in the local store, but they aren't part of the literal haveSet either. The walker must treat such missing objects as im
(t *testing.T)
| 1530 | // |
| 1531 | // load object <blob>: object not found |
| 1532 | func TestObjectsToPushTransitiveMissing(t *testing.T) { |
| 1533 | repo, err := git.Init(memory.NewStorage(), nil) |
| 1534 | if err != nil { |
| 1535 | t.Fatalf("init repo: %v", err) |
| 1536 | } |
| 1537 | |
| 1538 | // Blob that "exists in the target" but is not in our local store — |
| 1539 | // the source server pruned it because it's reachable from a have. |
| 1540 | prunedBlob := plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
| 1541 | |
| 1542 | // Tree referencing the pruned blob. The tree itself is in our store |
| 1543 | // (the source sent it because it's new since the have). |
| 1544 | tree := &object.Tree{ |
| 1545 | Entries: []object.TreeEntry{ |
| 1546 | {Name: "kept.txt", Mode: 0o100644, Hash: prunedBlob}, |
| 1547 | }, |
| 1548 | } |
| 1549 | treeObj := repo.Storer.NewEncodedObject() |
| 1550 | if err := tree.Encode(treeObj); err != nil { |
| 1551 | t.Fatalf("encode tree: %v", err) |
| 1552 | } |
| 1553 | treeHash, err := repo.Storer.SetEncodedObject(treeObj) |
| 1554 | if err != nil { |
| 1555 | t.Fatalf("store tree: %v", err) |
| 1556 | } |
| 1557 | |
| 1558 | // Have commit (target ref). Not in our store either — the server |
| 1559 | // stopped its walk here, so we never receive the commit object. |
| 1560 | haveCommit := plumbing.NewHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
| 1561 | |
| 1562 | // Want commit: present in our store, parent is haveCommit, tree |
| 1563 | // references the pruned blob. |
| 1564 | now := time.Now().UTC() |
| 1565 | wantCommit := &object.Commit{ |
| 1566 | Author: object.Signature{Name: "test", Email: "test@example.com", When: now}, |
| 1567 | Committer: object.Signature{Name: "test", Email: "test@example.com", When: now}, |
| 1568 | Message: "want", |
| 1569 | TreeHash: treeHash, |
| 1570 | ParentHashes: []plumbing.Hash{haveCommit}, |
| 1571 | } |
| 1572 | wantObj := repo.Storer.NewEncodedObject() |
| 1573 | if err := wantCommit.Encode(wantObj); err != nil { |
| 1574 | t.Fatalf("encode want commit: %v", err) |
| 1575 | } |
| 1576 | wantHash, err := repo.Storer.SetEncodedObject(wantObj) |
| 1577 | if err != nil { |
| 1578 | t.Fatalf("store want commit: %v", err) |
| 1579 | } |
| 1580 | |
| 1581 | targetRefs := map[plumbing.ReferenceName]plumbing.Hash{ |
| 1582 | plumbing.NewBranchReferenceName("main"): haveCommit, |
| 1583 | } |
| 1584 | hashes, err := ObjectsToPush(repo.Storer, []plumbing.Hash{wantHash}, targetRefs) |
| 1585 | if err != nil { |
| 1586 | t.Fatalf("ObjectsToPush: %v", err) |
| 1587 | } |
| 1588 | |
| 1589 | // Pack must contain the want commit and its tree, but not the pruned |
nothing calls this directly
no test coverage detected