Merge branch 'stable-2.11' into master
* origin/stable-2.11:
Fix buck test in standalone BUCK build
Add standalone BUCK build
Change-Id: Id849e37156268a04f125bff3b59c804427bbaa04
diff --git a/BUCK b/BUCK
index 26aafae..17cda8a 100644
--- a/BUCK
+++ b/BUCK
@@ -18,7 +18,7 @@
resources = glob(['src/main/resources/**/*']),
manifest_entries = [
'Implementation-Title: Ref Protection plugin',
- 'Implementation-URL: http://review-plus.sonyericsson.net/#/admin/projects/gerrit/plugins/ref-protection',
+ 'Implementation-URL: http://gerrit.googlesource.com/plugins/ref-protection',
'Gerrit-PluginName: ref-protection',
'Gerrit-Module: com.googlesource.gerrit.plugins.refprotection.RefProtectionModule'
],
diff --git a/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupBranch.java b/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupBranch.java
deleted file mode 100644
index dbed47a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupBranch.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * The MIT License
- *
- * Copyright 2015 Sony Mobile Communications AB. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package com.googlesource.gerrit.plugins.refprotection;
-
-import static org.eclipse.jgit.lib.Constants.R_HEADS;
-import static org.eclipse.jgit.lib.Constants.R_REFS;
-import static org.eclipse.jgit.lib.Constants.R_TAGS;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-public class BackupBranch {
- public static final String R_BACKUPS = R_REFS + "backups/";
-
- public static String get(String branchName) {
- if (branchName.startsWith(R_HEADS) || branchName.startsWith(R_TAGS)) {
- return String.format("%s-%s",
- R_BACKUPS + branchName.replaceFirst(R_REFS, ""),
- new SimpleDateFormat("YYYYMMdd-HHmmss").format(new Date()));
- }
-
- return branchName;
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java b/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java
new file mode 100644
index 0000000..af075c9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/refprotection/BackupRef.java
@@ -0,0 +1,214 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2015 Sony Mobile Communications AB. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.googlesource.gerrit.plugins.refprotection;
+
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.events.RefUpdatedEvent;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.CreateBranch;
+import com.google.gerrit.server.project.ProjectResource;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+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.RevTag;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.eclipse.jgit.lib.Constants.R_REFS;
+import static org.eclipse.jgit.lib.Constants.R_TAGS;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class BackupRef {
+ public static final String R_BACKUPS = R_REFS + "backups/";
+ private static final Logger log =
+ LoggerFactory.getLogger(BackupRef.class);
+ private final CreateBranch.Factory createBranchFactory;
+ @Inject private static PluginConfigFactory cfg;
+ @Inject private static GitRepositoryManager repoManager;
+ @Inject @PluginName private static String pluginName;
+
+ @Inject
+ BackupRef(CreateBranch.Factory createBranchFactory) {
+ this.createBranchFactory = createBranchFactory;
+ }
+
+ public void createBackup(RefUpdatedEvent event, ProjectResource project) {
+ String refName = event.getRefName();
+
+ try (Repository git = repoManager.openRepository(project.getNameKey())) {
+ String backupRef = get(project, refName);
+
+ // 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";
+ String fullMessage = "";
+ if (event.refUpdate.refName.startsWith(R_TAGS)) {
+ type = "tag";
+ try {
+ RevTag origTag =
+ revWalk.parseTag(ObjectId.fromString(event.refUpdate.oldRev));
+ SimpleDateFormat format = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy ZZZZ");
+ PersonIdent taggerIdent = origTag.getTaggerIdent();
+ String tagger =
+ String.format("Tagger: %s <%s>\nDate: %s",
+ taggerIdent.getName(), taggerIdent.getEmailAddress(),
+ format.format(taggerIdent.getWhen()));
+ fullMessage = "\n\nOriginal tag:\n" + tagger + "\n\n" + origTag.getFullMessage();
+ } catch (MissingObjectException e) {
+ log.warn("Original tag does not exist", e);
+ } catch (IncorrectObjectTypeException e) {
+ log.warn("Original tag was not a tag", e);
+ } catch (IOException e) {
+ log.warn("Unable to read original tag details", e);
+ }
+ }
+ tag.setMessage(update + " " + type + " " + event.refUpdate.refName + fullMessage);
+ 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("Could not open repository", e);
+ }
+ }
+
+ static String get(ProjectResource project, String refName) {
+ if (cfg.getFromGerritConfig(pluginName).getBoolean("useTimestamp", true)) {
+ return getTimestampBranch(refName);
+ }
+ else {
+ return getSequentialBranch(project, refName);
+ }
+ }
+
+ private static String getTimestampBranch(String refName) {
+ if (refName.startsWith(R_HEADS) || refName.startsWith(R_TAGS)) {
+ return String.format("%s-%s",
+ R_BACKUPS + refName.replaceFirst(R_REFS, ""),
+ new SimpleDateFormat("YYYYMMdd-HHmmss").format(new Date()));
+ }
+
+ return refName;
+ }
+
+ private static String getSequentialBranch(ProjectResource project, String branchName) {
+ Integer rev = 1;
+ String deletedName = branchName.replaceFirst(R_REFS, "");
+ try (Repository git = repoManager.openRepository(project.getNameKey())) {
+ for (Ref ref : git.getAllRefs().values()) {
+ String name = ref.getName();
+ if (name.startsWith(R_BACKUPS + deletedName + "/")) {
+ Integer thisNum =
+ Integer.parseInt(name.substring(name.lastIndexOf('/') + 1));
+ if (thisNum >= rev) {
+ rev = thisNum + 1;
+ }
+ }
+ }
+ } catch (RepositoryNotFoundException e) {
+ log.error("Repository does not exist", e);
+ } catch (IOException e) {
+ log.error("Could not determine latest revision of deleted branch", e);
+ }
+
+ return R_BACKUPS + deletedName + "/" + rev;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefProtectionModule.java b/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefProtectionModule.java
index 96d250c..b2700c7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefProtectionModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefProtectionModule.java
@@ -23,14 +23,15 @@
*/
package com.googlesource.gerrit.plugins.refprotection;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.common.EventListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.inject.AbstractModule;
public class RefProtectionModule extends AbstractModule {
@Override
protected void configure() {
- DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(
+ DynamicSet.bind(binder(), EventListener.class).to(
RefUpdateListener.class);
+ requestStaticInjection(BackupRef.class);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefUpdateListener.java b/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefUpdateListener.java
index 09d9c94..0ca08f4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefUpdateListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/refprotection/RefUpdateListener.java
@@ -26,14 +26,14 @@
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.common.EventListener;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.events.Event;
+import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.CreateBranch;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.ProjectResource;
@@ -49,75 +49,62 @@
import java.io.IOException;
-class RefUpdateListener implements GitReferenceUpdatedListener {
+class RefUpdateListener implements EventListener {
private static final Logger log =
LoggerFactory.getLogger(RefUpdateListener.class);
- private final CreateBranch.Factory createBranchFactory;
private final ProjectControl.GenericFactory projectControl;
private final CurrentUser user;
private final GitRepositoryManager repoManager;
+ private final BackupRef backupRef;
+ private final boolean protectDeleted;
+ private final boolean protectFastForward;
@Inject
- RefUpdateListener(CreateBranch.Factory createBranchFactory,
- ProjectControl.GenericFactory p,
+ RefUpdateListener(ProjectControl.GenericFactory p,
CurrentUser user,
- GitRepositoryManager repoManager) {
- this.createBranchFactory = createBranchFactory;
+ GitRepositoryManager repoManager,
+ BackupRef backupRef,
+ PluginConfigFactory cfg,
+ @PluginName String pluginName) {
this.projectControl = p;
this.user = user;
this.repoManager = repoManager;
+ this.backupRef = backupRef;
+ this.protectDeleted =
+ cfg.getFromGerritConfig(pluginName).getBoolean("protectDeleted", true);
+ this.protectFastForward =
+ cfg.getFromGerritConfig(pluginName).getBoolean("protectFastForward", true);
}
@Override
- public void onGitReferenceUpdated(final Event event) {
- if (isRelevantRef(event)) {
- Project.NameKey nameKey = new Project.NameKey(event.getProjectName());
- try {
- ProjectResource project =
- new ProjectResource(projectControl.controlFor(nameKey, user));
- if (isRefDeleted(event) || isNonFastForwardUpdate(event, project)) {
- createBackupBranch(event, project);
+ public void onEvent(Event event) {
+ if (event instanceof RefUpdatedEvent) {
+ RefUpdatedEvent refUpdate = (RefUpdatedEvent)event;
+ if ((protectDeleted || protectFastForward) && isRelevantRef(refUpdate)) {
+ Project.NameKey nameKey = refUpdate.getProjectNameKey();
+ try {
+ ProjectResource project =
+ new ProjectResource(projectControl.controlFor(nameKey, user));
+ if ((protectDeleted && isRefDeleted(refUpdate))
+ || (protectFastForward && isNonFastForwardUpdate(refUpdate,
+ project))) {
+ backupRef.createBackup(refUpdate, project);
+ }
+ } catch (NoSuchProjectException | IOException e) {
+ log.error(e.getMessage(), e);
}
- } catch (NoSuchProjectException | IOException e) {
- log.error(e.getMessage(), e);
}
}
}
/**
- * Create a backup branch for the given ref.
- *
- * @param event the Event
- */
- private void createBackupBranch(Event event, ProjectResource project) {
- String branchName = event.getRefName();
- String backupRef = BackupBranch.get(branchName);
-
- // No-op if the backup branch name is same as the original
- if (backupRef.equals(branchName)) {
- return;
- }
-
- CreateBranch.Input input = new CreateBranch.Input();
- input.ref = backupRef;
- input.revision = event.getOldObjectId();
-
- try {
- createBranchFactory.create(backupRef).apply(project, input);
- } catch (BadRequestException | AuthException | ResourceConflictException
- | IOException e) {
- log.error(e.getMessage(), e);
- }
- }
-
- /**
* Is the event on a relevant ref?
*
* @param event the Event
* @return True if relevant, otherwise False.
*/
- private boolean isRelevantRef(Event event) {
+ private boolean isRelevantRef(RefUpdatedEvent event) {
return (!isNewRef(event)) &&
(event.getRefName().startsWith(R_HEADS)
|| event.getRefName().startsWith(R_TAGS));
@@ -129,8 +116,8 @@
* @param event the Event
* @return True if a new ref, otherwise False.
*/
- private boolean isNewRef(Event event) {
- return event.getOldObjectId().equals(ObjectId.zeroId().getName());
+ private boolean isNewRef(RefUpdatedEvent event) {
+ return event.refUpdate.oldRev.equals(ObjectId.zeroId().getName());
}
/**
@@ -139,11 +126,11 @@
* @param event the Event
* @return True if a ref deletion, otherwise False.
*/
- private boolean isRefDeleted(Event event) {
- if (event.getNewObjectId().equals(ObjectId.zeroId().getName())) {
+ private boolean isRefDeleted(RefUpdatedEvent event) {
+ if (event.refUpdate.newRev.equals(ObjectId.zeroId().getName())) {
log.info(String.format(
"Ref Deleted: project [%s] refname [%s] old object id [%s]",
- event.getProjectName(), event.getRefName(), event.getOldObjectId()));
+ event.getProjectNameKey().toString(), event.getRefName(), event.refUpdate.oldRev));
return true;
}
return false;
@@ -155,14 +142,19 @@
* @param event the Event
* @return True if a non-fast-forward update, otherwise False.
*/
- private boolean isNonFastForwardUpdate(Event event, ProjectResource project)
+ private boolean isNonFastForwardUpdate(RefUpdatedEvent event, ProjectResource project)
throws RepositoryNotFoundException, IOException {
+ if (isRefDeleted(event)) {
+ // Can't be non-fast-forward if the ref was deleted, and
+ // attempting a check would cause a MissingObjectException.
+ return false;
+ }
try (Repository repo = repoManager.openRepository(project.getNameKey())) {
try (RevWalk walk = new RevWalk(repo)) {
RevCommit oldCommit =
- walk.parseCommit(repo.resolve(event.getOldObjectId()));
+ walk.parseCommit(repo.resolve(event.refUpdate.oldRev));
RevCommit newCommit =
- walk.parseCommit(repo.resolve(event.getNewObjectId()));
+ walk.parseCommit(repo.resolve(event.refUpdate.newRev));
return !walk.isMergedInto(oldCommit, newCommit);
}
}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index c681000..4d2d541 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -1,10 +1,24 @@
Ref protection plugin.
-Protects against commits being lost by creating backups of deleted refs under
-the `refs/backups/` namespace.
+Protects against commits being lost by creating backups of deleted refs
+(or non-fast-forward commits) under the `refs/backups/` namespace.
+
+Branch deletion protection can be disabled by setting
+`plugin.ref-protection.protectDeleted false` in `gerrit.config`.
+Similarly, non-fast-forward update protection can be disabled with
+`plugin.ref-protection.protectFastForward false`.
Branches under `refs/heads/` that are deleted or rewritten are backed up
-as `refs/backups/heads/branch-name-YYYYMMDD-HHmmss`.
+as `refs/backups/heads/branch-name-YYYYMMDD-HHmmss` by default, or as
+sequentially increasing numbers under `refs/backups/heads/branch-name/#`
+by setting `plugin.ref-protection.useTimestamp false`.
Tags under `refs/tags/` that are deleted are backed up (as branches) as
-`refs/backups/tags/tag-name-YYYYMMDD-HHmmss`.
+`refs/backups/tags/tag-name-YYYYMMDD-HHmmss` or as sequentially
+increasing numbers under `refs/backups/tags/branch-name/#` using the same
+`plugin.ref-protection.useTimestamp` setting.
+
+By default, the backups are created as branches. Optionally, they may
+be created as tags, containing information about the original ref that
+was changed, as well as the user that performed the change. This can
+be enabled by setting `plugin.ref-protection.createTag true`.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupBranchNameTest.java b/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupBranchNameTest.java
deleted file mode 100644
index b2bc9a2..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupBranchNameTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.googlesource.gerrit.plugins.refprotection;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-
-public class BackupBranchNameTest {
-
- @Test
- public void backupBranchNameForTag() throws Exception {
- String name = BackupBranch.get("refs/tags/v1.0");
- String expected_prefix = BackupBranch.R_BACKUPS + "tags/v1.0-";
- assertThat(name).startsWith(expected_prefix);
- }
-
- @Test
- public void backupBranchNameForBranch() throws Exception {
- String name = BackupBranch.get("refs/heads/master");
- String expected_prefix = BackupBranch.R_BACKUPS + "heads/master-";
- assertThat(name).startsWith(expected_prefix);
- }
-
- @Test
- public void backupBranchNameForUnsupportedNamespace() throws Exception {
- String ref = "refs/changes/45/12345/1";
- assertThat(BackupBranch.get(ref)).isEqualTo(ref);
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupRefNameTest.java b/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupRefNameTest.java
new file mode 100644
index 0000000..d38f3b5
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/refprotection/BackupRefNameTest.java
@@ -0,0 +1,28 @@
+package com.googlesource.gerrit.plugins.refprotection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+
+public class BackupRefNameTest {
+
+ @Test
+ public void backupTimestampRefNameForTag() throws Exception {
+ String name = BackupRef.get(null, "refs/tags/v1.0");
+ String expected_prefix = BackupRef.R_BACKUPS + "tags/v1.0-";
+ assertThat(name).startsWith(expected_prefix);
+ }
+
+ @Test
+ public void backupTimestampRefNameForBranch() throws Exception {
+ String name = BackupRef.get(null, "refs/heads/master");
+ String expected_prefix = BackupRef.R_BACKUPS + "heads/master-";
+ assertThat(name).startsWith(expected_prefix);
+ }
+
+ @Test
+ public void backupTimestampRefNameForUnsupportedNamespace() throws Exception {
+ String ref = "refs/changes/45/12345/1";
+ assertThat(BackupRef.get(null, ref)).isEqualTo(ref);
+ }
+}