feat(local): Add mirror mode (#308)

* feat(local): Add mirror mode

* fix: Add `.git` to the mirror repos too
This commit is contained in:
Aleksey @soar Smyrnov 2025-04-05 14:30:31 -04:00 committed by GitHub
parent 06a97f1f8a
commit eadd2f7347
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 20 additions and 10 deletions

View file

@ -269,6 +269,7 @@ destination:
zip: true # zips the repository after cloned and removes the repository afterwards zip: true # zips the repository after cloned and removes the repository afterwards
keep: 5 # only keeps x backups keep: 5 # only keeps x backups
bare: true # clone the repositories as bare bare: true # clone the repositories as bare
mirror: true # create mirror clones
lfs: true # clone lfs repos, !! ATTENTION !! git and git-lfs must be installed on the system! lfs: true # clone lfs repos, !! ATTENTION !! git and git-lfs must be installed on the system!
s3: s3:
- endpoint: somewhere:9000 # whatever your s3 endpoint is - endpoint: somewhere:9000 # whatever your s3 endpoint is

View file

@ -499,6 +499,10 @@
"type": "boolean", "type": "boolean",
"description": "clone the repository as a bare repository" "description": "clone the repository as a bare repository"
}, },
"mirror": {
"type": "boolean",
"description": "clone the repository as a mirror repository"
},
"lfs": { "lfs": {
"type": "boolean", "type": "boolean",
"description": "uses lfs to clone repositories" "description": "uses lfs to clone repositories"

View file

@ -22,17 +22,20 @@ func New() (GitCmd, error) {
return GitCmd{CMD: "git"}, nil return GitCmd{CMD: "git"}, nil
} }
func (g GitCmd) Clone(url, reponame string, bare bool) error { func (g GitCmd) Clone(url, reponame string, bare bool, mirror bool) error {
cmd := exec.Command(g.CMD, "clone", url, reponame) cmd := exec.Command(g.CMD, "clone", url, reponame)
if bare { if bare {
cmd.Args = append(cmd.Args, "--bare") cmd.Args = append(cmd.Args, "--bare")
} }
if mirror {
cmd.Args = append(cmd.Args, "--mirror")
}
return cmd.Run() return cmd.Run()
} }
func (g GitCmd) Pull(bare bool, repopath string) error { func (g GitCmd) Pull(bare bool, mirror bool, repopath string) error {
var args = []string{} var args = []string{}
if bare { if bare || mirror {
args = []string{"-C", repopath, "fetch", "--all"} args = []string{"-C", repopath, "fetch", "--all"}
} else { } else {
args = []string{"-C", repopath, "pull", "--all"} args = []string{"-C", repopath, "pull", "--all"}

View file

@ -50,7 +50,7 @@ func Locally(repo types.Repo, l types.Local, dry bool) bool {
repo.Name = path.Join(repo.Hoster, repo.Owner, repo.Name) repo.Name = path.Join(repo.Hoster, repo.Owner, repo.Name)
} }
if l.Bare { if l.Bare || l.Mirror {
repo.Name += ".git" repo.Name += ".git"
} }
@ -329,12 +329,12 @@ func updateRepository(reponame string, auth transport.AuthMethod, dry bool, l ty
sub.Info(). sub.Info().
Msgf("pulling %s", types.Green(reponame)) Msgf("pulling %s", types.Green(reponame))
err = gitc.Pull(l.Bare, filepath.Join(l.Path, reponame)) err = gitc.Pull(l.Bare, l.Mirror, filepath.Join(l.Path, reponame))
if err != nil { if err != nil {
return err return err
} }
if l.Bare { if l.Bare || l.Mirror {
sub.Info(). sub.Info().
Msgf("fetching lfs files for %s", types.Green(reponame)) Msgf("fetching lfs files for %s", types.Green(reponame))
@ -355,7 +355,7 @@ func updateRepository(reponame string, auth transport.AuthMethod, dry bool, l ty
} }
sub.Info(). sub.Info().
Msgf("pulling %s", types.Green(reponame)) Msgf("pulling %s", types.Green(reponame))
if !l.Bare { if !l.Bare && !l.Mirror {
w, err := r.Worktree() w, err := r.Worktree()
if err != nil { if err != nil {
if err == git.NoErrAlreadyUpToDate { if err == git.NoErrAlreadyUpToDate {
@ -440,12 +440,12 @@ func cloneRepository(repo types.Repo, auth transport.AuthMethod, dry bool, l typ
} }
} }
err = gitc.Clone(url, filepath.Join(l.Path, repo.Name), l.Bare) err = gitc.Clone(url, filepath.Join(l.Path, repo.Name), l.Bare, l.Mirror)
if err != nil { if err != nil {
return err return err
} }
if l.Bare { if l.Bare || l.Mirror {
sub.Info(). sub.Info().
Msgf("fetching lfs files for %s", types.Green(repo.Name)) Msgf("fetching lfs files for %s", types.Green(repo.Name))
@ -460,6 +460,7 @@ func cloneRepository(repo types.Repo, auth transport.AuthMethod, dry bool, l typ
URL: url, URL: url,
Auth: auth, Auth: auth,
SingleBranch: false, SingleBranch: false,
Mirror: l.Mirror,
}) })
if err != nil { if err != nil {
return err return err
@ -548,7 +549,7 @@ func TempClone(repo types.Repo, tempdir string) (*git.Repository, error) {
repo.URL = strings.Replace(repo.URL, "https://", fmt.Sprintf("https://xyz:%s@", repo.Token), -1) repo.URL = strings.Replace(repo.URL, "https://", fmt.Sprintf("https://xyz:%s@", repo.Token), -1)
} }
err = gitc.Clone(repo.URL, tempdir, false) err = gitc.Clone(repo.URL, tempdir, false, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -47,6 +47,7 @@ func (dest Destination) Count() int {
// Local TODO. // Local TODO.
type Local struct { type Local struct {
Bare bool `yaml:"bare"` Bare bool `yaml:"bare"`
Mirror bool `yaml:"mirror" default:"false"`
Path string `yaml:"path"` Path string `yaml:"path"`
Structured bool `yaml:"structured"` Structured bool `yaml:"structured"`
Zip bool `yaml:"zip"` Zip bool `yaml:"zip"`