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 ]