Merge branch 'stable-3.4' into stable-3.5
* stable-3.4: JGit v3.4.2.201412180340-r ObjectChecker: Disallow names potentially mapping to ".git" on HFS+ ObjectChecker: Disallow Windows shortname "GIT~1" ObjectChecker: Disallow ".git." and ".git<space>" Always ignore case when forbidding .git in ObjectChecker DirCache: Refuse to read files with invalid paths DirCache: Replace isValidPath with DirCacheCheckout.checkValidPath Replace "a." with "a-" in unit tests Apache HttpClientConnection: replace calls to deprecated LocalFile() Fix two nits about DirCacheEntry constructors Detect buffering failures while writing rebase todo file Deprecate TemporaryBuffer.LocalFile without parent directory Switch FileHeader.extractFileLines to TemporaryBuffer.Heap AmazonS3: Buffer pushed pack content under $GIT_DIR DirCache: Buffer TREE extension to $GIT_DIR Change-Id: I398cf40b006a05a6537788fc6eb1f84df1ed8814 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
commit
4d6f66400e
|
@ -309,19 +309,19 @@ public void setDoOutput(boolean dooutput) {
|
||||||
public void setFixedLengthStreamingMode(int contentLength) {
|
public void setFixedLengthStreamingMode(int contentLength) {
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
entity = new TemporaryBufferEntity(new LocalFile());
|
entity = new TemporaryBufferEntity(new LocalFile(null));
|
||||||
entity.setContentLength(contentLength);
|
entity.setContentLength(contentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() throws IOException {
|
public OutputStream getOutputStream() throws IOException {
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
entity = new TemporaryBufferEntity(new LocalFile());
|
entity = new TemporaryBufferEntity(new LocalFile(null));
|
||||||
return entity.getBuffer();
|
return entity.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChunkedStreamingMode(int chunklen) {
|
public void setChunkedStreamingMode(int chunklen) {
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
entity = new TemporaryBufferEntity(new LocalFile());
|
entity = new TemporaryBufferEntity(new LocalFile(null));
|
||||||
entity.setChunked(true);
|
entity.setChunked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ void read() throws IOException, InterruptedException {
|
||||||
buf.destroy();
|
buf.destroy();
|
||||||
}
|
}
|
||||||
commitId = line.substring("commit ".length());
|
commitId = line.substring("commit ".length());
|
||||||
buf = new TemporaryBuffer.LocalFile();
|
buf = new TemporaryBuffer.LocalFile(null);
|
||||||
} else if (buf != null) {
|
} else if (buf != null) {
|
||||||
buf.write(line.getBytes("ISO-8859-1"));
|
buf.write(line.getBytes("ISO-8859-1"));
|
||||||
buf.write('\n');
|
buf.write('\n');
|
||||||
|
|
|
@ -47,12 +47,19 @@
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.CorruptObjectException;
|
||||||
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
|
import org.eclipse.jgit.junit.MockSystemReader;
|
||||||
import org.eclipse.jgit.junit.RepositoryTestCase;
|
import org.eclipse.jgit.junit.RepositoryTestCase;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.FileMode;
|
import org.eclipse.jgit.lib.FileMode;
|
||||||
|
import org.eclipse.jgit.lib.ObjectInserter;
|
||||||
|
import org.eclipse.jgit.util.SystemReader;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class DirCacheBasicTest extends RepositoryTestCase {
|
public class DirCacheBasicTest extends RepositoryTestCase {
|
||||||
|
@ -190,7 +197,7 @@ public void testWriteEmptyLockEmpty_RealIndex() throws Exception {
|
||||||
public void testBuildThenClear() throws Exception {
|
public void testBuildThenClear() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
|
final String[] paths = { "a-", "a.b", "a/b", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -234,4 +241,41 @@ public void testFindOnEmpty() throws Exception {
|
||||||
final byte[] path = Constants.encode("a");
|
final byte[] path = Constants.encode("a");
|
||||||
assertEquals(-1, dc.findEntry(path, path.length));
|
assertEquals(-1, dc.findEntry(path, path.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRejectInvalidWindowsPaths() throws Exception {
|
||||||
|
SystemReader.setInstance(new MockSystemReader() {
|
||||||
|
{
|
||||||
|
setUnix();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String path = "src/con.txt";
|
||||||
|
DirCache dc = db.lockDirCache();
|
||||||
|
DirCacheBuilder b = dc.builder();
|
||||||
|
DirCacheEntry e = new DirCacheEntry(path);
|
||||||
|
e.setFileMode(FileMode.REGULAR_FILE);
|
||||||
|
e.setObjectId(new ObjectInserter.Formatter().idFor(
|
||||||
|
Constants.OBJ_BLOB,
|
||||||
|
Constants.encode(path)));
|
||||||
|
b.add(e);
|
||||||
|
b.commit();
|
||||||
|
db.readDirCache();
|
||||||
|
|
||||||
|
SystemReader.setInstance(new MockSystemReader() {
|
||||||
|
{
|
||||||
|
setWindows();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.readDirCache();
|
||||||
|
fail("should have rejected " + path);
|
||||||
|
} catch (CorruptObjectException err) {
|
||||||
|
assertEquals(MessageFormat.format(JGitText.get().invalidPath, path),
|
||||||
|
err.getMessage());
|
||||||
|
assertNotNull(err.getCause());
|
||||||
|
assertEquals("invalid name 'CON'", err.getCause().getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public void testPathFilterGroup_DoesNotSkipTail() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final FileMode mode = FileMode.REGULAR_FILE;
|
final FileMode mode = FileMode.REGULAR_FILE;
|
||||||
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
|
|
@ -290,7 +290,7 @@ public void testFindSingleFile() throws Exception {
|
||||||
public void testAdd_InGitSortOrder() throws Exception {
|
public void testAdd_InGitSortOrder() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
|
final String[] paths = { "a-", "a.b", "a/b", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -315,7 +315,7 @@ public void testAdd_InGitSortOrder() throws Exception {
|
||||||
public void testAdd_ReverseGitSortOrder() throws Exception {
|
public void testAdd_ReverseGitSortOrder() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
|
final String[] paths = { "a-", "a.b", "a/b", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -340,7 +340,7 @@ public void testAdd_ReverseGitSortOrder() throws Exception {
|
||||||
public void testBuilderClear() throws Exception {
|
public void testBuilderClear() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a.b", "a/b", "a0b" };
|
final String[] paths = { "a-", "a.b", "a/b", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
|
|
@ -213,7 +213,7 @@ public void testReadWriteV3() throws Exception {
|
||||||
assertV3TreeEntry(9, "newfile.txt", false, true, dc);
|
assertV3TreeEntry(9, "newfile.txt", false, true, dc);
|
||||||
|
|
||||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
dc.writeTo(bos);
|
dc.writeTo(null, bos);
|
||||||
final byte[] indexBytes = bos.toByteArray();
|
final byte[] indexBytes = bos.toByteArray();
|
||||||
final byte[] expectedBytes = IO.readFully(file);
|
final byte[] expectedBytes = IO.readFully(file);
|
||||||
assertArrayEquals(expectedBytes, indexBytes);
|
assertArrayEquals(expectedBytes, indexBytes);
|
||||||
|
|
|
@ -49,7 +49,6 @@
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Constants;
|
|
||||||
import org.eclipse.jgit.lib.FileMode;
|
import org.eclipse.jgit.lib.FileMode;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -71,7 +70,12 @@ public void testIsValidPath() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isValidPath(final String path) {
|
private static boolean isValidPath(final String path) {
|
||||||
return DirCacheEntry.isValidPath(Constants.encode(path));
|
try {
|
||||||
|
DirCacheCheckout.checkValidPath(path);
|
||||||
|
return true;
|
||||||
|
} catch (InvalidPathException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class DirCacheFindTest extends RepositoryTestCase {
|
||||||
public void testEntriesWithin() throws Exception {
|
public void testEntriesWithin() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -96,13 +96,13 @@ public void testEntriesWithin() throws Exception {
|
||||||
assertSame(ents[i], aContents[i]);
|
assertSame(ents[i], aContents[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(dc.getEntriesWithin("a."));
|
assertNotNull(dc.getEntriesWithin("a-"));
|
||||||
assertEquals(0, dc.getEntriesWithin("a.").length);
|
assertEquals(0, dc.getEntriesWithin("a-").length);
|
||||||
|
|
||||||
assertNotNull(dc.getEntriesWithin("a0b"));
|
assertNotNull(dc.getEntriesWithin("a0b"));
|
||||||
assertEquals(0, dc.getEntriesWithin("a0b.").length);
|
assertEquals(0, dc.getEntriesWithin("a0b-").length);
|
||||||
|
|
||||||
assertNotNull(dc.getEntriesWithin("zoo"));
|
assertNotNull(dc.getEntriesWithin("zoo"));
|
||||||
assertEquals(0, dc.getEntriesWithin("zoo.").length);
|
assertEquals(0, dc.getEntriesWithin("zoo-").length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ public void testEmptyTree_WithTreeWalk() throws Exception {
|
||||||
public void testNoSubtree_NoTreeWalk() throws Exception {
|
public void testNoSubtree_NoTreeWalk() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a0b" };
|
final String[] paths = { "a-", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -111,7 +111,7 @@ public void testNoSubtree_NoTreeWalk() throws Exception {
|
||||||
public void testNoSubtree_WithTreeWalk() throws Exception {
|
public void testNoSubtree_WithTreeWalk() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a0b" };
|
final String[] paths = { "a-", "a0b" };
|
||||||
final FileMode[] modes = { FileMode.EXECUTABLE_FILE, FileMode.GITLINK };
|
final FileMode[] modes = { FileMode.EXECUTABLE_FILE, FileMode.GITLINK };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
|
@ -144,7 +144,7 @@ public void testNoSubtree_WithTreeWalk() throws Exception {
|
||||||
public void testSingleSubtree_NoRecursion() throws Exception {
|
public void testSingleSubtree_NoRecursion() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -156,7 +156,7 @@ public void testSingleSubtree_NoRecursion() throws Exception {
|
||||||
b.add(ents[i]);
|
b.add(ents[i]);
|
||||||
b.finish();
|
b.finish();
|
||||||
|
|
||||||
final String[] expPaths = { "a.", "a", "a0b" };
|
final String[] expPaths = { "a-", "a", "a0b" };
|
||||||
final FileMode[] expModes = { FileMode.REGULAR_FILE, FileMode.TREE,
|
final FileMode[] expModes = { FileMode.REGULAR_FILE, FileMode.TREE,
|
||||||
FileMode.REGULAR_FILE };
|
FileMode.REGULAR_FILE };
|
||||||
final int expPos[] = { 0, -1, 4 };
|
final int expPos[] = { 0, -1, 4 };
|
||||||
|
@ -189,7 +189,7 @@ public void testSingleSubtree_Recursive() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final FileMode mode = FileMode.REGULAR_FILE;
|
final FileMode mode = FileMode.REGULAR_FILE;
|
||||||
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -224,7 +224,7 @@ public void testTwoLevelSubtree_Recursive() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final FileMode mode = FileMode.REGULAR_FILE;
|
final FileMode mode = FileMode.REGULAR_FILE;
|
||||||
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -258,7 +258,7 @@ public void testReset() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final FileMode mode = FileMode.REGULAR_FILE;
|
final FileMode mode = FileMode.REGULAR_FILE;
|
||||||
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -272,7 +272,7 @@ public void testReset() throws Exception {
|
||||||
|
|
||||||
DirCacheIterator dci = new DirCacheIterator(dc);
|
DirCacheIterator dci = new DirCacheIterator(dc);
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a.", dci.getEntryPathString());
|
assertEquals("a-", dci.getEntryPathString());
|
||||||
dci.next(1);
|
dci.next(1);
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a", dci.getEntryPathString());
|
assertEquals("a", dci.getEntryPathString());
|
||||||
|
@ -285,7 +285,7 @@ public void testReset() throws Exception {
|
||||||
// same entries the second time
|
// same entries the second time
|
||||||
dci.reset();
|
dci.reset();
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a.", dci.getEntryPathString());
|
assertEquals("a-", dci.getEntryPathString());
|
||||||
dci.next(1);
|
dci.next(1);
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a", dci.getEntryPathString());
|
assertEquals("a", dci.getEntryPathString());
|
||||||
|
@ -304,12 +304,12 @@ public void testReset() throws Exception {
|
||||||
assertEquals("a", dci.getEntryPathString());
|
assertEquals("a", dci.getEntryPathString());
|
||||||
dci.back(1);
|
dci.back(1);
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a.", dci.getEntryPathString());
|
assertEquals("a-", dci.getEntryPathString());
|
||||||
assertTrue(dci.first());
|
assertTrue(dci.first());
|
||||||
|
|
||||||
// forward
|
// forward
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a.", dci.getEntryPathString());
|
assertEquals("a-", dci.getEntryPathString());
|
||||||
dci.next(1);
|
dci.next(1);
|
||||||
assertFalse(dci.eof());
|
assertFalse(dci.eof());
|
||||||
assertEquals("a", dci.getEntryPathString());
|
assertEquals("a", dci.getEntryPathString());
|
||||||
|
@ -385,7 +385,7 @@ public void testTwoLevelSubtree_FilterPath() throws Exception {
|
||||||
final DirCache dc = DirCache.newInCore();
|
final DirCache dc = DirCache.newInCore();
|
||||||
|
|
||||||
final FileMode mode = FileMode.REGULAR_FILE;
|
final FileMode mode = FileMode.REGULAR_FILE;
|
||||||
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
|
|
@ -113,21 +113,23 @@ public void testAddDeleteTrickyNames() {
|
||||||
DirCache dc = DirCache.newInCore();
|
DirCache dc = DirCache.newInCore();
|
||||||
DirCacheEditor editor = dc.editor();
|
DirCacheEditor editor = dc.editor();
|
||||||
editor.add(new AddEdit("a/b"));
|
editor.add(new AddEdit("a/b"));
|
||||||
editor.add(new AddEdit("a."));
|
editor.add(new AddEdit("a-"));
|
||||||
editor.add(new AddEdit("ab"));
|
editor.add(new AddEdit("ab"));
|
||||||
editor.finish();
|
editor.finish();
|
||||||
assertEquals(3, dc.getEntryCount());
|
assertEquals(3, dc.getEntryCount());
|
||||||
|
|
||||||
// Validate sort order
|
// Validate sort order
|
||||||
assertEquals("a.", dc.getEntry(0).getPathString());
|
assertEquals("a-", dc.getEntry(0).getPathString());
|
||||||
assertEquals("a/b", dc.getEntry(1).getPathString());
|
assertEquals("a/b", dc.getEntry(1).getPathString());
|
||||||
assertEquals("ab", dc.getEntry(2).getPathString());
|
assertEquals("ab", dc.getEntry(2).getPathString());
|
||||||
|
|
||||||
editor = dc.editor();
|
editor = dc.editor();
|
||||||
|
|
||||||
// Sort order should not confuse DeleteTree
|
// Sort order should not confuse DeleteTree
|
||||||
editor.add(new DirCacheEditor.DeleteTree("a"));
|
editor.add(new DirCacheEditor.DeleteTree("a"));
|
||||||
editor.finish();
|
editor.finish();
|
||||||
assertEquals(2, dc.getEntryCount());
|
assertEquals(2, dc.getEntryCount());
|
||||||
assertEquals("a.", dc.getEntry(0).getPathString());
|
assertEquals("a-", dc.getEntry(0).getPathString());
|
||||||
assertEquals("ab", dc.getEntry(1).getPathString());
|
assertEquals("ab", dc.getEntry(1).getPathString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ public void testEmptyCache_Clear_NoCacheTree() throws Exception {
|
||||||
public void testSingleSubtree() throws Exception {
|
public void testSingleSubtree() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -130,7 +130,7 @@ public void testSingleSubtree() throws Exception {
|
||||||
public void testTwoLevelSubtree() throws Exception {
|
public void testTwoLevelSubtree() throws Exception {
|
||||||
final DirCache dc = db.readDirCache();
|
final DirCache dc = db.readDirCache();
|
||||||
|
|
||||||
final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
@ -190,7 +190,7 @@ public void testWriteReadTree() throws CorruptObjectException, IOException {
|
||||||
|
|
||||||
final String A = String.format("a%2000s", "a");
|
final String A = String.format("a%2000s", "a");
|
||||||
final String B = String.format("b%2000s", "b");
|
final String B = String.format("b%2000s", "b");
|
||||||
final String[] paths = { A + ".", A + "." + B, A + "/" + B, A + "0" + B };
|
final String[] paths = { A + "-", A + "-" + B, A + "/" + B, A + "0" + B };
|
||||||
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
ents[i] = new DirCacheEntry(paths[i]);
|
ents[i] = new DirCacheEntry(paths[i]);
|
||||||
|
|
|
@ -186,10 +186,7 @@ public void testMaliciousGitPathEndSpaceWindows() throws Exception {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMaliciousGitPathEndSpaceUnixOk() throws Exception {
|
public void testMaliciousGitPathEndSpaceUnixOk() throws Exception {
|
||||||
if (File.separatorChar == '\\')
|
testMaliciousPathBadFirstCheckout(".git ", "konfig");
|
||||||
return; // cannot emulate Unix on Windows for this test
|
|
||||||
((MockSystemReader) SystemReader.getInstance()).setUnix();
|
|
||||||
testMaliciousPathGoodFirstCheckout(".git ", "konfig");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -212,10 +209,7 @@ public void testMaliciousGitPathEndDotWindows3() throws Exception {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMaliciousGitPathEndDotUnixOk() throws Exception {
|
public void testMaliciousGitPathEndDotUnixOk() throws Exception {
|
||||||
if (File.separatorChar == '\\')
|
testMaliciousPathBadFirstCheckout(".git.", "konfig");
|
||||||
return; // cannot emulate Unix on Windows for this test
|
|
||||||
((MockSystemReader) SystemReader.getInstance()).setUnix();
|
|
||||||
testMaliciousPathGoodFirstCheckout(".git.", "konfig");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1295,12 +1295,11 @@ public void testInvalidTreeNameIsGit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidTreeNameIsMixedCaseGitWindows() {
|
public void testInvalidTreeNameIsMixedCaseGit() {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
entry(b, "100644 .GiT");
|
entry(b, "100644 .GiT");
|
||||||
byte[] data = Constants.encodeASCII(b.toString());
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
try {
|
try {
|
||||||
checker.setSafeForWindows(true);
|
|
||||||
checker.checkTree(data);
|
checker.checkTree(data);
|
||||||
fail("incorrectly accepted an invalid tree");
|
fail("incorrectly accepted an invalid tree");
|
||||||
} catch (CorruptObjectException e) {
|
} catch (CorruptObjectException e) {
|
||||||
|
@ -1309,19 +1308,255 @@ public void testInvalidTreeNameIsMixedCaseGitWindows() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidTreeNameIsMixedCaseGitMacOS() {
|
public void testInvalidTreeNameIsMacHFSGit() {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
entry(b, "100644 .GiT");
|
entry(b, "100644 .gi\u200Ct");
|
||||||
byte[] data = Constants.encodeASCII(b.toString());
|
byte[] data = Constants.encode(b.toString());
|
||||||
try {
|
try {
|
||||||
checker.setSafeForMacOS(true);
|
checker.setSafeForMacOS(true);
|
||||||
checker.checkTree(data);
|
checker.checkTree(data);
|
||||||
fail("incorrectly accepted an invalid tree");
|
fail("incorrectly accepted an invalid tree");
|
||||||
} catch (CorruptObjectException e) {
|
} catch (CorruptObjectException e) {
|
||||||
assertEquals("invalid name '.GiT'", e.getMessage());
|
assertEquals(
|
||||||
|
"invalid name '.gi\u200Ct' contains ignorable Unicode characters",
|
||||||
|
e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsMacHFSGit2() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 \u206B.git");
|
||||||
|
byte[] data = Constants.encode(b.toString());
|
||||||
|
try {
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals(
|
||||||
|
"invalid name '\u206B.git' contains ignorable Unicode characters",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsMacHFSGit3() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git\uFEFF");
|
||||||
|
byte[] data = Constants.encode(b.toString());
|
||||||
|
try {
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals(
|
||||||
|
"invalid name '.git\uFEFF' contains ignorable Unicode characters",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] concat(byte[] b1, byte[] b2) {
|
||||||
|
byte[] data = new byte[b1.length + b2.length];
|
||||||
|
System.arraycopy(b1, 0, data, 0, b1.length);
|
||||||
|
System.arraycopy(b2, 0, data, b1.length, b2.length);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd() {
|
||||||
|
byte[] data = concat(Constants.encode("100644 .git"),
|
||||||
|
new byte[] { (byte) 0xef });
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "");
|
||||||
|
data = concat(data, Constants.encode(b.toString()));
|
||||||
|
try {
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals(
|
||||||
|
"invalid name contains byte sequence '0xef' which is not a valid UTF-8 character",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd2() {
|
||||||
|
byte[] data = concat(Constants.encode("100644 .git"), new byte[] {
|
||||||
|
(byte) 0xe2, (byte) 0xab });
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "");
|
||||||
|
data = concat(data, Constants.encode(b.toString()));
|
||||||
|
try {
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals(
|
||||||
|
"invalid name contains byte sequence '0xe2ab' which is not a valid UTF-8 character",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsNotMacHFSGit()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git\u200Cx");
|
||||||
|
byte[] data = Constants.encode(b.toString());
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsNotMacHFSGit2()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .kit\u200C");
|
||||||
|
byte[] data = Constants.encode(b.toString());
|
||||||
|
checker.setSafeForMacOS(true);
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsNotMacHFSGitOtherPlatform()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git\u200C");
|
||||||
|
byte[] data = Constants.encode(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitDot() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git.");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name '.git.'", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidTreeNameIsDotGitDotDot()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git..");
|
||||||
|
checker.checkTree(Constants.encodeASCII(b.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSpace() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git ");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name '.git '", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSomething()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .gitfoobar");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSomethingSpaceSomething()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .gitfoo bar");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSomethingDot()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .gitfoobar.");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSomethingDotDot()
|
||||||
|
throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .gitfoobar..");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitDotSpace() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git. ");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name '.git. '", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsDotGitSpaceDot() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 .git . ");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name '.git . '", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsGITTilde1() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 GIT~1");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name 'GIT~1'", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidTreeNameIsGiTTilde1() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 GiT~1");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
try {
|
||||||
|
checker.checkTree(data);
|
||||||
|
fail("incorrectly accepted an invalid tree");
|
||||||
|
} catch (CorruptObjectException e) {
|
||||||
|
assertEquals("invalid name 'GiT~1'", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidTreeNameIsGitTilde11() throws CorruptObjectException {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
entry(b, "100644 GIT~11");
|
||||||
|
byte[] data = Constants.encodeASCII(b.toString());
|
||||||
|
checker.checkTree(data);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidTreeTruncatedInName() {
|
public void testInvalidTreeTruncatedInName() {
|
||||||
final StringBuilder b = new StringBuilder();
|
final StringBuilder b = new StringBuilder();
|
||||||
|
|
|
@ -169,7 +169,7 @@ public void testStopWalk() throws MissingObjectException,
|
||||||
}
|
}
|
||||||
|
|
||||||
// less obvious due to git sorting order
|
// less obvious due to git sorting order
|
||||||
filter.include(fakeWalk("d."));
|
filter.include(fakeWalk("d-"));
|
||||||
|
|
||||||
// less obvious due to git sorting order
|
// less obvious due to git sorting order
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
public class TemporaryBufferTest {
|
public class TemporaryBufferTest {
|
||||||
@Test
|
@Test
|
||||||
public void testEmpty() throws IOException {
|
public void testEmpty() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
try {
|
try {
|
||||||
b.close();
|
b.close();
|
||||||
assertEquals(0, b.length());
|
assertEquals(0, b.length());
|
||||||
|
@ -73,7 +73,7 @@ public void testEmpty() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneByte() throws IOException {
|
public void testOneByte() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte test = (byte) new TestRng(getName()).nextInt();
|
final byte test = (byte) new TestRng(getName()).nextInt();
|
||||||
try {
|
try {
|
||||||
b.write(test);
|
b.write(test);
|
||||||
|
@ -100,7 +100,7 @@ public void testOneByte() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneBlock_BulkWrite() throws IOException {
|
public void testOneBlock_BulkWrite() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.Block.SZ);
|
.nextBytes(TemporaryBuffer.Block.SZ);
|
||||||
try {
|
try {
|
||||||
|
@ -131,7 +131,7 @@ public void testOneBlock_BulkWrite() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneBlockAndHalf_BulkWrite() throws IOException {
|
public void testOneBlockAndHalf_BulkWrite() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
||||||
try {
|
try {
|
||||||
|
@ -162,7 +162,7 @@ public void testOneBlockAndHalf_BulkWrite() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneBlockAndHalf_SingleWrite() throws IOException {
|
public void testOneBlockAndHalf_SingleWrite() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
||||||
try {
|
try {
|
||||||
|
@ -191,7 +191,7 @@ public void testOneBlockAndHalf_SingleWrite() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneBlockAndHalf_Copy() throws IOException {
|
public void testOneBlockAndHalf_Copy() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
|
||||||
try {
|
try {
|
||||||
|
@ -221,7 +221,7 @@ public void testOneBlockAndHalf_Copy() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLarge_SingleWrite() throws IOException {
|
public void testLarge_SingleWrite() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
|
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
|
||||||
try {
|
try {
|
||||||
|
@ -263,7 +263,7 @@ public void testInCoreInputStream() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInCoreLimit_SwitchOnAppendByte() throws IOException {
|
public void testInCoreLimit_SwitchOnAppendByte() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT + 1);
|
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT + 1);
|
||||||
try {
|
try {
|
||||||
|
@ -292,7 +292,7 @@ public void testInCoreLimit_SwitchOnAppendByte() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException {
|
public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
|
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
|
||||||
try {
|
try {
|
||||||
|
@ -321,7 +321,7 @@ public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInCoreLimit_SwitchOnCopy() throws IOException {
|
public void testInCoreLimit_SwitchOnCopy() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final byte[] test = new TestRng(getName())
|
final byte[] test = new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2);
|
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2);
|
||||||
try {
|
try {
|
||||||
|
@ -354,7 +354,7 @@ public void testInCoreLimit_SwitchOnCopy() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void testDestroyWhileOpen() throws IOException {
|
public void testDestroyWhileOpen() throws IOException {
|
||||||
@SuppressWarnings("resource" /* java 7 */)
|
@SuppressWarnings("resource" /* java 7 */)
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
try {
|
try {
|
||||||
b.write(new TestRng(getName())
|
b.write(new TestRng(getName())
|
||||||
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2));
|
.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2));
|
||||||
|
@ -365,7 +365,7 @@ public void testDestroyWhileOpen() throws IOException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRandomWrites() throws IOException {
|
public void testRandomWrites() throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
|
||||||
final TestRng rng = new TestRng(getName());
|
final TestRng rng = new TestRng(getName());
|
||||||
final int max = TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2;
|
final int max = TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2;
|
||||||
final byte[] expect = new byte[max];
|
final byte[] expect = new byte[max];
|
||||||
|
|
|
@ -607,7 +607,8 @@ public void write() throws IOException {
|
||||||
final LockFile tmp = myLock;
|
final LockFile tmp = myLock;
|
||||||
requireLocked(tmp);
|
requireLocked(tmp);
|
||||||
try {
|
try {
|
||||||
writeTo(new SafeBufferedOutputStream(tmp.getOutputStream()));
|
writeTo(liveFile.getParentFile(),
|
||||||
|
new SafeBufferedOutputStream(tmp.getOutputStream()));
|
||||||
} catch (IOException err) {
|
} catch (IOException err) {
|
||||||
tmp.unlock();
|
tmp.unlock();
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -620,7 +621,7 @@ public void write() throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTo(final OutputStream os) throws IOException {
|
void writeTo(File dir, final OutputStream os) throws IOException {
|
||||||
final MessageDigest foot = Constants.newMessageDigest();
|
final MessageDigest foot = Constants.newMessageDigest();
|
||||||
final DigestOutputStream dos = new DigestOutputStream(os, foot);
|
final DigestOutputStream dos = new DigestOutputStream(os, foot);
|
||||||
|
|
||||||
|
@ -670,14 +671,18 @@ void writeTo(final OutputStream os) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeTree) {
|
if (writeTree) {
|
||||||
final TemporaryBuffer bb = new TemporaryBuffer.LocalFile();
|
TemporaryBuffer bb = new TemporaryBuffer.LocalFile(dir, 5 << 20);
|
||||||
tree.write(tmp, bb);
|
try {
|
||||||
bb.close();
|
tree.write(tmp, bb);
|
||||||
|
bb.close();
|
||||||
|
|
||||||
NB.encodeInt32(tmp, 0, EXT_TREE);
|
NB.encodeInt32(tmp, 0, EXT_TREE);
|
||||||
NB.encodeInt32(tmp, 4, (int) bb.length());
|
NB.encodeInt32(tmp, 4, (int) bb.length());
|
||||||
dos.write(tmp, 0, 8);
|
dos.write(tmp, 0, 8);
|
||||||
bb.writeTo(dos, null);
|
bb.writeTo(dos, null);
|
||||||
|
} finally {
|
||||||
|
bb.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
writeIndexChecksum = foot.digest();
|
writeIndexChecksum = foot.digest();
|
||||||
os.write(writeIndexChecksum);
|
os.write(writeIndexChecksum);
|
||||||
|
|
|
@ -1281,7 +1281,9 @@ public static void checkValidPath(String path) throws InvalidPathException {
|
||||||
}
|
}
|
||||||
chk.checkPathSegment(bytes, segmentStart, bytes.length);
|
chk.checkPathSegment(bytes, segmentStart, bytes.length);
|
||||||
} catch (CorruptObjectException e) {
|
} catch (CorruptObjectException e) {
|
||||||
throw new InvalidPathException(e.getMessage());
|
InvalidPathException p = new InvalidPathException(path);
|
||||||
|
p.initCause(e);
|
||||||
|
throw p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.CorruptObjectException;
|
||||||
import org.eclipse.jgit.internal.JGitText;
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.AnyObjectId;
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
@ -64,7 +65,6 @@
|
||||||
import org.eclipse.jgit.util.IO;
|
import org.eclipse.jgit.util.IO;
|
||||||
import org.eclipse.jgit.util.MutableInteger;
|
import org.eclipse.jgit.util.MutableInteger;
|
||||||
import org.eclipse.jgit.util.NB;
|
import org.eclipse.jgit.util.NB;
|
||||||
import org.eclipse.jgit.util.SystemReader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single file (or stage of a file) in a {@link DirCache}.
|
* A single file (or stage of a file) in a {@link DirCache}.
|
||||||
|
@ -190,6 +190,16 @@ public class DirCacheEntry {
|
||||||
md.update((byte) 0);
|
md.update((byte) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DirCacheCheckout.checkValidPath(toString(path));
|
||||||
|
} catch (InvalidPathException e) {
|
||||||
|
CorruptObjectException p =
|
||||||
|
new CorruptObjectException(e.getMessage());
|
||||||
|
if (e.getCause() != null)
|
||||||
|
p.initCause(e.getCause());
|
||||||
|
throw p;
|
||||||
|
}
|
||||||
|
|
||||||
// Index records are padded out to the next 8 byte alignment
|
// Index records are padded out to the next 8 byte alignment
|
||||||
// for historical reasons related to how C Git read the files.
|
// for historical reasons related to how C Git read the files.
|
||||||
//
|
//
|
||||||
|
@ -203,7 +213,6 @@ public class DirCacheEntry {
|
||||||
|
|
||||||
if (mightBeRacilyClean(smudge_s, smudge_ns))
|
if (mightBeRacilyClean(smudge_s, smudge_ns))
|
||||||
smudgeRacilyClean();
|
smudgeRacilyClean();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,7 +226,7 @@ public class DirCacheEntry {
|
||||||
* or DirCache file.
|
* or DirCache file.
|
||||||
*/
|
*/
|
||||||
public DirCacheEntry(final String newPath) {
|
public DirCacheEntry(final String newPath) {
|
||||||
this(Constants.encode(newPath));
|
this(Constants.encode(newPath), STAGE_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -266,11 +275,11 @@ public DirCacheEntry(final byte[] newPath) {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("boxing")
|
@SuppressWarnings("boxing")
|
||||||
public DirCacheEntry(final byte[] newPath, final int stage) {
|
public DirCacheEntry(final byte[] newPath, final int stage) {
|
||||||
if (!isValidPath(newPath))
|
DirCacheCheckout.checkValidPath(toString(newPath));
|
||||||
throw new InvalidPathException(toString(newPath));
|
|
||||||
if (stage < 0 || 3 < stage)
|
if (stage < 0 || 3 < stage)
|
||||||
throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidStageForPath
|
throw new IllegalArgumentException(MessageFormat.format(
|
||||||
, stage, toString(newPath)));
|
JGitText.get().invalidStageForPath,
|
||||||
|
stage, toString(newPath)));
|
||||||
|
|
||||||
info = new byte[INFO_LEN];
|
info = new byte[INFO_LEN];
|
||||||
infoOffset = 0;
|
infoOffset = 0;
|
||||||
|
@ -725,36 +734,6 @@ private static String toString(final byte[] path) {
|
||||||
return Constants.CHARSET.decode(ByteBuffer.wrap(path)).toString();
|
return Constants.CHARSET.decode(ByteBuffer.wrap(path)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isValidPath(final byte[] path) {
|
|
||||||
if (path.length == 0)
|
|
||||||
return false; // empty path is not permitted.
|
|
||||||
|
|
||||||
boolean componentHasChars = false;
|
|
||||||
for (final byte c : path) {
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
return false; // NUL is never allowed within the path.
|
|
||||||
|
|
||||||
case '/':
|
|
||||||
if (componentHasChars)
|
|
||||||
componentHasChars = false;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
case ':':
|
|
||||||
// Tree's never have a backslash in them, not even on Windows
|
|
||||||
// but even there we regard it as an invalid path
|
|
||||||
if (SystemReader.getInstance().isWindows())
|
|
||||||
return false;
|
|
||||||
//$FALL-THROUGH$
|
|
||||||
default:
|
|
||||||
componentHasChars = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return componentHasChars;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getMaximumInfoLength(boolean extended) {
|
static int getMaximumInfoLength(boolean extended) {
|
||||||
return extended ? INFO_LEN_EXTENDED : INFO_LEN;
|
return extended ? INFO_LEN_EXTENDED : INFO_LEN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,13 +453,27 @@ private void checkPathSegment2(byte[] raw, int ptr, int end)
|
||||||
throw new CorruptObjectException("invalid name '..'");
|
throw new CorruptObjectException("invalid name '..'");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (isDotGit(raw, ptr + 1))
|
if (isGit(raw, ptr + 1))
|
||||||
|
throw new CorruptObjectException(String.format(
|
||||||
|
"invalid name '%s'",
|
||||||
|
RawParseUtils.decode(raw, ptr, end)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (end - ptr > 4 && isNormalizedGit(raw, ptr + 1, end))
|
||||||
throw new CorruptObjectException(String.format(
|
throw new CorruptObjectException(String.format(
|
||||||
"invalid name '%s'",
|
"invalid name '%s'",
|
||||||
RawParseUtils.decode(raw, ptr, end)));
|
RawParseUtils.decode(raw, ptr, end)));
|
||||||
}
|
}
|
||||||
|
} else if (isGitTilde1(raw, ptr, end)) {
|
||||||
|
throw new CorruptObjectException(String.format("invalid name '%s'",
|
||||||
|
RawParseUtils.decode(raw, ptr, end)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (macosx && isMacHFSGit(raw, ptr, end))
|
||||||
|
throw new CorruptObjectException(String.format(
|
||||||
|
"invalid name '%s' contains ignorable Unicode characters",
|
||||||
|
RawParseUtils.decode(raw, ptr, end)));
|
||||||
|
|
||||||
if (windows) {
|
if (windows) {
|
||||||
// Windows ignores space and dot at end of file name.
|
// Windows ignores space and dot at end of file name.
|
||||||
if (raw[end - 1] == ' ' || raw[end - 1] == '.')
|
if (raw[end - 1] == ' ' || raw[end - 1] == '.')
|
||||||
|
@ -470,6 +484,88 @@ private void checkPathSegment2(byte[] raw, int ptr, int end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mac's HFS+ folds permutations of ".git" and Unicode ignorable characters
|
||||||
|
// to ".git" therefore we should prevent such names
|
||||||
|
private static boolean isMacHFSGit(byte[] raw, int ptr, int end)
|
||||||
|
throws CorruptObjectException {
|
||||||
|
boolean ignorable = false;
|
||||||
|
byte[] git = new byte[] { '.', 'g', 'i', 't' };
|
||||||
|
int g = 0;
|
||||||
|
while (ptr < end) {
|
||||||
|
switch (raw[ptr]) {
|
||||||
|
case (byte) 0xe2: // http://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192
|
||||||
|
checkTruncatedIgnorableUTF8(raw, ptr, end);
|
||||||
|
switch (raw[ptr + 1]) {
|
||||||
|
case (byte) 0x80:
|
||||||
|
switch (raw[ptr + 2]) {
|
||||||
|
case (byte) 0x8c: // U+200C 0xe2808c ZERO WIDTH NON-JOINER
|
||||||
|
case (byte) 0x8d: // U+200D 0xe2808d ZERO WIDTH JOINER
|
||||||
|
case (byte) 0x8e: // U+200E 0xe2808e LEFT-TO-RIGHT MARK
|
||||||
|
case (byte) 0x8f: // U+200F 0xe2808f RIGHT-TO-LEFT MARK
|
||||||
|
case (byte) 0xaa: // U+202A 0xe280aa LEFT-TO-RIGHT EMBEDDING
|
||||||
|
case (byte) 0xab: // U+202B 0xe280ab RIGHT-TO-LEFT EMBEDDING
|
||||||
|
case (byte) 0xac: // U+202C 0xe280ac POP DIRECTIONAL FORMATTING
|
||||||
|
case (byte) 0xad: // U+202D 0xe280ad LEFT-TO-RIGHT OVERRIDE
|
||||||
|
case (byte) 0xae: // U+202E 0xe280ae RIGHT-TO-LEFT OVERRIDE
|
||||||
|
ignorable = true;
|
||||||
|
ptr += 3;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case (byte) 0x81:
|
||||||
|
switch (raw[ptr + 2]) {
|
||||||
|
case (byte) 0xaa: // U+206A 0xe281aa INHIBIT SYMMETRIC SWAPPING
|
||||||
|
case (byte) 0xab: // U+206B 0xe281ab ACTIVATE SYMMETRIC SWAPPING
|
||||||
|
case (byte) 0xac: // U+206C 0xe281ac INHIBIT ARABIC FORM SHAPING
|
||||||
|
case (byte) 0xad: // U+206D 0xe281ad ACTIVATE ARABIC FORM SHAPING
|
||||||
|
case (byte) 0xae: // U+206E 0xe281ae NATIONAL DIGIT SHAPES
|
||||||
|
case (byte) 0xaf: // U+206F 0xe281af NOMINAL DIGIT SHAPES
|
||||||
|
ignorable = true;
|
||||||
|
ptr += 3;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (byte) 0xef: // http://www.utf8-chartable.de/unicode-utf8-table.pl?start=65024
|
||||||
|
checkTruncatedIgnorableUTF8(raw, ptr, end);
|
||||||
|
// U+FEFF 0xefbbbf ZERO WIDTH NO-BREAK SPACE
|
||||||
|
if ((raw[ptr + 1] == (byte) 0xbb)
|
||||||
|
&& (raw[ptr + 2] == (byte) 0xbf)) {
|
||||||
|
ignorable = true;
|
||||||
|
ptr += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
if (g == 4)
|
||||||
|
return false;
|
||||||
|
if (raw[ptr++] != git[g++])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g == 4 && ignorable)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkTruncatedIgnorableUTF8(byte[] raw, int ptr, int end)
|
||||||
|
throws CorruptObjectException {
|
||||||
|
if ((ptr + 2) >= end)
|
||||||
|
throw new CorruptObjectException(MessageFormat.format(
|
||||||
|
"invalid name contains byte sequence ''{0}'' which is not a valid UTF-8 character",
|
||||||
|
toHexString(raw, ptr, end)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toHexString(byte[] raw, int ptr, int end) {
|
||||||
|
StringBuilder b = new StringBuilder("0x"); //$NON-NLS-1$
|
||||||
|
for (int i = ptr; i < end; i++)
|
||||||
|
b.append(String.format("%02x", Byte.valueOf(raw[i]))); //$NON-NLS-1$
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkNotWindowsDevice(byte[] raw, int ptr, int end)
|
private static void checkNotWindowsDevice(byte[] raw, int ptr, int end)
|
||||||
throws CorruptObjectException {
|
throws CorruptObjectException {
|
||||||
switch (toLower(raw[ptr])) {
|
switch (toLower(raw[ptr])) {
|
||||||
|
@ -540,12 +636,36 @@ private static boolean isInvalidOnWindows(byte c) {
|
||||||
return 1 <= c && c <= 31;
|
return 1 <= c && c <= 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDotGit(byte[] buf, int p) {
|
private static boolean isGit(byte[] buf, int p) {
|
||||||
if (windows || macosx)
|
return toLower(buf[p]) == 'g'
|
||||||
return toLower(buf[p]) == 'g'
|
&& toLower(buf[p + 1]) == 'i'
|
||||||
&& toLower(buf[p + 1]) == 'i'
|
&& toLower(buf[p + 2]) == 't';
|
||||||
&& toLower(buf[p + 2]) == 't';
|
}
|
||||||
return buf[p] == 'g' && buf[p + 1] == 'i' && buf[p + 2] == 't';
|
|
||||||
|
private static boolean isGitTilde1(byte[] buf, int p, int end) {
|
||||||
|
if (end - p != 5)
|
||||||
|
return false;
|
||||||
|
return toLower(buf[p]) == 'g' && toLower(buf[p + 1]) == 'i'
|
||||||
|
&& toLower(buf[p + 2]) == 't' && buf[p + 3] == '~'
|
||||||
|
&& buf[p + 4] == '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNormalizedGit(byte[] raw, int ptr, int end) {
|
||||||
|
if (isGit(raw, ptr)) {
|
||||||
|
int dots = 0;
|
||||||
|
boolean space = false;
|
||||||
|
int p = end - 1;
|
||||||
|
for (; (ptr + 2) < p; p--) {
|
||||||
|
if (raw[p] == '.')
|
||||||
|
dots++;
|
||||||
|
else if (raw[p] == ' ')
|
||||||
|
space = true;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return p == ptr + 2 && (dots == 1 || space);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char toLower(byte b) {
|
private static char toLower(byte b) {
|
||||||
|
|
|
@ -43,17 +43,17 @@
|
||||||
|
|
||||||
package org.eclipse.jgit.lib;
|
package org.eclipse.jgit.lib;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStream;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.RebaseTodoLine.Action;
|
import org.eclipse.jgit.lib.RebaseTodoLine.Action;
|
||||||
import org.eclipse.jgit.util.IO;
|
import org.eclipse.jgit.util.IO;
|
||||||
import org.eclipse.jgit.util.RawParseUtils;
|
import org.eclipse.jgit.util.RawParseUtils;
|
||||||
|
import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offers methods to read and write files formatted like the git-rebase-todo
|
* Offers methods to read and write files formatted like the git-rebase-todo
|
||||||
|
@ -216,9 +216,8 @@ private static RebaseTodoLine parseLine(byte[] buf, int tokenBegin,
|
||||||
*/
|
*/
|
||||||
public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
|
public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
|
||||||
boolean append) throws IOException {
|
boolean append) throws IOException {
|
||||||
BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(
|
OutputStream fw = new SafeBufferedOutputStream(new FileOutputStream(
|
||||||
new FileOutputStream(new File(repo.getDirectory(), path),
|
new File(repo.getDirectory(), path), append));
|
||||||
append), Constants.CHARACTER_ENCODING));
|
|
||||||
try {
|
try {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (RebaseTodoLine step : steps) {
|
for (RebaseTodoLine step : steps) {
|
||||||
|
@ -232,8 +231,8 @@ public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
|
||||||
sb.append(" "); //$NON-NLS-1$
|
sb.append(" "); //$NON-NLS-1$
|
||||||
sb.append(step.getShortMessage().trim());
|
sb.append(step.getShortMessage().trim());
|
||||||
}
|
}
|
||||||
fw.write(sb.toString());
|
sb.append('\n');
|
||||||
fw.newLine();
|
fw.write(Constants.encode(sb.toString()));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
fw.close();
|
fw.close();
|
||||||
|
|
|
@ -267,7 +267,7 @@ private String[] extractFileLines(final Charset[] csGuess) {
|
||||||
final TemporaryBuffer[] tmp = new TemporaryBuffer[getParentCount() + 1];
|
final TemporaryBuffer[] tmp = new TemporaryBuffer[getParentCount() + 1];
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < tmp.length; i++)
|
for (int i = 0; i < tmp.length; i++)
|
||||||
tmp[i] = new TemporaryBuffer.LocalFile();
|
tmp[i] = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
|
||||||
for (final HunkHeader h : getHunks())
|
for (final HunkHeader h : getHunks())
|
||||||
h.extractFileLines(tmp);
|
h.extractFileLines(tmp);
|
||||||
|
|
||||||
|
@ -281,11 +281,6 @@ private String[] extractFileLines(final Charset[] csGuess) {
|
||||||
return r;
|
return r;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new RuntimeException(JGitText.get().cannotConvertScriptToText, ioe);
|
throw new RuntimeException(JGitText.get().cannotConvertScriptToText, ioe);
|
||||||
} finally {
|
|
||||||
for (final TemporaryBuffer b : tmp) {
|
|
||||||
if (b != null)
|
|
||||||
b.destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,14 +139,10 @@ public void parse(final InputStream is) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] readFully(final InputStream is) throws IOException {
|
private static byte[] readFully(final InputStream is) throws IOException {
|
||||||
final TemporaryBuffer b = new TemporaryBuffer.LocalFile();
|
TemporaryBuffer b = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
|
||||||
try {
|
b.copy(is);
|
||||||
b.copy(is);
|
b.close();
|
||||||
b.close();
|
return b.toByteArray();
|
||||||
return b.toByteArray();
|
|
||||||
} finally {
|
|
||||||
b.destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -182,6 +182,9 @@ private static MessageDigest newMD5() {
|
||||||
/** Encryption algorithm, may be a null instance that provides pass-through. */
|
/** Encryption algorithm, may be a null instance that provides pass-through. */
|
||||||
private final WalkEncryption encryption;
|
private final WalkEncryption encryption;
|
||||||
|
|
||||||
|
/** Directory for locally buffered content. */
|
||||||
|
private final File tmpDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new S3 client for the supplied user information.
|
* Create a new S3 client for the supplied user information.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -251,6 +254,9 @@ else if (StringUtils.equalsIgnoreCase("PUBLIC_READ", pacl)) //$NON-NLS-1$
|
||||||
maxAttempts = Integer.parseInt(props.getProperty(
|
maxAttempts = Integer.parseInt(props.getProperty(
|
||||||
"httpclient.retry-max", "3")); //$NON-NLS-1$ //$NON-NLS-2$
|
"httpclient.retry-max", "3")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
proxySelector = ProxySelector.getDefault();
|
proxySelector = ProxySelector.getDefault();
|
||||||
|
|
||||||
|
String tmp = props.getProperty("tmpdir"); //$NON-NLS-1$
|
||||||
|
tmpDir = tmp != null && tmp.length() > 0 ? new File(tmp) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -452,7 +458,7 @@ public OutputStream beginPut(final String bucket, final String key,
|
||||||
final ProgressMonitor monitor, final String monitorTask)
|
final ProgressMonitor monitor, final String monitorTask)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final MessageDigest md5 = newMD5();
|
final MessageDigest md5 = newMD5();
|
||||||
final TemporaryBuffer buffer = new TemporaryBuffer.LocalFile() {
|
final TemporaryBuffer buffer = new TemporaryBuffer.LocalFile(tmpDir) {
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
super.close();
|
super.close();
|
||||||
|
|
|
@ -147,7 +147,11 @@ public Transport open(URIish uri, Repository local, String remoteName)
|
||||||
throws NotSupportedException {
|
throws NotSupportedException {
|
||||||
super(local, uri);
|
super(local, uri);
|
||||||
|
|
||||||
s3 = new AmazonS3(loadProperties());
|
Properties props = loadProperties();
|
||||||
|
if (!props.contains("tmpdir") && local.getDirectory() != null) //$NON-NLS-1$
|
||||||
|
props.put("tmpdir", local.getDirectory().getPath()); //$NON-NLS-1$
|
||||||
|
|
||||||
|
s3 = new AmazonS3(props);
|
||||||
bucket = uri.getHost();
|
bucket = uri.getHost();
|
||||||
|
|
||||||
String p = uri.getPath();
|
String p = uri.getPath();
|
||||||
|
|
|
@ -361,7 +361,12 @@ public static class LocalFile extends TemporaryBuffer {
|
||||||
*/
|
*/
|
||||||
private File onDiskFile;
|
private File onDiskFile;
|
||||||
|
|
||||||
/** Create a new temporary buffer. */
|
/**
|
||||||
|
* Create a new temporary buffer.
|
||||||
|
*
|
||||||
|
* @deprecated Use the {@code File} overload to supply a directory.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public LocalFile() {
|
public LocalFile() {
|
||||||
this(null, DEFAULT_IN_CORE_LIMIT);
|
this(null, DEFAULT_IN_CORE_LIMIT);
|
||||||
}
|
}
|
||||||
|
@ -372,7 +377,9 @@ public LocalFile() {
|
||||||
* @param inCoreLimit
|
* @param inCoreLimit
|
||||||
* maximum number of bytes to store in memory. Storage beyond
|
* maximum number of bytes to store in memory. Storage beyond
|
||||||
* this limit will use the local file.
|
* this limit will use the local file.
|
||||||
|
* @deprecated Use the {@code File,int} overload to supply a directory.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public LocalFile(final int inCoreLimit) {
|
public LocalFile(final int inCoreLimit) {
|
||||||
this(null, inCoreLimit);
|
this(null, inCoreLimit);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue