Files

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)
}