/*
*
* * Copyright 2013-2014 Urs Wolfer
* *
* * 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.urswolfer.intellij.plugin.gerrit.ui.changesbrowser;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.urswolfer.intellij.plugin.gerrit.util.PathUtils;
import git4idea.GitCommit;
import git4idea.changes.GitChangeUtils;
import java.util.Collection;
/**
* This class diffs commits based in IntelliJ git4idea code and adds support for diffing commit msg.
*
* @author Thomas Forrer
*/
public class CommitDiffBuilder {
private static final Predicate<Change> COMMIT_MSG_CHANGE_PREDICATE = new Predicate<Change>() {
@Override
public boolean apply(Change change) {
String commitMsgFile = "/COMMIT_MSG";
ContentRevision afterRevision = change.getAfterRevision();
if (afterRevision != null) {
return commitMsgFile.equals(PathUtils.ensureSlashSeparators(afterRevision.getFile().getPath()));
}
ContentRevision beforeRevision = change.getBeforeRevision();
if (beforeRevision != null) {
return commitMsgFile.equals(PathUtils.ensureSlashSeparators(beforeRevision.getFile().getPath()));
}
throw new IllegalStateException("Change should have at least one ContentRevision set.");
}
};
private final Project project;
private final VirtualFile gitRepositoryRoot;
private final GitCommit base;
private final GitCommit commit;
private ChangesProvider changesProvider = new SimpleChangesProvider();
public CommitDiffBuilder(Project project, VirtualFile gitRepositoryRoot, GitCommit base, GitCommit commit) {
this.project = project;
this.gitRepositoryRoot = gitRepositoryRoot;
this.base = base;
this.commit = commit;
}
public CommitDiffBuilder withChangesProvider(ChangesProvider changesProvider) {
this.changesProvider = changesProvider;
return this;
}
public Collection<Change> getDiff() throws VcsException {
String baseHash = base.getId().asString();
String hash = commit.getId().asString();
Collection<Change> result = GitChangeUtils.getDiff(project, gitRepositoryRoot, baseHash, hash, null);
result.add(buildCommitMsgChange());
return result;
}
private Change buildCommitMsgChange() {
Change baseChange = Iterables.find(changesProvider.provide(base), COMMIT_MSG_CHANGE_PREDICATE);
ContentRevision baseRevision = baseChange.getAfterRevision();
Change change = Iterables.find(changesProvider.provide(commit), COMMIT_MSG_CHANGE_PREDICATE);
ContentRevision revision = change.getAfterRevision();
return new Change(baseRevision, revision);
}
public static interface ChangesProvider {
Collection<Change> provide(GitCommit gitCommit);
}
private static final class SimpleChangesProvider implements ChangesProvider {
@Override
public Collection<Change> provide(GitCommit gitCommit) {
return gitCommit.getChanges();
}
}
}