Merge topic 'inline-3'
* changes: InlineEdit: Add change edit collection and resource InlineEdit: Add acceptance test for edit operations InlineEdit: Factor out get content method for file resource InlineEdit: Add utility class to modify edits
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// 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.gerrit.extensions.restapi.RestResource;
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.edit.ChangeEdit;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
public class ChangeEditResource implements RestResource {
|
||||
public static final TypeLiteral<RestView<ChangeEditResource>> CHANGE_EDIT_KIND =
|
||||
new TypeLiteral<RestView<ChangeEditResource>>() {};
|
||||
|
||||
private final ChangeResource change;
|
||||
private final ChangeEdit edit;
|
||||
|
||||
public ChangeEditResource(ChangeResource change, ChangeEdit edit) {
|
||||
this.change = change;
|
||||
this.edit = edit;
|
||||
}
|
||||
|
||||
// TODO(davido): Make this cacheable.
|
||||
// Should just depend on the SHA-1 of the edit itself.
|
||||
public boolean isCacheable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ChangeResource getChangeResource() {
|
||||
return change;
|
||||
}
|
||||
|
||||
public ChangeControl getControl() {
|
||||
return getChangeResource().getControl();
|
||||
}
|
||||
|
||||
public Change getChange() {
|
||||
return edit.getChange();
|
||||
}
|
||||
|
||||
public ChangeEdit getChangeEdit() {
|
||||
return edit;
|
||||
}
|
||||
|
||||
Account.Id getAccountId() {
|
||||
return getUser().getAccountId();
|
||||
}
|
||||
|
||||
IdentifiedUser getUser() {
|
||||
return edit.getUser();
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
// 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.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.ChildCollection;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
class ChangeEdits implements
|
||||
ChildCollection<ChangeResource, ChangeEditResource> {
|
||||
private final DynamicMap<RestView<ChangeEditResource>> views;
|
||||
|
||||
@Inject
|
||||
ChangeEdits(DynamicMap<RestView<ChangeEditResource>> views) {
|
||||
this.views = views;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicMap<RestView<ChangeEditResource>> views() {
|
||||
return views;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestView<ChangeResource> list() {
|
||||
throw new IllegalStateException("not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeEditResource parse(ChangeResource change, IdString id) {
|
||||
throw new IllegalStateException("not yet implemented");
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2013 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.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@Singleton
|
||||
public class FileContentUtil {
|
||||
private final GitRepositoryManager repoManager;
|
||||
|
||||
@Inject
|
||||
FileContentUtil(GitRepositoryManager repoManager) {
|
||||
this.repoManager = repoManager;
|
||||
}
|
||||
|
||||
public BinaryResult getContent(Project.NameKey project, String revstr,
|
||||
String path) throws ResourceNotFoundException, IOException {
|
||||
Repository repo = repoManager.openRepository(project);
|
||||
try {
|
||||
RevWalk rw = new RevWalk(repo);
|
||||
try {
|
||||
RevCommit commit = rw.parseCommit(repo.resolve(revstr));
|
||||
TreeWalk tw =
|
||||
TreeWalk.forPath(rw.getObjectReader(), path,
|
||||
commit.getTree().getId());
|
||||
if (tw == null) {
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
final ObjectLoader object = repo.open(tw.getObjectId(0));
|
||||
@SuppressWarnings("resource")
|
||||
BinaryResult result = new BinaryResult() {
|
||||
@Override
|
||||
public void writeTo(OutputStream os) throws IOException {
|
||||
object.copyTo(os);
|
||||
}
|
||||
};
|
||||
return result.setContentLength(object.getSize()).base64();
|
||||
} finally {
|
||||
rw.release();
|
||||
}
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -17,65 +17,26 @@ package com.google.gerrit.server.change;
|
||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@Singleton
|
||||
public class GetContent implements RestReadView<FileResource> {
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final FileContentUtil fileContentUtil;
|
||||
|
||||
@Inject
|
||||
GetContent(GitRepositoryManager repoManager) {
|
||||
this.repoManager = repoManager;
|
||||
GetContent(FileContentUtil fileContentUtil) {
|
||||
this.fileContentUtil = fileContentUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryResult apply(FileResource rsrc)
|
||||
throws ResourceNotFoundException, IOException {
|
||||
return apply(rsrc.getRevision().getControl().getProject().getNameKey(),
|
||||
return fileContentUtil.getContent(
|
||||
rsrc.getRevision().getControl().getProject().getNameKey(),
|
||||
rsrc.getRevision().getPatchSet().getRevision().get(),
|
||||
rsrc.getPatchKey().get());
|
||||
}
|
||||
|
||||
public BinaryResult apply(Project.NameKey project, String revstr, String path)
|
||||
throws ResourceNotFoundException, IOException {
|
||||
Repository repo = repoManager.openRepository(project);
|
||||
try {
|
||||
RevWalk rw = new RevWalk(repo);
|
||||
try {
|
||||
RevCommit commit =
|
||||
rw.parseCommit(repo.resolve(revstr));
|
||||
TreeWalk tw =
|
||||
TreeWalk.forPath(rw.getObjectReader(), path,
|
||||
commit.getTree().getId());
|
||||
if (tw == null) {
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
final ObjectLoader object = repo.open(tw.getObjectId(0));
|
||||
@SuppressWarnings("resource")
|
||||
BinaryResult result = new BinaryResult() {
|
||||
@Override
|
||||
public void writeTo(OutputStream os) throws IOException {
|
||||
object.copyTo(os);
|
||||
}
|
||||
};
|
||||
return result.setContentLength(object.getSize()).base64();
|
||||
} finally {
|
||||
rw.release();
|
||||
}
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import static com.google.gerrit.server.change.DraftResource.DRAFT_KIND;
|
||||
import static com.google.gerrit.server.change.FileResource.FILE_KIND;
|
||||
import static com.google.gerrit.server.change.ReviewerResource.REVIEWER_KIND;
|
||||
import static com.google.gerrit.server.change.RevisionResource.REVISION_KIND;
|
||||
import static com.google.gerrit.server.change.ChangeEditResource.CHANGE_EDIT_KIND;
|
||||
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.RestApiModule;
|
||||
@@ -44,6 +45,7 @@ public class Module extends RestApiModule {
|
||||
DynamicMap.mapOf(binder(), FILE_KIND);
|
||||
DynamicMap.mapOf(binder(), REVIEWER_KIND);
|
||||
DynamicMap.mapOf(binder(), REVISION_KIND);
|
||||
DynamicMap.mapOf(binder(), CHANGE_EDIT_KIND);
|
||||
|
||||
get(CHANGE_KIND).to(GetChange.class);
|
||||
get(CHANGE_KIND, "detail").to(GetDetail.class);
|
||||
|
@@ -0,0 +1,336 @@
|
||||
// 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.edit;
|
||||
|
||||
import static com.google.gerrit.server.edit.ChangeEditUtil.editRefName;
|
||||
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
||||
import com.google.gerrit.server.util.TimeUtil;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Utility functions to manipulate change edits.
|
||||
* <p>
|
||||
* This class contains methods to modify edit's content.
|
||||
* For retrieving, publishing and deleting edit see
|
||||
* {@link ChangeEditUtil}.
|
||||
* <p>
|
||||
*/
|
||||
@Singleton
|
||||
public class ChangeEditModifier {
|
||||
|
||||
private static enum TreeOperation {
|
||||
CHANGE_ENTRY,
|
||||
DELETE_ENTRY,
|
||||
RESTORE_ENTRY
|
||||
}
|
||||
private final TimeZone tz;
|
||||
private final GitRepositoryManager gitManager;
|
||||
private final Provider<CurrentUser> currentUser;
|
||||
private final ChangeEditUtil editUtil;
|
||||
|
||||
@Inject
|
||||
ChangeEditModifier(@GerritPersonIdent PersonIdent gerritIdent,
|
||||
GitRepositoryManager gitManager,
|
||||
Provider<ReviewDb> dbProvider,
|
||||
Provider<CurrentUser> currentUser,
|
||||
ChangeEditUtil editUtil) {
|
||||
this.gitManager = gitManager;
|
||||
this.currentUser = currentUser;
|
||||
this.editUtil = editUtil;
|
||||
this.tz = gerritIdent.getTimeZone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new change edit.
|
||||
*
|
||||
* @param change to create change edit for
|
||||
* @param ps patch set to create change edit on
|
||||
* @return result
|
||||
* @throws AuthException
|
||||
* @throws IOException
|
||||
* @throws ResourceConflictException When change edit already
|
||||
* exists for the change
|
||||
*/
|
||||
public RefUpdate.Result createEdit(Change change, PatchSet ps)
|
||||
throws AuthException, IOException, ResourceConflictException {
|
||||
if (!currentUser.get().isIdentifiedUser()) {
|
||||
throw new AuthException("Authentication required");
|
||||
}
|
||||
|
||||
IdentifiedUser me = (IdentifiedUser) currentUser.get();
|
||||
Repository repo = gitManager.openRepository(change.getProject());
|
||||
String refName = editRefName(me.getAccountId(), change.getId());
|
||||
|
||||
try {
|
||||
if (repo.getRefDatabase().getRef(refName) != null) {
|
||||
throw new ResourceConflictException("edit already exists");
|
||||
}
|
||||
|
||||
RevWalk rw = new RevWalk(repo);
|
||||
ObjectInserter inserter = repo.newObjectInserter();
|
||||
try {
|
||||
RevCommit base = rw.parseCommit(ObjectId.fromString(
|
||||
ps.getRevision().get()));
|
||||
ObjectId commit = createCommit(me, inserter, base, base, base.getTree());
|
||||
inserter.flush();
|
||||
return update(repo, me, refName, rw, base, ObjectId.zeroId(), commit);
|
||||
} finally {
|
||||
rw.release();
|
||||
inserter.release();
|
||||
}
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify file in existing change edit from its base commit.
|
||||
*
|
||||
* @param edit change edit
|
||||
* @param file path to modify
|
||||
* @param content new content
|
||||
* @return result
|
||||
* @throws AuthException
|
||||
* @throws InvalidChangeOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public RefUpdate.Result modifyFile(ChangeEdit edit,
|
||||
String file, byte[] content) throws AuthException,
|
||||
InvalidChangeOperationException, IOException {
|
||||
return modify(TreeOperation.CHANGE_ENTRY, edit, file, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file in existing change edit.
|
||||
*
|
||||
* @param edit change edit
|
||||
* @param file path to delete
|
||||
* @return result
|
||||
* @throws AuthException
|
||||
* @throws InvalidChangeOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public RefUpdate.Result deleteFile(ChangeEdit edit,
|
||||
String file) throws AuthException, InvalidChangeOperationException,
|
||||
IOException {
|
||||
return modify(TreeOperation.DELETE_ENTRY, edit, file, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore file in existing change edit.
|
||||
*
|
||||
* @param edit change edit
|
||||
* @param file path to restore
|
||||
* @return result
|
||||
* @throws AuthException
|
||||
* @throws InvalidChangeOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public RefUpdate.Result restoreFile(ChangeEdit edit,
|
||||
String file) throws AuthException, InvalidChangeOperationException,
|
||||
IOException {
|
||||
return modify(TreeOperation.RESTORE_ENTRY, edit, file, null);
|
||||
}
|
||||
|
||||
private RefUpdate.Result modify(TreeOperation op,
|
||||
ChangeEdit edit, String file, byte[] content)
|
||||
throws AuthException, IOException, InvalidChangeOperationException {
|
||||
if (!currentUser.get().isIdentifiedUser()) {
|
||||
throw new AuthException("Authentication required");
|
||||
}
|
||||
IdentifiedUser me = (IdentifiedUser) currentUser.get();
|
||||
Repository repo = gitManager.openRepository(edit.getChange().getProject());
|
||||
try {
|
||||
RevWalk rw = new RevWalk(repo);
|
||||
ObjectInserter inserter = repo.newObjectInserter();
|
||||
ObjectReader reader = repo.newObjectReader();
|
||||
try {
|
||||
String refName = edit.getRefName();
|
||||
RevCommit prevEdit = rw.parseCommit(edit.getRef().getObjectId());
|
||||
PatchSet basePs = editUtil.getBasePatchSet(edit, prevEdit);
|
||||
|
||||
RevCommit base = rw.parseCommit(ObjectId.fromString(
|
||||
basePs.getRevision().get()));
|
||||
ObjectId oldObjectId = prevEdit;
|
||||
if (prevEdit == null) {
|
||||
prevEdit = base;
|
||||
oldObjectId = ObjectId.zeroId();
|
||||
}
|
||||
ObjectId newTree = writeNewTree(op, repo, rw, inserter,
|
||||
prevEdit, reader, file, content, base);
|
||||
if (ObjectId.equals(newTree, prevEdit.getTree())) {
|
||||
throw new InvalidChangeOperationException("no changes were made");
|
||||
}
|
||||
|
||||
ObjectId commit = createCommit(me, inserter, prevEdit, base, newTree);
|
||||
inserter.flush();
|
||||
return update(repo, me, refName, rw, base, oldObjectId, commit);
|
||||
} finally {
|
||||
rw.release();
|
||||
inserter.release();
|
||||
reader.release();
|
||||
}
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectId createCommit(IdentifiedUser me, ObjectInserter inserter,
|
||||
RevCommit prevEdit, RevCommit base, ObjectId tree) throws IOException {
|
||||
CommitBuilder builder = new CommitBuilder();
|
||||
builder.setTreeId(tree);
|
||||
builder.setParentIds(base);
|
||||
builder.setAuthor(prevEdit.getAuthorIdent());
|
||||
builder.setCommitter(getCommitterIdent(me));
|
||||
builder.setMessage(prevEdit.getFullMessage());
|
||||
return inserter.insert(builder);
|
||||
}
|
||||
|
||||
private RefUpdate.Result update(Repository repo, IdentifiedUser me,
|
||||
String refName, RevWalk rw, RevCommit base,
|
||||
ObjectId oldObjectId, ObjectId newEdit) throws IOException {
|
||||
RefUpdate ru = repo.updateRef(refName);
|
||||
ru.setExpectedOldObjectId(oldObjectId);
|
||||
ru.setNewObjectId(newEdit);
|
||||
ru.setRefLogIdent(getRefLogIdent(me));
|
||||
ru.setForceUpdate(true);
|
||||
RefUpdate.Result res = ru.update(rw);
|
||||
if (res != RefUpdate.Result.NEW &&
|
||||
res != RefUpdate.Result.FORCED) {
|
||||
throw new IOException("update failed: " + ru);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static ObjectId writeNewTree(TreeOperation op, Repository repo, RevWalk rw,
|
||||
ObjectInserter ins, RevCommit prevEdit, ObjectReader reader,
|
||||
String fileName, byte[] content, RevCommit base)
|
||||
throws IOException, InvalidChangeOperationException {
|
||||
DirCache newTree = createTree(reader, prevEdit);
|
||||
editTree(
|
||||
op,
|
||||
repo,
|
||||
rw,
|
||||
base,
|
||||
newTree.editor(),
|
||||
ins,
|
||||
fileName,
|
||||
content);
|
||||
return newTree.writeTree(ins);
|
||||
}
|
||||
|
||||
private static void editTree(TreeOperation op, Repository repo, RevWalk rw,
|
||||
RevCommit base, DirCacheEditor dce, ObjectInserter ins, String path,
|
||||
byte[] content) throws IOException, InvalidChangeOperationException {
|
||||
switch (op) {
|
||||
case CHANGE_ENTRY:
|
||||
case RESTORE_ENTRY:
|
||||
dce.add(getPathEdit(op, repo, rw, base, path, ins, content));
|
||||
break;
|
||||
case DELETE_ENTRY:
|
||||
dce.add(new DeletePath(path));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("unknown tree operation");
|
||||
}
|
||||
dce.finish();
|
||||
}
|
||||
|
||||
private static PathEdit getPathEdit(TreeOperation op, Repository repo, RevWalk rw,
|
||||
RevCommit base, String path, ObjectInserter ins, byte[] content)
|
||||
throws IOException, InvalidChangeOperationException {
|
||||
final ObjectId oid = op == TreeOperation.CHANGE_ENTRY
|
||||
? ins.insert(Constants.OBJ_BLOB, content)
|
||||
: getObjectIdForRestoreOperation(repo, rw, base, path);
|
||||
return new PathEdit(path) {
|
||||
@Override
|
||||
public void apply(DirCacheEntry ent) {
|
||||
ent.setFileMode(FileMode.REGULAR_FILE);
|
||||
ent.setObjectId(oid);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static ObjectId getObjectIdForRestoreOperation(Repository repo,
|
||||
RevWalk rw, RevCommit base, String path)
|
||||
throws IOException, InvalidChangeOperationException {
|
||||
TreeWalk tw = TreeWalk.forPath(rw.getObjectReader(), path,
|
||||
base.getTree().getId());
|
||||
// If the file does not exist in the base commit, try to restore it
|
||||
// from the base's parent commit.
|
||||
if (tw == null && base.getParentCount() == 1) {
|
||||
tw = TreeWalk.forPath(rw.getObjectReader(), path,
|
||||
rw.parseCommit(base.getParent(0)).getTree().getId());
|
||||
}
|
||||
if (tw == null) {
|
||||
throw new InvalidChangeOperationException(String.format(
|
||||
"cannot restore path %s: missing in base revision %s",
|
||||
path, base.abbreviate(8)));
|
||||
}
|
||||
return tw.getObjectId(0);
|
||||
}
|
||||
|
||||
private static DirCache createTree(ObjectReader reader, RevCommit prevEdit)
|
||||
throws IOException {
|
||||
DirCache dc = DirCache.newInCore();
|
||||
DirCacheBuilder b = dc.builder();
|
||||
b.addTree(new byte[0], DirCacheEntry.STAGE_0, reader, prevEdit.getTree()
|
||||
.getId());
|
||||
b.finish();
|
||||
return dc;
|
||||
}
|
||||
|
||||
private PersonIdent getCommitterIdent(IdentifiedUser user) {
|
||||
return user.newCommitterIdent(TimeUtil.nowTs(), tz);
|
||||
}
|
||||
|
||||
private PersonIdent getRefLogIdent(IdentifiedUser user) {
|
||||
return user.newRefLogIdent(TimeUtil.nowTs(), tz);
|
||||
}
|
||||
}
|
@@ -53,6 +53,7 @@ import java.util.List;
|
||||
* Utility functions to manipulate change edits.
|
||||
* <p>
|
||||
* This class contains methods to retrieve, publish and delete edits.
|
||||
* For changing edits see {@link ChangeEditModifier}.
|
||||
*/
|
||||
@Singleton
|
||||
public class ChangeEditUtil {
|
||||
|
@@ -17,25 +17,25 @@ package com.google.gerrit.server.project;
|
||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.server.change.FileContentUtil;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Singleton
|
||||
public class GetContent implements RestReadView<FileResource> {
|
||||
private final Provider<com.google.gerrit.server.change.GetContent> getContent;
|
||||
private final FileContentUtil fileContentUtil;
|
||||
|
||||
@Inject
|
||||
GetContent(Provider<com.google.gerrit.server.change.GetContent> getContent) {
|
||||
this.getContent = getContent;
|
||||
GetContent(FileContentUtil fileContentUtil) {
|
||||
this.fileContentUtil = fileContentUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryResult apply(FileResource rsrc)
|
||||
throws ResourceNotFoundException, IOException {
|
||||
return getContent.get().apply(rsrc.getProject(), rsrc.getRev(),
|
||||
return fileContentUtil.getContent(rsrc.getProject(), rsrc.getRev(),
|
||||
rsrc.getPath());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user