From 92b08995467f7545fb7c15fd675441c13d5a0675 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Thu, 31 Mar 2016 18:28:03 +0300 Subject: [PATCH] PY-18405 Version of devpi package is always latest --- .../python/packaging/PyPIPackageUtil.java | 73 +++++++++++++++++-- .../ui/PyPackageManagementService.java | 4 + 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java index e9a0f4fef32d..758a42ed816c 100644 --- a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java @@ -65,7 +65,7 @@ public class PyPIPackageUtil { private XmlRpcClient myXmlRpcClient; private Map packageToDetails = new HashMap(); - private Map> packageToReleases = new HashMap>(); + private static Map> packageToReleases = new HashMap>(); private Pattern PYPI_PATTERN = Pattern.compile("/pypi/([^/]*)/(.*)"); private static Set ourAdditionalPackageNames = new TreeSet(); @Nullable private volatile Set myPackageNames = null; @@ -98,9 +98,9 @@ public class PyPIPackageUtil { @NotNull private static Pair splitNameVersion(@NotNull final String pyPackage) { int dashInd = pyPackage.lastIndexOf("-"); - if (dashInd >= 0) { + if (dashInd >= 0 && dashInd+1 < pyPackage.length()) { final String name = pyPackage.substring(0, dashInd); - final String version = pyPackage.substring(dashInd); + final String version = pyPackage.substring(dashInd+1); if (StringUtil.containsAlphaCharacters(version)) { return Pair.create(pyPackage, null); } @@ -170,7 +170,14 @@ public class PyPIPackageUtil { final Vector params = new Vector(); params.add(packageName); try { - params.add(getPyPIPackages().get(packageName)); + String version = getPyPIPackages().get(packageName); + if (version == null) { + final List releases = getPackageReleases(packageName); + if (releases != null && !releases.isEmpty()) { + version = releases.get(0); + } + } + params.add(version); myXmlRpcClient.executeAsync("release_data", params, callback); } catch (Exception ignored) { @@ -199,11 +206,65 @@ public class PyPIPackageUtil { } @Nullable - public List getPackageReleases(@NonNls String packageName) { + public static List getPackageReleases(@NonNls String packageName) { if (packageToReleases.containsKey(packageName)) return packageToReleases.get(packageName); + final List repositories = PyPackageService.getInstance().additionalRepositories; + if (!repositories.isEmpty()) { + for (String repository : repositories) { + repository = composeSimpleUrl(packageName, repository); + + final List versions = parsePackageVersions(repository); + if (!versions.isEmpty()) { + packageToReleases.put(packageName, versions); + return versions; + } + } + } return null; } + private static List parsePackageVersions(@NotNull final String repository) { + return HttpRequests.request(repository).connect(new HttpRequests.RequestProcessor>() { + @Override + public List process(@NotNull HttpRequests.Request request) throws IOException { + final List versions = new ArrayList(); + Reader reader = request.getReader(); + new ParserDelegator().parse(reader, new HTMLEditorKit.ParserCallback() { + HTML.Tag myTag; + + @Override + public void handleStartTag(HTML.Tag tag, MutableAttributeSet set, int i) { + myTag = tag; + } + + @Override + public void handleText(char[] data, int pos) { + if (myTag != null && "a".equals(myTag.toString())) { + String packageVersion = String.valueOf(data); + final String suffix = ".tar.gz"; + if (!packageVersion.endsWith(suffix)) return; + packageVersion = StringUtil.trimEnd(packageVersion, suffix); + versions.add(splitNameVersion(packageVersion).second); + } + } + + }, true); + return versions; + } + }, Collections.emptyList(), LOG); + } + + @NotNull + private static String composeSimpleUrl(@NonNls @NotNull final String packageName, @NotNull final String rep) { + String suffix = ""; + final String repository = StringUtil.trimEnd(rep, "/"); + if (!repository.endsWith("+simple")) { + suffix = "/+simple"; + } + suffix += "/" + packageName; + return repository + suffix; + } + private PyPIPackageUtil() { try { DefaultXmlRpcTransportFactory factory = new PyPIXmlRpcTransportFactory(new URL(PYPI_URL)); @@ -286,7 +347,7 @@ public class PyPIPackageUtil { }, true); return packages; } - }, Collections.emptyList(), LOG); + }, Collections.emptyList(), LOG); } public Collection getPackageNames() { diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java index 25d878a42fa0..3c87c8a1a938 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java @@ -399,6 +399,10 @@ public class PyPackageManagementService extends PackageManagementServiceEx { } catch (IOException ignored) { } + final List releases = PyPIPackageUtil.getPackageReleases(pkg.getName()); + if (releases != null && !releases.isEmpty()) { + version = releases.get(0); + } consumer.consume(version); } } \ No newline at end of file