mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-05-07 05:05:50 +02:00
Modifications command between two revisions (#1761)
Adds the option to compute the modifications between two revisions unsing the modifications command.
This commit is contained in:
@@ -27,6 +27,7 @@ package sonia.scm.repository.spi;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.jgit.diff.DiffEntry;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTree;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
@@ -60,10 +61,65 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
|
||||
super(context);
|
||||
}
|
||||
|
||||
private Modifications createModifications(TreeWalk treeWalk, RevCommit commit, RevWalk revWalk, String revision)
|
||||
throws IOException {
|
||||
@Override
|
||||
public Modifications getModifications(String baseRevision, String revision) {
|
||||
org.eclipse.jgit.lib.Repository gitRepository = null;
|
||||
RevWalk revWalk = null;
|
||||
try {
|
||||
gitRepository = open();
|
||||
if (!gitRepository.getAllRefs().isEmpty()) {
|
||||
revWalk = new RevWalk(gitRepository);
|
||||
RevCommit commit = getCommit(revision, gitRepository, revWalk);
|
||||
TreeWalk treeWalk = createTreeWalk(gitRepository);
|
||||
if (baseRevision == null) {
|
||||
determineParentAsBase(treeWalk, commit, revWalk);
|
||||
} else {
|
||||
RevCommit baseCommit = getCommit(baseRevision, gitRepository, revWalk);
|
||||
treeWalk.addTree(baseCommit.getTree());
|
||||
}
|
||||
return new Modifications(baseRevision, revision, createModifications(treeWalk, commit));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log.error("could not open repository", ex);
|
||||
throw new InternalRepositoryException(entity(repository), "could not open repository", ex);
|
||||
} finally {
|
||||
GitUtil.release(revWalk);
|
||||
GitUtil.close(gitRepository);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private RevCommit getCommit(String revision, Repository gitRepository, RevWalk revWalk) throws IOException {
|
||||
ObjectId id = GitUtil.getRevisionId(gitRepository, revision);
|
||||
return revWalk.parseCommit(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifications getModifications(String revision) {
|
||||
return getModifications(null, revision);
|
||||
}
|
||||
|
||||
private TreeWalk createTreeWalk(Repository gitRepository) {
|
||||
TreeWalk treeWalk = new TreeWalk(gitRepository);
|
||||
treeWalk.reset();
|
||||
treeWalk.setRecursive(true);
|
||||
return treeWalk;
|
||||
}
|
||||
|
||||
private Collection<Modification> createModifications(TreeWalk treeWalk, RevCommit commit)
|
||||
throws IOException {
|
||||
treeWalk.addTree(commit.getTree());
|
||||
List<DiffEntry> entries = Differ.scanWithRename(context.open(), null, treeWalk);
|
||||
Collection<Modification> modifications = new ArrayList<>();
|
||||
for (DiffEntry e : entries) {
|
||||
if (!e.getOldId().equals(e.getNewId()) || !e.getOldPath().equals(e.getNewPath())) {
|
||||
modifications.add(asModification(e));
|
||||
}
|
||||
}
|
||||
return modifications;
|
||||
}
|
||||
|
||||
private void determineParentAsBase(TreeWalk treeWalk, RevCommit commit, RevWalk revWalk) throws IOException {
|
||||
if (commit.getParentCount() > 0) {
|
||||
RevCommit parent = commit.getParent(0);
|
||||
RevTree tree = parent.getTree();
|
||||
@@ -81,43 +137,6 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
|
||||
log.trace("no parent available for commit {}", commit.getName());
|
||||
treeWalk.addTree(new EmptyTreeIterator());
|
||||
}
|
||||
treeWalk.addTree(commit.getTree());
|
||||
List<DiffEntry> entries = Differ.scanWithRename(context.open(), null, treeWalk);
|
||||
Collection<Modification> modifications = new ArrayList<>();
|
||||
for (DiffEntry e : entries) {
|
||||
if (!e.getOldId().equals(e.getNewId()) || !e.getOldPath().equals(e.getNewPath())) {
|
||||
modifications.add(asModification(e));
|
||||
}
|
||||
}
|
||||
return new Modifications(revision, modifications);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifications getModifications(String revision) {
|
||||
org.eclipse.jgit.lib.Repository gitRepository = null;
|
||||
RevWalk revWalk = null;
|
||||
try {
|
||||
gitRepository = open();
|
||||
if (!gitRepository.getAllRefs().isEmpty()) {
|
||||
revWalk = new RevWalk(gitRepository);
|
||||
ObjectId id = GitUtil.getRevisionId(gitRepository, revision);
|
||||
RevCommit commit = revWalk.parseCommit(id);
|
||||
TreeWalk treeWalk = new TreeWalk(gitRepository);
|
||||
return createModifications(treeWalk, commit, revWalk, revision);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log.error("could not open repository", ex);
|
||||
throw new InternalRepositoryException(entity(repository), "could not open repository", ex);
|
||||
} finally {
|
||||
GitUtil.release(revWalk);
|
||||
GitUtil.close(gitRepository);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifications getModifications(ModificationsCommandRequest request) {
|
||||
return getModifications(request.getRevision());
|
||||
}
|
||||
|
||||
private Modification asModification(DiffEntry entry) throws UnsupportedModificationTypeException {
|
||||
|
||||
@@ -60,7 +60,10 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider {
|
||||
Command.MIRROR
|
||||
);
|
||||
|
||||
protected static final Set<Feature> FEATURES = EnumSet.of(Feature.INCOMING_REVISION);
|
||||
protected static final Set<Feature> FEATURES = EnumSet.of(
|
||||
Feature.INCOMING_REVISION,
|
||||
Feature.MODIFICATIONS_BETWEEN_REVISIONS
|
||||
);
|
||||
|
||||
private final GitContext context;
|
||||
private final Injector commandInjector;
|
||||
|
||||
@@ -106,6 +106,36 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase {
|
||||
assertModifications.accept(incomingModificationsCommand.getModifications(revision));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFindModificationsBetweenRevisions() throws Exception {
|
||||
write(outgoing, outgoingDirectory, "a.txt", "bal bla");
|
||||
write(outgoing, outgoingDirectory, "d.txt", "some file to be renamed");
|
||||
RevCommit baseCommit = commit(outgoing, "add files");
|
||||
|
||||
write(outgoing, outgoingDirectory, "a.txt", "modified content");
|
||||
commit(outgoing, "modify file");
|
||||
write(outgoing, outgoingDirectory, "c.txt", "brand new file");
|
||||
commit(outgoing, "add file");
|
||||
write(outgoing, outgoingDirectory, "o.txt", "some file to be renamed");
|
||||
outgoing.rm().addFilepattern("d.txt").call();
|
||||
RevCommit targetCommit = commit(outgoing, "move/rename file");
|
||||
|
||||
outgoing.checkout().setName("some_branch").setCreateBranch(true).setStartPoint(baseCommit).call();
|
||||
write(outgoing, outgoingDirectory, "x.txt", "bla bla");
|
||||
RevCommit otherBranchCommit = commit(outgoing, "other branch");
|
||||
|
||||
Modifications modifications = outgoingModificationsCommand.getModifications(otherBranchCommit.getName(), targetCommit.getName());
|
||||
|
||||
assertThat(modifications.getModifications())
|
||||
.hasSize(4)
|
||||
.extracting("class.simpleName")
|
||||
.contains("Modified") // File a.txt has been modified
|
||||
.contains("Removed") // File x.txt from the other branch is not present
|
||||
.contains("Added") // File c.txt has been created on the original branch
|
||||
.contains("Renamed") // File d.txt has been renamed on the original branch
|
||||
;
|
||||
}
|
||||
|
||||
void pushOutgoingAndPullIncoming() throws IOException {
|
||||
GitPushCommand cmd = new GitPushCommand(handler, new GitContext(outgoingDirectory, outgoingRepository, null, new GitConfig()));
|
||||
PushCommandRequest request = new PushCommandRequest();
|
||||
|
||||
Reference in New Issue
Block a user