98 lines
2.6 KiB
Go
98 lines
2.6 KiB
Go
package lanesnapshot
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"inbox/internal/app/lanegit"
|
|
"inbox/internal/base/timeutil"
|
|
"inbox/internal/domain/lane"
|
|
"inbox/internal/domain/task"
|
|
)
|
|
|
|
type Service struct {
|
|
runner lanegit.Runner
|
|
clock timeutil.Clock
|
|
}
|
|
|
|
func NewService(runner lanegit.Runner, clock timeutil.Clock) *Service {
|
|
if runner == nil {
|
|
runner = lanegit.ExecRunner{}
|
|
}
|
|
if clock == nil {
|
|
clock = timeutil.SystemClock{}
|
|
}
|
|
return &Service{runner: runner, clock: clock}
|
|
}
|
|
|
|
func (s *Service) Capture(ctx context.Context, item lane.Record, taskRecord task.Record) (string, error) {
|
|
worktree := strings.TrimSpace(item.WorktreePath)
|
|
if worktree == "" {
|
|
return "", fmt.Errorf("lane %s has empty worktree path", item.ID)
|
|
}
|
|
|
|
headBefore, err := s.headCommit(ctx, worktree)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
changed, err := s.hasChanges(ctx, worktree)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if !changed {
|
|
return headBefore, nil
|
|
}
|
|
if _, err := lanegit.Run(ctx, s.runner, worktree, nil, "add", "-A"); err != nil {
|
|
return "", err
|
|
}
|
|
staged, err := s.hasStagedChanges(ctx, worktree)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if !staged {
|
|
return headBefore, nil
|
|
}
|
|
|
|
msg := fmt.Sprintf("lane(%s): complete task %s - %s", strings.TrimSpace(item.Slug), taskRecord.ID, strings.TrimSpace(taskRecord.Title))
|
|
env := map[string]string{
|
|
"GIT_AUTHOR_NAME": "Inbox",
|
|
"GIT_AUTHOR_EMAIL": "inbox@local",
|
|
"GIT_COMMITTER_NAME": "Inbox",
|
|
"GIT_COMMITTER_EMAIL": "inbox@local",
|
|
"GIT_AUTHOR_DATE": timeutil.FormatRFC3339(s.clock.Now()),
|
|
"GIT_COMMITTER_DATE": timeutil.FormatRFC3339(s.clock.Now()),
|
|
}
|
|
if _, err := lanegit.Run(ctx, s.runner, worktree, env, "commit", "-m", msg); err != nil {
|
|
return "", err
|
|
}
|
|
return s.headCommit(ctx, worktree)
|
|
}
|
|
|
|
func (s *Service) headCommit(ctx context.Context, worktree string) (string, error) {
|
|
out, err := lanegit.Run(ctx, s.runner, worktree, nil, "rev-parse", "HEAD")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strings.TrimSpace(out), nil
|
|
}
|
|
|
|
func (s *Service) hasChanges(ctx context.Context, worktree string) (bool, error) {
|
|
out, err := lanegit.Run(ctx, s.runner, worktree, nil, "status", "--porcelain")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return strings.TrimSpace(out) != "", nil
|
|
}
|
|
|
|
func (s *Service) hasStagedChanges(ctx context.Context, worktree string) (bool, error) {
|
|
_, err := s.runner.Run(ctx, worktree, nil, "git", "diff", "--cached", "--quiet", "--exit-code")
|
|
if err == nil {
|
|
return false, nil
|
|
}
|
|
if lanegit.IsExitCode(err, 1) {
|
|
return true, nil
|
|
}
|
|
return false, fmt.Errorf("git diff --cached --quiet --exit-code: %w", err)
|
|
}
|