Skip to content

Commit 3d34735

Browse files
authored
Use gen_project.jl to generate the Project.toml file (#26)
1 parent 3dec910 commit 3d34735

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

Project.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name = "Git"
2+
uuid = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2"
3+
4+
[deps]
5+
BinDeps = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
6+
Homebrew = "d9be37ee-ecc9-5288-90f1-b9ca67657a75"
7+
VersionParsing = "81def892-9a0e-5fdd-b105-ffc91e053289"
8+
9+
[compat]
10+
julia = "≥ 0.7.0"
11+
12+
[extras]
13+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
14+
15+
[targets]
16+
test = ["Test"]

gen_project.jl

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#!/usr/bin/env julia
2+
3+
import Pkg
4+
import Pkg.Types: VersionSpec, VersionRange, VersionBound, semver_spec
5+
import Base: thismajor, thisminor, thispatch, nextmajor, nextminor, nextpatch
6+
7+
const STDLIBS = [
8+
"Base64"
9+
"CRC32c"
10+
"Dates"
11+
"DelimitedFiles"
12+
"Distributed"
13+
"FileWatching"
14+
"Future"
15+
"InteractiveUtils"
16+
"Libdl"
17+
"LibGit2"
18+
"LinearAlgebra"
19+
"Logging"
20+
"Markdown"
21+
"Mmap"
22+
"Pkg"
23+
"Printf"
24+
"Profile"
25+
"Random"
26+
"REPL"
27+
"Serialization"
28+
"SHA"
29+
"SharedArrays"
30+
"Sockets"
31+
"SparseArrays"
32+
"Statistics"
33+
"SuiteSparse"
34+
"Test"
35+
"Unicode"
36+
"UUIDs"
37+
]
38+
39+
function uuid(name::AbstractString)
40+
if name == "Pkg"
41+
return "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
42+
elseif name == "Statistics"
43+
return "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
44+
else
45+
string(Pkg.METADATA_compatible_uuid(String(name)))
46+
end
47+
end
48+
49+
function uses(repo::AbstractString, lib::AbstractString)
50+
pattern = string(raw"\b(import|using)\s+((\w|\.)+\s*,\s*)*", lib, raw"\b")
51+
success(`git -C $repo grep -Eq $pattern -- '*.jl'`)
52+
end
53+
54+
function semver(intervals)
55+
spec = String[]
56+
for ival in intervals
57+
if ival.upper == v""
58+
push!(spec, "$(thispatch(ival.lower))")
59+
else
60+
lo, hi = ival.lower, ival.upper
61+
if lo.major < hi.major
62+
push!(spec, "^$(lo.major).$(lo.minor).$(lo.patch)")
63+
for major = lo.major+1:hi.major-1
64+
push!(spec, "~$major")
65+
end
66+
for minor = 0:hi.minor-1
67+
push!(spec, "~$(hi.major).$minor")
68+
end
69+
for patch = 0:hi.patch-1
70+
push!(spec, "=$(hi.major).$(hi.minor).$patch")
71+
end
72+
elseif lo.minor < hi.minor
73+
push!(spec, "~$(lo.major).$(lo.minor).$(lo.patch)")
74+
for minor = lo.minor+1:hi.minor-1
75+
push!(spec, "~$(hi.major).$minor")
76+
end
77+
for patch = 0:hi.patch-1
78+
push!(spec, "=$(hi.major).$(hi.minor).$patch")
79+
end
80+
else
81+
for patch = lo.patch:hi.patch-1
82+
push!(spec, "=$(hi.major).$(hi.minor).$patch")
83+
end
84+
end
85+
end
86+
end
87+
return join(spec, ", ")
88+
end
89+
90+
if !isempty(ARGS) && ARGS[1] == "-f"
91+
const force = true
92+
popfirst!(ARGS)
93+
else
94+
const force = false
95+
end
96+
isempty(ARGS) && (push!(ARGS, pwd()))
97+
98+
for arg in ARGS
99+
dir = abspath(expanduser(arg))
100+
isdir(dir) ||
101+
error("$arg does not appear to be a package (not a directory)")
102+
103+
name = basename(dir)
104+
if isempty(name)
105+
dir = dirname(dir)
106+
name = basename(dir)
107+
end
108+
endswith(name, ".jl") && (name = chop(name, tail=3))
109+
110+
project_file = joinpath(dir, "Project.toml")
111+
!force && isfile(project_file) &&
112+
error("$arg already has a project file")
113+
114+
require_file = joinpath(dir, "REQUIRE")
115+
isfile(require_file) ||
116+
error("$arg does not appear to be a package (no REQUIRE file)")
117+
118+
project = Dict(
119+
"name" => name,
120+
"uuid" => uuid(name),
121+
"deps" => Dict{String,String}(),
122+
"compat" => Dict{String,String}(),
123+
"extras" => Dict{String,String}(),
124+
)
125+
126+
test_require_file = joinpath(dir, "test", "REQUIRE")
127+
128+
for (file, section) in ((require_file, "deps"),
129+
(test_require_file, "extras"))
130+
isfile(file) || continue
131+
reqs = Pkg.Pkg2.Reqs.read(file)
132+
for req in reqs
133+
req isa Pkg.Pkg2.Reqs.Requirement || continue
134+
dep = String(req.package)
135+
if dep != "julia"
136+
project[section][dep] = uuid(dep)
137+
end
138+
if req.versions != Pkg.Pkg2.Pkg2Types.VersionSet()
139+
project["compat"][dep] = semver(req.versions.intervals)
140+
end
141+
end
142+
end
143+
144+
for (srcdir, section) in (("src" => "deps"), ("test", "extras"))
145+
for stdlib in STDLIBS
146+
if uses(joinpath(dir, srcdir), stdlib)
147+
project[section][stdlib] = uuid(stdlib)
148+
end
149+
end
150+
end
151+
152+
if !isempty(project["extras"])
153+
project["targets"] = Dict("test" => collect(keys(project["extras"])))
154+
haskey(project["deps"], "Test") && delete!(project["deps"], "Test")
155+
end
156+
157+
println(stderr, "Generating project file for $name: $project_file")
158+
open(project_file, "w") do io
159+
Pkg.TOML.print(io, project, sorted=true)
160+
end
161+
project = Pkg.Types.read_project(project_file)
162+
Pkg.Types.write_project(project, project_file)
163+
end
164+

0 commit comments

Comments
 (0)