/*******************************************************************************
* Copyright (c) 2011, 2014 Tasktop Technologies and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.egit.core.test.op;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.op.CreatePatchOperation;
import org.eclipse.egit.core.op.CreatePatchOperation.DiffHeaderFormat;
import org.eclipse.egit.core.test.GitTestCase;
import org.eclipse.egit.core.test.TestProject;
import org.eclipse.egit.core.test.TestRepository;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.util.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CreatePatchOperationTest extends GitTestCase {
private static final String SIMPLE_GIT_PATCH_CONTENT = "From ca644a113ac60405e54731330be7879f6a36199c Sat, 23 Jul 2011 20:33:24 -0330\n"
+ "From: J. Git <j.git@egit.org>\n"
+ "Date: Sat, 15 Aug 2009 20:12:58 -0330\n"
+ "Subject: [PATCH] 2nd commit\n"
+ "\n"
+ "diff --git a/test-file b/test-file\n"
+ "index e69de29..af28d38 100644\n"
+ "--- a/test-file\n"
+ "+++ b/test-file\n"
+ "@@ -0,0 +1 @@\n"
+ "+another line\n";
private static final String SIMPLE_ONELINE_PATCH_CONTENT = "ca644a113ac60405e54731330be7879f6a36199c 2nd commit\n"
+ "diff --git a/test-file b/test-file\n"
+ "index e69de29..af28d38 100644\n"
+ "--- a/test-file\n"
+ "+++ b/test-file\n"
+ "@@ -0,0 +1 @@\n"
+ "+another line\n";
private static final String SIMPLE_PATCH_CONTENT = "diff --git a/test-file b/test-file\n"
+ "index e69de29..af28d38 100644\n"
+ "--- a/test-file\n"
+ "+++ b/test-file\n"
+ "@@ -0,0 +1 @@\n"
+ "+another line\n";
private static final String SIMPLE_WORKSPACE_PATCH_CONTENT = "### Eclipse Workspace Patch 1.0\n"
+ "#P Project-1\n"
+ "diff --git deleted-file deleted-file\n"
+ "deleted file mode 100644\n"
+ "index e69de29..0000000\n"
+ "--- deleted-file\n"
+ "+++ /dev/null\n"
+ "diff --git new-file new-file\n"
+ "new file mode 100644\n"
+ "index 0000000..b66ba06\n"
+ "--- /dev/null\n"
+ "+++ new-file\n"
+ "@@ -0,0 +1 @@\n"
+ "+new content\n"
+ "diff --git test-file test-file\n"
+ "index e69de29..af28d38 100644\n"
+ "--- test-file\n"
+ "+++ test-file\n"
+ "@@ -0,0 +1 @@\n"
+ "+another line\n";
private RevCommit commit;
private File file;
private TestRepository testRepository;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
gitDir = new File(project.getProject().getLocationURI().getPath(),
Constants.DOT_GIT);
testRepository = new TestRepository(gitDir);
testRepository.connect(project.getProject());
file = testRepository.createFile(project.getProject(), "test-file");
commit = testRepository.addAndCommit(project.getProject(), file,
"new file");
}
@Override
@After
public void tearDown() throws Exception {
testRepository.dispose();
super.tearDown();
}
@Test
public void testSimpleGitPatch() throws Exception {
RevCommit secondCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line\n", "2nd commit");
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.execute(new NullProgressMonitor());
String patchContent = operation.getPatchContent();
assertNotNull(patchContent);
assertGitPatch(SIMPLE_GIT_PATCH_CONTENT, patchContent);
// repeat setting the header format explicitly
operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.setHeaderFormat(DiffHeaderFormat.EMAIL);
operation.execute(new NullProgressMonitor());
patchContent = operation.getPatchContent();
assertNotNull(patchContent);
assertGitPatch(SIMPLE_GIT_PATCH_CONTENT, patchContent);
}
@Test
public void testSimplePatch() throws Exception {
RevCommit secondCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line\n", "2nd commit");
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.setHeaderFormat(DiffHeaderFormat.NONE);
operation.execute(new NullProgressMonitor());
String patchContent = operation.getPatchContent();
assertNotNull(patchContent);
assertPatch(SIMPLE_PATCH_CONTENT, patchContent);
}
@Test
public void testSimplePatchNoNewlineAtEnd() throws Exception {
RevCommit secondCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line", "2nd commit");
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.setHeaderFormat(DiffHeaderFormat.NONE);
operation.execute(new NullProgressMonitor());
String patchContent = operation.getPatchContent();
assertNotNull(patchContent);
assertPatch(SIMPLE_PATCH_CONTENT.replace("af28d38", "eb5f2c9")
+ "\\ No newline at end of file\n",
patchContent);
}
@Test
public void testOnelineHeaderPatch() throws Exception {
RevCommit secondCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line\n", "2nd commit");
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.setHeaderFormat(DiffHeaderFormat.ONELINE);
operation.execute(new NullProgressMonitor());
String patchContent = operation.getPatchContent();
assertNotNull(patchContent);
assertPatch(SIMPLE_ONELINE_PATCH_CONTENT, patchContent);
}
@Test
public void testFirstCommit() throws Exception {
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), commit);
operation.setHeaderFormat(DiffHeaderFormat.ONELINE);
operation.execute(null);
String patchContent = operation.getPatchContent();
assertPatch("5d67e6eaa2464d15c4216a93a0e7180ec905a2bb new file\n"
+ "diff --git a/test-file b/test-file\n"
+ "new file mode 100644\nindex 0000000..e69de29\n"
+ "--- /dev/null\n" + "+++ b/test-file\n", patchContent);
}
@SuppressWarnings("unused")
@Test
public void testNullCommit() throws Exception {
new CreatePatchOperation(testRepository.getRepository(), null);
}
@SuppressWarnings("unused")
@Test(expected = IllegalArgumentException.class)
public void testNullRepo() throws Exception {
new CreatePatchOperation(null, commit);
}
@Test(expected = IllegalStateException.class)
public void testExecuteFirst() throws Exception {
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), commit);
operation.getPatchContent();
}
@Test
public void testNullMonitor() throws Exception {
RevCommit secondCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line\n", "2nd commit");
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), secondCommit);
operation.execute(null);
}
@Test
public void testSuggestName() throws Exception {
RevCommit aCommit = testRepository.appendContentAndCommit(
project.getProject(), file, "another line\n", "2nd commit");
assertEquals("2nd-commit.patch", CreatePatchOperation.suggestFileName(aCommit));
aCommit = testRepository.appendContentAndCommit(
project.getProject(),
file, "another line\n",
"[findBugs] Change visibility of repositoryFile to package");
assertEquals("findBugs-Change-visibility-of-repositoryFile-to-pack.patch", CreatePatchOperation.suggestFileName(aCommit));
aCommit = testRepository.appendContentAndCommit(
project.getProject(),
file, "another line\n",
"Add collapse/expand all utility method for tree viewers.");
assertEquals("Add-collapse-expand-all-utility-method-for-tree-view.patch", CreatePatchOperation.suggestFileName(aCommit));
}
@Test
public void testComputeWorkspacePath() throws Exception {
IPath oldPath = CreatePatchOperation.computeWorkspacePath(new Path(
"test-file"), project.getProject());
IPath newPath = CreatePatchOperation.computeWorkspacePath(new Path(
"test-file"), project.getProject());
assertPatch("test-file", oldPath.toString());
assertPatch("test-file", newPath.toString());
}
@Test
public void testComputeWorkspacePathRepoAboveProject() throws Exception {
testRepository.disconnect(project.getProject());
// new setup
project = new TestProject(true, "repo/bundles/Project-1", true, null);
File repo = new File(project.getProject().getLocationURI().getPath())
.getParentFile().getParentFile();
gitDir = new File(repo, Constants.DOT_GIT);
testRepository = new TestRepository(gitDir);
testRepository.connect(project.getProject());
IPath oldPath = CreatePatchOperation.computeWorkspacePath(new Path(
"bundles/Project-1/test-file"), project.getProject());
IPath newPath = CreatePatchOperation.computeWorkspacePath(new Path(
"bundles/Project-1/test-file"), project.getProject());
assertPatch("test-file", oldPath.toString());
assertPatch("test-file", newPath.toString());
}
@Test
public void testUpdateWorkspacePatchPrefixes() throws Exception {
// setup workspace
File newFile = testRepository.createFile(project.getProject(), "new-file");
testRepository.appendFileContent(newFile, "new content\n");
File deletedFile = testRepository.createFile(project.getProject(), "deleted-file");
commit = testRepository.addAndCommit(project.getProject(), deletedFile,
"whatever");
FileUtils.delete(deletedFile);
// unprocessed patch
DiffFormatter diffFmt = new DiffFormatter(null);
diffFmt.setRepository(testRepository.getRepository());
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/deleted-file b/deleted-file").append("\n");
sb.append("deleted file mode 100644").append("\n");
sb.append("index e69de29..0000000").append("\n");
sb.append("--- a/deleted-file").append("\n");
sb.append("+++ /dev/null").append("\n");
sb.append("diff --git a/new-file b/new-file").append("\n");
sb.append("new file mode 100644").append("\n");
sb.append("index 0000000..b66ba06").append("\n");
sb.append("--- /dev/null").append("\n");
sb.append("+++ b/new-file").append("\n");
sb.append("@@ -0,0 +1 @@").append("\n");
sb.append("+new content").append("\n");
sb.append(SIMPLE_PATCH_CONTENT);
// update patch
CreatePatchOperation op = new CreatePatchOperation(testRepository.getRepository(), null);
op.updateWorkspacePatchPrefixes(sb, diffFmt);
// add workspace header
StringBuilder sb1 = new StringBuilder("### Eclipse Workspace Patch 1.0\n#P ")
.append(project.getProject().getName()).append("\n").append(sb);
assertPatch(SIMPLE_WORKSPACE_PATCH_CONTENT, sb1.toString());
}
@Test
public void testWorkspacePatchForCommit() throws Exception {
// setup workspace
File deletedFile = testRepository.createFile(project.getProject(), "deleted-file");
commit = testRepository.addAndCommit(project.getProject(), deletedFile,
"whatever");
FileUtils.delete(deletedFile);
testRepository.appendFileContent(file, "another line\n");
File newFile = testRepository.createFile(project.getProject(), "new-file");
testRepository.appendFileContent(newFile, "new content\n");
testRepository.untrack(deletedFile);
testRepository.track(file);
testRepository.track(newFile);
commit = testRepository.commit("2nd commit");
// create patch
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), commit);
operation.setHeaderFormat(DiffHeaderFormat.WORKSPACE);
operation.execute(new NullProgressMonitor());
assertPatch(SIMPLE_WORKSPACE_PATCH_CONTENT, operation.getPatchContent());
}
@Test
public void testWorkspacePatchForWorkingDir() throws Exception {
// setup workspace
testRepository.addToIndex(project.getProject().findMember(".classpath"));
testRepository.addToIndex(project.getProject().findMember(".project"));
testRepository.commit("commit all");
testRepository.appendFileContent(file, "another line\n");
File newFile = testRepository.createFile(project.getProject(), "new-file");
testRepository.appendFileContent(newFile, "new content\n");
File deletedFile = testRepository.createFile(project.getProject(), "deleted-file");
commit = testRepository.addAndCommit(project.getProject(), deletedFile,
"whatever");
FileUtils.delete(deletedFile);
// create patch
CreatePatchOperation operation = new CreatePatchOperation(
testRepository.getRepository(), null);
operation.setHeaderFormat(DiffHeaderFormat.WORKSPACE);
operation.execute(new NullProgressMonitor());
assertPatch(SIMPLE_WORKSPACE_PATCH_CONTENT, operation.getPatchContent());
}
private void assertGitPatch(String expected, String actual) {
assertEquals(expected.substring(0,45), actual.substring(0,45));
assertEquals(expected.substring(expected.indexOf("\n")), actual.substring(actual.indexOf("\n")));
}
private void assertPatch(String expected, String actual) {
assertEquals(expected, actual);
}
}