Permalink
Browse files

Allow admins to update symbolic references

Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
  • Loading branch information...
puiterwijk committed Dec 12, 2018
1 parent 409972a commit eba185510f2c5a27f7e23ee9dfb8f23042600069
Showing with 105 additions and 6 deletions.
  1. +59 −2 functional_tests/repomgmt_test.go
  2. +21 −1 server/cmd/admin-repo-edit.go
  3. +1 −0 server/datastructures/admin.go
  4. +24 −3 server/service/statestore.go
@@ -8,8 +8,9 @@ import (
)

type testRepoInfo struct {
name string
public bool
name string
public bool
symrefs map[string]string
}

func verifyReposExist(t *testing.T, node nodeNrType, repos ...testRepoInfo) {
@@ -32,6 +33,36 @@ func verifyReposExist(t *testing.T, node nodeNrType, repos ...testRepoInfo) {
repo.public,
)
}
if repo.symrefs == nil {
// Default: HEAD -> refs/heads/master
if len(retrieved.Symrefs) != 1 {
t.Errorf("Unexpected number of symrefs retrieved: %d", len(retrieved.Symrefs))
}
target, ok := retrieved.Symrefs["HEAD"]
if !ok {
t.Errorf("Unable to find HEAD")
} else {
if target != "refs/heads/master" {
t.Errorf("HEAD pointed to %s instead of master", target)
}
}
} else {
for symref, correcttarget := range repo.symrefs {
target, hasref := retrieved.Symrefs[symref]
if !hasref {
t.Errorf("Missing symref %s", symref)
continue
}

if target != correcttarget {
t.Errorf("Symref %s points to %s instead of %s", symref, target, correcttarget)
}
}

if len(retrieved.Symrefs) != len(repo.symrefs) {
t.Error("Too many symrefs returned")
}
}
}

if len(repos) != len(repolist.Repos) {
@@ -93,6 +124,32 @@ func TestRepoManagement(t *testing.T) {
verifyReposExist(t, nodeb, r1, r2, r3)
verifyReposExist(t, nodec, r1, r2, r3)

// Create a symrefs
runCommand(t, nodea.Name(),
"admin", "repo", "edit", "test1", "foo=bar")
r1.symrefs = make(map[string]string)
r1.symrefs["HEAD"] = "refs/heads/master"
r1.symrefs["foo"] = "bar"
verifyReposExist(t, nodea, r1, r2, r3)
verifyReposExist(t, nodeb, r1, r2, r3)
verifyReposExist(t, nodec, r1, r2, r3)

// Update a symref
runCommand(t, nodea.Name(),
"admin", "repo", "edit", "test1", "HEAD=refs/foo/nobody")
r1.symrefs["HEAD"] = "refs/foo/nobody"
verifyReposExist(t, nodea, r1, r2, r3)
verifyReposExist(t, nodeb, r1, r2, r3)
verifyReposExist(t, nodec, r1, r2, r3)

// Delete a symref
runCommand(t, nodea.Name(),
"admin", "repo", "edit", "test1", "HEAD=")
delete(r1.symrefs, "HEAD")
verifyReposExist(t, nodea, r1, r2, r3)
verifyReposExist(t, nodeb, r1, r2, r3)
verifyReposExist(t, nodec, r1, r2, r3)

// Delete test3
runCommand(t, nodec.Name(),
"admin", "repo", "delete", "test3")
@@ -16,7 +16,7 @@ var adminEditRepoCmd = &cobra.Command{
Short: "Repo editing",
Long: `Edit a repository.`,
Run: runAdminEditRepo,
Args: cobra.ExactArgs(1),
Args: cobra.MinimumNArgs(1),
}

func addHook(cmd *cobra.Command, req *datastructures.RepoUpdateRequest, reponame, flagname string) {
@@ -88,6 +88,26 @@ func runAdminEditRepo(cmd *cobra.Command, args []string) {
}
})

if len(args) > 1 {
// Parse symref updates
symrefupdate := make([]string, 0)

for _, arg := range args[1:] {
if !strings.Contains(arg, "=") {
fmt.Println("Symref rename argument", arg, "invalid: no = separator")
return
}
if strings.Contains(arg, " ") {
fmt.Println("Symref rename argument", arg, "invalid: contains space")
return
}

symrefupdate = append(symrefupdate, arg)
}

request.UpdateRequest[datastructures.RepoUpdateSymref] = strings.Join(symrefupdate, " ")
}

if len(request.UpdateRequest) == 0 {
fmt.Println("No update request provided")
return
@@ -36,6 +36,7 @@ const (
RepoUpdateHookPreReceive RepoUpdateField = "hook-prereceive"
RepoUpdateHookUpdate RepoUpdateField = "hook-update"
RepoUpdateHookPostReceive RepoUpdateField = "hook-postreceive"
RepoUpdateSymref RepoUpdateField = "update-symref"
)

type RepoUpdateRequest struct {
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path"
"strings"
"sync"
"time"

@@ -438,6 +439,24 @@ func (store *stateStore) unsubscribeRepoChangeRequest(repo string, crC chan *pb.
}
}

func (store *stateStore) applySymrefUpdate(repo datastructures.RepoInfo, symrefreq string) {
store.cfg.log.Errorf("Got symrefreq: %s", symrefreq)
updates := strings.Split(symrefreq, " ")

for _, update := range updates {
req := strings.SplitN(update, "=", 2)
store.cfg.log.Errorf("Req: %s", req)
symref := req[0]
target := req[1]

if target == "" {
delete(repo.Symrefs, symref)
} else {
repo.Symrefs[symref] = target
}
}
}

func (store *stateStore) applyUpdateRequest(reponame string, request datastructures.RepoUpdateRequest) {
repo := store.repoinfos[reponame]
for field, val := range request.UpdateRequest {
@@ -451,6 +470,8 @@ func (store *stateStore) applyUpdateRequest(reponame string, request datastructu
repo.Hooks.Update = val
case datastructures.RepoUpdateHookPostReceive:
repo.Hooks.PostReceive = val
case datastructures.RepoUpdateSymref:
store.applySymrefUpdate(repo, val)
}
}
store.repoinfos[reponame] = repo
@@ -582,7 +603,7 @@ func (store *stateStore) createRepo(repo string, public bool) error {
if err != nil {
return errors.Wrap(err, "Error marshalling newrepo request")
}
store.cfg.log.Info("Repo creation requested")
store.cfg.log.Infof("Repo creation requested of %s", repo)
crC := store.subscribeRepoChangeRequest(repo)
defer store.unsubscribeRepoChangeRequest(repo, crC)
store.proposeC <- out
@@ -608,7 +629,7 @@ func (store *stateStore) deleteRepo(repo string) error {
if err != nil {
return errors.Wrap(err, "Error marshalling deleterepo request")
}
store.cfg.log.Info("Repo deletion requested")
store.cfg.log.Infof("Repo deletion requested of %s", repo)
crC := store.subscribeRepoChangeRequest(repo)
defer store.unsubscribeRepoChangeRequest(repo, crC)
store.proposeC <- out
@@ -635,7 +656,7 @@ func (store *stateStore) editRepo(repo string, request []byte) error {
if err != nil {
return errors.Wrap(err, "Error marshalling editrepo request")
}
store.cfg.log.Info("Repo editing requested")
store.cfg.log.Infof("Repo editing requested on %s", repo)
crC := store.subscribeRepoChangeRequest(repo)
defer store.unsubscribeRepoChangeRequest(repo, crC)
store.proposeC <- out

0 comments on commit eba1855

Please sign in to comment.