about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2019-12-30T04·06+0100
committerVincent Ambo <tazjin@google.com>2019-12-30T04·06+0100
commit36beb6d43ccfd551c64d0aeaddae47ec3cff0afe (patch)
tree48a16f87989889beb1e55287dc0c9f8ee06e27d8
parent7c52a205ee3c1df423de0c63b30e666815824839 (diff)
feat(sync-gcsr): Synchronise all remote branches r/318
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.
-rw-r--r--ops/sync-gcsr/main.go60
1 files changed, 46 insertions, 14 deletions
diff --git a/ops/sync-gcsr/main.go b/ops/sync-gcsr/main.go
index 358c548055..a02f6d5527 100644
--- a/ops/sync-gcsr/main.go
+++ b/ops/sync-gcsr/main.go
@@ -12,6 +12,7 @@ import (
 	"time"
 
 	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"
 )
 
@@ -24,8 +25,43 @@ func EnvOr(key, def string) string {
 	return v
 }
 
-func updateRepo(repo *git.Repository, tree *git.Worktree, opts *git.PullOptions) error {
-	err := tree.Pull(opts)
+// ensure that all remote branches exist locally & are up to date.
+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 {
 		// nothing to do ...
 		return nil
@@ -33,8 +69,8 @@ func updateRepo(repo *git.Repository, tree *git.Worktree, opts *git.PullOptions)
 		return err
 	}
 
-	log.Println("Updated local repository mirror")
-	return nil
+	log.Println("Fetched updates from remote, updating local branches")
+	return updateBranches(auth, repo)
 }
 
 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),
 	}
 
-	handle, err := git.PlainClone(dest, false, &cloneOpts)
+	handle, err := git.PlainClone(dest, true, &cloneOpts)
 
 	if err == git.ErrRepositoryAlreadyExists {
 		handle, err = git.PlainOpen(dest)
 	}
 
-	return handle, err
+	return handle, updateBranches(auth, handle)
 }
 
 func main() {
@@ -78,20 +114,16 @@ func main() {
 		log.Println("Initiating update loop")
 	}
 
-	tree, err := handle.Worktree()
-	if err != nil {
-		log.Fatalln("Failed to open repository worktree:", err)
-	}
-
-	pullOpts := git.PullOptions{
+	fetchOpts := git.FetchOptions{
 		Auth:  auth,
 		Force: true,
 	}
 
 	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)
 		}
-		time.Sleep(30 * time.Second) //  TODO(tazjin): Config option for pull interval?
+
+		time.Sleep(10 * time.Second)
 	}
 }