4
import Base.isequal, Base.isless, Base.contains, Base.hash
6
export parse_requires, Version, VersionSet
8
function gen_versions(pkg::String)
9
for (ver,sha1) in Git.each_tagged_version(pkg)
10
dir = "METADATA/$pkg/versions/$ver"
12
open("$dir/sha1","w") do io
15
if isfile("$pkg/REQUIRE")
16
run(`cp $pkg/REQUIRE $dir/requires`)
20
gen_versions() = for pkg in each_package() gen_versions(pkg) end
22
function gen_hashes(pkg::String)
23
for (ver,dir) in each_tagged_version(pkg)
24
sha1 = readchomp("$dir/sha1")
25
run(`mkdir -p METADATA/$pkg/hashes`)
26
open("METADATA/$pkg/hashes/$sha1","w") do io
31
gen_hashes() = for pkg in each_package() gen_hashes(pkg) end
33
function pkg_url(pkg::String)
34
path = "METADATA/$pkg/url"
35
isfile(path) ? readchomp(path) : nothing
38
function version(pkg::String, sha1::String)
39
path = "METADATA/$pkg/hashes/$sha1"
40
isfile(path) || Metadata.gen_hashes(pkg)
41
isfile(path) ? convert(VersionNumber,readchomp(path)) : sha1
44
each_package() = @task begin
45
for line in each_line(`ls -1 METADATA`)
47
# stat() chokes if we try to check if the subdirectory of a non-directory exists
48
if isdir(joinpath("METADATA", line)) && isdir(joinpath("METADATA", line, "versions"))
54
each_tagged_version(pkg::String) = @task begin
55
for line in each_line(`ls -1 $(joinpath("METADATA", pkg, "versions"))`)
57
if isdir(joinpath("METADATA", pkg, "versions", line)) && ismatch(Base.VERSION_REGEX, line)
58
ver = convert(VersionNumber,line)
59
dir = "METADATA/$pkg/versions/$(line)"
60
if isfile("$dir/sha1")
69
for pkg in each_package()
77
version::VersionNumber
80
isequal(a::Version, b::Version) =
81
a.package == b.package && a.version == b.version
82
function isless(a::Version, b::Version)
83
(a.package < b.package) && return true
84
(a.package > b.package) && return false
85
return a.version < b.version
88
function versions(pkgs)
91
for (ver,dir) in each_tagged_version(pkg)
92
push!(vers,Version(pkg,ver))
97
versions() = versions(packages())
99
hash(v::Version) = hash([v.(n) for n in Version.names])
103
versions::Vector{VersionNumber}
105
function VersionSet(pkg::ByteString, vers::Vector{VersionNumber})
107
error("version numbers must be sorted")
112
VersionSet(pkg::ByteString) = VersionSet(pkg, VersionNumber[])
114
isequal(a::VersionSet, b::VersionSet) =
115
a.package == b.package && a.versions == b.versions
116
isless(a::VersionSet, b::VersionSet) = a.package < b.package
118
function contains(s::VersionSet, v::Version)
119
(s.package != v.package) && return false
120
for i in length(s.versions):-1:1
121
(v.version >= s.versions[i]) && return isodd(i)
123
return isempty(s.versions)
126
hash(s::VersionSet) = hash([s.(n) for n in VersionSet.names])
128
function parse_requires(file::String)
131
for line in each_line(io)
132
if ismatch(r"^\s*(?:#|$)", line) continue end
133
line = replace(line, r"#.*$", "")
136
vers = [ convert(VersionNumber,x) for x=fields ]
138
error("invalid requires entry for $pkg in $file: $vers")
140
# TODO: merge version sets instead of appending?
141
push!(reqs,VersionSet(pkg,vers))
147
function dependencies(pkgs,vers)
148
deps = Array((Version,VersionSet),0)
149
for pkg in each_package()
150
for (ver,dir) in each_tagged_version(pkg)
152
file = "$dir/requires"
154
for d in parse_requires("$dir/requires")
155
if !contains(pkgs,d.package)
156
error("Unknown dependency for $pkg: $(d.package)")
166
older(a::Version, b::Version) = a.package == b.package && a.version < b.version