Browse Source

Merge "Added new Status CLI command 'jgit status'"

stable-2.2
Matthias Sohn 12 years ago committed by Gerrit Code Review @ Eclipse.org
parent
commit
e5cd1d4add
  1. 1
      org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
  2. 4
      org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java
  3. 230
      org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/StatusTest.java
  4. 1
      org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
  5. 13
      org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties
  6. 34
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java
  7. 167
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java

1
org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF

@ -12,6 +12,7 @@ Import-Package: org.eclipse.jgit.api;version="[2.1.0,2.2.0)",
org.eclipse.jgit.lib;version="[2.1.0,2.2.0)",
org.eclipse.jgit.pgm;version="[2.1.0,2.2.0)",
org.eclipse.jgit.pgm.opt;version="[2.1.0,2.2.0)",
org.eclipse.jgit.revwalk;version="[2.1.0,2.2.0)",
org.eclipse.jgit.storage.file;version="[2.1.0,2.2.0)",
org.eclipse.jgit.util;version="[2.1.0,2.2.0)",
org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",

4
org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java

@ -79,4 +79,8 @@ public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase {
throws IOException {
return JGitTestUtil.writeTrashFile(db, name, data);
}
protected void deleteTrashFile(final String name) throws IOException {
JGitTestUtil.deleteTrashFile(db, name);
}
}

230
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/StatusTest.java

@ -0,0 +1,230 @@
/*
* Copyright (C) 2012, François Rey <eclipse.org_@_francois_._rey_._name>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.pgm;
import static org.junit.Assert.assertEquals;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.CLIRepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
public class StatusTest extends CLIRepositoryTestCase {
@Test
public void testStatus() throws Exception {
Git git = new Git(db);
// Write all files
writeTrashFile("tracked", "tracked");
writeTrashFile("stagedNew", "stagedNew");
writeTrashFile("stagedModified", "stagedModified");
writeTrashFile("stagedDeleted", "stagedDeleted");
writeTrashFile("trackedModified", "trackedModified");
writeTrashFile("trackedDeleted", "trackedDeleted");
writeTrashFile("untracked", "untracked");
// Test untracked
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Untracked files:", //
"# ",//
"# \tstagedDeleted", //
"# \tstagedModified", //
"# \tstagedNew", //
"# \ttracked", //
"# \ttrackedDeleted", //
"# \ttrackedModified", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Add to index
git.add().addFilepattern("tracked").call();
git.add().addFilepattern("stagedModified").call();
git.add().addFilepattern("stagedDeleted").call();
git.add().addFilepattern("trackedModified").call();
git.add().addFilepattern("trackedDeleted").call();
// Test staged count
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Changes to be committed:", //
"# ", //
"# \tnew file: stagedDeleted", //
"# \tnew file: stagedModified", //
"# \tnew file: tracked", //
"# \tnew file: trackedDeleted", //
"# \tnew file: trackedModified", //
"# ", //
"# Untracked files:", //
"# ", //
"# \tstagedNew", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Commit
git.commit().setMessage("initial commit")
.call();
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Untracked files:", //
"# ", //
"# \tstagedNew", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Make some changes and stage them
writeTrashFile("stagedModified", "stagedModified modified");
deleteTrashFile("stagedDeleted");
writeTrashFile("trackedModified", "trackedModified modified");
deleteTrashFile("trackedDeleted");
git.add().addFilepattern("stagedModified").call();
git.rm().addFilepattern("stagedDeleted").call();
git.add().addFilepattern("stagedNew").call();
// Test staged/not-staged status
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Changes to be committed:", //
"# ", //
"# \tdeleted: stagedDeleted", //
"# \tmodified: stagedModified", //
"# \tnew file: stagedNew", //
"# ", //
"# Changes not staged for commit:", //
"# ", //
"# \tdeleted: trackedDeleted", //
"# \tmodified: trackedModified", //
"# ", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Create unmerged file
writeTrashFile("unmerged", "unmerged");
git.add().addFilepattern("unmerged").call();
// Commit pending changes
git.add().addFilepattern("trackedModified").call();
git.rm().addFilepattern("trackedDeleted").call();
git.commit().setMessage("commit before branching").call();
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Checkout new branch
git.checkout().setCreateBranch(true).setName("test").call();
// Test branch status
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch test", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Commit change and checkout master again
writeTrashFile("unmerged", "changed in test branch");
git.add().addFilepattern("unmerged").call();
RevCommit testBranch = git.commit()
.setMessage("changed unmerged in test branch").call();
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch test", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
git.checkout().setName("master").call();
// Change the same file and commit
writeTrashFile("unmerged", "changed in master branch");
git.add().addFilepattern("unmerged").call();
git.commit().setMessage("changed unmerged in master branch").call();
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Merge test branch into master
git.merge().include(testBranch.getId()).call();
// Test unmerged status
assertArrayOfLinesEquals(new String[] { // git status output
"# On branch master", //
"# Unmerged paths:", //
"# ", //
"# \tunmerged", //
"# ", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
// Test detached head
String commitId = db.getRef(Constants.MASTER).getObjectId().name();
git.checkout().setName(commitId).call();
assertArrayOfLinesEquals(new String[] { // git status output
"# Not currently on any branch.", //
"# Unmerged paths:", //
"# ", //
"# \tunmerged", //
"# ", //
"# Untracked files:", //
"# ", //
"# \tuntracked", //
"" //
}, execute("git status")); //
}
private void assertArrayOfLinesEquals(String[] expected, String[] actual) {
assertEquals(toText(expected), toText(actual));
}
private String toText(String[] lines) {
StringBuilder b = new StringBuilder();
for (String s : lines) {
b.append(s);
b.append('\n');
}
return b.toString();
}
}

1
org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin

@ -25,6 +25,7 @@ org.eclipse.jgit.pgm.RevParse
org.eclipse.jgit.pgm.Rm
org.eclipse.jgit.pgm.Show
org.eclipse.jgit.pgm.ShowRef
org.eclipse.jgit.pgm.Status
org.eclipse.jgit.pgm.Tag
org.eclipse.jgit.pgm.UploadPack
org.eclipse.jgit.pgm.Version

13
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties

@ -34,6 +34,8 @@ cannotUseObjectsWithGlog=Cannot use --objects with glog
cannotWrite=Cannot write {0}
cantFindGitDirectory=error: can't find git directory
cantWrite=Can't write {0}
changesNotStagedForCommit=Changes not staged for commit:
changesToBeCommitted=Changes to be committed:
commitLabel=commit
configFileNotFound=configuration file {0} not found
conflictingUsageOf_git_dir_andArguments=conflicting usage of --git-dir and arguments
@ -58,6 +60,7 @@ fromURI=From {0}
initializedEmptyGitRepositoryIn=Initialized empty Git repository in {0}
invalidHttpProxyOnlyHttpSupported=Invalid http_proxy: {0}: Only http supported.
jgitVersion=jgit version {0}
lineFormat=# {0}
listeningOn=Listening on {0}
mergeConflict=CONFLICT(content): Merge conflict in {0}
mergeFailed=Automatic merge failed; fix conflicts and then commit the result
@ -123,6 +126,8 @@ notAnIndexFile={0} is not an index file
notAnObject={0} is not an object
notFound=!! NOT FOUND !!
noteObjectTooLargeToPrint=Note object {0} too large to print
notOnAnyBranch=Not currently on any branch.
onBranch=On branch {0}
onBranchToBeBorn=You are on a branch yet to be born
onlyOneMetaVarExpectedIn=Only one {0} expected in {1}.
onlyOneOfIncludeOnlyAllInteractiveCanBeUsed=Only one of --include/--only/--all/--interactive can be used.
@ -136,6 +141,11 @@ remoteSideDoesNotSupportDeletingRefs=remote side does not support deleting refs
repaint=Repaint
serviceNotSupported=Service '{0}' not supported
skippingObject=skipping {0} {1}
statusFileListFormat=\t%1$s
statusFileListFormatWithPrefix=\t%1$-11s %2$s
statusModified=modified:
statusNewFile=new file:
statusRemoved=deleted:
switchedToNewBranch=Switched to a new branch ''{0}''
switchedToBranch=Switched to branch ''{0}''
tagLabel=tag
@ -143,7 +153,9 @@ taggerInfo=Tagger: {0} <{1}>
timeInMilliSeconds={0} ms
tooManyRefsGiven=Too many refs given
unknownMergeStrategy=unknown merge strategy {0} specified
unmergedPaths=Unmerged paths:
unsupportedOperation=Unsupported operation: {0}
untrackedFiles=Untracked files:
usage_Blame=Show what revision and author last modified each line
usage_CommandLineClientForamazonsS3Service=Command line client for Amazon's S3 service
usage_CommitAll=commit all modified and deleted files
@ -165,6 +177,7 @@ usage_RepositoryToReceiveInto=Repository to receive into
usage_ServerSideBackendForJgitFetch=Server side backend for 'jgit fetch'
usage_ServerSideBackendForJgitPush=Server side backend for 'jgit push'
usage_ShowDiffs=Show diffs
usage_Status=Show the working tree status
usage_StopTrackingAFile=Stop tracking a file
usage_UpdateRemoteRepositoryFromLocalRefs=Update remote repository from local refs
usage_abbrevCommits=abbreviate commits to N + 1 digits

34
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java

@ -43,6 +43,8 @@
package org.eclipse.jgit.pgm;
import java.text.MessageFormat;
import org.eclipse.jgit.nls.NLS;
import org.eclipse.jgit.nls.TranslationBundle;
@ -58,6 +60,18 @@ public class CLIText extends TranslationBundle {
return NLS.getBundleFor(CLIText.class);
}
/**
* Format the given line for using the format defined by {@link #lineFormat}
* ("# " by default).
*
* @param line
* the line to format
* @return the formatted line
*/
public static String formatLine(String line) {
return MessageFormat.format(get().lineFormat, line);
}
/***/ public String IPZillaPasswordPrompt;
/***/ public String alreadyOnBranch;
/***/ public String authorInfo;
@ -88,6 +102,8 @@ public class CLIText extends TranslationBundle {
/***/ public String cannotWrite;
/***/ public String cantFindGitDirectory;
/***/ public String cantWrite;
/***/ public String changesNotStagedForCommit;
/***/ public String changesToBeCommitted;
/***/ public String commitLabel;
/***/ public String conflictingUsageOf_git_dir_andArguments;
/***/ public String couldNotCreateBranch;
@ -111,6 +127,7 @@ public class CLIText extends TranslationBundle {
/***/ public String initializedEmptyGitRepositoryIn;
/***/ public String invalidHttpProxyOnlyHttpSupported;
/***/ public String jgitVersion;
/***/ public String lineFormat;
/***/ public String listeningOn;
/***/ public String mergeConflict;
/***/ public String mergeFailed;
@ -169,8 +186,10 @@ public class CLIText extends TranslationBundle {
/***/ public String notAnIndexFile;
/***/ public String notAnObject;
/***/ public String notFound;
/***/ public String notOnAnyBranch;
/***/ public String noteObjectTooLargeToPrint;
/***/ public String onBranchToBeBorn;
/***/ public String onBranch;
/***/ public String onlyOneMetaVarExpectedIn;
/***/ public String onlyOneOfIncludeOnlyAllInteractiveCanBeUsed;
/***/ public String pathspecDidNotMatch;
@ -183,13 +202,24 @@ public class CLIText extends TranslationBundle {
/***/ public String repaint;
/***/ public String serviceNotSupported;
/***/ public String skippingObject;
/***/ public String switchedToNewBranch;
/***/ public String switchedToBranch;
/***/ public String statusFileListFormat;
/***/ public String statusFileListFormatWithPrefix;
/***/ public String statusModified;
/***/ public String statusNewFile;
/***/ public String statusRemoved;
/***/
public String switchedToNewBranch;
/***/
public String switchedToBranch;
/***/ public String tagLabel;
/***/ public String taggerInfo;
/***/ public String timeInMilliSeconds;
/***/ public String tooManyRefsGiven;
/***/ public String unknownMergeStrategy;
/***/ public String unmergedPaths;
/***/ public String unsupportedOperation;
/***/ public String untrackedFiles;
/***/ public String warningNoCommitGivenOnCommandLine;
}

167
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java

@ -0,0 +1,167 @@
/*
* Copyright (C) 2011, François Rey <eclipse.org_@_francois_._rey_._name>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.pgm;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@Command(usage = "usage_Status", common = true)
class Status extends TextBuiltin {
protected final String lineFormat = CLIText.get().lineFormat;
protected final String statusFileListFormat = CLIText.get().statusFileListFormat;
protected final String statusFileListFormatWithPrefix = CLIText.get().statusFileListFormatWithPrefix;
@Override
protected void run() throws Exception {
// Print current branch name
final Ref head = db.getRef(Constants.HEAD);
boolean firstHeader = true;
if (head != null && head.isSymbolic()) {
String branch = Repository.shortenRefName(head.getLeaf().getName());
out.println(CLIText.formatLine(
MessageFormat.format(CLIText.get().onBranch, branch)));
} else
out.println(CLIText.formatLine(CLIText.get().notOnAnyBranch));
// List changes
org.eclipse.jgit.api.Status status = new Git(db).status().call();
Collection<String> added = status.getAdded();
Collection<String> changed = status.getChanged();
Collection<String> removed = status.getRemoved();
Collection<String> modified = status.getModified();
Collection<String> missing = status.getMissing();
Collection<String> untracked = status.getUntracked();
Collection<String> unmerged = status.getConflicting();
Collection<String> toBeCommitted = new ArrayList<String>(added);
toBeCommitted.addAll(changed);
toBeCommitted.addAll(removed);
int nbToBeCommitted = toBeCommitted.size();
if (nbToBeCommitted > 0) {
printSectionHeader(CLIText.get().changesToBeCommitted);
printList(CLIText.get().statusNewFile,
CLIText.get().statusModified, CLIText.get().statusRemoved,
toBeCommitted, added, changed, removed);
firstHeader = false;
}
Collection<String> notStagedForCommit = new ArrayList<String>(modified);
notStagedForCommit.addAll(missing);
int nbNotStagedForCommit = notStagedForCommit.size();
if (nbNotStagedForCommit > 0) {
if (!firstHeader)
printSectionHeader("");
printSectionHeader(CLIText.get().changesNotStagedForCommit);
printList(CLIText.get().statusModified,
CLIText.get().statusRemoved, null, notStagedForCommit,
modified, missing, null);
firstHeader = false;
}
int nbUnmerged = unmerged.size();
if (nbUnmerged > 0) {
if (!firstHeader)
printSectionHeader("");
printSectionHeader(CLIText.get().unmergedPaths);
printList(unmerged);
firstHeader = false;
}
int nbUntracked = untracked.size();
if (nbUntracked > 0) {
if (!firstHeader)
printSectionHeader("");
printSectionHeader(CLIText.get().untrackedFiles);
printList(untracked);
}
}
protected void printSectionHeader(String pattern, Object... arguments) {
out.println(CLIText.formatLine(MessageFormat.format(pattern, arguments)));
if (!pattern.equals(""))
out.println(CLIText.formatLine(""));
out.flush();
}
protected int printList(Collection<String> list) {
if (!list.isEmpty()) {
List<String> sortedList = new ArrayList<String>(list);
java.util.Collections.sort(sortedList);
for (String filename : sortedList) {
out.println(CLIText.formatLine(String.format(
statusFileListFormat, filename)));
}
out.flush();
return list.size();
} else
return 0;
}
protected int printList(String status1, String status2, String status3,
Collection<String> list, Collection<String> set1,
Collection<String> set2,
@SuppressWarnings("unused") Collection<String> set3) {
List<String> sortedList = new ArrayList<String>(list);
java.util.Collections.sort(sortedList);
for (String filename : sortedList) {
String prefix;
if (set1.contains(filename))
prefix = status1;
else if (set2.contains(filename))
prefix = status2;
else
// if (set3.contains(filename))
prefix = status3;
out.println(CLIText.formatLine(String.format(
statusFileListFormatWithPrefix, prefix, filename)));
out.flush();
}
return list.size();
}
}
Loading…
Cancel
Save