Repository: conda/conda-build

Issue:
ENH: skeleton --version-compare for latest versions
a naieve `--version-compare` routine in `skeleton` would make comparing recipe version metadata with e.g. PyPI version metadata more simple

seeAlso: https://github.com/conda/conda-recipes/issues/291

potentially: UBY (usability), SEC (security) due to packaging latency



Discussion:
I don't understand what is being requested here.

As a package maintainer / package installer, when I need to review whether there are new versions (to be re-templated and diff'd) I must manually go to e.g. https://pypi.python.org/pypi/conda to check the version.

I believe the `conda skeleton` utilities should already have scraping / parsing logic for the the version field.

Oh, I see. So what is really needed are some better features for dealing with updates for packages. @hargup, this is related to the work you are doing. 


Resolving patch:
diff --git a/conda_build/main_skeleton.py b/conda_build/main_skeleton.py
--- a/conda_build/main_skeleton.py
+++ b/conda_build/main_skeleton.py
@@ -86,6 +86,12 @@ def main():
         action='store_true',
         help='Create recipes for dependencies if they do not already exist.'
     )
+    pypi.add_argument(
+        "--version-compare",
+        action='store_true',
+        help='Compare the package version of the recipe with the one available'
+        'on PyPI'
+        )
     pypi.add_argument(
         "--python-version",
         action='store',
diff --git a/conda_build/pypi.py b/conda_build/pypi.py
--- a/conda_build/pypi.py
+++ b/conda_build/pypi.py
@@ -264,7 +264,7 @@ def main(args, parser):
 
         if not is_url:
             dir_path = join(output_dir, package.lower())
-            if exists(dir_path):
+            if exists(dir_path) and not args.version_compare:
                 raise RuntimeError("directory already exists: %s" % dir_path)
         d = package_dicts.setdefault(package,
             {
@@ -287,15 +287,16 @@ def main(args, parser):
         if is_url:
             d['version'] = 'UNKNOWN'
         else:
+            versions = client.package_releases(package, True)
+            if args.version_compare:
+                version_compare(args, package, versions)
             if args.version:
                 [version] = args.version
-                versions = client.package_releases(package, True)
                 if version not in versions:
                     sys.exit("Error: Version %s of %s is not available on PyPI."
                              % (version, package))
                 d['version'] = version
             else:
-                versions = client.package_releases(package)
                 if not versions:
                     # The xmlrpc interface is case sensitive, but the index itself
                     # is apparently not (the last time I checked,
@@ -403,6 +404,41 @@ def main(args, parser):
 
     print("Done")
 
+
+def version_compare(args, package, versions):
+    if not versions:
+        # PyPI is case sensitive, this will pass control
+        # to a method in main() to take care of that.
+        return
+
+    from os.path import abspath, isdir
+    from conda_build.metadata import MetaData
+    from conda.resolve import normalized_version
+    nv = normalized_version
+
+    norm_versions = [nv(ver) for ver in versions]
+
+    recipe_dir = abspath(package.lower())
+    if not isdir(recipe_dir):
+        sys.exit("Error: no such directory: %s" % recipe_dir)
+    m = MetaData(recipe_dir)
+    local_version = nv(m.version())
+    print("Local recipe for %s has version %s" % (package, local_version))
+    if local_version not in versions:
+        sys.exit("Error: %s %s is not available on PyPI."
+                 % (package, local_version))
+    else:
+        # Comparing normalized versions, displaying non normalized ones
+        new_versions = versions[:norm_versions.index(local_version)]
+        if len(new_versions) > 0:
+            print("Following new versions of %s are avaliable" % (package))
+            for ver in new_versions:
+                print(ver)
+        else:
+            print("No new version for %s is available" % (package))
+        sys.exit()
+
+
 def get_package_metadata(args, package, d, data):
     # Unfortunately, two important pieces of metadata are only stored in
     # the package itself: the dependencies, and the entry points (if the


Test patch: