/
Pkg.jl
376 lines (290 loc) · 11.8 KB
/
Pkg.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# This file is a part of Julia. License is MIT: https://julialang.org/license
module Pkg
import Random
import REPL
export @pkg_str
export PackageSpec
export PackageMode, PKGMODE_MANIFEST, PKGMODE_PROJECT
export UpgradeLevel, UPLEVEL_MAJOR, UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH
depots() = Base.DEPOT_PATH
function depots1()
d = depots()
isempty(d) && Pkg.Types.pkgerror("no depots found in DEPOT_PATH")
return d[1]
end
logdir() = joinpath(depots1(), "logs")
devdir() = get(ENV, "JULIA_PKG_DEVDIR", joinpath(depots1(), "dev"))
envdir(depot = depots1()) = joinpath(depot, "environments")
const UPDATED_REGISTRY_THIS_SESSION = Ref(false)
# load snapshotted dependencies
include("../ext/TOML/src/TOML.jl")
include("GitTools.jl")
include("PlatformEngines.jl")
include("Types.jl")
include("Display.jl")
include("Pkg2/Pkg2.jl")
include("GraphType.jl")
include("Resolve.jl")
include("Operations.jl")
include("API.jl")
include("REPLMode.jl")
import .REPLMode: @pkg_str
import .Types: UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH, UPLEVEL_FIXED
import .Types: PKGMODE_MANIFEST, PKGMODE_PROJECT
# legacy CI script support
import .API: clone, dir
"""
PackageMode
An enum with the instances
* `PKGMODE_MANIFEST`
* `PKGMODE_PROJECT`
Determines if operations should be made on a project or manifest level.
Used as an argument to [`PackageSpec`](@ref) or as an argument to [`Pkg.rm`](@ref).
"""
const PackageMode = Types.PackageMode
"""
UpgradeLevel
An enum with the instances
* `UPLEVEL_FIXED`
* `UPLEVEL_PATCH`
* `UPLEVEL_MINOR`
* `UPLEVEL_MAJOR`
Determines how much a package is allowed to be updated.
Used as an argument to [`PackageSpec`](@ref) or as an argument to [`Pkg.update`](@ref).
"""
const UpgradeLevel = Types.UpgradeLevel
# Define new variables so tab comleting Pkg. works.
"""
Pkg.add(pkg::Union{String, Vector{String}})
Pkg.add(pkg::Union{PackageSpec, Vector{PackageSpec}})
Add a package to the current project. This package will be available using the
`import` and `using` keywords in the Julia REPL and if the current project is
a package, also inside that package.
# Examples
```julia
Pkg.add("Example") # Add a package from registry
Pkg.add(PackageSpec(name="Example", version="0.3")) # Specify version
Pkg.add(PackageSpec(url="https://github.com/JuliaLang/Example.jl", rev="master")) # From url to remote gitrepo
Pkg.add(PackageSpec(url="/remote/mycompany/juliapackages/OurPackage"))` # From path to local gitrepo
```
See also [`PackageSpec`](@ref).
"""
const add = API.add
"""
Pkg.rm(pkg::Union{String, Vector{String}})
Pkg.rm(pkg::Union{PackageSpec, Vector{PackageSpec}})
Remove a package from the current project. If the `mode` of `pkg` is
`PKGMODE_MANIFEST` also remove it from the manifest including all
recursive dependencies of `pkg`.
See also [`PackageSpec`](@ref), [`PackageMode`](@ref).
"""
const rm = API.rm
"""
Pkg.update(; level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode = PKGMODE_PROJECT)
Pkg.update(pkg::Union{String, Vector{String}})
Pkg.update(pkg::Union{PackageSpec, Vector{PackageSpec}})
Update a package `pkg`. If no posistional argument is given, update all packages in the manifest if `mode` is `PKGMODE_MANIFEST` and packages in both manifest and project if `mode` is `PKGMODE_PROJECT`.
If no positional argument is given `level` can be used to control what how much packages are allowed to be upgraded (major, minor, patch, fixed).
See also [`PackageSpec`](@ref), [`PackageMode`](@ref), [`UpgradeLevel`](@ref).
"""
const update = API.up
"""
Pkg.test(; coverage::Bool=false)
Pkg.test(pkg::Union{String, Vector{String}; coverage::Bool=false)
Pkg.test(pkgs::Union{PackageSpec, Vector{PackageSpec}}; coverage::Bool=false)
Run the tests for package `pkg` or if no positional argument is given to `test`,
the current project is tested (which thus needs to be a package).
A package is tested by running its `test/runtests.jl` file.
The tests are run by generating a temporary environment with only `pkg` and its (recursive) dependencies
(recursively) in it. If a manifest exist, the versions in that manifest is used, otherwise
a feasible set of package are resolved and installed.
During the test, test-specific dependencies are active, which are
given in the project file as e.g.
```
[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Test"]
```
Coverage statistics for the packages may be generated by
passing `coverage=true`. The default behavior is not to run coverage.
The tests are executed in a new process with `check-bounds=yes` and by default `startup-file=no`.
If using the startup file (`~/.julia/config/startup.jl`) is desired, start julia with `--startup-file=yes`.
"""
const test = API.test
"""
Pkg.gc()
Garbage collect packages that are no longer reachable from any project.
Only packages that are tracked by version are deleted, so no packages
that might contain local changes are touched.
"""
const gc = API.gc
"""
Pkg.build()
Pkg.build(pkg::Union{String, Vector{String}})
Pkg.build(pkgs::Union{PackageSpec, Vector{PackageSpec}})
Run the build script in `deps/build.jl` for `pkg` and all of the dependencies in
depth-first recursive order.
If no argument is given to `build`, the current project is built, which thus needs
to be a package.
This function is called automatically one any package that gets installed
for the first time.
"""
const build = API.build
# TODO: decide what to do with this
const installed = API.installed
"""
Pkg.pin(pkg::Union{String, Vector{String}})
Pkg.pin(pkgs::Union{Packagespec, Vector{Packagespec}})
Pin a package to the current version (or the one given in the `packagespec` or a certain
git revision. A pinned package is never updated.
"""
const pin = API.pin
"""
Pkg.free(pkg::Union{String, Vector{String}})
Pkg.free(pkgs::Union{Packagespec, Vector{Packagespec}})
Free a package which removes a `pin` if it exists, or if the package is tracking a path,
e.g. after [`Pkg.develop`](@ref), go back to tracking registered versions.
# Examples
```julia
Pkg.free("Package")
Pkg.free(PackageSpec("Package"))
```
"""
const free = API.free
"""
Pkg.develop(pkg::Union{String, Vector{String}})
Pkg.develop(pkgs::Union{Packagespec, Vector{Packagespec}})
Make a package available for development by tracking it by path.
If `pkg` is given with only a name or by a URL the packages will be downloaded
to the location by the environment variable `JULIA_PKG_DEVDIR` with
`.julia/dev` as the default.
If `pkg` is given as a local path, the package at that path will be tracked.
# Examples
```julia
# By name
Pkg.develop("Example")
# By url
Pkg.develop(PackageSpec(url="https://github.com/JuliaLang/Compat.jl"))
# By path
Pkg.develop(PackageSpec(path="MyJuliaPackages/Package.jl"))
```
See also [`PackageSpec`](@ref)
"""
const develop = API.develop
#TODO: Will probably be deprecated for something in PkgDev
const generate = API.generate
"""
Pkg.instantiate()
If a `Manifest.toml` file exist in the current project, download all
the packages declared in that manifest.
Else, resolve a set of feasible packages from the `Project.toml` files
and install them.
"""
const instantiate = API.instantiate
"""
Pkg.resolve()
Update the current manifest with eventual changes to the dependency graph
from packages that are tracking a path.
"""
const resolve = API.resolve
"""
Pkg.status(mode::PackageMode=PKGMODE_PROJECT)
Print out the status of the project/manifest.
If `mode` is `PKGMODE_PROJECT` prints out status about only those packages
that are in the project (explicitly added). If `mode` is `PKGMODE_MANIFEST`
also print for those in the manifest (recursive dependencies).
"""
const status = API.status
"""
Pkg.activate([s::String]; shared::Bool=false)
Activate the environment at `s`. The active environment is the environment
that is modified by executing package commands.
The logic for what path is activated is as follows:
* If `shared` is `true`, the first existing environment named `s` from the depots
in the depot stack will be activated. If no such environment exists,
create and activate that environment in the first depot.
* If `s` is an existing path, then activate the environment at that path.
* If `s` is a package in the current project and `s` is tracking a path, then
activate the environment at the tracked path.
* Else, `s` is interpreted as a non-existing path, activate that path.
If no argument is given to `activate`, then activate the home project.
The home project is specified by either the `--project` command line option to
the julia executable, or the `JULIA_PROJECT` environment variable.
# Examples
```
Pkg.activate()
Pkg.activate("local/path")
Pkg.activate("MyDependency")
```
"""
const activate = API.activate
"""
PackageSpec(name::String, [uuid::UUID, version::VersionNumber])
PackageSpec(; name, url, path, rev, version, mode, level)
A `PackageSpec` is a representation of a package with various metadata.
This includes:
* The `name` of the package.
* The package unique `uuid`.
* A `version` (for example when adding a package. When upgrading, can also be an instance of
the enum [`UpgradeLevel`](@ref)
* A `url` and an optional git `rev`ision. `rev` could be a branch name or a git commit SHA.
* A local path `path`. This is equivalent to using the `url` argument but can be more descriptive.
* A `mode`, which is an instance of the enum [`PackageMode`](@ref) which can be either `PKGMODE_PROJECT` or
`PKGMODE_MANIFEST`, defaults to `PKGMODE_PROJECT`. Used in e.g. [`Pkg.rm`](@ref).
Most functions in Pkg take a `Vector` of `PackageSpec` and do the operation on all the packages
in the vector.
Below is a comparison between the REPL version and the `PackageSpec` version:
| `REPL` | `API` |
|:---------------------|:------------------------------------------------------|
| `Package` | `PackageSpec("Package")` |
| `Package@0.2` | `PackageSpec(name="Package", version="0.2")` |
| `Package=a67d...` | `PackageSpec(name="Package", uuid="a67d...")` |
| `Package#master` | `PackageSpec(name="Package", rev="master")` |
| `local/path#feature` | `PackageSpec(path="local/path"; rev="feature")` |
| `www.mypkg.com` | `PackageSpec(url="www.mypkg.com")` |
| `--manifest Package` | `PackageSpec(name="Package", mode=PKGSPEC_MANIFEST)` |
| `--major Package` | `PackageSpec(name="Package", version=PKGLEVEL_MAJOR)` |
"""
const PackageSpec = Types.PackageSpec
"""
Pkg.setprotocol!(proto::Union{Nothing, AbstractString}=nothing)
Set the protocol used to access GitHub-hosted packages when `add`ing a url or `develop`ing a package.
Defaults to 'https', with `proto == nothing` delegating the choice to the package developer.
"""
const setprotocol! = API.setprotocol!
function __init__()
if isdefined(Base, :active_repl)
REPLMode.repl_init(Base.active_repl)
else
atreplinit() do repl
if isinteractive() && repl isa REPL.LineEditREPL
isdefined(repl, :interface) || (repl.interface = REPL.setup_interface(repl))
REPLMode.repl_init(repl)
end
end
end
end
METADATA_compatible_uuid(pkg::String) = Types.uuid5(Types.uuid_package, pkg)
##################
# Precompilation #
##################
const CTRL_C = '\x03'
const precompile_script = """
import Pkg
tmp = mktempdir()
cd(tmp)
empty!(DEPOT_PATH)
pushfirst!(DEPOT_PATH, tmp)
# Prevent cloning registry
mkdir("registries")
touch("registries/blocker") # prevents default registry from cloning
touch("Project.toml")
] activate .
$CTRL_C
Pkg.add("Test") # adding an stdlib doesn't require internet access
] add Te\t\t$CTRL_C
] st
$CTRL_C
rm(tmp; recursive=true)"""
end # module