Fast implementation of Git in pure Go
1package receivepack
2
3import (
4 "context"
5 "io"
6
7 "codeberg.org/lindenii/furgit/objectid"
8 "codeberg.org/lindenii/furgit/objectstore"
9 "codeberg.org/lindenii/furgit/receivepack/service"
10 "codeberg.org/lindenii/furgit/refstore"
11)
12
13type HookIO struct {
14 Progress io.Writer
15 Error io.Writer
16}
17
18// RefUpdate is one requested reference update presented to a receive-pack hook.
19type RefUpdate struct {
20 Name string
21 OldID objectid.ObjectID
22 NewID objectid.ObjectID
23}
24
25// UpdateDecision is one hook decision for a requested reference update.
26type UpdateDecision struct {
27 Accept bool
28 Message string
29}
30
31// HookRequest is the input presented to a receive-pack hook before quarantine
32// promotion and ref updates.
33type HookRequest struct {
34 Refs refstore.ReadingStore
35 ExistingObjects objectstore.Store
36 QuarantinedObjects objectstore.Store
37 Updates []RefUpdate
38 PushOptions []string
39 IO HookIO
40}
41
42// Hook decides whether each requested update should proceed.
43//
44// The hook runs after pack ingestion into quarantine and before quarantine
45// promotion or ref updates. The returned decisions must have the same length as
46// HookRequest.Updates.
47type Hook func(context.Context, HookRequest) ([]UpdateDecision, error)
48
49func translateHook(hook Hook) service.Hook {
50 if hook == nil {
51 return nil
52 }
53
54 return func(ctx context.Context, req service.HookRequest) ([]service.UpdateDecision, error) {
55 translatedUpdates := make([]RefUpdate, 0, len(req.Updates))
56 for _, update := range req.Updates {
57 translatedUpdates = append(translatedUpdates, RefUpdate{
58 Name: update.Name,
59 OldID: update.OldID,
60 NewID: update.NewID,
61 })
62 }
63
64 decisions, err := hook(ctx, HookRequest{
65 Refs: req.Refs,
66 ExistingObjects: req.ExistingObjects,
67 QuarantinedObjects: req.QuarantinedObjects,
68 Updates: translatedUpdates,
69 PushOptions: append([]string(nil), req.PushOptions...),
70 IO: HookIO{
71 Progress: req.IO.Progress,
72 Error: req.IO.Error,
73 },
74 })
75 if err != nil {
76 return nil, err
77 }
78
79 out := make([]service.UpdateDecision, 0, len(decisions))
80 for _, decision := range decisions {
81 out = append(out, service.UpdateDecision{
82 Accept: decision.Accept,
83 Message: decision.Message,
84 })
85 }
86
87 return out, nil
88 }
89}