
	 */
	public static void run(Shell shell, final RevCommit commit,
			Repository db, Collection<? extends IResource> resources) {
		final String title = UIText.GitCreatePatchWizard_CreatePatchTitle;
		final GitCreatePatchWizard wizard = new GitCreatePatchWizard(commit, db, resources);
		wizard.setWindowTitle(title);
		WizardDialog dialog = new WizardDialog(shell, wizard);
		dialog.setMinimumPageSize(INITIAL_WIDTH, INITIAL_HEIGHT);
		dialog.setHelpAvailable(false);
		dialog.open();
	}

	/**
	 * Creates a wizard which is used to export the changes introduced by a
	 * commit.
	 *
	 * @param commit
	 * @param db
	 * @param resources
	 */
	public GitCreatePatchWizard(RevCommit commit, Repository db, Collection<? extends IResource> resources) {
		this.commit = commit;
		this.db = db;
		this.resources = resources;

		setDialogSettings(getOrCreateSection(Activator.getDefault().getDialogSettings(), "GitCreatePatchWizard")); //$NON-NLS-1$
	}

	/*
	 * Copy of org.eclipse.jface.dialogs.DialogSettings.getOrCreateSection(IDialogSettings, String)
	 * which is not available in 3.5.
	 */
	private static IDialogSettings getOrCreateSection(IDialogSettings settings,
			String sectionName) {
		IDialogSettings section = settings.getSection(sectionName);
		if (section == null)
			section = settings.addNewSection(sectionName);
		return section;
	}

	@Override
	public void addPages() {
		String pageTitle = UIText.GitCreatePatchWizard_SelectLocationTitle;
		String pageDescription = UIText.GitCreatePatchWizard_SelectLocationDescription;

		locationPage = new LocationPage(pageTitle, pageTitle, UIIcons.WIZBAN_CREATE_PATCH);
		locationPage.setDescription(pageDescription);
		addPage(locationPage);

		pageTitle = UIText.GitCreatePatchWizard_SelectOptionsTitle;
		pageDescription = UIText.GitCreatePatchWizard_SelectOptionsDescription;
		optionsPage = new OptionsPage(pageTitle, pageTitle, UIIcons.WIZBAN_CREATE_PATCH);
		optionsPage.setDescription(pageDescription);
		addPage(optionsPage);
	}

	@Override
	public boolean performFinish() {
		final CreatePatchOperation operation = new CreatePatchOperation(db,
				commit);
		operation.setHeaderFormat(optionsPage.getSelectedHeaderFormat());
		operation.setContextLines(Integer.parseInt(optionsPage.contextLines.getText()));
		operation.setPathFilter(createPathFilter(resources));

		final File file =!locationPage.fsRadio.getSelection()? locationPage
				.getFile() : null;

		if (!(file == null || validateFile(file)))
			return false;

		try {
			getContainer().run(true, true, new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor)
						throws InvocationTargetException {
					try {
						operation.execute(monitor);

						String content = operation.getPatchContent();
						if (file!= null)
							writeToFile(file, content);
						else
							copyToClipboard(content);
					} catch (IOException e) {
						throw new InvocationTargetException(e);
					} catch (CoreException e) {
						throw new InvocationTargetException(e);
					}
				}
			});
		} catch (InvocationTargetException e) {
			((WizardPage) getContainer().getCurrentPage()).setErrorMessage(e
					.getMessage() == null? e.getMessage()
					: UIText.GitCreatePatchWizard_InternalError);
			Activator.logError("Patch file was not written", e); //$NON-NLS-1$
			return false;
		} catch (InterruptedException e) {
			Activator.logError("Patch file was not written", e); //$NON-NLS-1$
			return false;
		}
		return true;
	}

	private void copyToClipboard(final String content) {
		getShell().getDisplay().syncExec(new Runnable() {
			public void run() {
				TextTransfer plainTextTransfer = TextTransfer.getInstance();
				Clipboard clipboard = new Clipboard(getShell().getDisplay());
				clipboard.setContents(new String[] { content },
						new Transfer[] { plainTextTransfer });
				clipboard.dispose();
			}
		});
	}

	private TreeFilter createPathFilter(final Collection<? extends IResource> rs) {
		if (rs == null || rs.isEmpty())
			return null;
		final List<PathFilter> filters = new ArrayList<PathFilter>();
		for (IResource r : rs) {
			RepositoryMapping rm = RepositoryMapping.getMapping(r);
			String repoRelativePath = rm.getRepoRelativePath(r);
			if (repoRelativePath!= null)
				filters.add(PathFilter.create(repoRelativePath));
		}
		if (filters.size() == 0)
			return null;
		if (filters.size() == 1)
			return filters.get(0);
		return PathFilterGroup.create(filters);
	}

	private void writeToFile(final File file, String content)
			throws IOException {
		Writer output = new BufferedWriter(new FileWriter(file));
		try {
			// FileWriter always assumes default encoding is
			// OK!
			output.write(content);
		} finally {
			output.close();
		}
	}

	private boolean validateFile(File file) {
		if (file == null)
			return false;

		// Consider file valid if it doesn't exist for now.
		if (!file.exists())
			return true;

		// The file exists.
		if (!file.canWrite()) {
			final String title= UIText.GitCreatePatchWizard_ReadOnlyTitle;
			final String msg= UIText.GitCreatePatchWizard_ReadOnlyMsg;
			final MessageDialog dialog= new MessageDialog(getShell(), title, null, msg, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0);
			dialog.open();
			return false;
		}

		final String title = UIText.GitCreatePatchWizard_OverwriteTitle;
		final String msg = UIText.GitCreatePatchWizard_OverwriteMsg;
		final MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
		dialog.open();
		if (dialog.getReturnCode()!= 0)
			return false;

		return true;
	}

	/**
	 *
	 * A wizard Page used to specify options of the created patch
	 */
	public class OptionsPage extends WizardPage {
		private Label formatLabel;
		private ComboViewer formatCombo;
		private Text contextLines;
		private Label contextLinesLabel;

		/**
		 *
		 * @param pageName
		 * @param title
		 * @param titleImage
		 */
		protected OptionsPage(String pageName, String title,
				ImageDescriptor titleImage) {
			super(pageName, title, titleImage);
		}

		public void createControl(Composite parent) {
			final Composite composite = new Composite(parent, SWT.NULL);
			GridLayout gridLayout = new GridLayout(2, false);
			composite.setLayout(gridLayout);
			composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

			GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
			gd.horizontalSpan = 2;

			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());
			format