diff options
Diffstat (limited to 'java/com/google/gerrit/server/project/CreateRefControl.java')
-rw-r--r-- | java/com/google/gerrit/server/project/CreateRefControl.java | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/java/com/google/gerrit/server/project/CreateRefControl.java b/java/com/google/gerrit/server/project/CreateRefControl.java index 54ab628ccb..ab134b50ce 100644 --- a/java/com/google/gerrit/server/project/CreateRefControl.java +++ b/java/com/google/gerrit/server/project/CreateRefControl.java @@ -69,8 +69,9 @@ public class CreateRefControl { * * @param user the user performing the operation * @param repo repository on which user want to create - * @param branch the branch the new {@link RevObject} should be created on + * @param destBranch the branch the new {@link RevObject} should be created on * @param object the object the user will start the reference with + * @param sourceBranches the source ref from which the new ref is created from * @throws AuthException if creation is denied; the message explains the denial. * @throws PermissionBackendException on failure of permission checks. * @throws ResourceConflictException if the project state does not permit the operation @@ -78,25 +79,46 @@ public class CreateRefControl { public void checkCreateRef( Provider<? extends CurrentUser> user, Repository repo, - BranchNameKey branch, + BranchNameKey destBranch, RevObject object, - boolean forPush) + boolean forPush, + BranchNameKey... sourceBranches) throws AuthException, PermissionBackendException, NoSuchProjectException, IOException, ResourceConflictException { ProjectState ps = - projectCache.get(branch.project()).orElseThrow(noSuchProject(branch.project())); + projectCache.get(destBranch.project()).orElseThrow(noSuchProject(destBranch.project())); ps.checkStatePermitsWrite(); - PermissionBackend.ForRef perm = permissionBackend.user(user.get()).ref(branch); + PermissionBackend.ForRef perm = permissionBackend.user(user.get()).ref(destBranch); if (object instanceof RevCommit) { perm.check(RefPermission.CREATE); - checkCreateCommit(user, repo, (RevCommit) object, ps.getNameKey(), perm, forPush); + if (sourceBranches.length == 0) { + checkCreateCommit(user, repo, (RevCommit) object, ps.getNameKey(), perm, forPush); + } else { + for (BranchNameKey src : sourceBranches) { + PermissionBackend.ForRef forRef = permissionBackend.user(user.get()).ref(src); + if (forRef.testOrFalse(RefPermission.READ)) { + return; + } + } + AuthException e = + new AuthException( + String.format( + "must have %s on existing ref to create new ref from it", + RefPermission.READ.describeForException())); + e.setAdvice( + String.format( + "use an existing ref visible to you, or get %s permission on the ref", + RefPermission.READ.describeForException())); + throw e; + } } else if (object instanceof RevTag) { RevTag tag = (RevTag) object; try (RevWalk rw = new RevWalk(repo)) { rw.parseBody(tag); } catch (IOException e) { - logger.atSevere().withCause(e).log("RevWalk(%s) parsing %s:", branch.project(), tag.name()); + logger.atSevere().withCause(e).log( + "RevWalk(%s) parsing %s:", destBranch.project(), tag.name()); throw e; } @@ -112,12 +134,12 @@ public class CreateRefControl { if (target instanceof RevCommit) { checkCreateCommit(user, repo, (RevCommit) target, ps.getNameKey(), perm, forPush); } else { - checkCreateRef(user, repo, branch, target, forPush); + checkCreateRef(user, repo, destBranch, target, forPush); } // If the tag has a PGP signature, allow a lower level of permission // than if it doesn't have a PGP signature. - PermissionBackend.ForRef forRef = permissionBackend.user(user.get()).ref(branch); + PermissionBackend.ForRef forRef = permissionBackend.user(user.get()).ref(destBranch); if (tag.getRawGpgSignature() != null) { forRef.check(RefPermission.CREATE_SIGNED_TAG); } else { |