aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test/tst/org
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2015-03-12 19:30:37 -0700
committerChristian Halstrick <christian.halstrick@sap.com>2015-03-23 14:23:07 +0100
commit197e3393a51424fae45e51dce4a649ba26e5a368 (patch)
treef372aafc8cdd3b52aa41688fa3a07e3581ac4d51 /org.eclipse.jgit.test/tst/org
parent8ec01500e2eb8860e9e42dd20ead265cc2fb6735 (diff)
downloadjgit-197e3393a51424fae45e51dce4a649ba26e5a368.tar.gz
jgit-197e3393a51424fae45e51dce4a649ba26e5a368.zip
Merge bundle org.eclipse.jgit.java7 into org.eclipse.jgit
As we moved minimum Java version to 7 we don't need a separate bundle and feature for JGit features depending on Java 7 anymore. Change-Id: Ib5da61b0886ddbdea65298f1e8c6d65c9879ced1 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit.test/tst/org')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java99
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/SymlinksTest.java336
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorJava7Test.java200
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkJava7Test.java71
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSJava7Test.java190
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtils7Test.java86
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java192
8 files changed, 1176 insertions, 1 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
index 64bb8bfa4d..2220a536f1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
@@ -140,7 +140,8 @@ public class GitConstructionTest extends RepositoryTestCase {
public void testClose() throws IOException, JGitInternalException,
GitAPIException {
File workTree = db.getWorkTree();
- Git git = Git.wrap(db);
+ db.close();
+ Git git = Git.open(workTree);
git.gc().setExpire(null).call();
git.checkout().setName(git.getRepository().resolve("HEAD^").getName())
.call();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java
new file mode 100644
index 0000000000..b0d31cd372
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lib;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DirCacheCheckoutTestWithSymlinks extends RepositoryTestCase {
+ @Before
+ public void beforeMethod() {
+ // If this assumption fails the tests are skipped. When running on a
+ // filesystem not supporting symlinks I don't want this tests
+ org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
+ }
+
+ @Test
+ public void testDontDeleteSymlinkOnTopOfRootDir() throws Exception {
+ // create a parent folder containing a folder with a test repository
+ File repos = createTempDirectory("repos");
+ File testRepo = new File(repos, "repo");
+ testRepo.mkdirs();
+ Git git = Git.init().setDirectory(testRepo).call();
+ db = (FileRepository) git.getRepository();
+
+ // Create a situation where a checkout of master whould delete a file in
+ // a subfolder of the root of the worktree. No other files/folders exist
+ writeTrashFile("d/f", "f");
+ git.add().addFilepattern(".").call();
+ RevCommit initial = git.commit().setMessage("inital").call();
+ git.rm().addFilepattern("d/f").call();
+ git.commit().setMessage("modifyOnMaster").call();
+ git.checkout().setCreateBranch(true).setName("side")
+ .setStartPoint(initial).call();
+ writeTrashFile("d/f", "f2");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("modifyOnSide").call();
+ git.getRepository().close();
+
+ // Create a symlink pointing to the parent folder of the repo and open
+ // the repo with the path containing the symlink
+ File reposSymlink = createTempFile();
+ FileUtils.createSymLink(reposSymlink, repos.getPath());
+
+ Repository symlinkDB = FileRepositoryBuilder.create(new File(
+ reposSymlink, "repo/.git"));
+ Git symlinkRepo = Git.wrap(symlinkDB);
+ symlinkRepo.checkout().setName("master").call();
+
+ // check that the symlink still exists
+ assertTrue("The symlink to the repo should exist after a checkout",
+ reposSymlink.exists());
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/SymlinksTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/SymlinksTest.java
new file mode 100644
index 0000000000..3ddc3ded8c
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/SymlinksTest.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2013, Axel Richard <axel.richard@obeo.fr>
+ * 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.symlinks;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SymlinksTest extends RepositoryTestCase {
+ @Before
+ public void beforeMethod() {
+ // If this assumption fails the tests are skipped. When running on a
+ // filesystem not supporting symlinks I don't want this tests
+ org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
+ }
+
+ /**
+ * Steps: 1.Add file 'a' 2.Commit 3.Create branch '1' 4.Replace file 'a' by
+ * symlink 'a' 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestFileThenSymlink() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("a", "Hello world a");
+ writeTrashFile("b", "Hello world b");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("add files a & b").call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ git.rm().addFilepattern("a").call();
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "b");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("add symlink a").call();
+
+ FileEntry entry = new FileTreeIterator.FileEntry(new File(
+ db.getWorkTree(), "a"), db.getFS());
+ assertEquals(FileMode.SYMLINK, entry.getMode());
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
+ db.getFS());
+ assertEquals(FileMode.REGULAR_FILE, entry.getMode());
+ }
+
+ /**
+ * Steps: 1.Add symlink 'a' 2.Commit 3.Create branch '1' 4.Replace symlink
+ * 'a' by file 'a' 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should contain 'a' with FileMode.SYMLINK after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestSymlinkThenFile() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("b", "Hello world b");
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "b");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("add file b & symlink a").call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ git.rm().addFilepattern("a").call();
+ writeTrashFile("a", "Hello world a");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("add file a").call();
+
+ FileEntry entry = new FileTreeIterator.FileEntry(new File(
+ db.getWorkTree(), "a"), db.getFS());
+ assertEquals(FileMode.REGULAR_FILE, entry.getMode());
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
+ db.getFS());
+ assertEquals(FileMode.SYMLINK, entry.getMode());
+ }
+
+ /**
+ * Steps: 1.Add folder 'a' 2.Commit 3.Create branch '1' 4.Replace folder 'a'
+ * by symlink 'a' 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should contain 'a' with FileMode.TREE after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestFolderThenSymlink() throws Exception {
+ Git git = new Git(db);
+ FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
+ writeTrashFile("a/b", "Hello world b");
+ writeTrashFile("c", "Hello world c");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("add folder a").call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ git.rm().addFilepattern("a").call();
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "c");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("add symlink a").call();
+
+ FileEntry entry = new FileTreeIterator.FileEntry(new File(
+ db.getWorkTree(), "a"), db.getFS());
+ assertEquals(FileMode.SYMLINK, entry.getMode());
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
+ db.getFS());
+ assertEquals(FileMode.TREE, entry.getMode());
+ }
+
+ /**
+ * Steps: 1.Add symlink 'a' 2.Commit 3.Create branch '1' 4.Replace symlink
+ * 'a' by folder 'a' 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should contain 'a' with FileMode.SYMLINK after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestSymlinkThenFolder() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("c", "Hello world c");
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "c");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("add symlink a").call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ git.rm().addFilepattern("a").call();
+ FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
+ writeTrashFile("a/b", "Hello world b");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("add folder a").call();
+
+ FileEntry entry = new FileTreeIterator.FileEntry(new File(
+ db.getWorkTree(), "a"), db.getFS());
+ assertEquals(FileMode.TREE, entry.getMode());
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
+ db.getFS());
+ assertEquals(FileMode.SYMLINK, entry.getMode());
+ }
+
+ /**
+ * Steps: 1.Add file 'b' 2.Commit 3.Create branch '1' 4.Add symlink 'a'
+ * 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should not contain 'a' -> FileMode.MISSING after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestMissingThenSymlink() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("b", "Hello world b");
+ git.add().addFilepattern(".").call();
+ RevCommit commit1 = git.commit().setMessage("add file b").call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "b");
+ git.add().addFilepattern("a").call();
+ RevCommit commit2 = git.commit().setMessage("add symlink a").call();
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ TreeWalk tw = new TreeWalk(db);
+ tw.addTree(commit1.getTree());
+ tw.addTree(commit2.getTree());
+ List<DiffEntry> scan = DiffEntry.scan(tw);
+ assertEquals(1, scan.size());
+ assertEquals(FileMode.SYMLINK, scan.get(0).getNewMode());
+ assertEquals(FileMode.MISSING, scan.get(0).getOldMode());
+ }
+
+ /**
+ * Steps: 1.Add symlink 'a' 2.Commit 3.Create branch '1' 4.Delete symlink
+ * 'a' 5.Commit 6.Checkout branch '1'
+ *
+ * The working tree should contain 'a' with FileMode.SYMLINK after the
+ * checkout.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void fileModeTestSymlinkThenMissing() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("b", "Hello world b");
+ FileUtils.createSymLink(new File(db.getWorkTree(), "a"), "b");
+ git.add().addFilepattern(".").call();
+ RevCommit commit1 = git.commit().setMessage("add file b & symlink a")
+ .call();
+ Ref branch_1 = git.branchCreate().setName("branch_1").call();
+ git.rm().addFilepattern("a").call();
+ RevCommit commit2 = git.commit().setMessage("delete symlink a").call();
+
+ git.checkout().setName(branch_1.getName()).call();
+
+ TreeWalk tw = new TreeWalk(db);
+ tw.addTree(commit1.getTree());
+ tw.addTree(commit2.getTree());
+ List<DiffEntry> scan = DiffEntry.scan(tw);
+ assertEquals(1, scan.size());
+ assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
+ assertEquals(FileMode.SYMLINK, scan.get(0).getOldMode());
+ }
+
+ @Test
+ public void createSymlinkAfterTarget() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("a", "start");
+ git.add().addFilepattern("a").call();
+ RevCommit base = git.commit().setMessage("init").call();
+ writeTrashFile("target", "someData");
+ FileUtils.createSymLink(new File(db.getWorkTree(), "link"), "target");
+ git.add().addFilepattern("target").addFilepattern("link").call();
+ git.commit().setMessage("add target").call();
+ assertEquals(4, db.getWorkTree().list().length); // self-check
+ git.checkout().setName(base.name()).call();
+ assertEquals(2, db.getWorkTree().list().length); // self-check
+ git.checkout().setName("master").call();
+ assertEquals(4, db.getWorkTree().list().length);
+ String data = read(new File(db.getWorkTree(), "target"));
+ assertEquals(8, new File(db.getWorkTree(), "target").length());
+ assertEquals("someData", data);
+ data = read(new File(db.getWorkTree(), "link"));
+ assertEquals("target",
+ FileUtils.readSymLink(new File(db.getWorkTree(), "link")));
+ assertEquals("someData", data);
+ }
+
+ @Test
+ public void createFileSymlinkBeforeTarget() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("a", "start");
+ git.add().addFilepattern("a").call();
+ RevCommit base = git.commit().setMessage("init").call();
+ writeTrashFile("target", "someData");
+ FileUtils.createSymLink(new File(db.getWorkTree(), "tlink"), "target");
+ git.add().addFilepattern("target").addFilepattern("tlink").call();
+ git.commit().setMessage("add target").call();
+ assertEquals(4, db.getWorkTree().list().length); // self-check
+ git.checkout().setName(base.name()).call();
+ assertEquals(2, db.getWorkTree().list().length); // self-check
+ git.checkout().setName("master").call();
+ assertEquals(4, db.getWorkTree().list().length);
+ String data = read(new File(db.getWorkTree(), "target"));
+ assertEquals(8, new File(db.getWorkTree(), "target").length());
+ assertEquals("someData", data);
+ data = read(new File(db.getWorkTree(), "tlink"));
+ assertEquals("target",
+ FileUtils.readSymLink(new File(db.getWorkTree(), "tlink")));
+ assertEquals("someData", data);
+ }
+
+ @Test
+ public void createDirSymlinkBeforeTarget() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("a", "start");
+ git.add().addFilepattern("a").call();
+ RevCommit base = git.commit().setMessage("init").call();
+ FileUtils.createSymLink(new File(db.getWorkTree(), "link"), "target");
+ FileUtils.mkdir(new File(db.getWorkTree(), "target"));
+ writeTrashFile("target/file", "someData");
+ git.add().addFilepattern("target").addFilepattern("link").call();
+ git.commit().setMessage("add target").call();
+ assertEquals(4, db.getWorkTree().list().length); // self-check
+ git.checkout().setName(base.name()).call();
+ assertEquals(2, db.getWorkTree().list().length); // self-check
+ git.checkout().setName("master").call();
+ assertEquals(4, db.getWorkTree().list().length);
+ String data = read(new File(db.getWorkTree(), "target/file"));
+ assertEquals(8, new File(db.getWorkTree(), "target/file").length());
+ assertEquals("someData", data);
+ data = read(new File(db.getWorkTree(), "link/file"));
+ assertEquals("target",
+ FileUtils.readSymLink(new File(db.getWorkTree(), "link")));
+ assertEquals("someData", data);
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorJava7Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorJava7Test.java
new file mode 100644
index 0000000000..741396c519
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorJava7Test.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2012-2013, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * 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.treewalk;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEditor;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Test;
+
+public class FileTreeIteratorJava7Test extends RepositoryTestCase {
+ @Test
+ public void testFileModeSymLinkIsNotATree() throws IOException {
+ FS fs = db.getFS();
+ // mål = target in swedish, just to get som unicode in here
+ writeTrashFile("mål/data", "targetdata");
+ fs.createSymLink(new File(trash, "länk"), "mål");
+ FileTreeIterator fti = new FileTreeIterator(db);
+ assertFalse(fti.eof());
+ assertEquals("länk", fti.getEntryPathString());
+ assertEquals(FileMode.SYMLINK, fti.getEntryFileMode());
+ fti.next(1);
+ assertFalse(fti.eof());
+ assertEquals("mål", fti.getEntryPathString());
+ assertEquals(FileMode.TREE, fti.getEntryFileMode());
+ fti.next(1);
+ assertTrue(fti.eof());
+ }
+
+ @Test
+ public void testSymlinkNotModifiedThoughNormalized() throws Exception {
+ DirCache dc = db.lockDirCache();
+ DirCacheEditor dce = dc.editor();
+ final String UNNORMALIZED = "target/";
+ final byte[] UNNORMALIZED_BYTES = Constants.encode(UNNORMALIZED);
+ ObjectInserter oi = db.newObjectInserter();
+ final ObjectId linkid = oi.insert(Constants.OBJ_BLOB,
+ UNNORMALIZED_BYTES, 0,
+ UNNORMALIZED_BYTES.length);
+ oi.release();
+ dce.add(new DirCacheEditor.PathEdit("link") {
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.SYMLINK);
+ ent.setObjectId(linkid);
+ ent.setLength(UNNORMALIZED_BYTES.length);
+ }
+ });
+ assertTrue(dce.commit());
+ new Git(db).commit().setMessage("Adding link").call();
+ new Git(db).reset().setMode(ResetType.HARD).call();
+ DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator fti = new FileTreeIterator(db);
+
+ // self-check
+ assertEquals("link", fti.getEntryPathString());
+ assertEquals("link", dci.getEntryPathString());
+
+ // test
+ assertFalse(fti.isModified(dci.getDirCacheEntry(), true,
+ db.newObjectReader()));
+ }
+
+ /**
+ * Like #testSymlinkNotModifiedThoughNormalized but there is no
+ * normalization being done.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testSymlinkModifiedNotNormalized() throws Exception {
+ DirCache dc = db.lockDirCache();
+ DirCacheEditor dce = dc.editor();
+ final String NORMALIZED = "target";
+ final byte[] NORMALIZED_BYTES = Constants.encode(NORMALIZED);
+ ObjectInserter oi = db.newObjectInserter();
+ final ObjectId linkid = oi.insert(Constants.OBJ_BLOB, NORMALIZED_BYTES,
+ 0, NORMALIZED_BYTES.length);
+ oi.release();
+ dce.add(new DirCacheEditor.PathEdit("link") {
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.SYMLINK);
+ ent.setObjectId(linkid);
+ ent.setLength(NORMALIZED_BYTES.length);
+ }
+ });
+ assertTrue(dce.commit());
+ new Git(db).commit().setMessage("Adding link").call();
+ new Git(db).reset().setMode(ResetType.HARD).call();
+ DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator fti = new FileTreeIterator(db);
+
+ // self-check
+ assertEquals("link", fti.getEntryPathString());
+ assertEquals("link", dci.getEntryPathString());
+
+ // test
+ assertFalse(fti.isModified(dci.getDirCacheEntry(), true,
+ db.newObjectReader()));
+ }
+
+ /**
+ * Like #testSymlinkNotModifiedThoughNormalized but here the link is
+ * modified.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testSymlinkActuallyModified() throws Exception {
+ final String NORMALIZED = "target";
+ final byte[] NORMALIZED_BYTES = Constants.encode(NORMALIZED);
+ ObjectInserter oi = db.newObjectInserter();
+ final ObjectId linkid = oi.insert(Constants.OBJ_BLOB, NORMALIZED_BYTES,
+ 0, NORMALIZED_BYTES.length);
+ oi.release();
+ DirCache dc = db.lockDirCache();
+ DirCacheEditor dce = dc.editor();
+ dce.add(new DirCacheEditor.PathEdit("link") {
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.SYMLINK);
+ ent.setObjectId(linkid);
+ ent.setLength(NORMALIZED_BYTES.length);
+ }
+ });
+ assertTrue(dce.commit());
+ new Git(db).commit().setMessage("Adding link").call();
+ new Git(db).reset().setMode(ResetType.HARD).call();
+
+ FileUtils.delete(new File(trash, "link"), FileUtils.NONE);
+ FS.DETECTED.createSymLink(new File(trash, "link"), "newtarget");
+ DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator fti = new FileTreeIterator(db);
+
+ // self-check
+ assertEquals("link", fti.getEntryPathString());
+ assertEquals("link", dci.getEntryPathString());
+
+ // test
+ assertTrue(fti.isModified(dci.getDirCacheEntry(), true,
+ db.newObjectReader()));
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkJava7Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkJava7Test.java
new file mode 100644
index 0000000000..bb1f2a639b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkJava7Test.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012-2013, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * 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.treewalk;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.util.FS;
+import org.junit.Test;
+
+public class TreeWalkJava7Test extends RepositoryTestCase {
+ @Test
+ public void testSymlinkToDirNotRecursingViaSymlink() throws Exception {
+ FS fs = db.getFS();
+ assertTrue(fs.supportsSymlinks());
+ writeTrashFile("target/data", "targetdata");
+ fs.createSymLink(new File(trash, "link"), "target");
+ TreeWalk tw = new TreeWalk(db);
+ tw.setRecursive(true);
+ tw.addTree(new FileTreeIterator(db));
+ assertTrue(tw.next());
+ assertEquals("link", tw.getPathString());
+ assertTrue(tw.next());
+ assertEquals("target/data", tw.getPathString());
+ assertFalse(tw.next());
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSJava7Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSJava7Test.java
new file mode 100644
index 0000000000..9fba374dcd
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSJava7Test.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2012-2013, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Set;
+
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FSJava7Test {
+ private File trash;
+
+ @Before
+ public void setUp() throws Exception {
+ trash = File.createTempFile("tmp_", "");
+ trash.delete();
+ assertTrue("mkdir " + trash, trash.mkdir());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtils.delete(trash, FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+
+ /**
+ * The old File methods traverse symbolic links and look at the targets.
+ * With symbolic links we usually want to modify/look at the link. For some
+ * reason the executable attribute seems to always look at the target, but
+ * for the other attributes like lastModified, hidden and exists we must
+ * differ between the link and the target.
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ @Test
+ public void testSymlinkAttributes() throws IOException, InterruptedException {
+ FS fs = FS.DETECTED;
+ File link = new File(trash, "ä");
+ File target = new File(trash, "å");
+ fs.createSymLink(link, "å");
+ assertTrue(fs.exists(link));
+ String targetName = fs.readSymLink(link);
+ assertEquals("å", targetName);
+ assertTrue(fs.lastModified(link) > 0);
+ assertTrue(fs.exists(link));
+ assertFalse(fs.canExecute(link));
+ assertEquals(2, fs.length(link));
+ assertFalse(fs.exists(target));
+ assertFalse(fs.isFile(target));
+ assertFalse(fs.isDirectory(target));
+ assertFalse(fs.canExecute(target));
+
+ RepositoryTestCase.fsTick(link);
+ // Now create the link target
+ FileUtils.createNewFile(target);
+ assertTrue(fs.exists(link));
+ assertTrue(fs.lastModified(link) > 0);
+ assertTrue(fs.lastModified(target) > fs.lastModified(link));
+ assertFalse(fs.canExecute(link));
+ fs.setExecute(target, true);
+ assertFalse(fs.canExecute(link));
+ assumeTrue(fs.supportsExecute());
+ assertTrue(fs.canExecute(target));
+ }
+
+ @Test
+ public void testExecutableAttributes() throws Exception {
+ FS fs = FS.DETECTED;
+ // If this assumption fails the test is halted and ignored.
+ assumeTrue(fs instanceof FS_POSIX);
+
+ File f = new File(trash, "bla");
+ assertTrue(f.createNewFile());
+ assertFalse(fs.canExecute(f));
+
+ String umask = readUmask();
+ assumeNotNull(umask);
+
+ char others = umask.charAt(umask.length() - 1);
+
+ boolean badUmask;
+ if (others != '0' && others != '2' && others != '4' && others != '6') {
+ // umask is set in the way that "others" can not "execute" => git
+ // CLI will not set "execute" attribute for "others", so we also
+ // don't care
+ badUmask = true;
+ } else {
+ badUmask = false;
+ }
+
+ Set<PosixFilePermission> permissions = readPermissions(f);
+ assertTrue(!permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
+ assertTrue(!permissions.contains(PosixFilePermission.GROUP_EXECUTE));
+ assertTrue(!permissions.contains(PosixFilePermission.OWNER_EXECUTE));
+
+ fs.setExecute(f, true);
+
+ permissions = readPermissions(f);
+ assertTrue("'owner' execute permission not set",
+ permissions.contains(PosixFilePermission.OWNER_EXECUTE));
+ assertTrue("'group' execute permission not set",
+ permissions.contains(PosixFilePermission.GROUP_EXECUTE));
+ if (badUmask) {
+ assertFalse("'others' execute permission set",
+ permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
+ System.err.println("WARNING: your system's umask: \"" + umask
+ + "\" doesn't allow FSJava7Test to test if setting posix"
+ + " permissions for \"others\" works properly");
+ assumeFalse(badUmask);
+ } else {
+ assertTrue("'others' execute permission not set",
+ permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
+ }
+ }
+
+ private String readUmask() throws Exception {
+ Process p = Runtime.getRuntime().exec(
+ new String[] { "sh", "-c", "umask" }, null, null);
+ final BufferedReader lineRead = new BufferedReader(
+ new InputStreamReader(p.getInputStream(), Charset
+ .defaultCharset().name()));
+ p.waitFor();
+ return lineRead.readLine();
+ }
+
+ private Set<PosixFilePermission> readPermissions(File f) throws IOException {
+ return Files
+ .getFileAttributeView(f.toPath(), PosixFileAttributeView.class)
+ .readAttributes().permissions();
+ }
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtils7Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtils7Test.java
new file mode 100644
index 0000000000..9dc5fac5d8
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtils7Test.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * 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.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FileUtils7Test {
+
+ private final File trash = new File(new File("target"), "trash");
+
+ @Before
+ public void setUp() throws Exception {
+ FileUtils.delete(trash, FileUtils.RECURSIVE | FileUtils.RETRY | FileUtils.SKIP_MISSING);
+ assertTrue(trash.mkdirs());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtils.delete(trash, FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+
+ @Test
+ public void testDeleteSymlinkToDirectoryDoesNotDeleteTarget()
+ throws IOException {
+ FS fs = FS.DETECTED;
+ File dir = new File(trash, "dir");
+ File file = new File(dir, "file");
+ File link = new File(trash, "link");
+ FileUtils.mkdirs(dir);
+ FileUtils.createNewFile(file);
+ fs.createSymLink(link, "dir");
+ FileUtils.delete(link, FileUtils.RECURSIVE);
+ assertFalse(link.exists());
+ assertTrue(dir.exists());
+ assertTrue(file.exists());
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java
new file mode 100644
index 0000000000..b14a9bf2fa
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2014 Matthias Sohn <matthias.sohn@sap.com>
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.AbortedByHookException;
+import org.eclipse.jgit.hooks.CommitMsgHook;
+import org.eclipse.jgit.hooks.PreCommitHook;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class HookTest extends RepositoryTestCase {
+
+ @Test
+ public void testFindHook() throws Exception {
+ assumeSupportedPlatform();
+
+ assertNull("no hook should be installed",
+ FS.DETECTED.findHook(db, PreCommitHook.NAME));
+ File hookFile = writeHookFile(PreCommitHook.NAME,
+ "#!/bin/bash\necho \"test $1 $2\"");
+ assertEquals("expected to find pre-commit hook", hookFile,
+ FS.DETECTED.findHook(db, PreCommitHook.NAME));
+ }
+
+ @Test
+ public void testFailedCommitMsgHookBlocksCommit() throws Exception {
+ assumeSupportedPlatform();
+
+ writeHookFile(CommitMsgHook.NAME,
+ "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
+ Git git = Git.wrap(db);
+ String path = "a.txt";
+ writeTrashFile(path, "content");
+ git.add().addFilepattern(path).call();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ git.commit().setMessage("commit")
+ .setHookOutputStream(new PrintStream(out)).call();
+ fail("expected commit-msg hook to abort commit");
+ } catch (AbortedByHookException e) {
+ assertEquals("unexpected error message from commit-msg hook",
+ "Rejected by \"commit-msg\" hook.\nstderr\n",
+ e.getMessage());
+ assertEquals("unexpected output from commit-msg hook", "test\n",
+ out.toString());
+ }
+ }
+
+ @Test
+ public void testCommitMsgHookReceivesCorrectParameter() throws Exception {
+ assumeSupportedPlatform();
+
+ writeHookFile(CommitMsgHook.NAME,
+ "#!/bin/sh\necho $1\n\necho 1>&2 \"stderr\"\nexit 0");
+ Git git = Git.wrap(db);
+ String path = "a.txt";
+ writeTrashFile(path, "content");
+ git.add().addFilepattern(path).call();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ git.commit().setMessage("commit")
+ .setHookOutputStream(new PrintStream(out)).call();
+ assertEquals(".git/COMMIT_EDITMSG\n", out.toString("UTF-8"));
+ }
+
+ @Test
+ public void testCommitMsgHookCanModifyCommitMessage() throws Exception {
+ assumeSupportedPlatform();
+
+ writeHookFile(CommitMsgHook.NAME,
+ "#!/bin/sh\necho \"new message\" > $1\nexit 0");
+ Git git = Git.wrap(db);
+ String path = "a.txt";
+ writeTrashFile(path, "content");
+ git.add().addFilepattern(path).call();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ RevCommit revCommit = git.commit().setMessage("commit")
+ .setHookOutputStream(new PrintStream(out)).call();
+ assertEquals("new message\n", revCommit.getFullMessage());
+ }
+
+ @Test
+ public void testRunHook() throws Exception {
+ assumeSupportedPlatform();
+
+ writeHookFile(PreCommitHook.NAME,
+ "#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ ProcessResult res = FS.DETECTED.runHookIfPresent(db,
+ PreCommitHook.NAME,
+ new String[] {
+ "arg1", "arg2" },
+ new PrintStream(out), new PrintStream(err), "stdin");
+ assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
+ out.toString("UTF-8"));
+ assertEquals("unexpected output on stderr stream", "stderr\n",
+ err.toString("UTF-8"));
+ assertEquals("unexpected exit code", 0, res.getExitCode());
+ assertEquals("unexpected process status", ProcessResult.Status.OK,
+ res.getStatus());
+ }
+
+ @Test
+ public void testFailedPreCommitHookBlockCommit() throws Exception {
+ assumeSupportedPlatform();
+
+ writeHookFile(PreCommitHook.NAME,
+ "#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
+ Git git = Git.wrap(db);
+ String path = "a.txt";
+ writeTrashFile(path, "content");
+ git.add().addFilepattern(path).call();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ git.commit().setMessage("commit")
+ .setHookOutputStream(new PrintStream(out)).call();
+ fail("expected pre-commit hook to abort commit");
+ } catch (AbortedByHookException e) {
+ assertEquals("unexpected error message from pre-commit hook",
+ "Rejected by \"pre-commit\" hook.\nstderr\n",
+ e.getMessage());
+ assertEquals("unexpected output from pre-commit hook", "test\n",
+ out.toString());
+ }
+ }
+
+ private File writeHookFile(final String name, final String data)
+ throws IOException {
+ File path = new File(db.getWorkTree() + "/.git/hooks/", name);
+ JGitTestUtil.write(path, data);
+ FS.DETECTED.setExecute(path, true);
+ return path;
+ }
+
+ private void assumeSupportedPlatform() {
+ Assume.assumeTrue(FS.DETECTED instanceof FS_POSIX
+ || FS.DETECTED instanceof FS_Win32_Cygwin);
+ }
+}