diff options
Diffstat (limited to 'org.eclipse.jgit/src')
10 files changed, 182 insertions, 117 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java index 65af216ae8..645d3e7815 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, Chris Aniszczyk <caniszczyk@gmail.com> + * Copyright (C) 2011, 2013 Chris Aniszczyk <caniszczyk@gmail.com> * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -198,12 +198,19 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { throws MissingObjectException, IncorrectObjectTypeException, IOException, GitAPIException { - Ref head = result.getAdvertisedRef(branch); + Ref head = null; if (branch.equals(Constants.HEAD)) { Ref foundBranch = findBranchToCheckout(result); if (foundBranch != null) head = foundBranch; } + if (head == null) { + head = result.getAdvertisedRef(branch); + if (head == null) + head = result.getAdvertisedRef(Constants.R_HEADS + branch); + if (head == null) + head = result.getAdvertisedRef(Constants.R_TAGS + branch); + } if (head == null || head.getObjectId() == null) return; // throw exception? @@ -362,7 +369,9 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { /** * @param branch - * the initial branch to check out when cloning the repository + * the initial branch to check out when cloning the repository. + * Can be specified as ref name (<code>refs/heads/master</code>), + * branch name (<code>master</code>) or tag name (<code>v1.2.3</code>). * @return this instance */ public CloneCommand setBranch(String branch) { @@ -409,7 +418,8 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { /** * @param branchesToClone * collection of branches to clone. Ignored when allSelected is - * true. + * true. Must be specified as full ref names (e.g. + * <code>refs/heads/master</code>). * @return {@code this} */ public CloneCommand setBranchesToClone(Collection<String> branchesToClone) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java index 1f68a7df2c..162105b787 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java @@ -77,6 +77,8 @@ import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevObject; +import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.FileTreeIterator; @@ -150,13 +152,16 @@ public class CommitCommand extends GitCommand<RevCommit> { checkCallable(); Collections.sort(only); - RepositoryState state = repo.getRepositoryState(); - if (!state.canCommit()) - throw new WrongRepositoryStateException(MessageFormat.format( - JGitText.get().cannotCommitOnARepoWithState, state.name())); - processOptions(state); + RevWalk rw = new RevWalk(repo); try { + RepositoryState state = repo.getRepositoryState(); + if (!state.canCommit()) + throw new WrongRepositoryStateException(MessageFormat.format( + JGitText.get().cannotCommitOnARepoWithState, + state.name())); + processOptions(state, rw); + if (all && !repo.isBare() && repo.getWorkTree() != null) { Git git = new Git(repo); try { @@ -182,8 +187,7 @@ public class CommitCommand extends GitCommand<RevCommit> { if (headId != null) if (amend) { - RevCommit previousCommit = new RevWalk(repo) - .parseCommit(headId); + RevCommit previousCommit = rw.parseCommit(headId); for (RevCommit p : previousCommit.getParents()) parents.add(p.getId()); if (author == null) @@ -196,7 +200,7 @@ public class CommitCommand extends GitCommand<RevCommit> { DirCache index = repo.lockDirCache(); try { if (!only.isEmpty()) - index = createTemporaryIndex(headId, index); + index = createTemporaryIndex(headId, index, rw); ObjectInserter odi = repo.newObjectInserter(); try { @@ -219,56 +223,51 @@ public class CommitCommand extends GitCommand<RevCommit> { ObjectId commitId = odi.insert(commit); odi.flush(); - RevWalk revWalk = new RevWalk(repo); - try { - RevCommit revCommit = revWalk.parseCommit(commitId); - RefUpdate ru = repo.updateRef(Constants.HEAD); - ru.setNewObjectId(commitId); - if (reflogComment != null) { - ru.setRefLogMessage(reflogComment, false); - } else { - String prefix = amend ? "commit (amend): " //$NON-NLS-1$ - : parents.size() == 0 ? "commit (initial): " - : "commit: "; - ru.setRefLogMessage( - prefix + revCommit.getShortMessage(), false); - } - if (headId != null) - ru.setExpectedOldObjectId(headId); - else - ru.setExpectedOldObjectId(ObjectId.zeroId()); - Result rc = ru.forceUpdate(); - switch (rc) { - case NEW: - case FORCED: - case FAST_FORWARD: { - setCallable(false); - if (state == RepositoryState.MERGING_RESOLVED) { - // Commit was successful. Now delete the files - // used for merge commits - repo.writeMergeCommitMsg(null); - repo.writeMergeHeads(null); - } else if (state == RepositoryState.CHERRY_PICKING_RESOLVED) { - repo.writeMergeCommitMsg(null); - repo.writeCherryPickHead(null); - } else if (state == RepositoryState.REVERTING_RESOLVED) { - repo.writeMergeCommitMsg(null); - repo.writeRevertHead(null); - } - return revCommit; - } - case REJECTED: - case LOCK_FAILURE: - throw new ConcurrentRefUpdateException(JGitText - .get().couldNotLockHEAD, ru.getRef(), rc); - default: - throw new JGitInternalException(MessageFormat - .format(JGitText.get().updatingRefFailed, - Constants.HEAD, - commitId.toString(), rc)); + RevCommit revCommit = rw.parseCommit(commitId); + RefUpdate ru = repo.updateRef(Constants.HEAD); + ru.setNewObjectId(commitId); + if (reflogComment != null) { + ru.setRefLogMessage(reflogComment, false); + } else { + String prefix = amend ? "commit (amend): " //$NON-NLS-1$ + : parents.size() == 0 ? "commit (initial): " + : "commit: "; + ru.setRefLogMessage( + prefix + revCommit.getShortMessage(), false); + } + if (headId != null) + ru.setExpectedOldObjectId(headId); + else + ru.setExpectedOldObjectId(ObjectId.zeroId()); + Result rc = ru.forceUpdate(); + switch (rc) { + case NEW: + case FORCED: + case FAST_FORWARD: { + setCallable(false); + if (state == RepositoryState.MERGING_RESOLVED) { + // Commit was successful. Now delete the files + // used for merge commits + repo.writeMergeCommitMsg(null); + repo.writeMergeHeads(null); + } else if (state == RepositoryState.CHERRY_PICKING_RESOLVED) { + repo.writeMergeCommitMsg(null); + repo.writeCherryPickHead(null); + } else if (state == RepositoryState.REVERTING_RESOLVED) { + repo.writeMergeCommitMsg(null); + repo.writeRevertHead(null); } - } finally { - revWalk.release(); + return revCommit; + } + case REJECTED: + case LOCK_FAILURE: + throw new ConcurrentRefUpdateException( + JGitText.get().couldNotLockHEAD, ru.getRef(), + rc); + default: + throw new JGitInternalException(MessageFormat.format( + JGitText.get().updatingRefFailed, + Constants.HEAD, commitId.toString(), rc)); } } finally { odi.release(); @@ -281,6 +280,8 @@ public class CommitCommand extends GitCommand<RevCommit> { } catch (IOException e) { throw new JGitInternalException( JGitText.get().exceptionCaughtDuringExecutionOfCommitCommand, e); + } finally { + rw.dispose(); } } @@ -297,7 +298,8 @@ public class CommitCommand extends GitCommand<RevCommit> { + changeId.getName() + "\n"); //$NON-NLS-1$ } - private DirCache createTemporaryIndex(ObjectId headId, DirCache index) + private DirCache createTemporaryIndex(ObjectId headId, DirCache index, + RevWalk rw) throws IOException { ObjectInserter inserter = null; @@ -317,7 +319,7 @@ public class CommitCommand extends GitCommand<RevCommit> { int fIdx = treeWalk.addTree(new FileTreeIterator(repo)); int hIdx = -1; if (headId != null) - hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId)); + hIdx = treeWalk.addTree(rw.parseTree(headId)); treeWalk.setRecursive(true); String lastAddedFile = null; @@ -473,11 +475,14 @@ public class CommitCommand extends GitCommand<RevCommit> { * * @param state * the state of the repository we are working on + * @param rw + * the RevWalk to use * * @throws NoMessageException * if the commit message has not been specified */ - private void processOptions(RepositoryState state) throws NoMessageException { + private void processOptions(RepositoryState state, RevWalk rw) + throws NoMessageException { if (committer == null) committer = new PersonIdent(repo); if (author == null && !amend) @@ -487,6 +492,12 @@ public class CommitCommand extends GitCommand<RevCommit> { if (state == RepositoryState.MERGING_RESOLVED) { try { parents = repo.readMergeHeads(); + if (parents != null) + for (int i = 0; i < parents.size(); i++) { + RevObject ro = rw.parseAny(parents.get(i)); + if (ro instanceof RevTag) + parents.set(i, rw.peel(ro)); + } } catch (IOException e) { throw new JGitInternalException(MessageFormat.format( JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR, diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java index a3d4e09d70..06b2aec06b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java @@ -308,6 +308,8 @@ public class DiffEntry { r.changeType = changeType; r.score = score; + r.treeFilterMarks = src.treeFilterMarks | dst.treeFilterMarks; + return r; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index 11848e2c99..f660d6bbd9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -912,6 +912,11 @@ public class DiffFormatter { editList = new EditList(); type = PatchType.UNIFIED; + } else if (ent.getOldId() == null || ent.getNewId() == null) { + // Content not changed (e.g. only mode, pure rename) + editList = new EditList(); + type = PatchType.UNIFIED; + } else { assertHaveRepository(); @@ -1106,7 +1111,7 @@ public class DiffFormatter { o.write('\n'); } - if (!ent.getOldId().equals(ent.getNewId())) { + if (ent.getOldId() != null && !ent.getOldId().equals(ent.getNewId())) { formatIndexLine(o, ent); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index 7280a38512..8ac971ab62 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -336,6 +336,7 @@ public class JGitText extends TranslationBundle { /***/ public String invalidTimeout; /***/ public String invalidURL; /***/ public String invalidWildcards; + /***/ public String invalidRefSpec; /***/ public String invalidWindowSize; /***/ public String isAStaticFlagAndHasNorevWalkInstance; /***/ public String JRELacksMD5Implementation; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index ccf35e8968..75307decb1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -615,26 +615,25 @@ public class GC { while (treeWalk.next()) { ObjectId objectId = treeWalk.getObjectId(0); - switch (treeWalk.getRawMode(0) & FileMode.TYPE_MASK) { - case FileMode.TYPE_MISSING: - case FileMode.TYPE_GITLINK: - continue; - case FileMode.TYPE_TREE: - case FileMode.TYPE_FILE: - case FileMode.TYPE_SYMLINK: - ret.add(objectId); - continue; - default: + switch (treeWalk.getRawMode(0) & FileMode.TYPE_MASK) { + case FileMode.TYPE_MISSING: + case FileMode.TYPE_GITLINK: + continue; + case FileMode.TYPE_TREE: + case FileMode.TYPE_FILE: + case FileMode.TYPE_SYMLINK: + ret.add(objectId); + continue; + default: throw new IOException(MessageFormat.format( - JGitText.get().corruptObjectInvalidMode3, String - .format("%o", Integer.valueOf(treeWalk //$NON-NLS-1$ - .getRawMode(0)), - (objectId == null) ? "null" //$NON-NLS-1$ - : objectId.name(), treeWalk - .getPathString(), repo - .getIndexFile()))); - } - } + JGitText.get().corruptObjectInvalidMode3, + String.format("%o", //$NON-NLS-1$ + Integer.valueOf(treeWalk.getRawMode(0))), + (objectId == null) ? "null" : objectId.name(), //$NON-NLS-1$ + treeWalk.getPathString(), // + repo.getIndexFile())); + } + } return ret; } finally { if (revWalk != null) @@ -703,7 +702,6 @@ public class GC { } // write the packindex - @SuppressWarnings("resource") FileChannel idxChannel = new FileOutputStream(tmpIdx).getChannel(); OutputStream idxStream = Channels.newOutputStream(idxChannel); try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java index e408c79a3b..9db4a61c69 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java @@ -57,7 +57,7 @@ import org.eclipse.jgit.util.NB; * with this instance can alter at any time, if this instance is modified to * represent a different object name. */ -public abstract class AnyObjectId implements Comparable<Object> { +public abstract class AnyObjectId implements Comparable<AnyObjectId> { /** * Compare to object identifier byte sequences for equality. @@ -184,10 +184,6 @@ public abstract class AnyObjectId implements Comparable<Object> { return NB.compareUInt32(w5, other.w5); } - public final int compareTo(final Object other) { - return compareTo(((AnyObjectId) other)); - } - /** * Compare this ObjectId to a network-byte-order ObjectId. * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java index b86d6fad84..b369d0d1f5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java @@ -294,8 +294,6 @@ public class BatchRefUpdate { // Now to the update that may require more room in the name space for (ReceiveCommand cmd : commands2) { try { - monitor.update(1); - if (cmd.getResult() == NOT_ATTEMPTED) { cmd.updateType(walk); RefUpdate ru = newUpdate(cmd); @@ -305,7 +303,6 @@ public class BatchRefUpdate { break; case UPDATE: case UPDATE_NONFASTFORWARD: - monitor.update(1); RefUpdate ruu = newUpdate(cmd); cmd.setResult(ruu.update(walk)); break; @@ -329,6 +326,8 @@ public class BatchRefUpdate { } catch (IOException err) { cmd.setResult(REJECTED_OTHER_REASON, MessageFormat.format( JGitText.get().lockError, err.getMessage())); + } finally { + monitor.update(1); } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java index 9b38b29336..66ffc3abe9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java @@ -43,8 +43,8 @@ package org.eclipse.jgit.transport; -import java.text.MessageFormat; import java.io.Serializable; +import java.text.MessageFormat; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Constants; @@ -59,7 +59,7 @@ import org.eclipse.jgit.lib.Ref; public class RefSpec implements Serializable { private static final long serialVersionUID = 1L; - /** + /** * Suffix for wildcard ref spec component, that indicate matching all refs * with specified prefix. */ @@ -73,7 +73,7 @@ public class RefSpec implements Serializable { * @return true if provided string is a wildcard ref spec component. */ public static boolean isWildcard(final String s) { - return s != null && s.endsWith(WILDCARD_SUFFIX); + return s != null && s.contains("*"); //$NON-NLS-1$ } /** Does this specification ask for forced updated (rewind/reset)? */ @@ -112,6 +112,7 @@ public class RefSpec implements Serializable { * <li><code>+refs/heads/master</code></li> * <li><code>+refs/heads/master:refs/remotes/origin/master</code></li> * <li><code>+refs/heads/*:refs/remotes/origin/*</code></li> + * <li><code>+refs/pull/*/head:refs/remotes/origin/pr/*</code></li> * <li><code>:refs/heads/master</code></li> * </ul> * @@ -132,18 +133,24 @@ public class RefSpec implements Serializable { s = s.substring(1); if (isWildcard(s)) throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec)); - dstName = s; + dstName = checkValid(s); } else if (c > 0) { - srcName = s.substring(0, c); - dstName = s.substring(c + 1); - if (isWildcard(srcName) && isWildcard(dstName)) + String src = s.substring(0, c); + String dst = s.substring(c + 1); + if (isWildcard(src) && isWildcard(dst)) { + // Both contain wildcard wildcard = true; - else if (isWildcard(srcName) || isWildcard(dstName)) + } else if (isWildcard(src) || isWildcard(dst)) { + // If either source or destination has wildcard, the other one + // must have as well. throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec)); + } + srcName = checkValid(src); + dstName = checkValid(dst); } else { if (isWildcard(s)) throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidWildcards, spec)); - srcName = s; + srcName = checkValid(s); } } @@ -215,7 +222,7 @@ public class RefSpec implements Serializable { */ public RefSpec setSource(final String source) { final RefSpec r = new RefSpec(this); - r.srcName = source; + r.srcName = checkValid(source); if (isWildcard(r.srcName) && r.dstName == null) throw new IllegalStateException(JGitText.get().destinationIsNotAWildcard); if (isWildcard(r.srcName) != isWildcard(r.dstName)) @@ -254,7 +261,7 @@ public class RefSpec implements Serializable { */ public RefSpec setDestination(final String destination) { final RefSpec r = new RefSpec(this); - r.dstName = destination; + r.dstName = checkValid(destination); if (isWildcard(r.dstName) && r.srcName == null) throw new IllegalStateException(JGitText.get().sourceIsNotAWildcard); if (isWildcard(r.srcName) != isWildcard(r.dstName)) @@ -350,8 +357,7 @@ public class RefSpec implements Serializable { final String psrc = srcName, pdst = dstName; wildcard = false; srcName = name; - dstName = pdst.substring(0, pdst.length() - 1) - + name.substring(psrc.length() - 1); + dstName = expandWildcard(name, psrc, pdst); return this; } @@ -392,8 +398,7 @@ public class RefSpec implements Serializable { private RefSpec expandFromDstImp(final String name) { final String psrc = srcName, pdst = dstName; wildcard = false; - srcName = psrc.substring(0, psrc.length() - 1) - + name.substring(pdst.length() - 1); + srcName = expandWildcard(name, pdst, psrc); dstName = name; return this; } @@ -414,12 +419,50 @@ public class RefSpec implements Serializable { return expandFromDestination(r.getName()); } - private boolean match(final String refName, final String s) { + private boolean match(final String name, final String s) { if (s == null) return false; - if (isWildcard()) - return refName.startsWith(s.substring(0, s.length() - 1)); - return refName.equals(s); + if (isWildcard()) { + int wildcardIndex = s.indexOf('*'); + String prefix = s.substring(0, wildcardIndex); + String suffix = s.substring(wildcardIndex + 1); + return name.length() > prefix.length() + suffix.length() + && name.startsWith(prefix) && name.endsWith(suffix); + } + return name.equals(s); + } + + private static String expandWildcard(String name, String patternA, + String patternB) { + int a = patternA.indexOf('*'); + int trailingA = patternA.length() - (a + 1); + int b = patternB.indexOf('*'); + String match = name.substring(a, name.length() - trailingA); + return patternB.substring(0, b) + match + patternB.substring(b + 1); + } + + private static String checkValid(String spec) { + if (spec != null && !isValid(spec)) + throw new IllegalArgumentException(MessageFormat.format( + JGitText.get().invalidRefSpec, spec)); + return spec; + } + + private static boolean isValid(final String s) { + if (s.startsWith("/")) //$NON-NLS-1$ + return false; + if (s.contains("//")) //$NON-NLS-1$ + return false; + int i = s.indexOf('*'); + if (i != -1) { + if (s.indexOf('*', i + 1) > i) + return false; + if (i > 0 && s.charAt(i - 1) != '/') + return false; + if (i < s.length() - 1 && s.charAt(i + 1) != '/') + return false; + } + return true; } public int hashCode() { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawSubStringPattern.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawSubStringPattern.java index 2f7f486e91..bc101bd7d7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawSubStringPattern.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawSubStringPattern.java @@ -95,21 +95,21 @@ public class RawSubStringPattern { int matchPos = rcs.startPtr; final int maxPos = rcs.endPtr - needleLen; - OUTER: for (; matchPos < maxPos; matchPos++) { + OUTER: for (; matchPos <= maxPos; matchPos++) { if (neq(first, text[matchPos])) { - while (++matchPos < maxPos && neq(first, text[matchPos])) { + while (++matchPos <= maxPos && neq(first, text[matchPos])) { /* skip */ } - if (matchPos == maxPos) + if (matchPos > maxPos) return -1; } - int si = ++matchPos; + int si = matchPos + 1; for (int j = 1; j < needleLen; j++, si++) { if (neq(needle[j], text[si])) continue OUTER; } - return matchPos - 1; + return matchPos; } return -1; } |