all repos

mugit @ dc720d9b4ebce9977602babbfdc86b2ba7ace0fd

🐮 git server that your cow will love

mugit/internal/cli/repo.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
mirror: sync on mirror repo creation, 2 months ago
1
package cli
2
3
import (
4
	"context"
5
	"fmt"
6
	"log/slog"
7
	"os"
8
9
	"github.com/urfave/cli/v3"
10
	"olexsmir.xyz/mugit/internal/git"
11
	"olexsmir.xyz/mugit/internal/mirror"
12
)
13
14
func (c *Cli) repoNewAction(ctx context.Context, cmd *cli.Command) error {
15
	name, err := c.getRepoNameArg(cmd)
16
	if name == "" {
17
		return err
18
	}
19
20
	path, err := git.ResolvePath(c.cfg.Repo.Dir, name)
21
	if err != nil {
22
		return err
23
	}
24
25
	if _, err = os.Stat(path); err == nil {
26
		return fmt.Errorf("repository already exists: %s", name)
27
	}
28
29
	mirrorURL := cmd.String("mirror")
30
	if mirrorURL != "" {
31
		if merr := mirror.IsRemoteSupported(mirrorURL); merr != nil {
32
			return merr
33
		}
34
	}
35
36
	if err = git.Init(path); err != nil {
37
		return err
38
	}
39
40
	repo, err := git.Open(path, "")
41
	if err != nil {
42
		return fmt.Errorf("failed to open repo: %w", err)
43
	}
44
45
	if err := repo.SetPrivate(cmd.Bool("private")); err != nil {
46
		return fmt.Errorf("failed to set private status: %w", err)
47
	}
48
49
	if mirrorURL != "" {
50
		if err := repo.SetMirrorRemote(mirrorURL); err != nil {
51
			return fmt.Errorf("failed to set mirror remote: %w", err)
52
		}
53
54
		slog.Info("performing initial sync for mirror", "repo", name)
55
		if err := c.syncRepo(ctx, name); err != nil {
56
			return err
57
		}
58
		slog.Info("initial mirror sync completed", "repo", name)
59
	}
60
61
	desc := cmd.String("description")
62
	if desc != "" {
63
		if err := repo.SetDescription(desc); err != nil {
64
			return fmt.Errorf("failed to set description: %w", err)
65
		}
66
	}
67
68
	defaultBranch := cmd.String("default")
69
	if defaultBranch != "" {
70
		if err := repo.SetDefaultBranch(defaultBranch); err != nil {
71
			return fmt.Errorf("failed to set default branch: %w", err)
72
		}
73
	}
74
75
	return nil
76
}
77
78
func (c *Cli) repoDescriptionAction(ctx context.Context, cmd *cli.Command) error {
79
	name, err := c.getRepoNameArg(cmd)
80
	if name == "" {
81
		return err
82
	}
83
84
	repo, err := c.openRepo(name)
85
	if err != nil {
86
		return fmt.Errorf("failed to open repo: %w", err)
87
	}
88
89
	newDesc := cmd.Args().Get(0)
90
	if newDesc != "" {
91
		if err = repo.SetDescription(newDesc); err != nil {
92
			return fmt.Errorf("failed to set description: %w", err)
93
		}
94
	}
95
96
	desc, err := repo.Description()
97
	if err != nil {
98
		return fmt.Errorf("failed to get description: %w", err)
99
	}
100
101
	slog.Info("changed repo description", "repo", name, "new_description", desc)
102
	return nil
103
}
104
105
func (c *Cli) repoPrivateAction(ctx context.Context, cmd *cli.Command) error {
106
	name, err := c.getRepoNameArg(cmd)
107
	if name == "" {
108
		return err
109
	}
110
111
	repo, err := c.openRepo(name)
112
	if err != nil {
113
		return fmt.Errorf("failed to open repo: %w", err)
114
	}
115
116
	isPrivate, err := repo.IsPrivate()
117
	if err != nil {
118
		return fmt.Errorf("failed to get private status: %w", err)
119
	}
120
121
	newStatus := !isPrivate
122
	if err := repo.SetPrivate(newStatus); err != nil {
123
		return fmt.Errorf("failed to set private status: %w", err)
124
	}
125
126
	slog.Info("new repo private status", "repo", name, "is_private", newStatus)
127
	return nil
128
}
129
130
func (c *Cli) repoDefaultAction(ctx context.Context, cmd *cli.Command) error {
131
	name, err := c.getRepoNameArg(cmd)
132
	if name == "" {
133
		return err
134
	}
135
136
	repo, err := c.openRepo(name)
137
	if err != nil {
138
		return fmt.Errorf("failed to open repo: %w", err)
139
	}
140
141
	branch := cmd.Args().Get(0)
142
	if err = repo.SetDefaultBranch(branch); err != nil {
143
		return err
144
	}
145
146
	slog.Info("changed repo head", "repo", name, "branch", branch)
147
	return err
148
}
149
150
func (c *Cli) repoSyncAction(ctx context.Context, cmd *cli.Command) error {
151
	name, err := c.getRepoNameArg(cmd)
152
	if name == "" {
153
		return err
154
	}
155
156
	repo, err := c.openRepo(name)
157
	if err != nil {
158
		return fmt.Errorf("failed to open repo: %w", err)
159
	}
160
161
	isMirror, err := repo.IsMirror()
162
	if err != nil {
163
		return fmt.Errorf("failed to check mirror status: %w", err)
164
	}
165
	if !isMirror {
166
		return fmt.Errorf("repository is not a mirror: %s", name)
167
	}
168
169
	if err := c.syncRepo(ctx, name); err != nil {
170
		return err
171
	}
172
173
	slog.Info("mirror sync triggered", "repo", name)
174
	return nil
175
}
176
177
func (c *Cli) getRepoNameArg(cmd *cli.Command) (string, error) {
178
	name := cmd.StringArg("name")
179
	if name == "" {
180
		return "", fmt.Errorf("no name provided")
181
	}
182
	return git.ResolveName(name), nil
183
}
184
185
func (c *Cli) syncRepo(ctx context.Context, name string) error {
186
	worker := mirror.NewWorker(c.cfg)
187
	if err := worker.SyncRepo(ctx, name); err != nil {
188
		return fmt.Errorf("failed to sync mirror: %w", err)
189
	}
190
	return nil
191
}