From 44d23c2ae91f4c065843e888a76185c4a20ab488 Mon Sep 17 00:00:00 2001 From: Tomasz Zarna Date: Wed, 25 Jan 2012 02:15:57 +0100 Subject: Allow to select different diff header formats See "Pretty Formats" section of git-diff-tree man page for more examples Change-Id: I470ef0181b54d1780fe545cbb8c654247f958c8c --- .../core/test/op/CreatePatchOperationTest.java | 39 +++++- .../src/org/eclipse/egit/core/CoreText.java | 9 ++ .../src/org/eclipse/egit/core/coretext.properties | 3 + .../eclipse/egit/core/op/CreatePatchOperation.java | 142 +++++++++++++++++---- .../src/org/eclipse/egit/ui/UIText.java | 2 +- .../egit/ui/internal/history/CommitGraphTable.java | 3 +- .../ui/internal/history/GitCreatePatchWizard.java | 47 ++++++- .../src/org/eclipse/egit/ui/uitext.properties | 2 +- 8 files changed, 209 insertions(+), 38 deletions(-) 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 fb5941344b..b692f9dec4 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 @@ -18,6 +18,7 @@ import java.io.File; import org.eclipse.core.runtime.NullProgressMonitor; 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.TestRepository; import org.eclipse.jgit.lib.Constants; @@ -41,6 +42,15 @@ public class CreatePatchOperationTest extends GitTestCase { + "+another line\n" + "\\ No newline at end of file"; + private static final String SIMPLE_ONELINE_PATCH_CONTENT = "6dcd097c7d39e9ba0b31a380981d3fb46017d6c2 2nd commit\n" + + "diff --git a/test-file b/test-file\n" + + "index e69de29..eb5f2c9 100644\n" + + "--- a/test-file\n" + + "+++ b/test-file\n" + + "@@ -0,0 +1 @@\n" + + "+another line\n" + + "\\ No newline at end of file"; + private static final String SIMPLE_PATCH_CONTENT = "diff --git a/test-file b/test-file\n" + "index e69de29..eb5f2c9 100644\n" + "--- a/test-file\n" @@ -88,6 +98,17 @@ public class CreatePatchOperationTest extends GitTestCase { 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 @@ -98,7 +119,7 @@ public class CreatePatchOperationTest extends GitTestCase { CreatePatchOperation operation = new CreatePatchOperation( testRepository.getRepository(), secondCommit); - operation.useGitFormat(false); + operation.setHeaderFormat(DiffHeaderFormat.NONE); operation.execute(new NullProgressMonitor()); String patchContent = operation.getPatchContent(); @@ -106,6 +127,22 @@ public class CreatePatchOperationTest extends GitTestCase { assertPatch(SIMPLE_PATCH_CONTENT, patchContent); } + @Test + public void testOnelineHeaderPatch() throws Exception { + RevCommit secondCommit = testRepository.appendContentAndCommit( + project.getProject(), file, "another line", "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(expected = IllegalStateException.class) public void testFirstCommit() throws Exception { CreatePatchOperation operation = new CreatePatchOperation( 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 6a5165b6bf..fe205c4274 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 @@ -77,6 +77,15 @@ public class CoreText extends NLS { /** */ public static String DeleteTagOperation_exceptionMessage; + /** */ + public static String DiffHeaderFormat_Email; + + /** */ + public static String DiffHeaderFormat_None; + + /** */ + public static String DiffHeaderFormat_Oneline; + /** */ public static String DiscardChangesOperation_discardFailed; 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 b06b5ee41e..320baee468 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 @@ -18,6 +18,9 @@ ConnectProviderOperation_ConnectingProject=Connecting project {0} DeleteBranchOperation_TaskName=Deleting branch {0} DeleteTagOperation_exceptionMessage=Exception deleting tag ''{0}'' +DiffHeaderFormat_Email=email +DiffHeaderFormat_None=None +DiffHeaderFormat_Oneline=oneline DiscardChangesOperation_discardFailed=Discarding changes of {0} failed DiscardChangesOperation_discardFailedSeeLog=Discarding changes failed. See log for details DiscardChangesOperation_discardingChanges=Discarding changes 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 5c10280edb..de1b278c2f 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 @@ -18,6 +18,7 @@ import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.List; import java.util.Locale; +import java.util.Stack; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -40,6 +41,64 @@ import org.eclipse.jgit.treewalk.FileTreeIterator; */ public class CreatePatchOperation implements IEGitOperation { + /** + * Diff header format + * + */ + public enum DiffHeaderFormat { + /** + * No header + */ + NONE(CoreText.DiffHeaderFormat_None, false, null), + + /** + * 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$ + + /** + * Header designed to be as compact as possible + */ + ONELINE(CoreText.DiffHeaderFormat_Oneline, true, "${sha1} ${title line}\n"); //$NON-NLS-1$ + + private final String description; + + private final boolean commitRequired; + + private final String template; + + private DiffHeaderFormat(final String d, final boolean c, final String t) { + description = d; + commitRequired = c; + template = t; + } + + /** + * @return if this format requires a commit. + */ + public boolean isCommitRequired() { + return commitRequired; + } + + /** + * @return the template + */ + public String getTemplate() { + return template; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + } + + enum DiffHeaderKeyword{ + SHA1, AUTHOR_DATE, AUTHOR, DATE, TITLE_LINE, FULL_COMMIT_MESSAGE + } + /** * The default number of lines to use as context */ @@ -49,7 +108,7 @@ public class CreatePatchOperation implements IEGitOperation { private final Repository repository; - private boolean useGitFormat = true; + private DiffHeaderFormat headerFormat = DiffHeaderFormat.EMAIL; // the encoding for the currently processed file private String currentEncoding = null; @@ -101,7 +160,7 @@ public class CreatePatchOperation implements IEGitOperation { diffFmt.setProgressMonitor(gitMonitor); diffFmt.setContext(contextLines); - if (useGitFormat) + if (headerFormat != null && headerFormat != DiffHeaderFormat.NONE) writeGitPatchHeader(sb); diffFmt.setRepository(repository); @@ -154,36 +213,65 @@ public class CreatePatchOperation implements IEGitOperation { } private void writeGitPatchHeader(StringBuilder sb) { - final SimpleDateFormat dtfmt; - dtfmt = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); //$NON-NLS-1$ - dtfmt.setTimeZone(commit.getAuthorIdent().getTimeZone()); - sb.append("From").append(" ") //$NON-NLS-1$ //$NON-NLS-2$ - .append(commit.getId().getName()).append(" ") //$NON-NLS-1$ - .append(dtfmt.format(Long.valueOf(System.currentTimeMillis()))) - .append("\n"); //$NON-NLS-1$ - sb.append("From") //$NON-NLS-1$ - .append(": ") //$NON-NLS-1$ - .append(commit.getAuthorIdent().getName()) - .append(" <").append(commit.getAuthorIdent().getEmailAddress()) //$NON-NLS-1$ - .append(">\n"); //$NON-NLS-1$ - sb.append("Date").append(": ") //$NON-NLS-1$ //$NON-NLS-2$ - .append(dtfmt.format(commit.getAuthorIdent().getWhen())) - .append("\n"); //$NON-NLS-1$ - sb.append("Subject").append(": [PATCH] ") //$NON-NLS-1$ //$NON-NLS-2$ - .append(commit.getShortMessage()); - - String message = commit.getFullMessage().substring( - commit.getShortMessage().length()); - sb.append(message).append("\n\n"); //$NON-NLS-1$ + String template = headerFormat.getTemplate(); + String[] segments = template.split("\\$\\{"); //$NON-NLS-1$ + Stack evaluated = new Stack(); + evaluated.add(segments[0]); + + for (int i = 1; i < segments.length; i++) { + String segment = segments[i]; + String value = null; + int brace = segment.indexOf('}'); + if (brace > 0) { + String keyword = segment.substring(0, brace); + keyword = keyword.toUpperCase().replaceAll(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$ + value = processKeyword(commit, DiffHeaderKeyword.valueOf(keyword)); + } + + String trailingCharacters = segment.substring(brace + 1); + if (value != null) { + evaluated.add(value); + evaluated.add(trailingCharacters); + } else if (!evaluated.isEmpty()) + evaluated.add(trailingCharacters); + } + StringBuffer buffer = new StringBuffer(); + for (String string : evaluated) + buffer.append(string); + + sb.append(buffer); + } + + private static String processKeyword(RevCommit commit, DiffHeaderKeyword keyword) { + final SimpleDateFormat dtfmt = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); //$NON-NLS-1$ + switch (keyword) { + case SHA1: + return commit.getId().getName(); + case AUTHOR: + return commit.getAuthorIdent().getName() + + " <" + commit.getAuthorIdent().getEmailAddress() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ + case AUTHOR_DATE: + dtfmt.setTimeZone(commit.getAuthorIdent().getTimeZone()); + return dtfmt.format(commit.getAuthorIdent().getWhen()); + case DATE: + return dtfmt.format(Long.valueOf(System.currentTimeMillis())); + case TITLE_LINE: + return commit.getShortMessage(); + case FULL_COMMIT_MESSAGE: + return commit.getFullMessage().substring( + commit.getShortMessage().length()); + default: + return null; + } } /** - * Decides whether to use the git format for patches. + * Change the format of diff header * - * @param useFormat + * @param format header format */ - public void useGitFormat(boolean useFormat) { - this.useGitFormat = useFormat; + public void setHeaderFormat(DiffHeaderFormat format) { + this.headerFormat = format; } /** diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index b32b932cae..b8c1ac72e3 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -2980,7 +2980,7 @@ public class UIText extends NLS { public static String GitCreatePatchWizard_File; /** */ - public static String GitCreatePatchWizard_GitFormat; + public static String GitCreatePatchWizard_Format; /** */ public static String GitCreatePatchWizard_InternalError; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java index aa4f2e1b5c..7bfc737924 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java @@ -30,6 +30,7 @@ import org.eclipse.core.commands.common.NotDefinedException; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.egit.core.op.CreatePatchOperation; +import org.eclipse.egit.core.op.CreatePatchOperation.DiffHeaderFormat; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIPreferences; @@ -617,7 +618,7 @@ class CommitGraphTable { Repository repository = input.getRepository(); CreatePatchOperation operation = new CreatePatchOperation( repository, commit); - operation.useGitFormat(true); + operation.setHeaderFormat(DiffHeaderFormat.EMAIL); operation.setContextLines(CreatePatchOperation.DEFAULT_CONTEXT_LINES); try { operation.execute(null); 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 e37eb919c9..bbf7f48a54 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 @@ -24,6 +24,7 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; 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.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIText; @@ -33,6 +34,13 @@ import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jface.wizard.WizardPage; @@ -137,8 +145,7 @@ public class GitCreatePatchWizard extends Wizard { public boolean performFinish() { final CreatePatchOperation operation = new CreatePatchOperation(db, commit); - boolean useGitFormat = optionsPage.gitFormat.getSelection(); - operation.useGitFormat(useGitFormat); + operation.setHeaderFormat(optionsPage.getSelectedHeaderFormat()); operation.setContextLines(Integer.parseInt(optionsPage.contextLines.getText())); final boolean isFile = locationPage.fsRadio.getSelection(); @@ -404,7 +411,8 @@ public class GitCreatePatchWizard extends Wizard { * A wizard Page used to specify options of the created patch */ public class OptionsPage extends WizardPage { - private Button gitFormat; + private Label formatLabel; + private ComboViewer formatCombo; private Text contextLines; private Label contextLinesLabel; @@ -427,10 +435,29 @@ public class GitCreatePatchWizard extends Wizard { GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; - gitFormat = new Button(composite, SWT.CHECK); - gitFormat.setText(UIText.GitCreatePatchWizard_GitFormat); - gitFormat.setLayoutData(gd); - gitFormat.setEnabled(commit != null); + + formatLabel = new Label(composite, SWT.NONE); + formatLabel.setText(UIText.GitCreatePatchWizard_Format); + + formatCombo = new ComboViewer(composite, SWT.DROP_DOWN | SWT.READ_ONLY); + formatCombo.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false)); + formatCombo.setContentProvider(ArrayContentProvider.getInstance()); + formatCombo.setLabelProvider(new LabelProvider() { + @Override + public String getText(Object element) { + return ((DiffHeaderFormat) element).getDescription(); + } + }); + formatCombo.setInput(DiffHeaderFormat.values()); + formatCombo.setFilters(new ViewerFilter[] { new ViewerFilter() { + @Override + public boolean select(Viewer viewer, Object parentElement, + Object element) { + return commit != null + || !((DiffHeaderFormat) element).isCommitRequired(); + } + }}); + formatCombo.setSelection(new StructuredSelection(DiffHeaderFormat.NONE)); contextLinesLabel = new Label(composite, SWT.NONE); contextLinesLabel.setText(UIText.GitCreatePatchWizard_LinesOfContext); @@ -477,5 +504,11 @@ public class GitCreatePatchWizard extends Wizard { } return true; } + + DiffHeaderFormat getSelectedHeaderFormat() { + IStructuredSelection selection = (IStructuredSelection) formatCombo + .getSelection(); + return (DiffHeaderFormat) selection.getFirstElement(); + } } } \ No newline at end of file diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 4dbafebf29..b39bcd7545 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -1027,7 +1027,7 @@ GitCreatePatchWizard_Clipboard=&Clipboard GitCreatePatchWizard_ContextMustBePositiveInt=Context must be a valid number of lines ( >= 0 ) GitCreatePatchWizard_CreatePatchTitle=Create Patch GitCreatePatchWizard_File=Fil&e -GitCreatePatchWizard_GitFormat=Export in &Git patch format +GitCreatePatchWizard_Format=Format GitCreatePatchWizard_InternalError=An internal error occurred. GitCreatePatchWizard_SelectLocationDescription=Select the location for the patch. GitCreatePatchWizard_SelectLocationTitle=Create a Patch -- cgit v1.2.3