Add ability to back up as tag This creates the functionality required to create a tag instead of a branch, which also allows us to store audit information, such as who triggered the deletion or the push. Change-Id: I31fd05675a33a6eba20dd7cf6a3703fbfd981ead
diff --git a/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java b/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java index aab80bb..93f0227 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java +++ b/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java
@@ -36,8 +36,13 @@ import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.TagBuilder; import org.eclipse.jgit.revwalk.RevWalk; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,32 +71,81 @@ public void createBackup(RefUpdatedEvent event, ProjectResource project) { String refName = event.getRefName(); - String backupRef = get(project, refName); - - // No-op if the backup branch name is same as the original - if (backupRef.equals(refName)) { - return; - } try (Repository git = repoManager.openRepository(project.getNameKey())) { - try (RevWalk revWalk = new RevWalk(git)) { - CreateBranch.Input input = new CreateBranch.Input(); - input.ref = backupRef; - // We need to parse the commit to ensure if it's a tag, we get the - // commit the tag points to! - input.revision = - ObjectId.toString(revWalk.parseCommit(ObjectId.fromString(event.refUpdate.oldRev)) - .getId()); + String backupRef = get(project, refName); - try { - createBranchFactory.create(backupRef).apply(project, input); - } catch (BadRequestException | AuthException | ResourceConflictException - | IOException e) { - log.error(e.getMessage(), e); + // No-op if the backup branch name is same as the original + if (backupRef.equals(refName)) { + return; + } + + try (RevWalk revWalk = new RevWalk(git)) { + if (cfg.getFromGerritConfig(pluginName).getBoolean("createTag", + false)) { + TagBuilder tag = new TagBuilder(); + tag.setTagger( + new PersonIdent(event.submitter.name, event.submitter.email)); + tag.setObjectId(revWalk + .parseCommit(ObjectId.fromString(event.refUpdate.oldRev))); + String update = "Non-fast-forward update to"; + if (event.refUpdate.newRev.equals(ObjectId.zeroId().getName())) { + update = "Deleted"; + } + String type = "branch"; + if (event.refUpdate.refName.startsWith(R_TAGS)) { + type = "tag"; + } + tag.setMessage(update + " " + type + " " + event.refUpdate.refName); + tag.setTag(backupRef); + + ObjectInserter inserter = git.newObjectInserter(); + ObjectId tagId = inserter.insert(tag); + inserter.flush(); + RefUpdate tagRef = git.updateRef(tag.getTag()); + tagRef.setNewObjectId(tagId); + tagRef.setRefLogMessage("tagged deleted branch/tag " + tag.getTag(), + false); + tagRef.setForceUpdate(false); + Result result = tagRef.update(); + switch (result) { + case NEW: + case FORCED: + log.debug("Successfully created backup tag"); + break; + + case LOCK_FAILURE: + log.error("Failed to lock repository while creating backup tag"); + break; + + case REJECTED: + log.error("Tag already exists while creating backup tag"); + break; + + default: + log.error("Unknown error while creating backup tag"); + } + } else { + CreateBranch.Input input = new CreateBranch.Input(); + input.ref = backupRef; + // We need to parse the commit to ensure if it's a tag, we get the + // commit the tag points to! + input.revision = ObjectId.toString( + revWalk.parseCommit(ObjectId.fromString(event.refUpdate.oldRev)) + .getId()); + + try { + createBranchFactory.create(backupRef).apply(project, input); + } catch (BadRequestException | AuthException + | ResourceConflictException | IOException e) { + log.error(e.getMessage(), e); + } } } + } catch (RepositoryNotFoundException e) { + log.error("Repository does not exist", e); } catch (IOException e) { - log.error(e.getMessage(), e); + log.error("Could not open repository", e); } }