url stats: add --show-issues option (#25792)

* tests: make `spack url [stats|summary]` work on mock packages

Mock packages have historically had mock hashes, but this means they're also invalid
as far as Spack's hash detection is concerned.

- [x] convert all hashes in mock package to md5 or sha256
- [x] ensure that all mock packages have a URL
- [x] ignore some special cases with multiple VCS fetchers

* url stats: add `--show-issues` option

`spack url stats` tells us how many URLs are using what protocol, type of checksum,
etc., but it previously did not tell us which packages and URLs had the issues. This
adds a `--show-issues` option to show URLs with insecure (`http`) URLs or `md5` hashes
(which are now deprecated by NIST).
This commit is contained in:
Todd Gamblin 2021-09-08 07:59:06 -07:00 committed by GitHub
parent c2a6ccbea8
commit c309adb4b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 266 additions and 169 deletions

View File

@ -9,6 +9,7 @@
import six.moves.urllib.parse as urllib_parse import six.moves.urllib.parse as urllib_parse
import llnl.util.tty.color as color
from llnl.util import tty from llnl.util import tty
import spack.fetch_strategy as fs import spack.fetch_strategy as fs
@ -80,9 +81,13 @@ def setup_parser(subparser):
help='print a summary of how well we are parsing package urls') help='print a summary of how well we are parsing package urls')
# Stats # Stats
sp.add_parser( stats_parser = sp.add_parser(
'stats', 'stats',
help='print statistics on versions and checksums for all packages') help='print statistics on versions and checksums for all packages')
stats_parser.add_argument(
"--show-issues", action="store_true",
help="show packages with issues (md5 hashes, http urls)"
)
def url(parser, args): def url(parser, args):
@ -262,6 +267,9 @@ def url_summary(args):
def url_stats(args): def url_stats(args):
# dictionary of issue type -> package -> descriptions
issues = defaultdict(lambda: defaultdict(lambda: []))
class UrlStats(object): class UrlStats(object):
def __init__(self): def __init__(self):
self.total = 0 self.total = 0
@ -270,7 +278,7 @@ def __init__(self):
self.url_type = defaultdict(lambda: 0) self.url_type = defaultdict(lambda: 0)
self.git_type = defaultdict(lambda: 0) self.git_type = defaultdict(lambda: 0)
def add(self, fetcher): def add(self, pkg_name, fetcher):
self.total += 1 self.total += 1
url_type = fetcher.url_attr url_type = fetcher.url_attr
@ -284,10 +292,18 @@ def add(self, fetcher):
algo = 'no checksum' algo = 'no checksum'
self.checksums[algo] += 1 self.checksums[algo] += 1
if algo == "md5":
md5_hashes = issues["md5 hashes"]
md5_hashes[pkg_name].append(fetcher.url)
# parse out the URL scheme (https/http/ftp/etc.) # parse out the URL scheme (https/http/ftp/etc.)
urlinfo = urllib_parse.urlparse(fetcher.url) urlinfo = urllib_parse.urlparse(fetcher.url)
self.schemes[urlinfo.scheme] += 1 self.schemes[urlinfo.scheme] += 1
if urlinfo.scheme == "http":
http_urls = issues["http urls"]
http_urls[pkg_name].append(fetcher.url)
elif url_type == 'git': elif url_type == 'git':
if getattr(fetcher, 'commit', None): if getattr(fetcher, 'commit', None):
self.git_type['commit'] += 1 self.git_type['commit'] += 1
@ -305,13 +321,16 @@ def add(self, fetcher):
for pkg in spack.repo.path.all_packages(): for pkg in spack.repo.path.all_packages():
npkgs += 1 npkgs += 1
for v, args in pkg.versions.items(): for v in pkg.versions:
fetcher = fs.for_package_version(pkg, v) try:
version_stats.add(fetcher) fetcher = fs.for_package_version(pkg, v)
except (fs.InvalidArgsError, fs.FetcherConflict):
continue
version_stats.add(pkg.name, fetcher)
for _, resources in pkg.resources.items(): for _, resources in pkg.resources.items():
for resource in resources: for resource in resources:
resource_stats.add(resource.fetcher) resource_stats.add(pkg.name, resource.fetcher)
# print a nice summary table # print a nice summary table
tty.msg("URL stats for %d packages:" % npkgs) tty.msg("URL stats for %d packages:" % npkgs)
@ -361,6 +380,21 @@ def print_stat(indent, name, stat_name=None):
print_stat(4, git_type, "git_type") print_stat(4, git_type, "git_type")
print_line() print_line()
if args.show_issues:
total_issues = sum(
len(issues)
for _, pkg_issues in issues.items()
for _, issues in pkg_issues.items()
)
print()
tty.msg("Found %d issues." % total_issues)
for issue_type, pkgs in issues.items():
tty.msg("Package URLs with %s" % issue_type)
for pkg, pkg_issues in pkgs.items():
color.cprint(" @*C{%s}" % pkg)
for issue in pkg_issues:
print(" %s" % issue)
def print_name_and_version(url): def print_name_and_version(url):
"""Prints a URL. Underlines the detected name with dashes and """Prints a URL. Underlines the detected name with dashes and

View File

@ -69,13 +69,15 @@ def test_url_with_no_version_fails():
url('parse', 'http://www.netlib.org/voronoi/triangle.zip') url('parse', 'http://www.netlib.org/voronoi/triangle.zip')
@pytest.mark.maybeslow skip_python_26 = pytest.mark.skipif(
@pytest.mark.skipif(
sys.version_info < (2, 7), sys.version_info < (2, 7),
reason="Python 2.6 tests are run in a container, where " reason="Python 2.6 tests are run in a container, where "
"networking is super slow" "networking is super slow"
) )
def test_url_list():
@skip_python_26
def test_url_list(mock_packages):
out = url('list') out = url('list')
total_urls = len(out.split('\n')) total_urls = len(out.split('\n'))
@ -104,13 +106,8 @@ def test_url_list():
assert 0 < correct_version_urls < total_urls assert 0 < correct_version_urls < total_urls
@pytest.mark.maybeslow @skip_python_26
@pytest.mark.skipif( def test_url_summary(mock_packages):
sys.version_info < (2, 7),
reason="Python 2.6 tests are run in a container, where "
"networking is super slow"
)
def test_url_summary():
"""Test the URL summary command.""" """Test the URL summary command."""
# test url_summary, the internal function that does the work # test url_summary, the internal function that does the work
(total_urls, correct_names, correct_versions, (total_urls, correct_names, correct_versions,
@ -136,12 +133,8 @@ def test_url_summary():
assert out_correct_versions == correct_versions assert out_correct_versions == correct_versions
@pytest.mark.skipif( @skip_python_26
sys.version_info < (2, 7), def test_url_stats(capfd, mock_packages):
reason="Python 2.6 tests are run in a container, where "
"networking is super slow"
)
def test_url_stats(capfd):
with capfd.disabled(): with capfd.disabled():
output = url('stats') output = url('stats')
npkgs = '%d packages' % len(spack.repo.all_package_names()) npkgs = '%d packages' % len(spack.repo.all_package_names())
@ -151,3 +144,20 @@ def test_url_stats(capfd):
assert 'schemes' in output assert 'schemes' in output
assert 'versions' in output assert 'versions' in output
assert 'resources' in output assert 'resources' in output
output = url('stats', '--show-issues')
npkgs = '%d packages' % len(spack.repo.all_package_names())
assert npkgs in output
assert 'url' in output
assert 'git' in output
assert 'schemes' in output
assert 'versions' in output
assert 'resources' in output
assert 'Package URLs with md5 hashes' in output
assert 'needs-relocation' in output
assert 'https://cmake.org/files/v3.4/cmake-0.0.0.tar.gz' in output
assert 'Package URLs with http urls' in output
assert 'zmpi' in output
assert 'http://www.spack-fake-zmpi.org/downloads/zmpi-1.0.tar.gz' in output

View File

@ -281,25 +281,28 @@ def test_git_url_top_level_url_versions(mock_packages, config):
pkg = spack.repo.get('git-url-top-level') pkg = spack.repo.get('git-url-top-level')
# leading 62 zeros of sha256 hash
leading_zeros = '0' * 62
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.0') fetcher = spack.fetch_strategy.for_package_version(pkg, '2.0')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://example.com/some/tarball-2.0.tar.gz' assert fetcher.url == 'https://example.com/some/tarball-2.0.tar.gz'
assert fetcher.digest == 'abc20' assert fetcher.digest == leading_zeros + '20'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.1') fetcher = spack.fetch_strategy.for_package_version(pkg, '2.1')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://example.com/some/tarball-2.1.tar.gz' assert fetcher.url == 'https://example.com/some/tarball-2.1.tar.gz'
assert fetcher.digest == 'abc21' assert fetcher.digest == leading_zeros + '21'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.2') fetcher = spack.fetch_strategy.for_package_version(pkg, '2.2')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://www.example.com/foo2.2.tar.gz' assert fetcher.url == 'https://www.example.com/foo2.2.tar.gz'
assert fetcher.digest == 'abc22' assert fetcher.digest == leading_zeros + '22'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.3') fetcher = spack.fetch_strategy.for_package_version(pkg, '2.3')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://www.example.com/foo2.3.tar.gz' assert fetcher.url == 'https://www.example.com/foo2.3.tar.gz'
assert fetcher.digest == 'abc23' assert fetcher.digest == leading_zeros + '23'
def test_git_url_top_level_git_versions(mock_packages, config): def test_git_url_top_level_git_versions(mock_packages, config):
@ -409,15 +412,15 @@ def test_fetch_options(mock_packages, config):
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.0') fetcher = spack.fetch_strategy.for_package_version(pkg, '1.0')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc10' assert fetcher.digest == '00000000000000000000000000000010'
assert fetcher.extra_options == {'timeout': 42, 'cookie': 'foobar'} assert fetcher.extra_options == {'timeout': 42, 'cookie': 'foobar'}
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.1') fetcher = spack.fetch_strategy.for_package_version(pkg, '1.1')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc11' assert fetcher.digest == '00000000000000000000000000000011'
assert fetcher.extra_options == {'timeout': 65} assert fetcher.extra_options == {'timeout': 65}
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.2') fetcher = spack.fetch_strategy.for_package_version(pkg, '1.2')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy) assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc12' assert fetcher.digest == '00000000000000000000000000000012'
assert fetcher.extra_options == {'cookie': 'baz'} assert fetcher.extra_options == {'cookie': 'baz'}

View File

@ -160,13 +160,21 @@ def test_fetch(
@pytest.mark.parametrize('spec,url,digest', [ @pytest.mark.parametrize('spec,url,digest', [
('url-list-test @0.0.0', 'foo-0.0.0.tar.gz', 'abc000'), ('url-list-test @0.0.0', 'foo-0.0.0.tar.gz', '00000000000000000000000000000000'),
('url-list-test @1.0.0', 'foo-1.0.0.tar.gz', 'abc100'), ('url-list-test @1.0.0', 'foo-1.0.0.tar.gz', '00000000000000000000000000000100'),
('url-list-test @3.0', 'foo-3.0.tar.gz', 'abc30'), ('url-list-test @3.0', 'foo-3.0.tar.gz', '00000000000000000000000000000030'),
('url-list-test @4.5', 'foo-4.5.tar.gz', 'abc45'), ('url-list-test @4.5', 'foo-4.5.tar.gz', '00000000000000000000000000000450'),
('url-list-test @2.0.0b2', 'foo-2.0.0b2.tar.gz', 'abc200b2'), (
('url-list-test @3.0a1', 'foo-3.0a1.tar.gz', 'abc30a1'), 'url-list-test @2.0.0b2',
('url-list-test @4.5-rc5', 'foo-4.5-rc5.tar.gz', 'abc45rc5'), 'foo-2.0.0b2.tar.gz',
'000000000000000000000000000200b2'
),
('url-list-test @3.0a1', 'foo-3.0a1.tar.gz', '000000000000000000000000000030a1'),
(
'url-list-test @4.5-rc5',
'foo-4.5-rc5.tar.gz',
'000000000000000000000000000045c5'
),
]) ])
@pytest.mark.parametrize('_fetch_method', ['curl', 'urllib']) @pytest.mark.parametrize('_fetch_method', ['curl', 'urllib'])
def test_from_list_url(mock_packages, config, spec, url, digest, _fetch_method): def test_from_list_url(mock_packages, config, spec, url, digest, _fetch_method):

View File

@ -1798,7 +1798,7 @@ _spack_url_summary() {
} }
_spack_url_stats() { _spack_url_stats() {
SPACK_COMPREPLY="-h --help" SPACK_COMPREPLY="-h --help --show-issues"
} }
_spack_verify() { _spack_verify() {

View File

@ -13,7 +13,7 @@ class A(AutotoolsPackage):
url = "http://www.example.com/a-1.0.tar.gz" url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash') version('2.0', 'abcdef0123456789abcdef0123456789')
variant( variant(
'foo', description='', 'foo', description='',

View File

@ -13,7 +13,7 @@ class ArchiveFiles(AutotoolsPackage):
url = "http://www.example.com/a-1.0.tar.gz" url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash') version('2.0', 'abcdef0123456789abcdef0123456789')
@property @property
def archive_files(self): def archive_files(self):

View File

@ -12,7 +12,7 @@ class BuildError(Package):
homepage = "http://www.example.com/trivial_install" homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
with open('configure', 'w') as f: with open('configure', 'w') as f:

View File

@ -12,7 +12,7 @@ class BuildWarnings(Package):
homepage = "http://www.example.com/trivial_install" homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
with open('configure', 'w') as f: with open('configure', 'w') as f:

View File

@ -10,9 +10,9 @@ class Callpath(Package):
homepage = "https://github.com/tgamblin/callpath" homepage = "https://github.com/tgamblin/callpath"
url = "http://github.com/tgamblin/callpath-1.0.tar.gz" url = "http://github.com/tgamblin/callpath-1.0.tar.gz"
version(0.8, 'foobarbaz') version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, 'foobarbaz') version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
depends_on("dyninst") depends_on("dyninst")
depends_on("mpi") depends_on("mpi")

View File

@ -10,9 +10,9 @@ class ConflictParent(Package):
homepage = 'https://github.com/tgamblin/callpath' homepage = 'https://github.com/tgamblin/callpath'
url = 'http://github.com/tgamblin/callpath-1.0.tar.gz' url = 'http://github.com/tgamblin/callpath-1.0.tar.gz'
version(0.8, 'foobarbaz') version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, 'foobarbaz') version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
depends_on('conflict') depends_on('conflict')

View File

@ -10,9 +10,9 @@ class Conflict(Package):
homepage = 'https://github.com/tgamblin/callpath' homepage = 'https://github.com/tgamblin/callpath'
url = 'http://github.com/tgamblin/callpath-1.0.tar.gz' url = 'http://github.com/tgamblin/callpath-1.0.tar.gz'
version(0.8, 'foobarbaz') version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, 'foobarbaz') version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
variant('foo', default=True, description='') variant('foo', default=True, description='')

View File

@ -12,8 +12,8 @@ class DependencyInstall(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/a-1.0.tar.gz" url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', 'hash1.0') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', 'hash2.0') version('2.0', 'abcdef0123456789abcdef0123456789')
def install(self, spec, prefix): def install(self, spec, prefix):
touch(join_path(prefix, 'an_installation_file')) touch(join_path(prefix, 'an_installation_file'))

View File

@ -8,7 +8,7 @@ class DependentOfDevBuild(Package):
homepage = "example.com" homepage = "example.com"
url = "fake.com" url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh') version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
depends_on('dev-build-test-install') depends_on('dev-build-test-install')

View File

@ -8,7 +8,7 @@ class DevBuildTestDependent(Package):
homepage = "example.com" homepage = "example.com"
url = "fake.com" url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh') version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['edit', 'install'] phases = ['edit', 'install']

View File

@ -10,7 +10,7 @@ class DevBuildTestInstallPhases(Package):
homepage = "example.com" homepage = "example.com"
url = "fake.com" url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh') version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['one', 'two', 'three', 'install'] phases = ['one', 'two', 'three', 'install']

View File

@ -8,7 +8,7 @@ class DevBuildTestInstall(Package):
homepage = "example.com" homepage = "example.com"
url = "fake.com" url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh') version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['edit', 'install'] phases = ['edit', 'install']

View File

@ -10,6 +10,6 @@ class DirectMpich(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/direct_mpich-1.0.tar.gz" url = "http://www.example.com/direct_mpich-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
depends_on('mpich') depends_on('mpich')

View File

@ -10,11 +10,11 @@ class Dyninst(Package):
homepage = "https://paradyn.org" homepage = "https://paradyn.org"
url = "http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz" url = "http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz"
version('8.2', 'cxyzab', version('8.2', '0123456789abcdef0123456789abcdef',
url='http://www.paradyn.org/release8.2/DyninstAPI-8.2.tgz') url='http://www.paradyn.org/release8.2/DyninstAPI-8.2.tgz')
version('8.1.2', 'bcxyza', version('8.1.2', 'fedcba9876543210fedcba9876543210',
url='http://www.paradyn.org/release8.1.2/DyninstAPI-8.1.2.tgz') url='http://www.paradyn.org/release8.1.2/DyninstAPI-8.1.2.tgz')
version('8.1.1', 'abcxyz', version('8.1.1', '123456789abcdef0123456789abcdef0',
url='http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz') url='http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz')
depends_on("libelf") depends_on("libelf")

View File

@ -14,7 +14,7 @@ class Extendee(Package):
extendable = True extendable = True
version('1.0', 'hash-extendee-1.0') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -16,8 +16,8 @@ class Extension1(Package):
extends('extendee') extends('extendee')
version('1.0', 'hash-extension1-1.0') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', 'hash-extension1-2.0') version('2.0', 'abcdef0123456789abcdef0123456789')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -18,7 +18,7 @@ class Extension2(Package):
extends('extendee') extends('extendee')
depends_on('extension1', type=('build', 'run')) depends_on('extension1', type=('build', 'run'))
version('1.0', 'hash-extension2-1.0') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -12,7 +12,7 @@ class FailingBuild(Package):
homepage = "http://www.example.com/trivial_install" homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
raise InstallError("Expected failure.") raise InstallError("Expected failure.")

View File

@ -10,4 +10,4 @@ class Fake(Package):
homepage = "http://www.fake-spack-example.org" homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz" url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')

View File

@ -17,6 +17,6 @@ class FetchOptions(Package):
timeout = {'timeout': 65} timeout = {'timeout': 65}
cookie = {'cookie': 'baz'} cookie = {'cookie': 'baz'}
version('1.2', 'abc12', fetch_options=cookie) version('1.2', '00000000000000000000000000000012', fetch_options=cookie)
version('1.1', 'abc11', fetch_options=timeout) version('1.1', '00000000000000000000000000000011', fetch_options=timeout)
version('1.0', 'abc10') version('1.0', '00000000000000000000000000000010')

View File

@ -10,8 +10,8 @@ class Fftw(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/fftw-1.0.tar.gz" url = "http://www.example.com/fftw-1.0.tar.gz"
version(2.0, 'foobar') version(2.0, 'abcdef1234567890abcdef1234567890')
version(1.0, 'foobar') version(1.0, '1234567890abcdef1234567890abcdef')
variant('mpi', default=False, description='Enable MPI') variant('mpi', default=False, description='Enable MPI')

View File

@ -13,7 +13,7 @@ class FindExternals1(AutotoolsPackage):
url = "http://www.example.com/find-externals-1.0.tar.gz" url = "http://www.example.com/find-externals-1.0.tar.gz"
version('1.0', 'hash-1.0') version('1.0', 'abcdef1234567890abcdef1234567890')
@classmethod @classmethod
def determine_spec_details(cls, prefix, exes_in_prefix): def determine_spec_details(cls, prefix, exes_in_prefix):

View File

@ -13,8 +13,8 @@ class Gcc(Package):
url = "http://www.example.com/gcc-1.0.tar.gz" url = "http://www.example.com/gcc-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash') version('2.0', 'abcdef0123456789abcdef0123456789')
version('3.0', '3.0_a_hash') version('3.0', 'def0123456789abcdef0123456789abc')
depends_on('conflict', when='@3.0') depends_on('conflict', when='@3.0')

View File

@ -28,13 +28,35 @@ class GitUrlTopLevel(Package):
version('3.0', tag='v3.0') version('3.0', tag='v3.0')
# These resolve to URL fetchers # These resolve to URL fetchers
version('2.3', 'abc23', url='https://www.example.com/foo2.3.tar.gz') version(
version('2.2', sha256='abc22', url='https://www.example.com/foo2.2.tar.gz') '2.3', '0000000000000000000000000000000000000000000000000000000000000023',
version('2.1', sha256='abc21') url='https://www.example.com/foo2.3.tar.gz',
version('2.0', 'abc20') )
version(
'2.2',
sha256='0000000000000000000000000000000000000000000000000000000000000022',
url='https://www.example.com/foo2.2.tar.gz',
)
version(
'2.1',
sha256='0000000000000000000000000000000000000000000000000000000000000021',
)
version(
'2.0',
'0000000000000000000000000000000000000000000000000000000000000020',
)
# These result in a FetcherConflict b/c we can't tell what to use # These result in a FetcherConflict b/c we can't tell what to use
version('1.3', sha256='abc13', commit='abc13') version(
version('1.2', sha512='abc12', branch='releases/v1.2') '1.3',
version('1.1', md5='abc11', tag='v1.1') sha256='f66bbef3ccb8b06542c57d69804c5b0aba72051f693c17761ad8525786d259fa',
version('1.0', 'abc11', tag='abc123') commit='abc13'
)
version(
'1.2',
sha512='f66bbef3ccb8b06542c57d69804c5b0aba72051f693c17761ad8525786d259fa'
'9ed8f2e950a4fb8a4b936f33e689187784699357bc16e49f33dfcda8ab8b00e4',
branch='releases/v1.2'
)
version('1.1', md5='00000000000000000000000000000011', tag='v1.1')
version('1.0', '00000000000000000000000000000011', tag='abc123')

View File

@ -3,8 +3,10 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Gmt(Package): class Gmt(Package):
url = "http://www.example.com/"
url = "http://www.example.com/2.0.tar.gz"
version('2.0', 'abcdef') version('2.0', 'abcdef1234567890abcdef1234567890')
version('1.0', 'abcdef') version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('mvdefaults', when='@1.0') depends_on('mvdefaults', when='@1.0')

View File

@ -8,7 +8,7 @@ class Hdf5(Package):
homepage = "http://www.llnl.gov" homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/hdf5-1.0.tar.gz" url = "http://www.llnl.gov/hdf5-1.0.tar.gz"
version(2.3, 'foobarbaz') version(2.3, '0123456789abcdef0123456789abcdef')
variant('mpi', default=True, description='Enable mpi') variant('mpi', default=True, description='Enable mpi')

View File

@ -10,6 +10,6 @@ class ImpossibleConcretization(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/example-1.0.tar.gz" url = "http://www.example.com/example-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
conflicts('target=x86_64:') conflicts('target=x86_64:')

View File

@ -14,7 +14,7 @@ class IndirectMpich(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/indirect_mpich-1.0.tar.gz" url = "http://www.example.com/indirect_mpich-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
depends_on('mpi') depends_on('mpi')
depends_on('direct-mpich') depends_on('direct-mpich')

View File

@ -3,7 +3,10 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class LeafAddsVirtual(Package): class LeafAddsVirtual(Package):
version('2.0', sha256='abcde') url = "http://www.example.com/"
version('1.0', sha256='abcde') url = "http://www.example.com/2.0.tar.gz"
version('2.0', 'abcdef1234567890abcdef1234567890')
version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('blas', when='@2.0') depends_on('blas', when='@2.0')

View File

@ -15,9 +15,9 @@ class Libdwarf(Package):
list_url = homepage list_url = homepage
version(20130729, "64b42692e947d5180e162e46c689dfbf") version(20130729, "64b42692e947d5180e162e46c689dfbf")
version(20130207, 'foobarbaz') version(20130207, '0123456789abcdef0123456789abcdef')
version(20111030, 'foobarbaz') version(20111030, '0123456789abcdef0123456789abcdef')
version(20070703, 'foobarbaz') version(20070703, '0123456789abcdef0123456789abcdef')
depends_on("libelf") depends_on("libelf")

View File

@ -3,5 +3,9 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class MiddleAddsVirtual(Package): class MiddleAddsVirtual(Package):
version('1.0', sha256='abcde') url = "http://www.example.com/"
url = "http://www.example.com/2.0.tar.gz"
version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('leaf-adds-virtual') depends_on('leaf-adds-virtual')

View File

@ -9,6 +9,6 @@
class Mixedversions(Package): class Mixedversions(Package):
url = "http://www.fake-mixedversions.org/downloads/mixedversions-1.0.tar.gz" url = "http://www.fake-mixedversions.org/downloads/mixedversions-1.0.tar.gz"
version('2.0.1', 'hashc') version('2.0.1', '0000000000000000000000000000000c')
version('2.0', 'hashb') version('2.0', '0000000000000000000000000000000b')
version('1.0.1', 'hasha') version('1.0.1', '0000000000000000000000000000000a')

View File

@ -10,7 +10,7 @@ class ModulePathSeparator(Package):
homepage = "http://www.llnl.gov" homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/module-path-separator-1.0.tar.gz" url = "http://www.llnl.gov/module-path-separator-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
def setup_environment(self, senv, renv): def setup_environment(self, senv, renv):
renv.append_path("COLON", "foo") renv.append_path("COLON", "foo")

View File

@ -18,11 +18,11 @@ class Mpich(Package):
description="Compile MPICH with debug flags.") description="Compile MPICH with debug flags.")
version('3.0.4', '9c5d5d4fe1e17dd12153f40bc5b6dbc0') version('3.0.4', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
version('3.0.3', 'foobarbaz') version('3.0.3', '0123456789abcdef0123456789abcdef')
version('3.0.2', 'foobarbaz') version('3.0.2', '0123456789abcdef0123456789abcdef')
version('3.0.1', 'foobarbaz') version('3.0.1', '0123456789abcdef0123456789abcdef')
version('3.0', 'foobarbaz') version('3.0', '0123456789abcdef0123456789abcdef')
version('1.0', 'foobarbas') version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:3', when='@3:') provides('mpi@:3', when='@3:')
provides('mpi@:1', when='@:1') provides('mpi@:1', when='@:1')

View File

@ -15,11 +15,11 @@ class Mpich2(Package):
tags = ['tag1', 'tag3'] tags = ['tag1', 'tag3']
version('1.5', '9c5d5d4fe1e17dd12153f40bc5b6dbc0') version('1.5', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
version('1.4', 'foobarbaz') version('1.4', '0123456789abcdef0123456789abcdef')
version('1.3', 'foobarbaz') version('1.3', '0123456789abcdef0123456789abcdef')
version('1.2', 'foobarbaz') version('1.2', '0123456789abcdef0123456789abcdef')
version('1.1', 'foobarbaz') version('1.1', '0123456789abcdef0123456789abcdef')
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:2.0') provides('mpi@:2.0')
provides('mpi@:2.1', when='@1.1:') provides('mpi@:2.1', when='@1.1:')

View File

@ -10,10 +10,10 @@ class Mpileaks(Package):
homepage = "http://www.llnl.gov" homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz" url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
version(2.1, 'foobarbaz') version(2.1, '0123456789abcdef0123456789abcdef')
version(2.2, 'foobarbaz') version(2.2, '0123456789abcdef0123456789abcdef')
version(2.3, 'foobarbaz') version(2.3, '0123456789abcdef0123456789abcdef')
variant('debug', default=False, description='Debug variant') variant('debug', default=False, description='Debug variant')
variant('opt', default=False, description='Optimized variant') variant('opt', default=False, description='Optimized variant')

View File

@ -12,13 +12,13 @@ class MultiProviderMpi(Package):
homepage = "http://www.spack-fake-mpi.org" homepage = "http://www.spack-fake-mpi.org"
url = "http://www.spack-fake-mpi.org/downloads/multi-mpi-1.0.tar.gz" url = "http://www.spack-fake-mpi.org/downloads/multi-mpi-1.0.tar.gz"
version('2.0.0', 'foobarbaz') version('2.0.0', '0123456789abcdef0123456789abcdef')
version('1.10.3', 'foobarbaz') version('1.10.3', '0123456789abcdef0123456789abcdef')
version('1.10.2', 'foobarbaz') version('1.10.2', '0123456789abcdef0123456789abcdef')
version('1.10.1', 'foobarbaz') version('1.10.1', '0123456789abcdef0123456789abcdef')
version('1.10.0', 'foobarbaz') version('1.10.0', '0123456789abcdef0123456789abcdef')
version('1.8.8', 'foobarbaz') version('1.8.8', '0123456789abcdef0123456789abcdef')
version('1.6.5', 'foobarbaz') version('1.6.5', '0123456789abcdef0123456789abcdef')
provides('mpi@3.1', when='@2.0.0') provides('mpi@3.1', when='@2.0.0')
provides('mpi@3.0', when='@1.10.3') provides('mpi@3.0', when='@1.10.3')

View File

@ -10,10 +10,10 @@ class MultivalueVariant(Package):
homepage = "http://www.llnl.gov" homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz" url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
version(2.1, 'foobarbaz') version(2.1, '0123456789abcdef0123456789abcdef')
version(2.2, 'foobarbaz') version(2.2, '0123456789abcdef0123456789abcdef')
version(2.3, 'foobarbaz') version(2.3, '0123456789abcdef0123456789abcdef')
variant('debug', default=False, description='Debug variant') variant('debug', default=False, description='Debug variant')
variant( variant(

View File

@ -3,8 +3,10 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Mvdefaults(Package): class Mvdefaults(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/mvdefaults-1.0.tar.gz"
version('1.0', 'abcdef') version('1.0', 'abcdef1234567890abcdef1234567890')
variant('foo', values=('a', 'b', 'c'), default=('a', 'b', 'c'), variant('foo', values=('a', 'b', 'c'), default=('a', 'b', 'c'),
multi=True, description='') multi=True, description='')

View File

@ -14,7 +14,7 @@ class OverrideContextTemplates(Package):
homepage = "http://www.fake-spack-example.org" homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz" url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
tcl_template = 'extension.tcl' tcl_template = 'extension.tcl'
tcl_context = {'sentence': "sentence from package"} tcl_context = {'sentence': "sentence from package"}

View File

@ -10,7 +10,7 @@ class OverrideModuleTemplates(Package):
homepage = "http://www.fake-spack-example.org" homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz" url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
tcl_template = 'override.txt' tcl_template = 'override.txt'
lmod_template = 'override.txt' lmod_template = 'override.txt'

View File

@ -13,8 +13,8 @@ class PerlExtension(PerlPackage):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/extension1-1.0.tar.gz" url = "http://www.example.com/extension1-1.0.tar.gz"
version('1.0', 'hash-extension-1.0') version('1.0', '00000000000000000000000000000010')
version('2.0', 'hash-extension-2.0') version('2.0', '00000000000000000000000000000020')
extends("perl") extends("perl")

View File

@ -12,4 +12,4 @@ class Perl(Package):
extendable = True extendable = True
version('0.0.0', 'hash') version('0.0.0', 'abcdef1234567890abcdef1234567890')

View File

@ -14,7 +14,7 @@ class PrintingPackage(Package):
homepage = "http://www.example.com/printing_package" homepage = "http://www.example.com/printing_package"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
print("BEFORE INSTALL") print("BEFORE INSTALL")

View File

@ -16,8 +16,8 @@ class PyExtension1(PythonPackage):
# Override settings in base class # Override settings in base class
maintainers = [] maintainers = []
version('1.0', 'hash-extension1-1.0') version('1.0', '00000000000000000000000000000110')
version('2.0', 'hash-extension1-2.0') version('2.0', '00000000000000000000000000000120')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -20,7 +20,7 @@ class PyExtension2(PythonPackage):
extends("python") extends("python")
depends_on('py-extension1', type=('build', 'run')) depends_on('py-extension1', type=('build', 'run'))
version('1.0', 'hash-extension2-1.0') version('1.0', '00000000000000000000000000000210')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -16,6 +16,6 @@ class PyExtension3(Package):
depends_on('patchelf@0.9', when='@1.0:1.1 ^python@:2') depends_on('patchelf@0.9', when='@1.0:1.1 ^python@:2')
depends_on('patchelf@0.10', when='@1.0:1.1 ^python@3:') depends_on('patchelf@0.10', when='@1.0:1.1 ^python@3:')
version('2.0', 'hash-extension3-1.0') version('2.0', '00000000000000000000000000000320')
version('1.1', 'hash-extension3-1.0') version('1.1', '00000000000000000000000000000311')
version('1.0', 'hash-extension3-1.0') version('1.0', '00000000000000000000000000000310')

View File

@ -10,7 +10,7 @@ class QuantumEspresso(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/qe-1.0.tar.gz" url = "http://www.example.com/qe-1.0.tar.gz"
version(1.0, 'foobar') version(1.0, '1234567890abcdef1234567890abcdef')
variant('invino', default=True, description='?') variant('invino', default=True, description='?')
variant('veritas', default=True, description='?') variant('veritas', default=True, description='?')

View File

@ -17,7 +17,7 @@ class Raiser(Package):
url = "http://www.example.com/a-1.0.tar.gz" url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef') version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash') version('2.0', 'abcdef0123456789abcdef0123456789')
variant( variant(
'exc_type', 'exc_type',

View File

@ -11,6 +11,6 @@ class RequiresVirtual(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/a-1.0.tar.gz" url = "http://www.example.com/a-1.0.tar.gz"
version('2.0', '2.0_a_hash') version('2.0', 'abcdef0123456789abcdef0123456789')
depends_on('stuff') depends_on('stuff')

View File

@ -3,6 +3,9 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class RootAddsVirtual(Package): class RootAddsVirtual(Package):
version('1.0', sha256='abcde') homepage = "http://www.example.com"
url = "http://www.example.com/root-adds-virtual-1.0.tar.gz"
version('1.0', sha256='abcdef0123456789abcdef0123456789')
depends_on('middle-adds-virtual') depends_on('middle-adds-virtual')

View File

@ -3,6 +3,9 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Root(Package): class Root(Package):
version('1.0', 'abcdef') homepage = "http://www.example.com"
url = "http://www.example.com/root-1.0.tar.gz"
version('1.0', 'abcdef0123456789abcdef0123456789')
depends_on('gmt') depends_on('gmt')

View File

@ -8,7 +8,7 @@ class SinglevalueVariant(Package):
homepage = "http://www.llnl.gov" homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz" url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz') version(1.0, '0123456789abcdef0123456789abcdef')
variant( variant(
'fum', 'fum',

View File

@ -12,7 +12,7 @@ class TestError(Package):
homepage = "http://www.example.com/test-failure" homepage = "http://www.example.com/test-failure"
url = "http://www.test-failure.test/test-failure-1.0.tar.gz" url = "http://www.test-failure.test/test-failure-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -12,7 +12,7 @@ class TestFail(Package):
homepage = "http://www.example.com/test-failure" homepage = "http://www.example.com/test-failure"
url = "http://www.test-failure.test/test-failure-1.0.tar.gz" url = "http://www.test-failure.test/test-failure-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
mkdirp(prefix.bin) mkdirp(prefix.bin)

View File

@ -7,6 +7,6 @@ class TriggerExternalNonDefaultVariant(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.someurl.tar.gz" url = "http://www.someurl.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
depends_on('external-non-default-variant') depends_on('external-non-default-variant')

View File

@ -12,7 +12,7 @@ class TrivialInstallTestPackage(Package):
homepage = "http://www.example.com/trivial_install" homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix): def install(self, spec, prefix):
configure('--prefix=%s' % prefix) configure('--prefix=%s' % prefix)

View File

@ -11,7 +11,7 @@ class TrivialSmokeTest(Package):
homepage = "http://www.example.com/trivial_test" homepage = "http://www.example.com/trivial_test"
url = "http://www.unit-test-should-replace-this-url/trivial_test-1.0.tar.gz" url = "http://www.unit-test-should-replace-this-url/trivial_test-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
test_source_filename = 'cached_file.in' test_source_filename = 'cached_file.in'

View File

@ -7,7 +7,7 @@ class UnsatProvider(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/v1.0.tgz" url = "http://www.example.com/v1.0.tgz"
version('1.0', sha256='foobarbaz') version('1.0', sha256='0123456789abcdef0123456789abcdef')
variant('foo', default=True, description='') variant('foo', default=True, description='')

View File

@ -7,6 +7,6 @@ class UnsatVirtualDependency(Package):
homepage = "http://www.example.com" homepage = "http://www.example.com"
url = "http://www.example.com/v1.0.tgz" url = "http://www.example.com/v1.0.tgz"
version('1.0', sha256='foobarbaz') version('1.0', sha256='0123456789abcdef0123456789abcdef')
depends_on('unsatvdep') depends_on('unsatvdep')

View File

@ -16,10 +16,10 @@ class UrlListTest(Package):
list_url = 'file://' + web_data_path + '/index.html' list_url = 'file://' + web_data_path + '/index.html'
list_depth = 3 list_depth = 3
version('0.0.0', 'abc000') version('0.0.0', '00000000000000000000000000000000')
version('1.0.0', 'abc100') version('1.0.0', '00000000000000000000000000000100')
version('3.0', 'abc30') version('3.0', '00000000000000000000000000000030')
version('4.5', 'abc45') version('4.5', '00000000000000000000000000000450')
version('2.0.0b2', 'abc200b2') version('2.0.0b2', '000000000000000000000000000200b2')
version('3.0a1', 'abc30a1') version('3.0a1', '000000000000000000000000000030a1')
version('4.5-rc5', 'abc45rc5') version('4.5-rc5', '000000000000000000000000000045c5')

View File

@ -9,10 +9,13 @@
class UrlOnlyOverrideWithGaps(Package): class UrlOnlyOverrideWithGaps(Package):
homepage = 'http://www.example.com' homepage = 'http://www.example.com'
version('1.0.5', 'abcdef0') version('1.0.5', 'abcdef0123456789abcdef0123456789')
version('1.0.0', 'bcdef0a', url='http://a.example.com/url_override-1.0.0.tar.gz') version('1.0.0', 'bcdef0123456789abcdef0123456789a',
version('0.9.5', 'cdef0ab') url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.0', 'def0abc', url='http://b.example.com/url_override-0.9.0.tar.gz') version('0.9.5', 'cdef0123456789abcdef0123456789ab')
version('0.8.5', 'ef0abcd') version('0.9.0', 'def0123456789abcdef0123456789abc',
version('0.8.1', 'f0abcde', url='http://c.example.com/url_override-0.8.1.tar.gz') url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.7.0', '0abcdef') version('0.8.5', 'ef0123456789abcdef0123456789abcd')
version('0.8.1', 'f0123456789abcdef0123456789abcde',
url='http://c.example.com/url_override-0.8.1.tar.gz')
version('0.7.0', '0123456789abcdef0123456789abcdef')

View File

@ -9,6 +9,6 @@
class UrlOnlyOverride(Package): class UrlOnlyOverride(Package):
homepage = 'http://www.example.com' homepage = 'http://www.example.com'
version('1.0.0', 'cxyzab', url='http://a.example.com/url_override-1.0.0.tar.gz') version('1.0.0', '0123456789abcdef0123456789abcdef', url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.0', 'bcxyza', url='http://b.example.com/url_override-0.9.0.tar.gz') version('0.9.0', 'fedcba9876543210fedcba9876543210', url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.8.1', 'cxyzab', url='http://c.example.com/url_override-0.8.1.tar.gz') version('0.8.1', '0123456789abcdef0123456789abcdef', url='http://c.example.com/url_override-0.8.1.tar.gz')

View File

@ -10,6 +10,6 @@ class UrlOverride(Package):
homepage = 'http://www.doesnotexist.org' homepage = 'http://www.doesnotexist.org'
url = 'http://www.doesnotexist.org/url_override-1.0.0.tar.gz' url = 'http://www.doesnotexist.org/url_override-1.0.0.tar.gz'
version('1.0.0', 'cxyzab') version('1.0.0', '0123456789abcdef0123456789abcdef')
version('0.9.0', 'bcxyza', url='http://www.anothersite.org/uo-0.9.0.tgz') version('0.9.0', 'fedcba9876543210fedcba9876543210', url='http://www.anothersite.org/uo-0.9.0.tgz')
version('0.8.1', 'cxyzab') version('0.8.1', '0123456789abcdef0123456789abcdef')

View File

@ -12,7 +12,7 @@ class Zmpi(Package):
homepage = "http://www.spack-fake-zmpi.org" homepage = "http://www.spack-fake-zmpi.org"
url = "http://www.spack-fake-zmpi.org/downloads/zmpi-1.0.tar.gz" url = "http://www.spack-fake-zmpi.org/downloads/zmpi-1.0.tar.gz"
version('1.0', 'foobarbaz') version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:10.0') provides('mpi@:10.0')
depends_on('fake') depends_on('fake')