Commands take specs as input instead of names.
modified clean, create, fetch, install, and uninstall
This commit is contained in:
parent
ad4411bc9e
commit
b2a5fef6ad
15 changed files with 265 additions and 180 deletions
|
@ -1,7 +1,9 @@
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
import spack
|
||||
import spack.spec
|
||||
import spack.tty as tty
|
||||
import spack.attr as attr
|
||||
|
||||
|
@ -21,10 +23,6 @@
|
|||
commands.sort()
|
||||
|
||||
|
||||
def null_op(*args):
|
||||
pass
|
||||
|
||||
|
||||
def get_cmd_function_name(name):
|
||||
return name.replace("-", "_")
|
||||
|
||||
|
@ -36,7 +34,7 @@ def get_module(name):
|
|||
module_name, fromlist=[name, SETUP_PARSER, DESCRIPTION],
|
||||
level=0)
|
||||
|
||||
attr.setdefault(module, SETUP_PARSER, null_op)
|
||||
attr.setdefault(module, SETUP_PARSER, lambda *args: None) # null-op
|
||||
attr.setdefault(module, DESCRIPTION, "")
|
||||
|
||||
fn_name = get_cmd_function_name(name)
|
||||
|
@ -50,3 +48,22 @@ def get_module(name):
|
|||
def get_command(name):
|
||||
"""Imports the command's function from a module and returns it."""
|
||||
return getattr(get_module(name), get_cmd_function_name(name))
|
||||
|
||||
|
||||
def parse_specs(args):
|
||||
"""Convenience function for parsing arguments from specs. Handles common
|
||||
exceptions and dies if there are errors.
|
||||
"""
|
||||
if type(args) == list:
|
||||
args = " ".join(args)
|
||||
|
||||
try:
|
||||
return spack.spec.parse(" ".join(args))
|
||||
|
||||
except spack.parse.ParseError, e:
|
||||
e.print_error(sys.stdout)
|
||||
sys.exit(1)
|
||||
|
||||
except spack.spec.SpecError, e:
|
||||
tty.error(e.message)
|
||||
sys.exit(1)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import argparse
|
||||
|
||||
import spack.cmd
|
||||
import spack.packages as packages
|
||||
import spack.tty as tty
|
||||
import spack.stage as stage
|
||||
|
@ -5,21 +8,22 @@
|
|||
description = "Remove staged files for packages"
|
||||
|
||||
def setup_parser(subparser):
|
||||
subparser.add_argument('names', nargs='+', help="name(s) of package(s) to clean")
|
||||
subparser.add_argument('-c', "--clean", action="store_true", dest='clean',
|
||||
help="run make clean in the stage directory (default)")
|
||||
subparser.add_argument('-w', "--work", action="store_true", dest='work',
|
||||
help="delete and re-expand the entire stage directory")
|
||||
subparser.add_argument('-d', "--dist", action="store_true", dest='dist',
|
||||
help="delete the downloaded archive.")
|
||||
subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to clean")
|
||||
|
||||
|
||||
def clean(parser, args):
|
||||
if not args.names:
|
||||
tty.die("spack clean requires at least one package name.")
|
||||
if not args.packages:
|
||||
tty.die("spack clean requires at least one package argument")
|
||||
|
||||
for name in args.names:
|
||||
package = packages.get(name)
|
||||
specs = spack.cmd.parse_specs(args.packages)
|
||||
for spec in specs:
|
||||
package = packages.get(spec.name)
|
||||
if args.dist:
|
||||
package.do_clean_dist()
|
||||
elif args.work:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import spack
|
||||
import spack.packages as packages
|
||||
import spack.tty as tty
|
||||
import spack.version
|
||||
import spack.url
|
||||
|
||||
from spack.stage import Stage
|
||||
from contextlib import closing
|
||||
|
@ -38,7 +38,7 @@ def create(parser, args):
|
|||
url = args.url
|
||||
|
||||
# Try to deduce name and version of the new package from the URL
|
||||
name, version = spack.version.parse(url)
|
||||
name, version = spack.url.parse_name_and_version(url)
|
||||
if not name:
|
||||
print "Couldn't guess a name for this package."
|
||||
while not name:
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import argparse
|
||||
import spack.cmd
|
||||
import spack.packages as packages
|
||||
|
||||
description = "Fetch archives for packages"
|
||||
|
||||
def setup_parser(subparser):
|
||||
subparser.add_argument('names', nargs='+', help="names of packages to fetch")
|
||||
subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to fetch")
|
||||
|
||||
|
||||
def fetch(parser, args):
|
||||
for name in args.names:
|
||||
package = packages.get(name)
|
||||
if not args.packages:
|
||||
tty.die("fetch requires at least one package argument")
|
||||
|
||||
specs = spack.cmd.parse_specs(args.packages)
|
||||
for spec in specs:
|
||||
package = packages.get(spec.name)
|
||||
package.do_fetch()
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
import sys
|
||||
import argparse
|
||||
|
||||
import spack
|
||||
import spack.packages as packages
|
||||
import spack.cmd
|
||||
|
||||
description = "Build and install packages"
|
||||
|
||||
def setup_parser(subparser):
|
||||
subparser.add_argument('names', nargs='+', help="names of packages to install")
|
||||
subparser.add_argument('-i', '--ignore-dependencies',
|
||||
action='store_true', dest='ignore_dependencies',
|
||||
help="Do not try to install dependencies of requested packages.")
|
||||
subparser.add_argument('-d', '--dirty', action='store_true', dest='dirty',
|
||||
help="Don't clean up partially completed build/installation on error.")
|
||||
subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to install")
|
||||
|
||||
|
||||
def install(parser, args):
|
||||
if not args.packages:
|
||||
tty.die("install requires at least one package argument")
|
||||
|
||||
spack.ignore_dependencies = args.ignore_dependencies
|
||||
for name in args.names:
|
||||
package = packages.get(name)
|
||||
specs = spack.cmd.parse_specs(args.packages)
|
||||
for spec in specs:
|
||||
package = packages.get(spec.name)
|
||||
package.dirty = args.dirty
|
||||
package.do_install()
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import spack.cmd
|
||||
import spack.packages as packages
|
||||
import argparse
|
||||
|
||||
description="Remove an installed package"
|
||||
|
||||
def setup_parser(subparser):
|
||||
subparser.add_argument('names', nargs='+', help="name(s) of package(s) to uninstall")
|
||||
subparser.add_argument('-f', '--force', action='store_true', dest='force',
|
||||
help="Ignore installed packages that depend on this one and remove it anyway.")
|
||||
subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to uninstall")
|
||||
|
||||
def uninstall(parser, args):
|
||||
if not args.packages:
|
||||
tty.die("uninstall requires at least one package argument.")
|
||||
|
||||
specs = spack.cmd.parse_specs(args.packages)
|
||||
|
||||
# get packages to uninstall as a list.
|
||||
pkgs = [packages.get(name) for name in args.names]
|
||||
pkgs = [packages.get(spec.name) for spec in specs]
|
||||
|
||||
# Sort packages to be uninstalled by the number of installed dependents
|
||||
# This ensures we do things in the right order
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
class Dependency(object):
|
||||
"""Represents a dependency from one package to another.
|
||||
"""
|
||||
def __init__(self, name, version):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
@property
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
import tty
|
||||
import attr
|
||||
import validate
|
||||
import version
|
||||
import url
|
||||
import arch
|
||||
|
||||
from multi_function import platform
|
||||
|
@ -261,7 +261,7 @@ def __init__(self, sys_type = arch.sys_type()):
|
|||
validate.url(self.url)
|
||||
|
||||
# Set up version
|
||||
attr.setdefault(self, 'version', version.parse_version(self.url))
|
||||
attr.setdefault(self, 'version', url.parse_version(self.url))
|
||||
if not self.version:
|
||||
tty.die("Couldn't extract version from %s. " +
|
||||
"You must specify it explicitly for this URL." % self.url)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import re
|
||||
import spack.error as err
|
||||
import spack.tty as tty
|
||||
import itertools
|
||||
|
||||
|
||||
|
@ -11,9 +12,7 @@ def __init__(self, message, string, pos):
|
|||
self.pos = pos
|
||||
|
||||
def print_error(self, out):
|
||||
out.write(self.message + ":\n\n")
|
||||
out.write(" " + self.string + "\n")
|
||||
out.write(" " + self.pos * " " + "^\n\n")
|
||||
tty.error(self.message, self.string, self.pos * " " + "^")
|
||||
|
||||
|
||||
class LexError(ParseError):
|
||||
|
@ -107,7 +106,7 @@ def expect(self, id):
|
|||
if self.next:
|
||||
self.unexpected_token()
|
||||
else:
|
||||
self.next_token_error("Unexpected end of file")
|
||||
self.next_token_error("Unexpected end of input")
|
||||
sys.exit(1)
|
||||
|
||||
def parse(self, text):
|
||||
|
|
|
@ -44,6 +44,7 @@ class Mpileaks(Package):
|
|||
spack install mpileaks ^mvapich
|
||||
spack install mpileaks ^mpich
|
||||
"""
|
||||
import sys
|
||||
from dependency import Dependency
|
||||
|
||||
|
||||
|
|
|
@ -126,6 +126,9 @@ def expanded_archive_path(self):
|
|||
"""Returns the path to the expanded archive directory if it's expanded;
|
||||
None if the archive hasn't been expanded.
|
||||
"""
|
||||
if not self.archive_file:
|
||||
return None
|
||||
|
||||
for file in os.listdir(self.path):
|
||||
archive_path = spack.new_path(self.path, file)
|
||||
if os.path.isdir(archive_path):
|
||||
|
|
|
@ -3,18 +3,19 @@
|
|||
detection in Homebrew.
|
||||
"""
|
||||
import unittest
|
||||
import spack.version as ver
|
||||
import spack.url as url
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
class UrlParseTest(unittest.TestCase):
|
||||
def assert_not_detected(self, string):
|
||||
self.assertRaises(ver.UndetectableVersionError, ver.parse, string)
|
||||
self.assertRaises(
|
||||
url.UndetectableVersionError, url.parse_name_and_version, string)
|
||||
|
||||
def assert_detected(self, name, v, string):
|
||||
parsed_name, parsed_v = ver.parse(string)
|
||||
parsed_name, parsed_v = url.parse_name_and_version(string)
|
||||
self.assertEqual(parsed_name, name)
|
||||
self.assertEqual(parsed_v, ver.Version(v))
|
||||
self.assertEqual(parsed_v, url.Version(v))
|
||||
|
||||
def test_wwwoffle_version(self):
|
||||
self.assert_detected(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
from spack.version import *
|
||||
|
||||
|
||||
class CompareVersionsTest(unittest.TestCase):
|
||||
class VersionsTest(unittest.TestCase):
|
||||
|
||||
def assert_ver_lt(self, a, b):
|
||||
a, b = ver(a), ver(b)
|
||||
|
@ -129,7 +129,8 @@ def test_rpm_oddities(self):
|
|||
self.assert_ver_lt('1.fc17', '1g.fc17')
|
||||
|
||||
|
||||
# Stuff below here is not taken from RPM's tests.
|
||||
# Stuff below here is not taken from RPM's tests and is
|
||||
# unique to spack
|
||||
def test_version_ranges(self):
|
||||
self.assert_ver_lt('1.2:1.4', '1.6')
|
||||
self.assert_ver_gt('1.6', '1.2:1.4')
|
166
lib/spack/spack/url.py
Normal file
166
lib/spack/spack/url.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
"""
|
||||
This module has methods for parsing names and versions of packages from URLs.
|
||||
The idea is to allow package creators to supply nothing more than the
|
||||
download location of the package, and figure out version and name information
|
||||
from there.
|
||||
|
||||
Example: when spack is given the following URL:
|
||||
|
||||
ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz
|
||||
|
||||
It can figure out that the package name is ruby, and that it is at version
|
||||
1.9.1-p243. This is useful for making the creation of packages simple: a user
|
||||
just supplies a URL and skeleton code is generated automatically.
|
||||
|
||||
Spack can also figure out that it can most likely download 1.8.1 at this URL:
|
||||
|
||||
ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.8.1.tar.gz
|
||||
|
||||
This is useful if a user asks for a package at a particular version number;
|
||||
spack doesn't need anyone to tell it where to get the tarball even though
|
||||
it's never been told about that version before.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
import spack.error
|
||||
import spack.utils
|
||||
from spack.version import Version
|
||||
|
||||
|
||||
class UrlParseError(spack.error.SpackError):
|
||||
"""Raised when the URL module can't parse something correctly."""
|
||||
def __init__(self, msg, spec):
|
||||
super(UrlParseError, self).__init__(msg)
|
||||
self.spec = spec
|
||||
|
||||
|
||||
class UndetectableVersionError(UrlParseError):
|
||||
"""Raised when we can't parse a version from a string."""
|
||||
def __init__(self, spec):
|
||||
super(UndetectableVersionError, self).__init__(
|
||||
"Couldn't detect version in: " + spec, spec)
|
||||
|
||||
|
||||
class UndetectableNameError(UrlParseError):
|
||||
"""Raised when we can't parse a package name from a string."""
|
||||
def __init__(self, spec):
|
||||
super(UndetectableNameError, self).__init__(
|
||||
"Couldn't parse package name in: " + spec)
|
||||
|
||||
|
||||
def parse_version_string_with_indices(spec):
|
||||
"""Try to extract a version string from a filename or URL. This is taken
|
||||
largely from Homebrew's Version class."""
|
||||
|
||||
if os.path.isdir(spec):
|
||||
stem = os.path.basename(spec)
|
||||
elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', spec):
|
||||
stem = spack.utils.stem(os.path.dirname(spec))
|
||||
else:
|
||||
stem = spack.utils.stem(spec)
|
||||
|
||||
version_types = [
|
||||
# GitHub tarballs, e.g. v1.2.3
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+)$', spec),
|
||||
|
||||
# e.g. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
|
||||
(r'github.com/.+/(?:zip|tar)ball/.*-((\d+\.)+\d+)$', spec),
|
||||
|
||||
# e.g. https://github.com/isaacs/npm/tarball/v0.2.5-1
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+-(\d+))$', spec),
|
||||
|
||||
# e.g. https://github.com/petdance/ack/tarball/1.93_02
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+_(\d+))$', spec),
|
||||
|
||||
# e.g. https://github.com/erlang/otp/tarball/OTP_R15B01 (erlang style)
|
||||
(r'[-_](R\d+[AB]\d*(-\d+)?)', spec),
|
||||
|
||||
# e.g. boost_1_39_0
|
||||
(r'((\d+_)+\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.1-1
|
||||
# e.g. ruby-1.9.1-p243
|
||||
(r'-((\d+\.)*\d\.\d+-(p|rc|RC)?\d+)(?:[-._](?:bin|dist|stable|src|sources))?$', stem),
|
||||
|
||||
# e.g. lame-398-1
|
||||
(r'-((\d)+-\d)', stem),
|
||||
|
||||
# e.g. foobar-4.5.1
|
||||
(r'-((\d+\.)*\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.1b
|
||||
(r'-((\d+\.)*\d+([a-z]|rc|RC)\d*)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.0-beta1, or foobar-4.50-beta
|
||||
(r'-((\d+\.)*\d+-beta(\d+)?)$', stem),
|
||||
|
||||
# e.g. foobar4.5.1
|
||||
(r'((\d+\.)*\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.0-bin
|
||||
(r'-((\d+\.)+\d+[a-z]?)[-._](bin|dist|stable|src|sources?)$', stem),
|
||||
|
||||
# e.g. dash_0.5.5.1.orig.tar.gz (Debian style)
|
||||
(r'_((\d+\.)+\d+[a-z]?)[.]orig$', stem),
|
||||
|
||||
# e.g. http://www.openssl.org/source/openssl-0.9.8s.tar.gz
|
||||
(r'-([^-]+)', stem),
|
||||
|
||||
# e.g. astyle_1.23_macosx.tar.gz
|
||||
(r'_([^_]+)', stem),
|
||||
|
||||
# e.g. http://mirrors.jenkins-ci.org/war/1.486/jenkins.war
|
||||
(r'\/(\d\.\d+)\/', spec),
|
||||
|
||||
# e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz
|
||||
(r'\.v(\d+[a-z]?)', stem)]
|
||||
|
||||
for vtype in version_types:
|
||||
regex, match_string = vtype[:2]
|
||||
match = re.search(regex, match_string)
|
||||
if match and match.group(1) is not None:
|
||||
return match.group(1), match.start(1), match.end(1)
|
||||
|
||||
raise UndetectableVersionError(spec)
|
||||
|
||||
|
||||
def parse_version(spec):
|
||||
"""Given a URL or archive name, extract a version from it and return
|
||||
a version object.
|
||||
"""
|
||||
ver, start, end = parse_version_string_with_indices(spec)
|
||||
return Version(ver)
|
||||
|
||||
|
||||
def parse_name(spec, ver=None):
|
||||
if ver is None:
|
||||
ver = parse_version(spec)
|
||||
|
||||
ntypes = (r'/sourceforge/([^/]+)/',
|
||||
r'/([^/]+)/(tarball|zipball)/',
|
||||
r'/([^/]+)[_.-](bin|dist|stable|src|sources)[_.-]%s' % ver,
|
||||
r'/([^/]+)[_.-]v?%s' % ver,
|
||||
r'/([^/]+)%s' % ver,
|
||||
r'^([^/]+)[_.-]v?%s' % ver,
|
||||
r'^([^/]+)%s' % ver)
|
||||
|
||||
for nt in ntypes:
|
||||
match = re.search(nt, spec)
|
||||
if match:
|
||||
return match.group(1)
|
||||
raise UndetectableNameError(spec)
|
||||
|
||||
|
||||
def parse_name_and_version(spec):
|
||||
ver = parse_version(spec)
|
||||
name = parse_name(spec, ver)
|
||||
return (name, ver)
|
||||
|
||||
|
||||
def create_version_format(spec):
|
||||
"""Given a URL or archive name, find the version and create a format string
|
||||
that will allow another version to be substituted.
|
||||
"""
|
||||
ver, start, end = parse_version_string_with_indices(spec)
|
||||
return spec[:start] + '%s' + spec[end:]
|
|
@ -3,7 +3,10 @@
|
|||
from functools import total_ordering
|
||||
|
||||
import utils
|
||||
import spack.error as serr
|
||||
import spack.error
|
||||
|
||||
# Valid version characters
|
||||
VALID_VERSION = r'[A-Za-z0-9_.-]'
|
||||
|
||||
|
||||
def int_if_int(string):
|
||||
|
@ -26,28 +29,37 @@ def ver(string):
|
|||
@total_ordering
|
||||
class Version(object):
|
||||
"""Class to represent versions"""
|
||||
def __init__(self, version_string):
|
||||
def __init__(self, string):
|
||||
if not re.match(VALID_VERSION, string):
|
||||
raise ValueError("Bad characters in version string: %s" % string)
|
||||
|
||||
# preserve the original string
|
||||
self.version_string = version_string
|
||||
self.string = string
|
||||
|
||||
# Split version into alphabetical and numeric segments
|
||||
segments = re.findall(r'[a-zA-Z]+|[0-9]+', version_string)
|
||||
segment_regex = r'[a-zA-Z]+|[0-9]+'
|
||||
segments = re.findall(segment_regex, string)
|
||||
self.version = tuple(int_if_int(seg) for seg in segments)
|
||||
|
||||
|
||||
def up_to(self, index):
|
||||
"""Return a version string up to the specified component, exclusive.
|
||||
e.g., if this is 10.8.2, self.up_to(2) will return '10.8'.
|
||||
"""
|
||||
return '.'.join(str(x) for x in self[:index])
|
||||
|
||||
def __iter__(self):
|
||||
for v in self.version:
|
||||
yield v
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return tuple(self.version[idx])
|
||||
|
||||
def __repr__(self):
|
||||
return self.version_string
|
||||
return self.string
|
||||
|
||||
def __str__(self):
|
||||
return self.version_string
|
||||
return self.string
|
||||
|
||||
def __lt__(self, other):
|
||||
"""Version comparison is designed for consistency with the way RPM
|
||||
|
@ -145,144 +157,3 @@ def __str__(self):
|
|||
if self.end:
|
||||
out += str(self.end)
|
||||
return out
|
||||
|
||||
|
||||
class VersionParseError(serr.SpackError):
|
||||
"""Raised when the version module can't parse something."""
|
||||
def __init__(self, msg, spec):
|
||||
super(VersionParseError, self).__init__(msg)
|
||||
self.spec = spec
|
||||
|
||||
|
||||
class UndetectableVersionError(VersionParseError):
|
||||
"""Raised when we can't parse a version from a string."""
|
||||
def __init__(self, spec):
|
||||
super(UndetectableVersionError, self).__init__(
|
||||
"Couldn't detect version in: " + spec, spec)
|
||||
|
||||
|
||||
class UndetectableNameError(VersionParseError):
|
||||
"""Raised when we can't parse a package name from a string."""
|
||||
def __init__(self, spec):
|
||||
super(UndetectableNameError, self).__init__(
|
||||
"Couldn't parse package name in: " + spec)
|
||||
|
||||
|
||||
def parse_version_string_with_indices(spec):
|
||||
"""Try to extract a version string from a filename or URL. This is taken
|
||||
largely from Homebrew's Version class."""
|
||||
|
||||
if os.path.isdir(spec):
|
||||
stem = os.path.basename(spec)
|
||||
elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', spec):
|
||||
stem = utils.stem(os.path.dirname(spec))
|
||||
else:
|
||||
stem = utils.stem(spec)
|
||||
|
||||
version_types = [
|
||||
# GitHub tarballs, e.g. v1.2.3
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+)$', spec),
|
||||
|
||||
# e.g. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
|
||||
(r'github.com/.+/(?:zip|tar)ball/.*-((\d+\.)+\d+)$', spec),
|
||||
|
||||
# e.g. https://github.com/isaacs/npm/tarball/v0.2.5-1
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+-(\d+))$', spec),
|
||||
|
||||
# e.g. https://github.com/petdance/ack/tarball/1.93_02
|
||||
(r'github.com/.+/(?:zip|tar)ball/v?((\d+\.)+\d+_(\d+))$', spec),
|
||||
|
||||
# e.g. https://github.com/erlang/otp/tarball/OTP_R15B01 (erlang style)
|
||||
(r'[-_](R\d+[AB]\d*(-\d+)?)', spec),
|
||||
|
||||
# e.g. boost_1_39_0
|
||||
(r'((\d+_)+\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.1-1
|
||||
# e.g. ruby-1.9.1-p243
|
||||
(r'-((\d+\.)*\d\.\d+-(p|rc|RC)?\d+)(?:[-._](?:bin|dist|stable|src|sources))?$', stem),
|
||||
|
||||
# e.g. lame-398-1
|
||||
(r'-((\d)+-\d)', stem),
|
||||
|
||||
# e.g. foobar-4.5.1
|
||||
(r'-((\d+\.)*\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.1b
|
||||
(r'-((\d+\.)*\d+([a-z]|rc|RC)\d*)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.0-beta1, or foobar-4.50-beta
|
||||
(r'-((\d+\.)*\d+-beta(\d+)?)$', stem),
|
||||
|
||||
# e.g. foobar4.5.1
|
||||
(r'((\d+\.)*\d+)$', stem),
|
||||
|
||||
# e.g. foobar-4.5.0-bin
|
||||
(r'-((\d+\.)+\d+[a-z]?)[-._](bin|dist|stable|src|sources?)$', stem),
|
||||
|
||||
# e.g. dash_0.5.5.1.orig.tar.gz (Debian style)
|
||||
(r'_((\d+\.)+\d+[a-z]?)[.]orig$', stem),
|
||||
|
||||
# e.g. http://www.openssl.org/source/openssl-0.9.8s.tar.gz
|
||||
(r'-([^-]+)', stem),
|
||||
|
||||
# e.g. astyle_1.23_macosx.tar.gz
|
||||
(r'_([^_]+)', stem),
|
||||
|
||||
# e.g. http://mirrors.jenkins-ci.org/war/1.486/jenkins.war
|
||||
(r'\/(\d\.\d+)\/', spec),
|
||||
|
||||
# e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz
|
||||
(r'\.v(\d+[a-z]?)', stem)]
|
||||
|
||||
for vtype in version_types:
|
||||
regex, match_string = vtype[:2]
|
||||
match = re.search(regex, match_string)
|
||||
if match and match.group(1) is not None:
|
||||
return match.group(1), match.start(1), match.end(1)
|
||||
|
||||
raise UndetectableVersionError(spec)
|
||||
|
||||
|
||||
def parse_version(spec):
|
||||
"""Given a URL or archive name, extract a version from it and return
|
||||
a version object.
|
||||
"""
|
||||
ver, start, end = parse_version_string_with_indices(spec)
|
||||
return Version(ver)
|
||||
|
||||
|
||||
def create_version_format(spec):
|
||||
"""Given a URL or archive name, find the version and create a format string
|
||||
that will allow another version to be substituted.
|
||||
"""
|
||||
ver, start, end = parse_version_string_with_indices(spec)
|
||||
return spec[:start] + '%s' + spec[end:]
|
||||
|
||||
|
||||
def replace_version(spec, new_version):
|
||||
version = create_version_format(spec)
|
||||
# TODO: finish this function.
|
||||
|
||||
def parse_name(spec, ver=None):
|
||||
if ver is None:
|
||||
ver = parse_version(spec)
|
||||
|
||||
ntypes = (r'/sourceforge/([^/]+)/',
|
||||
r'/([^/]+)/(tarball|zipball)/',
|
||||
r'/([^/]+)[_.-](bin|dist|stable|src|sources)[_.-]%s' % ver,
|
||||
r'/([^/]+)[_.-]v?%s' % ver,
|
||||
r'/([^/]+)%s' % ver,
|
||||
r'^([^/]+)[_.-]v?%s' % ver,
|
||||
r'^([^/]+)%s' % ver)
|
||||
|
||||
for nt in ntypes:
|
||||
match = re.search(nt, spec)
|
||||
if match:
|
||||
return match.group(1)
|
||||
raise UndetectableNameError(spec)
|
||||
|
||||
def parse(spec):
|
||||
ver = parse_version(spec)
|
||||
name = parse_name(spec, ver)
|
||||
return (name, ver)
|
||||
|
|
Loading…
Reference in a new issue