@@ -, +, @@
- compare any two revisions
- compare working tree to any revision
--- a/libs.git/apichanges.xml Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/apichanges.xml Tue Mar 12 11:42:29 2013 +0100
@@ -111,6 +111,25 @@
+ Adding support comparing trees of arbitrary commits
+
+
+
+
+
+
+ - Adding a new method GitClient.getStatus(File[], String, ProgressMonitor)
+ allowing an API client to get statuses of local files not just against the HEAD but against
+ an arbitrary commit.
+ - Adding a new method GitClient.getStatus(File[], String, String, ProgressMonitor)
+ allowing an API client to get modifications from the Git history. It is similar to
+ GitRevisionInfo.getModifications but returns file statuses between two arbitrary commits
+ and not just a commit and its parent.
+
+
+
+
+
Adding support for rebase to the API
--- a/libs.git/manifest.mf Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/manifest.mf Tue Mar 12 11:42:29 2013 +0100
@@ -1,4 +1,4 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.libs.git/1
OpenIDE-Module-Localizing-Bundle: org/netbeans/libs/git/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.8
+OpenIDE-Module-Specification-Version: 1.9
--- a/libs.git/src/org/netbeans/libs/git/GitClassFactoryImpl.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/GitClassFactoryImpl.java Tue Mar 12 11:42:29 2013 +0100
@@ -60,6 +60,7 @@
import org.eclipse.jgit.transport.URIish;
import org.netbeans.libs.git.GitConflictDescriptor.Type;
import org.netbeans.libs.git.GitRevertResult.Status;
+import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
import org.netbeans.libs.git.jgit.GitClassFactory;
/**
@@ -92,6 +93,11 @@
}
@Override
+ public GitFileInfo createFileInfo (File file, String oldPath, GitFileInfo.Status status, File originalFile, String originalPath) {
+ return new GitFileInfo(file, oldPath, status, originalFile, originalPath);
+ }
+
+ @Override
public GitMergeResult createMergeResult (MergeResult mergeResult, File workTree) {
return new GitMergeResult(mergeResult, workTree);
}
--- a/libs.git/src/org/netbeans/libs/git/GitClient.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/GitClient.java Tue Mar 12 11:42:29 2013 +0100
@@ -49,9 +49,11 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
+import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
import org.netbeans.libs.git.jgit.GitClassFactory;
import org.netbeans.libs.git.jgit.JGitCredentialsProvider;
import org.netbeans.libs.git.jgit.JGitRepository;
@@ -62,6 +64,7 @@
import org.netbeans.libs.git.jgit.commands.CheckoutRevisionCommand;
import org.netbeans.libs.git.jgit.commands.CleanCommand;
import org.netbeans.libs.git.jgit.commands.CommitCommand;
+import org.netbeans.libs.git.jgit.commands.CompareCommand;
import org.netbeans.libs.git.jgit.commands.ConflictCommand;
import org.netbeans.libs.git.jgit.commands.CopyCommand;
import org.netbeans.libs.git.jgit.commands.CreateBranchCommand;
@@ -603,19 +606,56 @@
}
/**
- * Returns an array of statuses for files under given roots
+ * Compares the working tree with the current HEAD and returns an array of
+ * statuses for files under given roots
+ *
* @param roots root folders or files to search under
* @return status array
* @throws GitException an unexpected error occurs
*/
public Map getStatus (File[] roots, ProgressMonitor monitor) throws GitException {
+ return getStatus(roots, Constants.HEAD, monitor);
+ }
+
+ /**
+ * Compares working tree with a given revision and returns an array of
+ * statuses for files under given roots
+ *
+ * @param roots root folders or files to search under
+ * @param revision revision to compare with the working tree. If set
+ * to null
HEAD will be used instead.
+ * @return status array
+ * @throws GitException an unexpected error occurs
+ * @since 1.9
+ */
+ public Map getStatus (File[] roots, String revision, ProgressMonitor monitor) throws GitException {
Repository repository = gitRepository.getRepository();
- StatusCommand cmd = new StatusCommand(repository, getClassFactory(), roots, monitor, delegateListener);
+ StatusCommand cmd = new StatusCommand(repository, revision == null ? Constants.HEAD : revision,
+ roots, getClassFactory(), monitor, delegateListener);
cmd.execute();
return cmd.getStatuses();
}
/**
+ * Compares two different commit trees and returns an array of file
+ * modifications between revisionFirst
and revisionSecond
+ *
+ * @param roots root folders or files to search under
+ * @param revisionFirst first revision to compare
+ * @param revisionSecond second revision to compare
+ * @return status array
+ * @throws GitException an unexpected error occurs
+ * @since 1.9
+ */
+ public Map getStatus (File[] roots, String revisionFirst, String revisionSecond, ProgressMonitor monitor) throws GitException {
+ Repository repository = gitRepository.getRepository();
+ CompareCommand cmd = new CompareCommand(repository, revisionFirst, revisionSecond, roots,
+ getClassFactory(), monitor);
+ cmd.execute();
+ return cmd.getFileDifferences();
+ }
+
+ /**
* Returns remote configuration set up for this repository identified by a given remoteName
* @param remoteName name under which the remote is stored in repository's config file
* @param monitor progress monitor
--- a/libs.git/src/org/netbeans/libs/git/GitRevisionInfo.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/GitRevisionInfo.java Tue Mar 12 11:42:29 2013 +0100
@@ -50,8 +50,6 @@
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
-import org.eclipse.jgit.diff.DiffEntry;
-import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
@@ -62,6 +60,7 @@
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.netbeans.libs.git.jgit.Utils;
/**
* Provides information about a certain commit, usually is returned by
@@ -164,7 +163,7 @@
RevWalk revWalk = new RevWalk(repository);
TreeWalk walk = new TreeWalk(repository);
try {
- ArrayList result = new ArrayList();
+ List result;
walk.reset();
walk.setRecursive(true);
RevCommit parentCommit = null;
@@ -184,52 +183,9 @@
walk.addTree(revCommit.getTree().getId());
walk.setFilter(AndTreeFilter.create(TreeFilter.ANY_DIFF, PathFilter.ANY_DIFF));
if (parentCommit != null) {
- List entries = DiffEntry.scan(walk);
- RenameDetector rd = new RenameDetector(repository);
- rd.addAll(entries);
- entries = rd.compute();
- for (DiffEntry e : entries) {
- GitFileInfo.Status status;
- File oldFile = null;
- String oldPath = null;
- String path = e.getOldPath();
- if (path == null) {
- path = e.getNewPath();
- }
- switch (e.getChangeType()) {
- case ADD:
- status = GitFileInfo.Status.ADDED;
- path = e.getNewPath();
- break;
- case COPY:
- status = GitFileInfo.Status.COPIED;
- oldFile = new File(repository.getWorkTree(), e.getOldPath());
- oldPath = e.getOldPath();
- path = e.getNewPath();
- break;
- case DELETE:
- status = GitFileInfo.Status.REMOVED;
- path = e.getOldPath();
- break;
- case MODIFY:
- status = GitFileInfo.Status.MODIFIED;
- path = e.getOldPath();
- break;
- case RENAME:
- status = GitFileInfo.Status.RENAMED;
- oldFile = new File(repository.getWorkTree(), e.getOldPath());
- oldPath = e.getOldPath();
- path = e.getNewPath();
- break;
- default:
- status = GitFileInfo.Status.UNKNOWN;
- }
- if (status == GitFileInfo.Status.RENAMED) {
- result.add(new GitFileInfo(new File(repository.getWorkTree(), e.getOldPath()), e.getOldPath(), GitFileInfo.Status.REMOVED, null, null));
- }
- result.add(new GitFileInfo(new File(repository.getWorkTree(), path), path, status, oldFile, oldPath));
- }
+ result = Utils.getDiffEntries(repository, walk, GitClassFactoryImpl.getInstance());
} else {
+ result = new ArrayList();
while (walk.next()) {
result.add(new GitFileInfo(new File(repository.getWorkTree(), walk.getPathString()), walk.getPathString(), GitFileInfo.Status.ADDED, null, null));
}
--- a/libs.git/src/org/netbeans/libs/git/jgit/GitClassFactory.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/jgit/GitClassFactory.java Tue Mar 12 11:42:29 2013 +0100
@@ -69,6 +69,7 @@
import org.netbeans.libs.git.GitRemoteConfig;
import org.netbeans.libs.git.GitRevertResult;
import org.netbeans.libs.git.GitRevisionInfo;
+import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
import org.netbeans.libs.git.GitStatus;
import org.netbeans.libs.git.GitStatus.Status;
import org.netbeans.libs.git.GitTag;
@@ -86,6 +87,8 @@
public abstract GitBranch createBranch (String name, boolean remote, boolean active, ObjectId id);
public abstract GitConflictDescriptor createConflictDescriptor (Type type);
+
+ public abstract GitFileInfo createFileInfo (File file, String oldPath, GitFileInfo.Status status, File originalFile, String originalPath);
public abstract GitMergeResult createMergeResult (MergeResult mergeResult, File workTree);
--- a/libs.git/src/org/netbeans/libs/git/jgit/Utils.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/jgit/Utils.java Tue Mar 12 11:42:29 2013 +0100
@@ -55,6 +55,8 @@
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -79,6 +81,8 @@
import org.netbeans.libs.git.GitBranch;
import org.netbeans.libs.git.GitException;
import org.netbeans.libs.git.GitObjectType;
+import org.netbeans.libs.git.GitRevisionInfo;
+import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
/**
*
@@ -119,6 +123,56 @@
return filter;
}
+ public static List getDiffEntries (Repository repository, TreeWalk walk, GitClassFactory fac) throws IOException {
+ List result = new ArrayList();
+ List entries = DiffEntry.scan(walk);
+ RenameDetector rd = new RenameDetector(repository);
+ rd.addAll(entries);
+ entries = rd.compute();
+ for (DiffEntry e : entries) {
+ GitRevisionInfo.GitFileInfo.Status status;
+ File oldFile = null;
+ String oldPath = null;
+ String path = e.getOldPath();
+ if (path == null) {
+ path = e.getNewPath();
+ }
+ switch (e.getChangeType()) {
+ case ADD:
+ status = GitRevisionInfo.GitFileInfo.Status.ADDED;
+ path = e.getNewPath();
+ break;
+ case COPY:
+ status = GitRevisionInfo.GitFileInfo.Status.COPIED;
+ oldFile = new File(repository.getWorkTree(), e.getOldPath());
+ oldPath = e.getOldPath();
+ path = e.getNewPath();
+ break;
+ case DELETE:
+ status = GitRevisionInfo.GitFileInfo.Status.REMOVED;
+ path = e.getOldPath();
+ break;
+ case MODIFY:
+ status = GitRevisionInfo.GitFileInfo.Status.MODIFIED;
+ path = e.getOldPath();
+ break;
+ case RENAME:
+ status = GitRevisionInfo.GitFileInfo.Status.RENAMED;
+ oldFile = new File(repository.getWorkTree(), e.getOldPath());
+ oldPath = e.getOldPath();
+ path = e.getNewPath();
+ break;
+ default:
+ status = GitRevisionInfo.GitFileInfo.Status.UNKNOWN;
+ }
+ if (status == GitRevisionInfo.GitFileInfo.Status.RENAMED) {
+ result.add(fac.createFileInfo(new File(repository.getWorkTree(), e.getOldPath()), e.getOldPath(), GitRevisionInfo.GitFileInfo.Status.REMOVED, null, null));
+ }
+ result.add(fac.createFileInfo(new File(repository.getWorkTree(), path), path, status, oldFile, oldPath));
+ }
+ return result;
+ }
+
private static Collection getPathFilters (Collection relativePaths) {
Collection filters = new LinkedList();
for (String path : relativePaths) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ 236d21a95856 Tue Mar 12 11:42:29 2013 +0100
@@ -0,0 +1,130 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.libs.git.jgit.commands;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.*;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.netbeans.libs.git.GitException;
+import org.netbeans.libs.git.GitRevisionInfo;
+import org.netbeans.libs.git.jgit.GitClassFactory;
+import org.netbeans.libs.git.jgit.Utils;
+import org.netbeans.libs.git.progress.ProgressMonitor;
+
+/**
+ *
+ * @author ondra
+ */
+public class CompareCommand extends GitCommand {
+ private final LinkedHashMap statuses;
+ private final File[] roots;
+ private final String revisionFirst;
+ private final String revisionSecond;
+
+ public CompareCommand (Repository repository, String revisionFirst, String revisionSecond, File[] roots,
+ GitClassFactory gitFactory, ProgressMonitor monitor) {
+ super(repository, gitFactory, monitor);
+ this.roots = roots;
+ this.revisionFirst = revisionFirst;
+ this.revisionSecond = revisionSecond;
+ statuses = new LinkedHashMap();
+ }
+
+ @Override
+ protected String getCommandDescription () {
+ StringBuilder sb = new StringBuilder("git diff --raw"); //NOI18N
+ sb.append(revisionFirst).append(' ').append(revisionSecond);
+ for (File root : roots) {
+ sb.append(" ").append(root.getAbsolutePath());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ protected boolean prepareCommand () throws GitException {
+ return getRepository().getDirectory().exists();
+ }
+
+ @Override
+ protected void run () throws GitException {
+ Repository repository = getRepository();
+ TreeWalk walk = new TreeWalk(repository);
+ try {
+ walk.reset();
+ walk.setRecursive(true);
+ walk.addTree(Utils.findCommit(repository, revisionFirst).getTree());
+ walk.addTree(Utils.findCommit(repository, revisionSecond).getTree());
+ Collection pathFilters = Utils.getPathFilters(repository.getWorkTree(), roots);
+ if (pathFilters.isEmpty()) {
+ walk.setFilter(AndTreeFilter.create(TreeFilter.ANY_DIFF, PathFilter.ANY_DIFF));
+ } else {
+ walk.setFilter(AndTreeFilter.create(new TreeFilter[] {
+ TreeFilter.ANY_DIFF,
+ PathFilter.ANY_DIFF,
+ PathFilterGroup.create(pathFilters)
+ }));
+ }
+ List infos = Utils.getDiffEntries(repository, walk, getClassFactory());
+ for (GitRevisionInfo.GitFileInfo info : infos) {
+ statuses.put(info.getFile(), info);
+ }
+ } catch (IOException ex) {
+ throw new GitException(ex);
+ } finally {
+ walk.release();
+ }
+ }
+
+ public Map getFileDifferences () {
+ return statuses;
+ }
+}
--- a/libs.git/src/org/netbeans/libs/git/jgit/commands/ConflictCommand.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/jgit/commands/ConflictCommand.java Tue Mar 12 11:42:29 2013 +0100
@@ -49,6 +49,7 @@
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
@@ -72,7 +73,7 @@
private final File[] roots;
public ConflictCommand (Repository repository, GitClassFactory gitFactory, File[] roots, ProgressMonitor monitor, StatusListener listener) {
- super(repository, gitFactory, roots, monitor, listener);
+ super(repository, Constants.HEAD, roots, gitFactory, monitor, listener);
this.monitor = monitor;
this.listener = listener;
this.roots = roots;
--- a/libs.git/src/org/netbeans/libs/git/jgit/commands/RebaseCommand.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/jgit/commands/RebaseCommand.java Tue Mar 12 11:42:29 2013 +0100
@@ -162,8 +162,8 @@
Repository repository = getRepository();
GitRevisionInfo info = getClassFactory().createRevisionInfo(currentCommit, repository);
Map modifiedFiles = info.getModifiedFiles();
- StatusCommand cmd = new StatusCommand(repository, getClassFactory(), modifiedFiles.keySet().toArray(
- new File[modifiedFiles.keySet().size()]),
+ StatusCommand cmd = new StatusCommand(repository, Constants.HEAD, modifiedFiles.keySet().toArray(
+ new File[modifiedFiles.keySet().size()]), getClassFactory(),
new DelegatingGitProgressMonitor(monitor),
new StatusListener() {
@Override
--- a/libs.git/src/org/netbeans/libs/git/jgit/commands/StatusCommand.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/src/org/netbeans/libs/git/jgit/commands/StatusCommand.java Tue Mar 12 11:42:29 2013 +0100
@@ -95,19 +95,27 @@
private final File[] roots;
private final ProgressMonitor monitor;
private final StatusListener listener;
+ private final String revision;
private static final String PROP_TRACK_SYMLINKS = "org.netbeans.libs.git.trackSymLinks"; //NOI18N
- public StatusCommand (Repository repository, GitClassFactory gitFactory, File[] roots, ProgressMonitor monitor, StatusListener listener) {
+ public StatusCommand (Repository repository, String revision, File[] roots, GitClassFactory gitFactory,
+ ProgressMonitor monitor, StatusListener listener) {
super(repository, gitFactory, monitor);
this.roots = roots;
this.monitor = monitor;
this.listener = listener;
+ this.revision = revision;
statuses = new LinkedHashMap();
}
@Override
protected String getCommandDescription () {
- StringBuilder sb = new StringBuilder("git status"); //NOI18N
+ StringBuilder sb = new StringBuilder("git "); //NOI18N
+ if (Constants.HEAD.equals(revision)) {
+ sb.append("status"); //NOI18N
+ } else {
+ sb.append("diff --raw"); //NOI18N
+ }
for (File root : roots) {
sb.append(" ").append(root.getAbsolutePath());
}
@@ -128,16 +136,16 @@
try {
String workTreePath = repository.getWorkTree().getAbsolutePath();
Collection pathFilters = Utils.getPathFilters(repository.getWorkTree(), roots);
- Map renames = detectRenames(repository, cache);
+ ObjectId commitId = Utils.parseObjectId(repository, revision);
+ Map renames = detectRenames(repository, cache, commitId);
TreeWalk treeWalk = new TreeWalk(repository);
if (!pathFilters.isEmpty()) {
treeWalk.setFilter(PathFilterGroup.create(pathFilters));
}
treeWalk.setRecursive(false);
treeWalk.reset();
- ObjectId headId = repository.resolve(Constants.HEAD);
- if (headId != null) {
- treeWalk.addTree(new RevWalk(repository).parseTree(headId));
+ if (commitId != null) {
+ treeWalk.addTree(new RevWalk(repository).parseTree(commitId));
} else {
treeWalk.addTree(new EmptyTreeIterator());
}
@@ -145,7 +153,7 @@
treeWalk.addTree(new DirCacheIterator(cache));
// Working directory
treeWalk.addTree(new FileTreeIterator(repository));
- final int T_HEAD = 0;
+ final int T_COMMIT = 0;
final int T_INDEX = 1;
final int T_WORKSPACE = 2;
String lastPath = null;
@@ -166,7 +174,7 @@
}
lastPath = path;
File file = new File(workTreePath + File.separator + path);
- int mHead = treeWalk.getRawMode(T_HEAD);
+ int mHead = treeWalk.getRawMode(T_COMMIT);
int mIndex = treeWalk.getRawMode(T_INDEX);
int mWorking = treeWalk.getRawMode(T_WORKSPACE);
GitStatus.Status statusHeadIndex;
@@ -177,7 +185,7 @@
statusHeadIndex = GitStatus.Status.STATUS_ADDED;
} else if (mIndex == FileMode.MISSING.getBits() && mHead != FileMode.MISSING.getBits()) {
statusHeadIndex = GitStatus.Status.STATUS_REMOVED;
- } else if (mHead != mIndex || (mIndex != FileMode.TREE.getBits() && !treeWalk.idEqual(T_HEAD, T_INDEX))) {
+ } else if (mHead != mIndex || (mIndex != FileMode.TREE.getBits() && !treeWalk.idEqual(T_COMMIT, T_INDEX))) {
statusHeadIndex = GitStatus.Status.STATUS_MODIFIED;
} else {
statusHeadIndex = GitStatus.Status.STATUS_NORMAL;
@@ -234,7 +242,7 @@
&& (indexEntry == null || !indexEntry.isAssumeValid()) //no update-index --assume-unchanged
// head vs wt can be modified only when head vs index or index vs wt are modified, otherwise it's probably line-endings issue
&& (statusIndexWC != GitStatus.Status.STATUS_NORMAL || statusHeadIndex != GitStatus.Status.STATUS_NORMAL)
- && !treeWalk.getObjectId(T_HEAD).equals(fti.getEntryObjectId())))) {
+ && !treeWalk.getObjectId(T_COMMIT).equals(fti.getEntryObjectId())))) {
statusHeadWC = GitStatus.Status.STATUS_MODIFIED;
} else {
statusHeadWC = GitStatus.Status.STATUS_NORMAL;
@@ -271,15 +279,14 @@
return statuses;
}
- private Map detectRenames (Repository repository, DirCache cache) {
+ private Map detectRenames (Repository repository, DirCache cache, ObjectId commitId) {
List entries;
TreeWalk treeWalk = new TreeWalk(repository);
try {
treeWalk.setRecursive(true);
treeWalk.reset();
- ObjectId headId = repository.resolve(Constants.HEAD);
- if (headId != null) {
- treeWalk.addTree(new RevWalk(repository).parseTree(headId));
+ if (commitId != null) {
+ treeWalk.addTree(new RevWalk(repository).parseTree(commitId));
} else {
treeWalk.addTree(new EmptyTreeIterator());
}
--- a/libs.git/test/unit/src/org/netbeans/libs/git/jgit/CommandsTestSuite.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/test/unit/src/org/netbeans/libs/git/jgit/CommandsTestSuite.java Tue Mar 12 11:42:29 2013 +0100
@@ -53,6 +53,7 @@
import org.netbeans.libs.git.jgit.commands.CheckoutTest;
import org.netbeans.libs.git.jgit.commands.CleanTest;
import org.netbeans.libs.git.jgit.commands.CommitTest;
+import org.netbeans.libs.git.jgit.commands.CompareCommitTest;
import org.netbeans.libs.git.jgit.commands.CopyTest;
import org.netbeans.libs.git.jgit.commands.ExportCommitTest;
import org.netbeans.libs.git.jgit.commands.ExportDiffTest;
@@ -97,6 +98,7 @@
suite.addTestSuite(CheckoutTest.class);
suite.addTestSuite(CleanTest.class);
suite.addTestSuite(CommitTest.class);
+ suite.addTestSuite(CompareCommitTest.class);
suite.addTestSuite(CopyTest.class);
suite.addTestSuite(ExportCommitTest.class);
suite.addTestSuite(ExportDiffTest.class);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ 236d21a95856 Tue Mar 12 11:42:29 2013 +0100
@@ -0,0 +1,181 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.libs.git.jgit.commands;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import static junit.framework.Assert.assertEquals;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.netbeans.libs.git.GitClient;
+import org.netbeans.libs.git.GitRevisionInfo;
+import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo.Status;
+import org.netbeans.libs.git.jgit.AbstractGitTestCase;
+
+/**
+ *
+ * @author ondra
+ */
+public class CompareCommitTest extends AbstractGitTestCase {
+ private Repository repository;
+ private File workDir;
+
+ public CompareCommitTest (String testName) throws IOException {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ workDir = getWorkingDirectory();
+ repository = getRepository(getLocalGitRepository());
+ }
+
+ public void testCompareSimple () throws Exception {
+ File file = new File(workDir, "file");
+ File[] files = new File[] { file };
+ write(file, "init\n");
+ add(files);
+ commit(files);
+
+ GitClient client = getClient(workDir);
+ String revision1 = client.getBranches(false, NULL_PROGRESS_MONITOR).get(Constants.MASTER).getId();
+ write(file, "modification\n");
+ add(files);
+ GitRevisionInfo revision2 = client.commit(files, "my commit message", null, null, NULL_PROGRESS_MONITOR);
+ Map statuses = client.getStatus(files, Constants.HEAD, revision1, NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+
+ write(file, "modification 2\n");
+ add(files);
+ GitRevisionInfo revision3 = client.commit(files, "my commit 3 message", null, null, NULL_PROGRESS_MONITOR);
+ statuses = client.getStatus(files, revision1, Constants.HEAD, NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+
+ statuses = client.getStatus(files, revision1, revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+
+ statuses = client.getStatus(files, revision2.getRevision(), revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+ }
+
+ public void testCompareRevertModification () throws Exception {
+ File file = new File(workDir, "file");
+ File[] files = new File[] { file };
+ write(file, "init\n");
+ add(files);
+ commit(files);
+
+ GitClient client = getClient(workDir);
+ String revision1 = client.getBranches(false, NULL_PROGRESS_MONITOR).get(Constants.MASTER).getId();
+ write(file, "modification\n");
+ add(files);
+ GitRevisionInfo revision2 = client.commit(files, "my commit message", null, null, NULL_PROGRESS_MONITOR);
+
+ write(file, "init\n");
+ add(files);
+ GitRevisionInfo revision3 = client.commit(files, "my commit 3 message", null, null, NULL_PROGRESS_MONITOR);
+ Map statuses = client.getStatus(files, revision1, Constants.HEAD, NULL_PROGRESS_MONITOR);
+ assertTrue(statuses.isEmpty());
+ }
+
+ public void testCompareSelection () throws Exception {
+ File file = new File(workDir, "file");
+ File file2 = new File(workDir, "file2");
+ File[] files = new File[] { file, file2 };
+ write(file, "init\n");
+ add(files);
+ commit(files);
+
+ GitClient client = getClient(workDir);
+ String revision1 = client.getBranches(false, NULL_PROGRESS_MONITOR).get(Constants.MASTER).getId();
+ write(file, "modification\n");
+ add(files);
+ GitRevisionInfo revision2 = client.commit(files, "my commit message", null, null, NULL_PROGRESS_MONITOR);
+
+ write(file2, "adding file 2\n");
+ add(files);
+ GitRevisionInfo revision3 = client.commit(files, "adding file 2", null, null, NULL_PROGRESS_MONITOR);
+ Map statuses = client.getStatus(new File[] { file }, revision1, revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+
+ statuses = client.getStatus(new File[] { file2 }, revision1, revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(1, statuses.size());
+ assertEquals(Status.ADDED, statuses.get(file2).getStatus());
+
+ statuses = client.getStatus(files, revision1, revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(2, statuses.size());
+ assertEquals(Status.MODIFIED, statuses.get(file).getStatus());
+ assertEquals(Status.ADDED, statuses.get(file2).getStatus());
+ }
+
+ public void testCompareRename () throws Exception {
+ File file = new File(workDir, "file");
+ File file2 = new File(workDir, "file2");
+ File[] files = new File[] { file, file2 };
+ write(file, "files content\n");
+ add(files);
+ commit(files);
+
+ GitClient client = getClient(workDir);
+ String revision1 = client.getBranches(false, NULL_PROGRESS_MONITOR).get(Constants.MASTER).getId();
+ remove(false, file);
+
+ client.commit(files, "removing file", null, null, NULL_PROGRESS_MONITOR);
+
+ write(file2, "files content\n");
+ add(files);
+ GitRevisionInfo revision3 = client.commit(files, "adding file as file2", null, null, NULL_PROGRESS_MONITOR);
+ Map statuses = client.getStatus(files, revision1, revision3.getRevision(), NULL_PROGRESS_MONITOR);
+ assertEquals(2, statuses.size());
+ assertEquals(Status.REMOVED, statuses.get(file).getStatus());
+ assertEquals(Status.RENAMED, statuses.get(file2).getStatus());
+ assertEquals(file, statuses.get(file2).getOriginalFile());
+ }
+}
--- a/libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/StatusTest.java Tue Mar 12 11:37:35 2013 +0100
+++ a/libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/StatusTest.java Tue Mar 12 11:42:29 2013 +0100
@@ -45,11 +45,12 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import org.eclipse.jgit.api.Git;
+import static junit.framework.Assert.assertFalse;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.netbeans.libs.git.GitClient;
@@ -166,6 +167,120 @@
// what about isIgnored() here?
assertStatus(statuses, workDir, ignored, false, Status.STATUS_NORMAL, Status.STATUS_IGNORED, Status.STATUS_ADDED, false, listener);
}
+
+ // diff WT against a commit other than HEAD
+ public void testMiscStatusCommit () throws Exception {
+ write(new File(workDir, ".gitignore"), "ignored");
+ File untracked = new File(workDir, "untracked");
+ write(untracked, "untracked");
+ File ignored = new File(workDir, "ignored");
+ write(ignored, "ignored");
+ File added_uptodate = new File(workDir, "added-uptodate");
+ write(added_uptodate, "added-uptodate");
+ File added_modified = new File(workDir, "added-modified");
+ write(added_modified, "added_modified");
+ File added_deleted = new File(workDir, "added-deleted");
+ write(added_deleted, "added_deleted");
+
+ File uptodate_uptodate = new File(workDir, "uptodate-uptodate");
+ write(uptodate_uptodate, "uptodate_uptodate");
+ File uptodate_modified = new File(workDir, "uptodate-modified");
+ write(uptodate_modified, "uptodate_modified");
+ File uptodate_deleted = new File(workDir, "uptodate-deleted");
+ write(uptodate_deleted, "uptodate_deleted");
+
+ File modified_uptodate = new File(workDir, "modified-uptodate");
+ write(modified_uptodate, "modified_uptodate");
+ File modified_modified = new File(workDir, "modified-modified");
+ write(modified_modified, "modified_modified");
+ File modified_reset = new File(workDir, "modified-reset");
+ write(modified_reset, "modified_reset");
+ File modified_deleted = new File(workDir, "modified-deleted");
+ write(modified_deleted, "modified_deleted");
+
+ // we cannot
+ File deleted_uptodate = new File(workDir, "deleted-uptodate");
+ write(deleted_uptodate, "deleted_uptodate");
+ File deleted_untracked = new File(workDir, "deleted-untracked");
+ write(deleted_untracked, "deleted_untracked");
+ File deleted_modified = new File(workDir, "deleted-modified");
+ write(deleted_modified, "deleted_modified");
+
+ add(uptodate_uptodate, uptodate_modified, uptodate_deleted, modified_uptodate, modified_modified, modified_reset, modified_deleted, deleted_uptodate, deleted_untracked, deleted_modified);
+ commit(workDir);
+ add(added_uptodate, added_modified, added_deleted);
+ write(modified_deleted, "modification modified_deleted");
+ write(modified_modified, "modification modified_modified");
+ write(modified_reset, "modification modified_reset");
+ write(modified_uptodate, "modification modified_uptodate");
+ add(modified_deleted, modified_modified, modified_reset, modified_uptodate);
+ deleted_uptodate.delete();
+ deleted_untracked.delete();
+ deleted_modified.delete();
+ remove(true, deleted_uptodate, deleted_untracked, deleted_modified);
+ write(added_modified, "modification2 added_modified");
+ write(uptodate_modified, "modification2 uptodate_modified");
+ write(modified_modified, "modification2 modified_modified");
+ write(modified_reset, "modified_reset");
+ added_deleted.delete();
+ modified_deleted.delete();
+ uptodate_deleted.delete();
+ write(deleted_untracked, "deleted_untracked");
+ write(deleted_modified, "deleted_modified\nchange");
+
+ GitClient client = getClient(workDir);
+ String revId = client.getBranches(false, NULL_PROGRESS_MONITOR).get(Constants.MASTER).getId();
+
+ File someFile = new File(workDir, "fileforothercommit");
+ write(someFile, "fileforothercommit");
+ add(someFile);
+ commit(someFile);
+
+ TestStatusListener listener = new TestStatusListener();
+ client.addNotificationListener(listener);
+ Map statuses = client.getStatus(new File[] { workDir }, Constants.HEAD, NULL_PROGRESS_MONITOR);
+ assertFalse(statuses.isEmpty());
+ assertStatus(statuses, workDir, untracked, false, Status.STATUS_NORMAL, Status.STATUS_ADDED, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_uptodate, true, Status.STATUS_ADDED, Status.STATUS_NORMAL, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_modified, true, Status.STATUS_ADDED, Status.STATUS_MODIFIED, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_deleted, true, Status.STATUS_ADDED, Status.STATUS_REMOVED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, uptodate_uptodate, true, Status.STATUS_NORMAL, Status.STATUS_NORMAL, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, uptodate_modified, true, Status.STATUS_NORMAL, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, uptodate_deleted, true, Status.STATUS_NORMAL, Status.STATUS_REMOVED, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, modified_uptodate, true, Status.STATUS_MODIFIED, Status.STATUS_NORMAL, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, modified_modified, true, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, modified_reset, true, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, modified_deleted, true, Status.STATUS_MODIFIED, Status.STATUS_REMOVED, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, deleted_uptodate, true, Status.STATUS_REMOVED, Status.STATUS_NORMAL, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, deleted_untracked, true, Status.STATUS_REMOVED, Status.STATUS_ADDED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, deleted_modified, true, Status.STATUS_REMOVED, Status.STATUS_ADDED, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, someFile, true, Status.STATUS_NORMAL, Status.STATUS_NORMAL, Status.STATUS_NORMAL, false, listener);
+ // what about isIgnored() here?
+ assertStatus(statuses, workDir, ignored, false, Status.STATUS_NORMAL, Status.STATUS_IGNORED, Status.STATUS_ADDED, false, listener);
+
+ listener = new TestStatusListener();
+ client.addNotificationListener(listener);
+ statuses = client.getStatus(new File[] { workDir }, revId, NULL_PROGRESS_MONITOR);
+ assertFalse(statuses.isEmpty());
+ assertStatus(statuses, workDir, untracked, false, Status.STATUS_NORMAL, Status.STATUS_ADDED, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_uptodate, true, Status.STATUS_ADDED, Status.STATUS_NORMAL, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_modified, true, Status.STATUS_ADDED, Status.STATUS_MODIFIED, Status.STATUS_ADDED, false, listener);
+ assertStatus(statuses, workDir, added_deleted, true, Status.STATUS_ADDED, Status.STATUS_REMOVED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, uptodate_uptodate, true, Status.STATUS_NORMAL, Status.STATUS_NORMAL, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, uptodate_modified, true, Status.STATUS_NORMAL, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, uptodate_deleted, true, Status.STATUS_NORMAL, Status.STATUS_REMOVED, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, modified_uptodate, true, Status.STATUS_MODIFIED, Status.STATUS_NORMAL, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, modified_modified, true, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, false, listener);
+ assertStatus(statuses, workDir, modified_reset, true, Status.STATUS_MODIFIED, Status.STATUS_MODIFIED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, modified_deleted, true, Status.STATUS_MODIFIED, Status.STATUS_REMOVED, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, deleted_uptodate, true, Status.STATUS_REMOVED, Status.STATUS_NORMAL, Status.STATUS_REMOVED, false, listener);
+ assertStatus(statuses, workDir, deleted_untracked, true, Status.STATUS_REMOVED, Status.STATUS_ADDED, Status.STATUS_NORMAL, false, listener);
+ assertStatus(statuses, workDir, deleted_modified, true, Status.STATUS_REMOVED, Status.STATUS_ADDED, Status.STATUS_MODIFIED, false, listener);
+ // what about isIgnored() here?
+ assertStatus(statuses, workDir, ignored, false, Status.STATUS_NORMAL, Status.STATUS_IGNORED, Status.STATUS_ADDED, false, listener);
+ // file somefile was not known in that revision
+ assertStatus(statuses, workDir, someFile, true, Status.STATUS_ADDED, Status.STATUS_NORMAL, Status.STATUS_ADDED, false, listener);
+ }
public void testStatusSingleFile () throws Exception {
File untracked = new File(workDir, "untracked");