diff options
| author | 2026-03-26 09:14:59 +0000 | |
|---|---|---|
| committer | 2026-03-26 09:14:59 +0000 | |
| commit | 3d25bda9d5da6814661828adabe8a09f9d01aefb (patch) | |
| tree | d034e28079333f85e5d7b96d921282eddd4798d6 /network/receivepack/hook.go | |
| parent | object/id: Empty tree (diff) | |
| signature | No signature | |
network/receivepack: Rename from receivepack
Diffstat (limited to 'network/receivepack/hook.go')
| -rw-r--r-- | network/receivepack/hook.go | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/network/receivepack/hook.go b/network/receivepack/hook.go new file mode 100644 index 00000000..81286bea --- /dev/null +++ b/network/receivepack/hook.go @@ -0,0 +1,93 @@ +package receivepack + +import ( + "context" + "io" + + objectid "codeberg.org/lindenii/furgit/object/id" + objectstorer "codeberg.org/lindenii/furgit/object/storer" + "codeberg.org/lindenii/furgit/network/receivepack/service" + refstore "codeberg.org/lindenii/furgit/ref/store" +) + +type HookIO struct { + Progress io.Writer + Error io.Writer +} + +// RefUpdate is one requested reference update presented to a receive-pack hook. +type RefUpdate struct { + Name string + OldID objectid.ObjectID + NewID objectid.ObjectID +} + +// UpdateDecision is one hook decision for a requested reference update. +type UpdateDecision struct { + Accept bool + Message string +} + +// HookRequest is the input presented to a receive-pack hook before quarantine +// promotion and ref updates. +// +// Refs, ExistingObjects, and QuarantinedObjects are borrowed and are only +// valid for the duration of the hook call. +type HookRequest struct { + Refs refstore.ReadingStore + ExistingObjects objectstorer.Store + QuarantinedObjects objectstorer.Store + Updates []RefUpdate + PushOptions []string + IO HookIO +} + +// Hook decides whether each requested update should proceed. +// +// The hook runs after pack ingestion into quarantine and before quarantine +// promotion or ref updates. The returned decisions must have the same length as +// HookRequest.Updates. Hook borrows the data and stores in HookRequest only for +// the duration of the call. +type Hook func(context.Context, HookRequest) ([]UpdateDecision, error) + +func translateHook(hook Hook) service.Hook { + if hook == nil { + return nil + } + + return func(ctx context.Context, req service.HookRequest) ([]service.UpdateDecision, error) { + translatedUpdates := make([]RefUpdate, 0, len(req.Updates)) + for _, update := range req.Updates { + translatedUpdates = append(translatedUpdates, RefUpdate{ + Name: update.Name, + OldID: update.OldID, + NewID: update.NewID, + }) + } + + decisions, err := hook(ctx, HookRequest{ + Refs: req.Refs, + ExistingObjects: req.ExistingObjects, + QuarantinedObjects: req.QuarantinedObjects, + Updates: translatedUpdates, + PushOptions: append([]string(nil), req.PushOptions...), + IO: HookIO{ + Progress: req.IO.Progress, + Error: req.IO.Error, + }, + }) + if err != nil { + return nil, err + } + + out := make([]service.UpdateDecision, 0, len(decisions)) + for _, decision := range decisions { + out = append(out, service.UpdateDecision{ + Accept: decision.Accept, + Message: decision.Message, + }) + } + + return out, nil + } +} |
