diff options
Diffstat (limited to 'gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java')
-rw-r--r-- | gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java deleted file mode 100644 index 34c7534be2..0000000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright (C) 2014 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.change; - -import com.google.common.base.Strings; -import com.google.gerrit.extensions.common.DiffWebLinkInfo; -import com.google.gerrit.extensions.common.EditInfo; -import com.google.gerrit.extensions.registration.DynamicMap; -import com.google.gerrit.extensions.restapi.AcceptsCreate; -import com.google.gerrit.extensions.restapi.AcceptsDelete; -import com.google.gerrit.extensions.restapi.AcceptsPost; -import com.google.gerrit.extensions.restapi.AuthException; -import com.google.gerrit.extensions.restapi.BadRequestException; -import com.google.gerrit.extensions.restapi.BinaryResult; -import com.google.gerrit.extensions.restapi.ChildCollection; -import com.google.gerrit.extensions.restapi.DefaultInput; -import com.google.gerrit.extensions.restapi.IdString; -import com.google.gerrit.extensions.restapi.RawInput; -import com.google.gerrit.extensions.restapi.ResourceConflictException; -import com.google.gerrit.extensions.restapi.ResourceNotFoundException; -import com.google.gerrit.extensions.restapi.Response; -import com.google.gerrit.extensions.restapi.RestApiException; -import com.google.gerrit.extensions.restapi.RestModifyView; -import com.google.gerrit.extensions.restapi.RestReadView; -import com.google.gerrit.extensions.restapi.RestView; -import com.google.gerrit.reviewdb.client.Change; -import com.google.gerrit.reviewdb.client.PatchSet; -import com.google.gerrit.reviewdb.client.Project; -import com.google.gerrit.server.WebLinks; -import com.google.gerrit.server.edit.ChangeEdit; -import com.google.gerrit.server.edit.ChangeEditJson; -import com.google.gerrit.server.edit.ChangeEditModifier; -import com.google.gerrit.server.edit.ChangeEditUtil; -import com.google.gerrit.server.edit.UnchangedCommitMessageException; -import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.patch.PatchListNotAvailableException; -import com.google.gerrit.server.permissions.PermissionBackendException; -import com.google.gerrit.server.project.InvalidChangeOperationException; -import com.google.gerrit.server.project.ProjectCache; -import com.google.gwtorm.server.OrmException; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; -import com.google.inject.assistedinject.Assisted; -import java.io.IOException; -import java.util.List; -import java.util.Optional; -import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevWalk; -import org.kohsuke.args4j.Option; - -@Singleton -public class ChangeEdits - implements ChildCollection<ChangeResource, ChangeEditResource>, - AcceptsCreate<ChangeResource>, - AcceptsPost<ChangeResource>, - AcceptsDelete<ChangeResource> { - private final DynamicMap<RestView<ChangeEditResource>> views; - private final Create.Factory createFactory; - private final DeleteFile.Factory deleteFileFactory; - private final Provider<Detail> detail; - private final ChangeEditUtil editUtil; - private final Post post; - - @Inject - ChangeEdits( - DynamicMap<RestView<ChangeEditResource>> views, - Create.Factory createFactory, - Provider<Detail> detail, - ChangeEditUtil editUtil, - Post post, - DeleteFile.Factory deleteFileFactory) { - this.views = views; - this.createFactory = createFactory; - this.detail = detail; - this.editUtil = editUtil; - this.post = post; - this.deleteFileFactory = deleteFileFactory; - } - - @Override - public DynamicMap<RestView<ChangeEditResource>> views() { - return views; - } - - @Override - public RestView<ChangeResource> list() { - return detail.get(); - } - - @Override - public ChangeEditResource parse(ChangeResource rsrc, IdString id) - throws ResourceNotFoundException, AuthException, IOException, OrmException { - Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser()); - if (!edit.isPresent()) { - throw new ResourceNotFoundException(id); - } - return new ChangeEditResource(rsrc, edit.get(), id.get()); - } - - @Override - public Create create(ChangeResource parent, IdString id) throws RestApiException { - return createFactory.create(id.get()); - } - - @Override - public Post post(ChangeResource parent) throws RestApiException { - return post; - } - - /** - * Create handler that is activated when collection element is accessed but doesn't exist, e. g. - * PUT request with a path was called but change edit wasn't created yet. Change edit is created - * and PUT handler is called. - */ - @Override - public DeleteFile delete(ChangeResource parent, IdString id) throws RestApiException { - // It's safe to assume that id can never be null, because - // otherwise we would end up in dedicated endpoint for - // deleting of change edits and not a file in change edit - return deleteFileFactory.create(id.get()); - } - - public static class Create implements RestModifyView<ChangeResource, Put.Input> { - - interface Factory { - Create create(String path); - } - - private final Put putEdit; - private final String path; - - @Inject - Create(Put putEdit, @Assisted String path) { - this.putEdit = putEdit; - this.path = path; - } - - @Override - public Response<?> apply(ChangeResource resource, Put.Input input) - throws AuthException, ResourceConflictException, IOException, OrmException, - PermissionBackendException { - putEdit.apply(resource, path, input.content); - return Response.none(); - } - } - - public static class DeleteFile implements RestModifyView<ChangeResource, DeleteFile.Input> { - public static class Input {} - - interface Factory { - DeleteFile create(String path); - } - - private final DeleteContent deleteContent; - private final String path; - - @Inject - DeleteFile(DeleteContent deleteContent, @Assisted String path) { - this.deleteContent = deleteContent; - this.path = path; - } - - @Override - public Response<?> apply(ChangeResource rsrc, DeleteFile.Input in) - throws IOException, AuthException, ResourceConflictException, OrmException, - PermissionBackendException { - return deleteContent.apply(rsrc, path); - } - } - - // TODO(davido): Turn the boolean options to ChangeEditOption enum, - // like it's already the case for ListChangesOption/ListGroupsOption - public static class Detail implements RestReadView<ChangeResource> { - private final ChangeEditUtil editUtil; - private final ChangeEditJson editJson; - private final FileInfoJson fileInfoJson; - private final Revisions revisions; - - private String base; - private boolean list; - private boolean downloadCommands; - - @Option(name = "--base", metaVar = "revision-id") - public void setBase(String base) { - this.base = base; - } - - @Option(name = "--list") - public void setList(boolean list) { - this.list = list; - } - - @Option(name = "--download-commands") - public void setDownloadCommands(boolean downloadCommands) { - this.downloadCommands = downloadCommands; - } - - @Inject - Detail( - ChangeEditUtil editUtil, - ChangeEditJson editJson, - FileInfoJson fileInfoJson, - Revisions revisions) { - this.editJson = editJson; - this.editUtil = editUtil; - this.fileInfoJson = fileInfoJson; - this.revisions = revisions; - } - - @Override - public Response<EditInfo> apply(ChangeResource rsrc) - throws AuthException, IOException, ResourceNotFoundException, OrmException, - PermissionBackendException { - Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser()); - if (!edit.isPresent()) { - return Response.none(); - } - - EditInfo editInfo = editJson.toEditInfo(edit.get(), downloadCommands); - if (list) { - PatchSet basePatchSet = null; - if (base != null) { - RevisionResource baseResource = revisions.parse(rsrc, IdString.fromDecoded(base)); - basePatchSet = baseResource.getPatchSet(); - } - try { - editInfo.files = - fileInfoJson.toFileInfoMap( - rsrc.getChange(), edit.get().getEditCommit(), basePatchSet); - } catch (PatchListNotAvailableException e) { - throw new ResourceNotFoundException(e.getMessage()); - } - } - return Response.ok(editInfo); - } - } - - /** - * Post to edit collection resource. Two different operations are supported: - * - * <ul> - * <li>Create non existing change edit - * <li>Restore path in existing change edit - * </ul> - * - * The combination of two operations in one request is supported. - */ - @Singleton - public static class Post implements RestModifyView<ChangeResource, Post.Input> { - public static class Input { - public String restorePath; - public String oldPath; - public String newPath; - } - - private final ChangeEditModifier editModifier; - private final GitRepositoryManager repositoryManager; - - @Inject - Post(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) { - this.editModifier = editModifier; - this.repositoryManager = repositoryManager; - } - - @Override - public Response<?> apply(ChangeResource resource, Post.Input input) - throws AuthException, IOException, ResourceConflictException, OrmException, - PermissionBackendException { - Project.NameKey project = resource.getProject(); - try (Repository repository = repositoryManager.openRepository(project)) { - if (isRestoreFile(input)) { - editModifier.restoreFile(repository, resource.getNotes(), input.restorePath); - } else if (isRenameFile(input)) { - editModifier.renameFile(repository, resource.getNotes(), input.oldPath, input.newPath); - } else { - editModifier.createEdit(repository, resource.getNotes()); - } - } catch (InvalidChangeOperationException e) { - throw new ResourceConflictException(e.getMessage()); - } - return Response.none(); - } - - private static boolean isRestoreFile(Input input) { - return input != null && !Strings.isNullOrEmpty(input.restorePath); - } - - private static boolean isRenameFile(Input input) { - return input != null - && !Strings.isNullOrEmpty(input.oldPath) - && !Strings.isNullOrEmpty(input.newPath); - } - } - - /** Put handler that is activated when PUT request is called on collection element. */ - @Singleton - public static class Put implements RestModifyView<ChangeEditResource, Put.Input> { - public static class Input { - @DefaultInput public RawInput content; - } - - private final ChangeEditModifier editModifier; - private final GitRepositoryManager repositoryManager; - - @Inject - Put(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) { - this.editModifier = editModifier; - this.repositoryManager = repositoryManager; - } - - @Override - public Response<?> apply(ChangeEditResource rsrc, Input input) - throws AuthException, ResourceConflictException, IOException, OrmException, - PermissionBackendException { - return apply(rsrc.getChangeResource(), rsrc.getPath(), input.content); - } - - public Response<?> apply(ChangeResource rsrc, String path, RawInput newContent) - throws ResourceConflictException, AuthException, IOException, OrmException, - PermissionBackendException { - if (Strings.isNullOrEmpty(path) || path.charAt(0) == '/') { - throw new ResourceConflictException("Invalid path: " + path); - } - - try (Repository repository = repositoryManager.openRepository(rsrc.getProject())) { - editModifier.modifyFile(repository, rsrc.getNotes(), path, newContent); - } catch (InvalidChangeOperationException e) { - throw new ResourceConflictException(e.getMessage()); - } - return Response.none(); - } - } - - /** - * Handler to delete a file. - * - * <p>This deletes the file from the repository completely. This is not the same as reverting or - * restoring a file to its previous contents. - */ - @Singleton - public static class DeleteContent - implements RestModifyView<ChangeEditResource, DeleteContent.Input> { - public static class Input {} - - private final ChangeEditModifier editModifier; - private final GitRepositoryManager repositoryManager; - - @Inject - DeleteContent(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) { - this.editModifier = editModifier; - this.repositoryManager = repositoryManager; - } - - @Override - public Response<?> apply(ChangeEditResource rsrc, DeleteContent.Input input) - throws AuthException, ResourceConflictException, OrmException, IOException, - PermissionBackendException { - return apply(rsrc.getChangeResource(), rsrc.getPath()); - } - - public Response<?> apply(ChangeResource rsrc, String filePath) - throws AuthException, IOException, OrmException, ResourceConflictException, - PermissionBackendException { - try (Repository repository = repositoryManager.openRepository(rsrc.getProject())) { - editModifier.deleteFile(repository, rsrc.getNotes(), filePath); - } catch (InvalidChangeOperationException e) { - throw new ResourceConflictException(e.getMessage()); - } - return Response.none(); - } - } - - public static class Get implements RestReadView<ChangeEditResource> { - private final FileContentUtil fileContentUtil; - private final ProjectCache projectCache; - - @Option( - name = "--base", - aliases = {"-b"}, - usage = "whether to load the content on the base revision instead of the change edit") - private boolean base; - - @Inject - Get(FileContentUtil fileContentUtil, ProjectCache projectCache) { - this.fileContentUtil = fileContentUtil; - this.projectCache = projectCache; - } - - @Override - public Response<BinaryResult> apply(ChangeEditResource rsrc) throws IOException { - try { - ChangeEdit edit = rsrc.getChangeEdit(); - return Response.ok( - fileContentUtil.getContent( - projectCache.checkedGet(rsrc.getChangeResource().getProject()), - base - ? ObjectId.fromString(edit.getBasePatchSet().getRevision().get()) - : edit.getEditCommit(), - rsrc.getPath(), - null)); - } catch (ResourceNotFoundException | BadRequestException e) { - return Response.none(); - } - } - } - - @Singleton - public static class GetMeta implements RestReadView<ChangeEditResource> { - private final WebLinks webLinks; - - @Inject - GetMeta(WebLinks webLinks) { - this.webLinks = webLinks; - } - - @Override - public FileInfo apply(ChangeEditResource rsrc) { - FileInfo r = new FileInfo(); - ChangeEdit edit = rsrc.getChangeEdit(); - Change change = edit.getChange(); - List<DiffWebLinkInfo> links = - webLinks.getDiffLinks( - change.getProject().get(), - change.getChangeId(), - edit.getBasePatchSet().getPatchSetId(), - edit.getBasePatchSet().getRefName(), - rsrc.getPath(), - 0, - edit.getRefName(), - rsrc.getPath()); - r.webLinks = links.isEmpty() ? null : links; - return r; - } - - public static class FileInfo { - public List<DiffWebLinkInfo> webLinks; - } - } - - @Singleton - public static class EditMessage implements RestModifyView<ChangeResource, EditMessage.Input> { - public static class Input { - @DefaultInput public String message; - } - - private final ChangeEditModifier editModifier; - private final GitRepositoryManager repositoryManager; - - @Inject - EditMessage(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) { - this.editModifier = editModifier; - this.repositoryManager = repositoryManager; - } - - @Override - public Object apply(ChangeResource rsrc, Input input) - throws AuthException, IOException, BadRequestException, ResourceConflictException, - OrmException, PermissionBackendException { - if (input == null || Strings.isNullOrEmpty(input.message)) { - throw new BadRequestException("commit message must be provided"); - } - - Project.NameKey project = rsrc.getProject(); - try (Repository repository = repositoryManager.openRepository(project)) { - editModifier.modifyMessage(repository, rsrc.getNotes(), input.message); - } catch (UnchangedCommitMessageException e) { - throw new ResourceConflictException(e.getMessage()); - } - - return Response.none(); - } - } - - public static class GetMessage implements RestReadView<ChangeResource> { - private final GitRepositoryManager repoManager; - private final ChangeEditUtil editUtil; - - @Option( - name = "--base", - aliases = {"-b"}, - usage = "whether to load the message on the base revision instead of the change edit") - private boolean base; - - @Inject - GetMessage(GitRepositoryManager repoManager, ChangeEditUtil editUtil) { - this.repoManager = repoManager; - this.editUtil = editUtil; - } - - @Override - public BinaryResult apply(ChangeResource rsrc) - throws AuthException, IOException, ResourceNotFoundException, OrmException { - Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser()); - String msg; - if (edit.isPresent()) { - if (base) { - try (Repository repo = repoManager.openRepository(rsrc.getProject()); - RevWalk rw = new RevWalk(repo)) { - RevCommit commit = - rw.parseCommit( - ObjectId.fromString(edit.get().getBasePatchSet().getRevision().get())); - msg = commit.getFullMessage(); - } - } else { - msg = edit.get().getEditCommit().getFullMessage(); - } - - return BinaryResult.create(msg) - .setContentType(FileContentUtil.TEXT_X_GERRIT_COMMIT_MESSAGE) - .base64(); - } - throw new ResourceNotFoundException(); - } - } -} |