diff options
| author | Tomasz Zarna | 2012-03-16 00:38:34 +0000 |
|---|---|---|
| committer | Matthias Sohn | 2012-03-22 23:21:11 +0000 |
| commit | 624ec10bd93e6ec14dc2cbdc59c6843bd4fec940 (patch) | |
| tree | 86fca40a7809a63d82c93f846e66ffb6954343fc | |
| parent | c527dbc3d59b8311666b2f8efb3eb590158de61a (diff) | |
| download | egit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.tar.gz egit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.tar.xz egit-624ec10bd93e6ec14dc2cbdc59c6843bd4fec940.zip | |
Add support for "workspace patches"
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>
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 a7b6f96c8e..b40bd67f38 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 b692f9dec4..05dfab2b0f 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 d00a1f378f..6cfa2e1bdf 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 a695a41b82..06da6b8f6b 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 09ffb84006..e6caf0210a 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 117c7bd35f..049794815d 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 cb41f2ab9c..8f4c2b2a34 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 15f40726e4..0148f53ed8 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 28e59041dc..5691c2bb5f 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 ca6375d7a5..ff48bf8f53 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 8220a84980..5918d7682b 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 0000000000..ae6062cb07 --- /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 bdaa4eb41c..9f4caf63fc 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 a1fc9efb89..80538c20b2 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 8f9c999984..9ba4c0fd2f 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(); |
