| /******************************************************************************* |
| * Copyright (c) 2007, 2018 Alphonse Van Assche and others. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Alphonse Van Assche - initial API and implementation |
| * Red Hat Inc. - ongoging maintenance |
| *******************************************************************************/ |
| |
| package org.eclipse.linuxtools.rpm.ui.editor.wizards; |
| |
| import java.io.BufferedInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.LineNumberReader; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.linuxtools.internal.rpm.ui.editor.Activator; |
| import org.eclipse.linuxtools.internal.rpm.ui.editor.SpecfileLog; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.dialogs.ContainerSelectionDialog; |
| |
| public class SpecfileNewWizardPage extends WizardPage { |
| |
| private static final String NAME = "package_name"; //$NON-NLS-1$ |
| |
| private static final String VERSION = "1.0"; //$NON-NLS-1$ |
| |
| private static final String SUMMARY = "Summary of the package"; //$NON-NLS-1$ |
| |
| private static final String GROUP = "Amusements/Games"; //$NON-NLS-1$ |
| |
| private static final String LICENSE = "GPL"; //$NON-NLS-1$ |
| |
| private static final String URL = "http://"; //$NON-NLS-1$ |
| |
| private static final String SOURCE0 = "archive_name-%{version}"; //$NON-NLS-1$ |
| |
| private Text projectText; |
| |
| private Text nameText; |
| |
| private Text versionText; |
| |
| private Text summaryText; |
| |
| private Combo groupCombo; |
| |
| private Text licenseText; |
| |
| private Text urlText; |
| |
| private Text source0Text; |
| |
| private GridData gd; |
| |
| private ISelection selection; |
| |
| private String selectedTemplate = "minimal"; //$NON-NLS-1$ |
| |
| private String content; |
| |
| /** |
| * Constructor for SpecfileNewWizardPage. |
| * |
| * @param selection The selection to put the new spec file in. |
| */ |
| public SpecfileNewWizardPage(ISelection selection) { |
| super("wizardPage"); //$NON-NLS-1$ |
| setTitle(Messages.SpecfileNewWizardPage_9); |
| setDescription(Messages.SpecfileNewWizardPage_10); |
| this.selection = selection; |
| } |
| |
| @Override |
| public void createControl(Composite parent) { |
| final Composite container = new Composite(parent, SWT.NULL); |
| GridLayout layout = new GridLayout(); |
| container.setLayout(layout); |
| layout.numColumns = 3; |
| layout.verticalSpacing = 9; |
| |
| // Project |
| Label label = new Label(container, SWT.NULL); |
| label.setText(Messages.SpecfileNewWizardPage_11); |
| projectText = new Text(container, SWT.BORDER | SWT.SINGLE); |
| gd = new GridData(GridData.FILL_HORIZONTAL); |
| projectText.setLayoutData(gd); |
| projectText.addModifyListener(e -> dialogChanged()); |
| Button button = new Button(container, SWT.PUSH); |
| button.setText(Messages.SpecfileNewWizardPage_12); |
| button.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> handleBrowse())); |
| |
| // Template to use |
| label = new Label(container, SWT.NULL); |
| label.setText(Messages.SpecfileNewWizardPage_13); |
| Combo templateCombo = new Combo(container, SWT.NULL); |
| try { |
| populateTemplateCombo(templateCombo); |
| } catch (CoreException e2) { |
| SpecfileLog.logError(e2); |
| } |
| // empty label for the last row. |
| label = new Label(container, SWT.NULL); |
| templateCombo.addModifyListener(e -> { |
| selectedTemplate = ((Combo) e.getSource()).getText(); |
| InputStream inputStream = runRpmdevNewSpec(selectedTemplate); |
| LineNumberReader reader = new LineNumberReader(new InputStreamReader(inputStream)); |
| String line; |
| try { |
| content = ""; //$NON-NLS-1$ |
| setDefaultValues(); |
| while ((line = reader.readLine()) != null) { |
| if (line.startsWith("Name:")) { //$NON-NLS-1$ |
| setTemplateTagValue(nameText, line); |
| } |
| if (line.startsWith("Version:")) { //$NON-NLS-1$ |
| setTemplateTagValue(versionText, line); |
| } |
| if (line.startsWith("Summary:")) { //$NON-NLS-1$ |
| setTemplateTagValue(summaryText, line); |
| } |
| if (line.startsWith("Group:")) { //$NON-NLS-1$ |
| String[] items = line.split(":", 2); //$NON-NLS-1$ |
| String value = items[1].trim(); |
| if (!value.equals("")) {//$NON-NLS-1$ |
| groupCombo.setText(value); |
| } |
| } |
| if (line.startsWith("License:")) { //$NON-NLS-1$ |
| setTemplateTagValue(licenseText, line); |
| } |
| if (line.startsWith("URL:")) { //$NON-NLS-1$ |
| setTemplateTagValue(urlText, line); |
| } |
| if (line.startsWith("Source0:")) { //$NON-NLS-1$ |
| setTemplateTagValue(source0Text, line); |
| } |
| content += line + '\n'; |
| } |
| } catch (IOException e1) { |
| SpecfileLog.logError(e1); |
| } |
| }); |
| |
| // Package Name |
| nameText = setTextItem(container, Messages.SpecfileNewWizardPage_14); |
| |
| // Package Version |
| versionText = setTextItem(container, Messages.SpecfileNewWizardPage_15); |
| |
| // Package Summary |
| summaryText = setTextItem(container, Messages.SpecfileNewWizardPage_16); |
| |
| // Package Group |
| label = new Label(container, SWT.NULL); |
| label.setText(Messages.SpecfileNewWizardPage_17); |
| groupCombo = new Combo(container, SWT.NULL); |
| populateGroupCombo(groupCombo); |
| // empty label for the last row. |
| new Label(container, SWT.NULL); |
| |
| // Package License |
| licenseText = setTextItem(container, Messages.SpecfileNewWizardPage_18); |
| |
| // Package URL |
| urlText = setTextItem(container, Messages.SpecfileNewWizardPage_19); |
| |
| // Package Source0 |
| source0Text = setTextItem(container, Messages.SpecfileNewWizardPage_20); |
| |
| initialize(); |
| dialogChanged(); |
| setControl(container); |
| } |
| |
| private Text setTextItem(Composite container, String textLabel) { |
| Label label = new Label(container, SWT.NULL); |
| label.setText(textLabel); |
| Text text = new Text(container, SWT.BORDER | SWT.SINGLE); |
| text.setLayoutData(gd); |
| text.addModifyListener(e -> dialogChanged()); |
| // empty label for the last row. |
| new Label(container, SWT.NULL); |
| return text; |
| } |
| |
| private void setTemplateTagValue(Text text, String line) { |
| String[] items = line.split(":", 2); //$NON-NLS-1$ |
| String value = items[1].trim(); |
| if (!value.equals("")) { //$NON-NLS-1$ |
| text.setText(value); |
| } |
| } |
| |
| public String getProjectName() { |
| return projectText.getText(); |
| } |
| |
| public String getFileName() { |
| return nameText.getText() + ".spec"; //$NON-NLS-1$ |
| } |
| |
| public String getSelectedTemplate() { |
| return selectedTemplate; |
| } |
| |
| public String getContent() { |
| InputStream inputStream = runRpmdevNewSpec(selectedTemplate); |
| LineNumberReader reader = new LineNumberReader(new InputStreamReader(inputStream)); |
| String line; |
| try { |
| content = ""; //$NON-NLS-1$ |
| while ((line = reader.readLine()) != null) { |
| if (line.startsWith("Name:")) { //$NON-NLS-1$ |
| line = "Name:" + " " + nameText.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("Version:")) { //$NON-NLS-1$ |
| line = "Version:" + " " + versionText.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("Summary:")) { //$NON-NLS-1$ |
| line = "Summary:" + " " + summaryText.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("Group:")) { //$NON-NLS-1$ |
| line = "Group:" + " " + groupCombo.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("License:")) { //$NON-NLS-1$ |
| line = "License:" + " " + licenseText.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("URL:")) { //$NON-NLS-1$ |
| line = "URL:" + " " + urlText.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| if (line.startsWith("Source0:")) { //$NON-NLS-1$ |
| line = "Source0:" + " " + source0Text.getText(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| content += line + '\n'; |
| } |
| } catch (IOException e1) { |
| SpecfileLog.logError(e1); |
| } |
| return content; |
| } |
| |
| /** |
| * Tests if the current workbench selection is a suitable container to use. |
| */ |
| private void initialize() { |
| if (selection instanceof IStructuredSelection && !selection.isEmpty()) { |
| IStructuredSelection ssel = (IStructuredSelection) selection; |
| if (ssel.size() > 1) { |
| return; |
| } |
| Object obj = ssel.getFirstElement(); |
| if (obj instanceof IResource) { |
| IContainer container; |
| if (obj instanceof IContainer) { |
| container = (IContainer) obj; |
| } else { |
| container = ((IResource) obj).getParent(); |
| } |
| projectText.setText(container.getFullPath().toString()); |
| } |
| } |
| setDefaultValues(); |
| } |
| |
| /** |
| * Uses the standard container selection dialog to choose the new value for the |
| * container field. |
| */ |
| private void handleBrowse() { |
| ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(), |
| ResourcesPlugin.getWorkspace().getRoot(), false, Messages.SpecfileNewWizardPage_21); |
| if (dialog.open() == Window.OK) { |
| Object[] result = dialog.getResult(); |
| if (result.length == 1) { |
| projectText.setText(((Path) result[0]).toString()); |
| } |
| } |
| } |
| |
| /** |
| * Ensures that both text fields are set. |
| */ |
| private void dialogChanged() { |
| IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(getProjectName())); |
| String fileName = getFileName(); |
| if (getProjectName().length() == 0) { |
| updateStatus(Messages.SpecfileNewWizardPage_22); |
| return; |
| } |
| if (container == null || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) { |
| updateStatus(Messages.SpecfileNewWizardPage_23); |
| return; |
| } |
| if (!container.isAccessible()) { |
| updateStatus(Messages.SpecfileNewWizardPage_24); |
| return; |
| } |
| if (fileName.length() == 0) { |
| updateStatus(Messages.SpecfileNewWizardPage_25); |
| return; |
| } |
| |
| /* |
| * Current RPM doc content (4.4.2): Names must not include whitespace and may |
| * include a hyphen '-' (unlike version and releasetags). Names should not |
| * include any numeric operators ('<', '>','=') as future versions of rpm may |
| * need to reserve characters other than '-'. |
| */ |
| String packageName = nameText.getText(); |
| if (packageName.indexOf(' ') != -1 || packageName.indexOf('<') != -1 || packageName.indexOf('>') != -1 |
| || packageName.indexOf('=') != -1) { |
| updateStatus(Messages.SpecfileNewWizardPage_26 + Messages.SpecfileNewWizardPage_27); |
| return; |
| } |
| |
| if (versionText.getText().indexOf("-") > -1) { //$NON-NLS-1$ |
| updateStatus(Messages.SpecfileNewWizardPage_28); |
| return; |
| } |
| |
| updateStatus(null); |
| } |
| |
| protected void updateStatus(String message) { |
| setErrorMessage(message); |
| setPageComplete(message == null); |
| } |
| |
| private void setDefaultValues() { |
| nameText.setText(NAME); |
| versionText.setText(VERSION); |
| summaryText.setText(SUMMARY); |
| groupCombo.setText(GROUP); |
| licenseText.setText(LICENSE); |
| urlText.setText(URL); |
| source0Text.setText(SOURCE0); |
| } |
| |
| private void populateTemplateCombo(Combo templateCombo) throws CoreException { |
| // get a list of all files in a directory |
| File dir = new File("/etc/rpmdevtools"); //$NON-NLS-1$ |
| String[] files = dir.list(); |
| if (dir.exists()) { |
| String templateCSV = ""; //$NON-NLS-1$ |
| for (String file : files) { |
| if (file.startsWith("spectemplate-")) { //$NON-NLS-1$ |
| templateCSV += file.split("-", 2)[1].replace(".spec", //$NON-NLS-1$ //$NON-NLS-2$ |
| "") //$NON-NLS-1$ |
| + ","; //$NON-NLS-1$ |
| } |
| } |
| String[] templates = templateCSV.split(","); //$NON-NLS-1$ |
| for (String template : templates) { |
| templateCombo.add(template); |
| } |
| templateCombo.setText(selectedTemplate); |
| } else { |
| throwCoreException(Messages.SpecfileNewWizardPage_29); |
| } |
| } |
| |
| private void populateGroupCombo(Combo groupsCombo) { |
| List<String> rpmGroups = Activator.getDefault().getRpmGroups(); |
| for (String rpmGroup : rpmGroups) { |
| groupsCombo.add(rpmGroup); |
| } |
| } |
| |
| private BufferedInputStream runRpmdevNewSpec(String template) { |
| BufferedInputStream in = null; |
| // Here we assuming that the rpmdevtools package is installed. |
| try { |
| in = org.eclipse.linuxtools.rpm.core.utils.Utils.runCommandToInputStream("rpmdev-newspec", "-o", "-", "-t", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| template); |
| } catch (IOException e) { |
| // FIXME: rpmdev-newspec is not in the system $PATH, what should we |
| // do here?. |
| SpecfileLog.logError(e); |
| } |
| return in; |
| } |
| |
| private void throwCoreException(String message) throws CoreException { |
| IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.OK, message, null); |
| throw new CoreException(status); |
| } |
| |
| public Text getNameText() { |
| return nameText; |
| } |
| |
| public Text getProjectText() { |
| return projectText; |
| } |
| |
| public Text getVersionText() { |
| return versionText; |
| } |
| |
| public Text getUrlText() { |
| return urlText; |
| } |
| |
| public Text getLicenseText() { |
| return licenseText; |
| } |
| |
| public Text getSourceText() { |
| return source0Text; |
| } |
| |
| public Text getSummaryText() { |
| return summaryText; |
| } |
| |
| } |