URL parsing improvements
This commit is contained in:
		
							
								
								
									
										10
									
								
								lib/spack/env/cc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								lib/spack/env/cc
									
									
									
									
										vendored
									
									
								
							@@ -275,9 +275,15 @@ for dir in "${libraries[@]}"; do args+=("-L$dir"); done
 | 
			
		||||
for lib in "${libs[@]}";      do args+=("-l$lib"); done
 | 
			
		||||
 | 
			
		||||
if [ "$mode" = ccld ]; then
 | 
			
		||||
    for dir in "${rpaths[@]}"; do args+=("-Wl,-rpath=$dir"); done
 | 
			
		||||
    for dir in "${rpaths[@]}"; do
 | 
			
		||||
        args+=("-Wl,-rpath")
 | 
			
		||||
        args+=("-Wl,$dir");
 | 
			
		||||
    done
 | 
			
		||||
elif [ "$mode" = ld ]; then
 | 
			
		||||
    for dir in "${rpaths[@]}"; do args+=("-rpath=$dir"); done
 | 
			
		||||
    for dir in "${rpaths[@]}"; do
 | 
			
		||||
        args+=("-rpath")
 | 
			
		||||
        args+=("$dir");
 | 
			
		||||
    done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
 
 | 
			
		||||
@@ -1096,8 +1096,9 @@ def __getitem__(self, name):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __contains__(self, spec):
 | 
			
		||||
        """True if this spec has any dependency that satisfies the supplied
 | 
			
		||||
           spec."""
 | 
			
		||||
        """True if this spec satisfis the provided spec, or if any dependency
 | 
			
		||||
           does.  If the spec has no name, then we parse this one first.
 | 
			
		||||
        """
 | 
			
		||||
        spec = self._autospec(spec)
 | 
			
		||||
        for s in self.traverse():
 | 
			
		||||
            if s.satisfies(spec):
 | 
			
		||||
 
 | 
			
		||||
@@ -34,15 +34,35 @@
 | 
			
		||||
 | 
			
		||||
class UrlExtrapolateTest(MockPackagesTest):
 | 
			
		||||
 | 
			
		||||
    def test_known_version(self):
 | 
			
		||||
        d = spack.db.get('dyninst')
 | 
			
		||||
    def test_libelf_version(self):
 | 
			
		||||
        base = "http://www.mr511.de/software/libelf-0.8.13.tar.gz"
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '0.8.13'), base)
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '0.8.12'),
 | 
			
		||||
                         "http://www.mr511.de/software/libelf-0.8.12.tar.gz")
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '0.3.1'),
 | 
			
		||||
                         "http://www.mr511.de/software/libelf-0.3.1.tar.gz")
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '1.3.1b'),
 | 
			
		||||
                         "http://www.mr511.de/software/libelf-1.3.1b.tar.gz")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def test_libdwarf_version(self):
 | 
			
		||||
        base = "http://www.prevanders.net/libdwarf-20130729.tar.gz"
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '20130729'), base)
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '8.12'),
 | 
			
		||||
                         "http://www.prevanders.net/libdwarf-8.12.tar.gz")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def test_dyninst_version(self):
 | 
			
		||||
        # Dyninst has a version twice in the URL.
 | 
			
		||||
        base = "http://www.dyninst.org/sites/default/files/downloads/dyninst/8.1.2/DyninstAPI-8.1.2.tgz"
 | 
			
		||||
        self.assertEqual(url.substitute_version(base, '8.1.2'), base)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            url.substitute_version(base, '8.2'),
 | 
			
		||||
            "http://www.dyninst.org/sites/default/files/downloads/dyninst/8.2/DyninstAPI-8.2.tgz")
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            d.url_for_version('8.2'), 'http://www.paradyn.org/release8.2/DyninstAPI-8.2.tgz')
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            d.url_for_version('8.1.2'), 'http://www.paradyn.org/release8.1.2/DyninstAPI-8.1.2.tgz')
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            d.url_for_version('8.1.1'), 'http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz')
 | 
			
		||||
            url.substitute_version(base, '8.3.1'),
 | 
			
		||||
            "http://www.dyninst.org/sites/default/files/downloads/dyninst/8.3.1/DyninstAPI-8.3.1.tgz")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def test_extrapolate_version(self):
 | 
			
		||||
@@ -59,8 +79,8 @@ def test_extrapolate_version(self):
 | 
			
		||||
        # 8.2 matches both the release8.2 component and the DyninstAPI-8.2 component.
 | 
			
		||||
        # Extrapolation should replace both with the new version.
 | 
			
		||||
        # TODO: figure out a consistent policy for this.
 | 
			
		||||
        # self.assertEqual(
 | 
			
		||||
        #     d.url_for_version('8.2.3'), 'http://www.paradyn.org/release8.2.3/DyninstAPI-8.2.3.tgz')
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            d.url_for_version('8.2.3'), 'http://www.paradyn.org/release8.2.3/DyninstAPI-8.2.3.tgz')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def test_with_package(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -57,27 +57,6 @@
 | 
			
		||||
# "path" seemed like the most generic term.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class UrlParseError(spack.error.SpackError):
 | 
			
		||||
    """Raised when the URL module can't parse something correctly."""
 | 
			
		||||
    def __init__(self, msg, path):
 | 
			
		||||
        super(UrlParseError, self).__init__(msg)
 | 
			
		||||
        self.path = path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UndetectableVersionError(UrlParseError):
 | 
			
		||||
    """Raised when we can't parse a version from a string."""
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        super(UndetectableVersionError, self).__init__(
 | 
			
		||||
            "Couldn't detect version in: " + path, path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UndetectableNameError(UrlParseError):
 | 
			
		||||
    """Raised when we can't parse a package name from a string."""
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        super(UndetectableNameError, self).__init__(
 | 
			
		||||
            "Couldn't parse package name in: " + path, path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def find_list_url(url):
 | 
			
		||||
    """Finds a good list URL for the supplied URL.  This depends on
 | 
			
		||||
       the site.  By default, just assumes that a good list URL is the
 | 
			
		||||
@@ -98,7 +77,7 @@ def find_list_url(url):
 | 
			
		||||
        return os.path.dirname(url)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_version_string_with_indices(path):
 | 
			
		||||
def parse_version_offset(path):
 | 
			
		||||
    """Try to extract a version string from a filename or URL.  This is taken
 | 
			
		||||
       largely from Homebrew's Version class."""
 | 
			
		||||
 | 
			
		||||
@@ -112,6 +91,7 @@ def parse_version_string_with_indices(path):
 | 
			
		||||
    # Take basename to avoid including parent dirs in version name
 | 
			
		||||
    # Remember the offset of the stem in the full path.
 | 
			
		||||
    stem = os.path.basename(path)
 | 
			
		||||
    offset = len(path) - len(stem)
 | 
			
		||||
 | 
			
		||||
    version_types = [
 | 
			
		||||
        # GitHub tarballs, e.g. v1.2.3
 | 
			
		||||
@@ -172,13 +152,13 @@ def parse_version_string_with_indices(path):
 | 
			
		||||
        # e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz
 | 
			
		||||
        (r'\.v(\d+[a-z]?)', stem)]
 | 
			
		||||
 | 
			
		||||
    for vtype in version_types:
 | 
			
		||||
    for i, vtype in enumerate(version_types):
 | 
			
		||||
        regex, match_string = vtype[:2]
 | 
			
		||||
        match = re.search(regex, match_string)
 | 
			
		||||
        if match and match.group(1) is not None:
 | 
			
		||||
            version = match.group(1)
 | 
			
		||||
            start = path.index(version)
 | 
			
		||||
            return version, start, start+len(version)
 | 
			
		||||
            start = offset + match.start(1)
 | 
			
		||||
            return version, start, len(version)
 | 
			
		||||
 | 
			
		||||
    raise UndetectableVersionError(path)
 | 
			
		||||
 | 
			
		||||
@@ -187,11 +167,11 @@ def parse_version(path):
 | 
			
		||||
    """Given a URL or archive name, extract a version from it and return
 | 
			
		||||
       a version object.
 | 
			
		||||
    """
 | 
			
		||||
    ver, start, end = parse_version_string_with_indices(path)
 | 
			
		||||
    ver, start, l = parse_version_offset(path)
 | 
			
		||||
    return Version(ver)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_name(path, ver=None):
 | 
			
		||||
def parse_name_offset(path, ver=None):
 | 
			
		||||
    if ver is None:
 | 
			
		||||
        ver = parse_version(path)
 | 
			
		||||
 | 
			
		||||
@@ -207,10 +187,16 @@ def parse_name(path, ver=None):
 | 
			
		||||
    for nt in ntypes:
 | 
			
		||||
        match = re.search(nt, path)
 | 
			
		||||
        if match:
 | 
			
		||||
            return match.group(1)
 | 
			
		||||
            name = match.group(1)
 | 
			
		||||
            return name, match.start(1), len(name)
 | 
			
		||||
    raise UndetectableNameError(path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_name(path, ver=None):
 | 
			
		||||
    name, start, l = parse_name_offset(path, ver)
 | 
			
		||||
    return name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_name_and_version(path):
 | 
			
		||||
    ver = parse_version(path)
 | 
			
		||||
    name = parse_name(path, ver)
 | 
			
		||||
@@ -231,8 +217,8 @@ def substitute_version(path, new_version):
 | 
			
		||||
    """Given a URL or archive name, find the version in the path and substitute
 | 
			
		||||
       the new version for it.
 | 
			
		||||
    """
 | 
			
		||||
    ver, start, end = parse_version_string_with_indices(path)
 | 
			
		||||
    return path[:start] + str(new_version) + path[end:]
 | 
			
		||||
    ver, start, l = parse_version_offset(path)
 | 
			
		||||
    return path[:start] + str(new_version) + path[(start+l):]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def wildcard_version(path):
 | 
			
		||||
@@ -266,3 +252,24 @@ def wildcard_version(path):
 | 
			
		||||
 | 
			
		||||
    # Put it all back together with original name matches intact.
 | 
			
		||||
    return ''.join(name_parts) + '.' + ext
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UrlParseError(spack.error.SpackError):
 | 
			
		||||
    """Raised when the URL module can't parse something correctly."""
 | 
			
		||||
    def __init__(self, msg, path):
 | 
			
		||||
        super(UrlParseError, self).__init__(msg)
 | 
			
		||||
        self.path = path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UndetectableVersionError(UrlParseError):
 | 
			
		||||
    """Raised when we can't parse a version from a string."""
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        super(UndetectableVersionError, self).__init__(
 | 
			
		||||
            "Couldn't detect version in: " + path, path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UndetectableNameError(UrlParseError):
 | 
			
		||||
    """Raised when we can't parse a package name from a string."""
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        super(UndetectableNameError, self).__init__(
 | 
			
		||||
            "Couldn't parse package name in: " + path, path)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user