aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/JGitTestUtil.java7
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java392
-rw-r--r--org.eclipse.jgit/.settings/.api_filters8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java55
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java13
8 files changed, 477 insertions, 8 deletions
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/JGitTestUtil.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/JGitTestUtil.java
index 136c64726f..521593ea80 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/JGitTestUtil.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/JGitTestUtil.java
@@ -55,6 +55,7 @@ import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Path;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FileUtils;
@@ -240,4 +241,10 @@ public abstract class JGitTestUtil {
FileUtils.delete(path);
}
+ public static Path writeLink(Repository db, String link,
+ String target) throws Exception {
+ return FileUtils.createSymLink(new File(db.getWorkTree(), link),
+ target);
+ }
+
}
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java
index ac4539a848..28c61778c7 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java
@@ -55,6 +55,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.nio.file.Path;
import java.util.Map;
import org.eclipse.jgit.api.Git;
@@ -107,6 +108,11 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
return JGitTestUtil.writeTrashFile(db, name, data);
}
+ protected Path writeLink(final String link, final String target)
+ throws Exception {
+ return JGitTestUtil.writeLink(db, link, target);
+ }
+
protected File writeTrashFile(final String subdir, final String name,
final String data)
throws IOException {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
index a8a54a8df7..6d62528f85 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
@@ -924,6 +924,299 @@ public class DirCacheCheckoutTest extends RepositoryTestCase {
}
@Test
+ public void testCheckoutChangeLinkToEmptyDir() throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+
+ // Add a link to file
+ String linkName = "link";
+ File link = writeLink(linkName, fname).toFile();
+ git.add().addFilepattern(linkName).call();
+ git.commit().setMessage("Added file and link").call();
+
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ // replace link with empty directory
+ FileUtils.delete(link);
+ FileUtils.mkdir(link);
+ assertTrue("Link must be a directory now", link.isDirectory());
+
+ // modify file
+ writeTrashFile(fname, "b");
+ assertWorkDir(mkmap(fname, "b", linkName, "/"));
+
+ // revert both paths to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD)
+ .addPath(fname).addPath(linkName).call();
+
+ assertWorkDir(mkmap(fname, "a", linkName, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeLinkToEmptyDirs() throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+
+ // Add a link to file
+ String linkName = "link";
+ File link = writeLink(linkName, fname).toFile();
+ git.add().addFilepattern(linkName).call();
+ git.commit().setMessage("Added file and link").call();
+
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ // replace link with directory containing only directories, no files
+ FileUtils.delete(link);
+ FileUtils.mkdirs(new File(link, "dummyDir"));
+ assertTrue("Link must be a directory now", link.isDirectory());
+
+ assertFalse("Must not delete non empty directory", link.delete());
+
+ // modify file
+ writeTrashFile(fname, "b");
+ assertWorkDir(mkmap(fname, "b", linkName + "/dummyDir", "/"));
+
+ // revert both paths to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD)
+ .addPath(fname).addPath(linkName).call();
+
+ assertWorkDir(mkmap(fname, "a", linkName, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeLinkToNonEmptyDirs() throws Exception {
+ String fname = "file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+
+ // Add a link to file
+ String linkName = "link";
+ File link = writeLink(linkName, fname).toFile();
+ git.add().addFilepattern(linkName).call();
+ git.commit().setMessage("Added file and link").call();
+
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ // replace link with directory containing only directories, no files
+ FileUtils.delete(link);
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir1", "file1", "c");
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir2", "file2", "d");
+
+ assertTrue("File must be a directory now", link.isDirectory());
+ assertFalse("Must not delete non empty directory", link.delete());
+
+ // 2 extra files are created
+ assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
+ linkName + "/dir2/file2", "d"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(linkName).call();
+
+ // expect only the one added to the index
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeLinkToNonEmptyDirsAndNewIndexEntry()
+ throws Exception {
+ String fname = "file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+
+ // Add a link to file
+ String linkName = "link";
+ File link = writeLink(linkName, fname).toFile();
+ git.add().addFilepattern(linkName).call();
+ git.commit().setMessage("Added file and link").call();
+
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ // replace link with directory containing only directories, no files
+ FileUtils.delete(link);
+
+ // create and add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir1", "file1", "c");
+ git.add().addFilepattern(linkName + "/dir1/file1").call();
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir2", "file2", "d");
+
+ assertTrue("File must be a directory now", link.isDirectory());
+ assertFalse("Must not delete non empty directory", link.delete());
+
+ // 2 extra files are created
+ assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
+ linkName + "/dir2/file2", "d"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(linkName).call();
+
+ // original file and link
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ Status st = git.status().call();
+ assertFalse(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeFileToEmptyDir() throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ File file = writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+ git.commit().setMessage("Added file").call();
+
+ // replace file with empty directory
+ FileUtils.delete(file);
+ FileUtils.mkdir(file);
+ assertTrue("File must be a directory now", file.isDirectory());
+
+ assertWorkDir(mkmap(fname, "/"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
+
+ assertWorkDir(mkmap(fname, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeFileToEmptyDirs() throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ File file = writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+ git.commit().setMessage("Added file").call();
+
+ // replace file with directory containing only directories, no files
+ FileUtils.delete(file);
+ FileUtils.mkdirs(new File(file, "dummyDir"));
+ assertTrue("File must be a directory now", file.isDirectory());
+ assertFalse("Must not delete non empty directory", file.delete());
+
+ assertWorkDir(mkmap(fname + "/dummyDir", "/"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
+
+ assertWorkDir(mkmap(fname, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeFileToNonEmptyDirs() throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ File file = writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+ git.commit().setMessage("Added file").call();
+
+ assertWorkDir(mkmap(fname, "a"));
+
+ // replace file with directory containing only directories, no files
+ FileUtils.delete(file);
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(fname + "/dir1", "file1", "c");
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(fname + "/dir2", "file2", "d");
+
+ assertTrue("File must be a directory now", file.isDirectory());
+ assertFalse("Must not delete non empty directory", file.delete());
+
+ // 2 extra files are created
+ assertWorkDir(
+ mkmap(fname + "/dir1/file1", "c", fname + "/dir2/file2", "d"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
+
+ // expect only the one added to the index
+ assertWorkDir(mkmap(fname, "a"));
+
+ Status st = git.status().call();
+ assertTrue(st.isClean());
+ }
+
+ @Test
+ public void testCheckoutChangeFileToNonEmptyDirsAndNewIndexEntry()
+ throws Exception {
+ String fname = "was_file";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ File file = writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+ git.commit().setMessage("Added file").call();
+
+ assertWorkDir(mkmap(fname, "a"));
+
+ // replace file with directory containing only directories, no files
+ FileUtils.delete(file);
+
+ // create and add a file in the new directory to the index
+ writeTrashFile(fname + "/dir", "file1", "c");
+ git.add().addFilepattern(fname + "/dir/file1").call();
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(fname + "/dir", "file2", "d");
+
+ assertTrue("File must be a directory now", file.isDirectory());
+ assertFalse("Must not delete non empty directory", file.delete());
+
+ // 2 extra files are created
+ assertWorkDir(
+ mkmap(fname + "/dir/file1", "c", fname + "/dir/file2", "d"));
+
+ // revert path to HEAD state
+ git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
+ assertWorkDir(mkmap(fname, "a"));
+
+ Status st = git.status().call();
+ assertFalse(st.isClean());
+ assertEquals(1, st.getAdded().size());
+ assertTrue(st.getAdded().contains(fname + "/dir/file1"));
+ }
+
+ @Test
public void testCheckoutOutChangesAutoCRLFfalse() throws IOException {
setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
checkout();
@@ -1024,6 +1317,102 @@ public class DirCacheCheckoutTest extends RepositoryTestCase {
}
@Test
+ public void testOverwriteUntrackedFileModeChange()
+ throws IOException, GitAPIException {
+ String fname = "file.txt";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ File file = writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+ git.commit().setMessage("create file").call();
+ assertWorkDir(mkmap(fname, "a"));
+
+ // Create branch
+ git.branchCreate().setName("side").call();
+
+ // Switch branches
+ git.checkout().setName("side").call();
+
+ // replace file with directory containing files
+ FileUtils.delete(file);
+
+ // create and add a file in the new directory to the index
+ writeTrashFile(fname + "/dir1", "file1", "c");
+ git.add().addFilepattern(fname + "/dir1/file1").call();
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(fname + "/dir2", "file2", "d");
+
+ assertTrue("File must be a directory now", file.isDirectory());
+ assertFalse("Must not delete non empty directory", file.delete());
+
+ // 2 extra files are created
+ assertWorkDir(
+ mkmap(fname + "/dir1/file1", "c", fname + "/dir2/file2", "d"));
+
+ try {
+ git.checkout().setName("master").call();
+ fail("did not throw exception");
+ } catch (Exception e) {
+ // 2 extra files are still there
+ assertWorkDir(mkmap(fname + "/dir1/file1", "c",
+ fname + "/dir2/file2", "d"));
+ }
+ }
+
+ @Test
+ public void testOverwriteUntrackedLinkModeChange()
+ throws Exception {
+ String fname = "file.txt";
+ Git git = Git.wrap(db);
+
+ // Add a file
+ writeTrashFile(fname, "a");
+ git.add().addFilepattern(fname).call();
+
+ // Add a link to file
+ String linkName = "link";
+ File link = writeLink(linkName, fname).toFile();
+ git.add().addFilepattern(linkName).call();
+ git.commit().setMessage("Added file and link").call();
+
+ assertWorkDir(mkmap(linkName, "a", fname, "a"));
+
+ // Create branch
+ git.branchCreate().setName("side").call();
+
+ // Switch branches
+ git.checkout().setName("side").call();
+
+ // replace link with directory containing files
+ FileUtils.delete(link);
+
+ // create and add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir1", "file1", "c");
+ git.add().addFilepattern(linkName + "/dir1/file1").call();
+
+ // create but do not add a file in the new directory to the index
+ writeTrashFile(linkName + "/dir2", "file2", "d");
+
+ assertTrue("Link must be a directory now", link.isDirectory());
+ assertFalse("Must not delete non empty directory", link.delete());
+
+ // 2 extra files are created
+ assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
+ linkName + "/dir2/file2", "d"));
+
+ try {
+ git.checkout().setName("master").call();
+ fail("did not throw exception");
+ } catch (Exception e) {
+ // 2 extra files are still there
+ assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
+ linkName + "/dir2/file2", "d"));
+ }
+ }
+
+ @Test
public void testFileModeChangeWithNoContentChangeUpdate() throws Exception {
if (!FS.DETECTED.supportsExecute())
return;
@@ -1219,7 +1608,8 @@ public class DirCacheCheckoutTest extends RepositoryTestCase {
assertNotNull(git.checkout().setName(Constants.MASTER).call());
}
- public void assertWorkDir(HashMap<String, String> i) throws CorruptObjectException,
+ public void assertWorkDir(Map<String, String> i)
+ throws CorruptObjectException,
IOException {
TreeWalk walk = new TreeWalk(db);
walk.setRecursive(false);
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index a1e79e2d29..f34226c42b 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -21,4 +21,12 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/jgit/util/FileUtils.java" type="org.eclipse.jgit.util.FileUtils">
+ <filter id="338792546">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.FileUtils"/>
+ <message_argument value="createSymLink(File, String)"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index 8d8aada622..8d85bfcb15 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -457,7 +457,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
private void checkoutPath(DirCacheEntry entry, ObjectReader reader) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader);
+ DirCacheCheckout.checkoutEntry(repo, entry, reader, true);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
index 6de25a052a..8ef550871f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -357,7 +357,7 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
private void checkoutPath(DirCacheEntry entry, ObjectReader reader) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader);
+ DirCacheCheckout.checkoutEntry(repo, entry, reader, true);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 00252547db..0036ab5089 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -447,7 +447,7 @@ public class DirCacheCheckout {
for (String path : updated.keySet()) {
DirCacheEntry entry = dc.getEntry(path);
if (!FileMode.GITLINK.equals(entry.getRawMode()))
- checkoutEntry(repo, entry, objectReader);
+ checkoutEntry(repo, entry, objectReader, false);
}
// commit the index builder - a new index is persisted
@@ -1127,6 +1127,13 @@ public class DirCacheCheckout {
* final filename.
*
* <p>
+ * <b>Note:</b> if the entry path on local file system exists as a non-empty
+ * directory, and the target entry type is a link or file, the checkout will
+ * fail with {@link IOException} since existing non-empty directory cannot
+ * be renamed to file or link without deleting it recursively.
+ * </p>
+ *
+ * <p>
* TODO: this method works directly on File IO, we may need another
* abstraction (like WorkingTreeIterator). This way we could tell e.g.
* Eclipse that Files in the workspace got changed
@@ -1143,6 +1150,42 @@ public class DirCacheCheckout {
*/
public static void checkoutEntry(Repository repo, DirCacheEntry entry,
ObjectReader or) throws IOException {
+ checkoutEntry(repo, entry, or, false);
+ }
+
+ /**
+ * Updates the file in the working tree with content and mode from an entry
+ * in the index. The new content is first written to a new temporary file in
+ * the same directory as the real file. Then that new file is renamed to the
+ * final filename.
+ *
+ * <p>
+ * <b>Note:</b> if the entry path on local file system exists as a file, it
+ * will be deleted and if it exists as a directory, it will be deleted
+ * recursively, independently if has any content.
+ * </p>
+ *
+ * <p>
+ * TODO: this method works directly on File IO, we may need another
+ * abstraction (like WorkingTreeIterator). This way we could tell e.g.
+ * Eclipse that Files in the workspace got changed
+ * </p>
+ *
+ * @param repo
+ * repository managing the destination work tree.
+ * @param entry
+ * the entry containing new mode and content
+ * @param or
+ * object reader to use for checkout
+ * @param deleteRecursive
+ * true to recursively delete final path if it exists on the file
+ * system
+ *
+ * @throws IOException
+ * @since 4.2
+ */
+ public static void checkoutEntry(Repository repo, DirCacheEntry entry,
+ ObjectReader or, boolean deleteRecursive) throws IOException {
ObjectLoader ol = or.open(entry.getObjectId());
File f = new File(repo.getWorkTree(), entry.getPathString());
File parentDir = f.getParentFile();
@@ -1153,6 +1196,9 @@ public class DirCacheCheckout {
&& opt.getSymLinks() == SymLinks.TRUE) {
byte[] bytes = ol.getBytes();
String target = RawParseUtils.decode(bytes);
+ if (deleteRecursive && f.isDirectory()) {
+ FileUtils.delete(f, FileUtils.RECURSIVE);
+ }
fs.createSymLink(f, target);
entry.setLength(bytes.length);
entry.setLastModified(fs.lastModified(f));
@@ -1183,11 +1229,18 @@ public class DirCacheCheckout {
}
}
try {
+ if (deleteRecursive && f.isDirectory()) {
+ FileUtils.delete(f, FileUtils.RECURSIVE);
+ }
FileUtils.rename(tmpFile, f);
} catch (IOException e) {
throw new IOException(MessageFormat.format(
JGitText.get().renameFileFailed, tmpFile.getPath(),
f.getPath()));
+ } finally {
+ if (tmpFile.exists()) {
+ FileUtils.delete(tmpFile);
+ }
}
entry.setLastModified(f.lastModified());
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index 548d239c8d..720fdedefb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -399,20 +399,25 @@ public class FileUtils {
*
* @param path
* @param target
+ * @return path to the created link
* @throws IOException
- * @since 3.0
+ * @since 4.2
*/
- public static void createSymLink(File path, String target)
+ public static Path createSymLink(File path, String target)
throws IOException {
Path nioPath = path.toPath();
if (Files.exists(nioPath, LinkOption.NOFOLLOW_LINKS)) {
- Files.delete(nioPath);
+ if (Files.isRegularFile(nioPath)) {
+ delete(path);
+ } else {
+ delete(path, EMPTY_DIRECTORIES_ONLY | RECURSIVE);
+ }
}
if (SystemReader.getInstance().isWindows()) {
target = target.replace('/', '\\');
}
Path nioTarget = new File(target).toPath();
- Files.createSymbolicLink(nioPath, nioTarget);
+ return Files.createSymbolicLink(nioPath, nioTarget);
}
/**