Checkout should be able to override modified symbolic links

Handle existing symlink as a file, not as directory if deleting a file
before creating (overriding) a symlink.

Bug: 484491
Change-Id: I29dbf57d1daec2ba98454975b093e1d381d05196
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
This commit is contained in:
Andrey Loskutov 2015-12-16 16:41:34 +01:00
parent 8cfbbc9f54
commit 1aafa61958
3 changed files with 86 additions and 9 deletions

View File

@ -43,10 +43,12 @@
package org.eclipse.jgit.api;
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 java.nio.file.Path;
import org.eclipse.jgit.api.CheckoutCommand.Stage;
import org.eclipse.jgit.api.errors.JGitInternalException;
@ -59,6 +61,9 @@
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@ -73,6 +78,8 @@ public class PathCheckoutCommandTest extends RepositoryTestCase {
private static final String FILE3 = "Test3.txt";
private static final String LINK = "link";
Git git;
RevCommit initialCommit;
@ -98,6 +105,64 @@ public void setUp() throws Exception {
git.commit().setMessage("Third commit").call();
}
@Test
public void testUpdateSymLink() throws Exception {
Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
Path path = writeLink(LINK, FILE1);
git.add().addFilepattern(LINK).call();
git.commit().setMessage("Added link").call();
assertEquals("3", read(path.toFile()));
writeLink(LINK, FILE2);
assertEquals("c", read(path.toFile()));
CheckoutCommand co = git.checkout();
co.addPath(LINK).call();
assertEquals("3", read(path.toFile()));
}
@Test
public void testUpdateBrokenSymLinkToDirectory() throws Exception {
Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
Path path = writeLink(LINK, "f");
git.add().addFilepattern(LINK).call();
git.commit().setMessage("Added link").call();
assertEquals("f", FileUtils.readSymLink(path.toFile()));
assertTrue(path.toFile().exists());
writeLink(LINK, "link_to_nowhere");
assertFalse(path.toFile().exists());
assertEquals("link_to_nowhere", FileUtils.readSymLink(path.toFile()));
CheckoutCommand co = git.checkout();
co.addPath(LINK).call();
assertEquals("f", FileUtils.readSymLink(path.toFile()));
}
@Test
public void testUpdateBrokenSymLink() throws Exception {
Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
Path path = writeLink(LINK, FILE1);
git.add().addFilepattern(LINK).call();
git.commit().setMessage("Added link").call();
assertEquals("3", read(path.toFile()));
assertEquals(FILE1, FileUtils.readSymLink(path.toFile()));
writeLink(LINK, "link_to_nowhere");
assertFalse(path.toFile().exists());
assertEquals("link_to_nowhere", FileUtils.readSymLink(path.toFile()));
CheckoutCommand co = git.checkout();
co.addPath(LINK).call();
assertEquals("3", read(path.toFile()));
}
@Test
public void testUpdateWorkingDirectory() throws Exception {
CheckoutCommand co = git.checkout();

View File

@ -54,6 +54,7 @@
import org.eclipse.jgit.junit.JGitTestUtil;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@ -424,18 +425,27 @@ public void testRenameOverExistingEmptyDirectory() throws IOException {
@Test
public void testCreateSymlink() throws IOException {
FS fs = FS.DETECTED;
try {
fs.createSymLink(new File(trash, "x"), "y");
} catch (IOException e) {
if (fs.supportsSymlinks())
fail("FS claims to support symlinks but attempt to create symlink failed");
return;
}
assertTrue(fs.supportsSymlinks());
// show test as ignored if the FS doesn't support symlinks
Assume.assumeTrue(fs.supportsSymlinks());
fs.createSymLink(new File(trash, "x"), "y");
String target = fs.readSymLink(new File(trash, "x"));
assertEquals("y", target);
}
@Test
public void testCreateSymlinkOverrideExisting() throws IOException {
FS fs = FS.DETECTED;
// show test as ignored if the FS doesn't support symlinks
Assume.assumeTrue(fs.supportsSymlinks());
File file = new File(trash, "x");
fs.createSymLink(file, "y");
String target = fs.readSymLink(file);
assertEquals("y", target);
fs.createSymLink(file, "z");
target = fs.readSymLink(file);
assertEquals("z", target);
}
@Test
public void testRelativize_doc() {
// This is the javadoc example

View File

@ -409,7 +409,9 @@ public static Path createSymLink(File path, String target)
throws IOException {
Path nioPath = path.toPath();
if (Files.exists(nioPath, LinkOption.NOFOLLOW_LINKS)) {
if (Files.isRegularFile(nioPath)) {
BasicFileAttributes attrs = Files.readAttributes(nioPath,
BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
if (attrs.isRegularFile() || attrs.isSymbolicLink()) {
delete(path);
} else {
delete(path, EMPTY_DIRECTORIES_ONLY | RECURSIVE);