1package configsrc
2
3import (
4 "context"
5 "fmt"
6 "os"
7 "time"
8
9 "github.com/go-git/go-git/v5/plumbing"
10 "github.com/go-git/go-git/v5/plumbing/object"
11 "golang.org/x/crypto/ssh"
12
13 "tug/internal/platform/replica"
14)
15
16type CheckpointHead struct {
17 Commit string
18 Time time.Time
19 Signer ssh.PublicKey
20}
21
22func InspectCheckpoint(ctx context.Context, stateDir string, in Input) (CheckpointHead, error) {
23 var result CheckpointHead
24 checkpoint, err := commitID(in.Checkpoint, false)
25 if err != nil || checkpoint.IsZero() {
26 return result, fmt.Errorf("no checkpoint is set; a first start needs no reset")
27 }
28 dir, err := os.MkdirTemp(stateDir, "config-checkpoint-")
29 if err != nil {
30 return result, err
31 }
32 defer os.RemoveAll(dir)
33 s := &Source{dir: dir}
34 auth, err := s.auth(in)
35 if err != nil {
36 return result, err
37 }
38 repo, err := s.repo()
39 if err != nil {
40 return result, err
41 }
42 head, err := replica.Fetch(ctx, repo, in.Remote.URL, auth, plumbing.ReferenceName("refs/heads/"+in.Remote.Branch))
43 if err != nil {
44 return result, fmt.Errorf("unreachable: %w", err)
45 }
46 if head.IsZero() {
47 return result, errEmpty
48 }
49 key, refused, err := verify(repo.Storer, head, in.Signers)
50 if err != nil {
51 return result, err
52 }
53 if refused != nil {
54 return result, fmt.Errorf("%s: %w", refused.kind, refused.cause)
55 }
56 found, err := walk(repo.Storer, head, checkpoint)
57 if err != nil {
58 return result, err
59 }
60 if found {
61 return result, fmt.Errorf("the branch still holds the checkpoint; an ordinary start repairs the clone")
62 }
63 commit, err := object.GetCommit(repo.Storer, head)
64 if err != nil {
65 return result, err
66 }
67 return CheckpointHead{Commit: head.String(), Time: commit.Committer.When, Signer: key}, nil
68}