# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /data/work/src/netbeans-cdev/diff # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: apichanges.xml --- apichanges.xml Base (BASE) +++ apichanges.xml Locally Modified (Based On LOCAL) @@ -184,6 +184,18 @@ + + + New DiffController API + + + + + + Adding PatchUtils.java to the API. Contains two new methods - isPatch(patchFile) and applyPatch(patchFile, contextFile) + + + Index: nbproject/project.xml --- nbproject/project.xml Base (BASE) +++ nbproject/project.xml Locally Modified (Based On LOCAL) @@ -263,6 +263,10 @@ + + org.netbeans.modules.masterfs + + qa-functional Index: src/org/netbeans/api/diff/PatchUtils.java --- src/org/netbeans/api/diff/PatchUtils.java Base (BASE) +++ src/org/netbeans/api/diff/PatchUtils.java Locally New @@ -0,0 +1,58 @@ + +package org.netbeans.api.diff; + +import org.netbeans.modules.diff.builtin.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import org.netbeans.modules.diff.builtin.ContextualPatch; +import org.netbeans.modules.diff.builtin.Patch; + +/** + * Utility class for patch application. + * + * @author Tomas Stupka + * @since 1.19 + */ +public class PatchUtils { + + /** + * Applies the patch file on the context file or folder. The patch file may be + * in a context, normal or unified format. + * + * @param patch the patch file + * @param context the file or folder to be updated with the patch + * @throws PatchException + * @throws IOException - the patch is invalid or cannot be applied + * @since 1.19 + */ + public static void applyPatch(File patch, File context) throws IOException { + ContextualPatch cp = ContextualPatch.create(patch, context); + cp.patch(false); // false - dry run + } + + /** + * Returns true only if the given file is a patch + * in a format recognizable as a + *
    + *
  • context
  • + *
  • normal
  • + *
  • unified
  • + *
+ * @param file patch file + * @return true if the given input stream is a patch otherwise false + * @throws IOException + * @since 1.19 + */ + public static boolean isPatch(File patch) throws IOException { + Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(patch))); + try { + return (Patch.parse(reader).length > 0); + } finally { + reader.close(); + } + } +} Index: src/org/netbeans/modules/diff/builtin/PatchException.java --- src/org/netbeans/modules/diff/builtin/PatchException.java Base (BASE) +++ src/org/netbeans/modules/diff/builtin/PatchException.java Locally Modified (Based On LOCAL) @@ -40,12 +40,14 @@ */ package org.netbeans.modules.diff.builtin; +import java.io.IOException; + /** * The patch is invalid or cannot be applied on the specified file. * * @author Maros Sandor */ -public final class PatchException extends Exception { +public final class PatchException extends IOException { public PatchException(String msg) { super(msg); Index: test/unit/data/patch/contextPatchFile --- test/unit/data/patch/contextPatchFile Base (BASE) +++ test/unit/data/patch/contextPatchFile Locally New @@ -0,0 +1,20 @@ +diff -c file1 file2 +*** file1 Tue Jul 7 16:48:22 2009 +--- file1 Tue Jul 7 16:49:01 2009 +*************** +*** 1,7 **** + one + two + three +! for + five + six + seven +--- 1,7 ---- + one + two + three +! four + five + six + seven \ No newline at end of file Index: test/unit/data/patch/contextPatchNoTimestamp --- test/unit/data/patch/contextPatchNoTimestamp Base (BASE) +++ test/unit/data/patch/contextPatchNoTimestamp Locally New @@ -0,0 +1,19 @@ +*** goldenFile1 +--- goldenFile2 +*************** +*** 1,7 **** + one + two + three +! for + five + six + seven +--- 1,7 ---- + one + two + three +! four + five + six + seven \ No newline at end of file Index: test/unit/data/patch/emptyFile --- test/unit/data/patch/emptyFile Base (BASE) +++ test/unit/data/patch/emptyFile Locally New Index: test/unit/data/patch/goldenFileAfter --- test/unit/data/patch/goldenFileAfter Base (BASE) +++ test/unit/data/patch/goldenFileAfter Locally New @@ -0,0 +1,7 @@ +one +two +three +four +five +six +seven Index: test/unit/data/patch/goldenFileBefore --- test/unit/data/patch/goldenFileBefore Base (BASE) +++ test/unit/data/patch/goldenFileBefore Locally New @@ -0,0 +1,7 @@ +one +two +three +for +five +six +seven Index: test/unit/data/patch/normalPatchFile --- test/unit/data/patch/normalPatchFile Base (BASE) +++ test/unit/data/patch/normalPatchFile Locally New @@ -0,0 +1,5 @@ +diff --normal file1 file2 +4c4 +< for +--- +> four \ No newline at end of file Index: test/unit/data/patch/plainTextFile --- test/unit/data/patch/plainTextFile Base (BASE) +++ test/unit/data/patch/plainTextFile Locally New @@ -0,0 +1,3 @@ +raz +dva +tri \ No newline at end of file Index: test/unit/data/patch/unifiedPatchFile --- test/unit/data/patch/unifiedPatchFile Base (BASE) +++ test/unit/data/patch/unifiedPatchFile Locally New @@ -0,0 +1,12 @@ +diff -u file1 file2 +--- file1 2009-07-07 16:48:22.000000000 +0200 ++++ file1 2009-07-07 16:49:01.000000000 +0200 +@@ -1,7 +1,7 @@ + one + two + three +-for ++four + five + six + seven \ No newline at end of file Index: test/unit/data/patch/unifiedPatchNoTimestamp --- test/unit/data/patch/unifiedPatchNoTimestamp Base (BASE) +++ test/unit/data/patch/unifiedPatchNoTimestamp Locally New @@ -0,0 +1,11 @@ +--- goldenFile1 ++++ goldenFile2 +@@ -1,7 +1,7 @@ + one + two + three +-for ++four + five + six + seven \ No newline at end of file Index: test/unit/src/org/netbeans/api/diff/PatchUtilsTest.java --- test/unit/src/org/netbeans/api/diff/PatchUtilsTest.java Base (BASE) +++ test/unit/src/org/netbeans/api/diff/PatchUtilsTest.java Locally New @@ -0,0 +1,164 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.api.diff; + + +import java.io.*; + +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.FileUtil; + +/** + * + * + * @author Tomas Stupka + */ +public class PatchUtilsTest extends NbTestCase { + private File dataDir; + + public PatchUtilsTest(String testName) { + super(testName); + } + + @Override + protected void setUp() throws Exception { + dataDir = new File(getDataDir(), "patch"); + } + + public void testIsPatchNoFile() { + try { + assertFalse(PatchUtils.isPatch(new File(getWorkDir(), "nofile"))); + } catch (IOException ex) { + return; + } + fail("Exception should be thrown"); + } + + public void testIsNoPatch() throws IOException { + assertFalse(PatchUtils.isPatch(new File(dataDir, "emptyFile"))); + assertFalse(PatchUtils.isPatch(new File(dataDir, "plainTextFile"))); + } + + public void testIsPatchContext() throws IOException { + assertTrue(PatchUtils.isPatch(new File(dataDir, "contextPatchFile"))); + assertTrue(PatchUtils.isPatch(new File(dataDir, "contextPatchNoTimestamp"))); + } + + public void testIsPatchNormal() throws IOException { + assertTrue(PatchUtils.isPatch(new File(dataDir, "normalPatchFile"))); + } + + public void testIsPatchUnified() throws IOException { + assertTrue(PatchUtils.isPatch(new File(dataDir, "unifiedPatchFile"))); + assertTrue(PatchUtils.isPatch(new File(dataDir, "unifiedPatchNoTimestamp"))); + } + + public void testFileApplyPatchNormal() throws IOException { + File normalPatch = new File(dataDir, "normalPatchFile"); + File file = createFile(); + + PatchUtils.applyPatch(normalPatch, file); + assertFiles(new File(dataDir, "goldenFileAfter"), file, true); + } + + public void testFileApplyPatchContext() throws IOException { + File normalPatch = new File(dataDir, "contextPatchFile"); + File file = createFile(); + + PatchUtils.applyPatch(normalPatch, file); + assertFiles(new File(dataDir, "goldenFileAfter"), file, true); + } + + public void testFileApplyPatchUnified() throws IOException { + File normalPatch = new File(dataDir, "unifiedPatchFile"); + File file = createFile(); + + PatchUtils.applyPatch(normalPatch, file); + assertFiles(new File(dataDir, "goldenFileAfter"), file, true); + } + + private void assertFiles(File golden, File file, boolean equal) throws FileNotFoundException, IOException { + if(equal) { + assertEquals(golden.length(), file.length()); + } else { + if(golden.length() != file.length()) { + return; + } + } + + BufferedReader goldenReader = new BufferedReader(new FileReader(golden)); + BufferedReader fileReader = new BufferedReader(new FileReader(file)); + + String gl, fl; + boolean diff = false; + while( (gl = goldenReader.readLine()) != null ) { + fl = fileReader.readLine(); + if(equal) assertEquals(gl, fl); + if(!equal) { + diff = !gl.equals(fl); + if(diff) { + break; + } + } + } + if(!equal && !diff) fail("files are the same"); + if(equal) { + assertNull(fileReader.readLine()); + } + } + + private File createFile() throws IOException { + return createFile(new File(getWorkDir(), "file")); + } + + private File createFile(File file) throws IOException { + final FileInputStream fileInputStream = new FileInputStream(new File(dataDir, "goldenFileBefore")); + final FileOutputStream fileOutputStream = new FileOutputStream(file); + try { + FileUtil.copy(fileInputStream, fileOutputStream); + } finally { + fileInputStream.close(); + fileOutputStream.close(); + } + return file; + } + +}