aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-26 05:51:25 +0000
committerFuwn <[email protected]>2026-01-26 05:51:25 +0000
commit58efa86227d91981f38b8b51d73b8716acd749d8 (patch)
treead986a1d85a81be6830bcb10392c7d6e5c8b773e
parentdocs(README): Add example output screenshot (diff)
downloadmugi-58efa86227d91981f38b8b51d73b8716acd749d8.tar.xz
mugi-58efa86227d91981f38b8b51d73b8716acd749d8.zip
feat: Add force push flag
-rw-r--r--cmd/mugi/main.go2
-rw-r--r--internal/cli/cli.go20
-rw-r--r--internal/git/git.go11
-rw-r--r--internal/ui/ui.go10
4 files changed, 35 insertions, 8 deletions
diff --git a/cmd/mugi/main.go b/cmd/mugi/main.go
index 6caed07..f1af065 100644
--- a/cmd/mugi/main.go
+++ b/cmd/mugi/main.go
@@ -46,5 +46,5 @@ func run() error {
return fmt.Errorf("no matching repositories or remotes found")
}
- return ui.Run(cmd.Operation, tasks, cmd.Verbose)
+ return ui.Run(cmd.Operation, tasks, cmd.Verbose, cmd.Force)
}
diff --git a/internal/cli/cli.go b/internal/cli/cli.go
index 1ab54b2..1bee391 100644
--- a/internal/cli/cli.go
+++ b/internal/cli/cli.go
@@ -15,6 +15,7 @@ type Command struct {
Remotes []string
ConfigPath string
Verbose bool
+ Force bool
Help bool
Version bool
}
@@ -34,6 +35,7 @@ func Parse(args []string) (Command, error) {
args, cmd.ConfigPath = extractConfigFlag(args)
args, cmd.Verbose = extractVerboseFlag(args)
+ args, cmd.Force = extractForceFlag(args)
for _, arg := range args {
if arg == "-h" || arg == "--help" || arg == "help" {
@@ -100,6 +102,7 @@ Commands:
Flags:
-c, --config <path> Override config file path
-V, --verbose Show detailed output
+ -f, --force Force push (use with caution)
Examples:
mugi pull Pull all repositories from all remotes
@@ -174,3 +177,20 @@ func extractVerboseFlag(args []string) ([]string, bool) {
return remaining, verbose
}
+
+func extractForceFlag(args []string) ([]string, bool) {
+ var remaining []string
+ var force bool
+
+ for _, arg := range args {
+ if arg == "-f" || arg == "--force" {
+ force = true
+
+ continue
+ }
+
+ remaining = append(remaining, arg)
+ }
+
+ return remaining, force
+}
diff --git a/internal/git/git.go b/internal/git/git.go
index 13e9cb2..2455977 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -41,13 +41,13 @@ func (r *Result) setError(err error) {
}
}
-func Execute(ctx context.Context, op remote.Operation, repoPath, remoteName string) Result {
+func Execute(ctx context.Context, op remote.Operation, repoPath, remoteName string, force bool) Result {
result := Result{
Repo: repoPath,
Remote: remoteName,
}
- args := buildArgs(op, remoteName, repoPath)
+ args := buildArgs(op, remoteName, repoPath, force)
cmd := exec.CommandContext(ctx, "git", args...)
cmd.Dir = repoPath
cmd.Env = gitEnv()
@@ -66,15 +66,20 @@ func Execute(ctx context.Context, op remote.Operation, repoPath, remoteName stri
return result
}
-func buildArgs(op remote.Operation, remoteName, repoPath string) []string {
+func buildArgs(op remote.Operation, remoteName, repoPath string, force bool) []string {
switch op {
case remote.Pull:
branch := currentBranch(repoPath)
if branch == "" {
branch = "HEAD"
}
+
return []string{"pull", remoteName, branch}
case remote.Push:
+ if force {
+ return []string{"push", "--force", remoteName}
+ }
+
return []string{"push", remoteName}
case remote.Fetch:
return []string{"fetch", remoteName}
diff --git a/internal/ui/ui.go b/internal/ui/ui.go
index cee3442..e6e6ab2 100644
--- a/internal/ui/ui.go
+++ b/internal/ui/ui.go
@@ -44,10 +44,11 @@ type Model struct {
spinner spinner.Model
operation remote.Operation
verbose bool
+ force bool
done bool
}
-func NewModel(op remote.Operation, tasks []Task, verbose bool) Model {
+func NewModel(op remote.Operation, tasks []Task, verbose, force bool) Model {
s := spinner.New()
s.Spinner = spinner.Dot
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
@@ -65,6 +66,7 @@ func NewModel(op remote.Operation, tasks []Task, verbose bool) Model {
spinner: s,
operation: op,
verbose: verbose,
+ force: force,
}
}
@@ -180,7 +182,7 @@ func (m *Model) runTask(task Task) tea.Cmd {
op = m.operation
}
- result := git.Execute(context.Background(), op, task.RepoPath, task.RemoteName)
+ result := git.Execute(context.Background(), op, task.RepoPath, task.RemoteName, m.force)
return taskResult{task: task, result: result}
}
@@ -226,7 +228,7 @@ func indentOutput(s string, style lipgloss.Style) string {
return strings.Join(lines, "\n")
}
-func Run(op remote.Operation, tasks []Task, verbose bool) error {
+func Run(op remote.Operation, tasks []Task, verbose, force bool) error {
if op == remote.Pull {
inits := NeedsInit(tasks)
if len(inits) > 0 {
@@ -242,7 +244,7 @@ func Run(op remote.Operation, tasks []Task, verbose bool) error {
tasks = adjustPullTasks(tasks)
}
- model := NewModel(op, tasks, verbose)
+ model := NewModel(op, tasks, verbose, force)
p := tea.NewProgram(model)
_, err := p.Run()