diff options
12 files changed, 165 insertions, 20 deletions
diff --git a/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/symlinks/SymlinksTest.java b/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/symlinks/SymlinksTest.java index 366ab9e904..49627db352 100644 --- a/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/symlinks/SymlinksTest.java +++ b/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/symlinks/SymlinksTest.java @@ -260,4 +260,78 @@ public class SymlinksTest extends RepositoryTestCase { 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.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF index 1a812bf691..403c2f4638 100644 --- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF @@ -18,6 +18,7 @@ Import-Package: org.eclipse.jgit.api;version="[3.3.0,3.4.0)", org.eclipse.jgit.revwalk;version="[3.3.0,3.4.0)", org.eclipse.jgit.storage.file;version="[3.3.0,3.4.0)", org.eclipse.jgit.transport;version="[3.3.0,3.4.0)", + org.eclipse.jgit.treewalk;version="[3.3.0,3.4.0)", org.eclipse.jgit.util;version="[3.3.0,3.4.0)", org.eclipse.jgit.util.io;version="[3.3.0,3.4.0)", org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java index a6ea48c0ea..8012893f92 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java @@ -46,6 +46,10 @@ import java.io.File; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.treewalk.FileTreeIterator; +import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry; import org.eclipse.jgit.util.FileUtils; import org.junit.Assert; import org.junit.Test; @@ -133,6 +137,52 @@ public class CheckoutTest extends CLIRepositoryTestCase { Assert.assertEquals("\ta", execute[1]); } + /** + * Steps: + * <ol> + * <li>Add file 'a' and 'b' + * <li>Commit + * <li>Create branch '1' + * <li>modify file 'a' + * <li>Commit + * <li>Delete file 'a' in the working tree + * <li>Checkout branch '1' + * </ol> + * The working tree should contain 'a' with FileMode.REGULAR_FILE after the + * checkout. + * + * @throws Exception + */ + @Test + public void testCheckoutWithMissingWorkingTreeFile() throws Exception { + Git git = new Git(db); + File fileA = 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(); + writeTrashFile("a", "b"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("modify file a").call(); + + FileEntry entry = new FileTreeIterator.FileEntry(new File( + db.getWorkTree(), "a"), db.getFS()); + assertEquals(FileMode.REGULAR_FILE, entry.getMode()); + + FileUtils.delete(fileA); + + git.checkout().setName(branch_1.getName()).call(); + + entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"), + db.getFS()); + assertEquals(FileMode.REGULAR_FILE, entry.getMode()); + assertEquals("Hello world a", read(fileA)); + } + + static private void assertEquals(Object expected, Object actual) { + Assert.assertEquals(expected, actual); + } + static private void assertEquals(String expected, String[] actual) { // if there is more than one line, ignore last one if empty Assert.assertEquals( diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index ca32479adb..53c1b35207 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -293,6 +293,7 @@ usage_mergeRef=Ref to be merged usage_mergeStrategy=Use the given merge strategy. Can be supplied more than once to specify them in the order they should be tried. If there is no -s option, the recursive strategy is used. Currently the following strategies are supported: ours, theirs, simple-two-way-in-core, resolve, recursive usage_moveRenameABranch=move/rename a branch usage_nameStatus=show only name and status of files +usage_noCheckoutAfterClone=no checkout of HEAD is performed after the clone is complete usage_noCommit=Don't commit after a successful merge usage_noPrefix=do not show any source or destination prefix usage_noRenames=disable rename detection diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java index 888f54da2b..d9a877cd67 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java @@ -79,6 +79,9 @@ class Clone extends AbstractFetchCommand { @Option(name = "--branch", aliases = { "-b" }, metaVar = "metaVar_branchName", usage = "usage_checkoutBranchAfterClone") private String branch; + @Option(name = "--no-checkout", aliases = { "-n" }, usage = "usage_noCheckoutAfterClone") + private boolean noCheckout; + @Argument(index = 0, required = true, metaVar = "metaVar_uriish") private String sourceUri; @@ -122,16 +125,19 @@ class Clone extends AbstractFetchCommand { saveRemote(uri); final FetchResult r = runFetch(); - final Ref checkoutRef; - if (branch == null) - checkoutRef = guessHEAD(r); - else { - checkoutRef = r.getAdvertisedRef(Constants.R_HEADS + branch); - if (checkoutRef == null) - throw die(MessageFormat.format(CLIText.get().noSuchRemoteRef, - branch)); + + if (!noCheckout) { + final Ref checkoutRef; + if (branch == null) + checkoutRef = guessHEAD(r); + else { + checkoutRef = r.getAdvertisedRef(Constants.R_HEADS + branch); + if (checkoutRef == null) + throw die(MessageFormat.format( + CLIText.get().noSuchRemoteRef, branch)); + } + doCheckout(checkoutRef); } - doCheckout(checkoutRef); } private void saveRemote(final URIish uri) throws URISyntaxException, diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java index dc081439df..7f7ef8d4d1 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java @@ -103,6 +103,7 @@ public abstract class TextBuiltin { * * @deprecated Use outw instead */ + @Deprecated protected PrintWriter out; /** Git repository the command was invoked within. */ 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 79fe8d6f56..f8be5006e3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -909,9 +909,9 @@ public class DirCacheCheckout { // file content update(name, mId, mMode); } else if (dce != null - && (f == null || f.isModified(dce, true, + && (f != null && f.isModified(dce, true, this.walk.getObjectReader()))) { - // File doesn't exist or is dirty + // File exists and is dirty // Head and Index don't contain a submodule // Head contains the same as Index. Merge differs // Something in Merge @@ -919,7 +919,7 @@ public class DirCacheCheckout { // but the file is dirty. Report a conflict conflict(name, dce, h, m); } else { - // File exists and is clean + // File doesn't exist or is clean // Head and Index don't contain a submodule // Head contains the same as Index. Merge differs // Something in Merge diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java index aa48c60414..ce84659d66 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java @@ -635,6 +635,16 @@ public class DirCacheEntry { } /** + * Get a copy of the entry's raw path bytes. + * + * @return raw path bytes. + * @since 3.3 + */ + public byte[] getRawPath() { + return path.clone(); + } + + /** * Use for debugging only ! */ @SuppressWarnings("nls") diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java index 434eadf5fa..882f5c8a45 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java @@ -557,11 +557,11 @@ public class ObjectDirectory extends FileObjectDatabase { // If the object is already in the repository, remove temporary file. // if (unpackedObjectCache.isUnpacked(id)) { - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); return InsertLooseObjectResult.EXISTS_LOOSE; } if (!createDuplicate && has(id)) { - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); return InsertLooseObjectResult.EXISTS_PACKED; } @@ -571,7 +571,7 @@ public class ObjectDirectory extends FileObjectDatabase { // that already exists. We can't be sure renameTo() would // fail on all platforms if dst exists, so we check first. // - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); return InsertLooseObjectResult.EXISTS_LOOSE; } if (tmp.renameTo(dst)) { @@ -592,7 +592,7 @@ public class ObjectDirectory extends FileObjectDatabase { } if (!createDuplicate && has(id)) { - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); return InsertLooseObjectResult.EXISTS_PACKED; } @@ -601,7 +601,7 @@ public class ObjectDirectory extends FileObjectDatabase { // either. We really don't know what went wrong, so // fail. // - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); return InsertLooseObjectResult.FAILURE; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryInserter.java index c55c60a208..c3e6ad9630 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryInserter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryInserter.java @@ -182,7 +182,7 @@ class ObjectDirectoryInserter extends ObjectInserter { return tmp; } finally { if (delete) - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); } } @@ -211,7 +211,7 @@ class ObjectDirectoryInserter extends ObjectInserter { return tmp; } finally { if (delete) - FileUtils.delete(tmp); + FileUtils.delete(tmp, FileUtils.RETRY); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index 291803ee59..c350dddb25 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -384,7 +384,8 @@ public abstract class Repository { try { Object resolved = resolve(rw, revstr); if (resolved instanceof String) { - return getRef((String) resolved).getLeaf().getObjectId(); + final Ref ref = getRef((String)resolved); + return ref != null ? ref.getLeaf().getObjectId() : null; } else { return (ObjectId) resolved; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java index 633865ed4d..a50adf91f4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -810,6 +810,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { * @return true if content is most likely different. * @deprecated Use {@link #isModified(DirCacheEntry, boolean, ObjectReader)} */ + @Deprecated public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { try { return isModified(entry, forceContentCheck, null); |