Update policy for replacement of managed files

This commit is contained in:
2026-06-18 13:38:44 -05:00
parent 8b0ce4d134
commit 69043801d0
18 changed files with 330 additions and 107 deletions

View File

@@ -16,6 +16,8 @@ type Action string
const (
ActionPublishNew Action = "publish_new"
ActionReplaceOlder Action = "replace_older"
ActionReplaceConflict Action = "replace_conflict"
ActionReplaceNewer Action = "replace_newer"
ActionSkipSame Action = "skip_same"
ActionSkipDestinationNewer Action = "skip_destination_newer"
ActionFailConflict Action = "fail_conflict"
@@ -269,16 +271,21 @@ func planSharedRootOwner(ctx context.Context, req Request, status state.Destinat
}
conflicts := sharedRootPathOwnershipConflicts(status, scope, plannedPaths)
if len(conflicts) > 0 {
conflictAction := ActionReplaceTakeover
for _, conflict := range conflicts {
if sharedRootTakeoverAllowed(req, status, conflict) {
continue
}
if req.Transfer.OnConflict == config.TransferActionReplace {
conflictAction = ActionReplaceConflict
continue
}
reason := sharedRootOwnershipConflictReason(conflict)
details.Action = ActionFailConflict
details.Reason = reason
return details, fmt.Errorf("%s: %s", ActionFailConflict, reason)
}
details.Action = ActionReplaceTakeover
details.Action = conflictAction
details.Reason = sharedRootOwnershipConflictReason(conflicts[0])
details.TakenOverOwnerOutputs = sharedRootConflictOutputs(status.SharedRoot, conflicts)
}
@@ -299,11 +306,11 @@ func planSharedRootOwner(ctx context.Context, req Request, status state.Destinat
if _, exists := planned[output.Path]; exists {
continue
}
if details.Action == ActionReplaceTakeover || (details.Action == ActionReplaceOlder && reconciliation.Mode == config.ReconciliationModeReplace) {
if details.Action == ActionReplaceTakeover || details.Action == ActionReplaceConflict || (isReconciliationReplacementAction(details.Action) && reconciliation.Mode == config.ReconciliationModeReplace) {
details.OwnerOutputsToDelete = append(details.OwnerOutputsToDelete, output)
continue
}
if details.Action == ActionReplaceOlder && reconciliation.Mode == config.ReconciliationModeMerge {
if isReconciliationReplacementAction(details.Action) && reconciliation.Mode == config.ReconciliationModeMerge {
details.RetainedOwnerOutputs = append(details.RetainedOwnerOutputs, output)
}
}
@@ -313,7 +320,7 @@ func planSharedRootOwner(ctx context.Context, req Request, status state.Destinat
func isWriteAction(action Action) bool {
switch action {
case ActionPublishNew, ActionReplaceOlder, ActionReplaceTakeover, ActionForceReplace:
case ActionPublishNew, ActionReplaceOlder, ActionReplaceConflict, ActionReplaceNewer, ActionReplaceTakeover, ActionForceReplace:
return true
default:
return false
@@ -506,10 +513,7 @@ func actionForComparison(comparison state.Comparison, transfer config.TransferPo
return ActionFailConflict, comparison.Reason
case state.OutcomeIdentityMismatch, state.OutcomeSameCreatedConflict, state.OutcomeDifferentSourceConflict:
if transfer.OnConflict == config.TransferActionReplace {
if force {
return ActionForceReplace, "forced replacement of conflicting destination state: " + comparison.Reason
}
return ActionFailConflict, "destination conflict replacement requires --force"
return ActionReplaceConflict, comparison.Reason
}
return ActionFailConflict, comparison.Reason
case state.OutcomeSameSource:
@@ -524,10 +528,7 @@ func actionForComparison(comparison state.Comparison, transfer config.TransferPo
return ActionReplaceOlder, comparison.Reason
case state.OutcomeDestinationNewer:
if transfer.OnDestinationNewer == config.TransferActionReplace {
if force {
return ActionForceReplace, "forced replacement of newer destination state"
}
return ActionFailConflict, "destination is newer and replacement requires --force"
return ActionReplaceNewer, comparison.Reason
}
if transfer.OnDestinationNewer == config.TransferActionFail {
return ActionFailConflict, "destination is newer and transfer policy requires failure"
@@ -538,6 +539,10 @@ func actionForComparison(comparison state.Comparison, transfer config.TransferPo
}
}
func isReconciliationReplacementAction(action Action) bool {
return action == ActionReplaceOlder || action == ActionReplaceNewer
}
func takeoverActionAllowed(req Request, status state.DestinationStatus, comparison state.Comparison, stateMode string, action Action) bool {
if stateMode != config.StateModeSingleOwner || status.State == nil {
return false