Add the revision diff REST API implementation.

A revision diff shows the contents of a file diff'd against
a base revision.  The "content" key in the root object contains
an array of objects where there is:
  "ab" for common lines to both sides
   only "a" when lines were deleted in "b"
   only "b" when lines were inserted in "b"
   "a" and "b" when the lines were replaced
   skip line count when the file is too large to show all common lines

If the url parameter "intraline" is specified.  Replaced regions may
also contain an "edit_a" and "edit_b" list of <offset, length> pairs,
from the begining of the region. edit_a represents deleted text sections
and edit_b represents insterted text sections. Note, the implied newline
character is included in the offset position.

Whitespace behavior can be controlled via the "ignore-whitespace" URL
parameter. Also, # of lines of surrounding context can be control
via the "context" URL parameter.

PatchScript was updated to include the calculated content type of the
file, which is exposed in the meta_[a|b] field of the root object.

PatchScriptFactory was refactored to take the ChangeControl, due to
scoping issues in the REST API. Furthermore, Patch.Key was replaced by
fileName.  The Git patch diff header was updated to not include the
trailing newline.

TODO: improve the content-type detection, since it returns
"application/octet-stream" more often than it should.

Change-Id: I96a6e0d569f3ecf24c5529dc706ae85c61bfb699
This commit is contained in:
Colby Ranger
2013-05-10 09:21:24 -07:00
committed by Shawn Pearce
parent 010daed12d
commit efe7aca78d
7 changed files with 383 additions and 25 deletions

View File

@@ -48,6 +48,8 @@ public class PatchScript {
protected List<Edit> edits; protected List<Edit> edits;
protected DisplayMethod displayMethodA; protected DisplayMethod displayMethodA;
protected DisplayMethod displayMethodB; protected DisplayMethod displayMethodB;
protected transient String mimeTypeA;
protected transient String mimeTypeB;
protected CommentDetail comments; protected CommentDetail comments;
protected List<Patch> history; protected List<Patch> history;
protected boolean hugeFile; protected boolean hugeFile;
@@ -60,8 +62,9 @@ public class PatchScript {
final List<String> h, final AccountDiffPreference dp, final List<String> h, final AccountDiffPreference dp,
final SparseFileContent ca, final SparseFileContent cb, final SparseFileContent ca, final SparseFileContent cb,
final List<Edit> e, final DisplayMethod ma, final DisplayMethod mb, final List<Edit> e, final DisplayMethod ma, final DisplayMethod mb,
final CommentDetail cd, final List<Patch> hist, final boolean hf, final String mta, final String mtb, final CommentDetail cd,
final boolean id, final boolean idf, final boolean idt) { final List<Patch> hist, final boolean hf, final boolean id,
final boolean idf, final boolean idt) {
changeId = ck; changeId = ck;
changeType = ct; changeType = ct;
oldName = on; oldName = on;
@@ -75,6 +78,8 @@ public class PatchScript {
edits = e; edits = e;
displayMethodA = ma; displayMethodA = ma;
displayMethodB = mb; displayMethodB = mb;
mimeTypeA = mta;
mimeTypeB = mtb;
comments = cd; comments = cd;
history = hist; history = hist;
hugeFile = hf; hugeFile = hf;
@@ -170,6 +175,14 @@ public class PatchScript {
return b; return b;
} }
public String getMimeTypeA() {
return mimeTypeA;
}
public String getMimeTypeB() {
return mimeTypeB;
}
public List<Edit> getEdits() { public List<Edit> getEdits() {
return edits; return edits;
} }

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.changedetail.DeleteDraftPatchSet; import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
import com.google.gerrit.server.patch.PatchScriptFactory; import com.google.gerrit.server.patch.PatchScriptFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException; import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException; import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gwtjsonrpc.common.AsyncCallback; import com.google.gwtjsonrpc.common.AsyncCallback;
@@ -51,6 +52,7 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
private final PatchScriptFactory.Factory patchScriptFactoryFactory; private final PatchScriptFactory.Factory patchScriptFactoryFactory;
private final SaveDraft.Factory saveDraftFactory; private final SaveDraft.Factory saveDraftFactory;
private final ChangeDetailFactory.Factory changeDetailFactory; private final ChangeDetailFactory.Factory changeDetailFactory;
private final ChangeControl.Factory changeControlFactory;
@Inject @Inject
PatchDetailServiceImpl(final Provider<ReviewDb> schema, PatchDetailServiceImpl(final Provider<ReviewDb> schema,
@@ -58,13 +60,15 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
final DeleteDraftPatchSet.Factory deleteDraftPatchSetFactory, final DeleteDraftPatchSet.Factory deleteDraftPatchSetFactory,
final PatchScriptFactory.Factory patchScriptFactoryFactory, final PatchScriptFactory.Factory patchScriptFactoryFactory,
final SaveDraft.Factory saveDraftFactory, final SaveDraft.Factory saveDraftFactory,
final ChangeDetailFactory.Factory changeDetailFactory) { final ChangeDetailFactory.Factory changeDetailFactory,
final ChangeControl.Factory changeControlFactory) {
super(schema, currentUser); super(schema, currentUser);
this.deleteDraftPatchSetFactory = deleteDraftPatchSetFactory; this.deleteDraftPatchSetFactory = deleteDraftPatchSetFactory;
this.patchScriptFactoryFactory = patchScriptFactoryFactory; this.patchScriptFactoryFactory = patchScriptFactoryFactory;
this.saveDraftFactory = saveDraftFactory; this.saveDraftFactory = saveDraftFactory;
this.changeDetailFactory = changeDetailFactory; this.changeDetailFactory = changeDetailFactory;
this.changeControlFactory = changeControlFactory;
} }
public void patchScript(final Patch.Key patchKey, final PatchSet.Id psa, public void patchScript(final Patch.Key patchKey, final PatchSet.Id psa,
@@ -74,8 +78,16 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
callback.onFailure(new NoSuchEntityException()); callback.onFailure(new NoSuchEntityException());
return; return;
} }
Handler.wrap(patchScriptFactoryFactory.create(patchKey, psa, psb, dp))
.to(callback); new Handler<PatchScript>() {
@Override
public PatchScript call() throws Exception {
Change.Id changeId = patchKey.getParentKey().getParentKey();
ChangeControl control = changeControlFactory.validateFor(changeId);
return patchScriptFactoryFactory.create(
control, patchKey.getFileName(), psa, psb, dp).call();
}
}.to(callback);
} }
public void saveDraft(final PatchLineComment comment, public void saveDraft(final PatchLineComment comment,

View File

@@ -0,0 +1,335 @@
// 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 static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScript.DisplayMethod;
import com.google.gerrit.common.data.PatchScript.FileMode;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.prettify.common.SparseFileContent;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gerrit.reviewdb.client.Patch.ChangeType;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.patch.PatchScriptFactory;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.git.LargeObjectException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.ReplaceEdit;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.NamedOptionDef;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
import java.util.List;
public class GetDiff implements RestReadView<FileResource> {
private final PatchScriptFactory.Factory patchScriptFactoryFactory;
private final Provider<Revisions> revisions;
@Option(name = "--base", metaVar = "REVISION")
String base;
@Option(name = "--ignore-whitespace")
IgnoreWhitespace ignoreWhitespace = IgnoreWhitespace.NONE;
@Option(name = "--context", handler = ContextOptionHandler.class)
short context = AccountDiffPreference.DEFAULT_CONTEXT;
@Option(name = "--intraline")
boolean intraline;
@Inject
GetDiff(PatchScriptFactory.Factory patchScriptFactoryFactory,
Provider<Revisions> revisions) {
this.patchScriptFactoryFactory = patchScriptFactoryFactory;
this.revisions = revisions;
}
@Override
public Object apply(FileResource resource)
throws OrmException, NoSuchChangeException, LargeObjectException, ResourceNotFoundException {
PatchSet.Id basePatchSet = null;
if (base != null) {
RevisionResource baseResource = revisions.get().parse(
resource.getRevision().getChangeResource(), IdString.fromDecoded(base));
basePatchSet = baseResource.getPatchSet().getId();
}
AccountDiffPreference prefs = new AccountDiffPreference(new Account.Id(0));
prefs.setIgnoreWhitespace(ignoreWhitespace.whitespace);
prefs.setContext(context);
prefs.setIntralineDifference(intraline);
PatchScript ps = patchScriptFactoryFactory.create(
resource.getRevision().getControl(),
resource.getPatchKey().getFileName(),
basePatchSet,
resource.getPatchKey().getParentKey(),
prefs)
.call();
Content content = new Content(ps);
for (Edit edit : ps.getEdits()) {
if (edit.getType() == Edit.Type.EMPTY) {
continue;
}
content.addCommon(edit.getBeginA());
checkState(content.nextA == edit.getBeginA(),
"nextA = %d; want %d", content.nextA, edit.getBeginA());
checkState(content.nextB == edit.getBeginB(),
"nextB = %d; want %d", content.nextB, edit.getBeginB());
switch (edit.getType()) {
case DELETE:
case INSERT:
case REPLACE:
List<Edit> internalEdit = edit instanceof ReplaceEdit
? ((ReplaceEdit) edit).getInternalEdits()
: null;
content.addDiff(edit.getEndA(), edit.getEndB(), internalEdit);
break;
case EMPTY:
default:
throw new IllegalStateException();
}
}
content.addCommon(ps.getA().size());
Result result = new Result();
if (ps.getDisplayMethodA() != DisplayMethod.NONE) {
result.metaA = new FileMeta();
result.metaA.name = Objects.firstNonNull(ps.getOldName(), ps.getNewName());
result.metaA.setContentType(ps.getFileModeA(), ps.getMimeTypeA());
}
if (ps.getDisplayMethodB() != DisplayMethod.NONE) {
result.metaB = new FileMeta();
result.metaB.name = ps.getNewName();
result.metaB.setContentType(ps.getFileModeB(), ps.getMimeTypeB());
}
if (intraline) {
if (ps.hasIntralineTimeout()) {
result.intralineStatus = IntraLineStatus.TIMEOUT;
} else if (ps.hasIntralineFailure()) {
result.intralineStatus = IntraLineStatus.FAILURE;
} else {
result.intralineStatus = IntraLineStatus.OK;
}
}
result.changeType = ps.getChangeType();
if (ps.getPatchHeader().size() > 0) {
result.diffHeader = ps.getPatchHeader();
}
result.content = content.lines;
return result;
}
static class Result {
FileMeta metaA;
FileMeta metaB;
IntraLineStatus intralineStatus;
ChangeType changeType;
List<String> diffHeader;
List<ContentEntry> content;
}
static class FileMeta {
String name;
String contentType;
String url;
void setContentType(FileMode fileMode, String mimeType) {
switch (fileMode) {
case FILE:
contentType = mimeType;
break;
case GITLINK:
contentType = "x-git/gitlink";
break;
case SYMLINK:
contentType = "x-git/symlink";
break;
default:
throw new IllegalStateException("file mode: " + fileMode);
}
}
}
enum IntraLineStatus {
OK,
TIMEOUT,
FAILURE;
}
private static class Content {
final List<ContentEntry> lines;
final SparseFileContent fileA;
final SparseFileContent fileB;
int nextA;
int nextB;
Content(PatchScript ps) {
lines = Lists.newArrayListWithExpectedSize(ps.getEdits().size() + 2);
fileA = ps.getA();
fileB = ps.getB();
}
void addCommon(int end) {
end = Math.min(end, fileA.size());
if (nextA >= end) {
return;
}
nextB += end - nextA;
while (nextA < end) {
if (fileA.contains(nextA)) {
ContentEntry e = entry();
e.ab = Lists.newArrayListWithCapacity(end - nextA);
for (int i = nextA; i == nextA && i < end; i = fileA.next(i), nextA++) {
e.ab.add(fileA.get(i));
}
} else {
int endRegion = Math.min(end,
(nextA == 0) ? fileA.first() : fileA.next(nextA - 1));
ContentEntry e = entry();
e.skip = endRegion - nextA;
nextA = endRegion;
}
}
}
void addDiff(int endA, int endB, List<Edit> internalEdit) {
int lenA = endA - nextA;
int lenB = endB - nextB;
checkState(lenA > 0 || lenB > 0);
ContentEntry e = entry();
if (lenA > 0) {
e.a = Lists.newArrayListWithCapacity(lenA);
for (; nextA < endA; nextA++) {
e.a.add(fileA.get(nextA));
}
}
if (lenB > 0) {
e.b = Lists.newArrayListWithCapacity(lenB);
for (; nextB < endB; nextB++) {
e.b.add(fileB.get(nextB));
}
}
if (internalEdit != null && !internalEdit.isEmpty()) {
e.editA = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
e.editB = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
for (Edit edit : internalEdit) {
if (edit.getBeginA() != edit.getEndA()) {
e.editA.add(ImmutableList.of(edit.getBeginA(), edit.getEndA() - edit.getBeginA()));
}
if (edit.getBeginB() != edit.getEndB()) {
e.editB.add(ImmutableList.of(edit.getBeginB(), edit.getEndB() - edit.getBeginB()));
}
}
}
}
private ContentEntry entry() {
ContentEntry e = new ContentEntry();
lines.add(e);
return e;
}
}
enum IgnoreWhitespace {
NONE(AccountDiffPreference.Whitespace.IGNORE_NONE),
TRAILING(AccountDiffPreference.Whitespace.IGNORE_SPACE_AT_EOL),
CHANGED(AccountDiffPreference.Whitespace.IGNORE_SPACE_CHANGE),
ALL(AccountDiffPreference.Whitespace.IGNORE_ALL_SPACE);
private final AccountDiffPreference.Whitespace whitespace;
private IgnoreWhitespace(AccountDiffPreference.Whitespace whitespace) {
this.whitespace = whitespace;
}
}
static final class ContentEntry {
// Common lines to both sides.
List<String> ab;
// Lines of a.
List<String> a;
// Lines of b.
List<String> b;
// A list of changed sections of the of the corresponding line list.
// Each entry is a character <offset, length> pair. The offset is from the
// beginning of the first line in the list. Also, the offset includes an
// implied trailing newline character for each line.
List<List<Integer>> editA;
List<List<Integer>> editB;
// Number of lines to skip on both sides.
Integer skip;
}
public static class ContextOptionHandler extends OptionHandler<Short> {
public ContextOptionHandler(
CmdLineParser parser, OptionDef option, Setter<Short> setter) {
super(parser, option, setter);
}
@Override
public final int parseArguments(final Parameters params)
throws CmdLineException {
final String value = params.getParameter(0);
short context;
if ("all".equalsIgnoreCase(value)) {
context = AccountDiffPreference.WHOLE_FILE_CONTEXT;
} else {
try {
context = Short.parseShort(value, 10);
if (context < 0) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
throw new CmdLineException(owner,
String.format("\"%s\" is not a valid value for \"%s\"",
value, ((NamedOptionDef) option).name()));
}
}
setter.addValue(context);
return 1;
}
@Override
public final String getDefaultMetaVariable() {
return "ALL|# LINES";
}
}
}

View File

@@ -85,6 +85,7 @@ public class Module extends RestApiModule {
put(FILE_KIND, "reviewed").to(PutReviewed.class); put(FILE_KIND, "reviewed").to(PutReviewed.class);
delete(FILE_KIND, "reviewed").to(DeleteReviewed.class); delete(FILE_KIND, "reviewed").to(DeleteReviewed.class);
get(FILE_KIND, "content").to(GetContent.class); get(FILE_KIND, "content").to(GetContent.class);
get(FILE_KIND, "diff").to(GetDiff.class);
install(new FactoryModule() { install(new FactoryModule() {
@Override @Override

View File

@@ -171,7 +171,10 @@ public class PatchListEntry {
final List<String> headerLines = new ArrayList<String>(m.size() - 1); final List<String> headerLines = new ArrayList<String>(m.size() - 1);
for (int i = 1; i < m.size() - 1; i++) { for (int i = 1; i < m.size() - 1; i++) {
final int b = m.get(i); final int b = m.get(i);
final int e = m.get(i + 1); int e = m.get(i + 1);
if (header[e - 1] == '\n') {
e--;
}
headerLines.add(RawParseUtils.decode(Constants.CHARSET, header, b, e)); headerLines.add(RawParseUtils.decode(Constants.CHARSET, header, b, e));
} }
return headerLines; return headerLines;

View File

@@ -211,7 +211,8 @@ class PatchScriptBuilder {
return new PatchScript(change.getKey(), content.getChangeType(), return new PatchScript(change.getKey(), content.getChangeType(),
content.getOldName(), content.getNewName(), a.fileMode, b.fileMode, content.getOldName(), content.getNewName(), a.fileMode, b.fileMode,
content.getHeaderLines(), diffPrefs, a.dst, b.dst, edits, content.getHeaderLines(), diffPrefs, a.dst, b.dst, edits,
a.displayMethod, b.displayMethod, comments, history, hugeFile, a.displayMethod, b.displayMethod, a.mimeType.toString(),
b.mimeType.toString(), comments, history, hugeFile,
intralineDifferenceIsPossible, intralineFailure, intralineTimeout); intralineDifferenceIsPossible, intralineFailure, intralineTimeout);
} }

View File

@@ -56,7 +56,9 @@ import javax.annotation.Nullable;
public class PatchScriptFactory implements Callable<PatchScript> { public class PatchScriptFactory implements Callable<PatchScript> {
public interface Factory { public interface Factory {
PatchScriptFactory create(Patch.Key patchKey, PatchScriptFactory create(
ChangeControl control,
String fileName,
@Assisted("patchSetA") PatchSet.Id patchSetA, @Assisted("patchSetA") PatchSet.Id patchSetA,
@Assisted("patchSetB") PatchSet.Id patchSetB, @Assisted("patchSetB") PatchSet.Id patchSetB,
AccountDiffPreference diffPrefs); AccountDiffPreference diffPrefs);
@@ -69,20 +71,17 @@ public class PatchScriptFactory implements Callable<PatchScript> {
private final Provider<PatchScriptBuilder> builderFactory; private final Provider<PatchScriptBuilder> builderFactory;
private final PatchListCache patchListCache; private final PatchListCache patchListCache;
private final ReviewDb db; private final ReviewDb db;
private final ChangeControl.Factory changeControlFactory;
private final AccountInfoCacheFactory.Factory aicFactory; private final AccountInfoCacheFactory.Factory aicFactory;
private final Patch.Key patchKey; private final String fileName;
@Nullable @Nullable
private final PatchSet.Id psa; private final PatchSet.Id psa;
private final PatchSet.Id psb; private final PatchSet.Id psb;
private final AccountDiffPreference diffPrefs; private final AccountDiffPreference diffPrefs;
private final PatchSet.Id patchSetId;
private final Change.Id changeId; private final Change.Id changeId;
private Change change; private Change change;
private PatchSet patchSet;
private Project.NameKey projectKey; private Project.NameKey projectKey;
private ChangeControl control; private ChangeControl control;
private ObjectId aId; private ObjectId aId;
@@ -94,9 +93,9 @@ public class PatchScriptFactory implements Callable<PatchScript> {
PatchScriptFactory(final GitRepositoryManager grm, PatchScriptFactory(final GitRepositoryManager grm,
Provider<PatchScriptBuilder> builderFactory, Provider<PatchScriptBuilder> builderFactory,
final PatchListCache patchListCache, final ReviewDb db, final PatchListCache patchListCache, final ReviewDb db,
final ChangeControl.Factory changeControlFactory,
final AccountInfoCacheFactory.Factory aicFactory, final AccountInfoCacheFactory.Factory aicFactory,
@Assisted final Patch.Key patchKey, @Assisted ChangeControl control,
@Assisted final String fileName,
@Assisted("patchSetA") @Nullable final PatchSet.Id patchSetA, @Assisted("patchSetA") @Nullable final PatchSet.Id patchSetA,
@Assisted("patchSetB") final PatchSet.Id patchSetB, @Assisted("patchSetB") final PatchSet.Id patchSetB,
@Assisted final AccountDiffPreference diffPrefs) { @Assisted final AccountDiffPreference diffPrefs) {
@@ -104,16 +103,15 @@ public class PatchScriptFactory implements Callable<PatchScript> {
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.patchListCache = patchListCache; this.patchListCache = patchListCache;
this.db = db; this.db = db;
this.changeControlFactory = changeControlFactory; this.control = control;
this.aicFactory = aicFactory; this.aicFactory = aicFactory;
this.patchKey = patchKey; this.fileName = fileName;
this.psa = patchSetA; this.psa = patchSetA;
this.psb = patchSetB; this.psb = patchSetB;
this.diffPrefs = diffPrefs; this.diffPrefs = diffPrefs;
patchSetId = patchKey.getParentKey(); changeId = patchSetB.getParentKey();
changeId = patchSetId.getParentKey();
} }
@Override @Override
@@ -122,13 +120,8 @@ public class PatchScriptFactory implements Callable<PatchScript> {
validatePatchSetId(psa); validatePatchSetId(psa);
validatePatchSetId(psb); validatePatchSetId(psb);
control = changeControlFactory.validateFor(changeId);
change = control.getChange(); change = control.getChange();
projectKey = change.getProject(); projectKey = change.getProject();
patchSet = db.patchSets().get(patchSetId);
if (patchSet == null) {
throw new NoSuchChangeException(changeId);
}
aId = psa != null ? toObjectId(db, psa) : null; aId = psa != null ? toObjectId(db, psa) : null;
bId = toObjectId(db, psb); bId = toObjectId(db, psb);
@@ -146,7 +139,7 @@ public class PatchScriptFactory implements Callable<PatchScript> {
try { try {
final PatchList list = listFor(keyFor(diffPrefs.getIgnoreWhitespace())); final PatchList list = listFor(keyFor(diffPrefs.getIgnoreWhitespace()));
final PatchScriptBuilder b = newBuilder(list, git); final PatchScriptBuilder b = newBuilder(list, git);
final PatchListEntry content = list.get(patchKey.getFileName()); final PatchListEntry content = list.get(fileName);
loadCommentsAndHistory(content.getChangeType(), // loadCommentsAndHistory(content.getChangeType(), //
content.getOldName(), // content.getOldName(), //
@@ -227,7 +220,7 @@ public class PatchScriptFactory implements Callable<PatchScript> {
// proper rename detection between the patch sets. // proper rename detection between the patch sets.
// //
for (final PatchSet ps : db.patchSets().byChange(changeId)) { for (final PatchSet ps : db.patchSets().byChange(changeId)) {
String name = patchKey.get(); String name = fileName;
if (psa != null) { if (psa != null) {
switch (changeType) { switch (changeType) {
case COPIED: case COPIED: