aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Zarna2012-03-05 00:14:23 (EST)
committerChris Aniszczyk2012-03-05 00:29:01 (EST)
commit92f90eb2298100c593fe233195ccf2de5bdf47cf (patch)
tree275697fcdb1b9920a0c763f3b90c6fad365b3aaa
parent8e1bc46061930c8c89faa0444d531958ac0e8d8d (diff)
downloadjgit-92f90eb2298100c593fe233195ccf2de5bdf47cf.zip
jgit-92f90eb2298100c593fe233195ccf2de5bdf47cf.tar.gz
jgit-92f90eb2298100c593fe233195ccf2de5bdf47cf.tar.bz2
Add ApplyCommand to JGit APIrefs/changes/17/4717/8
Bug: 361548 CQ: 6243 Change-Id: I08e1369e142bb19f42a8d7bbb5a7d062cc8533fc Signed-off-by: Chris Aniszczyk <zx@twitter.com>
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1.patch9
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1_PostImage3
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2.patch10
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2_PostImage3
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D.patch9
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D_PreImage3
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1.patch4
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1_PreImage25
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2.patch8
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2_PreImage25
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java191
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java258
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyResult.java73
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchApplyException.java69
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchFormatException.java77
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java20
19 files changed, 807 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1.patch
new file mode 100644
index 0000000..7ddab88
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1.patch
@@ -0,0 +1,9 @@
+diff --git a/A1 b/A1
+new file mode 100644
+index 0000000..de98044
+--- /dev/null
++++ b/A1
+@@ -0,0 +1,3 @@
++a
++b
++c \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1_PostImage
new file mode 100644
index 0000000..de98044
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A1_PostImage
@@ -0,0 +1,3 @@
+a
+b
+c
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2.patch
new file mode 100644
index 0000000..83869ce
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2.patch
@@ -0,0 +1,10 @@
+diff --git a/A2 b/A2
+new file mode 100644
+index 0000000..de98044
+--- /dev/null
++++ b/A2
+@@ -0,0 +1,3 @@
++a
++b
++c
+\ No newline at end of file \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2_PostImage
new file mode 100644
index 0000000..1c943a9
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A2_PostImage
@@ -0,0 +1,3 @@
+a
+b
+c \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D.patch
new file mode 100644
index 0000000..f7db127
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D.patch
@@ -0,0 +1,9 @@
+diff --git a/D b/D
+deleted file mode 100644
+index a3648a1..0000000
+--- a/D
++++ /dev/null
+@@ -1,3 +0,0 @@
+-a
+-b
+-c
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D_PreImage
new file mode 100644
index 0000000..de98044
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/D_PreImage
@@ -0,0 +1,3 @@
+a
+b
+c
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1.patch
new file mode 100644
index 0000000..526d381
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1.patch
@@ -0,0 +1,4 @@
+@@ -2,2 +2,3 @@ a
+ b
++c
+ d
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1_PreImage
new file mode 100644
index 0000000..a3648a1
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F1_PreImage
@@ -0,0 +1,25 @@
+a
+b
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2.patch
new file mode 100644
index 0000000..9930e5d
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2.patch
@@ -0,0 +1,8 @@
+diff --git a/F2 b/F2
+index a3648a1..2d44096 100644
+--- a/F2
++++ b/F2
+@@ -2,2 +2,3 @@ a
+ B
++c
+ d
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2_PreImage
new file mode 100644
index 0000000..a3648a1
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/F2_PreImage
@@ -0,0 +1,25 @@
+a
+b
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
new file mode 100644
index 0000000..dceb0ec
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011, 2012, Tomasz Zarna <Tomasz.Zarna@pl.ibm.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.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jgit.api.errors.PatchApplyException;
+import org.eclipse.jgit.api.errors.PatchFormatException;
+import org.eclipse.jgit.diff.DiffFormatterReflowTest;
+import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.junit.Test;
+
+public class ApplyCommandTest extends RepositoryTestCase {
+
+ private RawText a;
+
+ private RawText b;
+
+ private ApplyResult init(final String name) throws Exception {
+ return init(name, true, true);
+ }
+
+ private ApplyResult init(final String name, final boolean preExists,
+ final boolean postExists) throws Exception {
+ Git git = new Git(db);
+
+ if (preExists) {
+ a = new RawText(readFile(name + "_PreImage"));
+ write(new File(db.getDirectory().getParent(), name),
+ a.getString(0, a.size(), false));
+
+ git.add().addFilepattern(name).call();
+ git.commit().setMessage("PreImage").call();
+ }
+
+ if (postExists)
+ b = new RawText(readFile(name + "_PostImage"));
+
+ return git
+ .apply()
+ .setPatch(
+ DiffFormatterReflowTest.class.getResourceAsStream(name
+ + ".patch")).call();
+ }
+
+ @Test
+ public void testAddA1() throws Exception {
+ ApplyResult result = init("A1", false, true);
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "A1"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "A1"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
+ public void testAddA2() throws Exception {
+ ApplyResult result = init("A2", false, true);
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "A2"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "A2"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
+ public void testDeleteD() throws Exception {
+ ApplyResult result = init("D", true, false);
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "D"), result.getUpdatedFiles()
+ .get(0));
+ assertFalse(new File(db.getWorkTree(), "D").exists());
+ }
+
+ @Test(expected = PatchFormatException.class)
+ public void testFailureF1() throws Exception {
+ init("F1", true, false);
+ }
+
+ @Test(expected = PatchApplyException.class)
+ public void testFailureF2() throws Exception {
+ init("F2", true, false);
+ }
+
+ @Test
+ public void testModifyE() throws Exception {
+ ApplyResult result = init("E");
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "E"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "E"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
+ public void testModifyX() throws Exception {
+ ApplyResult result = init("X");
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "X"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "X"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
+ public void testModifyY() throws Exception {
+ ApplyResult result = init("Y");
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "Y"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "Y"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
+ public void testModifyZ() throws Exception {
+ ApplyResult result = init("Z");
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "Z"), result.getUpdatedFiles()
+ .get(0));
+ checkFile(new File(db.getWorkTree(), "Z"),
+ b.getString(0, b.size(), false));
+ }
+
+ private byte[] readFile(final String patchFile) throws IOException {
+ final InputStream in = DiffFormatterReflowTest.class
+ .getResourceAsStream(patchFile);
+ if (in == null) {
+ fail("No " + patchFile + " test vector");
+ return null; // Never happens
+ }
+ try {
+ final byte[] buf = new byte[1024];
+ final ByteArrayOutputStream temp = new ByteArrayOutputStream();
+ int n;
+ while ((n = in.read(buf)) > 0)
+ temp.write(buf, 0, n);
+ return temp.toByteArray();
+ } finally {
+ in.close();
+ }
+ }
+}
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index 3e9d738..2f07c97 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -347,6 +347,8 @@ packingCancelledDuringObjectsWriting=Packing cancelled during objects writing
packObjectCountMismatch=Pack object count mismatch: pack {0} index {1}: {2}
packTooLargeForIndexVersion1=Pack too large for index version 1
packWriterStatistics=Total {0,number,#0} (delta {1,number,#0}), reused {2,number,#0} (delta {3,number,#0})
+patchApplyException=Cannot apply: {0}
+patchFormatException=Format error: {0}
pathIsNotInWorkingDir=Path is not in working dir
pathNotConfigured=Submodule path is not configured
peeledLineBeforeRef=Peeled line before ref.
@@ -378,6 +380,7 @@ remoteNameCantBeNull=Remote name can't be null.
renameBranchFailedBecauseTag=Can not rename as Ref {0} is a tag
renameBranchFailedUnknownReason=Rename failed with unknown reason
renameBranchUnexpectedResult=Unexpected rename result {0}
+renameFileFailed=Could not rename file {0} to {1}
renamesAlreadyFound=Renames have already been found.
renamesBreakingModifies=Breaking apart modified file pairs
renamesFindingByContent=Finding renames by content similarity
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index a75bf1f..068e944 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -407,6 +407,8 @@ public class JGitText extends TranslationBundle {
/***/ public String packObjectCountMismatch;
/***/ public String packTooLargeForIndexVersion1;
/***/ public String packWriterStatistics;
+ /***/ public String patchApplyException;
+ /***/ public String patchFormatException;
/***/ public String pathIsNotInWorkingDir;
/***/ public String pathNotConfigured;
/***/ public String peeledLineBeforeRef;
@@ -438,6 +440,7 @@ public class JGitText extends TranslationBundle {
/***/ public String renameBranchFailedBecauseTag;
/***/ public String renameBranchFailedUnknownReason;
/***/ public String renameBranchUnexpectedResult;
+ /***/ public String renameFileFailed;
/***/ public String renamesAlreadyFound;
/***/ public String renamesBreakingModifies;
/***/ public String renamesFindingByContent;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
new file mode 100644
index 0000000..bd489a9
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2011, 2012, IBM Corporation and others.
+ * 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.api;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.PatchApplyException;
+import org.eclipse.jgit.api.errors.PatchFormatException;
+import org.eclipse.jgit.diff.DiffEntry.ChangeType;
+import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.patch.FileHeader;
+import org.eclipse.jgit.patch.HunkHeader;
+import org.eclipse.jgit.patch.Patch;
+import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.IO;
+
+/**
+ * Apply a patch to files and/or to the index.
+ *
+ * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-apply.html"
+ * >Git documentation about apply</a>
+ */
+public class ApplyCommand extends GitCommand<ApplyResult> {
+
+ private InputStream in;
+
+ /**
+ * Constructs the command if the patch is to be applied to the index.
+ *
+ * @param repo
+ */
+ ApplyCommand(Repository repo) {
+ super(repo);
+ }
+
+ /**
+ * @param in
+ * the patch to apply
+ * @return this instance
+ */
+ public ApplyCommand setPatch(InputStream in) {
+ checkCallable();
+ this.in = in;
+ return this;
+ }
+
+ /**
+ * Executes the {@code ApplyCommand} command with all the options and
+ * parameters collected by the setter methods (e.g.
+ * {@link #setPatch(InputStream)} of this class. Each instance of this class
+ * should only be used for one invocation of the command. Don't call this
+ * method twice on an instance.
+ *
+ * @return an {@link ApplyResult} object representing the command result
+ */
+ public ApplyResult call() throws GitAPIException {
+ checkCallable();
+ ApplyResult r = new ApplyResult();
+ try {
+ final Patch p = new Patch();
+ try {
+ p.parse(in);
+ } finally {
+ in.close();
+ }
+ if (!p.getErrors().isEmpty())
+ throw new PatchFormatException(p.getErrors());
+ for (FileHeader fh : p.getFiles()) {
+ ChangeType type = fh.getChangeType();
+ File f = null;
+ switch (type) {
+ case ADD:
+ f = getFile(fh.getNewPath(), true);
+ apply(f, fh);
+ break;
+ case MODIFY:
+ f = getFile(fh.getOldPath(), false);
+ apply(f, fh);
+ break;
+ case DELETE:
+ f = getFile(fh.getOldPath(), false);
+ if (!f.delete())
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().cannotDeleteFile, f));
+ break;
+ case RENAME:
+ f = getFile(fh.getOldPath(), false);
+ File dest = getFile(fh.getNewPath(), false);
+ if (!f.renameTo(dest))
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().renameFileFailed, f, dest));
+ break;
+ case COPY:
+ f = getFile(fh.getOldPath(), false);
+ byte[] bs = IO.readFully(f);
+ FileWriter fw = new FileWriter(getFile(fh.getNewPath(),
+ true));
+ fw.write(new String(bs));
+ fw.close();
+ }
+ r.addUpdatedFile(f);
+ }
+ } catch (IOException e) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().patchApplyException, e.getMessage()), e);
+ }
+ setCallable(false);
+ return r;
+ }
+
+ private File getFile(String path, boolean create)
+ throws PatchApplyException {
+ File f = new File(getRepository().getWorkTree(), path);
+ if (create)
+ try {
+ FileUtils.createNewFile(f);
+ } catch (IOException e) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().createNewFileFailed, f), e);
+ }
+ return f;
+ }
+
+ /**
+ * @param f
+ * @param fh
+ * @throws IOException
+ * @throws PatchApplyException
+ */
+ private void apply(File f, FileHeader fh)
+ throws IOException, PatchApplyException {
+ RawText rt = new RawText(f);
+ List<String> oldLines = new ArrayList<String>(rt.size());
+ for (int i = 0; i < rt.size(); i++)
+ oldLines.add(rt.getString(i));
+ List<String> newLines = new ArrayList<String>(oldLines);
+ for (HunkHeader hh : fh.getHunks()) {
+ StringBuilder hunk = new StringBuilder();
+ for (int j = hh.getStartOffset(); j < hh.getEndOffset(); j++)
+ hunk.append((char) hh.getBuffer()[j]);
+ RawText hrt = new RawText(hunk.toString().getBytes());
+ List<String> hunkLines = new ArrayList<String>(hrt.size());
+ for (int i = 0; i < hrt.size(); i++)
+ hunkLines.add(hrt.getString(i));
+ int pos = 0;
+ for (int j = 1; j < hunkLines.size(); j++) {
+ String hunkLine = hunkLines.get(j);
+ switch (hunkLine.charAt(0)) {
+ case ' ':
+ if (!newLines.get(hh.getNewStartLine() - 1 + pos).equals(
+ hunkLine.substring(1))) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().patchApplyException, hh));
+ }
+ pos++;
+ break;
+ case '-':
+ if (!newLines.get(hh.getNewStartLine() - 1 + pos).equals(
+ hunkLine.substring(1))) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().patchApplyException, hh));
+ }
+ newLines.remove(hh.getNewStartLine() - 1 + pos);
+ break;
+ case '+':
+ newLines.add(hh.getNewStartLine() - 1 + pos,
+ hunkLine.substring(1));
+ pos++;
+ break;
+ }
+ }
+ }
+ if (!isNoNewlineAtEndOfFile(fh))
+ newLines.add("");
+ if (!rt.isMissingNewlineAtEnd())
+ oldLines.add("");
+ if (!isChanged(oldLines, newLines))
+ return; // don't touch the file
+ StringBuilder sb = new StringBuilder();
+ final String eol = rt.size() == 0
+ || (rt.size() == 1 && rt.isMissingNewlineAtEnd()) ? "\n" : rt
+ .getEOL();
+ for (String l : newLines) {
+ sb.append(l);
+ if (eol != null)
+ sb.append(eol);
+ }
+ sb.deleteCharAt(sb.length() - 1);
+ FileWriter fw = new FileWriter(f);
+ fw.write(sb.toString());
+ fw.close();
+ }
+
+ private boolean isChanged(List<String> ol, List<String> nl) {
+ if (ol.size() != nl.size())
+ return true;
+ for (int i = 0; i < ol.size(); i++)
+ if (!ol.get(i).equals(nl.get(i)))
+ return true;
+ return false;
+ }
+
+ private boolean isNoNewlineAtEndOfFile(FileHeader fh) {
+ HunkHeader lastHunk = fh.getHunks().get(fh.getHunks().size() - 1);
+ RawText lhrt = new RawText(lastHunk.getBuffer());
+ return lhrt.getString(lhrt.size() - 1).equals(
+ "\\ No newline at end of file"); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyResult.java
new file mode 100644
index 0000000..0c38f1b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyResult.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011, 2012 IBM Corporation and others.
+ * 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.api;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Encapsulates the result of a {@link ApplyCommand}
+ */
+public class ApplyResult {
+
+ private List<File> updatedFiles = new ArrayList<File>();
+
+ /**
+ * @param f
+ * an updated file
+ * @return this instance
+ */
+ public ApplyResult addUpdatedFile(File f) {
+ updatedFiles.add(f);
+ return this;
+
+ }
+
+ /**
+ * @return updated files
+ */
+ public List<File> getUpdatedFiles() {
+ return updatedFiles;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
index 597ce99..6c44d95 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
@@ -591,6 +591,20 @@ public class Git {
}
/**
+ * Returns a command object to execute a {@code apply} command
+ *
+ * @see <a
+ * href="http://www.kernel.org/pub/software/scm/git/docs/git-apply.html"
+ * >Git documentation about apply</a>
+ *
+ * @return a {@link ApplyCommand} used to collect all optional parameters
+ * and to finally execute the {@code apply} command
+ */
+ public ApplyCommand apply() {
+ return new ApplyCommand(repo);
+ }
+
+ /**
* @return the git repository this class is interacting with
*/
public Repository getRepository() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchApplyException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchApplyException.java
new file mode 100644
index 0000000..389c776
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchApplyException.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012, IBM Corporation and others.
+ * 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.api.errors;
+
+/**
+ * Exception thrown when applying a patch fails
+ *
+ * @since 2.0
+ *
+ */
+public class PatchApplyException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public PatchApplyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @param message
+ */
+ public PatchApplyException(String message) {
+ super(message);
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchFormatException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchFormatException.java
new file mode 100644
index 0000000..9aecaea
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/PatchFormatException.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012, IBM Corporation and others.
+ * 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.api.errors;
+
+import java.text.MessageFormat;
+import java.util.List;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.patch.FormatError;
+
+/**
+ * Exception thrown when applying a patch fails due to an invalid format
+ *
+ * @since 2.0
+ *
+ */
+public class PatchFormatException extends GitAPIException {
+ private static final long serialVersionUID = 1L;
+
+ private List<FormatError> errors;
+
+ /**
+ * @param errors
+ */
+ public PatchFormatException(List<FormatError> errors) {
+ super(MessageFormat.format(JGitText.get().patchFormatException, errors));
+ this.errors = errors;
+ }
+
+ /**
+ * @return all the errors where unresolved conflicts have been detected
+ */
+ public List<FormatError> getErrors() {
+ return errors;
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java
index fa9ca84..ddb00d1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java
@@ -280,6 +280,7 @@ public class RawText extends Sequence {
/**
* Get the line delimiter for the first line.
*
+ * @since 2.0
* @return the line delimiter or <code>null</code>
*/
public String getLineDelimiter() {
@@ -293,4 +294,23 @@ public class RawText extends Sequence {
else
return "\n";
}
+
+ /**
+ * Get the EOL chars for the first line.
+ *
+ * @since 2.0
+ * @return the EOL chars or <code>null</code>
+ */
+ public String getEOL() {
+ int e = getEnd(0);
+ if (content.length > 1 && content[e - 2] == '\r'
+ && content[e - 1] == '\n')
+ return "\r\n";
+ if (content.length > 0 && content[e - 1] == '\n')
+ return "\n";
+ if (content.length > 0 && content[e - 1] == '\r')
+ return "\r";
+ return null;
+ }
+
}