Introduce globalrefdb update-ref command
Allow the Gerrit admin to update refs on the global-refdb
in the same way he can update refs on the local one, using
a command similar to 'git update-ref'.
This allows to resolve split-brains situations with a
simple command line, without having to connect directly
to the global-refdb implementation console backend.
Change-Id: Ice02d4faa08ac3c275eb241d3a8249e46bede516
diff --git a/multi-primary/globalrefdb.groovy b/multi-primary/globalrefdb.groovy
index 89d4412..33ee85d 100644
--- a/multi-primary/globalrefdb.groovy
+++ b/multi-primary/globalrefdb.groovy
@@ -34,7 +34,12 @@
}
void error(String msg) {
- stderr.println msg
+ stderr.println "[ERROR] $msg"
+ stderr.flush()
+ }
+
+ void warning(String msg) {
+ stderr.println "[WARNING] $msg"
stderr.flush()
}
}
@@ -120,5 +125,48 @@
}
}
-commands = [ ProjectRefsCheck ]
+@Export("update-ref")
+@CommandMetaData(description = "Update the global-refdb ref name/value for a project")
+@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
+class ProjectRefsUpdate extends BaseSshCommand {
+
+ @Argument(index = 0, usage = "Project name", metaVar = "PROJECT", required = true)
+ String project
+
+ @Argument(index = 1, usage = "Ref name", metaVar = "REF", required = true)
+ String ref
+
+ @Argument(index = 2, usage = "New value", metaVar = "NEWVALUE", required = true)
+ String newValue
+
+ @Inject
+ GitRepositoryManager repoMgr
+
+ @Inject
+ DynamicItem<GlobalRefDatabase> globalRefDb
+
+ public void run() {
+ try {
+ def projectName = Project.nameKey(project)
+
+ repoMgr.openRepository(projectName).with { repo ->
+ if (!repo.refDatabase.exactRef(ref)) {
+ warning "Local project $project does not have $ref"
+ }
+ def currValue = globalRefDb.get().get(projectName, ref, String.class)
+ if (currValue.isEmpty()) {
+ error "Global-refdb for project $project does not have $ref"
+ } else {
+ println "Updating global-refdb ref for /$project/$ref ${currValue.get()} => $newValue ... "
+ def updateDone = globalRefDb.get().compareAndPut(projectName, ref, currValue.get(), newValue)
+ println "Result: /$project/$ref global-refdb update has ${updateDone ? 'SUCCEEDED':'FAILED'}"
+ }
+ }
+ } catch (RepositoryNotFoundException e) {
+ error "Project $project not found"
+ }
+ }
+}
+
+commands = [ ProjectRefsCheck, ProjectRefsUpdate ]