Merge "Add the intended file to avoid breakage"
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
index 731b4ca..91e749e 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
@@ -220,7 +220,6 @@ private boolean initRangeRequest(final HttpServletRequest req,
return true;
}
- @SuppressWarnings("unchecked")
private static Enumeration<String> getRange(final HttpServletRequest req) {
return req.getHeaders(HDR_RANGE);
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
index eee98d4..8c769e6 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
@@ -87,7 +87,7 @@ protected void run() throws Exception {
switch (result.getMergeStatus()) {
case ALREADY_UP_TO_DATE:
- out.println(CLIText.get().alreadyUpToDate);
+ outw.println(CLIText.get().alreadyUpToDate);
break;
case FAST_FORWARD:
outw.println(result.getMergeStatus().toString());
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java
index 2c10cf9..534e6de 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java
@@ -252,7 +252,7 @@ private String safeAbbreviate(ObjectReader reader, ObjectId id) {
private void printUpdateLine(final char flag, final String summary,
final String srcRef, final String destRef, final String message)
throws IOException {
- out.format(" %c %-17s", valueOf(flag), summary);
+ outw.format(" %c %-17s", valueOf(flag), summary);
if (srcRef != null)
outw.format(" %s ->", abbreviateRef(srcRef, true));
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
index 64e3859..6abbfb0 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
@@ -43,6 +43,7 @@
package org.eclipse.jgit.pgm;
+import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -69,10 +70,10 @@ protected void run() throws Exception {
boolean firstHeader = true;
if (head != null && head.isSymbolic()) {
String branch = Repository.shortenRefName(head.getLeaf().getName());
- out.println(CLIText.formatLine(
+ outw.println(CLIText.formatLine(
MessageFormat.format(CLIText.get().onBranch, branch)));
} else
- out.println(CLIText.formatLine(CLIText.get().notOnAnyBranch));
+ outw.println(CLIText.formatLine(CLIText.get().notOnAnyBranch));
// List changes
org.eclipse.jgit.api.Status status = new Git(db).status().call();
Collection<String> added = status.getAdded();
@@ -122,22 +123,24 @@ protected void run() throws Exception {
}
}
- protected void printSectionHeader(String pattern, Object... arguments) {
- out.println(CLIText.formatLine(MessageFormat.format(pattern, arguments)));
+ protected void printSectionHeader(String pattern, Object... arguments)
+ throws IOException {
+ outw.println(CLIText.formatLine(MessageFormat
+ .format(pattern, arguments)));
if (!pattern.equals(""))
- out.println(CLIText.formatLine(""));
- out.flush();
+ outw.println(CLIText.formatLine(""));
+ outw.flush();
}
- protected int printList(Collection<String> list) {
+ protected int printList(Collection<String> list) throws IOException {
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(
+ outw.println(CLIText.formatLine(String.format(
statusFileListFormat, filename)));
}
- out.flush();
+ outw.flush();
return list.size();
} else
return 0;
@@ -146,7 +149,8 @@ protected int printList(Collection<String> list) {
protected int printList(String status1, String status2, String status3,
Collection<String> list, Collection<String> set1,
Collection<String> set2,
- @SuppressWarnings("unused") Collection<String> set3) {
+ @SuppressWarnings("unused") Collection<String> set3)
+ throws IOException {
List<String> sortedList = new ArrayList<String>(list);
java.util.Collections.sort(sortedList);
for (String filename : sortedList) {
@@ -158,9 +162,9 @@ else if (set2.contains(filename))
else
// if (set3.contains(filename))
prefix = status3;
- out.println(CLIText.formatLine(String.format(
+ outw.println(CLIText.formatLine(String.format(
statusFileListFormatWithPrefix, prefix, filename)));
- out.flush();
+ outw.flush();
}
return list.size();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java
index 243d791..d37f572 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java
@@ -47,11 +47,13 @@
import java.io.File;
import java.io.IOException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.RepositoryTestCase;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -243,4 +245,23 @@ public void testCheckoutRepository() throws Exception {
assertEquals("1", read(test));
assertEquals("a", read(test2));
}
+
+ @Test(expected = JGitInternalException.class)
+ public void testCheckoutOfConflictingFileShouldThrow()
+ throws Exception {
+ // Setup
+ git.checkout().setCreateBranch(true).setName("conflict")
+ .setStartPoint(initialCommit).call();
+ writeTrashFile(FILE1, "Conflicting");
+ RevCommit conflict = git.commit().setAll(true)
+ .setMessage("Conflicting change").call();
+
+ git.checkout().setName("master").call();
+
+ git.merge().include(conflict).call();
+ assertEquals(RepositoryState.MERGING, db.getRepositoryState());
+
+ // Now check out the conflicting path
+ git.checkout().addPath(FILE1).call();
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java
index fe28b47..80cd163 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java
@@ -152,6 +152,7 @@ public void resolvePreviousBranch() throws Exception {
db.resolve("@{-1}@{0}");
fail();
} catch (RevisionSyntaxException e) {
+ // good
}
assertEquals(c1.getName(), db.resolve("@{-2}@{0}").getName());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java
index defd93b..91364ce 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java
@@ -47,14 +47,18 @@
package org.eclipse.jgit.lib;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
@@ -133,9 +137,11 @@ public void testDistance() throws IOException {
public void testDistance_past_root() throws IOException {
assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1",db.resolve("6462e7d8024396b14d7651e2ec11e2bbf07a05c4~1").name());
assertNull(db.resolve("6462e7d8024396b14d7651e2ec11e2bbf07a05c4~~"));
+ assertNull(db.resolve("6462e7d8024396b14d7651e2ec11e2bbf07a05c4^^"));
assertNull(db.resolve("6462e7d8024396b14d7651e2ec11e2bbf07a05c4~2"));
assertNull(db.resolve("6462e7d8024396b14d7651e2ec11e2bbf07a05c4~99"));
assertNull(db.resolve("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1~~"));
+ assertNull(db.resolve("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1^^"));
assertNull(db.resolve("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1~2"));
assertNull(db.resolve("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1~99"));
assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1",db.resolve("master~6").name());
@@ -289,6 +295,53 @@ public void resolveUpstream() throws Exception {
assertEquals("refs/remotes/origin/main", db.simplify("@{upstream}"));
}
+ @Test
+ public void invalidNames() throws AmbiguousObjectException, IOException {
+ assertTrue(Repository.isValidRefName("x/a"));
+ assertTrue(Repository.isValidRefName("x/a.b"));
+ assertTrue(Repository.isValidRefName("x/a@b"));
+ assertTrue(Repository.isValidRefName("x/a@b{x}"));
+ assertTrue(Repository.isValidRefName("x/a/b"));
+ assertTrue(Repository.isValidRefName("x/a]b")); // odd, yes..
+ assertTrue(Repository.isValidRefName("x/\u00a0")); // unicode is fine,
+ // even hard space
+ assertFalse(Repository.isValidRefName("x/.a"));
+ assertFalse(Repository.isValidRefName("x/a."));
+ assertFalse(Repository.isValidRefName("x/a..b"));
+ assertFalse(Repository.isValidRefName("x//a"));
+ assertFalse(Repository.isValidRefName("x/a/"));
+ assertFalse(Repository.isValidRefName("x/a//b"));
+ assertFalse(Repository.isValidRefName("x/a[b"));
+ assertFalse(Repository.isValidRefName("x/a^b"));
+ assertFalse(Repository.isValidRefName("x/a*b"));
+ assertFalse(Repository.isValidRefName("x/a?b"));
+ assertFalse(Repository.isValidRefName("x/a~1"));
+ assertFalse(Repository.isValidRefName("x/a\\b"));
+ assertFalse(Repository.isValidRefName("x/a\u0000"));
+
+ assertUnparseable(".");
+ assertUnparseable("x@{3");
+ assertUnparseable("x[b");
+ assertUnparseable("x y");
+ assertUnparseable("x.");
+ assertUnparseable(".x");
+ assertUnparseable("a..b");
+ assertUnparseable("x\\b");
+ assertUnparseable("a~b");
+ assertUnparseable("a^b");
+ assertUnparseable("a\u0000");
+ }
+
+ private void assertUnparseable(String s) throws AmbiguousObjectException,
+ IOException {
+ try {
+ db.resolve(s);
+ fail("'" + s + "' should be unparseable");
+ } catch (RevisionSyntaxException e) {
+ // good
+ }
+ }
+
private static ObjectId id(String name) {
return ObjectId.fromString(name);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
new file mode 100644
index 0000000..075852a
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012, Marc Strapetz
+ * 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.storage.file;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.IO;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FileBasedConfigTest {
+
+ private static final String USER = "user";
+
+ private static final String NAME = "name";
+
+ private static final String ALICE = "Alice";
+
+ private static final String BOB = "Bob";
+
+ private static final String CONTENT1 = "[" + USER + "]\n\t" + NAME + " = "
+ + ALICE + "\n";
+
+ private static final String CONTENT2 = "[" + USER + "]\n\t" + NAME + " = "
+ + BOB + "\n";
+
+ private final File trash = new File(new File("target"), "trash");
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtils.delete(trash, FileUtils.RECURSIVE | FileUtils.SKIP_MISSING);
+ }
+
+ @Test
+ public void testSystemEncoding() throws IOException, ConfigInvalidException {
+ final File file = createFile(CONTENT1.getBytes());
+ final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED);
+ config.load();
+ assertEquals(ALICE, config.getString(USER, null, NAME));
+
+ config.setString(USER, null, NAME, BOB);
+ config.save();
+ assertArrayEquals(CONTENT2.getBytes(), IO.readFully(file));
+ }
+
+ @Test
+ public void testUTF8withoutBOM() throws IOException, ConfigInvalidException {
+ final File file = createFile(CONTENT1.getBytes("UTF-8"));
+ final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED);
+ config.load();
+ assertEquals(ALICE, config.getString(USER, null, NAME));
+
+ config.setString(USER, null, NAME, BOB);
+ config.save();
+ assertArrayEquals(CONTENT2.getBytes(), IO.readFully(file));
+ }
+
+ @Test
+ public void testUTF8withBOM() throws IOException, ConfigInvalidException {
+ final ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ bos1.write(0xEF);
+ bos1.write(0xBB);
+ bos1.write(0xBF);
+ bos1.write(CONTENT1.getBytes("UTF-8"));
+
+ final File file = createFile(bos1.toByteArray());
+ final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED);
+ config.load();
+ assertEquals(ALICE, config.getString(USER, null, NAME));
+
+ config.setString(USER, null, NAME, BOB);
+ config.save();
+
+ final ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ bos2.write(0xEF);
+ bos2.write(0xBB);
+ bos2.write(0xBF);
+ bos2.write(CONTENT2.getBytes("UTF-8"));
+ assertArrayEquals(bos2.toByteArray(), IO.readFully(file));
+ }
+
+ @Test
+ public void testLeadingWhitespaces() throws IOException, ConfigInvalidException {
+ final ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ bos1.write(" \n\t".getBytes());
+ bos1.write(CONTENT1.getBytes());
+
+ final File file = createFile(bos1.toByteArray());
+ final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED);
+ config.load();
+ assertEquals(ALICE, config.getString(USER, null, NAME));
+
+ config.setString(USER, null, NAME, BOB);
+ config.save();
+
+ final ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ bos2.write(" \n\t".getBytes());
+ bos2.write(CONTENT2.getBytes());
+ assertArrayEquals(bos2.toByteArray(), IO.readFully(file));
+ }
+
+ private File createFile(byte[] content) throws IOException {
+ trash.mkdirs();
+ File f = File.createTempFile(getClass().getName(), null, trash);
+ FileOutputStream os = new FileOutputStream(f, true);
+ try {
+ os.write(content);
+ } finally {
+ os.close();
+ }
+ return f;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index d8efbe7..57f47a4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -64,6 +64,7 @@
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.AmbiguousObjectException;
+import org.eclipse.jgit.errors.UnmergedPathException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
@@ -284,7 +285,8 @@ protected CheckoutCommand checkoutPaths() throws IOException,
startWalk.setRecursive(true);
if (!checkoutAllPaths)
startWalk.setFilter(PathFilterGroup.createFromStrings(paths));
- boolean checkoutIndex = startCommit == null && startPoint == null;
+ final boolean checkoutIndex = startCommit == null
+ && startPoint == null;
if (!checkoutIndex)
startWalk.addTree(revWalk.parseCommit(getStartPoint())
.getTree());
@@ -299,6 +301,11 @@ protected CheckoutCommand checkoutPaths() throws IOException,
final FileMode mode = startWalk.getFileMode(0);
editor.add(new PathEdit(startWalk.getPathString()) {
public void apply(DirCacheEntry ent) {
+ if (checkoutIndex
+ && ent.getStage() > DirCacheEntry.STAGE_0) {
+ UnmergedPathException e = new UnmergedPathException(ent);
+ throw new JGitInternalException(e.getMessage(), e);
+ }
ent.setObjectId(blobId);
ent.setFileMode(mode);
File file = new File(workTree, ent.getPathString());
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 49dc914..9d2babd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
@@ -510,8 +510,8 @@ public final String getName() {
/**
* Return an abbreviation (prefix) of this object SHA-1.
- *
- * This implementation does not guaranteeing uniqueness. Callers should
+ * <p>
+ * This implementation does not guarantee uniqueness. Callers should
* instead use {@link ObjectReader#abbreviate(AnyObjectId, int)} to obtain a
* unique abbreviation within the scope of a particular object database.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 16f8cdf..76f5378 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -429,7 +429,12 @@ private Object resolve(final RevWalk rw, final String revstr)
case '^':
if (rev == null) {
if (name == null)
- name = new String(revChars, done, i);
+ if (done == 0)
+ name = new String(revChars, done, i);
+ else {
+ done = i + 1;
+ break;
+ }
rev = parseSimple(rw, name);
name = null;
if (rev == null)
@@ -471,7 +476,7 @@ private Object resolve(final RevWalk rw, final String revstr)
rev = commit.getParent(pnum - 1);
}
i = j - 1;
- done = i;
+ done = j;
break;
case '{':
int k;
@@ -512,7 +517,6 @@ private Object resolve(final RevWalk rw, final String revstr)
} else
throw new IncorrectObjectTypeException(rev,
Constants.TYPE_COMMIT);
-
}
} else {
rev = rw.peel(rev);
@@ -526,11 +530,17 @@ private Object resolve(final RevWalk rw, final String revstr)
throw new IncorrectObjectTypeException(rev,
Constants.TYPE_COMMIT);
}
+ done = i + 1;
break;
case '~':
if (rev == null) {
if (name == null)
- name = new String(revChars, done, i);
+ if (done == 0)
+ name = new String(revChars, done, i);
+ else {
+ done = i + 1;
+ break;
+ }
rev = parseSimple(rw, name);
name = null;
if (rev == null)
@@ -568,10 +578,13 @@ private Object resolve(final RevWalk rw, final String revstr)
--dist;
}
i = l - 1;
+ done = l;
break;
case '@':
if (rev != null)
throw new RevisionSyntaxException(revstr);
+ if (i + 1 < revChars.length && revChars[i + 1] != '{')
+ continue;
int m;
String time = null;
for (m = i + 2; m < revChars.length; ++m) {
@@ -588,6 +601,8 @@ private Object resolve(final RevWalk rw, final String revstr)
// Currently checked out branch, HEAD if
// detached
name = Constants.HEAD;
+ if (!Repository.isValidRefName("x/" + name))
+ throw new RevisionSyntaxException(revstr);
Ref ref = getRef(name);
name = null;
if (ref == null)
@@ -636,6 +651,8 @@ private Object resolve(final RevWalk rw, final String revstr)
name = new String(revChars, done, i);
if (name.equals(""))
name = Constants.HEAD;
+ if (!Repository.isValidRefName("x/" + name))
+ throw new RevisionSyntaxException(revstr);
Ref ref = getRef(name);
name = null;
if (ref == null)
@@ -680,7 +697,11 @@ private Object resolve(final RevWalk rw, final String revstr)
return rev.copy();
if (name != null)
return name;
+ if (rev == null && done == revstr.length())
+ return null;
name = revstr.substring(done);
+ if (!Repository.isValidRefName("x/" + name))
+ throw new RevisionSyntaxException(revstr);
if (getRef(name) != null)
return name;
return resolveSimple(name);
@@ -709,9 +730,11 @@ private ObjectId resolveSimple(final String revstr) throws IOException {
if (ObjectId.isId(revstr))
return ObjectId.fromString(revstr);
- Ref r = getRefDatabase().getRef(revstr);
- if (r != null)
- return r.getObjectId();
+ if (Repository.isValidRefName("x/" + revstr)) {
+ Ref r = getRefDatabase().getRef(revstr);
+ if (r != null)
+ return r.getObjectId();
+ }
if (AbbreviatedObjectId.isId(revstr))
return resolveAbbreviation(revstr);
@@ -1132,6 +1155,8 @@ public static boolean isValidRefName(final String refName) {
case '/':
if (i == 0 || i == len - 1)
return false;
+ if (p == '/')
+ return false;
components++;
break;
case '{':
@@ -1141,6 +1166,7 @@ public static boolean isValidRefName(final String refName) {
case '~': case '^': case ':':
case '?': case '[': case '*':
case '\\':
+ case '\u007F':
return false;
}
p = c;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
index f302536..7ae491b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
@@ -49,6 +49,7 @@
package org.eclipse.jgit.storage.file;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -70,8 +71,13 @@
*/
public class FileBasedConfig extends StoredConfig {
private final File configFile;
+
private final FS fs;
+
+ private boolean utf8Bom;
+
private volatile FileSnapshot snapshot;
+
private volatile ObjectId hash;
/**
@@ -141,7 +147,16 @@ public void load() throws IOException, ConfigInvalidException {
else
snapshot = newSnapshot;
} else {
- fromText(RawParseUtils.decode(in));
+ final String decoded;
+ if (in.length >= 3 && in[0] == (byte) 0xEF
+ && in[1] == (byte) 0xBB && in[2] == (byte) 0xBF) {
+ decoded = RawParseUtils.decode(RawParseUtils.UTF8_CHARSET,
+ in, 3, in.length);
+ utf8Bom = true;
+ } else {
+ decoded = RawParseUtils.decode(in);
+ }
+ fromText(decoded);
snapshot = newSnapshot;
hash = newHash;
}
@@ -170,7 +185,19 @@ public void load() throws IOException, ConfigInvalidException {
* the file could not be written.
*/
public void save() throws IOException {
- final byte[] out = Constants.encode(toText());
+ final byte[] out;
+ final String text = toText();
+ if (utf8Bom) {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ bos.write(0xEF);
+ bos.write(0xBB);
+ bos.write(0xBF);
+ bos.write(text.getBytes(RawParseUtils.UTF8_CHARSET));
+ out = bos.toByteArray();
+ } else {
+ out = Constants.encode(text);
+ }
+
final LockFile lf = new LockFile(getFile(), fs);
if (!lf.lock())
throw new LockFailedException(getFile());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
index 3344c3f..d6dcb32 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
@@ -193,4 +193,21 @@ private RefUpdate.Result decode(ReceiveCommand.Result status) {
}
}
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("TrackingRefUpdate[");
+ sb.append(remoteName);
+ sb.append(" -> ");
+ sb.append(localName);
+ if (forceUpdate)
+ sb.append(" (forced)");
+ sb.append(" ");
+ sb.append(oldObjectId == null ? "" : oldObjectId.abbreviate(7).name());
+ sb.append("..");
+ sb.append(newObjectId == null ? "" : newObjectId.abbreviate(7).name());
+ sb.append("]");
+ return sb.toString();
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
index 91184ba..89fbeed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
@@ -65,6 +65,11 @@
/** Handy utility functions to parse raw object contents. */
public final class RawParseUtils {
+ /**
+ * UTF-8 charset constant.
+ */
+ public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+
private static final byte[] digits10;
private static final byte[] digits16;