-
-
Notifications
You must be signed in to change notification settings - Fork 260
/
Pkg.jl
737 lines (594 loc) · 27 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
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
# This file is a part of Julia. License is MIT: https://julialang.org/license
module Pkg
import Random
import REPL
import TOML
using Dates
export @pkg_str
export PackageSpec
export PackageMode, PKGMODE_MANIFEST, PKGMODE_PROJECT
export UpgradeLevel, UPLEVEL_MAJOR, UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH
export PreserveLevel, PRESERVE_TIERED, PRESERVE_ALL, PRESERVE_DIRECT, PRESERVE_SEMVER, PRESERVE_NONE
export Registry, RegistrySpec
depots() = Base.DEPOT_PATH
function depots1()
d = depots()
isempty(d) && Pkg.Types.pkgerror("no depots found in DEPOT_PATH")
return d[1]
end
function pkg_server()
server = get(ENV, "JULIA_PKG_SERVER", "https://pkg.julialang.org")
isempty(server) && return nothing
startswith(server, r"\w+://") || (server = "https://$server")
return rstrip(server, '/')
end
logdir(depot = depots1()) = joinpath(depot, "logs")
devdir(depot = depots1()) = get(ENV, "JULIA_PKG_DEVDIR", joinpath(depot, "dev"))
envdir(depot = depots1()) = joinpath(depot, "environments")
const UPDATED_REGISTRY_THIS_SESSION = Ref(false)
const OFFLINE_MODE = Ref(false)
# For globally overriding in e.g. tests
const DEFAULT_IO = Ref{Union{IO,Nothing}}(nothing)
stderr_f() = something(DEFAULT_IO[], stderr)
stdout_f() = something(DEFAULT_IO[], stdout)
can_fancyprint(io::IO) = (io isa Base.TTY) && (get(ENV, "CI", nothing) != "true")
include("../ext/LazilyInitializedFields/LazilyInitializedFields.jl")
include("utils.jl")
include("MiniProgressBars.jl")
include("GitTools.jl")
include("PlatformEngines.jl")
include("Versions.jl")
include("Registry/Registry.jl")
include("Resolve/Resolve.jl")
include("Types.jl")
include("BinaryPlatforms_compat.jl")
include("Artifacts.jl")
include("Operations.jl")
include("API.jl")
include("REPLMode/REPLMode.jl")
import .REPLMode: @pkg_str
import .Types: UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH, UPLEVEL_FIXED
import .Types: PKGMODE_MANIFEST, PKGMODE_PROJECT
import .Types: PRESERVE_TIERED, PRESERVE_ALL, PRESERVE_DIRECT, PRESERVE_SEMVER, PRESERVE_NONE
# Import artifacts API
using .Artifacts, .PlatformEngines
"""
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 [`Pkg.rm`](@ref), [`Pkg.update`](@ref) and [`Pkg.status`](@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
const PreserveLevel = Types.PreserveLevel
# Define new variables so tab comleting Pkg. works.
"""
Pkg.add(pkg::Union{String, Vector{String}}; preserve=PRESERVE_TIERED)
Pkg.add(pkg::Union{PackageSpec, Vector{PackageSpec}}; preserve=PRESERVE_TIERED)
Add a package to the current project. This package will be available by using the
`import` and `using` keywords in the Julia REPL, and if the current project is
a package, also inside that package.
## Resolution Tiers
`Pkg` resolves the set of packages in your environment using a tiered algorithm.
The `preserve` keyword argument allows you to key into a specific tier in the resolve algorithm.
The following table describes the argument values for `preserve` (in order of strictness):
| Value | Description |
|:------------------|:------------------------------------------------------------------------------------|
| `PRESERVE_ALL` | Preserve the state of all existing dependencies (including recursive dependencies) |
| `PRESERVE_DIRECT` | Preserve the state of all existing direct dependencies |
| `PRESERVE_SEMVER` | Preserve semver-compatible versions of direct dependencies |
| `PRESERVE_NONE` | Do not attempt to preserve any version information |
| `PRESERVE_TIERED` | Use the tier which will preserve the most version information (this is the default) |
# Examples
```julia
Pkg.add("Example") # Add a package from registry
Pkg.add("Example"; preserve=Pkg.PRESERVE_ALL) # Add the `Example` package and preserve existing dependencies
Pkg.add(name="Example", version="0.3") # Specify version; latest release in the 0.3 series
Pkg.add(name="Example", version="0.3.1") # Specify version; exact release
Pkg.add(url="https://github.com/JuliaLang/Example.jl", rev="master") # From url to remote gitrepo
Pkg.add(url="/remote/mycompany/juliapackages/OurPackage") # From path to local gitrepo
Pkg.add(url="https://github.com/Company/MonoRepo", subdir="juliapkgs/Package.jl)") # With subdir
```
See also [`PackageSpec`](@ref), [`Pkg.develop`](@ref).
"""
const add = API.add
"""
Pkg.precompile(; strict::Bool=false)
Precompile all the dependencies of the project in parallel.
!!! note
Errors will only throw when precompiling the top-level dependencies, given that
not all manifest dependencies may be loaded by the top-level dependencies on the given system.
This can be overridden to make errors in all dependencies throw by setting the kwarg `strict` to `true`
!!! note
This method is called automatically after any Pkg action that changes the manifest.
Any packages that have previously errored during precompilation won't be retried in auto mode
until they have changed. To disable automatic precompilation set `ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0`.
To manually control the number of tasks used set `ENV["JULIA_NUM_PRECOMPILE_TASKS"]`.
!!! compat "Julia 1.3"
This function requires at least Julia 1.3. On earlier versions
you can use `Pkg.API.precompile()` or the `precompile` Pkg REPL command.
# Examples
```julia
Pkg.precompile()
```
"""
const precompile = API.precompile
"""
Pkg.rm(pkg::Union{String, Vector{String}}; mode::PackageMode = PKGMODE_PROJECT)
Pkg.rm(pkg::Union{PackageSpec, Vector{PackageSpec}}; mode::PackageMode = PKGMODE_PROJECT)
Remove a package from the current project. If `mode` is equal to
`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 by 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(; kwargs...)
Pkg.test(pkg::Union{String, Vector{String}; kwargs...)
Pkg.test(pkgs::Union{PackageSpec, Vector{PackageSpec}}; kwargs...)
**Keyword arguments:**
- `coverage::Bool=false`: enable or disable generation of coverage statistics.
- `julia_args::Union{Cmd, Vector{String}}`: options to be passed the test process.
- `test_args::Union{Cmd, Vector{String}}`: test arguments (`ARGS`) available in the test process.
!!! compat "Julia 1.3"
`julia_args` and `test_args` requires at least Julia 1.3.
Run the tests for package `pkg`, or for the current project (which thus needs to be a package) if no
positional argument is given to `Pkg.test`. 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
in it. If a manifest exists, the versions in that manifest are used, otherwise
a feasible set of packages is resolved and installed.
During the tests, 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"]
```
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`.
Inlining of functions during testing can be disabled (for better coverage accuracy)
by starting julia with `--inline=no`.
"""
const test = API.test
"""
Pkg.gc(; collect_delay::Period=Day(7), io::IO=stderr)
Garbage-collect package and artifact installations by sweeping over all known
`Manifest.toml` and `Artifacts.toml` files, noting those that have been deleted, and then
finding artifacts and packages that are thereafter not used by any other projects,
marking them as "orphaned". This method will only remove orphaned objects (package
versions, artifacts, and scratch spaces) that have been continually un-used for a period
of `collect_delay`; which defaults to seven days.
"""
const gc = API.gc
"""
Pkg.build(; verbose = false, io::IO=stderr)
Pkg.build(pkg::Union{String, Vector{String}}; verbose = false, io::IO=stderr)
Pkg.build(pkgs::Union{PackageSpec, Vector{PackageSpec}}; verbose = false, io::IO=stderr)
Run the build script in `deps/build.jl` for `pkg` and all of its 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 on any package that gets installed
for the first time.
`verbose = true` prints the build output to `stdout`/`stderr` instead of
redirecting to the `build.log` file.
"""
const build = API.build
"""
Pkg.pin(pkg::Union{String, Vector{String}}; io::IO=stderr)
Pkg.pin(pkgs::Union{PackageSpec, Vector{PackageSpec}}; io::IO=stderr)
Pin a package to the current version (or the one given in the `PackageSpec`) or to a certain
git revision. A pinned package is never updated.
# Examples
```julia
Pkg.pin("Example")
Pkg.pin(name="Example", version="0.3.1")
```
"""
const pin = API.pin
"""
Pkg.free(pkg::Union{String, Vector{String}}; io::IO=stderr)
Pkg.free(pkgs::Union{PackageSpec, Vector{PackageSpec}}; io::IO=stderr)
If `pkg` is pinned, remove the pin.
If `pkg` is tracking a path,
e.g. after [`Pkg.develop`](@ref), go back to tracking registered versions.
# Examples
```julia
Pkg.free("Package")
```
"""
const free = API.free
"""
Pkg.develop(pkg::Union{String, Vector{String}}; io::IO=stderr)
Pkg.develop(pkgs::Union{Packagespec, Vector{Packagespec}}; io::IO=stderr)
Make a package available for development by tracking it by path.
If `pkg` is given with only a name or by a URL, the package will be downloaded
to the location specified by the environment variable `JULIA_PKG_DEVDIR`, with
`joinpath(DEPOT_PATH[1],"dev")` being 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(url="https://github.com/JuliaLang/Compat.jl")
# By path
Pkg.develop(path="MyJuliaPackages/Package.jl")
```
See also [`PackageSpec`](@ref), [`Pkg.add`](@ref).
"""
const develop = API.develop
"""
Pkg.generate(pkgname::String)
Create a minimal project called `pkgname` in the current folder. For more featureful package creation, please see `PkgTemplates.jl`.
"""
const generate = API.generate
"""
Pkg.dependencies()::Dict{UUID, PackageInfo}
!!! compat "Julia 1.4"
This feature requires Julia 1.4, and is considered experimental.
Query the dependency graph.
The result is a `Dict` that maps a package UUID to a `PackageInfo` struct representing the dependency (a package).
# `PackageInfo` fields
| Field | Description |
|:------------------|:-----------------------------------------------------------|
| `name` | The name of the package |
| `version` | The version of the package (this is `Nothing` for stdlibs) |
| `is_direct_dep` | The package is a direct dependency |
| `is_tracking_path`| Whether a package is directly tracking a directory |
| `is_pinned` | Whether a package is pinned |
| `source` | The directory containing the source code for that package |
| `dependencies` | The dependencies of that package as a vector of UUIDs |
"""
const dependencies = API.dependencies
"""
Pkg.project()::ProjectInfo
!!! compat "Julia 1.4"
This feature requires Julia 1.4, and is considered experimental.
Request a `ProjectInfo` struct which contains information about the active project.
# `ProjectInfo` fields
| Field | Description |
|:-------------|:--------------------------------------------------------------------------------------------|
| name | The project's name |
| uuid | The project's UUID |
| version | The project's version |
| dependencies | The project's direct dependencies as a `Dict` which maps dependency name to dependency UUID |
| path | The location of the project file which defines the active project |
"""
const project = API.project
"""
Pkg.instantiate(; verbose = false, io::IO=stderr)
If a `Manifest.toml` file exists in the active project, download all
the packages declared in that manifest.
Otherwise, resolve a set of feasible packages from the `Project.toml` files
and install them.
`verbose = true` prints the build output to `stdout`/`stderr` instead of
redirecting to the `build.log` file.
If no `Project.toml` exist in the current active project, create one with all the
dependencies in the manifest and instantiate the resulting project.
"""
const instantiate = API.instantiate
"""
Pkg.resolve(; io::IO=stderr)
Update the current manifest with potential changes to the dependency graph
from packages that are tracking a path.
"""
const resolve = API.resolve
"""
Pkg.status([pkgs...]; mode::PackageMode=PKGMODE_PROJECT, diff::Bool=false, io::IO=stdout)
Print out the status of the project/manifest.
If `mode` is `PKGMODE_PROJECT`, print out status only about the packages
that are in the project (explicitly added). If `mode` is `PKGMODE_MANIFEST`,
print status also about those in the manifest (recursive dependencies). If there are
any packages listed as arguments, the output will be limited to those packages.
Setting `diff=true` will, if the environment is in a git repository, limit
the output to the difference as compared to the last git commit.
See [`Pkg.project`](@ref) and [`Pkg.dependencies`](@ref) to get the project/manifest
status as a Julia object instead of printing it.
!!! compat "Julia 1.1"
`Pkg.status` with package arguments requires at least Julia 1.1.
!!! compat "Julia 1.3"
The `diff` keyword argument requires Julia 1.3. In earlier versions `diff=true`
is the default for environments in git repositories.
"""
const status = API.status
"""
Pkg.activate([s::String]; shared::Bool=false, io::IO=stderr)
Pkg.activate(; temp::Bool=false, shared::Bool=false, io::IO=stderr)
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 `temp` is `true` this will create and activate a temporary enviroment which will
be deleted when the julia process is exited.
* 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.
* Otherwise, `s` is interpreted as a non-existing path, which is then activated.
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")
Pkg.activate(; temp=true)
```
!!! compat "Julia 1.4"
the `temp` option requires at least Julia 1.4.
"""
const activate = API.activate
"""
Pkg.offline(b::Bool=true)
Enable (`b=true`) or disable (`b=false`) offline mode.
In offline mode Pkg tries to do as much as possible without connecting
to internet. For example, when adding a package Pkg only considers
versions that are already downloaded in version resolution.
To work in offline mode across Julia sessions you can
set the environment variable `JULIA_PKG_OFFLINE` to `"true"`.
!!! compat "Julia 1.5"
Pkg's offline mode requires Julia 1.5 or later.
"""
offline(b::Bool=true) = (OFFLINE_MODE[] = b; nothing)
"""
PackageSpec(name::String, [uuid::UUID, version::VersionNumber])
PackageSpec(; name, url, path, subdir, rev, version, mode, level)
A `PackageSpec` is a representation of a package with various metadata.
This includes:
* The `name` of the package.
* The package's 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` can be a branch name or a git commit SHA1.
* A local `path`. This is equivalent to using the `url` argument but can be more descriptive.
* A `subdir` which can be used when adding a package that is not in the root of a repository.
Most functions in Pkg take a `Vector` of `PackageSpec` and do the operation on all the packages
in the vector.
!!! compat "Julia 1.5"
Many functions that take a `PackageSpec` or a `Vector{PackageSpec}` can be called with a more concise notation with `NamedTuple`s.
For example, `Pkg.add` can be called either as the explicit or concise versions as:
| Explicit | Concise |
|:--------------------------------------------------------------------|:-----------------------------------------------|
| `Pkg.add(PackageSpec(name="Package"))` | `Pkg.add(name = "Package")` |
| `Pkg.add(PackageSpec(url="www.myhost.com/MyPkg")))` | `Pkg.add(name = "Package")` |
|` Pkg.add([PackageSpec(name="Package"), PackageSpec(path="/MyPkg"])` | `Pkg.add([(;name="Package"), (;path="MyPkg")])`|
Below is a comparison between the REPL mode and the functional API:
| `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")` |
| `--major Package` | `PackageSpec(name="Package", version=PKGLEVEL_MAJOR)` |
"""
const PackageSpec = Types.PackageSpec
"""
setprotocol!(;
domain::AbstractString = "github.com",
protocol::Union{Nothing, AbstractString}=nothing
)
Set the protocol used to access hosted packages when `add`ing a url or `develop`ing a package.
Defaults to delegating the choice to the package developer (`protocol === nothing`).
Other choices for `protocol` are `"https"` or `"git"`.
# Examples
```julia-repl
julia> Pkg.setprotocol!(domain = "github.com", protocol = "ssh")
julia> Pkg.setprotocol!(domain = "gitlab.mycompany.com")
```
"""
const setprotocol! = API.setprotocol!
"""
undo()
Undoes the latest change to the active project. Only states in the current session are stored,
up to a maximum of $(API.max_undo_limit) states.
See also: [`redo`](@ref).
"""
const undo = API.undo
"""
redo()
Redoes the changes from the latest [`undo`](@ref).
"""
const redo = API.redo
"""
RegistrySpec(name::String)
RegistrySpec(; name, url, path)
A `RegistrySpec` is a representation of a registry with various metadata, much like
[`PackageSpec`](@ref).
Most registry functions in Pkg take a `Vector` of `RegistrySpec` and do the operation
on all the registries in the vector.
!!! compat "Julia 1.1"
Pkg's registry handling requires at least Julia 1.1.
# Examples
Below is a comparison between the REPL mode and the functional API::
| `REPL` | `API` |
|:---------------------|:------------------------------------------------|
| `Registry` | `RegistrySpec("Registry")` |
| `Registry=a67d...` | `RegistrySpec(name="Registry", uuid="a67d...")` |
| `local/path` | `RegistrySpec(path="local/path")` |
| `www.myregistry.com` | `RegistrySpec(url="www.myregistry.com")` |
"""
const RegistrySpec = Registry.RegistrySpec
"""
upgrade_manifest()
Upgrades the format of the manifest file from v1.0 to v2.0 without re-resolving.
"""
const upgrade_manifest = API.upgrade_manifest
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
push!(empty!(REPL.install_packages_hooks), REPLMode.try_prompt_pkg_add)
OFFLINE_MODE[] = get(ENV, "JULIA_PKG_OFFLINE", nothing) == "true"
return nothing
end
################
# Deprecations #
################
function installed()
@warn "Pkg.installed() is deprecated"
deps = dependencies()
installs = Dict{String, VersionNumber}()
for (uuid, dep) in deps
dep.is_direct_dep || continue
dep.version === nothing && continue
installs[dep.name] = dep.version
end
return installs
end
function dir(pkg::String, paths::AbstractString...)
@warn "`Pkg.dir(pkgname, paths...)` is deprecated; instead, do `import $pkg; joinpath(dirname(pathof($pkg)), \"..\", paths...)`." maxlog=1
pkgid = Base.identify_package(pkg)
pkgid === nothing && return nothing
path = Base.locate_package(pkgid)
path === nothing && return nothing
return abspath(path, "..", "..", paths...)
end
###########
# AUTO GC #
###########
const DEPOT_ORPHANAGE_TIMESTAMPS = Dict{String,Float64}()
const _auto_gc_enabled = Ref{Bool}(true)
function _auto_gc(ctx::Types.Context; collect_delay::Period = Day(7))
if !_auto_gc_enabled[]
return
end
# If we don't know the last time this depot was GC'ed (because this is the
# first time we've looked this session), or it looks like we might want to
# collect; let's go ahead and hit the filesystem to find the mtime of the
# `orphaned.toml` file, which should tell us how long since the last time
# we GC'ed.
orphanage_path = joinpath(logdir(depots1()), "orphaned.toml")
delay_secs = Second(collect_delay).value
curr_time = time()
if curr_time - get(DEPOT_ORPHANAGE_TIMESTAMPS, depots1(), 0.0) >= delay_secs
DEPOT_ORPHANAGE_TIMESTAMPS[depots1()] = mtime(orphanage_path)
end
if curr_time - DEPOT_ORPHANAGE_TIMESTAMPS[depots1()] > delay_secs
@info("We haven't cleaned this depot up for a bit, running Pkg.gc()...")
try
Pkg.gc(ctx; collect_delay)
DEPOT_ORPHANAGE_TIMESTAMPS[depots1()] = curr_time
catch ex
@error("GC failed", exception=ex)
end
end
end
##################
# Precompilation #
##################
function _auto_precompile(ctx::Types.Context)
if Base.JLOptions().use_compiled_modules == 1 && tryparse(Int, get(ENV, "JULIA_PKG_PRECOMPILE_AUTO", "1")) == 1
Pkg.precompile(ctx; internal_call=true)
end
end
using LibGit2: LibGit2
function _run_precompilation_script_setup()
tmp = mktempdir()
cd(tmp)
empty!(DEPOT_PATH)
pushfirst!(DEPOT_PATH, tmp)
touch("Project.toml")
Pkg.activate(".")
Pkg.generate("TestPkg")
uuid = TOML.parsefile(joinpath("TestPkg", "Project.toml"))["uuid"]
mv("TestPkg", "TestPkg.jl")
tree_hash = cd("TestPkg.jl") do
sig = LibGit2.Signature("TEST", "TEST@TEST.COM", round(time()), 0)
repo = LibGit2.init(".")
LibGit2.add!(repo, "")
commit = LibGit2.commit(repo, "initial commit"; author=sig, committer=sig)
th = LibGit2.peel(LibGit2.GitTree, LibGit2.GitObject(repo, commit)) |> LibGit2.GitHash |> string
close(repo)
th
end
# Prevent cloning the General registry by adding a fake one
mkpath("registries/Registry/T/TestPkg")
write("registries/Registry/Registry.toml", """
name = "Registry"
uuid = "37c07fec-e54c-4851-934c-2e3885e4053e"
repo = "https://github.com/JuliaRegistries/Registry.git"
[packages]
$uuid = { name = "TestPkg", path = "T/TestPkg" }
""")
write("registries/Registry/T/TestPkg/Compat.toml", """
["0"]
julia = "1"
""")
write("registries/Registry/T/TestPkg/Deps.toml", """
["0"]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
""")
write("registries/Registry/T/TestPkg/Versions.toml", """
["0.1.0"]
git-tree-sha1 = "$tree_hash"
""")
write("registries/Registry/T/TestPkg/Package.toml", """
name = "TestPkg"
uuid = "$uuid"
repo = "$(escape_string(tmp))/TestPkg.jl"
""")
return tmp
end
function _run_precompilation_script_artifact()
# Create simple artifact, bind it, then use it:
foo_hash = Pkg.Artifacts.create_artifact(dir -> touch(joinpath(dir, "foo")))
Artifacts.bind_artifact!("./Artifacts.toml", "foo", foo_hash)
# Also create multiple platform-specific ones because that's a codepath we need precompiled
Artifacts.bind_artifact!("./Artifacts.toml", "foo_plat", foo_hash; platform=Base.BinaryPlatforms.HostPlatform())
# Because @artifact_str doesn't work at REPL-level, we JIT out a file that we can include()
write("load_artifact.jl", """
Pkg.Artifacts.artifact"foo"
Pkg.Artifacts.artifact"foo_plat"
""")
foo_path = include("load_artifact.jl")
end
const CTRL_C = '\x03'
const precompile_script = """
import Pkg
tmp = Pkg._run_precompilation_script_setup()
$CTRL_C
Pkg.add("TestPkg")
Pkg.develop(Pkg.PackageSpec(path="TestPkg.jl"))
Pkg.add(Pkg.PackageSpec(path="TestPkg.jl/"))
Pkg.REPLMode.try_prompt_pkg_add(Symbol[:notapackage])
] add Te\t\t$CTRL_C
] st
$CTRL_C
Pkg._run_precompilation_script_artifact()
rm(tmp; recursive=true)"""
end # module