package replica import ( "context" "errors" "time" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" ) const dailyInterval = 24 * time.Hour var ErrNoDigest = errors.New("replica: start-up needs a digest function for committed exports") type StartInput struct { Repo *git.Repository Dir string Checkpoints Checkpoints Primary Remote Digest func([]byte) ([32]byte, error) Current [32]byte } type StartPlan struct { StepNow, Pending bool CheckpointUnreadable bool Committed [32]byte DailyDue time.Time } func PlanStart(ctx context.Context, in StartInput) (StartPlan, error) { if in.Digest == nil { return StartPlan{}, ErrNoDigest } k, err := in.Checkpoints.ReadCheckpoint(ctx) if err != nil { return StartPlan{}, err } if err := ensureCheckpoint(ctx, in.Repo, in.Dir, in.Primary, k); err != nil { return StartPlan{}, err } local, err := localHead(in.Repo) if err != nil { return StartPlan{}, err } if !k.Set { if local.IsZero() { return StartPlan{Pending: true}, nil } return StartPlan{StepNow: true}, nil } if local.String() != k.Value { return StartPlan{StepNow: true}, nil } id := plumbing.NewHash(k.Value) c, err := object.GetCommit(in.Repo.Storer, id) if err != nil { return StartPlan{}, err } blob, err := ReadFile(in.Repo.Storer, id) if err != nil { return StartPlan{}, err } dailyDue := c.Committer.When.UTC().Add(dailyInterval) committed, err := in.Digest(blob) if err != nil { return StartPlan{StepNow: true, CheckpointUnreadable: true, DailyDue: dailyDue}, nil } return StartPlan{ Pending: committed != in.Current, Committed: committed, DailyDue: dailyDue, }, nil }