diff --git a/stdlib/Pkg/docs/make.jl b/stdlib/Pkg/docs/make.jl index 8dd9fe8aaf89f..36a09acd0cf4b 100644 --- a/stdlib/Pkg/docs/make.jl +++ b/stdlib/Pkg/docs/make.jl @@ -1,6 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Documenter, Pkg +Base.ACTIVE_PROJECT[] = joinpath(@__DIR__, "..") +using Documenter +using Pkg makedocs( modules = [Pkg], diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index a0478120fc606..b4eb42a5cc930 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -193,6 +193,9 @@ Since we haven't created our own project yet, we are in the default project, loc To return to the `julia>` prompt, either press backspace when the input line is empty or press Ctrl+C. Help is available by calling `pkg> help`. +If you are in an environment that does not have access to a REPL you can still use the REPL mode commands using +the string macro `pkg` available after `using Pkg`. The command `pkg"cmd"` would be equivalent to executing `cmd` +in the REPL mode. The documentation here describes using Pkg from the REPL mode. Documentation of using the Pkg API (by calling `Pkg.` functions) is in progress of being written. @@ -831,3 +834,30 @@ Simply clone their project using e.g. `git clone`, `cd` to the project directory If the project contains a manifest, this will install the packages in the same state that is given by that manifest. Otherwise, it will resolve the latest versions of the dependencies compatible with the project. + +## References + +This section describes the "API mode" of interacting with Pkg.jl which is recommended for non-interactive usage, +in i.e. scripts. In the REPL mode packages (with associated version, UUID, URL etc) are parsed from strings, +for example, `"Package#master"`,`"Package@v0.1"`, `"www.mypkg.com/MyPkg#my/feature"`. +It is possible to use strings as arguments for simple commands in the API mode (like `Pkg.add(["PackageA", "PackageB"])`, +more complicated commands, that e.g. specify URLs or version range, uses a more structured format over strings. +This is done by creating an instance of a [`PackageSpec`](@ref) which are passed in to functions. + +```@docs +PackageSpec +PackageMode +UpgradeLevel +Pkg.add +Pkg.develop +Pkg.activate +Pkg.rm +Pkg.update +Pkg.test +Pkg.build +Pkg.pin +Pkg.free +Pkg.instantiate +Pkg.resolve +Pkg.setprotocol! +``` diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index cbe13a2dc7266..717096a67c81d 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -17,15 +17,25 @@ preview_info() = printstyled("───── Preview mode ─────\n"; c include("generate.jl") -parse_package(pkg) = Pkg.REPLMode.parse_package(pkg; add_or_develop=true) +function check_package_name(x::String) + if !(occursin(Pkg.REPLMode.name_re, x)) + cmderror("$x is not a valid packagename") + end + return PackageSpec(x) +end add_or_develop(pkg::Union{String, PackageSpec}; kwargs...) = add_or_develop([pkg]; kwargs...) -add_or_develop(pkgs::Vector{String}; kwargs...) = add_or_develop([parse_package(pkg) for pkg in pkgs]; kwargs...) +add_or_develop(pkgs::Vector{String}; kwargs...) = add_or_develop([check_package_name(pkg) for pkg in pkgs]; kwargs...) add_or_develop(pkgs::Vector{PackageSpec}; kwargs...) = add_or_develop(Context(), pkgs; kwargs...) function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, kwargs...) Context!(ctx; kwargs...) + # All developed packages should go through handle_repos_develop so just give them an empty repo + for pkg in pkgs + mode == :develop && pkg.repo == nothing && (pkg.repo = Types.GitRepo()) + end + # if julia is passed as a package the solver gets tricked; # this catches the error early on any(pkg->(pkg.name == "julia"), pkgs) && @@ -55,12 +65,10 @@ end add(args...; kwargs...) = add_or_develop(args...; mode = :add, kwargs...) develop(args...; kwargs...) = add_or_develop(args...; mode = :develop, kwargs...) -@deprecate checkout develop - -rm(pkg::Union{String, PackageSpec}; kwargs...) = rm([pkg]; kwargs...) -rm(pkgs::Vector{String}; kwargs...) = rm([PackageSpec(pkg) for pkg in pkgs]; kwargs...) -rm(pkgs::Vector{PackageSpec}; kwargs...) = rm(Context(), pkgs; kwargs...) +rm(pkg::Union{String, PackageSpec}; kwargs...) = rm([pkg]; kwargs...) +rm(pkgs::Vector{String}; kwargs...) = rm([PackageSpec(pkg) for pkg in pkgs]; kwargs...) +rm(pkgs::Vector{PackageSpec}; kwargs...) = rm(Context(), pkgs; kwargs...) function rm(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) Context!(ctx; kwargs...) @@ -379,11 +387,11 @@ function _get_deps!(ctx::Context, pkgs::Vector{PackageSpec}, uuids::Vector{UUID} return end + build(pkgs...) = build([PackageSpec(pkg) for pkg in pkgs]) build(pkg::Array{Union{}, 1}) = build(PackageSpec[]) build(pkg::PackageSpec) = build([pkg]) build(pkgs::Vector{PackageSpec}) = build(Context(), pkgs) - function build(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) Context!(ctx; kwargs...) @@ -424,7 +432,7 @@ function clone(url::String, name::String = "") if !isempty(name) ctx.old_pkg2_clone_name = name end - develop(ctx, [parse_package(url)]) + develop(ctx, [Pkg.REPLMode.parse_package(url; add_or_develop=true)]) end function dir(pkg::String, paths::String...) @@ -541,6 +549,13 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, kwarg Operations.build_versions(ctx, union(new_apply, new_git)) end + +status(mode=PKGMODE_PROJECT) = status(Context(), mode) +function status(ctx::Context, mode=PKGMODE_PROJECT) + Pkg.Display.status(ctx, mode) + return +end + function activate(path::Union{String,Nothing}=nothing) Base.ACTIVE_PROJECT[] = Base.load_path_expand(path) end diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index ee1d8acc8c405..7dea9697a7582 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -26,31 +26,303 @@ include("Operations.jl") include("API.jl") include("REPLMode.jl") +import .Types: UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH, UPLEVEL_FIXED +import .Types: PKGMODE_MANIFEST, PKGMODE_PROJECT + +""" + 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. -const add = API.add -const rm = API.rm -const up = API.up -const test = API.test -const gc = API.gc -const build = API.build -const installed = API.installed -const pin = API.pin -const free = API.free -const checkout = API.checkout -const develop = API.develop -const generate = API.generate -const instantiate = API.instantiate -const resolve = API.resolve -const status = Display.status -const update = up -const activate = API.activate +""" + 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 +Pkg.add(PackageSpec(url="/remote/mycompany/juliapackages/OurPackage"))` # From path (has to be a 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=true) + Pkg.test(pkg::Union{String, Vector{String}; coverage::Bool=true) + Pkg.test(pkgs::Union{PackageSpec, Vector{PackageSpec}}; coverage::Bool=true) + +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", rev="master")) + +# By path (also uses url keyword to PackageSpec) +Pkg.develop(PackageSpec(url="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]) + +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 `s` is a path that exist, that environment will be activcated. + * If `s` is a package name in the current projec activate that is tracking a path, +activate the environment at that path. + * If `s` is a non-existing path, activate that path. + + +If no argument is given to `activate`, activate the home project, +which is the one specified by either `--project` command line when starting julia, +or `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, 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` (which might also be a local path) and an optional git `rev`ision. + `rev` could be a branch name or a git commit SHA. + * 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(url="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! + # legacy CI script support import .API: clone, dir import .REPLMode: @pkg_str -export @pkg_str +export @pkg_str, PackageSpec function __init__() @@ -66,13 +338,14 @@ function __init__() end end -using .Types -using UUIDs -import LibGit2 -import Dates +module PrecompileArea + using ..Types + using UUIDs + import LibGit2 + import Dates + include("precompile.jl") +end METADATA_compatible_uuid(pkg::String) = Types.uuid5(Types.uuid_package, pkg) -include("precompile.jl") - end # module diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index a07d7820501d0..a90577103bbdc 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -642,7 +642,6 @@ function do_add_or_develop!(ctx::Context, tokens::Vector{Token}, cmd::CommandKin token = popfirst!(tokens) if token isa String push!(pkgs, parse_package(token; add_or_develop=true)) - cmd == CMD_DEVELOP && pkgs[end].repo == nothing && (pkgs[end].repo = Types.GitRepo("", "")) elseif token isa VersionRange pkgs[end].version = VersionSpec(token) elseif token isa Rev diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index dffdc68fe30ac..9cbfa2e34987b 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -125,21 +125,13 @@ Base.show(io::IO, err::CommandError) = print(io, err.msg) # PackageSpec # ############### @enum(UpgradeLevel, UPLEVEL_FIXED, UPLEVEL_PATCH, UPLEVEL_MINOR, UPLEVEL_MAJOR) - -function UpgradeLevel(s::Symbol) - s == :fixed ? UPLEVEL_FIXED : - s == :patch ? UPLEVEL_PATCH : - s == :minor ? UPLEVEL_MINOR : - s == :major ? UPLEVEL_MAJOR : - throw(ArgumentError("invalid upgrade bound: $s")) -end - @enum(PackageMode, PKGMODE_PROJECT, PKGMODE_MANIFEST, PKGMODE_COMBINED) @enum(PackageSpecialAction, PKGSPEC_NOTHING, PKGSPEC_PINNED, PKGSPEC_FREED, PKGSPEC_DEVELOPED, PKGSPEC_TESTED, PKGSPEC_REPO_ADDED) const VersionTypes = Union{VersionNumber,VersionSpec,UpgradeLevel} +# The url field can also be a local path, rename? mutable struct GitRepo url::String rev::String @@ -148,6 +140,8 @@ end GitRepo(url::String, revspec) = GitRepo(url, revspec, nothing) GitRepo(url::String) = GitRepo(url, "", nothing) +GitRepo(;url::Union{String, Nothing}=nothing, rev::Union{String, Nothing} =nothing) = + GitRepo(url == nothing ? "" : url, rev == nothing ? "" : rev, nothing) Base.:(==)(repo1::GitRepo, repo2::GitRepo) = (repo1.url == repo2.url && repo1.rev == repo2.rev && repo1.git_tree_sha1 == repo2.git_tree_sha1) mutable struct PackageSpec @@ -158,12 +152,11 @@ mutable struct PackageSpec path::Union{Nothing,String} special_action::PackageSpecialAction # If the package is currently being pinned, freed etc repo::Union{Nothing,GitRepo} - PackageSpec() = new("", UUID(zero(UInt128)), VersionSpec(), PKGMODE_PROJECT, nothing, PKGSPEC_NOTHING, nothing) - PackageSpec(name::AbstractString, uuid::UUID, version::VersionTypes, - mode::PackageMode=PKGMODE_PROJECT, path=nothing, special_action=PKGSPEC_NOTHING, - repo=nothing) = - new(String(name), uuid, version, mode, path, special_action, repo) end +PackageSpec() = PackageSpec("", UUID(zero(UInt128)), VersionSpec(), PKGMODE_PROJECT, nothing, PKGSPEC_NOTHING, nothing) +PackageSpec(name::AbstractString, uuid::UUID, version::VersionTypes, + mode::PackageMode=PKGMODE_PROJECT, path=nothing, special_action=PKGSPEC_NOTHING, + repo=nothing) = PackageSpec(String(name), uuid, version, mode, path, special_action, repo) PackageSpec(name::AbstractString, uuid::UUID) = PackageSpec(name, uuid, VersionSpec()) PackageSpec(name::AbstractString, version::VersionTypes=VersionSpec()) = @@ -176,18 +169,41 @@ function PackageSpec(repo::GitRepo) return pkg end +# kwarg constructor +function PackageSpec(;name::AbstractString="", uuid::Union{String, UUID}=UUID(0), version::Union{VersionNumber, String} = "*", + url = nothing, rev = nothing, mode::PackageMode = PKGMODE_PROJECT) + if url !== nothing || rev !== nothing + repo = GitRepo(url=url, rev=rev) + else + repo = nothing + end + + version = VersionSpec(version) + uuid isa String && (uuid = UUID(uuid)) + PackageSpec(name, uuid, version, mode, nothing, PKGSPEC_NOTHING, repo) +end + has_name(pkg::PackageSpec) = !isempty(pkg.name) has_uuid(pkg::PackageSpec) = pkg.uuid != UUID(zero(UInt128)) function Base.show(io::IO, pkg::PackageSpec) - print(io, "PackageSpec(") - has_name(pkg) && show(io, pkg.name) - has_name(pkg) && has_uuid(pkg) && print(io, ", ") - has_uuid(pkg) && show(io, pkg.uuid) vstr = repr(pkg.version) - if vstr != "VersionSpec(\"*\")" - (has_name(pkg) || has_uuid(pkg)) && print(io, ", ") - print(io, vstr) + f = ["name" => pkg.name, "uuid" => has_uuid(pkg) ? pkg.uuid : "", "v" => (vstr == "VersionSpec(\"*\")" ? "" : vstr)] + if pkg.repo !== nothing + if !isempty(pkg.repo.url) + push!(f, "url/path" => pkg.repo.url) + end + if !isempty(pkg.repo.rev) + push!(f, "rev" => pkg.repo.rev) + end + end + print(io, "PackageSpec(") + first = true + for (field, value) in f + value == "" && continue + first || print(io, ", ") + print(io, field, "=", value) + first = false end print(io, ")") end @@ -658,7 +674,7 @@ function parse_package!(ctx, pkg, project_path) Pkg.Operations.set_maximum_version_registry!(env, pkg) end else - @warn "package $(pkg.name) at $(project_path) will need to have a [Julia]Project.toml file in the future" + # @warn "package $(pkg.name) at $(project_path) will need to have a [Julia]Project.toml file in the future" if !isempty(ctx.old_pkg2_clone_name) # remove when legacy CI script support is removed pkg.name = ctx.old_pkg2_clone_name else diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index fc02f0d800041..1a312ae5a0685 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -77,7 +77,6 @@ import Pkg.Types: semver_spec, VersionSpec @test semver_spec("≥1.3.0") == semver_spec(">=1.3.0") - @test semver_spec(">= 1.2.3") == VersionSpec("1.2.3-*") @test semver_spec(">=1.2 ") == VersionSpec("1.2.0-*") @test semver_spec(" >= 1") == VersionSpec("1.0.0-*") @@ -145,9 +144,9 @@ temp_pkg_dir() do project_path # VersionRange Pkg.add(PackageSpec(TEST_PKG.name, VersionSpec(VersionRange("0.3.0-0.3.2")))) @test Pkg.installed()[TEST_PKG.name] == v"0.3.2" - Pkg.up(; level = UpgradeLevel(:patch)) + Pkg.update(; level = UPLEVEL_PATCH) @test Pkg.installed()[TEST_PKG.name] == v"0.3.3" - Pkg.up(; level = UpgradeLevel(:minor)) + Pkg.update(; level = UPLEVEL_MINOR) @test Pkg.installed()[TEST_PKG.name].minor != 3 Pkg.rm(TEST_PKG.name) end @@ -168,10 +167,10 @@ temp_pkg_dir() do project_path old_v = Pkg.installed()[TEST_PKG.name] Pkg.pin(PackageSpec(TEST_PKG.name, v"0.2")) @test Pkg.installed()[TEST_PKG.name].minor == 2 - Pkg.up(TEST_PKG.name) + Pkg.update(TEST_PKG.name) @test Pkg.installed()[TEST_PKG.name].minor == 2 Pkg.free(TEST_PKG.name) - Pkg.up() + Pkg.update() @test Pkg.installed()[TEST_PKG.name] == old_v Pkg.rm(TEST_PKG.name) end @@ -182,7 +181,7 @@ temp_pkg_dir() do project_path Pkg.rm(TEST_PKG.name) mktempdir() do devdir withenv("JULIA_PKG_DEVDIR" => devdir) do - Pkg.REPLMode.pkgstr("develop $(TEST_PKG.name)") + Pkg.develop(TEST_PKG.name) @test isinstalled(TEST_PKG) @test Pkg.installed()[TEST_PKG.name] > old_v test_pkg_main_file = joinpath(devdir, TEST_PKG.name, "src", TEST_PKG.name * ".jl") @@ -215,19 +214,24 @@ temp_pkg_dir() do project_path end end + @testset "invalid pkg name" begin + @test_throws CommandError Pkg.add(",sa..,--") + end + @testset "stdlibs as direct dependency" begin uuid_pkg = (name = "CRC32c", uuid = UUID("8bf52ea8-c179-5cab-976a-9e18b702a9bc")) Pkg.add("CRC32c") @test haskey(Pkg.installed(), uuid_pkg.name) - Pkg.up() + Pkg.update() Pkg.test("CRC32c") Pkg.rm("CRC32c") end @testset "package name in resolver errors" begin try - Pkg.add([PackageSpec(TEST_PKG.name, VersionSpec(v"55"))]) + Pkg.add(PackageSpec(;name = TEST_PKG.name, version = v"55")) catch e + @show sprint(showerror, e) @test occursin(TEST_PKG.name, sprint(showerror, e)) end end @@ -237,10 +241,9 @@ temp_pkg_dir() do project_path withenv("JULIA_PKG_DEVDIR" => devdir) do try Pkg.setprotocol!("notarealprotocol") - # Pkg.develop is broken, update to use when fixed - @test_throws CommandError pkg"develop Example" + @test_throws CommandError Pkg.develop("Example") Pkg.setprotocol!("https") - pkg"develop Example" + Pkg.develop("Example") @test isinstalled(TEST_PKG) finally Pkg.setprotocol!() @@ -257,7 +260,7 @@ temp_pkg_dir() do project_path @testset "adding nonexisting packages" begin nonexisting_pkg = randstring(14) @test_throws CommandError Pkg.add(nonexisting_pkg) - @test_throws CommandError Pkg.up(nonexisting_pkg) + @test_throws CommandError Pkg.update(nonexisting_pkg) end Pkg.rm(TEST_PKG.name) @@ -294,7 +297,7 @@ temp_pkg_dir() do project_path cp(joinpath(@__DIR__, "test_packages", "UnregisteredWithProject"), joinpath(dir, "UnregisteredWithProject")) cd(joinpath(dir, "UnregisteredWithProject")) do with_current_env() do - Pkg.up() + Pkg.update() @test haskey(Pkg.installed(), "Example") end end @@ -376,7 +379,7 @@ temp_pkg_dir() do project_path mv(joinpath(pkg_name, "Project.toml"), joinpath(pkg_name, "JuliaProject.toml")) mv(joinpath(pkg_name, "Manifest.toml"), joinpath(pkg_name, "JuliaManifest.toml")) # make sure things still work - Pkg.develop(abspath(pkg_name)) + Pkg.develop(PackageSpec(url = abspath(pkg_name))) @test isinstalled((name=pkg_name, uuid=UUID(uuid))) Pkg.rm(pkg_name) @test !isinstalled((name=pkg_name, uuid=UUID(uuid))) @@ -406,10 +409,10 @@ temp_pkg_dir() do project_path @testset "inconsistent repo state" begin package_path = joinpath(project_path, "Example") LibGit2.with(LibGit2.clone("https://github.com/JuliaLang/Example.jl", package_path)) do repo - Pkg.add(package_path) + Pkg.add(PackageSpec(url=package_path)) end rm(joinpath(package_path, ".git"); force=true, recursive=true) - @test_throws CommandError Pkg.up() + @test_throws CommandError Pkg.update() end end end