feat(sync-gcsr): Synchronise all remote branches

Explicitly sets all local branches to all equivalent remote branches
after each update.

Branches deleted on the remote will eventually disappear when the
container is restarted.
This commit is contained in:
Vincent Ambo 2019-12-30 05:06:46 +01:00
parent 7c52a205ee
commit 36beb6d43c

View file

@ -12,6 +12,7 @@ import (
"time" "time"
git "gopkg.in/src-d/go-git.v4" git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/transport/http" "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
) )
@ -24,8 +25,43 @@ func EnvOr(key, def string) string {
return v return v
} }
func updateRepo(repo *git.Repository, tree *git.Worktree, opts *git.PullOptions) error { // ensure that all remote branches exist locally & are up to date.
err := tree.Pull(opts) func updateBranches(auth *http.BasicAuth, repo *git.Repository) error {
origin, err := repo.Remote("origin")
if err != nil {
return err
}
refs, err := origin.List(&git.ListOptions{
Auth: auth,
})
if err != nil {
return err
}
for _, ref := range refs {
if !ref.Name().IsBranch() || ref.Type() != plumbing.HashReference {
continue
}
branch := plumbing.NewHashReference(
plumbing.NewBranchReferenceName(ref.Name().Short()),
ref.Hash(),
)
err := repo.Storer.SetReference(branch)
if err != nil {
return err
}
log.Println("Updated branch", ref.Name().String())
}
return nil
}
func updateRepo(auth *http.BasicAuth, repo *git.Repository, opts *git.FetchOptions) error {
err := repo.Fetch(opts)
if err == git.NoErrAlreadyUpToDate { if err == git.NoErrAlreadyUpToDate {
// nothing to do ... // nothing to do ...
return nil return nil
@ -33,8 +69,8 @@ func updateRepo(repo *git.Repository, tree *git.Worktree, opts *git.PullOptions)
return err return err
} }
log.Println("Updated local repository mirror") log.Println("Fetched updates from remote, updating local branches")
return nil return updateBranches(auth, repo)
} }
func cloneRepo(dest, project, repo string, auth *http.BasicAuth) (*git.Repository, error) { func cloneRepo(dest, project, repo string, auth *http.BasicAuth) (*git.Repository, error) {
@ -43,13 +79,13 @@ func cloneRepo(dest, project, repo string, auth *http.BasicAuth) (*git.Repositor
URL: fmt.Sprintf("https://source.developers.google.com/p/%s/r/%s", project, repo), URL: fmt.Sprintf("https://source.developers.google.com/p/%s/r/%s", project, repo),
} }
handle, err := git.PlainClone(dest, false, &cloneOpts) handle, err := git.PlainClone(dest, true, &cloneOpts)
if err == git.ErrRepositoryAlreadyExists { if err == git.ErrRepositoryAlreadyExists {
handle, err = git.PlainOpen(dest) handle, err = git.PlainOpen(dest)
} }
return handle, err return handle, updateBranches(auth, handle)
} }
func main() { func main() {
@ -78,20 +114,16 @@ func main() {
log.Println("Initiating update loop") log.Println("Initiating update loop")
} }
tree, err := handle.Worktree() fetchOpts := git.FetchOptions{
if err != nil {
log.Fatalln("Failed to open repository worktree:", err)
}
pullOpts := git.PullOptions{
Auth: auth, Auth: auth,
Force: true, Force: true,
} }
for { for {
if err = updateRepo(handle, tree, &pullOpts); err != nil { if err = updateRepo(auth, handle, &fetchOpts); err != nil {
log.Fatalf("Failed to pull updated repository: %s", err) log.Fatalf("Failed to pull updated repository: %s", err)
} }
time.Sleep(30 * time.Second) // TODO(tazjin): Config option for pull interval?
time.Sleep(10 * time.Second)
} }
} }