tangled
alpha
login
or
join now
runxiyu.tngl.sh
/
furgit
6
fork
atom
Fast implementation of Git in pure Go
6
fork
atom
overview
issues
pulls
pipelines
receivepack/hooks: Add pre-defined hooks
runxiyu.tngl.sh
6 days ago
ab312b30
26f7f0e3
verified
This commit was signed with the committer's
known signature
.
runxiyu.tngl.sh
SSH Key Fingerprint:
SHA256:jdcgZM4f40eqgoEW57poBu5vM9WoGE02ZzhWbfbNzc0=
+115
2 changed files
expand all
collapse all
unified
split
receivepack
hooks
chain.go
reject_force_push.go
+51
receivepack/hooks/chain.go
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
package hooks
2
+
3
+
import (
4
+
"context"
5
+
"fmt"
6
+
7
+
receivepack "codeberg.org/lindenii/furgit/receivepack"
8
+
)
9
+
10
+
// Chain combines hooks by running them in order and intersecting their
11
+
// decisions. The first rejecting message for each update is preserved.
12
+
func Chain(hooks ...receivepack.Hook) receivepack.Hook {
13
+
return func(
14
+
ctx context.Context,
15
+
req receivepack.HookRequest,
16
+
) ([]receivepack.UpdateDecision, error) {
17
+
decisions := make([]receivepack.UpdateDecision, len(req.Updates))
18
+
for i := range decisions {
19
+
decisions[i].Accept = true
20
+
}
21
+
22
+
for _, hook := range hooks {
23
+
if hook == nil {
24
+
continue
25
+
}
26
+
27
+
hookDecisions, err := hook(ctx, req)
28
+
if err != nil {
29
+
return nil, err
30
+
}
31
+
32
+
if len(hookDecisions) != len(req.Updates) {
33
+
return nil, fmt.Errorf("hook returned %d decisions for %d updates", len(hookDecisions), len(req.Updates))
34
+
}
35
+
36
+
for i, decision := range hookDecisions {
37
+
if decision.Accept {
38
+
continue
39
+
}
40
+
41
+
if decisions[i].Accept {
42
+
decisions[i].Message = decision.Message
43
+
}
44
+
45
+
decisions[i].Accept = false
46
+
}
47
+
}
48
+
49
+
return decisions, nil
50
+
}
51
+
}
+64
receivepack/hooks/reject_force_push.go
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
package hooks
2
+
3
+
import (
4
+
"context"
5
+
"errors"
6
+
"fmt"
7
+
8
+
"codeberg.org/lindenii/furgit/ancestor"
9
+
"codeberg.org/lindenii/furgit/objectid"
10
+
objectmix "codeberg.org/lindenii/furgit/objectstore/mix"
11
+
receivepack "codeberg.org/lindenii/furgit/receivepack"
12
+
"codeberg.org/lindenii/furgit/refstore"
13
+
)
14
+
15
+
// RejectForcePush rejects updates whose new value is not a fast-forward of the
16
+
// currently resolved reference.
17
+
func RejectForcePush() receivepack.Hook {
18
+
return func(
19
+
ctx context.Context,
20
+
req receivepack.HookRequest,
21
+
) ([]receivepack.UpdateDecision, error) {
22
+
_ = ctx
23
+
24
+
objects := objectmix.New(req.QuarantinedObjects, req.ExistingObjects)
25
+
26
+
decisions := make([]receivepack.UpdateDecision, len(req.Updates))
27
+
for i := range decisions {
28
+
decisions[i].Accept = true
29
+
}
30
+
31
+
for i, update := range req.Updates {
32
+
if update.OldID == objectid.Zero(update.OldID.Algorithm()) || update.NewID == objectid.Zero(update.NewID.Algorithm()) {
33
+
continue
34
+
}
35
+
36
+
current, err := req.Refs.ResolveFully(update.Name)
37
+
switch {
38
+
case err == nil:
39
+
case errors.Is(err, refstore.ErrReferenceNotFound):
40
+
continue
41
+
default:
42
+
return nil, fmt.Errorf("resolve %s: %w", update.Name, err)
43
+
}
44
+
45
+
if current.ID == update.NewID {
46
+
continue
47
+
}
48
+
49
+
ok, err := ancestor.Is(objects, nil, current.ID, update.NewID)
50
+
if err != nil {
51
+
return nil, fmt.Errorf("check fast-forward %s: %w", update.Name, err)
52
+
}
53
+
54
+
if !ok {
55
+
decisions[i] = receivepack.UpdateDecision{
56
+
Accept: false,
57
+
Message: "non-fast-forward",
58
+
}
59
+
}
60
+
}
61
+
62
+
return decisions, nil
63
+
}
64
+
}