Files
kenaito-kopsc/internal/executor/gitundo.go
T

95 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package executor
import (
"context"
"errors"
"fmt"
"strings"
)
// gitUndoOptions are the parsed arguments of `kopsc git undo`.
type gitUndoOptions struct {
Hard bool
}
// runGitUndo undoes the last commit.
func runGitUndo(ctx context.Context, req BuiltinRequest) error {
return runGitUndoWith(ctx, req, execGitRunner{})
}
func runGitUndoWith(ctx context.Context, req BuiltinRequest, runner gitRunner) error {
opts, confirmed, err := parseGitUndoArgs(req.Args)
if err != nil {
return err
}
confirmed = confirmed || req.Confirmed
// Get the last commit info
out, _, err := runner.Run(ctx, "log", "-1", "--format=%h %s")
if err != nil {
return fmt.Errorf("获取提交信息失败: %w", err)
}
lastCommit := strings.TrimSpace(out)
if lastCommit == "" {
return errors.New("没有提交可以撤销")
}
// Show preview
fmt.Fprintf(req.Stdout, "撤销最后一次提交\n\n")
fmt.Fprintf(req.Stdout, "提交: %s\n", lastCommit)
if opts.Hard {
fmt.Fprintf(req.Stdout, "模式: 完全丢弃改动(--hard)\n")
} else {
fmt.Fprintf(req.Stdout, "模式: 保留改动到暂存区(--soft)\n")
}
if !confirmed {
fmt.Fprintf(req.Stdout, "\n")
if opts.Hard {
fmt.Fprintf(req.Stdout, "⚠️ 这将永久丢弃最后一次提交的改动!加 --yes 确认执行。\n")
} else {
fmt.Fprintf(req.Stdout, "撤销后改动会保留在暂存区,加 --yes 执行。\n")
}
return &ExitError{Code: 2, Err: errors.New("需要确认")}
}
// Execute undo
resetArg := "--soft"
if opts.Hard {
resetArg = "--hard"
}
if _, stderr, err := runner.Run(ctx, "reset", resetArg, "HEAD~1"); err != nil {
return fmt.Errorf("撤销失败: %w\n%s", err, stderr)
}
if opts.Hard {
fmt.Fprintf(req.Stdout, "\n✓ 已撤销提交并丢弃改动\n")
} else {
fmt.Fprintf(req.Stdout, "\n✓ 已撤销提交,改动保留在暂存区\n")
}
return nil
}
func parseGitUndoArgs(args []string) (gitUndoOptions, bool, error) {
var opts gitUndoOptions
var confirmed bool
for _, arg := range args {
switch arg {
case "--yes", "-y":
confirmed = true
case "--hard":
opts.Hard = true
default:
if strings.HasPrefix(arg, "-") {
return opts, false, fmt.Errorf("未知选项 %q", arg)
}
}
}
return opts, confirmed, nil
}