Archived
Hard restore with X asks before dropping staged pins
X dropped staged pins without a question, including the selected submodule's own pin, which the loss check didn't count. A staged pin is a decision, and X sits one Shift away from x, so dropped staged pins now count as a loss and make X ask (D31, amends D30). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,10 +35,29 @@ func (p *Provider) RestoreLoss(ctx context.Context, path string, to submodule.Re
|
||||
if err != nil {
|
||||
return submodule.Loss{}, err
|
||||
}
|
||||
if dir == "" { // not initialized: nothing on disk to lose
|
||||
return submodule.Loss{}, nil
|
||||
var loss submodule.Loss
|
||||
if dir != "" { // not initialized: nothing on disk to lose
|
||||
loss = p.lossOf(ctx, dir, target, to.KeepsStaged())
|
||||
}
|
||||
return p.lossOf(ctx, dir, target, to.KeepsStaged()), nil
|
||||
if to == submodule.RestoreHard && path != "" && p.pinStaged(ctx, path, target) {
|
||||
// a hard restore unstages the submodule's own pin too
|
||||
loss.StagedPins++
|
||||
loss.Modules = max(loss.Modules, 1)
|
||||
}
|
||||
return loss, nil
|
||||
}
|
||||
|
||||
// pinStaged reports whether the pin of path in its parent's index differs
|
||||
// from committed, the pin a hard restore goes to.
|
||||
func (p *Provider) pinStaged(ctx context.Context, path, committed string) bool {
|
||||
p.mu.RLock()
|
||||
in, ok := p.mods[path]
|
||||
p.mu.RUnlock()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
staged, err := pinOf(ctx, in, submodule.RestoreStaged)
|
||||
return err == nil && staged != committed
|
||||
}
|
||||
|
||||
// Restore makes path ("" is the superproject) and all submodules below it
|
||||
|
||||
@@ -364,6 +364,29 @@ func TestRestoreHardOfASubmoduleUnstagesItsPin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRestoreLossOfAHardRestoreCountsTheOwnStagedPin(t *testing.T) {
|
||||
p, _ := ownFixture(t)
|
||||
committed, err := p.RestoreLoss(context.Background(), "libs/staged", submodule.RestoreCommitted)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hard, err := p.RestoreLoss(context.Background(), "libs/staged", submodule.RestoreHard)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hard.StagedPins != committed.StagedPins+1 || hard.Modules == 0 {
|
||||
t.Errorf("hard loss %+v, want the own staged pin on top of %+v", hard, committed)
|
||||
}
|
||||
// without a staged pin, a hard restore unstages nothing of its own
|
||||
clean, err := p.RestoreLoss(context.Background(), "src/ui", submodule.RestoreHard)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if clean.StagedPins != 0 {
|
||||
t.Errorf("loss of src/ui %+v, want no staged pin", clean)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRestoreLossCountsStagedPinsOfAMovingRepository(t *testing.T) {
|
||||
p, root := ownFixture(t)
|
||||
super := filepath.Join(root, "super")
|
||||
|
||||
Reference in New Issue
Block a user