aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Guzman2013-07-11 14:17:48 (EDT)
committerAlexander Kurtakov2013-07-31 11:16:56 (EDT)
commit73e5e28fc1f81ee33925f096d512a9da6058c7ab (patch)
tree66b4bf112ec595c0637dba8df01269f80acdd027
parent1f3d1aefa5c3d54f490799a1874f1d7990986aa8 (diff)
downloadorg.eclipse.linuxtools-73e5e28fc1f81ee33925f096d512a9da6058c7ab.zip
org.eclipse.linuxtools-73e5e28fc1f81ee33925f096d512a9da6058c7ab.tar.gz
org.eclipse.linuxtools-73e5e28fc1f81ee33925f096d512a9da6058c7ab.tar.bz2
RPMStubby: Python Egg template B#350065refs/changes/94/14594/8
Simple parser to parse a setup.py for its setup properties to be put into a python specfile template. Todo: o support triple quotations Amend: o added javadoc o fixed case of setup(...) function being 1 line o handles empty files o handles incorrect setup(...) function o added StubbyLog.logError in catch statements o added as popup action when right-clicking setup.py files o ignore function calls, clean up returned value Change-Id: Ie740144d8dca55ebde547d4677daa3418347deea Signed-off-by: Neil Guzman <nguzman@redhat.com> Reviewed-on: https://git.eclipse.org/r/14594 Tested-by: Hudson CI Reviewed-by: Alexander Kurtakov <akurtako@redhat.com> IP-Clean: Alexander Kurtakov <akurtako@redhat.com> Tested-by: Alexander Kurtakov <akurtako@redhat.com>
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/plugin.xml30
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/StubbyEggGenerator.java200
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/model/EggModel.java226
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/CommonMetaData.java24
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/PythonEggParser.java382
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/ValidLicenses.java39
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/popup/actions/StubifyEggHandler.java26
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/Generator.java7
-rw-r--r--rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/InputType.java7
9 files changed, 937 insertions, 4 deletions
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/plugin.xml b/rpmstubby/org.eclipse.linuxtools.rpmstubby/plugin.xml
index 44fe5ef..d3ee769 100644
--- a/rpmstubby/org.eclipse.linuxtools.rpmstubby/plugin.xml
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<!--
- Copyright (c) 2009 Red Hat, Inc. All rights reserved. This program and
+ Copyright (c) 2013 Red Hat, Inc. 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
@@ -30,6 +30,12 @@
description="%action.label"
name="%action.label">
</command>
+ <command
+ categoryId="rpmstubby.commands"
+ description="%action.label"
+ id="rpmstubby.stubifyEgg"
+ name="%action.label">
+ </command>
</extension>
<extension
@@ -42,6 +48,10 @@
class="org.eclipse.linuxtools.internal.rpmstubby.popup.actions.StubifyPomHandler"
commandId="rpmstubby.stubifyPom">
</handler>
+ <handler
+ class="org.eclipse.linuxtools.internal.rpmstubby.popup.actions.StubifyEggHandler"
+ commandId="rpmstubby.stubifyEgg">
+ </handler>
</extension>
<extension
point="org.eclipse.ui.menus">
@@ -83,6 +93,24 @@
</with>
</visibleWhen>
</command>
+ <command
+ commandId="rpmstubby.stubifyEgg">
+ <visibleWhen>
+ <with
+ variable="selection">
+ <iterate
+ ifEmpty="false">
+ <adapt
+ type="org.eclipse.core.resources.IResource">
+ <test
+ property="org.eclipse.core.resources.name"
+ value="setup.py">
+ </test>
+ </adapt>
+ </iterate>
+ </with>
+ </visibleWhen>
+ </command>
</menuContribution>
</extension>
</plugin>
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/StubbyEggGenerator.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/StubbyEggGenerator.java
new file mode 100644
index 0000000..f8e26a6
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/StubbyEggGenerator.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.linuxtools.internal.rpmstubby.model.EggModel;
+
+/**
+ * Generator for RPM specfile from python setup.py.
+ *
+ */
+public class StubbyEggGenerator extends AbstractGenerator {
+
+ private EggModel model;
+
+ /**
+ * Creates the generator by parsing the setup.py file.
+ *
+ * @param eggFile
+ * The setup.py file to generate specfile for.
+ */
+ public StubbyEggGenerator(IFile eggFile) {
+ parse(eggFile);
+ specfileName = model.getPackageName().toLowerCase() + ".spec";
+ projectName = eggFile.getProject().getName();
+ }
+
+ /**
+ * Creates the model which contains the information
+ *
+ * @param eggFile The setup.py file
+ */
+ private void parse(IFile eggFile) {
+ model = new EggModel(eggFile);
+ }
+
+ /**
+ * Generates a RPM specfile based on the parsed data from the setup.py file.
+ *
+ * @return The generated specfile.
+ */
+ @Override
+ public String generateSpecfile() {
+ StringBuilder buffer = new StringBuilder();
+ generateSiteLibSiteArch(buffer);
+ String packageName = model.getPackageName();
+ buffer.append("Name: " + packageName.toLowerCase() + "\n");
+ buffer.append("Version: " + model.getVersion() + "\n");
+ buffer.append("Release: 1%{?dist}" + "\n");
+ buffer.append("Summary: " + model.getSummary() + "\n\n");
+
+ buffer.append("Group: Development/Libraries\n");
+ buffer.append("License: " + model.getLicense() + "\n");
+ buffer.append("URL: " + model.getURL() + "\n");
+ buffer.append("Source0: #FIXME\n\n");
+
+ buffer.append("BuildArch: noarch\n");
+ generateRequires(buffer);
+ buffer.append("\n%description\n" + model.getDescription() + "\n\n");
+
+ generatePython3SubPackage(buffer);
+ generatePrepSection(buffer);
+ generateBuildSection(buffer);
+ generateInstallSection(buffer);
+ generateFilesSections(buffer);
+ generateChangelog(buffer);
+
+ return buffer.toString();
+ }
+
+ /**
+ * Generate python_sitelib depending on fedora release and srcname of package
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateSiteLibSiteArch(StringBuilder buffer) {
+ buffer.append("%if 0%{?fedora} > 12\n");
+ buffer.append("%global with_python3 1\n");
+ buffer.append("%else\n");
+ buffer.append("%{!?python_sitelib: %global python_sitelib %(%{__python} -c \"from distutils.sysconfig import get_python_lib; print (get_python_lib())\")}\n");
+ buffer.append("%endif\n\n");
+ buffer.append("%global srcname " + model.getPackageName().toLowerCase() +"\n\n");
+ }
+
+ /**
+ * Generate requires
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateRequires(StringBuilder buffer) {
+ buffer.append("BuildRequires: python2-devel\n");
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("BuildRequires: python3-devel\n");
+ buffer.append("%endif # if with_python3\n\n");
+
+ List<String> requireList = model.getInstallRequiresList();
+ for (String require : requireList) {
+ buffer.append("Requires: " + require + "\n");
+ }
+ }
+
+ /**
+ * Generate the python 3 subpackage
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generatePython3SubPackage(StringBuilder buffer) {
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("%package -n python3-" + model.getPackageName().toLowerCase() + "\n\n");
+
+ buffer.append("Summary: " + model.getSummary() + "\n");
+ buffer.append("Group: Development/Libraries\n");
+
+ buffer.append("\n%description -n python3-" + model.getPackageName().toLowerCase() + "\n" + model.getDescription() + "\n");
+ buffer.append("%endif # with_python3\n\n");
+ }
+
+ /**
+ * Generate prep
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generatePrepSection(StringBuilder buffer) {
+ buffer.append("\n%prep\n");
+ buffer.append("%setup -q -n %{srcname}-%{version} #You may need to update this according to your Source0\n\n");
+
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("rm -rf %{py3dir}\n");
+ buffer.append("cp -a . %{py3dir}\n");
+ buffer.append("%endif # with_python3\n\n\n");
+ }
+
+ /**
+ * Generate build
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateBuildSection(StringBuilder buffer) {
+ buffer.append("%build\n");
+ buffer.append("%{__python} setup.py build\n\n");
+
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("pushd %{py3dir}\n");
+ buffer.append("%{__python3} setup.py build\n");
+ buffer.append("popd\n");
+ buffer.append("%endif # with_python3\n\n\n");
+ }
+
+ /**
+ * Generate install
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateInstallSection(StringBuilder buffer) {
+ buffer.append("%install\n");
+
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("pushd %{py3dir}\n");
+ buffer.append("%{__python3} setup.py install --skip-build --root %{buildroot}\n");
+ buffer.append("popd\n");
+ buffer.append("%endif # with_python3\n\n");
+
+ buffer.append("%{__python} setup.py install --skip-build --root %{buildroot}\n\n\n");
+ }
+
+ /**
+ * Generate files
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateFilesSections(StringBuilder buffer) {
+ buffer.append("%files\n");
+ buffer.append("%{python_sitelib}/*\n\n");
+
+ buffer.append("%if 0%{?with_python3}\n");
+ buffer.append("%files -n python3-" + model.getPackageName().toLowerCase() +"\n");
+ buffer.append("%{python3_sitelib}/*\n");
+ buffer.append("%endif # with_python3\n\n\n");
+ }
+
+ /**
+ * Generate changelog
+ *
+ * @param buffer Buffer to write content to
+ */
+ private void generateChangelog(StringBuilder buffer) {
+ buffer.append("%changelog\n");
+ buffer.append("#FIXME\n");
+ }
+} \ No newline at end of file
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/model/EggModel.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/model/EggModel.java
new file mode 100644
index 0000000..e036513
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/model/EggModel.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby.model;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.linuxtools.internal.rpmstubby.StubbyLog;
+import org.eclipse.linuxtools.internal.rpmstubby.parser.CommonMetaData;
+import org.eclipse.linuxtools.internal.rpmstubby.parser.PythonEggParser;
+import org.eclipse.linuxtools.internal.rpmstubby.parser.ValidLicenses;
+
+/**
+ * Gives easy access to data from the python setup.py file.
+ *
+ */
+public class EggModel {
+
+ private static final String[] validLicenses = {
+ ValidLicenses.GPL,
+ ValidLicenses.ARTISTIC,
+ ValidLicenses.MIT,
+ ValidLicenses.APACHE,
+ ValidLicenses.PUBLIC_DOMAIN,
+ ValidLicenses.ZLIB,
+ ValidLicenses.RICOH_SOURCE_CODE,
+ ValidLicenses.VOVIDA_SOFTWARE,
+ ValidLicenses.INTEL_OPEN_SOURCE,
+ ValidLicenses.LGPL,
+ ValidLicenses.BSD,
+ ValidLicenses.QPL,
+ ValidLicenses.IBM_PUBLIC,
+ ValidLicenses.PHP,
+ ValidLicenses.MODIFIED_CNRI_OPEN_SOURCE,
+ ValidLicenses.CVW,
+ ValidLicenses.PYTHON,
+ ValidLicenses.SUN_INTERNET_STANDARDS_SOURCE,
+ ValidLicenses.JABBER_OPEN_SOURCE
+ };
+
+ private static final String LONG_DESCRIPTION = "long_description";
+ private static final String CLASSIFIERS = "classifiers";
+ private static final String INSTALL_REQUIRES = "install_requires";
+
+ private static final String FIX_ME = "#FIXME";
+
+ private PythonEggParser pyEggParser;
+
+ /**
+ * Python egg setup.py file
+ *
+ * @param file The Python setup.py file
+ */
+ public EggModel(IFile file) {
+ try {
+ pyEggParser = new PythonEggParser(file);
+ } catch (IOException e) {
+ StubbyLog.logError(e);
+ } catch (CoreException e) {
+ StubbyLog.logError(e);
+ }
+ }
+
+ /**
+ * Get the value from one of the setup options.
+ * If the value is empty, it will return #FIXME
+ * It will also return #FIX_ME if it looks like a function
+ *
+ * @param option The option from the setup(...) function to get value of
+ * @return The value of the option
+ */
+ private String getValue(String option) {
+ String str = pyEggParser.getValue(option);
+
+ if (str.isEmpty() || pyEggParser.checkFunction(str)) {
+ str = FIX_ME;
+ }
+
+ return str;
+ }
+
+ /**
+ * Get the list of values from one of the setup options
+ * that stores a list of strings
+ *
+ * @param option The option from the setup(...) function to get value of
+ * @return The list of values of the option
+ */
+ private List<String> getValueList(String option) {
+ return pyEggParser.getValueList(option);
+ }
+
+ /**
+ * Get the values from the classifiers option and
+ * check to see if the keyword is in one of them
+ *
+ * @param keyword What to check for within the list of values in classifiers
+ * @return The value within classifiers that contains the keyword
+ */
+ private String getClassifiersList(String keyword) {
+ String rc = "";
+ List<String> list = getValueList(CLASSIFIERS);
+
+ for (String str : list) {
+ if (str.toLowerCase().contains(keyword)) {
+ rc = str;
+ }
+ }
+
+ return rc;
+ }
+
+ /**
+ * Get the values from the install_requires option
+ *
+ * @return The values within install_requires
+ */
+ public List<String> getInstallRequiresList() {
+ return getValueList(INSTALL_REQUIRES);
+ }
+
+ /**
+ * Returns the package name.
+ *
+ * @return The package name.
+ */
+ public String getSimplePackageName() {
+ return getValue(CommonMetaData.NAME);
+ }
+
+ /**
+ * The simple package name with "eclipse-" prepended to make better RPM package name.
+ *
+ * @return The package
+ */
+ public String getPackageName() {
+ return "eclipse-"+getSimplePackageName();
+ }
+
+ /**
+ * Returns the version as retrieved by /feature/@version xpath with .qualifier removed if any.
+ *
+ * @return The version of the feature.
+ */
+ public String getVersion() {
+ String version = getValue(CommonMetaData.VERSION);
+
+ if (!hasDigits(version)) {
+ version = "1 " + FIX_ME;
+ }
+
+ return version;
+ }
+
+ /**
+ * Utitlity method to try and see if a string contains
+ * digits within it
+ *
+ * @param str The string to check if it has digits
+ * @return True if string contains digits
+ */
+ public boolean hasDigits(String str) {
+ return str.matches(".*\\d.*");
+ }
+
+ /**
+ * Returns the summary
+ *
+ * @return The package summary
+ */
+ public String getSummary() {
+ return getValue(LONG_DESCRIPTION);
+ }
+
+ /**
+ * Returns the license
+ *
+ * @return The license
+ */
+ public String getLicense() {
+ String rawLicense = getClassifiersList(CommonMetaData.LICENSE).toLowerCase();
+ String license = "";
+
+ for (String valid : validLicenses) {
+ if (rawLicense.contains(valid.toLowerCase())) {
+ license += valid + ", ";
+ }
+ }
+
+ if (!license.isEmpty()) {
+ license = license.substring(0, license.length()-2);
+ } else {
+ license = FIX_ME;
+ }
+
+ return license;
+ }
+
+ /**
+ * Returns the url
+ *
+ * @return The url
+ */
+ public String getURL() {
+ return getValue(CommonMetaData.URL);
+ }
+
+ /**
+ * Returns the description
+ *
+ * @return The description
+ */
+ public String getDescription() {
+ return getValue(CommonMetaData.DESCRIPTION);
+ }
+}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/CommonMetaData.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/CommonMetaData.java
new file mode 100644
index 0000000..5ebc57e
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/CommonMetaData.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby.parser;
+
+/**
+ * Meta-Data tags common within the files
+ *
+ */
+@SuppressWarnings("javadoc")
+public interface CommonMetaData {
+ String NAME = "name";
+ String DESCRIPTION = "description";
+ String VERSION = "version";
+ String LICENSE = "license";
+ String URL = "url";
+}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/PythonEggParser.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/PythonEggParser.java
new file mode 100644
index 0000000..ba2759e
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/PythonEggParser.java
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby.parser;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.linuxtools.internal.rpmstubby.StubbyLog;
+
+/**
+ * Class to parse a Python setup.py to grab specfile properties
+ *
+ */
+public class PythonEggParser {
+
+ private Map<String, String> variables;
+ private Map<String, String> setupOptions;
+ private IFile file;
+
+ /**
+ * Initialize and then parse the file
+ *
+ * @param file The Python setup.py file
+ * @throws CoreException Throws CoreException
+ * @throws IOException Throws IOException
+ */
+ public PythonEggParser(IFile file) throws IOException, CoreException {
+ setupOptions = new HashMap<String, String>();
+ variables = new HashMap<String, String>();
+ // end if file is empty or cannot get its contents
+ if (file.getContents().available() <= 0) {
+ return;
+ }
+ this.file = file;
+ parse();
+ }
+
+ /**
+ * Parse the contents of the Python setup.py file and grab
+ * variables and meta-data from the setup(...) function
+ *
+ */
+ public void parse() {
+ String line = "";
+ String setupLine = "";
+ List<String> vars = new ArrayList<String>();
+ List<String> list = new ArrayList<String>();
+ int offset = 0;
+ try {
+ RandomAccessFile raf = new RandomAccessFile(file.getRawLocation().makeAbsolute().toFile(), "r");
+
+ // end if cannot find setup(
+ long bytesToSkip = findStartSetup(raf);
+ if (bytesToSkip == -1) {
+ return;
+ }
+
+ // end if the end of setup cannot be found
+ long stop = findEndSetup(raf, bytesToSkip);
+ if (stop == -1) {
+ return;
+ }
+
+ raf.seek(0);
+ while ((line = raf.readLine()) != null) {
+ if (!line.trim().startsWith("#")) {
+ if (isLineSimpleDefinition(line)) {
+ vars.add(line);
+ } else if (!vars.isEmpty() && vars.get(vars.size()-1).trim().endsWith("\\") && isLineContinuation(line)){
+ offset = vars.get(vars.size()-1).lastIndexOf('\\');
+ vars.set(vars.size() -1, vars.get(vars.size() - 1).substring(0, offset));
+ vars.set(vars.size() - 1, vars.get(vars.size() - 1)
+ .concat(line.trim()));
+ }
+ }
+ }
+
+ raf.seek(bytesToSkip);
+ while ((line = raf.readLine()) != null && raf.getFilePointer() <= stop) {
+ line = line.trim();
+ if (!line.startsWith("#")) {
+ if (setupLine.equals("")) {
+ setupLine = line.trim();
+ } else {
+ setupLine = setupLine.concat(line.trim());
+ }
+ }
+ }
+
+ list = prepareSetupOptions(setupLine);
+
+ for (String str : vars) {
+ variables.putAll(parseLine(str));
+ }
+
+ for (String str : list) {
+ setupOptions.putAll(parseLine(str));
+ }
+
+ resolveVariables(variables, setupOptions);
+
+ raf.close();
+ } catch (FileNotFoundException e) {
+ StubbyLog.logError(e);
+ } catch (IOException e) {
+ StubbyLog.logError(e);
+ }
+ }
+
+ /**
+ * Check to see if the string passed in is a function
+ *
+ * @param str The string to check
+ * @return True if the string matches the function regex
+ */
+ public boolean checkFunction(String str) {
+ boolean rc = false;
+ Pattern pattern = Pattern.compile("\\s*\\w*\\s*?\\(.*\\)\\s*");
+ Matcher variableMatcher = pattern.matcher(str);
+
+ if (variableMatcher.matches()) {
+ rc = true;
+ }
+
+ return rc;
+ }
+
+ /**
+ * Get the value of the variable
+ *
+ * @param key The variable to get the value of
+ * @return The value of the variable
+ */
+ public String getValue(String key) {
+ String rc = "";
+ Pattern pattern = Pattern.compile("\\s*\\((.+)\\)\\s*");
+ Matcher variableMatcher = null;
+
+ if (setupOptions.containsKey(key)) {
+ rc = setupOptions.get(key).replaceAll("('|\")", "").trim();
+ variableMatcher = pattern.matcher(rc);
+ if (variableMatcher.matches()) {
+ rc = variableMatcher.group(1);
+ }
+ }
+
+ return rc;
+ }
+
+ /**
+ * Get the list of strings for a key.
+ * Use with classifiers, platforms, install_requires, etc.
+ *
+ * @param key The variable to get the value of
+ * @return The value of the variable
+ */
+ public List<String> getValueList(String key) {
+ List<String> rc = new ArrayList<String>();
+ Pattern pattern = Pattern.compile("^\\[(.*)\\]");
+ String[] temp = {};
+
+ if (setupOptions.containsKey(key)) {
+ Matcher variableMatcher = pattern.matcher(setupOptions.get(key).trim());
+ if (variableMatcher.find()) {
+ temp = variableMatcher.group(1).replaceAll("('|\")", "").split(",");
+ for (String str : temp) {
+ if (!str.isEmpty() && !str.trim().startsWith("#")) {
+ rc.add(str.trim());
+ }
+ }
+ }
+ }
+
+ return rc;
+ }
+
+ /**
+ * Prepare the setup options by returning each comma delimited option
+ *
+ * @param setupLine The single string containing all the setup options
+ * @return A list of setup options
+ */
+ private static List<String> prepareSetupOptions(String setupLine) {
+ List<String> rc = new ArrayList<String>();
+ String[] tempList = {};
+ // match the setup(...) pattern
+ Pattern pattern = Pattern.compile("\\bsetup\\b(\\s+)?\\((.*)\\)");
+ Matcher variableMatcher = pattern.matcher(setupLine);
+
+ if (variableMatcher.find()) {
+ setupLine = variableMatcher.group(2);
+ }
+
+ tempList = setupLine.split("(?=,)");
+
+ for (String str : tempList) {
+ if (isOptionLineKeyValuePair(str) && !str.trim().startsWith("#")) {
+ if (str.startsWith(",")) {
+ str = str.substring(1, str.length()).trim();
+ }
+ rc.add(str);
+ } else if (!str.trim().startsWith("#") && !rc.isEmpty()) {
+ rc.set(rc.size() - 1, rc.get(rc.size() - 1).concat(str.trim()));
+ }
+ }
+
+ return rc;
+ }
+
+ /**
+ * Resolves the setup option variables if they are referencing a
+ * define from outside the setup() function.
+ *
+ * @param variables The variables outside the setup() function
+ * @param options The options to be resolved within the setup() function
+ */
+ private static void resolveVariables(Map<String, String> variables, Map<String, String> options) {
+ for (String key : options.keySet()) {
+ if (variables.containsKey(options.get(key))) {
+ options.put(key, variables.get(options.get(key)));
+ }
+ }
+ }
+
+ /**
+ * Check to see if the line in setup option is a new key->value pair
+ *
+ * @param line Line to check
+ * @return True if the line contains a key->value
+ */
+ private static boolean isOptionLineKeyValuePair(String line) {
+ boolean rc = false;
+ Pattern pattern = Pattern.compile("(\\w+)(\\s+)?=[^=].*");
+ Matcher variableMatcher = pattern.matcher(line.toLowerCase());
+
+ if (variableMatcher.find()) {
+ rc = true;
+ }
+
+ return rc;
+ }
+
+ /**
+ * Check to see if the line is a simple variable declaration (var=value)
+ *
+ * @param line Line to check
+ * @return True if it is a simple variable declaration
+ */
+ private static boolean isLineSimpleDefinition(String line) {
+ boolean rc = false;
+ Pattern pattern = Pattern.compile("^(\\w+)(\\s+)?=(\\s+)?");
+ Matcher variableMatcher = pattern.matcher(line.toLowerCase());
+
+ if (variableMatcher.find()) {
+ rc = true;
+ }
+
+ return rc;
+ }
+
+ /**
+ * Check to see if the line is a continuation from the previous.
+ * It is a continuation from the previous if it starts
+ * with a ' or "
+ *
+ * @param line Line to check
+ * @return True if the line is a continuation
+ */
+ private static boolean isLineContinuation(String line) {
+ boolean rc = false;
+ Pattern pattern = Pattern.compile(".*[\'\"](/s+)?$");
+ Matcher variableMatcher = pattern.matcher(line.toLowerCase());
+
+ if (variableMatcher.find()) {
+ rc = true;
+ }
+
+ return rc;
+ }
+
+ /**
+ * Parse the line and split it into a key->value pair
+ *
+ * @param line The line to be parsed
+ * @return The map containing the key->value pair
+ */
+ private static Map<String, String> parseLine(String line) {
+ Map<String, String> rc = new HashMap<String, String>();
+ Pattern pattern = Pattern.compile("(\\s+)?(\\w+)(\\s+)?=(\\s+)?(.*)");
+ Matcher variableMatcher = pattern.matcher(line);
+
+ if (variableMatcher.find()) {
+ String value = variableMatcher.group(5);
+ if (value.charAt(value.length()-1) == ',') {
+ value = value.substring(0, value.length()-1);
+ }
+ rc.put(variableMatcher.group(2), value);
+ }
+
+ return rc;
+ }
+
+ /**
+ * Find the offset of when setup(...) starts
+ *
+ * @param reader The file reader
+ * @return The position of the start of setup(...
+ * @throws IOException
+ */
+ private static long findStartSetup(RandomAccessFile reader) throws IOException {
+ long rc = -1;
+ long previous = 0;
+ Pattern pattern = Pattern.compile("^\\bsetup\\b(\\s+)?(\\()?");
+ Matcher variableMatcher = null;
+ String line = "";
+
+ reader.seek(0);
+ while ((line = reader.readLine()) != null && rc == -1) {
+ variableMatcher = pattern.matcher(line.toLowerCase());
+ if (variableMatcher.find()) {
+ // get the previous line's file pointer location
+ rc = previous;
+ }
+ previous = reader.getFilePointer();
+ }
+
+ return rc;
+ }
+
+ /**
+ * Find the offset of when setup(...) ends based on the
+ * position AFTER the closing bracket of setup()
+ *
+ * @param reader The file reader
+ * @param startPosition The position of the start of setup(...
+ * @return The position of the end of setup ...)
+ * @throws IOException
+ */
+ private static long findEndSetup(RandomAccessFile reader, long startPosition) throws IOException {
+ int bracketCounter = 0;
+ boolean flag = false;
+ boolean stop = false;
+ String line = "";
+
+ reader.seek(startPosition);
+ while ((line = reader.readLine()) != null && stop == false) {
+ for (char x : line.toCharArray()) {
+ if (x == '(') {
+ bracketCounter++;
+ } else if (x == ')') {
+ bracketCounter--;
+ }
+ if (flag && bracketCounter == 0) {
+ stop = true;
+ }
+ // prevent ending prematurely
+ if (bracketCounter != 0) {
+ flag = true;
+ }
+ }
+ }
+
+ return reader.getFilePointer();
+ }
+}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/ValidLicenses.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/ValidLicenses.java
new file mode 100644
index 0000000..e6cce52
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/parser/ValidLicenses.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby.parser;
+
+/**
+ * Licenses that are valid for RPM
+ *
+ */
+@SuppressWarnings("javadoc")
+public interface ValidLicenses {
+ String GPL = "GPL";
+ String ARTISTIC = "Artistic";
+ String MIT = "MIT";
+ String MPL = "MPL";
+ String APACHE = "Apache";
+ String PUBLIC_DOMAIN = "Public";
+ String ZLIB = "zlib";
+ String RICOH_SOURCE_CODE = "Ricoh";
+ String VOVIDA_SOFTWARE = "Vovida";
+ String INTEL_OPEN_SOURCE = "Intel";
+ String LGPL = "LGPL";
+ String BSD = "BSD";
+ String QPL = "QPL";
+ String IBM_PUBLIC = "IBM";
+ String PHP = "PHP";
+ String MODIFIED_CNRI_OPEN_SOURCE = "CNRI";
+ String CVW = "CVW";
+ String PYTHON = "Python";
+ String SUN_INTERNET_STANDARDS_SOURCE = "Sun";
+ String JABBER_OPEN_SOURCE = "Jabber";
+}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/popup/actions/StubifyEggHandler.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/popup/actions/StubifyEggHandler.java
new file mode 100644
index 0000000..9f36bde
--- /dev/null
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/internal/rpmstubby/popup/actions/StubifyEggHandler.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Neil Guzman - python implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.rpmstubby.popup.actions;
+
+import org.eclipse.linuxtools.rpmstubby.InputType;
+
+/**
+ * Handler for the setup.py stubify command.
+ *
+ */
+public class StubifyEggHandler extends StubifyHandler {
+
+ @Override
+ protected InputType getInputType() {
+ return InputType.PYTHON_EGG;
+ }
+
+}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/Generator.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/Generator.java
index 13aa7c4..f5737b7 100644
--- a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/Generator.java
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/Generator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 Red Hat Inc. and others.
+ * Copyright (c) 2013 Red Hat Inc. 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
@@ -7,11 +7,13 @@
*
* Contributors:
* Alexander Kurtakov - initial API and implementation
+ * Neil Guzman - python implementation
*******************************************************************************/
package org.eclipse.linuxtools.rpmstubby;
import org.eclipse.core.resources.IFile;
+import org.eclipse.linuxtools.internal.rpmstubby.StubbyEggGenerator;
import org.eclipse.linuxtools.internal.rpmstubby.StubbyGenerator;
import org.eclipse.linuxtools.internal.rpmstubby.StubbyPomGenerator;
@@ -47,6 +49,9 @@ public class Generator {
case MAVEN_POM:
new StubbyPomGenerator(file).writeContent();
break;
+ case PYTHON_EGG:
+ new StubbyEggGenerator(file).writeContent();
+ break;
default:
break;
}
diff --git a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/InputType.java b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/InputType.java
index 9c38351..6a174cf 100644
--- a/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/InputType.java
+++ b/rpmstubby/org.eclipse.linuxtools.rpmstubby/src/org/eclipse/linuxtools/rpmstubby/InputType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 Red Hat, Inc.
+ * Copyright (c) 2013 Red Hat, Inc.
* 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Alexander Kurtakov - initial API and implementation
+ * Neil Guzman - python implementation
*******************************************************************************/
package org.eclipse.linuxtools.rpmstubby;
@@ -20,7 +21,9 @@ public enum InputType {
/** Eclipse feature.xml file. */
ECLIPSE_FEATURE("feature.xml"),
/** Maven pom.xml file. */
- MAVEN_POM("pom.xml");
+ MAVEN_POM("pom.xml"),
+ /** Python Egg setup.py file */
+ PYTHON_EGG("setup.py");
private String fileNamePattern;