aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Zarna2012-03-15 20:38:34 (EDT)
committerMatthias Sohn2012-03-22 19:21:11 (EDT)
commit624ec10bd93e6ec14dc2cbdc59c6843bd4fec940 (patch)
tree86fca40a7809a63d82c93f846e66ffb6954343fc
parentc527dbc3d59b8311666b2f8efb3eb590158de61a (diff)
downloadegit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.zip
egit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.tar.gz
egit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.tar.bz2
Add support for "workspace patches"refs/changes/46/5046/7
Workspace-aware patches include comments to tell the Apply Patch wizard about the target projects for individual diffs. They contain enough information to allow the wizard to decide which resources need to be patched. Bug: 367735 CQ: 6349 Change-Id: Ie9036845e7bce43a2fe227294e99222e59a26f9f Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java15
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/CreatePatchOperationTest.java147
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java6
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties2
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/CreatePatchOperation.java155
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CommitDialogTester.java8
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CreatePatchWizard.java8
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java15
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/TestUtil.java29
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/CreatePatchActionTest.java71
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/LocationPage.java5
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/OptionsPage.java30
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/patch/PatchOperationUI.java4
15 files changed, 456 insertions, 44 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java
index a7b6f96..b40bd67 100644
--- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestRepository.java
@@ -244,6 +244,21 @@ public class TestRepository {
throw new IOException(e.getMessage());
}
}
+ /**
+ * Removes file from version control
+ *
+ * @param file
+ * @throws IOException
+ */
+ public void untrack(File file) throws IOException {
+ String repoPath = getRepoRelativePath(new Path(file.getPath())
+ .toString());
+ try {
+ new Git(repository).rm().addFilepattern(repoPath).call();
+ } catch (NoFilepatternException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
/**
* Creates a new branch and immediately checkout it.
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/CreatePatchOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/CreatePatchOperationTest.java
index b692f9d..05dfab2 100644
--- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/CreatePatchOperationTest.java
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/op/CreatePatchOperationTest.java
@@ -16,13 +16,19 @@ import static org.junit.Assert.assertNotNull;
import java.io.File;
+import org.eclipse.core.resources.IFile;
+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;
@@ -59,6 +65,29 @@ public class CreatePatchOperationTest extends GitTestCase {
+ "+another line\n"
+ "\\ No newline at end of file";
+ 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..47d2739\n"
+ + "--- /dev/null\n"
+ + "+++ new-file\n"
+ + "@@ -0,0 +1 @@\n"
+ + "+new content\n"
+ + "\\ No newline at end of file\n"
+ + "diff --git test-file test-file\n"
+ + "index e69de29..eb5f2c9 100644\n"
+ + "--- test-file\n"
+ + "+++ test-file\n"
+ + "@@ -0,0 +1 @@\n"
+ + "+another line\n"
+ + "\\ No newline at end of file";
+
private RevCommit commit;
private File file;
@@ -192,6 +221,124 @@ public class CreatePatchOperationTest extends GitTestCase {
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");
+ 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..47d2739").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("\\ No newline at end of file").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");
+ File newFile = testRepository.createFile(project.getProject(), "new-file");
+ testRepository.appendFileContent(newFile, "new content");
+ 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((IFile) project.getProject().findMember(".classpath"));
+ testRepository.addToIndex((IFile) project.getProject().findMember(".project"));
+ testRepository.commit("commit all");
+ testRepository.appendFileContent(file, "another line");
+ File newFile = testRepository.createFile(project.getProject(), "new-file");
+ testRepository.appendFileContent(newFile, "new content");
+ 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")));
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
index d00a1f3..6cfa2e1 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
@@ -90,6 +90,9 @@ public class CoreText extends NLS {
public static String DiffHeaderFormat_Oneline;
/** */
+ public static String DiffHeaderFormat_Workspace;
+
+ /** */
public static String DiscardChangesOperation_discardFailed;
/** */
@@ -237,6 +240,9 @@ public class CoreText extends NLS {
public static String CreatePatchOperation_cannotCreatePatchForFirstCommit;
/** */
+ public static String CreatePatchOperation_couldNotFindProject;
+
+ /** */
public static String CreatePatchOperation_patchFileCouldNotBeWritten;
/** */
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
index a695a41..06da6b8 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
@@ -22,6 +22,7 @@ DeleteTagOperation_exceptionMessage=Exception deleting tag ''{0}''
DiffHeaderFormat_Email=email
DiffHeaderFormat_None=None
DiffHeaderFormat_Oneline=oneline
+DiffHeaderFormat_Workspace=Workspace
DiscardChangesOperation_discardFailed=Discarding changes of {0} failed
DiscardChangesOperation_discardFailedSeeLog=Discarding changes failed. See log for details
DiscardChangesOperation_discardingChanges=Discarding changes
@@ -97,6 +98,7 @@ CreateLocalBranchOperation_CreatingBranchMessage=Creating branch {0}
CreatePatchOperation_repoRequired=A repository is required to create a patch
CreatePatchOperation_cannotCreatePatchForMergeCommit=Cannot create patch for merge commit
CreatePatchOperation_cannotCreatePatchForFirstCommit=Cannot create patch for first commit
+CreatePatchOperation_couldNotFindProject=Could not find project for {0} in repository {1}
CreatePatchOperation_patchFileCouldNotBeWritten=Patch file could not be written
IndexDiffCacheEntry_reindexing=Re-indexing repository {0}
IndexFileRevision_errorLookingUpPath=IO error looking up path {0} in index.
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CreatePatchOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CreatePatchOperation.java
index 09ffb84..e6caf02 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CreatePatchOperation.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CreatePatchOperation.java
@@ -13,30 +13,47 @@
*******************************************************************************/
package org.eclipse.egit.core.op;
+import static org.eclipse.jgit.lib.Constants.encodeASCII;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.CoreText;
import org.eclipse.egit.core.EclipseGitProgressTransformer;
import org.eclipse.egit.core.internal.CompareCoreUtils;
+import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
+import org.eclipse.jgit.diff.DiffEntry.Side;
import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.osgi.util.NLS;
/**
* Creates a patch for a specific commit
@@ -54,6 +71,11 @@ public class CreatePatchOperation implements IEGitOperation {
NONE(CoreText.DiffHeaderFormat_None, false, null),
/**
+ * Workspace patch
+ */
+ WORKSPACE(CoreText.DiffHeaderFormat_Workspace, false, "### Eclipse Workspace Patch 1.0\n"), //$NON-NLS-1$
+
+ /**
* Email header
*/
EMAIL(CoreText.DiffHeaderFormat_Email, true, "From ${sha1} ${date}\nFrom: ${author}\nDate: ${author date}\nSubject: [PATCH] ${title line}\n${full commit message}\n"), //$NON-NLS-1$
@@ -120,6 +142,7 @@ public class CreatePatchOperation implements IEGitOperation {
private int contextLines = DEFAULT_CONTEXT_LINES;
private TreeFilter pathFilter = null;
+
/**
* Creates the new operation.
*
@@ -151,14 +174,32 @@ public class CreatePatchOperation implements IEGitOperation {
super.write(b, off, len);
if (currentEncoding == null)
sb.append(toString());
- else try {
- sb.append(toString(currentEncoding));
- } catch (UnsupportedEncodingException e) {
- sb.append(toString());
- }
+ else
+ try {
+ sb.append(toString(currentEncoding));
+ } catch (UnsupportedEncodingException e) {
+ sb.append(toString());
+ }
reset();
}
- });
+ }) {
+ private IProject project;
+
+ @Override
+ public void format(DiffEntry ent) throws IOException,
+ CorruptObjectException, MissingObjectException {
+ // for "workspace patches" add project header each time project changes
+ if (DiffHeaderFormat.WORKSPACE == headerFormat) {
+ IProject p = getProject(ent);
+ if (!p.equals(project)) {
+ project = p;
+ getOutputStream().write(
+ encodeASCII("#P " + project.getName() + "\n")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ super.format(ent);
+ }
+ };
diffFmt.setProgressMonitor(gitMonitor);
diffFmt.setContext(contextLines);
@@ -197,10 +238,28 @@ public class CreatePatchOperation implements IEGitOperation {
Activator.logError(CoreText.CreatePatchOperation_patchFileCouldNotBeWritten, e);
}
- patchContent = sb.toString();
+ if (DiffHeaderFormat.WORKSPACE == headerFormat)
+ updateWorkspacePatchPrefixes(sb, diffFmt);
+
// trim newline
- if (patchContent.endsWith("\n")) //$NON-NLS-1$
- patchContent = patchContent.substring(0, patchContent.length() - 1);
+ if (sb.charAt(sb.length() - 1) == '\n')
+ sb.setLength(sb.length() - 1);
+
+ patchContent = sb.toString();
+ }
+
+ private IProject getProject(final DiffEntry ent) {
+ Side side = ent.getChangeType() == ChangeType.ADD ? Side.NEW : Side.OLD;
+ String path = ent.getPath(side);
+ return getProject(path);
+ }
+
+ private IProject getProject(String path) {
+ URI pathUri = repository.getWorkTree().toURI().resolve(path);
+ IFile[] files = ResourcesPlugin.getWorkspace().getRoot()
+ .findFilesForLocationURI(pathUri);
+ Assert.isLegal(files.length == 1, NLS.bind(CoreText.CreatePatchOperation_couldNotFindProject, path, repository));
+ return files[0].getProject();
}
/**
@@ -269,6 +328,84 @@ public class CreatePatchOperation implements IEGitOperation {
}
/**
+ * Updates prefixes to workspace paths
+ *
+ * @param sb
+ * @param diffFmt
+ */
+ public void updateWorkspacePatchPrefixes(StringBuilder sb, DiffFormatter diffFmt) {
+ RawText rt = new RawText(sb.toString().getBytes());
+
+ final String oldPrefix = diffFmt.getOldPrefix();
+ final String newPrefix = diffFmt.getNewPrefix();
+
+ StringBuilder newSb = new StringBuilder();
+ final Pattern diffPattern = Pattern
+ .compile("^diff --git (" + oldPrefix + "(.+)) (" + newPrefix + "(.+))$"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ final Pattern oldPattern = Pattern
+ .compile("^--- (" + oldPrefix + "(.+))$"); //$NON-NLS-1$ //$NON-NLS-2$
+ final Pattern newPattern = Pattern
+ .compile("^\\+\\+\\+ (" + newPrefix + "(.+))$"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ int i = 0;
+ while (i < rt.size()) {
+ String line = rt.getString(i);
+
+ Matcher diffMatcher = diffPattern.matcher(line);
+ Matcher oldMatcher = oldPattern.matcher(line);
+ Matcher newMatcher = newPattern.matcher(line);
+ if (diffMatcher.find()) {
+ String group = diffMatcher.group(2); // old path
+ IProject project = getProject(group);
+ IPath newPath = computeWorkspacePath(new Path(group), project);
+ line = line.replaceAll(diffMatcher.group(1), newPath.toString());
+ group = diffMatcher.group(4); // new path
+ newPath = computeWorkspacePath(new Path(group), project);
+ line = line.replaceAll(diffMatcher.group(3), newPath.toString());
+ } else if (oldMatcher.find()) {
+ String group = oldMatcher.group(2);
+ IProject project = getProject(group);
+ IPath newPath = computeWorkspacePath(new Path(group), project);
+ line = line.replaceAll(oldMatcher.group(1), newPath.toString());
+ } else if (newMatcher.find()) {
+ String group = newMatcher.group(2);
+ IProject project = getProject(group);
+ IPath newPath = computeWorkspacePath(new Path(group), project);
+ line = line.replaceAll(newMatcher.group(1), newPath.toString());
+ }
+ newSb.append(line);
+
+ i++;
+ if (i < rt.size() || !rt.isMissingNewlineAtEnd())
+ newSb.append(rt.getLineDelimiter());
+ }
+ // reset sb to newSb
+ sb.setLength(0);
+ sb.append(newSb);
+ }
+
+ /**
+ * Returns a workspace path
+ *
+ * @param path
+ * @param project
+ * @return path
+ */
+ public static IPath computeWorkspacePath(final IPath path, final IProject project) {
+ RepositoryMapping rm = RepositoryMapping.getMapping(project);
+ String repoRelativePath = rm.getRepoRelativePath(project);
+ // the relative path cannot be determined, return unchanged
+ if (repoRelativePath == null)
+ return path;
+ // repository and project at the same level
+ if (repoRelativePath.equals("")) //$NON-NLS-1$
+ return path;
+ return path.removeFirstSegments(path.matchingFirstSegments(new Path(
+ repoRelativePath)));
+ }
+
+
+ /**
* Change the format of diff header
*
* @param format header format
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CommitDialogTester.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CommitDialogTester.java
index 117c7bd..0497948 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CommitDialogTester.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CommitDialogTester.java
@@ -72,7 +72,7 @@ public class CommitDialogTester {
SWTWorkbenchBot workbenchBot) {
SWTBotTree projectExplorerTree = workbenchBot
.viewById("org.eclipse.jdt.ui.PackageExplorer").bot().tree();
- util.getProjectItem(projectExplorerTree, projectName).select();
+ util.getProjectItems(projectExplorerTree, projectName)[0].select();
String menuString = util.getPluginLocalizedValue("CommitAction_label");
ContextMenuHelper.clickContextMenu(projectExplorerTree, "Team",
menuString);
@@ -145,10 +145,8 @@ public class CommitDialogTester {
if (select) {
if (!button.isChecked())
button.select();
- } else {
- if (button.isChecked())
- button.deselect();
- }
+ } else if (button.isChecked())
+ button.deselect();
}
public int getRowCount() {
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CreatePatchWizard.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CreatePatchWizard.java
index cb41f2a..8f4c2b2 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CreatePatchWizard.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/CreatePatchWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2012, Tomasz Zarna <Tomasz.Zarna@pl.ibm.com>
+ * Copyright (C) 2012, IBM Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -15,6 +15,7 @@ import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
public class CreatePatchWizard {
@@ -40,10 +41,11 @@ public class CreatePatchWizard {
this.shell = shell;
}
- public static void openWizard(final String project) {
+ public static void openWizard(final String... projects) {
SWTBotTree projectExplorerTree = bot
.viewById("org.eclipse.jdt.ui.PackageExplorer").bot().tree();
- util.getProjectItem(projectExplorerTree, project).select();
+ SWTBotTreeItem[] items = util.getProjectItems(projectExplorerTree, projects);
+ projectExplorerTree.select(items);
String[] menuPath = new String[] {
util.getPluginLocalizedValue("TeamMenu.label"),
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
index 15f4072..0148f53 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
@@ -82,7 +82,7 @@ import org.junit.BeforeClass;
* <p>
* A typical code sequence for setting up these two repositories could look
* like:
- *
+ *
* <pre>
* private File localRepo;
* private File remoteRepo;
@@ -124,7 +124,7 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
public static File getTestDirectory() {
return testDirectory;
}
-
+
@BeforeClass
public static void beforeClassBase() throws Exception {
deleteAllProjects();
@@ -380,8 +380,8 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
return name.equals(".project");
}
};
- for (File file : myRepository.getWorkTree().listFiles()) {
- if (file.isDirectory()) {
+ for (File file : myRepository.getWorkTree().listFiles())
+ if (file.isDirectory())
if (file.list(projectFilter).length > 0) {
IProjectDescription desc = ResourcesPlugin.getWorkspace()
.newProjectDescription(file.getName());
@@ -394,8 +394,6 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
new ConnectProviderOperation(prj, myRepository
.getDirectory()).execute(null);
}
- }
- }
}
@SuppressWarnings("boxing")
@@ -502,9 +500,8 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
if (file.exists()) {
byte[] bytes = IO.readFully(file.getLocation().toFile());
return new String(bytes, file.getCharset());
- } else {
+ } else
return "";
- }
}
/**
@@ -515,7 +512,7 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
*/
protected SWTBotTreeItem getProjectItem(SWTBotTree projectExplorerTree,
String project) {
- return new TestUtil().getProjectItem(projectExplorerTree, project);
+ return new TestUtil().getProjectItems(projectExplorerTree, project)[0];
}
protected void pressAltAndChar(SWTBotShell shell, char charToPress) {
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/TestUtil.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/TestUtil.java
index 28e5904..5691c2b 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/TestUtil.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/TestUtil.java
@@ -18,9 +18,11 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
@@ -80,7 +82,7 @@ public class TestUtil {
* in menu items and field labels for keyboard shortcuts) will be filtered
* out (see also {@link #getPluginLocalizedValue(String, boolean)} in order
* to be able to reference these fields using SWTBot).
- *
+ *
* @param key
* the key, must not be null
* @return the localized value in the current default {@link Locale}, or
@@ -96,7 +98,7 @@ public class TestUtil {
/**
* Allows access to the localized values of the EGit UI Plug-in
* <p>
- *
+ *
* @param key
* see {@link #getPluginLocalizedValue(String)}
* @param keepAmpersands
@@ -375,12 +377,11 @@ public class TestUtil {
byte[] expectedContent = expectedfiles.get(path).getBytes();
byte[] repoContent = treeWalk.getObjectReader().open(objectId)
.getBytes();
- if (!Arrays.equals(repoContent, expectedContent)) {
+ if (!Arrays.equals(repoContent, expectedContent))
fail("File " + path + " has repository content "
+ new String(repoContent)
+ " instead of expected content "
+ new String(expectedContent));
- }
expectedfiles.remove(path);
}
if (expectedfiles.size() > 0) {
@@ -398,20 +399,20 @@ public class TestUtil {
if ((args.length % 2) > 0)
throw new IllegalArgumentException("needs to be pairs");
HashMap<String, String> map = new HashMap<String, String>();
- for (int i = 0; i < args.length; i += 2) {
+ for (int i = 0; i < args.length; i += 2)
map.put(args[i], args[i+1]);
- }
return map;
}
/**
* @param projectExplorerTree
- * @param project
+ * @param projects
* name of a project
* @return the project item pertaining to the project
*/
- public SWTBotTreeItem getProjectItem(SWTBotTree projectExplorerTree,
- String project) {
+ public SWTBotTreeItem[] getProjectItems(SWTBotTree projectExplorerTree,
+ String... projects) {
+ List<SWTBotTreeItem> items = new ArrayList<SWTBotTreeItem>();
for (SWTBotTreeItem item : projectExplorerTree.getAllItems()) {
String itemText = item.getText();
StringTokenizer tok = new StringTokenizer(itemText, " ");
@@ -419,10 +420,11 @@ public class TestUtil {
// may be a dirty marker
if (name.equals(">"))
name = tok.nextToken();
- if (project.equals(name))
- return item;
+ for (String project : projects)
+ if (project.equals(name))
+ items.add(item);
}
- return null;
+ return items.isEmpty() ? null : items.toArray(new SWTBotTreeItem[items.size()]);
}
/**
@@ -475,9 +477,8 @@ public class TestUtil {
public static void waitUntilViewWithGivenIdShows(final String viewId) {
waitForView(new BaseMatcher<IViewReference>() {
public boolean matches(Object item) {
- if (item instanceof IViewReference) {
+ if (item instanceof IViewReference)
return viewId.equals(((IViewReference) item).getId());
- }
return false;
}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/CreatePatchActionTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/CreatePatchActionTest.java
index ca6375d..ff48bf8 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/CreatePatchActionTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/CreatePatchActionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2012, Tomasz Zarna <Tomasz.Zarna@pl.ibm.com>
+ * Copyright (C) 2012, IBM Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -10,7 +10,9 @@ package org.eclipse.egit.ui.test.team.actions;
import static org.junit.Assert.assertEquals;
+import java.io.ByteArrayInputStream;
import java.io.File;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -18,6 +20,7 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.egit.core.CoreText;
import org.eclipse.egit.core.op.CommitOperation;
import org.eclipse.egit.core.op.ResetOperation;
import org.eclipse.egit.core.op.ResetOperation.ResetType;
@@ -31,6 +34,7 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TagBuilder;
import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.swt.dnd.Clipboard;
@@ -68,6 +72,36 @@ public class CreatePatchActionTest extends LocalRepositoryTestCase {
+ "+newContent\n" //
+ "\\ No newline at end of file";
+ private static final String EXPECTED_WORKSPACE_PATCH_CONTENT = //
+ "### Eclipse Workspace Patch 1.0\n" //
+ + "#P " + PROJ1 + "\n"
+ + "diff --git folder/test.txt folder/test.txt\n" //
+ + "index e256dbb..d070357 100644\n" //
+ + "--- folder/test.txt\n" //
+ + "+++ folder/test.txt\n" //
+ + "@@ -1 +1 @@\n" //
+ + "-oldContent\n" //
+ + "\\ No newline at end of file\n" //
+ + "+newContent\n" //
+ + "\\ No newline at end of file\n"
+ + "diff --git folder/test2.txt folder/test2.txt\n"
+ + "deleted file mode 100644\n" //
+ + "index 8f4e8d3..0000000\n" //
+ + "--- folder/test2.txt\n" //
+ + "+++ /dev/null\n" //
+ + "@@ -1 +0,0 @@\n" //
+ + "-Some more content\n" //
+ + "\\ No newline at end of file\n" //
+ + "#P " + PROJ2 + "\n" //
+ + "diff --git test.txt test.txt\n" //
+ + "new file mode 100644\n" //
+ + "index 0000000..dbe9dba\n" //
+ + "--- /dev/null\n" //
+ + "+++ test.txt\n" //
+ + "@@ -0,0 +1 @@\n" //
+ + "+Hello, world\n" //
+ + "\\ No newline at end of file";
+
@BeforeClass
public static void setup() throws Exception {
perspective = bot.activePerspective();
@@ -193,8 +227,41 @@ public class CreatePatchActionTest extends LocalRepositoryTestCase {
assertEquals(EXPECTED_PATCH_CONTENT, patchContent);
}
+ @Test
+ public void testWorkspaceHeader() throws Exception {
+ touchAndSubmit("oldContent", null);
+ touch("newContent");
+ URI fileLocationUri = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(PROJ1).getFolder(FOLDER).getFile(FILE2)
+ .getLocationURI();
+ FileUtils.delete(new File(fileLocationUri));
+ IProject secondProject = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(PROJ2);
+ IFile newFile = secondProject.getFile(FILE1);
+ newFile.create(
+ new ByteArrayInputStream("Hello, world".getBytes(secondProject
+ .getDefaultCharset())), false, null);
+ waitInUI();
+
+ CreatePatchWizard createPatchWizard = openCreatePatchWizard();
+ LocationPage locationPage = createPatchWizard.getLocationPage();
+ locationPage.selectWorkspace("/" + PROJ1 + "/" + PATCH_FILE);
+ OptionsPage optionsPage = locationPage.nextToOptionsPage();
+ optionsPage.setFormat(CoreText.DiffHeaderFormat_Workspace);
+ createPatchWizard.finish();
+
+ bot.waitUntil(Conditions.shellCloses(createPatchWizard.getShell()));
+
+ IFile patch = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(PROJ1).getFile(PATCH_FILE);
+ byte[] bytes = IO.readFully(patch.getLocation().toFile());
+ String patchContent = new String(bytes, patch.getCharset());
+
+ assertEquals(EXPECTED_WORKSPACE_PATCH_CONTENT, patchContent);
+ }
+
private CreatePatchWizard openCreatePatchWizard() throws Exception {
- CreatePatchWizard.openWizard(PROJ1);
+ CreatePatchWizard.openWizard(PROJ1, PROJ2);
SWTBotShell shell = bot
.shell(UIText.GitCreatePatchWizard_CreatePatchTitle);
return new CreatePatchWizard(shell);
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/LocationPage.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/LocationPage.java
index 8220a84..5918d76 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/LocationPage.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/LocationPage.java
@@ -31,4 +31,9 @@ public class LocationPage {
shell.bot().radio(UIText.GitCreatePatchWizard_Workspace).click();
shell.bot().text(1).setText(path);
}
+
+ OptionsPage nextToOptionsPage() {
+ shell.bot().button("Next >").click();
+ return new OptionsPage(shell);
+ }
}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/OptionsPage.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/OptionsPage.java
new file mode 100644
index 0000000..ae6062c
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/team/actions/OptionsPage.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (C) 2012, IBM Corporation 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.ui.test.team.actions;
+
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotCombo;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+
+public class OptionsPage {
+
+ private SWTBotShell shell;
+
+ public OptionsPage(SWTBotShell shell) {
+ this.shell = shell;
+ }
+
+ private SWTBotCombo getFormatCombo() {
+ return shell.bot().comboBoxWithLabel(UIText.GitCreatePatchWizard_Format);
+ }
+
+ public void setFormat(final String selection) {
+ getFormatCombo().setSelection(selection);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java
index bdaa4eb..9f4caf6 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CreatePatchActionHandler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2011-2012, Tomasz Zarna <Tomasz.Zarna@pl.ibm.com>
+ * Copyright (C) 2011-2012, IBM Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java
index a1fc9ef..80538c2 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java
@@ -85,6 +85,7 @@ public class GitCreatePatchWizard extends Wizard {
private OptionsPage optionsPage;
+
// The initial size of this wizard.
private final static int INITIAL_WIDTH = 300;
@@ -387,4 +388,4 @@ public class GitCreatePatchWizard extends Wizard {
RevCommit getCommit() {
return commit;
}
-} \ No newline at end of file
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/patch/PatchOperationUI.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/patch/PatchOperationUI.java
index 8f9c999..9ba4c0f 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/patch/PatchOperationUI.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/patch/PatchOperationUI.java
@@ -120,6 +120,10 @@ public class PatchOperationUI {
}
private Shell getShell() {
+ return getShell(part);
+ }
+
+ private static Shell getShell(IWorkbenchPart part) {
if (part != null)
return part.getSite().getShell();
return PlatformUI.getWorkbench().getDisplay().getActiveShell();