From 3e88964271da95740291c3cf604bcd89ccf4f80f Mon Sep 17 00:00:00 2001 From: David Varela Date: Tue, 31 Jul 2018 02:02:18 -0700 Subject: [PATCH 01/22] [RFC] Make command spec more declarative (#509) * Refactor `REPLMode.parse_quotes` --- stdlib/Pkg/src/API.jl | 17 +- stdlib/Pkg/src/REPLMode.jl | 1587 ++++++++++++++++++++---------------- stdlib/Pkg/test/repl.jl | 331 +++++++- 3 files changed, 1217 insertions(+), 718 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 8d6d85fb284f0..dc659e3959408 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -28,9 +28,11 @@ add_or_develop(pkg::Union{String, PackageSpec}; kwargs...) = add_or_develop([pkg 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, devdir::Union{String,Nothing}=nothing, kwargs...) +function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, devdir::Bool=false, kwargs...) Context!(ctx; kwargs...) + devdir = devdir ? joinpath(dirname(ctx.env.project_file), "dev") : nothing + # 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()) @@ -67,7 +69,12 @@ 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...) +function rm(ctx::Context, pkgs::Vector{PackageSpec}; mode=PKGMODE_PROJECT, kwargs...) + for pkg in pkgs + #TODO only overwrite pkg.mode is default value ? + pkg.mode = mode + end + Context!(ctx; kwargs...) ctx.preview && preview_info() project_deps_resolve!(ctx.env, pkgs) @@ -144,6 +151,12 @@ up(pkgs::Vector{PackageSpec}; kwargs...) = up(Context(), pkgs; kwargs...) function up(ctx::Context, pkgs::Vector{PackageSpec}; level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode=PKGMODE_PROJECT, do_update_registry=true, kwargs...) + for pkg in pkgs + # TODO only override if they are not already set + pkg.mode = mode + pkg.version = level + end + Context!(ctx; kwargs...) ctx.preview && preview_info() do_update_registry && update_registry(ctx) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index a7df17f52b8a0..c38749b968b14 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1,5 +1,3 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - module REPLMode using Markdown @@ -11,45 +9,6 @@ import REPL: LineEdit, REPLCompletions import ..devdir, ..Types.casesensitive_isdir, ..TOML using ..Types, ..Display, ..Operations, ..API -############ -# Commands # -############ -@enum(CommandKind, CMD_HELP, CMD_STATUS, CMD_SEARCH, CMD_ADD, CMD_RM, CMD_UP, - CMD_TEST, CMD_GC, CMD_PREVIEW, CMD_INIT, CMD_BUILD, CMD_FREE, - CMD_PIN, CMD_CHECKOUT, CMD_DEVELOP, CMD_GENERATE, CMD_PRECOMPILE, - CMD_INSTANTIATE, CMD_RESOLVE, CMD_ACTIVATE, CMD_DEACTIVATE) - -struct Command - kind::CommandKind - val::String -end -Base.show(io::IO, cmd::Command) = print(io, cmd.val) - -const cmds = Dict( - "help" => CMD_HELP, - "?" => CMD_HELP, - "status" => CMD_STATUS, - "st" => CMD_STATUS, - "add" => CMD_ADD, - "rm" => CMD_RM, - "remove" => CMD_RM, - "up" => CMD_UP, - "update" => CMD_UP, - "test" => CMD_TEST, - "gc" => CMD_GC, - "preview" => CMD_PREVIEW, - "build" => CMD_BUILD, - "pin" => CMD_PIN, - "free" => CMD_FREE, - "develop" => CMD_DEVELOP, - "dev" => CMD_DEVELOP, - "generate" => CMD_GENERATE, - "precompile" => CMD_PRECOMPILE, - "instantiate" => CMD_INSTANTIATE, - "resolve" => CMD_RESOLVE, - "activate" => CMD_ACTIVATE, -) - ################# # Git revisions # ################# @@ -60,64 +19,133 @@ end ########### # Options # ########### -@enum(OptionKind, OPT_ENV, OPT_PROJECT, OPT_MANIFEST, OPT_MAJOR, OPT_MINOR, - OPT_PATCH, OPT_FIXED, OPT_COVERAGE, OPT_NAME, - OPT_LOCAL, OPT_SHARED) - -function Types.PackageMode(opt::OptionKind) - opt == OPT_MANIFEST && return PKGMODE_MANIFEST - opt == OPT_PROJECT && return PKGMODE_PROJECT - throw(ArgumentError("invalid option $opt")) +#TODO should this opt be removed: ("name", :cmd, :temp => false) +struct OptionSpec + name::String + short_name::Union{Nothing,String} + api::Pair{Symbol, Any} + is_switch::Bool end -function Types.UpgradeLevel(opt::OptionKind) - opt == OPT_MAJOR && return UPLEVEL_MAJOR - opt == OPT_MINOR && return UPLEVEL_MINOR - opt == OPT_PATCH && return UPLEVEL_PATCH - opt == OPT_FIXED && return UPLEVEL_FIXED - throw(ArgumentError("invalid option $opt")) +@enum(OptionClass, OPT_ARG, OPT_SWITCH) +const OptionDeclaration = Tuple{Union{String,Vector{String}}, # name + short_name? + OptionClass, # arg or switch + Pair{Symbol, Any} # api keywords + } + +function OptionSpec(x::OptionDeclaration)::OptionSpec + get_names(name::String) = (name, nothing) + function get_names(names::Vector{String}) + @assert length(names) == 2 + return (names[1], names[2]) + end + + is_switch = x[2] == OPT_SWITCH + api = x[3] + (name, short_name) = get_names(x[1]) + #TODO assert matching lex regex + if !is_switch + @assert api.second === nothing || hasmethod(api.second, Tuple{String}) + end + return OptionSpec(name, short_name, api, is_switch) end -struct Option - kind::OptionKind - val::String - argument::Union{String, Nothing} - Option(kind::OptionKind, val::String) = new(kind, val, nothing) - function Option(kind::OptionKind, val::String, argument::Union{String, Nothing}) - if kind in (OPT_PROJECT, OPT_MANIFEST, OPT_MAJOR, - OPT_MINOR, OPT_PATCH, OPT_FIXED) && - argument !== nothing - cmderror("the `$val` option does not take an argument") - elseif kind in (OPT_ENV,) && argument == nothing - cmderror("the `$val` option requires an argument") +function OptionSpecs(decs::Vector{OptionDeclaration})::Dict{String, OptionSpec} + specs = Dict() + for x in decs + opt_spec = OptionSpec(x) + @assert get(specs, opt_spec.name, nothing) === nothing # don't overwrite + specs[opt_spec.name] = opt_spec + if opt_spec.short_name !== nothing + @assert get(specs, opt_spec.short_name, nothing) === nothing # don't overwrite + specs[opt_spec.short_name] = opt_spec end - new(kind, val, argument) end + return specs end -Base.show(io::IO, opt::Option) = print(io, "--$(opt.val)", opt.argument == nothing ? "" : "=$(opt.argument)") -const opts = Dict( - "env" => OPT_ENV, - "project" => OPT_PROJECT, - "p" => OPT_PROJECT, - "manifest" => OPT_MANIFEST, - "m" => OPT_MANIFEST, - "major" => OPT_MAJOR, - "minor" => OPT_MINOR, - "patch" => OPT_PATCH, - "fixed" => OPT_FIXED, - "coverage" => OPT_COVERAGE, - "name" => OPT_NAME, - "local" => OPT_LOCAL, - "shared" => OPT_SHARED, -) +struct Option + val::String + argument::Union{Nothing,String} + Option(val::AbstractString) = new(val, nothing) + Option(val::AbstractString, arg::Union{Nothing,String}) = new(val, arg) +end +Base.show(io::IO, opt::Option) = print(io, "--$(opt.val)", opt.argument == nothing ? "" : "=$(opt.argument)") function parse_option(word::AbstractString)::Option m = match(r"^(?: -([a-z]) | --([a-z]{2,})(?:\s*=\s*(\S*))? )$"ix, word) - m == nothing && cmderror("invalid option: ", repr(word)) - k = m.captures[1] != nothing ? m.captures[1] : m.captures[2] - haskey(opts, k) || cmderror("invalid option: ", repr(word)) - return Option(opts[k], String(k), m.captures[3] == nothing ? nothing : String(m.captures[3])) + m == nothing && cmderror("malformed option: ", repr(word)) + option_name = (m.captures[1] != nothing ? m.captures[1] : m.captures[2]) + option_arg = (m.captures[3] == nothing ? nothing : String(m.captures[3])) + return Option(option_name, option_arg) +end + +meta_option_declarations = OptionDeclaration[ + ("env", OPT_ARG, :env => arg->EnvCache(Base.parse_env(arg))) +] +meta_option_specs = OptionSpecs(meta_option_declarations) + +################ +# Command Spec # +################ +@enum(CommandKind, CMD_HELP, CMD_RM, CMD_ADD, CMD_DEVELOP, CMD_UP, + CMD_STATUS, CMD_TEST, CMD_GC, CMD_BUILD, CMD_PIN, + CMD_FREE, CMD_GENERATE, CMD_RESOLVE, CMD_PRECOMPILE, + CMD_INSTANTIATE, CMD_ACTIVATE, CMD_PREVIEW, + CMD_REGISTRY_ADD, + ) +@enum(ArgClass, ARG_RAW, ARG_PKG, ARG_VERSION, ARG_REV, ARG_ALL) +struct ArgSpec + class::ArgClass + count::Vector{Int} +end +const CommandDeclaration = Tuple{CommandKind, + Vector{String}, # names + Function, # handler + Tuple{ArgClass, Vector{Int}}, # argument count + Vector{OptionDeclaration}, # options + Union{Nothing, Markdown.MD}, #help + } +struct CommandSpec + kind::CommandKind + names::Vector{String} + handler::Function + argument_spec::ArgSpec # note: just use range operator for max/min + option_specs::Dict{String, OptionSpec} + help::Union{Nothing, Markdown.MD} +end +command_specs = Dict{String,CommandSpec}() # TODO remove this ? + +function SuperSpecs(foo)::Dict{String,Dict{String,CommandSpec}} + super_specs = Dict() + for x in foo + sub_specs = CommandSpecs(x.second) + for name in x.first + @assert get(super_specs, name, nothing) === nothing + super_specs[name] = sub_specs + end + end + return super_specs +end + +# populate a dictionary: command_name -> command_spec +function CommandSpecs(declarations::Vector{CommandDeclaration})::Dict{String,CommandSpec} + specs = Dict() + for dec in declarations + names = dec[2] + spec = CommandSpec(dec[1], + names, + dec[3], + ArgSpec(dec[4]...), + OptionSpecs(dec[5]), + dec[end]) + for name in names + # TODO regex check name + @assert get(specs, name, nothing) === nothing + specs[name] = spec + end + end + return specs end ################### @@ -154,44 +182,97 @@ end ################ # REPL parsing # ################ -const lex_re = r"^[\?\./\+\-](?!\-) | ((git|ssh|http(s)?)|(git@[\w\-\.]+))(:(//)?)([\w\.@\:/\-~]+)(\.git)(/)? | [^@\#\s;]+\s*=\s*[^@\#\s;]+ | \#\s*[^@\#\s;]* | @\s*[^@\#\s;]* | [^@\#\s;]+|;"x +mutable struct Statement + command::Union{Nothing,CommandSpec} + options::Vector{String} + arguments::Vector{String} + meta_options::Vector{String} + Statement() = new(nothing, [], [], []) +end -const Token = Union{Command, Option, VersionRange, String, Rev} - -function tokenize(cmd::String)::Vector{Vector{Token}} - # phase 1: tokenize accoring to whitespace / quotes - chunks = parse_quotes(cmd) - # phase 2: tokenzie unquoted tokens according to pkg REPL syntax - words::Vector{String} = [] - for chunk in chunks - is_quoted = chunk[1] - word = chunk[2] - if is_quoted - push!(words, word) - else # break unquoted chunks further according to lexer - # note: space before `$word` is necessary to keep using current `lex_re` - # v - append!(words, map(m->m.match, eachmatch(lex_re, " $word"))) - end +struct QuotedWord + word::String + isquoted::Bool +end + +function parse(cmd::String)::Vector{Statement} + # replace new lines with ; to support multiline commands + cmd = replace(replace(cmd, "\r\n" => "; "), "\n" => "; ") + # tokenize accoring to whitespace / quotes + qwords = parse_quotes(cmd) + # tokenzie unquoted tokens according to pkg REPL syntax + words::Vector{String} = collect(Iterators.flatten(map(qword2word, qwords))) + # break up words according to ";"(doing this early makes subsequent processing easier) + word_groups = group_words(words) + # create statements + statements = map(Statement, word_groups) + return statements +end + +# vector of words -> structured statement +# minimal checking is done in this phase +function Statement(words) + is_option(word) = first(word) == '-' + statement = Statement() + + word = popfirst!(words) + # meta options + while is_option(word) + push!(statement.meta_options, word) + isempty(words) && cmderror("no command specified") + word = popfirst!(words) end + # command + if word in keys(super_specs) + super = super_specs[word] + word = popfirst!(words) + else + super = super_specs["package"] + end + command = get(super, word, nothing) + command !== nothing || cmderror("expected command. instead got [$word]") + statement.command = command + # command arguments + for word in words + push!((is_option(word) ? statement.options : statement.arguments), word) + end + return statement +end - commands = Vector{Token}[] - while !isempty(words) - push!(commands, tokenize!(words)) +# break up words according to `;`(doing this early makes subsequent processing easier) +# the final group does not require a trailing `;` +function group_words(words)::Vector{Vector{String}} + statements = Vector{String}[] + x = String[] + for word in words + if word == ";" + isempty(x) ? cmderror("empty statement") : push!(statements, x) + x = String[] + else + push!(x, word) + end end - return commands + isempty(x) || push!(statements, x) + return statements +end + +const lex_re = r"^[\?\./\+\-](?!\-) | ((git|ssh|http(s)?)|(git@[\w\-\.]+))(:(//)?)([\w\.@\:/\-~]+)(\.git)(/)? | [^@\#\s;]+\s*=\s*[^@\#\s;]+ | \#\s*[^@\#\s;]* | @\s*[^@\#\s;]* | [^@\#\s;]+|;"x + +function qword2word(qword::QuotedWord) + return qword.isquoted ? [qword.word] : map(m->m.match, eachmatch(lex_re, " $(qword.word)")) + # ^ + # note: space before `$word` is necessary to keep using current `lex_re` end -function parse_quotes(cmd::String) +function parse_quotes(cmd::String)::Vector{QuotedWord} in_doublequote = false in_singlequote = false - all_tokens::Array = [] - token_in_progress::Array{Char} = [] + qwords = QuotedWord[] + token_in_progress = Char[] push_token!(is_quoted) = begin - complete_token = String(token_in_progress) + push!(qwords, QuotedWord(String(token_in_progress), is_quoted)) empty!(token_in_progress) - push!(all_tokens, (is_quoted, complete_token)) end for c in cmd @@ -216,644 +297,364 @@ function parse_quotes(cmd::String) end end if (in_doublequote || in_singlequote) - ArgumentError("unterminated quote") + cmderror("unterminated quote") else push_token!(false) end # to avoid complexity in the main loop, empty tokens are allowed above and # filtered out before returning - isnotempty(x) = !isempty(x[2]) - filter!(isnotempty, all_tokens) - return all_tokens + return filter(x->!isempty(x.word), qwords) end -function tokenize!(words::Vector{<:AbstractString})::Vector{Token} - tokens = Token[] - help_mode = false - preview_mode = false - # First parse a Command or a modifier (help / preview) + Command - while !isempty(words) - word = popfirst!(words) - if word[1] == '-' && length(word) > 1 - push!(tokens, parse_option(word)) - else - haskey(cmds, word) || cmderror("invalid command: ", repr(word)) - cmdkind = cmds[word] - push!(tokens, Command(cmdkind, word)) - # If help / preview and not in help mode we want to eat another cmd - if !help_mode - cmdkind == CMD_HELP && (help_mode = true; continue) - cmdkind == CMD_PREVIEW && (preview_mode = true; continue) - end - break - end - end - if isempty(tokens) || !(tokens[end] isa Command) - cmderror("no package command given") - end - # Now parse the arguments / options to the command - while !isempty(words) - word = popfirst!(words) - if word == ";" - return tokens - elseif first(word) == '-' - push!(tokens, parse_option(word)) - elseif first(word) == '@' - push!(tokens, VersionRange(strip(word[2:end]))) - elseif first(word) == '#' - push!(tokens, Rev(word[2:end])) - else - push!(tokens, String(word)) - end - end - return tokens +############## +# PkgCommand # +############## +const Token = Union{String, VersionRange, Rev} +const PkgArguments = Union{Vector{String}, Vector{PackageSpec}} +#TODO embed spec in PkgCommand? +struct PkgCommand + meta_options::Vector{Option} + spec::CommandSpec + options::Vector{Option} + arguments::PkgArguments + PkgCommand() = new([], "", [], []) + PkgCommand(meta_opts, cmd_name, opts, args) = new(meta_opts, cmd_name, opts, args) end +const APIOption = Pair{Symbol, Any} +APIOptions(command::PkgCommand)::Vector{APIOption} = + APIOptions(command.options, command.spec.option_specs) + +function APIOptions(options::Vector{Option}, + specs::Dict{String, OptionSpec}, + )::Vector{APIOption} + return map(options) do opt + spec = specs[opt.val] + # opt is switch + spec.is_switch && return spec.api + # no opt wrapper -> just use raw argument + spec.api.second === nothing && return spec.api.first => opt.argument + # given opt wrapper + return spec.api.first => spec.api.second(opt.argument) + end +end -############# -# Execution # -############# - -function do_cmd(repl::REPL.AbstractREPL, input::String; do_rethrow=false) - try - commands = tokenize(input) - for command in commands - do_cmd!(command, repl) - end - catch err - if do_rethrow - rethrow(err) - end - if err isa CommandError || err isa ResolverError - Base.display_error(repl.t.err_stream, ErrorException(sprint(showerror, err)), Ptr{Nothing}[]) - else - Base.display_error(repl.t.err_stream, err, Base.catch_backtrace()) - end +function key_api(key::Symbol, api_opts::Vector{APIOption}) + index = findfirst(x->x.first == key, api_opts) + if index !== nothing + return api_opts[index].second end end -function enforce_argument_order(tokens::Vector{Token}) - prev_token = nothing - function check_prev_token(valid_type::DataType, error_message::AbstractString) - prev_token isa valid_type || cmderror(error_message) +set_default!(opt, api_opts::Vector{APIOption}) = + key_api(opt.first, api_opts) === nothing && push!(api_opts, opt) + +function enforce_argument_order(args::Vector{Token}) + prev_arg = nothing + function check_prev_arg(valid_type::DataType, error_message::AbstractString) + prev_arg isa valid_type || cmderror(error_message) end - for token in tokens - if token isa VersionRange - check_prev_token(String, "package name/uuid must precede version spec `@$token`") - elseif token isa Rev - check_prev_token(String, "package name/uuid must precede rev spec `#$(token.rev)`") + for arg in args + if arg isa VersionRange + check_prev_arg(String, "package name/uuid must precede version spec `@$arg`") + elseif arg isa Rev + check_prev_arg(String, "package name/uuid must precede rev spec `#$(arg.rev)`") end - prev_token = token + prev_arg = arg end end -function do_cmd!(tokens::Vector{Token}, repl) - cmd = env_opt = nothing - while !isempty(tokens) - token = popfirst!(tokens) - if token isa Command - cmd = token - break - elseif token isa Option - # Only OPT_ENV is allowed before a command - if token.kind == OPT_ENV - env_opt = Base.parse_env(token.argument) - else - cmderror("unrecognized command option: `$token`") - end - else - cmderror("misplaced token: ", token) - end +function word2token(word::AbstractString)::Token + if first(word) == '@' + return VersionRange(word[2:end]) + elseif first(word) == '#' + return Rev(word[2:end]) + else + return String(word) end +end - if cmd.kind == CMD_ACTIVATE - return Base.invokelatest(do_activate!, Base.active_project() === nothing ? - nothing : EnvCache(env_opt), tokens) +function enforce_arg_spec(raw_args::Vector{String}, class::ArgClass) + # TODO is there a more idiomatic way to do this? + function has_types(arguments::Vector{Token}, types::Vector{DataType}) + return !isempty(filter(x->typeof(x) in types, arguments)) end - ctx = Context(env = EnvCache(env_opt)) - if cmd.kind == CMD_PREVIEW - ctx.preview = true - isempty(tokens) && cmderror("expected a command to preview") - cmd = popfirst!(tokens) - end + class == ARG_RAW && return raw_args + args::Vector{Token} = map(word2token, raw_args) + class == ARG_ALL && return args - enforce_argument_order(tokens) - - # Using invokelatest to hide the functions from inference. - # Otherwise it would try to infer everything here. - cmd.kind == CMD_INIT ? Base.invokelatest( do_init!, ctx, tokens) : - cmd.kind == CMD_HELP ? Base.invokelatest( do_help!, ctx, tokens, repl) : - cmd.kind == CMD_RM ? Base.invokelatest( do_rm!, ctx, tokens) : - cmd.kind == CMD_ADD ? Base.invokelatest(do_add_or_develop!, ctx, tokens, CMD_ADD) : - cmd.kind == CMD_CHECKOUT ? Base.invokelatest(do_add_or_develop!, ctx, tokens, CMD_DEVELOP) : - cmd.kind == CMD_DEVELOP ? Base.invokelatest(do_add_or_develop!, ctx, tokens, CMD_DEVELOP) : - cmd.kind == CMD_UP ? Base.invokelatest( do_up!, ctx, tokens) : - cmd.kind == CMD_STATUS ? Base.invokelatest( do_status!, ctx, tokens) : - cmd.kind == CMD_TEST ? Base.invokelatest( do_test!, ctx, tokens) : - cmd.kind == CMD_GC ? Base.invokelatest( do_gc!, ctx, tokens) : - cmd.kind == CMD_BUILD ? Base.invokelatest( do_build!, ctx, tokens) : - cmd.kind == CMD_PIN ? Base.invokelatest( do_pin!, ctx, tokens) : - cmd.kind == CMD_FREE ? Base.invokelatest( do_free!, ctx, tokens) : - cmd.kind == CMD_GENERATE ? Base.invokelatest( do_generate!, ctx, tokens) : - cmd.kind == CMD_RESOLVE ? Base.invokelatest( do_resolve!, ctx, tokens) : - cmd.kind == CMD_PRECOMPILE ? Base.invokelatest( do_precompile!, ctx, tokens) : - cmd.kind == CMD_INSTANTIATE ? Base.invokelatest( do_instantiate!, ctx, tokens) : - cmderror("`$cmd` command not yet implemented") - return + if class == ARG_PKG && has_types(args, [VersionRange, Rev]) + cmderror("no versioned packages allowed") + elseif class == ARG_REV && has_types(args, [VersionRange]) + cmderror("no versioned packages allowed") + elseif class == ARG_VERSION && has_types(args, [Rev]) + cmderror("no reved packages allowed") + end + return args end -const help = md""" - -**Welcome to the Pkg REPL-mode**. To return to the `julia>` prompt, either press -backspace when the input line is empty or press Ctrl+C. - - -**Synopsis** - - pkg> [--env=...] cmd [opts] [args] - -Multiple commands can be given on the same line by interleaving a `;` between the commands. - -**Environment** - -The `--env` meta option determines which project environment to manipulate. By -default, this looks for a git repo in the parents directories of the current -working directory, and if it finds one, it uses that as an environment. Otherwise, -it uses a named environment (typically found in `~/.julia/environments`) looking -for environments named `v$(VERSION.major).$(VERSION.minor).$(VERSION.patch)`, -`v$(VERSION.major).$(VERSION.minor)`, `v$(VERSION.major)` or `default` in order. - -**Commands** - -What action you want the package manager to take: - -`help`: show this message - -`status`: summarize contents of and changes to environment - -`add`: add packages to project - -`develop`: clone the full package repo locally for development - -`rm`: remove packages from project or manifest - -`up`: update packages in manifest - -`test`: run tests for packages - -`build`: run the build script for packages - -`pin`: pins the version of packages - -`free`: undoes a `pin`, `develop`, or stops tracking a repo. - -`instantiate`: downloads all the dependencies for the project - -`resolve`: resolves to update the manifest from changes in dependencies of -developed packages - -`generate`: generate files for a new project - -`preview`: previews a subsequent command without affecting the current state - -`precompile`: precompile all the project dependencies - -`gc`: garbage collect packages not used for a significant time - -`activate`: set the primary environment the package manager manipulates -""" - -const helps = Dict( - CMD_HELP => md""" - - help - - Display this message. - - help cmd ... - - Display usage information for commands listed. - - Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test`, `build`, `free`, `pin`, `develop`. - """, CMD_STATUS => md""" - - status - status [-p|--project] - status [-m|--manifest] - - Show the status of the current environment. By default, the full contents of - the project file is summarized, showing what version each package is on and - how it has changed since the last git commit (if in a git repo), as well as - any changes to manifest packages not already listed. In `--project` mode, the - status of the project file is summarized. In `--manifest` mode the output also - includes the dependencies of explicitly added packages. - """, CMD_GENERATE => md""" - - generate pkgname - - Create a project called `pkgname` in the current folder. - """, - CMD_ADD => md""" - - add pkg[=uuid] [@version] [#rev] ... - - Add package `pkg` to the current project file. If `pkg` could refer to - multiple different packages, specifying `uuid` allows you to disambiguate. - `@version` optionally allows specifying which versions of packages. Versions - may be specified by `@1`, `@1.2`, `@1.2.3`, allowing any version with a prefix - that matches, or ranges thereof, such as `@1.2-3.4.5`. A git-revision can be - specified by `#branch` or `#commit`. - - If a local path is used as an argument to `add`, the path needs to be a git repository. - The project will then track that git repository just like if it is was tracking a remote repository online. - - **Examples** - ``` - pkg> add Example - pkg> add Example@0.5 - pkg> add Example#master - pkg> add Example#c37b675 - pkg> add https://github.com/JuliaLang/Example.jl#master - pkg> add git@github.com:JuliaLang/Example.jl.git - pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a - ``` - """, CMD_RM => md""" - - rm [-p|--project] pkg[=uuid] ... - - Remove package `pkg` from the project file. Since the name `pkg` can only - refer to one package in a project this is unambiguous, but you can specify - a `uuid` anyway, and the command is ignored, with a warning if package name - and UUID do not mactch. When a package is removed from the project file, it - may still remain in the manifest if it is required by some other package in - the project. Project mode operation is the default, so passing `-p` or - `--project` is optional unless it is preceded by the `-m` or `--manifest` - options at some earlier point. - - rm [-m|--manifest] pkg[=uuid] ... - - Remove package `pkg` from the manifest file. If the name `pkg` refers to - multiple packages in the manifest, `uuid` disambiguates it. Removing a package - from the manifest forces the removal of all packages that depend on it, as well - as any no-longer-necessary manifest packages due to project package removals. - """, CMD_UP => md""" - - up [-p|project] [opts] pkg[=uuid] [@version] ... - up [-m|manifest] [opts] pkg[=uuid] [@version] ... - - opts: --major | --minor | --patch | --fixed - - Update the indicated package within the constraints of the indicated version - specifications. Versions may be specified by `@1`, `@1.2`, `@1.2.3`, allowing - any version with a prefix that matches, or ranges thereof, such as `@1.2-3.4.5`. - In `--project` mode, package specifications only match project packages, while - in `manifest` mode they match any manifest package. Bound level options force - the following packages to be upgraded only within the current major, minor, - patch version; if the `--fixed` upgrade level is given, then the following - packages will not be upgraded at all. - """, CMD_PREVIEW => md""" - - preview cmd - - Runs the command `cmd` in preview mode. This is defined such that no side effects - will take place i.e. no packages are downloaded and neither the project nor manifest - is modified. - """, CMD_TEST => md""" - - test [opts] pkg[=uuid] ... - - opts: --coverage - - Run the tests for package `pkg`. This is done by running the file `test/runtests.jl` - in the package directory. The option `--coverage` can be used to run the tests with - coverage enabled. - """, CMD_GC => md""" - - Deletes packages that cannot be reached from any existing environment. - """, CMD_BUILD =>md""" - - build pkg[=uuid] ... - - Run the build script in deps/build.jl for each package in `pkg`` and all of their dependencies in depth-first recursive order. - If no packages are given, runs the build scripts for all packages in the manifest. - """, CMD_PIN => md""" - - pin pkg[=uuid] ... - - Pin packages to given versions, or the current version if no version is specified. A pinned package has its version fixed and will not be upgraded or downgraded. - A pinned package has the symbol `⚲` next to its version in the status list. - """, CMD_FREE => md""" - free pkg[=uuid] ... - - Free a pinned package `pkg`, which allows it to be upgraded or downgraded again. If the package is checked out (see `help develop`) then this command - makes the package no longer being checked out. - """, CMD_DEVELOP => md""" - develop [--shared|--local] pkg[=uuid] [#rev] ... - - Make a package available for development. If `pkg` is an existing local path that path will be recorded in - the manifest and used. Otherwise, a full git clone of `pkg` at rev `rev` is made. The location of the clone is - controlled by the `--shared` (default) and `--local` arguments. The `--shared` location defaults to - `~/.julia/dev`, but can be controlled with the `JULIA_PKG_DEVDIR` environment variable. When `--local` is given, - the clone is placed in a `dev` folder in the current project. - This operation is undone by `free`. - - *Example* - ```jl - pkg> develop Example - pkg> develop Example#master - pkg> develop Example#c37b675 - pkg> develop https://github.com/JuliaLang/Example.jl#master - pkg> develop --local Example - ``` - """, CMD_PRECOMPILE => md""" - precompile - - Precompile all the dependencies of the project by running `import` on all of them in a new process. - """, CMD_INSTANTIATE => md""" - instantiate - instantiate [-m|--manifest] - instantiate [-p|--project] - - Download all the dependencies for the current project at the version given by the project's manifest. - If no manifest exists or the `--project` option is given, resolve and download the dependencies compatible with the project. - """, CMD_RESOLVE => md""" - resolve - - Resolve the project i.e. run package resolution and update the Manifest. This is useful in case the dependencies of developed - packages have changed causing the current Manifest to_indices be out of sync. - """ -) - -function do_help!( - ctk::Context, - tokens::Vector{Token}, - repl::REPL.AbstractREPL, -) - disp = REPL.REPLDisplay(repl) - if isempty(tokens) - Base.display(disp, help) - return - end - help_md = md"" - for token in tokens - if token isa Command - if haskey(helps, token.kind) - isempty(help_md.content) || - push!(help_md.content, md"---") - push!(help_md.content, helps[token.kind].content) +function package_args(args::Vector{Token}, spec::CommandSpec)::Vector{PackageSpec} + pkgs = PackageSpec[] + for arg in args + if arg isa String + is_add_or_develop = spec.kind in (CMD_ADD, CMD_DEVELOP) + push!(pkgs, parse_package(arg; add_or_develop=is_add_or_develop)) + elseif arg isa VersionRange + pkgs[end].version = arg + elseif arg isa Rev + pkg = pkgs[end] + if pkg.repo == nothing + pkg.repo = Types.GitRepo("", arg.rev) else - cmderror("Sorry, I don't have any help for the `$(token.val)` command.") + pkgs[end].repo.rev = arg.rev end else - error("invalid usage of help command") + assert(false) end end - Base.display(disp, help_md) + return pkgs end -function do_rm!(ctx::Context, tokens::Vector{Token}) - # tokens: package names and/or uuids - mode = PKGMODE_PROJECT - pkgs = PackageSpec[] - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token)) - pkgs[end].mode = mode - elseif token isa VersionRange - cmderror("`rm` does not take version specs") - elseif token isa Option - if token.kind in (OPT_PROJECT, OPT_MANIFEST) - mode = PackageMode(token.kind) - else - cmderror("invalid option for `rm`: $token") - end - end - end - isempty(pkgs) && - cmderror("`rm` – list packages to remove") - API.rm(ctx, pkgs) +function enforce_arg_count(count::Vector{Int}, args::PkgArguments) + isempty(count) && return + length(args) in count || + cmderror("Wrong number of arguments") end -function do_add_or_develop!(ctx::Context, tokens::Vector{Token}, cmd::CommandKind) - @assert cmd in (CMD_ADD, CMD_DEVELOP) - mode = cmd == CMD_ADD ? :add : :develop - # tokens: package names and/or uuids, optionally followed by version specs - isempty(tokens) && - cmderror("`$mode` – list packages to $mode") - pkgs = PackageSpec[] - dev_mode = OPT_SHARED # TODO: Make this default configurable - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token; add_or_develop=true)) - elseif token isa VersionRange - pkgs[end].version = VersionSpec(token) - elseif token isa Rev - # WE did not get the repo from the - pkg = pkgs[end] - if pkg.repo == nothing - pkg.repo = Types.GitRepo("", token.rev) - else - pkgs[end].repo.rev = token.rev - end - elseif token isa Option - if mode === :develop && token.kind in (OPT_LOCAL, OPT_SHARED) - dev_mode = token.kind - else - cmderror("`$mode` doesn't take options: $token") - end - end +function enforce_args(raw_args::Vector{String}, spec::ArgSpec, cmd_spec::CommandSpec)::PkgArguments + if spec.class == ARG_RAW + enforce_arg_count(spec.count, raw_args) + return raw_args end - dev_dir = mode === :add ? nothing : dev_mode == OPT_LOCAL ? - joinpath(dirname(ctx.env.project_file), "dev") : nothing - return API.add_or_develop(ctx, pkgs, mode=mode, devdir=dev_dir) + + args = enforce_arg_spec(raw_args, spec.class) + enforce_argument_order(args) + pkgs = package_args(args, cmd_spec) + enforce_arg_count(spec.count, pkgs) + return pkgs end -function do_up!(ctx::Context, tokens::Vector{Token}) - # tokens: - # - upgrade levels as options: --[fixed|patch|minor|major] - # - package names and/or uuids, optionally followed by version specs - pkgs = PackageSpec[] - mode = PKGMODE_PROJECT - level = UPLEVEL_MAJOR - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token)) - pkgs[end].version = level - pkgs[end].mode = mode - elseif token isa VersionRange - pkgs[end].version = VersionSpec(token) - elseif token isa Option - if token.kind in (OPT_PROJECT, OPT_MANIFEST) - mode = PackageMode(token.kind) - elseif token.kind in (OPT_MAJOR, OPT_MINOR, OPT_PATCH, OPT_FIXED) - level = UpgradeLevel(token.kind) - else - cmderror("invalid option for `up`: $(token)") - end - end +function enforce_option(option::String, specs::Dict{String,OptionSpec})::Option + opt = parse_option(option) + spec = get(specs, opt.val, nothing) + spec !== nothing || + cmderror("option '$(opt.val)' is not a valid option") + if spec.is_switch + opt.argument === nothing || + cmderror("option '$(opt.val)' does not take an argument, but '$(opt.argument)' given") + else # option takes an argument + opt.argument !== nothing || + cmderror("option '$(opt.val)' expects an argument, but no argument given") end - API.up(ctx, pkgs; level=level, mode=mode) + return opt end -function do_pin!(ctx::Context, tokens::Vector{Token}) - pkgs = PackageSpec[] - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token)) - elseif token isa VersionRange - if token.lower != token.upper - cmderror("pinning a package requires a single version, not a versionrange") - end - pkgs[end].version = VersionSpec(token) - else - cmderror("free only takes a list of packages ") - end +function enforce_meta_options(options::Vector{String}, specs::Dict{String,OptionSpec})::Vector{Option} + meta_opt_names = keys(specs) + return map(options) do opt + tok = enforce_option(opt, specs) + tok.val in meta_opt_names || + cmderror("option '$opt' is not a valid meta option.") + #TODO hint that maybe they intended to use it as a command option + return tok end - API.pin(ctx, pkgs) end -function do_free!(ctx::Context, tokens::Vector{Token}) - pkgs = PackageSpec[] - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token)) +function enforce_opts(options::Vector{String}, specs::Dict{String,OptionSpec})::Vector{Option} + unique_keys = Symbol[] + get_key(opt::Option) = specs[opt.val].api.first + + # final parsing + toks = map(x->enforce_option(x,specs),options) + # checking + for opt in toks + # valid option + opt.val in keys(specs) || + cmderror("option '$(opt.val)' is not supported") + # conflicting options + key = get_key(opt) + if key in unique_keys + conflicting = filter(opt->get_key(opt) == key, toks) + cmderror("Conflicting options: $conflicting") else - cmderror("free only takes a list of packages") + push!(unique_keys, key) end end - API.free(ctx, pkgs) + return toks end -function do_status!(ctx::Context, tokens::Vector{Token}) - mode = PKGMODE_COMBINED - while !isempty(tokens) - token = popfirst!(tokens) - if token isa Option - if token.kind in (OPT_PROJECT, OPT_MANIFEST) - mode = PackageMode(token.kind) - else - cmderror("invalid option for `status`: $(token)") - end - else - cmderror("`status` does not take arguments") - end - end - Display.status(ctx, mode) +# this the entry point for the majority of input checks +function PkgCommand(statement::Statement)::PkgCommand + meta_opts = enforce_meta_options(statement.meta_options, + meta_option_specs) + args = enforce_args(statement.arguments, + statement.command.argument_spec, + statement.command) + opts = enforce_opts(statement.options, statement.command.option_specs) + return PkgCommand(meta_opts, statement.command, opts, args) end -# TODO , test recursive dependencies as on option. -function do_test!(ctx::Context, tokens::Vector{Token}) - pkgs = PackageSpec[] - coverage = false - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - pkg = parse_package(token) - pkg.mode = PKGMODE_MANIFEST - push!(pkgs, pkg) - elseif token isa Option - if token.kind == OPT_COVERAGE - coverage = true - else - cmderror("invalid option for `test`: $token") - end +############# +# Execution # +############# +function do_cmd(repl::REPL.AbstractREPL, input::String; do_rethrow=false) + try + statements = parse(input) + commands = map(PkgCommand, statements) + for cmd in commands + do_cmd!(cmd, repl) + end + catch err + if do_rethrow + rethrow(err) + end + if err isa CommandError || err isa ResolverError + Base.display_error(repl.t.err_stream, ErrorException(sprint(showerror, err)), Ptr{Nothing}[]) else - # TODO: Better error message - cmderror("invalid usage for `test`") + Base.display_error(repl.t.err_stream, err, Base.catch_backtrace()) end end - API.test(ctx, pkgs; coverage = coverage) end -function do_gc!(ctx::Context, tokens::Vector{Token}) - !isempty(tokens) && cmderror("`gc` does not take any arguments") - API.gc(ctx) +function do_cmd!(command::PkgCommand, repl) + meta_opts = APIOptions(command.meta_options, meta_option_specs) + ctx = Context(meta_opts...) + spec = command.spec + + # REPL specific commands + if spec.kind == CMD_HELP + return Base.invokelatest(do_help!, ctx, command, repl) + elseif spec.kind == CMD_PREVIEW + ctx.preview = true + cmd = command.arguments[1] + cmd_spec = get(command_specs, cmd, nothing) + cmd_spec === nothing && + cmderror("'$cmd' is not a valid command") + spec = cmd_spec + command = PkgCommand([], cmd, [], PackageSpec[]) + end + + # API commands + # TODO is invokelatest still needed? + Base.invokelatest(spec.handler, ctx, command.arguments, APIOptions(command)) end -function do_build!(ctx::Context, tokens::Vector{Token}) - pkgs = PackageSpec[] - while !isempty(tokens) - token = popfirst!(tokens) - if token isa String - push!(pkgs, parse_package(token)) - else - cmderror("`build` only takes a list of packages") - end +function do_help!(ctk::Context, command::PkgCommand, repl::REPL.AbstractREPL) + disp = REPL.REPLDisplay(repl) + if isempty(command.arguments) + Base.display(disp, help) + return end - API.build(ctx, pkgs) + help_md = md"" + for arg in command.arguments + spec = get(command_specs, arg, nothing) + spec === nothing && + cmderror("'$arg' does not name a command") + spec.help === nothing && + cmderror("Sorry, I don't have any help for the `$arg` command.") + isempty(help_md.content) || + push!(help_md.content, md"---") + push!(help_md.content, spec.help) + end + Base.display(disp, help_md) end -function do_generate!(ctx::Context, tokens::Vector{Token}) - isempty(tokens) && cmderror("`generate` requires a project name as an argument") - token = popfirst!(tokens) - token isa String || cmderror("`generate` takes a name of the project to create") - isempty(tokens) || cmderror("`generate` takes a single project name as an argument") - API.generate(ctx, token) +# TODO set default Display.status keyword: mode = PKGMODE_COMBINED +function do_status!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + set_default!(:mode => PKGMODE_COMBINED, api_opts) + Display.status(ctx, key_api(:mode, api_opts)) end -function do_precompile!(ctx::Context, tokens::Vector{Token}) - if !isempty(tokens) - cmderror("`precompile` does not take any arguments") - end - API.precompile(ctx) +# TODO remove the need to specify a handler function (not needed for REPL commands) +do_preview!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = nothing + +# TODO , test recursive dependencies as on option. +function do_test!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + foreach(arg -> arg.mode = PKGMODE_MANIFEST, args) + API.test(ctx, args; api_opts...) end -function do_instantiate!(ctx::Context, tokens::Vector{Token}) - manifest = nothing - for token in tokens - if token isa Option - if token.kind == OPT_MANIFEST - manifest = true - elseif token.kind == OPT_PROJECT - manifest = false - else - cmderror("invalid option for `instantiate`: $(token)") - end - else - cmderror("invalid argument for `instantiate` :$(token)") - end +function do_registry_add!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + println("This is a dummy function for now") + println("My args are:") + for arg in args + println("- $arg") end - API.instantiate(ctx; manifest=manifest) end -function do_resolve!(ctx::Context, tokens::Vector{Token}) - !isempty(tokens) && cmderror("`resolve` does not take any arguments") +do_precompile!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.precompile(ctx) + +do_resolve!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = API.resolve(ctx) -end -function do_activate!(env::Union{EnvCache,Nothing}, tokens::Vector{Token}) - if isempty(tokens) +do_gc!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.gc(ctx; api_opts...) + +do_instantiate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.instantiate(ctx; api_opts...) + +do_generate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.generate(ctx, args[1]) + +do_build!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.build(ctx, args; api_opts...) + +do_rm!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.rm(ctx, args; api_opts...) + +do_free!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.free(ctx, args; api_opts...) + +do_up!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = + API.up(ctx, args; api_opts...) + +function do_activate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + if isempty(args) return API.activate() + end + + path = args[1] + env = Base.active_project() === nothing ? nothing : ctx.env + devpath = nothing + if env !== nothing && haskey(env.project["deps"], path) + uuid = UUID(env.project["deps"][path]) + info = manifest_info(env, uuid) + devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing + end + # `pkg> activate path` does the following + # 1. if path exists, activate that + # 2. if path exists in deps, and the dep is deved, activate that path (`devpath`) above + # 3. activate the non-existing directory (e.g. as in `pkg> activate . for initing a new dev`) + if Types.isdir_windows_workaround(path) + API.activate(abspath(path)) + elseif devpath !== nothing + API.activate(abspath(devpath)) else - path = popfirst!(tokens) - if !isempty(tokens) || !(path isa String) - cmderror("`activate` takes an optional path to the env to activate") - end - devpath = nothing - if env !== nothing && haskey(env.project["deps"], path) - uuid = UUID(env.project["deps"][path]) - info = manifest_info(env, uuid) - devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing - end - # `pkg> activate path` does the following - # 1. if path exists, activate that - # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) - # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) - if Types.isdir_windows_workaround(path) - API.activate(abspath(path)) - elseif devpath !== nothing - API.activate(abspath(devpath)) - else - API.activate(abspath(path)) + API.activate(abspath(path)) + end +end + +function do_pin!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + for arg in args + # TODO not sure this is correct + if arg.version.ranges[1].lower != arg.version.ranges[1].upper + cmderror("pinning a package requires a single version, not a versionrange") end end + API.pin(ctx, args; api_opts...) +end + +function do_add!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + push!(api_opts, :mode => :add) + API.add_or_develop(ctx, args; api_opts...) +end + +function do_develop!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + push!(api_opts, :mode => :develop) + API.add_or_develop(ctx, args; api_opts...) end ###################### @@ -872,10 +673,11 @@ function MiniREPL() end REPL.REPLDisplay(repl::MiniREPL) = repl.display -__init__() = minirepl[] = MiniREPL() const minirepl = Ref{MiniREPL}() +#= __init__() = =# minirepl[] = MiniREPL() + macro pkg_str(str::String) :($(do_cmd)(minirepl[], $str; do_rethrow=true)) end @@ -883,9 +685,25 @@ end pkgstr(str::String) = do_cmd(minirepl[], str; do_rethrow=true) # handle completions -all_commands_sorted = sort!(collect(keys(cmds))) +all_commands_sorted = [] +long_commands = [] +all_options_sorted = [] +long_options = [] + +all_commands_sorted = sort(collect(String,keys(command_specs))) long_commands = filter(c -> length(c) > 2, all_commands_sorted) -all_options_sorted = [length(opt) > 1 ? "--$opt" : "-$opt" for opt in sort!(collect(keys(opts)))] +function all_options() + all_opts = [] + for command in values(command_specs) + for opt_spec in command.option_specs + push!(all_opts, opt_spec.name) + opt_spec.short_name !== nothing && push!(all_opts, opt_spec.short_name) + end + end + unique!(all_opts) + return all_opts +end +all_options_sorted = [length(opt) > 1 ? "--$opt" : "-$opt" for opt in sort!(all_options())] long_options = filter(c -> length(c) > 2, all_options_sorted) struct PkgCompletionProvider <: LineEdit.CompletionProvider end @@ -912,7 +730,7 @@ function complete_option(s, i1, i2) end function complete_package(s, i1, i2, lastcommand, project_opt) - if lastcommand in [CMD_STATUS, CMD_RM, CMD_UP, CMD_TEST, CMD_BUILD, CMD_FREE, CMD_PIN, CMD_CHECKOUT] + if lastcommand in [CMD_STATUS, CMD_RM, CMD_UP, CMD_TEST, CMD_BUILD, CMD_FREE, CMD_PIN] return complete_installed_package(s, i1, i2, project_opt) elseif lastcommand in [CMD_ADD, CMD_DEVELOP] return complete_remote_package(s, i1, i2) @@ -971,25 +789,17 @@ function completions(full, index) end # tokenize input, don't offer any completions for invalid commands - tokens = try - tokenize(join(pre_words[1:end-1], ' '))[end] + statement = try + parse(join(pre_words[1:end-1], ' '))[end] catch return String[], 0:-1, false end - tokens = reverse!(tokens) - - lastcommand = nothing + lastcommand = statement.command.kind project_opt = true - for t in tokens - if t isa Command - lastcommand = t.kind - break - end - end - for t in tokens - if t isa Option && t.kind in [OPT_PROJECT, OPT_MANIFEST] - project_opt = t.kind == OPT_PROJECT + for opt in statement.options + if opt in ["--manifest", "--project", "-m", "-p"] + project_opt = opt in ["--project", "-p"] break end end @@ -1011,7 +821,7 @@ prev_prefix = "" function promptf() global prev_project_timestamp, prev_prefix, prev_project_file project_file = try - project_file = Base.active_project() + Types.find_project_file() catch nothing end @@ -1121,4 +931,385 @@ function repl_init(repl) return end +######## +# SPEC # +######## +command_declarations = [ +["registry"] => CommandDeclaration[ +( + CMD_REGISTRY_ADD, + ["add"], + do_registry_add!, + (ARG_PKG, []), + [], + nothing, +), +], #registry + +["package"] => CommandDeclaration[ +( CMD_TEST, + ["test"], + do_test!, + (ARG_PKG, []), + [ + ("coverage", OPT_SWITCH, :coverage => true), + ], + md""" + + test [opts] pkg[=uuid] ... + + opts: --coverage + +Run the tests for package `pkg`. This is done by running the file `test/runtests.jl` +in the package directory. The option `--coverage` can be used to run the tests with +coverage enabled. The `startup.jl` file is disabled during testing unless +julia is started with `--startup-file=yes`. + """, +),( CMD_HELP, + ["help", "?"], + do_help!, + (ARG_RAW, []), + [], + md""" + + help + +Display this message. + + help cmd ... + +Display usage information for commands listed. + +Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test`, `build`, `free`, `pin`, `develop`. + """, +),( CMD_INSTANTIATE, + ["instantiate"], + do_instantiate!, + (ARG_RAW, [0]), + [ + (["project", "p"], OPT_SWITCH, :manifest => false), + (["manifest", "m"], OPT_SWITCH, :manifest => true), + ], + md""" + instantiate + instantiate [-m|--manifest] + instantiate [-p|--project] + +Download all the dependencies for the current project at the version given by the project's manifest. +If no manifest exists or the `--project` option is given, resolve and download the dependencies compatible with the project. + """, +),( CMD_RM, + ["remove", "rm"], + do_rm!, + (ARG_PKG, []), + [ + (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), + (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), + ], + md""" + + rm [-p|--project] pkg[=uuid] ... + +Remove package `pkg` from the project file. Since the name `pkg` can only +refer to one package in a project this is unambiguous, but you can specify +a `uuid` anyway, and the command is ignored, with a warning if package name +and UUID do not mactch. When a package is removed from the project file, it +may still remain in the manifest if it is required by some other package in +the project. Project mode operation is the default, so passing `-p` or +`--project` is optional unless it is preceded by the `-m` or `--manifest` +options at some earlier point. + + rm [-m|--manifest] pkg[=uuid] ... + +Remove package `pkg` from the manifest file. If the name `pkg` refers to +multiple packages in the manifest, `uuid` disambiguates it. Removing a package +from the manifest forces the removal of all packages that depend on it, as well +as any no-longer-necessary manifest packages due to project package removals. + """, +),( CMD_ADD, + ["add"], + do_add!, + (ARG_ALL, []), + [], + md""" + + add pkg[=uuid] [@version] [#rev] ... + +Add package `pkg` to the current project file. If `pkg` could refer to +multiple different packages, specifying `uuid` allows you to disambiguate. +`@version` optionally allows specifying which versions of packages. Versions +may be specified by `@1`, `@1.2`, `@1.2.3`, allowing any version with a prefix +that matches, or ranges thereof, such as `@1.2-3.4.5`. A git-revision can be +specified by `#branch` or `#commit`. + +If a local path is used as an argument to `add`, the path needs to be a git repository. +The project will then track that git repository just like if it is was tracking a remote repository online. + +**Examples** +``` +pkg> add Example +pkg> add Example@0.5 +pkg> add Example#master +pkg> add Example#c37b675 +pkg> add https://github.com/JuliaLang/Example.jl#master +pkg> add git@github.com:JuliaLang/Example.jl.git +pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a +``` + """, +),( CMD_DEVELOP, + ["develop", "dev"], + do_develop!, + (ARG_ALL, []), + [ + ("local", OPT_SWITCH, :devdir => true), + ("shared", OPT_SWITCH, :devdir => false), + ], + md""" + develop [--shared|--local] pkg[=uuid] [#rev] ... + +Make a package available for development. If `pkg` is an existing local path that path will be recorded in +the manifest and used. Otherwise, a full git clone of `pkg` at rev `rev` is made. The location of the clone is +controlled by the `--shared` (default) and `--local` arguments. The `--shared` location defaults to +`~/.julia/dev`, but can be controlled with the `JULIA_PKG_DEVDIR` environment variable. When `--local` is given, +the clone is placed in a `dev` folder in the current project. +This operation is undone by `free`. + +*Example* +```jl +pkg> develop Example +pkg> develop Example#master +pkg> develop Example#c37b675 +pkg> develop https://github.com/JuliaLang/Example.jl#master +pkg> develop --local Example +``` + """, +),( CMD_FREE, + ["free"], + do_free!, + (ARG_PKG, []), + [], + md""" + free pkg[=uuid] ... + +Free a pinned package `pkg`, which allows it to be upgraded or downgraded again. If the package is checked out (see `help develop`) then this command +makes the package no longer being checked out. + """, +),( CMD_PIN, + ["pin"], + do_pin!, + (ARG_VERSION, []), + [], + md""" + + pin pkg[=uuid] ... + +Pin packages to given versions, or the current version if no version is specified. A pinned package has its version fixed and will not be upgraded or downgraded. +A pinned package has the symbol `⚲` next to its version in the status list. + """, +),( CMD_BUILD, + ["build"], + do_build!, + (ARG_PKG, []), + [], + md""" + + build pkg[=uuid] ... + +Run the build script in `deps/build.jl` for each package in `pkg` and all of their dependencies in depth-first recursive order. +If no packages are given, runs the build scripts for all packages in the manifest. +The `startup.jl` file is disabled during building unless julia is started with `--startup-file=yes`. + """, +),( CMD_RESOLVE, + ["resolve"], + do_resolve!, + (ARG_RAW, [0]), + [], + md""" + resolve + +Resolve the project i.e. run package resolution and update the Manifest. This is useful in case the dependencies of developed +packages have changed causing the current Manifest to_indices be out of sync. + """, +),( CMD_ACTIVATE, + ["activate"], + do_activate!, + (ARG_RAW, [0,1]), + [], + nothing, +),( CMD_UP, + ["update", "up"], + do_up!, + (ARG_VERSION, []), + [ + (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), + (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), + ("major", OPT_SWITCH, :level => UPLEVEL_MAJOR), + ("minor", OPT_SWITCH, :level => UPLEVEL_MINOR), + ("patch", OPT_SWITCH, :level => UPLEVEL_PATCH), + ("fixed", OPT_SWITCH, :level => UPLEVEL_FIXED), + ], + md""" + + up [-p|project] [opts] pkg[=uuid] [@version] ... + up [-m|manifest] [opts] pkg[=uuid] [@version] ... + + opts: --major | --minor | --patch | --fixed + +Update the indicated package within the constraints of the indicated version +specifications. Versions may be specified by `@1`, `@1.2`, `@1.2.3`, allowing +any version with a prefix that matches, or ranges thereof, such as `@1.2-3.4.5`. +In `--project` mode, package specifications only match project packages, while +in `manifest` mode they match any manifest package. Bound level options force +the following packages to be upgraded only within the current major, minor, +patch version; if the `--fixed` upgrade level is given, then the following +packages will not be upgraded at all. + """, +),( CMD_GENERATE, + ["generate"], + do_generate!, + (ARG_RAW, [1]), + [], + md""" + + generate pkgname + +Create a project called `pkgname` in the current folder. + """, +),( CMD_PRECOMPILE, + ["precompile"], + do_precompile!, + (ARG_RAW, [0]), + [], + md""" + precompile + +Precompile all the dependencies of the project by running `import` on all of them in a new process. +The `startup.jl` file is disabled during precompilation unless julia is started with `--startup-file=yes`. + """, +),( CMD_STATUS, + ["status", "st"], + do_status!, + (ARG_RAW, [0]), + [ + (["project", "p"], OPT_SWITCH, :mode => PKGMODE_PROJECT), + (["manifest", "m"], OPT_SWITCH, :mode => PKGMODE_MANIFEST), + ], + md""" + + status + status [-p|--project] + status [-m|--manifest] + +Show the status of the current environment. By default, the full contents of +the project file is summarized, showing what version each package is on and +how it has changed since the last git commit (if in a git repo), as well as +any changes to manifest packages not already listed. In `--project` mode, the +status of the project file is summarized. In `--manifest` mode the output also +includes the dependencies of explicitly added packages. + """, +),( CMD_GC, + ["gc"], + do_gc!, + (ARG_RAW, [0]), + [], + md""" + +Deletes packages that cannot be reached from any existing environment. + """, +),( CMD_PREVIEW, + ["preview"], + do_preview!, + (ARG_RAW, [1]), + [], + md""" + + preview cmd + +Runs the command `cmd` in preview mode. This is defined such that no side effects +will take place i.e. no packages are downloaded and neither the project nor manifest +is modified. + """, +), +], #package +] #command_declarations + +super_specs = SuperSpecs(command_declarations) # TODO should this go here ? +command_specs = super_specs["package"] +all_commands_sorted = sort(collect(String,keys(command_specs))) +long_commands = filter(c -> length(c) > 2, all_commands_sorted) +function all_options() + all_opts = [] + for command in values(command_specs) + for opt_spec in values(command.option_specs) + push!(all_opts, opt_spec.name) + opt_spec.short_name !== nothing && push!(all_opts, opt_spec.short_name) + end + end + unique!(all_opts) + return all_opts end +all_options_sorted = [length(opt) > 1 ? "--$opt" : "-$opt" for opt in sort!(all_options())] +long_options = filter(c -> length(c) > 2, all_options_sorted) + +const help = md""" + +**Welcome to the Pkg REPL-mode**. To return to the `julia>` prompt, either press +backspace when the input line is empty or press Ctrl+C. + + +**Synopsis** + + pkg> [--env=...] cmd [opts] [args] + +Multiple commands can be given on the same line by interleaving a `;` between the commands. + +**Environment** + +The `--env` meta option determines which project environment to manipulate. By +default, this looks for a git repo in the parents directories of the current +working directory, and if it finds one, it uses that as an environment. Otherwise, +it uses a named environment (typically found in `~/.julia/environments`) looking +for environments named `v$(VERSION.major).$(VERSION.minor).$(VERSION.patch)`, +`v$(VERSION.major).$(VERSION.minor)`, `v$(VERSION.major)` or `default` in order. + +**Commands** + +What action you want the package manager to take: + +`help`: show this message + +`status`: summarize contents of and changes to environment + +`add`: add packages to project + +`develop`: clone the full package repo locally for development + +`rm`: remove packages from project or manifest + +`up`: update packages in manifest + +`test`: run tests for packages + +`build`: run the build script for packages + +`pin`: pins the version of packages + +`free`: undoes a `pin`, `develop`, or stops tracking a repo. + +`instantiate`: downloads all the dependencies for the project + +`resolve`: resolves to update the manifest from changes in dependencies of +developed packages + +`generate`: generate files for a new project + +`preview`: previews a subsequent command without affecting the current state + +`precompile`: precompile all the project dependencies + +`gc`: garbage collect packages not used for a significant time + +`activate`: set the primary environment the package manager manipulates +""" + +end #module diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 2530a4ed5709a..34e7ad9f75918 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -72,23 +72,27 @@ temp_pkg_dir() do project_path end @testset "tokens" begin - tokens = Pkg.REPLMode.tokenize("add git@github.com:JuliaLang/Example.jl.git") - @test tokens[1][2] == "git@github.com:JuliaLang/Example.jl.git" - tokens = Pkg.REPLMode.tokenize("add git@github.com:JuliaLang/Example.jl.git#master") - @test tokens[1][2] == "git@github.com:JuliaLang/Example.jl.git" - @test tokens[1][3].rev == "master" - tokens = Pkg.REPLMode.tokenize("add git@github.com:JuliaLang/Example.jl.git#c37b675") - @test tokens[1][2] == "git@github.com:JuliaLang/Example.jl.git" - @test tokens[1][3].rev == "c37b675" - tokens = Pkg.REPLMode.tokenize("add git@github.com:JuliaLang/Example.jl.git@v0.5.0") - @test tokens[1][2] == "git@github.com:JuliaLang/Example.jl.git" - @test repr(tokens[1][3]) == "VersionRange(\"0.5.0\")" - tokens = Pkg.REPLMode.tokenize("add git@github.com:JuliaLang/Example.jl.git@0.5.0") - @test tokens[1][2] == "git@github.com:JuliaLang/Example.jl.git" - @test repr(tokens[1][3]) == "VersionRange(\"0.5.0\")" - tokens = Pkg.REPLMode.tokenize("add git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git@0.5.0") - @test tokens[1][2] == "git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git" - @test repr(tokens[1][3]) == "VersionRange(\"0.5.0\")" + statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git")[1] + @test "add" in statement.command.names + @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" + statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git#master")[1] + @test "add" in statement.command.names + @test length(statement.arguments) == 2 + @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" + @test statement.arguments[2] == "#master" + statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git#c37b675")[1] + @test "add" in statement.command.names + @test length(statement.arguments) == 2 + @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" + @test statement.arguments[2] == "#c37b675" + statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git@v0.5.0")[1] + @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" + @test statement.arguments[2] == "@v0.5.0" + statement = Pkg.REPLMode.parse("add git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git@0.5.0")[1] + @test "add" in statement.command.names + @test length(statement.arguments) == 2 + @test statement.arguments[1] == "git@gitlab-fsl.jsc.näsan.guvv:drats/URGA2010.jl.git" + @test statement.arguments[2] == "@0.5.0" end temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path @@ -566,10 +570,301 @@ end @testset "`do_generate!` error paths" begin with_temp_env() do - @test_throws CommandError Pkg.REPLMode.pkgstr("generate @0.0.0") @test_throws CommandError Pkg.REPLMode.pkgstr("generate Example Example2") @test_throws CommandError Pkg.REPLMode.pkgstr("generate") end end +@testset "`parse_option` unit tests" begin + opt = Pkg.REPLMode.parse_option("-x") + @test opt.val == "x" + @test opt.argument === nothing + opt = Pkg.REPLMode.parse_option("--hello") + @test opt.val == "hello" + @test opt.argument === nothing + opt = Pkg.REPLMode.parse_option("--env=some") + @test opt.val == "env" + @test opt.argument == "some" +end + +@testset "`parse` integration tests" begin + @test isempty(Pkg.REPLMode.parse("")) + + statement = Pkg.REPLMode.parse("up")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_UP + @test isempty(statement.meta_options) + @test isempty(statement.options) + @test isempty(statement.arguments) + + statement = Pkg.REPLMode.parse("dev Example")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_DEVELOP + @test isempty(statement.meta_options) + @test isempty(statement.options) + @test statement.arguments == ["Example"] + + statement = Pkg.REPLMode.parse("dev Example#foo #bar")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_DEVELOP + @test isempty(statement.meta_options) + @test isempty(statement.options) + @test statement.arguments == ["Example", "#foo", "#bar"] + + statement = Pkg.REPLMode.parse("dev Example#foo Example@v0.0.1")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_DEVELOP + @test isempty(statement.meta_options) + @test isempty(statement.options) + @test statement.arguments == ["Example", "#foo", "Example", "@v0.0.1"] + + statement = Pkg.REPLMode.parse("--one -t add --first --second arg1")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_ADD + @test statement.meta_options == ["--one", "-t"] + @test statement.options == ["--first", "--second"] + @test statement.arguments == ["arg1"] + + statements = Pkg.REPLMode.parse("--one -t add --first -o arg1; --meta pin -x -a arg0 Example") + @test statements[1].command.kind == Pkg.REPLMode.CMD_ADD + @test statements[1].meta_options == ["--one", "-t"] + @test statements[1].options == ["--first", "-o"] + @test statements[1].arguments == ["arg1"] + @test statements[2].command.kind == Pkg.REPLMode.CMD_PIN + @test statements[2].meta_options == ["--meta"] + @test statements[2].options == ["-x", "-a"] + @test statements[2].arguments == ["arg0", "Example"] + + statements = Pkg.REPLMode.parse("up; --meta -x pin --first; dev") + @test statements[1].command.kind == Pkg.REPLMode.CMD_UP + @test isempty(statements[1].meta_options) + @test isempty(statements[1].options) + @test isempty(statements[1].arguments) + @test statements[2].command.kind == Pkg.REPLMode.CMD_PIN + @test statements[2].meta_options == ["--meta", "-x"] + @test statements[2].options == ["--first"] + @test isempty(statements[2].arguments) + @test statements[3].command.kind == Pkg.REPLMode.CMD_DEVELOP + @test isempty(statements[3].meta_options) + @test isempty(statements[3].options) + @test isempty(statements[3].arguments) +end + +@testset "argument count errors" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("activate one two") + @test_throws CommandError Pkg.REPLMode.pkgstr("activate one two three") + @test_throws CommandError Pkg.REPLMode.pkgstr("precompile Example") + end + end + end +end + +@testset "invalid options" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("rm --minor Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("pin --project Example") + end + end + end +end + +@testset "Argument order" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("add FooBar Example#foobar#foobar") + @test_throws CommandError Pkg.REPLMode.pkgstr("up Example#foobar@0.0.0") + @test_throws CommandError Pkg.REPLMode.pkgstr("pin Example@0.0.0@0.0.1") + @test_throws CommandError Pkg.REPLMode.pkgstr("up #foobar") + @test_throws CommandError Pkg.REPLMode.pkgstr("add @0.0.1") + end + end + end +end + +@testset "conflicting options" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("up --major --minor") + @test_throws CommandError Pkg.REPLMode.pkgstr("rm --project --manifest") + end + end + end +end + +@testset "gc" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("gc --project") + @test_throws CommandError Pkg.REPLMode.pkgstr("gc --minor") + @test_throws CommandError Pkg.REPLMode.pkgstr("gc Example") + Pkg.REPLMode.pkgstr("gc") + end + end + end +end + +@testset "precompile" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("precompile --project") + @test_throws CommandError Pkg.REPLMode.pkgstr("precompile Example") + Pkg.REPLMode.pkgstr("precompile") + end + end + end +end + +@testset "generate" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("generate --major Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("generate --foobar Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("generate Example1 Example2") + Pkg.REPLMode.pkgstr("generate Example") + end + end + end +end + +@testset "test" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + Pkg.add("Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("test --project Example") + Pkg.REPLMode.pkgstr("test --coverage Example") + Pkg.REPLMode.pkgstr("test Example") + end + end + end +end + +@testset "build" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("build --project") + @test_throws CommandError Pkg.REPLMode.pkgstr("build --minor") + end + end + end +end + +@testset "free" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError Pkg.REPLMode.pkgstr("free --project") + @test_throws CommandError Pkg.REPLMode.pkgstr("free --major") + end + end + end +end + +@testset "unit tests for `group_words`" begin + # simple + groups = Pkg.REPLMode.group_words(["add", "Example"]) + @test length(groups) == 1 + @test groups[1][1] == "add" + @test groups[1][2] == "Example" + # statement break + groups = Pkg.REPLMode.group_words(["a", "b", "c", ";", "a", "b"]) + @test length(groups) == 2 + groups = Pkg.REPLMode.group_words(["a", "b", "c", ";", "a", "b", ";", "d"]) + @test length(groups) == 3 + # trailing statement break + groups = Pkg.REPLMode.group_words(["a", "b", "c", ";", "a", "b", ";"]) + @test length(groups) == 2 + # errors + @test_throws CommandError Pkg.REPLMode.group_words(["a", "b", ";", ";", "a", "b"]) + @test_throws CommandError Pkg.REPLMode.group_words([";", "add", "Example"]) +end + +@testset "tests for api opts" begin + specs = Pkg.REPLMode.OptionSpecs(Pkg.REPLMode.OptionDeclaration[ + (["project", "p"], Pkg.REPLMode.OPT_SWITCH, :mode => Pkg.Types.PKGMODE_PROJECT), + (["manifest", "m"], Pkg.REPLMode.OPT_SWITCH, :mode => Pkg.Types.PKGMODE_MANIFEST), + ("major", Pkg.REPLMode.OPT_SWITCH, :level => Pkg.Types.UPLEVEL_MAJOR), + ("minor", Pkg.REPLMode.OPT_SWITCH, :level => Pkg.Types.UPLEVEL_MINOR), + ("patch", Pkg.REPLMode.OPT_SWITCH, :level => Pkg.Types.UPLEVEL_PATCH), + ("fixed", Pkg.REPLMode.OPT_SWITCH, :level => Pkg.Types.UPLEVEL_FIXED), + ("rawnum", Pkg.REPLMode.OPT_ARG, :num => nothing), + ("plus", Pkg.REPLMode.OPT_ARG, :num => x->parse(Int,x)+1), + ]) + + api_opts = Pkg.REPLMode.APIOptions([ + Pkg.REPLMode.Option("manifest"), + Pkg.REPLMode.Option("patch"), + Pkg.REPLMode.Option("rawnum", "5"), + ], specs) + + @test Pkg.REPLMode.key_api(:foo, api_opts) === nothing + @test Pkg.REPLMode.key_api(:mode, api_opts) == Pkg.Types.PKGMODE_MANIFEST + @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH + @test Pkg.REPLMode.key_api(:num, api_opts) == "5" + + api_opts = Pkg.REPLMode.APIOptions([ + Pkg.REPLMode.Option("project"), + Pkg.REPLMode.Option("patch"), + Pkg.REPLMode.Option("plus", "5"), + ], specs) + + @test Pkg.REPLMode.key_api(:mode, api_opts) == Pkg.Types.PKGMODE_PROJECT + @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH + @test Pkg.REPLMode.key_api(:num, api_opts) == 6 + + @test Pkg.REPLMode.key_api(:foo, api_opts) === nothing + Pkg.REPLMode.set_default!(:foo => "bar", api_opts) + @test Pkg.REPLMode.key_api(:foo, api_opts) == "bar" + Pkg.REPLMode.set_default!(:level => "bar", api_opts) + @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH +end + +@testset "meta option errors" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + # unregistered meta options + @test_throws CommandError Pkg.REPLMode.pkgstr("--foo=foo add Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("--bar add Example") + @test_throws CommandError Pkg.REPLMode.pkgstr("-x add Example") + # malformed, but registered meta option + @test_throws CommandError Pkg.REPLMode.pkgstr("--env Example") + end + end + end +end + +@testset "activate" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + mkdir("Foo") + pkg"activate" + default = Base.active_project() + pkg"activate Foo" + @test Base.active_project() == joinpath(pwd(), "Foo", "Project.toml") + pkg"activate" + @test Base.active_project() == default + end + end + end +end + +@testset "subcommands" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do + Pkg.REPLMode.pkg"package add Example" + @test isinstalled(TEST_PKG) + Pkg.REPLMode.pkg"package rm Example" + @test !isinstalled(TEST_PKG) + end + end + end +end + +@testset "`parse_quotes` unit tests" begin + qwords = Pkg.REPLMode.parse_quotes("\"Don't\" forget to '\"test\"'") + @test qwords[1].isquoted + @test qwords[1].word == "Don't" + @test !qwords[2].isquoted + @test qwords[2].word == "forget" + @test !qwords[3].isquoted + @test qwords[3].word == "to" + @test qwords[4].isquoted + @test qwords[4].word == "\"test\"" + @test_throws CommandError Pkg.REPLMode.parse_quotes("Don't") + @test_throws CommandError Pkg.REPLMode.parse_quotes("Unterminated \"quot") +end + +@testset "argument kinds" begin + temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; + @test_throws CommandError pkg"pin Example#foo" + @test_throws CommandError pkg"test Example#foo" + @test_throws CommandError pkg"test Example@v0.0.1" + end + end + end +end + end # module From e9e320b3fb59868425388ecbb51e9a42a5afff77 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 1 Aug 2018 00:31:21 +0200 Subject: [PATCH 02/22] Make `Pkg.activate(path)` behave like `pkg> activate path`. (#543) --- stdlib/Pkg/src/API.jl | 21 ++++++++++++++++++++ stdlib/Pkg/src/REPLMode.jl | 23 +++------------------- stdlib/Pkg/test/api.jl | 39 ++++++++++++++++++++++++++++++++++++++ stdlib/Pkg/test/pkg.jl | 1 + stdlib/Pkg/test/repl.jl | 2 ++ 5 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 stdlib/Pkg/test/api.jl diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index dc659e3959408..010d9047dec17 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -548,7 +548,28 @@ function status(ctx::Context, mode=PKGMODE_PROJECT) end function activate(path::Union{String,Nothing}=nothing) + if path !== nothing + devpath = nothing + env = Base.active_project() === nothing ? nothing : EnvCache() + if env !== nothing && haskey(env.project["deps"], path) + uuid = UUID(env.project["deps"][path]) + info = manifest_info(env, uuid) + devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing + end + # `pkg> activate path`/`Pkg.activate(path)` does the following + # 1. if path exists, activate that + # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) + # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) + if Types.isdir_windows_workaround(path) + path = abspath(path) + elseif devpath !== nothing + path = abspath(devpath) + else + path = abspath(path) + end + end Base.ACTIVE_PROJECT[] = Base.load_path_expand(path) + return end """ diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index c38749b968b14..13a173ffe774b 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -612,28 +612,11 @@ do_up!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = API.up(ctx, args; api_opts...) function do_activate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) + # TODO: Remove the ctx argument to this function. if isempty(args) - return API.activate() - end - - path = args[1] - env = Base.active_project() === nothing ? nothing : ctx.env - devpath = nothing - if env !== nothing && haskey(env.project["deps"], path) - uuid = UUID(env.project["deps"][path]) - info = manifest_info(env, uuid) - devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing - end - # `pkg> activate path` does the following - # 1. if path exists, activate that - # 2. if path exists in deps, and the dep is deved, activate that path (`devpath`) above - # 3. activate the non-existing directory (e.g. as in `pkg> activate . for initing a new dev`) - if Types.isdir_windows_workaround(path) - API.activate(abspath(path)) - elseif devpath !== nothing - API.activate(abspath(devpath)) + return API.activate(nothing) else - API.activate(abspath(path)) + return API.activate(args[1]) end end diff --git a/stdlib/Pkg/test/api.jl b/stdlib/Pkg/test/api.jl new file mode 100644 index 0000000000000..edbc15f186754 --- /dev/null +++ b/stdlib/Pkg/test/api.jl @@ -0,0 +1,39 @@ +module APITests + +using Pkg, Test + +@testset "Pkg.activate" begin + cd(mktempdir()) do + path = pwd() + Pkg.activate(".") + mkdir("Foo") + cd(mkdir("modules")) do + Pkg.generate("Foo") + end + Pkg.develop(Pkg.Types.PackageSpec(url="modules/Foo")) # to avoid issue #542 + Pkg.activate("Foo") # activate path Foo over deps Foo + @test Base.active_project() == joinpath(path, "Foo", "Project.toml") + Pkg.activate(".") + rm("Foo"; force=true, recursive=true) + Pkg.activate("Foo") # activate path from developed Foo + @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + Pkg.activate(".") + Pkg.activate("./Foo") # activate empty directory Foo (sidestep the developed Foo) + @test Base.active_project() == joinpath(path, "Foo", "Project.toml") + Pkg.activate(".") + Pkg.activate("Bar") # activate empty directory Bar + @test Base.active_project() == joinpath(path, "Bar", "Project.toml") + Pkg.activate(".") + Pkg.add("Example") # non-deved deps should not be activated + Pkg.activate("Example") + @test Base.active_project() == joinpath(path, "Example", "Project.toml") + Pkg.activate(".") + cd(mkdir("tests")) + Pkg.activate("Foo") # activate developed Foo from another directory + @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + Pkg.activate() # activate home project + @test Base.ACTIVE_PROJECT[] === nothing + end +end + +end # module APITests diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index ae9a706aefbd3..6538a4bba0d88 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -436,5 +436,6 @@ temp_pkg_dir() do project_path end include("repl.jl") +include("api.jl") end # module diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 34e7ad9f75918..5714dc7a9fd17 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -282,6 +282,8 @@ temp_pkg_dir() do project_path cd(mkdir("tests")) pkg"activate Foo" # activate developed Foo from another directory @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + pkg"activate" # activate home project + @test Base.ACTIVE_PROJECT[] === nothing end end From 5b6fbb0d898a99c62b9df9285f977f2bae3383dc Mon Sep 17 00:00:00 2001 From: David Varela Date: Wed, 1 Aug 2018 01:15:32 -0700 Subject: [PATCH 03/22] Refactor some REPL issues (#552) * Refactor: APIOptions should be a dictionary * Fix `do_activate!` interface * Update tests: APIOptions is a dictionary * Allow more flexibility for REPL `do_<>` functions --- stdlib/Pkg/src/REPLMode.jl | 117 +++++++++++++++++-------------------- stdlib/Pkg/src/Types.jl | 8 +++ stdlib/Pkg/test/repl.jl | 20 +++---- 3 files changed, 68 insertions(+), 77 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 13a173ffe774b..443f7f2a3017b 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -19,7 +19,6 @@ end ########### # Options # ########### -#TODO should this opt be removed: ("name", :cmd, :temp => false) struct OptionSpec name::String short_name::Union{Nothing,String} @@ -101,7 +100,7 @@ struct ArgSpec end const CommandDeclaration = Tuple{CommandKind, Vector{String}, # names - Function, # handler + Union{Nothing,Function}, # handler Tuple{ArgClass, Vector{Int}}, # argument count Vector{OptionDeclaration}, # options Union{Nothing, Markdown.MD}, #help @@ -109,7 +108,7 @@ const CommandDeclaration = Tuple{CommandKind, struct CommandSpec kind::CommandKind names::Vector{String} - handler::Function + handler::Union{Nothing,Function} argument_spec::ArgSpec # note: just use range operator for max/min option_specs::Dict{String, OptionSpec} help::Union{Nothing, Markdown.MD} @@ -311,7 +310,6 @@ end ############## const Token = Union{String, VersionRange, Rev} const PkgArguments = Union{Vector{String}, Vector{PackageSpec}} -#TODO embed spec in PkgCommand? struct PkgCommand meta_options::Vector{Option} spec::CommandSpec @@ -321,14 +319,14 @@ struct PkgCommand PkgCommand(meta_opts, cmd_name, opts, args) = new(meta_opts, cmd_name, opts, args) end -const APIOption = Pair{Symbol, Any} -APIOptions(command::PkgCommand)::Vector{APIOption} = +const APIOptions = Dict{Symbol, Any} +APIOptions(command::PkgCommand)::Dict{Symbol, Any} = APIOptions(command.options, command.spec.option_specs) function APIOptions(options::Vector{Option}, specs::Dict{String, OptionSpec}, - )::Vector{APIOption} - return map(options) do opt + )::Dict{Symbol, Any} + keyword_vec = map(options) do opt spec = specs[opt.val] # opt is switch spec.is_switch && return spec.api @@ -337,18 +335,9 @@ function APIOptions(options::Vector{Option}, # given opt wrapper return spec.api.first => spec.api.second(opt.argument) end + return Dict(keyword_vec) end -function key_api(key::Symbol, api_opts::Vector{APIOption}) - index = findfirst(x->x.first == key, api_opts) - if index !== nothing - return api_opts[index].second - end -end - -set_default!(opt, api_opts::Vector{APIOption}) = - key_api(opt.first, api_opts) === nothing && push!(api_opts, opt) - function enforce_argument_order(args::Vector{Token}) prev_arg = nothing function check_prev_arg(valid_type::DataType, error_message::AbstractString) @@ -496,6 +485,8 @@ function PkgCommand(statement::Statement)::PkgCommand return PkgCommand(meta_opts, statement.command, opts, args) end +Context!(ctx::APIOptions)::Context = Types.Context!(collect(ctx)) + ############# # Execution # ############# @@ -519,15 +510,14 @@ function do_cmd(repl::REPL.AbstractREPL, input::String; do_rethrow=false) end function do_cmd!(command::PkgCommand, repl) - meta_opts = APIOptions(command.meta_options, meta_option_specs) - ctx = Context(meta_opts...) + context = APIOptions(command.meta_options, meta_option_specs) spec = command.spec # REPL specific commands if spec.kind == CMD_HELP - return Base.invokelatest(do_help!, ctx, command, repl) + return Base.invokelatest(do_help!, command, repl) elseif spec.kind == CMD_PREVIEW - ctx.preview = true + context[:preview] = true cmd = command.arguments[1] cmd_spec = get(command_specs, cmd, nothing) cmd_spec === nothing && @@ -538,10 +528,15 @@ function do_cmd!(command::PkgCommand, repl) # API commands # TODO is invokelatest still needed? - Base.invokelatest(spec.handler, ctx, command.arguments, APIOptions(command)) + api_opts = APIOptions(command) + if applicable(spec.handler, context, command.arguments, api_opts) + Base.invokelatest(spec.handler, context, command.arguments, api_opts) + else + Base.invokelatest(spec.handler, command.arguments, api_opts) + end end -function do_help!(ctk::Context, command::PkgCommand, repl::REPL.AbstractREPL) +function do_help!(command::PkgCommand, repl::REPL.AbstractREPL) disp = REPL.REPLDisplay(repl) if isempty(command.arguments) Base.display(disp, help) @@ -562,21 +557,16 @@ function do_help!(ctk::Context, command::PkgCommand, repl::REPL.AbstractREPL) end # TODO set default Display.status keyword: mode = PKGMODE_COMBINED -function do_status!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) - set_default!(:mode => PKGMODE_COMBINED, api_opts) - Display.status(ctx, key_api(:mode, api_opts)) -end - -# TODO remove the need to specify a handler function (not needed for REPL commands) -do_preview!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = nothing +do_status!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + Display.status(Context!(ctx), get(api_opts, :mode, PKGMODE_COMBINED)) # TODO , test recursive dependencies as on option. -function do_test!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) +function do_test!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) foreach(arg -> arg.mode = PKGMODE_MANIFEST, args) - API.test(ctx, args; api_opts...) + API.test(Context!(ctx), args; collect(api_opts)...) end -function do_registry_add!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) +function do_registry_add!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) println("This is a dummy function for now") println("My args are:") for arg in args @@ -584,35 +574,34 @@ function do_registry_add!(ctx::Context, args::PkgArguments, api_opts::Vector{API end end -do_precompile!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.precompile(ctx) +do_precompile!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.precompile(Context!(ctx)) -do_resolve!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.resolve(ctx) +do_resolve!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.resolve(Context!(ctx)) -do_gc!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.gc(ctx; api_opts...) +do_gc!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.gc(Context!(ctx); collect(api_opts)...) -do_instantiate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.instantiate(ctx; api_opts...) +do_instantiate!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.instantiate(Context!(ctx); collect(api_opts)...) -do_generate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.generate(ctx, args[1]) +do_generate!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.generate(Context!(ctx), args[1]) -do_build!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.build(ctx, args; api_opts...) +do_build!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.build(Context!(ctx), args; collect(api_opts)...) -do_rm!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.rm(ctx, args; api_opts...) +do_rm!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.rm(Context!(ctx), args; collect(api_opts)...) -do_free!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.free(ctx, args; api_opts...) +do_free!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.free(Context!(ctx), args; collect(api_opts)...) -do_up!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) = - API.up(ctx, args; api_opts...) +do_up!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = + API.up(Context!(ctx), args; collect(api_opts)...) -function do_activate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) - # TODO: Remove the ctx argument to this function. +function do_activate!(args::PkgArguments, api_opts::APIOptions) if isempty(args) return API.activate(nothing) else @@ -620,24 +609,24 @@ function do_activate!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOpti end end -function do_pin!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) +function do_pin!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) for arg in args # TODO not sure this is correct if arg.version.ranges[1].lower != arg.version.ranges[1].upper cmderror("pinning a package requires a single version, not a versionrange") end end - API.pin(ctx, args; api_opts...) + API.pin(Context!(ctx), args; collect(api_opts)...) end -function do_add!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) - push!(api_opts, :mode => :add) - API.add_or_develop(ctx, args; api_opts...) +function do_add!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) + api_opts[:mode] = :add + API.add_or_develop(Context!(ctx), args; collect(api_opts)...) end -function do_develop!(ctx::Context, args::PkgArguments, api_opts::Vector{APIOption}) - push!(api_opts, :mode => :develop) - API.add_or_develop(ctx, args; api_opts...) +function do_develop!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) + api_opts[:mode] = :develop + API.add_or_develop(Context!(ctx), args; collect(api_opts)...) end ###################### @@ -950,7 +939,7 @@ julia is started with `--startup-file=yes`. """, ),( CMD_HELP, ["help", "?"], - do_help!, + nothing, (ARG_RAW, []), [], md""" @@ -1201,7 +1190,7 @@ Deletes packages that cannot be reached from any existing environment. """, ),( CMD_PREVIEW, ["preview"], - do_preview!, + nothing, (ARG_RAW, [1]), [], md""" diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 0a247849650d7..a17d660f7b6cb 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -358,6 +358,14 @@ Base.@kwdef mutable struct Context old_pkg2_clone_name::String = "" end +function Context!(kw_context::Vector{Pair{Symbol,Any}})::Context + ctx = Context() + for (k, v) in kw_context + setfield!(ctx, k, v) + end + return ctx +end + function Context!(ctx::Context; kwargs...) for (k, v) in kwargs setfield!(ctx, k, v) diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 5714dc7a9fd17..9486804e9f97c 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -785,10 +785,10 @@ end Pkg.REPLMode.Option("rawnum", "5"), ], specs) - @test Pkg.REPLMode.key_api(:foo, api_opts) === nothing - @test Pkg.REPLMode.key_api(:mode, api_opts) == Pkg.Types.PKGMODE_MANIFEST - @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH - @test Pkg.REPLMode.key_api(:num, api_opts) == "5" + @test get(api_opts,:foo,nothing) === nothing + @test get(api_opts,:mode,nothing) == Pkg.Types.PKGMODE_MANIFEST + @test get(api_opts,:level,nothing) == Pkg.Types.UPLEVEL_PATCH + @test get(api_opts,:num,nothing) == "5" api_opts = Pkg.REPLMode.APIOptions([ Pkg.REPLMode.Option("project"), @@ -796,15 +796,9 @@ end Pkg.REPLMode.Option("plus", "5"), ], specs) - @test Pkg.REPLMode.key_api(:mode, api_opts) == Pkg.Types.PKGMODE_PROJECT - @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH - @test Pkg.REPLMode.key_api(:num, api_opts) == 6 - - @test Pkg.REPLMode.key_api(:foo, api_opts) === nothing - Pkg.REPLMode.set_default!(:foo => "bar", api_opts) - @test Pkg.REPLMode.key_api(:foo, api_opts) == "bar" - Pkg.REPLMode.set_default!(:level => "bar", api_opts) - @test Pkg.REPLMode.key_api(:level, api_opts) == Pkg.Types.UPLEVEL_PATCH + @test get(api_opts,:mode,nothing) == Pkg.Types.PKGMODE_PROJECT + @test get(api_opts,:level,nothing) == Pkg.Types.UPLEVEL_PATCH + @test get(api_opts,:num,nothing) == 6 end @testset "meta option errors" begin From 85d2a7e3b5b3e74be4af4cb580bb9928a7348e7e Mon Sep 17 00:00:00 2001 From: David Varela Date: Wed, 1 Aug 2018 23:47:16 -0700 Subject: [PATCH 04/22] Fix `instantiate` error message (#560) --- stdlib/Pkg/src/API.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 010d9047dec17..e2cd8fb3f60ba 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -505,7 +505,7 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, kwarg return end if !isfile(ctx.env.manifest_file) && manifest == true - cmderror("manifest at $(ctx.env.manifest) does not exist") + cmderror("manifest at $(ctx.env.manifest_file) does not exist") end update_registry(ctx) urls = Dict{} From 0ecaf2d7ad203ab2cfed5ffc657f0404a9dcd021 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 2 Aug 2018 10:08:13 +0200 Subject: [PATCH 05/22] Replace depots()[1] with depots1() where depots1 throws (#563) a more descriptive error, instead of a BoundsError, in the case where DEPOT_PATH is empty. --- stdlib/Pkg/src/Operations.jl | 6 +++--- stdlib/Pkg/src/Pkg.jl | 10 ++++++++-- stdlib/Pkg/src/Types.jl | 8 ++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index 547cebdc75842..c59ba70827507 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -9,7 +9,7 @@ import LibGit2 import REPL using REPL.TerminalMenus using ..Types, ..GraphType, ..Resolve, ..Pkg2, ..BinaryProvider, ..GitTools, ..Display -import ..depots, ..devdir, ..Types.uuid_julia +import ..depots, ..depots1, ..devdir, ..Types.uuid_julia function find_installed(name::String, uuid::UUID, sha1::SHA1) slug_default = Base.version_slug(uuid, sha1) @@ -20,7 +20,7 @@ function find_installed(name::String, uuid::UUID, sha1::SHA1) ispath(path) && return path end end - return abspath(depots()[1], "packages", name, slug_default) + return abspath(depots1(), "packages", name, slug_default) end function load_versions(path::String) @@ -480,7 +480,7 @@ function install_git( tree = nothing try repo, git_hash = Base.shred!(LibGit2.CachedCredentials()) do creds - clones_dir = joinpath(depots()[1], "clones") + clones_dir = joinpath(depots1(), "clones") ispath(clones_dir) || mkpath(clones_dir) repo_path = joinpath(clones_dir, string(uuid)) repo = ispath(repo_path) ? LibGit2.GitRepo(repo_path) : begin diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 3efe4bc1b4619..fabbcf54698a0 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -12,8 +12,14 @@ export PackageMode, PKGMODE_MANIFEST, PKGMODE_PROJECT export UpgradeLevel, UPLEVEL_MAJOR, UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH depots() = Base.DEPOT_PATH -logdir() = joinpath(depots()[1], "logs") -devdir() = get(ENV, "JULIA_PKG_DEVDIR", joinpath(depots()[1], "dev")) +function depots1() + d = depots() + isempty(d) && cmderror("no depots found in DEPOT_PATH") + return d[1] +end + +logdir() = joinpath(depots1(), "logs") +devdir() = get(ENV, "JULIA_PKG_DEVDIR", joinpath(depots1(), "dev")) const UPDATED_REGISTRY_THIS_SESSION = Ref(false) # load snapshotted dependencies diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index a17d660f7b6cb..c47b4d9005b9d 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -11,7 +11,7 @@ using REPL.TerminalMenus using ..TOML import ..Pkg, ..UPDATED_REGISTRY_THIS_SESSION -import Pkg: GitTools, depots, logdir +import Pkg: GitTools, depots, depots1, logdir import Base: SHA1 using SHA @@ -519,7 +519,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, # We save the repo in case another environement wants to # develop from the same repo, this avoids having to reclone it # from scratch. - clone_path = joinpath(depots()[1], "clones") + clone_path = joinpath(depots1(), "clones") mkpath(clone_path) repo_path = joinpath(clone_path, string(hash(pkg.repo.url), "_full")) repo = nothing @@ -595,7 +595,7 @@ function handle_repos_add!(ctx::Context, pkgs::AbstractVector{PackageSpec}; upgr pkg.repo == nothing && continue pkg.special_action = PKGSPEC_REPO_ADDED isempty(pkg.repo.url) && set_repo_for_pkg!(env, pkg) - clones_dir = joinpath(depots()[1], "clones") + clones_dir = joinpath(depots1(), "clones") mkpath(clones_dir) repo_path = joinpath(clones_dir, string(hash(pkg.repo.url))) repo = nothing @@ -895,7 +895,7 @@ end # Return paths of all registries in all depots function registries(; clone_default=true)::Vector{String} isempty(depots()) && return String[] - user_regs = abspath(depots()[1], "registries") + user_regs = abspath(depots1(), "registries") # TODO: delete the following let block in Julia 1.0 let uncurated = joinpath(user_regs, "Uncurated"), general = joinpath(user_regs, "General") From fcb1e4f1111a9031eb019add6b1c12ec271d70a9 Mon Sep 17 00:00:00 2001 From: David Varela Date: Thu, 2 Aug 2018 02:34:44 -0700 Subject: [PATCH 06/22] Refactor `activate` to avoid complexity in the main method (#559) --- stdlib/Pkg/src/API.jl | 40 ++++++++++++++++++-------------------- stdlib/Pkg/src/REPLMode.jl | 2 +- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index e2cd8fb3f60ba..89f1002134e34 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -547,29 +547,27 @@ function status(ctx::Context, mode=PKGMODE_PROJECT) return end -function activate(path::Union{String,Nothing}=nothing) - if path !== nothing - devpath = nothing - env = Base.active_project() === nothing ? nothing : EnvCache() - if env !== nothing && haskey(env.project["deps"], path) - uuid = UUID(env.project["deps"][path]) - info = manifest_info(env, uuid) - devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing - end - # `pkg> activate path`/`Pkg.activate(path)` does the following - # 1. if path exists, activate that - # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) - # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) - if Types.isdir_windows_workaround(path) - path = abspath(path) - elseif devpath !== nothing - path = abspath(devpath) - else - path = abspath(path) - end +activate() = (Base.ACTIVE_PROJECT[] = Base.load_path_expand(nothing)) +function activate(path::String) + devpath = nothing + env = Base.active_project() === nothing ? nothing : EnvCache() + if env !== nothing && haskey(env.project["deps"], path) + uuid = UUID(env.project["deps"][path]) + info = manifest_info(env, uuid) + devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing + end + # `pkg> activate path`/`Pkg.activate(path)` does the following + # 1. if path exists, activate that + # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) + # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) + if Types.isdir_windows_workaround(path) + path = abspath(path) + elseif devpath !== nothing + path = abspath(devpath) + else + path = abspath(path) end Base.ACTIVE_PROJECT[] = Base.load_path_expand(path) - return end """ diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 443f7f2a3017b..6510d4bf66f95 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -603,7 +603,7 @@ do_up!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) = function do_activate!(args::PkgArguments, api_opts::APIOptions) if isempty(args) - return API.activate(nothing) + return API.activate() else return API.activate(args[1]) end From 484deaf85a8f43fc69d6c12e6dd095a9f1c7af2d Mon Sep 17 00:00:00 2001 From: Christof Stocker Date: Thu, 2 Aug 2018 11:48:26 +0200 Subject: [PATCH 07/22] rename Uncurated to General (#564) --- stdlib/Pkg/bin/generate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Pkg/bin/generate.jl b/stdlib/Pkg/bin/generate.jl index cbbe0a1e447cc..3481698eaf884 100644 --- a/stdlib/Pkg/bin/generate.jl +++ b/stdlib/Pkg/bin/generate.jl @@ -11,7 +11,7 @@ write_toml(prefix, "Registry") do io println(io, "repo = ", repr(repo)) println(io, "\ndescription = \"\"\"") print(io, """ - Official uncurated Julia package registry where people can + Official general Julia package registry where people can register any package they want without too much debate about naming and without enforced standards on documentation or testing. We nevertheless encourage documentation, testing and From f4d04110c0ca93619cade4b043a4e9b62103eb53 Mon Sep 17 00:00:00 2001 From: David Varela Date: Thu, 2 Aug 2018 02:50:36 -0700 Subject: [PATCH 08/22] Fix parser (lexer) (#553) * Fix parser * Add test for REPL `?` help syntax --- stdlib/Pkg/src/REPLMode.jl | 24 ++++++++++++++---------- stdlib/Pkg/test/repl.jl | 12 +++++++----- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 6510d4bf66f95..358e10038b4fe 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -200,7 +200,7 @@ function parse(cmd::String)::Vector{Statement} # tokenize accoring to whitespace / quotes qwords = parse_quotes(cmd) # tokenzie unquoted tokens according to pkg REPL syntax - words::Vector{String} = collect(Iterators.flatten(map(qword2word, qwords))) + words = lex(qwords) # break up words according to ";"(doing this early makes subsequent processing easier) word_groups = group_words(words) # create statements @@ -210,7 +210,7 @@ end # vector of words -> structured statement # minimal checking is done in this phase -function Statement(words) +function Statement(words)::Statement is_option(word) = first(word) == '-' statement = Statement() @@ -257,10 +257,16 @@ end const lex_re = r"^[\?\./\+\-](?!\-) | ((git|ssh|http(s)?)|(git@[\w\-\.]+))(:(//)?)([\w\.@\:/\-~]+)(\.git)(/)? | [^@\#\s;]+\s*=\s*[^@\#\s;]+ | \#\s*[^@\#\s;]* | @\s*[^@\#\s;]* | [^@\#\s;]+|;"x -function qword2word(qword::QuotedWord) - return qword.isquoted ? [qword.word] : map(m->m.match, eachmatch(lex_re, " $(qword.word)")) - # ^ - # note: space before `$word` is necessary to keep using current `lex_re` +function lex(qwords::Vector{QuotedWord})::Vector{String} + words = String[] + for qword in qwords + if qword.isquoted + push!(words, qword.word) + else + append!(words, map(m->m.match, eachmatch(lex_re, qword.word))) + end + end + return words end function parse_quotes(cmd::String)::Vector{QuotedWord} @@ -279,18 +285,16 @@ function parse_quotes(cmd::String)::Vector{QuotedWord} if in_singlequote # raw char push!(token_in_progress, c) else # delimiter + in_doublequote ? push_token!(true) : push_token!(false) in_doublequote = !in_doublequote - push_token!(true) end elseif c == '\'' if in_doublequote # raw char push!(token_in_progress, c) else # delimiter + in_singlequote ? push_token!(true) : push_token!(false) in_singlequote = !in_singlequote - push_token!(true) end - elseif c == ' ' && !(in_doublequote || in_singlequote) - push_token!(false) else push!(token_in_progress, c) end diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 9486804e9f97c..6dc3e00fe7058 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -72,6 +72,10 @@ temp_pkg_dir() do project_path end @testset "tokens" begin + statement = Pkg.REPLMode.parse("?dev")[1] + @test statement.command.kind == Pkg.REPLMode.CMD_HELP + @test length(statement.arguments) == 1 + @test statement.arguments[1] == "dev" statement = Pkg.REPLMode.parse("add git@github.com:JuliaLang/Example.jl.git")[1] @test "add" in statement.command.names @test statement.arguments[1] == "git@github.com:JuliaLang/Example.jl.git" @@ -844,11 +848,9 @@ end @test qwords[1].isquoted @test qwords[1].word == "Don't" @test !qwords[2].isquoted - @test qwords[2].word == "forget" - @test !qwords[3].isquoted - @test qwords[3].word == "to" - @test qwords[4].isquoted - @test qwords[4].word == "\"test\"" + @test qwords[2].word == " forget to " + @test qwords[3].isquoted + @test qwords[3].word == "\"test\"" @test_throws CommandError Pkg.REPLMode.parse_quotes("Don't") @test_throws CommandError Pkg.REPLMode.parse_quotes("Unterminated \"quot") end From 94eec9bde0ca3270d66b74eec8249bcd5390dd97 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 2 Aug 2018 13:55:38 +0200 Subject: [PATCH 09/22] Change devdir kwarg to shared in REPL mode, add the kwarg to the API (#565) --- stdlib/Pkg/src/API.jl | 9 ++++----- stdlib/Pkg/src/REPLMode.jl | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 89f1002134e34..9fa5450dc3e3d 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -28,11 +28,9 @@ add_or_develop(pkg::Union{String, PackageSpec}; kwargs...) = add_or_develop([pkg 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, devdir::Bool=false, kwargs...) +function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, shared::Bool=true, kwargs...) Context!(ctx; kwargs...) - devdir = devdir ? joinpath(dirname(ctx.env.project_file), "dev") : nothing - # 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()) @@ -45,7 +43,8 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, d ctx.preview && preview_info() if mode == :develop - new_git = handle_repos_develop!(ctx, pkgs, something(devdir, Pkg.devdir())) + devdir = shared ? Pkg.devdir() : joinpath(dirname(ctx.env.project_file), "dev") + new_git = handle_repos_develop!(ctx, pkgs, devdir) else new_git = handle_repos_add!(ctx, pkgs; upgrade_or_add=true) end @@ -63,7 +62,7 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, d end add(args...; kwargs...) = add_or_develop(args...; mode = :add, kwargs...) -develop(args...; kwargs...) = add_or_develop(args...; mode = :develop, kwargs...) +develop(args...; shared=true, kwargs...) = add_or_develop(args...; mode = :develop, shared = shared, kwargs...) rm(pkg::Union{String, PackageSpec}; kwargs...) = rm([pkg]; kwargs...) rm(pkgs::Vector{String}; kwargs...) = rm([PackageSpec(pkg) for pkg in pkgs]; kwargs...) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 358e10038b4fe..75aaee666c48d 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1037,8 +1037,8 @@ pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a do_develop!, (ARG_ALL, []), [ - ("local", OPT_SWITCH, :devdir => true), - ("shared", OPT_SWITCH, :devdir => false), + ("local", OPT_SWITCH, :shared => false), + ("shared", OPT_SWITCH, :shared => true), ], md""" develop [--shared|--local] pkg[=uuid] [#rev] ... From e5da1831b2f4260625efc22a1fa48a25d71df2e9 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 3 Aug 2018 17:27:03 +0200 Subject: [PATCH 10/22] use full path for local paths when determining package name (#571) --- stdlib/Pkg/src/Types.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index c47b4d9005b9d..56d99426c14c3 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -700,8 +700,12 @@ function parse_package!(ctx, pkg, project_path) pkg.name = ctx.old_pkg2_clone_name else # This is an old style package, get the name from src/PackageName - m = match(reg_pkg, pkg.repo.url) - m === nothing && cmderror("cannot determine package name from URL: $(pkg.repo.url)") + if isdir_windows_workaround(pkg.repo.url) + m = match(reg_pkg, abspath(pkg.repo.url)) + else + m = match(reg_pkg, pkg.repo.url) + end + m === nothing && cmderror("cannot determine package name from URL or path: $(pkg.repo.url)") pkg.name = m.captures[1] end reg_uuids = registered_uuids(env, pkg.name) From 4b43e63cd3a0da85c9a9a473ab3fdecbb9cb1095 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 3 Aug 2018 17:59:17 +0200 Subject: [PATCH 11/22] stop using PkgError (#577) --- stdlib/Pkg/src/Pkg2/reqs.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/Pkg/src/Pkg2/reqs.jl b/stdlib/Pkg/src/Pkg2/reqs.jl index 9d6da6cdf2944..59f0690e7ad01 100644 --- a/stdlib/Pkg/src/Pkg2/reqs.jl +++ b/stdlib/Pkg/src/Pkg2/reqs.jl @@ -23,12 +23,12 @@ struct Requirement <: Line while !isempty(fields) && fields[1][1] == '@' push!(system, popfirst!(fields)[2:end]) end - isempty(fields) && throw(PkgError("invalid requires entry: $content")) + isempty(fields) && error("invalid requires entry: $content") package = popfirst!(fields) all(field->occursin(Base.VERSION_REGEX, field), fields) || - throw(PkgError("invalid requires entry for $package: $content")) + error("invalid requires entry for $package: $content") versions = VersionNumber.(fields) - issorted(versions) || throw(PkgError("invalid requires entry for $package: $content")) + issorted(versions) || error("invalid requires entry for $package: $content") new(content, package, VersionSet(versions), system) end end From 855ea64a083020b49ab389de2d95d1ca2b139c92 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 3 Aug 2018 22:44:43 +0200 Subject: [PATCH 12/22] ignore julia in test/REQUIRE (#578) --- stdlib/Pkg/src/Operations.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index c59ba70827507..858019b6ae02e 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -945,6 +945,7 @@ function pkg2_test_target_compatibility!(ctx, path, pkgs) for r in Pkg2.Reqs.read(test_reqfile) r isa Pkg2.Reqs.Requirement || continue pkg_name, vspec = r.package, VersionSpec(VersionRange[r.versions.intervals...]) + pkg_name == "julia" && continue push!(pkgs, PackageSpec(pkg_name, vspec)) end registry_resolve!(ctx.env, pkgs) From 917b1e714b3dd2c977210712cf4e522002598547 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 3 Aug 2018 22:45:15 +0200 Subject: [PATCH 13/22] Also collect manifest entries from target deps when testing / building. (#572) --- stdlib/Pkg/src/Operations.jl | 34 +++++++++++-------- stdlib/Pkg/test/pkg.jl | 12 +++++++ stdlib/Pkg/test/test_packages/x1/Project.toml | 5 +++ stdlib/Pkg/test/test_packages/x1/src/x1.jl | 5 +++ stdlib/Pkg/test/test_packages/x2/Project.toml | 6 ++++ stdlib/Pkg/test/test_packages/x2/src/x2.jl | 5 +++ stdlib/Pkg/test/test_packages/x3/Project.toml | 9 +++++ stdlib/Pkg/test/test_packages/x3/src/x3.jl | 5 +++ .../test/test_packages/x3/test/runtests.jl | 7 ++++ 9 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 stdlib/Pkg/test/test_packages/x1/Project.toml create mode 100644 stdlib/Pkg/test/test_packages/x1/src/x1.jl create mode 100644 stdlib/Pkg/test/test_packages/x2/Project.toml create mode 100644 stdlib/Pkg/test/test_packages/x2/src/x2.jl create mode 100644 stdlib/Pkg/test/test_packages/x3/Project.toml create mode 100644 stdlib/Pkg/test/test_packages/x3/src/x3.jl create mode 100644 stdlib/Pkg/test/test_packages/x3/test/runtests.jl diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index 858019b6ae02e..fd04ff86cff1c 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -791,6 +791,19 @@ function with_dependencies_loadable_at_toplevel(f, mainctx::Context, pkg::Packag need_to_resolve = false is_project = Types.is_project(localctx.env, pkg) + # Only put `pkg` and its deps + target deps (recursively) in the temp project + collect_deps!(seen, pkg) = begin + pkg.uuid in seen && return + push!(seen, pkg.uuid) + info = manifest_info(localctx.env, pkg.uuid) + info === nothing && return + need_to_resolve |= haskey(info, "path") + localctx.env.project["deps"][pkg.name] = string(pkg.uuid) + for (dpkg, duuid) in get(info, "deps", []) + collect_deps!(seen, PackageSpec(dpkg, UUID(duuid))) + end + end + if is_project # testing the project itself # the project might have changes made to it so need to resolve need_to_resolve = true @@ -807,23 +820,11 @@ function with_dependencies_loadable_at_toplevel(f, mainctx::Context, pkg::Packag )] else # Only put `pkg` and its deps (recursively) in the temp project - collect_deps!(seen, pkg) = begin - pkg.uuid in seen && return - push!(seen, pkg.uuid) - info = manifest_info(localctx.env, pkg.uuid) - need_to_resolve |= haskey(info, "path") - localctx.env.project["deps"][pkg.name] = string(pkg.uuid) - for (dpkg, duuid) in get(info, "deps", []) - collect_deps!(seen, PackageSpec(dpkg, UUID(duuid))) - end - end - # Only put `pkg` and its deps (revursively) in the temp project empty!(localctx.env.project["deps"]) localctx.env.project["deps"][pkg.name] = string(pkg.uuid) - seen_uuids = Set{UUID}() - collect_deps!(seen_uuids, pkg)# Only put `pkg` and its deps (recursively) in the temp project - + # Only put `pkg` and its deps (recursively) in the temp project + collect_deps!(seen_uuids, pkg) end pkgs = PackageSpec[] @@ -833,6 +834,11 @@ function with_dependencies_loadable_at_toplevel(f, mainctx::Context, pkg::Packag end if !isempty(target) collect_target_deps!(localctx, pkgs, pkg, target) + seen_uuids = Set{UUID}() + for dpkg in pkgs + # Also put eventual deps of target deps in new manifest + collect_deps!(seen_uuids, dpkg) + end end mktempdir() do tmpdir diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 6538a4bba0d88..459672847f9ce 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -435,6 +435,18 @@ temp_pkg_dir() do project_path end end +@testset "dependency of test dependency (#567)" begin + mktempdir() do tmpdir + temp_pkg_dir() do project_path; cd(tmpdir) do; with_temp_env() do + for x in ["x1", "x2", "x3"] + cp(joinpath(@__DIR__, "test_packages/$x"), joinpath(tmpdir, "$x")) + Pkg.develop(Pkg.PackageSpec(url = joinpath(tmpdir, x))) + end + Pkg.test("x3") + end end end + end +end + include("repl.jl") include("api.jl") diff --git a/stdlib/Pkg/test/test_packages/x1/Project.toml b/stdlib/Pkg/test/test_packages/x1/Project.toml new file mode 100644 index 0000000000000..1026a589fde5c --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x1/Project.toml @@ -0,0 +1,5 @@ +name = "x1" +uuid = "52033f98-96b1-11e8-17f9-4d5b643961d8" +version = "0.1.0" + +[deps] diff --git a/stdlib/Pkg/test/test_packages/x1/src/x1.jl b/stdlib/Pkg/test/test_packages/x1/src/x1.jl new file mode 100644 index 0000000000000..bd929422af3f4 --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x1/src/x1.jl @@ -0,0 +1,5 @@ +module x1 + +greet() = print("Hello World!") + +end # module diff --git a/stdlib/Pkg/test/test_packages/x2/Project.toml b/stdlib/Pkg/test/test_packages/x2/Project.toml new file mode 100644 index 0000000000000..ada91ef334f7c --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x2/Project.toml @@ -0,0 +1,6 @@ +name = "x2" +uuid = "52baf49e-96b1-11e8-23dd-2d073a3a6758" +version = "0.1.0" + +[deps] +x1 = "52033f98-96b1-11e8-17f9-4d5b643961d8" diff --git a/stdlib/Pkg/test/test_packages/x2/src/x2.jl b/stdlib/Pkg/test/test_packages/x2/src/x2.jl new file mode 100644 index 0000000000000..8afcc2e013477 --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x2/src/x2.jl @@ -0,0 +1,5 @@ +module x2 + +greet() = print("Hello World!") + +end # module diff --git a/stdlib/Pkg/test/test_packages/x3/Project.toml b/stdlib/Pkg/test/test_packages/x3/Project.toml new file mode 100644 index 0000000000000..8cd99a21c7922 --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x3/Project.toml @@ -0,0 +1,9 @@ +name = "x3" +uuid = "53501efc-96b1-11e8-0d90-e1a45c33f0f8" +version = "0.1.0" + +[extras] +x2 = "52baf49e-96b1-11e8-23dd-2d073a3a6758" + +[targets] +test = ["x2"] diff --git a/stdlib/Pkg/test/test_packages/x3/src/x3.jl b/stdlib/Pkg/test/test_packages/x3/src/x3.jl new file mode 100644 index 0000000000000..a9b26ef703c75 --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x3/src/x3.jl @@ -0,0 +1,5 @@ +module x3 + +greet() = print("Hello World!") + +end # module diff --git a/stdlib/Pkg/test/test_packages/x3/test/runtests.jl b/stdlib/Pkg/test/test_packages/x3/test/runtests.jl new file mode 100644 index 0000000000000..85b0336d373e1 --- /dev/null +++ b/stdlib/Pkg/test/test_packages/x3/test/runtests.jl @@ -0,0 +1,7 @@ +module X3Tests + +using x2 + +println("hello") + +end # module From ff586edf41645e59f00289c1dd90628f66b311be Mon Sep 17 00:00:00 2001 From: Twan Koolen Date: Fri, 3 Aug 2018 17:03:45 -0400 Subject: [PATCH 14/22] Propagate track-allocation option to test process. (#579) --- stdlib/Pkg/src/Operations.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index fd04ff86cff1c..d809d584bc72a 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -1291,7 +1291,8 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false) --color=$(Base.have_color ? "yes" : "no") --compiled-modules=$(Bool(Base.JLOptions().use_compiled_modules) ? "yes" : "no") --check-bounds=yes - --startup-file=$(Base.JLOptions().startupfile != 2 ? "yes" : "no") + --startup-file=$(Base.JLOptions().startupfile == 1 ? "yes" : "no") + --track-allocation=$(("none", "user", "all")[Base.JLOptions().malloc_log + 1]) --eval $code ``` run_test = () -> begin From f647d704719c96307a797d9b1fde02b3f247e4a7 Mon Sep 17 00:00:00 2001 From: Christof Stocker Date: Fri, 3 Aug 2018 23:14:20 +0200 Subject: [PATCH 15/22] add --shared option for activate (#558) --- stdlib/Pkg/src/API.jl | 58 +++++++++++++++++++++++++------------- stdlib/Pkg/src/Pkg.jl | 13 +++++---- stdlib/Pkg/src/REPLMode.jl | 17 +++++++++-- stdlib/Pkg/test/repl.jl | 23 +++++++++++++-- 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 9fa5450dc3e3d..a57b39edd35a8 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -546,27 +546,47 @@ function status(ctx::Context, mode=PKGMODE_PROJECT) return end -activate() = (Base.ACTIVE_PROJECT[] = Base.load_path_expand(nothing)) -function activate(path::String) - devpath = nothing - env = Base.active_project() === nothing ? nothing : EnvCache() - if env !== nothing && haskey(env.project["deps"], path) - uuid = UUID(env.project["deps"][path]) - info = manifest_info(env, uuid) - devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing - end - # `pkg> activate path`/`Pkg.activate(path)` does the following - # 1. if path exists, activate that - # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) - # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) - if Types.isdir_windows_workaround(path) - path = abspath(path) - elseif devpath !== nothing - path = abspath(devpath) +activate() = (Base.ACTIVE_PROJECT[] = nothing) +function activate(path::String; shared::Bool=false) + if !shared + devpath = nothing + env = Base.active_project() === nothing ? nothing : EnvCache() + if env !== nothing && haskey(env.project["deps"], path) + uuid = UUID(env.project["deps"][path]) + info = manifest_info(env, uuid) + devpath = haskey(info, "path") ? joinpath(dirname(env.project_file), info["path"]) : nothing + end + # `pkg> activate path`/`Pkg.activate(path)` does the following + # 1. if path exists, activate that + # 2. if path exists in deps, and the dep is deved, activate that path (`devpath` above) + # 3. activate the non-existing directory (e.g. as in `pkg> activate .` for initing a new env) + if Types.isdir_windows_workaround(path) + fullpath = abspath(path) + elseif devpath !== nothing + fullpath = abspath(devpath) + else + fullpath = abspath(path) + isdir(fullpath) || @info("new environment will be placed at $fullpath") + end else - path = abspath(path) + # initialize `fullpath` in case of empty `Pkg.depots()` + fullpath = "" + # loop over all depots to check if the shared environment already exists + for depot in Pkg.depots() + fullpath = joinpath(Pkg.envdir(depot), path) + isdir(fullpath) && break + end + # this disallows names such as "Foo/bar", ".", "..", etc + if basename(abspath(fullpath)) != path + cmderror("not a valid name for a shared environment: $(path)") + end + # unless the shared environment already exists, place it in the first depots + if !isdir(fullpath) + fullpath = joinpath(Pkg.envdir(Pkg.depots1()), path) + @info("new shared environment \"$path\" will be placed at $fullpath") + end end - Base.ACTIVE_PROJECT[] = Base.load_path_expand(path) + Base.ACTIVE_PROJECT[] = Base.load_path_expand(fullpath) end """ diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index fabbcf54698a0..5c341e745925d 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -20,6 +20,7 @@ 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 @@ -261,18 +262,20 @@ const status = API.status """ - Pkg.activate([s::String]) + 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 `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 `shared` is `true`, the first existing environment named `s` from the depots + in the depot stack will be activated. If no such environment exists yet, + activate it in the first depot. + * If `s` is a path that exist, that environment will be activated. + * If `s` is a package name in the current project 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. diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 75aaee666c48d..740e8d96096eb 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -609,7 +609,7 @@ function do_activate!(args::PkgArguments, api_opts::APIOptions) if isempty(args) return API.activate() else - return API.activate(args[1]) + return API.activate(args[1]; collect(api_opts)...) end end @@ -1110,8 +1110,19 @@ packages have changed causing the current Manifest to_indices be out of sync. ["activate"], do_activate!, (ARG_RAW, [0,1]), - [], - nothing, + [ + ("shared", OPT_SWITCH, :shared => true), + ], + md""" + activate + activate [--shared] path + +Activate the environment at the given `path`, or the home project environment if no `path` is specified. +The active environment is the environment that is modified by executing package commands. +When the option `--shared` is given, `path` will be assumed to be a directory name and searched for in the +`environments` folders of the depots in the depot stack. In case no such environment exists in any of the depots, +it will be placed in the first depot of the stack. + """ , ),( CMD_UP, ["update", "up"], do_up!, diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 6dc3e00fe7058..374815d0044fb 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -261,6 +261,14 @@ temp_pkg_dir() do project_path cd(mktempdir()) do path = pwd() pkg"activate ." + @test Base.active_project() == joinpath(path, "Project.toml") + # tests illegal names for shared environments + @test_throws Pkg.Types.CommandError pkg"activate --shared ." + @test_throws Pkg.Types.CommandError pkg"activate --shared ./Foo" + @test_throws Pkg.Types.CommandError pkg"activate --shared Foo/Bar" + @test_throws Pkg.Types.CommandError pkg"activate --shared ../Bar" + # check that those didn't change te enviroment + @test Base.active_project() == joinpath(path, "Project.toml") mkdir("Foo") cd(mkdir("modules")) do pkg"generate Foo" @@ -269,23 +277,32 @@ temp_pkg_dir() do project_path pkg"activate Foo" # activate path Foo over deps Foo @test Base.active_project() == joinpath(path, "Foo", "Project.toml") pkg"activate ." + @test_logs (:info, r"new shared environment") pkg"activate --shared Foo" # activate shared Foo + @test Base.active_project() == joinpath(Pkg.envdir(), "Foo", "Project.toml") + pkg"activate ." rm("Foo"; force=true, recursive=true) pkg"activate Foo" # activate path from developed Foo @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") pkg"activate ." - pkg"activate ./Foo" # activate empty directory Foo (sidestep the developed Foo) + @test_logs (:info, r"new environment") pkg"activate ./Foo" # activate empty directory Foo (sidestep the developed Foo) @test Base.active_project() == joinpath(path, "Foo", "Project.toml") pkg"activate ." - pkg"activate Bar" # activate empty directory Bar + @test_logs (:info, r"new environment") pkg"activate Bar" # activate empty directory Bar @test Base.active_project() == joinpath(path, "Bar", "Project.toml") pkg"activate ." pkg"add Example" # non-deved deps should not be activated - pkg"activate Example" + @test_logs (:info, r"new environment") pkg"activate Example" @test Base.active_project() == joinpath(path, "Example", "Project.toml") pkg"activate ." cd(mkdir("tests")) pkg"activate Foo" # activate developed Foo from another directory @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + tmpdepot = mktempdir() + tmpdir = mkpath(joinpath(tmpdepot, "environments", "Foo")) + push!(Base.DEPOT_PATH, tmpdepot) + pkg"activate --shared Foo" # activate existing shared Foo + @test Base.active_project() == joinpath(tmpdir, "Project.toml") + pop!(Base.DEPOT_PATH) pkg"activate" # activate home project @test Base.ACTIVE_PROJECT[] === nothing end From e804d11ef9cefe75d08126cc3323fab59672572c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 00:18:16 +0200 Subject: [PATCH 16/22] allow using a path kword arg to PackageSpec (#580) --- stdlib/Pkg/src/Pkg.jl | 10 +++++----- stdlib/Pkg/src/REPLMode.jl | 18 +----------------- stdlib/Pkg/src/Types.jl | 13 +++++++++---- stdlib/Pkg/test/api.jl | 2 +- stdlib/Pkg/test/pkg.jl | 2 +- 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 5c341e745925d..1f0b83db24a78 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -292,7 +292,7 @@ const activate = API.activate """ PackageSpec(name::String, [uuid::UUID, version::VersionNumber]) - PackageSpec(; name, url, rev, version, mode, level) + PackageSpec(; name, url, path, rev, version, mode, level) A `PackageSpec` is a representation of a package with various metadata. This includes: @@ -301,8 +301,8 @@ This includes: * 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 `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). @@ -317,8 +317,8 @@ Below is a comparison between the REPL version and the `PackageSpec` version: | `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")` | +| `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`)| """ diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 740e8d96096eb..29dd6a44e774e 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -666,22 +666,6 @@ long_commands = [] all_options_sorted = [] long_options = [] -all_commands_sorted = sort(collect(String,keys(command_specs))) -long_commands = filter(c -> length(c) > 2, all_commands_sorted) -function all_options() - all_opts = [] - for command in values(command_specs) - for opt_spec in command.option_specs - push!(all_opts, opt_spec.name) - opt_spec.short_name !== nothing && push!(all_opts, opt_spec.short_name) - end - end - unique!(all_opts) - return all_opts -end -all_options_sorted = [length(opt) > 1 ? "--$opt" : "-$opt" for opt in sort!(all_options())] -long_options = filter(c -> length(c) > 2, all_options_sorted) - struct PkgCompletionProvider <: LineEdit.CompletionProvider end function LineEdit.complete_line(c::PkgCompletionProvider, s) @@ -1220,7 +1204,7 @@ is modified. ], #package ] #command_declarations -super_specs = SuperSpecs(command_declarations) # TODO should this go here ? +super_specs = SuperSpecs(command_declarations) command_specs = super_specs["package"] all_commands_sorted = sort(collect(String,keys(command_specs))) long_commands = filter(c -> length(c) > 2, all_commands_sorted) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 56d99426c14c3..68d2cac2c9a36 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -169,9 +169,14 @@ function PackageSpec(repo::GitRepo) 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 +function PackageSpec(;name::AbstractString="", uuid::Union{String, UUID}=UUID(0), + version::Union{VersionNumber, String, VersionSpec} = VersionSpec(), + url = nothing, rev = nothing, path=nothing, mode::PackageMode = PKGMODE_PROJECT) + if url !== nothing || path !== nothing || rev !== nothing + if path !== nothing || url !== nothing + path !== nothing && url !== nothing && cmderror("cannot specify both path and url") + url = url == nothing ? path : url + end repo = GitRepo(url=url, rev=rev) else repo = nothing @@ -190,7 +195,7 @@ function Base.show(io::IO, pkg::PackageSpec) 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) + push!(f, "url/path" => string("\"", pkg.repo.url, "\"")) end if !isempty(pkg.repo.rev) push!(f, "rev" => pkg.repo.rev) diff --git a/stdlib/Pkg/test/api.jl b/stdlib/Pkg/test/api.jl index edbc15f186754..452eca69126c5 100644 --- a/stdlib/Pkg/test/api.jl +++ b/stdlib/Pkg/test/api.jl @@ -10,7 +10,7 @@ using Pkg, Test cd(mkdir("modules")) do Pkg.generate("Foo") end - Pkg.develop(Pkg.Types.PackageSpec(url="modules/Foo")) # to avoid issue #542 + Pkg.develop(Pkg.Types.PackageSpec(path="modules/Foo")) # to avoid issue #542 Pkg.activate("Foo") # activate path Foo over deps Foo @test Base.active_project() == joinpath(path, "Foo", "Project.toml") Pkg.activate(".") diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 459672847f9ce..3fb935e1efd0f 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -405,7 +405,7 @@ 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(PackageSpec(url=package_path)) + Pkg.add(PackageSpec(path=package_path)) end rm(joinpath(package_path, ".git"); force=true, recursive=true) @test_throws CommandError Pkg.update() From eed9ea7fb6c927432954987ac46d89791f0804b3 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 01:15:19 +0200 Subject: [PATCH 17/22] rename CommandError to PkgError (#475) --- stdlib/Pkg/src/API.jl | 18 ++--- stdlib/Pkg/src/GitTools.jl | 8 +-- stdlib/Pkg/src/Operations.jl | 22 +++---- stdlib/Pkg/src/Pkg.jl | 2 +- stdlib/Pkg/src/REPLMode.jl | 44 ++++++------- stdlib/Pkg/src/Types.jl | 32 ++++----- stdlib/Pkg/src/generate.jl | 2 +- stdlib/Pkg/test/pkg.jl | 16 ++--- stdlib/Pkg/test/repl.jl | 123 ++++++++++++++++++----------------- stdlib/Pkg/test/resolve.jl | 2 +- 10 files changed, 136 insertions(+), 133 deletions(-) diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index a57b39edd35a8..09d807b0e0a74 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -19,7 +19,7 @@ include("generate.jl") function check_package_name(x::String) if !(occursin(Pkg.REPLMode.name_re, x)) - cmderror("$x is not a valid packagename") + pkgerror("$x is not a valid packagename") end return PackageSpec(x) end @@ -39,7 +39,7 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, s # if julia is passed as a package the solver gets tricked; # this catches the error early on any(pkg->(pkg.name == "julia"), pkgs) && - cmderror("Trying to $mode julia as a package") + pkgerror("Trying to $mode julia as a package") ctx.preview && preview_info() if mode == :develop @@ -54,7 +54,7 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, s ensure_resolved(ctx.env, pkgs, registry=true) any(pkg -> Types.collides_with_project(ctx.env, pkg), pkgs) && - cmderror("Cannot $mode package with the same name or uuid as the project") + pkgerror("Cannot $mode package with the same name or uuid as the project") Operations.add_or_develop(ctx, pkgs; new_git=new_git) ctx.preview && preview_info() @@ -107,7 +107,7 @@ function update_registry(ctx) try GitTools.fetch(repo; refspecs=["+refs/heads/$branch:refs/remotes/origin/$branch"]) catch e - e isa CommandError || rethrow(e) + e isa PkgError || rethrow(e) push!(errors, (reg, "failed to fetch from repo")) return end @@ -219,7 +219,7 @@ function free(ctx::Context, pkgs::Vector{PackageSpec}; kwargs...) for pkg in pkgs info = manifest_info(ctx.env, pkg.uuid) if !get(info, "pinned", false) && !(pkg.uuid in uuids_in_registry) - cmderror("cannot free an unpinned package that does not exist in a registry") + pkgerror("cannot free an unpinned package that does not exist in a registry") end end Operations.free(ctx, pkgs) @@ -238,7 +238,7 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false, kwargs... ctx.preview && preview_info() if isempty(pkgs) # TODO: Allow this? - ctx.env.pkg == nothing && cmderror("trying to test unnamed project") + ctx.env.pkg == nothing && pkgerror("trying to test unnamed project") push!(pkgs, ctx.env.pkg) end project_resolve!(ctx.env, pkgs) @@ -468,7 +468,7 @@ function precompile(ctx::Context) sourcepath = Base.locate_package(pkg) if sourcepath == nothing # XXX: this isn't supposed to be fatal - cmderror("couldn't find path to $(pkg.name) when trying to precompilie project") + pkgerror("couldn't find path to $(pkg.name) when trying to precompilie project") end stale = true for path_to_try in paths::Vector{String} @@ -504,7 +504,7 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, kwarg return end if !isfile(ctx.env.manifest_file) && manifest == true - cmderror("manifest at $(ctx.env.manifest_file) does not exist") + pkgerror("manifest at $(ctx.env.manifest_file) does not exist") end update_registry(ctx) urls = Dict{} @@ -578,7 +578,7 @@ function activate(path::String; shared::Bool=false) end # this disallows names such as "Foo/bar", ".", "..", etc if basename(abspath(fullpath)) != path - cmderror("not a valid name for a shared environment: $(path)") + pkgerror("not a valid name for a shared environment: $(path)") end # unless the shared environment already exists, place it in the first depots if !isdir(fullpath) diff --git a/stdlib/Pkg/src/GitTools.jl b/stdlib/Pkg/src/GitTools.jl index 05d4dc6998318..acd988ead9bd9 100644 --- a/stdlib/Pkg/src/GitTools.jl +++ b/stdlib/Pkg/src/GitTools.jl @@ -97,9 +97,9 @@ function clone(url, source_path; header=nothing, kwargs...) err isa LibGit2.GitError || rethrow(err) if (err.class == LibGit2.Error.Net && err.code == LibGit2.Error.EINVALIDSPEC) || (err.class == LibGit2.Error.Repository && err.code == LibGit2.Error.ENOTFOUND) - Pkg.Types.cmderror("Git repository not found at '$(url)'") + Pkg.Types.pkgerror("Git repository not found at '$(url)'") else - Pkg.Types.cmderror("failed to clone from $(url), error: $err") + Pkg.Types.pkgerror("failed to clone from $(url), error: $err") end finally print(stdout, "\033[2K") # clear line @@ -128,9 +128,9 @@ function fetch(repo::LibGit2.GitRepo, remoteurl=nothing; header=nothing, kwargs. catch err err isa LibGit2.GitError || rethrow(err) if (err.class == LibGit2.Error.Repository && err.code == LibGit2.Error.ERROR) - Pkg.Types.cmderror("Git repository not found at '$(remoteurl)'") + Pkg.Types.pkgerror("Git repository not found at '$(remoteurl)'") else - Pkg.Types.cmderror("failed to fetch from $(remoteurl), error: $err") + Pkg.Types.pkgerror("failed to fetch from $(remoteurl), error: $err") end finally print(stdout, "\033[2K") # clear line diff --git a/stdlib/Pkg/src/Operations.jl b/stdlib/Pkg/src/Operations.jl index d809d584bc72a..468c48a941a9b 100644 --- a/stdlib/Pkg/src/Operations.jl +++ b/stdlib/Pkg/src/Operations.jl @@ -37,7 +37,7 @@ function load_package_data(f::Base.Callable, path::String, versions) vr = VersionRange(v) ver in vr || continue dict = get!(data, ver, Dict{String,Any}()) - haskey(dict, key) && cmderror("$ver/$key is duplicated in $path") + haskey(dict, key) && pkgerror("$ver/$key is duplicated in $path") dict[key] = f(value) end end @@ -53,7 +53,7 @@ function load_package_data_raw(T::Type, path::String) for (v, d) in toml, (key, value) in d vr = VersionRange(v) dict = get!(data, vr, Dict{String,T}()) - haskey(dict, key) && cmderror("$vr/$key is duplicated in $path") + haskey(dict, key) && pkgerror("$vr/$key is duplicated in $path") dict[key] = T(value) end return data @@ -106,7 +106,7 @@ function collect_fixed!(ctx::Context, pkgs::Vector{PackageSpec}, uuid_to_name::D path = project_rel_path(ctx, path) if !isdir(path) - cmderror("path $(path) for package $(pkg.name) no longer exists. Remove the package or `develop` it at a new path") + pkgerror("path $(path) for package $(pkg.name) no longer exists. Remove the package or `develop` it at a new path") end uuid_to_pkg[pkg.uuid] = pkg @@ -328,7 +328,7 @@ function resolve_versions!(ctx::Context, pkgs::Vector{PackageSpec})::Dict{UUID,V proj_compat = Types.project_compatibility(ctx, name) v = intersect(pkg.version, proj_compat) if isempty(v) - cmderror(string("for package $(pkg.name) intersection between project compatibility $(proj_compat) ", + pkgerror(string("for package $(pkg.name) intersection between project compatibility $(proj_compat) ", "and package version $(pkg.version) is empty")) end pkg.version = v @@ -382,7 +382,7 @@ function version_data!(ctx::Context, pkgs::Vector{PackageSpec}) info = parse_toml(path, "Package.toml") if haskey(names, uuid) names[uuid] == info["name"] || - cmderror("$uuid: name mismatch between registries: ", + pkgerror("$uuid: name mismatch between registries: ", "$(names[uuid]) vs. $(info["name"])") else names[uuid] = info["name"] @@ -569,7 +569,7 @@ function apply_versions(ctx::Context, pkgs::Vector{PackageSpec}, hashes::Dict{UU try success = install_archive(urls[pkg.uuid], hashes[pkg.uuid], path) if ctx.use_only_tarballs_for_downloads && !success - cmderror("failed to get tarball from $(urls[pkg.uuid])") + pkgerror("failed to get tarball from $(urls[pkg.uuid])") end put!(results, (pkg, success, path)) catch err @@ -582,7 +582,7 @@ function apply_versions(ctx::Context, pkgs::Vector{PackageSpec}, hashes::Dict{UU missed_packages = Tuple{PackageSpec, String}[] for i in 1:length(pkgs_to_install) pkg, exc_or_success, bt_or_path = take!(results) - exc_or_success isa Exception && cmderror("Error when installing packages:\n", sprint(Base.showerror, exc_or_success, bt_or_path)) + exc_or_success isa Exception && pkgerror("Error when installing packages:\n", sprint(Base.showerror, exc_or_success, bt_or_path)) success, path = exc_or_success, bt_or_path if success vstr = pkg.version != nothing ? "v$(pkg.version)" : "[$h]" @@ -1021,7 +1021,7 @@ function build_versions(ctx::Context, uuids::Vector{UUID}; might_need_to_resolve path = project_rel_path(ctx, info["path"]) hash_or_path = path else - cmderror("Could not find either `git-tree-sha1` or `path` for package $(pkg.name)") + pkgerror("Could not find either `git-tree-sha1` or `path` for package $(pkg.name)") end version = v"0.0" end @@ -1257,7 +1257,7 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false) elseif pkg.uuid in keys(ctx.stdlibs) version_path = Types.stdlib_path(pkg.name) else - cmderror("Could not find either `git-tree-sha1` or `path` for package $(pkg.name)") + pkgerror("Could not find either `git-tree-sha1` or `path` for package $(pkg.name)") end end testfile = joinpath(version_path, "test", "runtests.jl") @@ -1268,7 +1268,7 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false) push!(testfiles, testfile) end if !isempty(missing_runtests) - cmderror(length(missing_runtests) == 1 ? "Package " : "Packages ", + pkgerror(length(missing_runtests) == 1 ? "Package " : "Packages ", join(missing_runtests, ", "), " did not provide a `test/runtests.jl` file") end @@ -1313,7 +1313,7 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false) end if !isempty(pkgs_errored) - cmderror(length(pkgs_errored) == 1 ? "Package " : "Packages ", + pkgerror(length(pkgs_errored) == 1 ? "Package " : "Packages ", join(pkgs_errored, ", "), " errored during testing") end diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index 1f0b83db24a78..e1551c0e0369e 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -14,7 +14,7 @@ export UpgradeLevel, UPLEVEL_MAJOR, UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH depots() = Base.DEPOT_PATH function depots1() d = depots() - isempty(d) && cmderror("no depots found in DEPOT_PATH") + isempty(d) && pkgerror("no depots found in DEPOT_PATH") return d[1] end diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 29dd6a44e774e..39366bc5a207c 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -73,7 +73,7 @@ Base.show(io::IO, opt::Option) = print(io, "--$(opt.val)", opt.argument == nothi function parse_option(word::AbstractString)::Option m = match(r"^(?: -([a-z]) | --([a-z]{2,})(?:\s*=\s*(\S*))? )$"ix, word) - m == nothing && cmderror("malformed option: ", repr(word)) + m == nothing && pkgerror("malformed option: ", repr(word)) option_name = (m.captures[1] != nothing ? m.captures[1] : m.captures[2]) option_arg = (m.captures[3] == nothing ? nothing : String(m.captures[3])) return Option(option_name, option_arg) @@ -174,7 +174,7 @@ function parse_package(word::AbstractString; add_or_develop=false)::PackageSpec # Guess it is a url then return PackageSpec(Types.GitRepo(word)) else - cmderror("`$word` cannot be parsed as a package") + pkgerror("`$word` cannot be parsed as a package") end end @@ -218,7 +218,7 @@ function Statement(words)::Statement # meta options while is_option(word) push!(statement.meta_options, word) - isempty(words) && cmderror("no command specified") + isempty(words) && pkgerror("no command specified") word = popfirst!(words) end # command @@ -229,7 +229,7 @@ function Statement(words)::Statement super = super_specs["package"] end command = get(super, word, nothing) - command !== nothing || cmderror("expected command. instead got [$word]") + command !== nothing || pkgerror("expected command. instead got [$word]") statement.command = command # command arguments for word in words @@ -245,7 +245,7 @@ function group_words(words)::Vector{Vector{String}} x = String[] for word in words if word == ";" - isempty(x) ? cmderror("empty statement") : push!(statements, x) + isempty(x) ? pkgerror("empty statement") : push!(statements, x) x = String[] else push!(x, word) @@ -300,7 +300,7 @@ function parse_quotes(cmd::String)::Vector{QuotedWord} end end if (in_doublequote || in_singlequote) - cmderror("unterminated quote") + pkgerror("unterminated quote") else push_token!(false) end @@ -345,7 +345,7 @@ end function enforce_argument_order(args::Vector{Token}) prev_arg = nothing function check_prev_arg(valid_type::DataType, error_message::AbstractString) - prev_arg isa valid_type || cmderror(error_message) + prev_arg isa valid_type || pkgerror(error_message) end for arg in args @@ -379,11 +379,11 @@ function enforce_arg_spec(raw_args::Vector{String}, class::ArgClass) class == ARG_ALL && return args if class == ARG_PKG && has_types(args, [VersionRange, Rev]) - cmderror("no versioned packages allowed") + pkgerror("no versioned packages allowed") elseif class == ARG_REV && has_types(args, [VersionRange]) - cmderror("no versioned packages allowed") + pkgerror("no versioned packages allowed") elseif class == ARG_VERSION && has_types(args, [Rev]) - cmderror("no reved packages allowed") + pkgerror("no reved packages allowed") end return args end @@ -413,7 +413,7 @@ end function enforce_arg_count(count::Vector{Int}, args::PkgArguments) isempty(count) && return length(args) in count || - cmderror("Wrong number of arguments") + pkgerror("Wrong number of arguments") end function enforce_args(raw_args::Vector{String}, spec::ArgSpec, cmd_spec::CommandSpec)::PkgArguments @@ -433,13 +433,13 @@ function enforce_option(option::String, specs::Dict{String,OptionSpec})::Option opt = parse_option(option) spec = get(specs, opt.val, nothing) spec !== nothing || - cmderror("option '$(opt.val)' is not a valid option") + pkgerror("option '$(opt.val)' is not a valid option") if spec.is_switch opt.argument === nothing || - cmderror("option '$(opt.val)' does not take an argument, but '$(opt.argument)' given") + pkgerror("option '$(opt.val)' does not take an argument, but '$(opt.argument)' given") else # option takes an argument opt.argument !== nothing || - cmderror("option '$(opt.val)' expects an argument, but no argument given") + pkgerror("option '$(opt.val)' expects an argument, but no argument given") end return opt end @@ -449,7 +449,7 @@ function enforce_meta_options(options::Vector{String}, specs::Dict{String,Option return map(options) do opt tok = enforce_option(opt, specs) tok.val in meta_opt_names || - cmderror("option '$opt' is not a valid meta option.") + pkgerror("option '$opt' is not a valid meta option.") #TODO hint that maybe they intended to use it as a command option return tok end @@ -465,12 +465,12 @@ function enforce_opts(options::Vector{String}, specs::Dict{String,OptionSpec}):: for opt in toks # valid option opt.val in keys(specs) || - cmderror("option '$(opt.val)' is not supported") + pkgerror("option '$(opt.val)' is not supported") # conflicting options key = get_key(opt) if key in unique_keys conflicting = filter(opt->get_key(opt) == key, toks) - cmderror("Conflicting options: $conflicting") + pkgerror("Conflicting options: $conflicting") else push!(unique_keys, key) end @@ -505,7 +505,7 @@ function do_cmd(repl::REPL.AbstractREPL, input::String; do_rethrow=false) if do_rethrow rethrow(err) end - if err isa CommandError || err isa ResolverError + if err isa PkgError || err isa ResolverError Base.display_error(repl.t.err_stream, ErrorException(sprint(showerror, err)), Ptr{Nothing}[]) else Base.display_error(repl.t.err_stream, err, Base.catch_backtrace()) @@ -525,7 +525,7 @@ function do_cmd!(command::PkgCommand, repl) cmd = command.arguments[1] cmd_spec = get(command_specs, cmd, nothing) cmd_spec === nothing && - cmderror("'$cmd' is not a valid command") + pkgerror("'$cmd' is not a valid command") spec = cmd_spec command = PkgCommand([], cmd, [], PackageSpec[]) end @@ -550,9 +550,9 @@ function do_help!(command::PkgCommand, repl::REPL.AbstractREPL) for arg in command.arguments spec = get(command_specs, arg, nothing) spec === nothing && - cmderror("'$arg' does not name a command") + pkgerror("'$arg' does not name a command") spec.help === nothing && - cmderror("Sorry, I don't have any help for the `$arg` command.") + pkgerror("Sorry, I don't have any help for the `$arg` command.") isempty(help_md.content) || push!(help_md.content, md"---") push!(help_md.content, spec.help) @@ -617,7 +617,7 @@ function do_pin!(ctx::APIOptions, args::PkgArguments, api_opts::APIOptions) for arg in args # TODO not sure this is correct if arg.version.ranges[1].lower != arg.version.ranges[1].upper - cmderror("pinning a package requires a single version, not a versionrange") + pkgerror("pinning a package requires a single version, not a versionrange") end end API.pin(Context!(ctx), args; collect(api_opts)...) diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index 68d2cac2c9a36..b867186ef89ad 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -19,7 +19,7 @@ using SHA export UUID, pkgID, SHA1, VersionRange, VersionSpec, empty_versionspec, Requires, Fixed, merge_requires!, satisfies, ResolverError, PackageSpec, EnvCache, Context, Context!, - CommandError, cmderror, has_name, has_uuid, write_env, parse_toml, find_registered!, + PkgError, pkgerror, has_name, has_uuid, write_env, parse_toml, find_registered!, project_resolve!, project_deps_resolve!, manifest_resolve!, registry_resolve!, stdlib_resolve!, handle_repos_develop!, handle_repos_add!, ensure_resolved, manifest_info, registered_uuids, registered_paths, registered_uuid, registered_name, read_project, read_package, read_manifest, pathrepr, registries, @@ -112,13 +112,13 @@ function Base.showerror(io::IO, pkgerr::ResolverError) end ################# -# Command Error # +# Pkg Error # ################# -struct CommandError <: Exception +struct PkgError <: Exception msg::String end -cmderror(msg::String...) = throw(CommandError(join(msg))) -Base.show(io::IO, err::CommandError) = print(io, err.msg) +pkgerror(msg::String...) = throw(PkgError(join(msg))) +Base.show(io::IO, err::PkgError) = print(io, err.msg) ############### @@ -174,7 +174,7 @@ function PackageSpec(;name::AbstractString="", uuid::Union{String, UUID}=UUID(0) url = nothing, rev = nothing, path=nothing, mode::PackageMode = PKGMODE_PROJECT) if url !== nothing || path !== nothing || rev !== nothing if path !== nothing || url !== nothing - path !== nothing && url !== nothing && cmderror("cannot specify both path and url") + path !== nothing && url !== nothing && pkgerror("cannot specify both path and url") url = url == nothing ? path : url end repo = GitRepo(url=url, rev=rev) @@ -398,7 +398,7 @@ function get_deps(project::Dict, target::Union{Nothing,String}=nothing) for name in names haskey(deps, name) && continue haskey(extras, name) || - cmderror("target `$target` has unlisted dependency `$name`") + pkgerror("target `$target` has unlisted dependency `$name`") deps[name] = extras[name] end return deps @@ -441,7 +441,7 @@ function read_project(file::String) isfile(file) ? open(read_project, file) : read_project(devnull) end -_throw_package_err(x, f) = cmderror("expected a `$x` entry in project file at $(abspath(f))") +_throw_package_err(x, f) = pkgerror("expected a `$x` entry in project file at $(abspath(f))") function read_package(f::String) project = read_project(f) haskey(project, "name") || _throw_package_err("name", f) @@ -449,7 +449,7 @@ function read_package(f::String) name = project["name"] entry = joinpath(dirname(f), "src", "$name.jl") if !isfile(entry) - cmderror("expected the file `src/$name.jl` to exist for package $name at $(dirname(f))") + pkgerror("expected the file `src/$name.jl` to exist for package $name at $(dirname(f))") end return project end @@ -571,7 +571,7 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, dev_pkg_path = joinpath(devdir, pkg.name) if isdir(dev_pkg_path) if !isfile(joinpath(dev_pkg_path, "src", pkg.name * ".jl")) - cmderror("Path `$(dev_pkg_path)` exists but it does not contain `src/$(pkg.name).jl") + pkgerror("Path `$(dev_pkg_path)` exists but it does not contain `src/$(pkg.name).jl") else @info "Path `$(dev_pkg_path)` exists and looks like the correct package, using existing path instead of cloning" end @@ -710,7 +710,7 @@ function parse_package!(ctx, pkg, project_path) else m = match(reg_pkg, pkg.repo.url) end - m === nothing && cmderror("cannot determine package name from URL or path: $(pkg.repo.url)") + m === nothing && pkgerror("cannot determine package name from URL or path: $(pkg.repo.url)") pkg.name = m.captures[1] end reg_uuids = registered_uuids(env, pkg.name) @@ -757,7 +757,7 @@ function get_object_branch(repo, rev) gitobject = LibGit2.GitObject(repo, rev) catch err err isa LibGit2.GitError && err.code == LibGit2.Error.ENOTFOUND || rethrow(err) - cmderror("git object $(rev) could not be found") + pkgerror("git object $(rev) could not be found") end end return gitobject, isbranch @@ -783,7 +783,7 @@ function project_deps_resolve!(env::EnvCache, pkgs::AbstractVector{PackageSpec}) uuids = env.project["deps"] names = Dict(uuid => name for (uuid, name) in uuids) length(uuids) < length(names) && # TODO: handle this somehow? - cmderror("duplicate UUID found in project file's [deps] section") + pkgerror("duplicate UUID found in project file's [deps] section") for pkg in pkgs pkg.mode == PKGMODE_PROJECT || continue if has_name(pkg) && !has_uuid(pkg) && pkg.name in keys(uuids) @@ -886,7 +886,7 @@ function ensure_resolved(env::EnvCache, end print(io, "Please specify by known `name=uuid`.") end - cmderror(msg) + pkgerror(msg) end const DEFAULT_REGISTRIES = Dict("General" => "https://github.com/JuliaRegistries/General.git") @@ -1066,7 +1066,7 @@ function registered_name(env::EnvCache, uuid::UUID)::String name = nothing for value in values name == nothing && (name = value[2]) - name != value[2] && cmderror("package `$uuid` has multiple registered name values: $name, $(value[2])") + name != value[2] && pkgerror("package `$uuid` has multiple registered name values: $name, $(value[2])") end return name end @@ -1074,7 +1074,7 @@ end # Return most current package info for a registered UUID function registered_info(env::EnvCache, uuid::UUID, key::String) paths = env.paths[uuid] - isempty(paths) && cmderror("`$uuid` is not registered") + isempty(paths) && pkgerror("`$uuid` is not registered") values = [] for path in paths info = parse_toml(path, "Package.toml") diff --git a/stdlib/Pkg/src/generate.jl b/stdlib/Pkg/src/generate.jl index 04663c7196ae8..bd5d57cc93605 100644 --- a/stdlib/Pkg/src/generate.jl +++ b/stdlib/Pkg/src/generate.jl @@ -5,7 +5,7 @@ function generate(ctx::Context, path::String; kwargs...) Context!(ctx; kwargs...) ctx.preview && preview_info() dir, pkg = dirname(path), basename(path) - isdir(path) && cmderror("$(abspath(path)) already exists") + isdir(path) && pkgerror("$(abspath(path)) already exists") printstyled("Generating"; color=:green, bold=true) print(" project $pkg:\n") project(pkg, dir; preview=ctx.preview) diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 3fb935e1efd0f..92aac84606b37 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -215,7 +215,7 @@ temp_pkg_dir() do project_path end @testset "invalid pkg name" begin - @test_throws CommandError Pkg.add(",sa..,--") + @test_throws PkgError Pkg.add(",sa..,--") end @testset "stdlibs as direct dependency" begin @@ -241,7 +241,7 @@ temp_pkg_dir() do project_path withenv("JULIA_PKG_DEVDIR" => devdir) do try Pkg.setprotocol!("notarealprotocol") - @test_throws CommandError Pkg.develop("Example") + @test_throws PkgError Pkg.develop("Example") Pkg.setprotocol!("https") Pkg.develop("Example") @test isinstalled(TEST_PKG) @@ -259,8 +259,8 @@ 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.update(nonexisting_pkg) + @test_throws PkgError Pkg.add(nonexisting_pkg) + @test_throws PkgError Pkg.update(nonexisting_pkg) end Pkg.rm(TEST_PKG.name) @@ -281,7 +281,7 @@ temp_pkg_dir() do project_path end @testset "add julia" begin - @test_throws CommandError Pkg.add("julia") + @test_throws PkgError Pkg.add("julia") end end @@ -390,9 +390,9 @@ end temp_pkg_dir() do project_path @testset "invalid repo url" begin cd(project_path) do - @test_throws CommandError Pkg.add("https://github.com") + @test_throws PkgError Pkg.add("https://github.com") Pkg.generate("FooBar") - @test_throws CommandError Pkg.add("./Foobar") + @test_throws PkgError Pkg.add("./Foobar") end end end @@ -408,7 +408,7 @@ temp_pkg_dir() do project_path Pkg.add(PackageSpec(path=package_path)) end rm(joinpath(package_path, ".git"); force=true, recursive=true) - @test_throws CommandError Pkg.update() + @test_throws PkgError Pkg.update() end end end diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 374815d0044fb..c29c5ff165a84 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -3,7 +3,7 @@ module REPLTests using Pkg -import Pkg.Types.CommandError +import Pkg.Types.PkgError using UUIDs using Test import LibGit2 @@ -25,7 +25,7 @@ function git_init_package(tmp, path) end @testset "generate args" begin - @test_throws CommandError pkg"generate" + @test_throws PkgError pkg"generate" end temp_pkg_dir() do project_path @@ -56,18 +56,18 @@ temp_pkg_dir() do project_path pkg"generate Foo" pkg"dev Foo" mv(joinpath("Foo", "src", "Foo.jl"), joinpath("Foo", "src", "Foo2.jl")) - @test_throws CommandError pkg"dev Foo" + @test_throws PkgError pkg"dev Foo" mv(joinpath("Foo", "src", "Foo2.jl"), joinpath("Foo", "src", "Foo.jl")) write(joinpath("Foo", "Project.toml"), """ name = "Foo" """ ) - @test_throws CommandError pkg"dev Foo" + @test_throws PkgError pkg"dev Foo" write(joinpath("Foo", "Project.toml"), """ uuid = "b7b78b08-812d-11e8-33cd-11188e330cbe" """ ) - @test_throws CommandError pkg"dev Foo" + @test_throws PkgError pkg"dev Foo" end end @@ -135,7 +135,7 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path #@eval import $(Symbol(pkg2)) @test Pkg.installed()[pkg2] == v"0.1.0" Pkg.REPLMode.pkgstr("free $pkg2") - @test_throws CommandError Pkg.REPLMode.pkgstr("free $pkg2") + @test_throws PkgError Pkg.REPLMode.pkgstr("free $pkg2") Pkg.test("UnregisteredWithProject") write(joinpath(p2, "Project.toml"), """ @@ -263,10 +263,10 @@ temp_pkg_dir() do project_path pkg"activate ." @test Base.active_project() == joinpath(path, "Project.toml") # tests illegal names for shared environments - @test_throws Pkg.Types.CommandError pkg"activate --shared ." - @test_throws Pkg.Types.CommandError pkg"activate --shared ./Foo" - @test_throws Pkg.Types.CommandError pkg"activate --shared Foo/Bar" - @test_throws Pkg.Types.CommandError pkg"activate --shared ../Bar" + @test_throws Pkg.Types.PkgError pkg"activate --shared ." + @test_throws Pkg.Types.PkgError pkg"activate --shared ./Foo" + @test_throws Pkg.Types.PkgError pkg"activate --shared Foo/Bar" + @test_throws Pkg.Types.PkgError pkg"activate --shared ../Bar" # check that those didn't change te enviroment @test Base.active_project() == joinpath(path, "Project.toml") mkdir("Foo") @@ -420,11 +420,14 @@ temp_pkg_dir() do project_path; cd(project_path) do pkg"build" @eval using BigProject pkg"build BigProject" - @test_throws CommandError pkg"add BigProject" - pkg"test SubModule" - pkg"test SubModule2" - pkg"test BigProject" - pkg"test" + @test_throws PkgError pkg"add BigProject" + # the command below also tests multiline input + Pkg.REPLMode.pkgstr(""" + test SubModule + test SubModule2 + test BigProject + test + """) current_json = Pkg.API.installed()["JSON"] old_project = read("Project.toml", String) open("Project.toml"; append=true) do io @@ -541,8 +544,8 @@ end pkg = Pkg.REPLMode.parse_package(path; add_or_develop=true) @test (pkg.repo.url == path) # errors - @test_throws CommandError Pkg.REPLMode.parse_package(url) - @test_throws CommandError Pkg.REPLMode.parse_package(path) + @test_throws PkgError Pkg.REPLMode.parse_package(url) + @test_throws PkgError Pkg.REPLMode.parse_package(path) end @testset "unit test for REPLMode.promptf" begin @@ -583,18 +586,18 @@ end @testset "Argument order" begin with_temp_env() do - @test_throws CommandError Pkg.REPLMode.pkgstr("add FooBar Example#foobar#foobar") - @test_throws CommandError Pkg.REPLMode.pkgstr("up Example#foobar@0.0.0") - @test_throws CommandError Pkg.REPLMode.pkgstr("pin Example@0.0.0@0.0.1") - @test_throws CommandError Pkg.REPLMode.pkgstr("up #foobar") - @test_throws CommandError Pkg.REPLMode.pkgstr("add @0.0.1") + @test_throws PkgError Pkg.REPLMode.pkgstr("add FooBar Example#foobar#foobar") + @test_throws PkgError Pkg.REPLMode.pkgstr("up Example#foobar@0.0.0") + @test_throws PkgError Pkg.REPLMode.pkgstr("pin Example@0.0.0@0.0.1") + @test_throws PkgError Pkg.REPLMode.pkgstr("up #foobar") + @test_throws PkgError Pkg.REPLMode.pkgstr("add @0.0.1") end end @testset "`do_generate!` error paths" begin with_temp_env() do - @test_throws CommandError Pkg.REPLMode.pkgstr("generate Example Example2") - @test_throws CommandError Pkg.REPLMode.pkgstr("generate") + @test_throws PkgError Pkg.REPLMode.pkgstr("generate Example Example2") + @test_throws PkgError Pkg.REPLMode.pkgstr("generate") end end @@ -670,9 +673,9 @@ end @testset "argument count errors" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("activate one two") - @test_throws CommandError Pkg.REPLMode.pkgstr("activate one two three") - @test_throws CommandError Pkg.REPLMode.pkgstr("precompile Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("activate one two") + @test_throws PkgError Pkg.REPLMode.pkgstr("activate one two three") + @test_throws PkgError Pkg.REPLMode.pkgstr("precompile Example") end end end @@ -680,8 +683,8 @@ end @testset "invalid options" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("rm --minor Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("pin --project Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("rm --minor Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("pin --project Example") end end end @@ -689,11 +692,11 @@ end @testset "Argument order" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("add FooBar Example#foobar#foobar") - @test_throws CommandError Pkg.REPLMode.pkgstr("up Example#foobar@0.0.0") - @test_throws CommandError Pkg.REPLMode.pkgstr("pin Example@0.0.0@0.0.1") - @test_throws CommandError Pkg.REPLMode.pkgstr("up #foobar") - @test_throws CommandError Pkg.REPLMode.pkgstr("add @0.0.1") + @test_throws PkgError Pkg.REPLMode.pkgstr("add FooBar Example#foobar#foobar") + @test_throws PkgError Pkg.REPLMode.pkgstr("up Example#foobar@0.0.0") + @test_throws PkgError Pkg.REPLMode.pkgstr("pin Example@0.0.0@0.0.1") + @test_throws PkgError Pkg.REPLMode.pkgstr("up #foobar") + @test_throws PkgError Pkg.REPLMode.pkgstr("add @0.0.1") end end end @@ -701,8 +704,8 @@ end @testset "conflicting options" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("up --major --minor") - @test_throws CommandError Pkg.REPLMode.pkgstr("rm --project --manifest") + @test_throws PkgError Pkg.REPLMode.pkgstr("up --major --minor") + @test_throws PkgError Pkg.REPLMode.pkgstr("rm --project --manifest") end end end @@ -710,9 +713,9 @@ end @testset "gc" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("gc --project") - @test_throws CommandError Pkg.REPLMode.pkgstr("gc --minor") - @test_throws CommandError Pkg.REPLMode.pkgstr("gc Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("gc --project") + @test_throws PkgError Pkg.REPLMode.pkgstr("gc --minor") + @test_throws PkgError Pkg.REPLMode.pkgstr("gc Example") Pkg.REPLMode.pkgstr("gc") end end @@ -721,8 +724,8 @@ end @testset "precompile" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("precompile --project") - @test_throws CommandError Pkg.REPLMode.pkgstr("precompile Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("precompile --project") + @test_throws PkgError Pkg.REPLMode.pkgstr("precompile Example") Pkg.REPLMode.pkgstr("precompile") end end @@ -731,9 +734,9 @@ end @testset "generate" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("generate --major Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("generate --foobar Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("generate Example1 Example2") + @test_throws PkgError Pkg.REPLMode.pkgstr("generate --major Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("generate --foobar Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("generate Example1 Example2") Pkg.REPLMode.pkgstr("generate Example") end end @@ -743,7 +746,7 @@ end @testset "test" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; Pkg.add("Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("test --project Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("test --project Example") Pkg.REPLMode.pkgstr("test --coverage Example") Pkg.REPLMode.pkgstr("test Example") end @@ -753,8 +756,8 @@ end @testset "build" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("build --project") - @test_throws CommandError Pkg.REPLMode.pkgstr("build --minor") + @test_throws PkgError Pkg.REPLMode.pkgstr("build --project") + @test_throws PkgError Pkg.REPLMode.pkgstr("build --minor") end end end @@ -762,8 +765,8 @@ end @testset "free" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError Pkg.REPLMode.pkgstr("free --project") - @test_throws CommandError Pkg.REPLMode.pkgstr("free --major") + @test_throws PkgError Pkg.REPLMode.pkgstr("free --project") + @test_throws PkgError Pkg.REPLMode.pkgstr("free --major") end end end @@ -784,8 +787,8 @@ end groups = Pkg.REPLMode.group_words(["a", "b", "c", ";", "a", "b", ";"]) @test length(groups) == 2 # errors - @test_throws CommandError Pkg.REPLMode.group_words(["a", "b", ";", ";", "a", "b"]) - @test_throws CommandError Pkg.REPLMode.group_words([";", "add", "Example"]) + @test_throws PkgError Pkg.REPLMode.group_words(["a", "b", ";", ";", "a", "b"]) + @test_throws PkgError Pkg.REPLMode.group_words([";", "add", "Example"]) end @testset "tests for api opts" begin @@ -825,11 +828,11 @@ end @testset "meta option errors" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; # unregistered meta options - @test_throws CommandError Pkg.REPLMode.pkgstr("--foo=foo add Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("--bar add Example") - @test_throws CommandError Pkg.REPLMode.pkgstr("-x add Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("--foo=foo add Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("--bar add Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("-x add Example") # malformed, but registered meta option - @test_throws CommandError Pkg.REPLMode.pkgstr("--env Example") + @test_throws PkgError Pkg.REPLMode.pkgstr("--env Example") end end end @@ -868,15 +871,15 @@ end @test qwords[2].word == " forget to " @test qwords[3].isquoted @test qwords[3].word == "\"test\"" - @test_throws CommandError Pkg.REPLMode.parse_quotes("Don't") - @test_throws CommandError Pkg.REPLMode.parse_quotes("Unterminated \"quot") + @test_throws PkgError Pkg.REPLMode.parse_quotes("Don't") + @test_throws PkgError Pkg.REPLMode.parse_quotes("Unterminated \"quot") end @testset "argument kinds" begin temp_pkg_dir() do project_path; cd_tempdir() do tmpdir; with_temp_env() do; - @test_throws CommandError pkg"pin Example#foo" - @test_throws CommandError pkg"test Example#foo" - @test_throws CommandError pkg"test Example@v0.0.1" + @test_throws PkgError pkg"pin Example#foo" + @test_throws PkgError pkg"test Example#foo" + @test_throws PkgError pkg"test Example@v0.0.1" end end end diff --git a/stdlib/Pkg/test/resolve.jl b/stdlib/Pkg/test/resolve.jl index 20c919d8ef62e..8bfd55010b76b 100644 --- a/stdlib/Pkg/test/resolve.jl +++ b/stdlib/Pkg/test/resolve.jl @@ -54,7 +54,7 @@ function load_package_data_raw(T::Type, input::String) for (v, d) in toml, (key, value) in d vr = VersionRange(v) dict = get!(data, vr, Dict{String,T}()) - haskey(dict, key) && cmderror("$ver/$key is duplicated in $path") + haskey(dict, key) && pkgerror("$ver/$key is duplicated in $path") dict[key] = T(value) end return data From d7381349d3204ebc8081d40816ec3f28d5dbbb54 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 02:15:30 +0200 Subject: [PATCH 18/22] only look for Project files in installed (#539) --- stdlib/Pkg/docs/src/index.md | 3 --- stdlib/Pkg/src/API.jl | 3 ++- stdlib/Pkg/src/REPLMode.jl | 2 +- stdlib/Pkg/test/pkg.jl | 32 ++++++++++++++--------------- stdlib/Pkg/test/repl.jl | 40 +++++++++++++++--------------------- 5 files changed, 36 insertions(+), 44 deletions(-) diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index 571f4f157a81a..34c8a570aae97 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -1,8 +1,5 @@ # Pkg -!!! warning - This documentation is a work in progress and the information in it might be or become outdated. - ## Introduction Pkg is the standard package manager for Julia 1.0 and newer. Unlike traditional diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 09d807b0e0a74..76d067cce29c8 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -253,7 +253,8 @@ function test(ctx::Context, pkgs::Vector{PackageSpec}; coverage=false, kwargs... end -function installed(mode::PackageMode=PKGMODE_MANIFEST) +installed() = __installed(PKGMODE_PROJECT) +function __installed(mode::PackageMode=PKGMODE_MANIFEST) diffs = Display.status(Context(), mode, #=use_as_api=# true) version_status = Dict{String, Union{VersionNumber,Nothing}}() diffs == nothing && return version_status diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 39366bc5a207c..6d18bca325a59 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -699,7 +699,7 @@ function complete_package(s, i1, i2, lastcommand, project_opt) end function complete_installed_package(s, i1, i2, project_opt) - pkgs = project_opt ? API.installed(PKGMODE_PROJECT) : API.installed() + pkgs = project_opt ? API.__installed(PKGMODE_PROJECT) : API.__installed() pkgs = sort!(collect(keys(filter((p) -> p[2] != nothing, pkgs)))) cmp = filter(cmd -> startswith(cmd, s), pkgs) return cmp, i1:i2, !isempty(cmp) diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 92aac84606b37..00f846619d5f9 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -136,18 +136,18 @@ temp_pkg_dir() do project_path @testset "adding and upgrading different versions" begin # VersionNumber Pkg.add(PackageSpec(TEST_PKG.name, v"0.3")) - @test Pkg.installed()[TEST_PKG.name] == v"0.3" + @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3" Pkg.add(PackageSpec(TEST_PKG.name, v"0.3.1")) - @test Pkg.installed()[TEST_PKG.name] == v"0.3.1" + @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.1" Pkg.rm(TEST_PKG.name) # 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" + @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.2" Pkg.update(; level = UPLEVEL_PATCH) - @test Pkg.installed()[TEST_PKG.name] == v"0.3.3" + @test Pkg.API.__installed()[TEST_PKG.name] == v"0.3.3" Pkg.update(; level = UPLEVEL_MINOR) - @test Pkg.installed()[TEST_PKG.name].minor != 3 + @test Pkg.API.__installed()[TEST_PKG.name].minor != 3 Pkg.rm(TEST_PKG.name) end @@ -164,26 +164,26 @@ temp_pkg_dir() do project_path @testset "pinning / freeing" begin Pkg.add(TEST_PKG.name) - old_v = Pkg.installed()[TEST_PKG.name] + old_v = Pkg.API.__installed()[TEST_PKG.name] Pkg.pin(PackageSpec(TEST_PKG.name, v"0.2")) - @test Pkg.installed()[TEST_PKG.name].minor == 2 + @test Pkg.API.__installed()[TEST_PKG.name].minor == 2 Pkg.update(TEST_PKG.name) - @test Pkg.installed()[TEST_PKG.name].minor == 2 + @test Pkg.API.__installed()[TEST_PKG.name].minor == 2 Pkg.free(TEST_PKG.name) Pkg.update() - @test Pkg.installed()[TEST_PKG.name] == old_v + @test Pkg.API.__installed()[TEST_PKG.name] == old_v Pkg.rm(TEST_PKG.name) end @testset "develop / freeing" begin Pkg.add(TEST_PKG.name) - old_v = Pkg.installed()[TEST_PKG.name] + old_v = Pkg.API.__installed()[TEST_PKG.name] Pkg.rm(TEST_PKG.name) mktempdir() do devdir withenv("JULIA_PKG_DEVDIR" => devdir) do Pkg.develop(TEST_PKG.name) @test isinstalled(TEST_PKG) - @test Pkg.installed()[TEST_PKG.name] > old_v + @test Pkg.API.__installed()[TEST_PKG.name] > old_v test_pkg_main_file = joinpath(devdir, TEST_PKG.name, "src", TEST_PKG.name * ".jl") @test isfile(test_pkg_main_file) # Pkg #152 @@ -209,7 +209,7 @@ temp_pkg_dir() do project_path @test isfile(joinpath(devdir, TEST_PKG.name, "deps", "deps.jl")) Pkg.test(TEST_PKG.name) Pkg.free(TEST_PKG.name) - @test Pkg.installed()[TEST_PKG.name] == old_v + @test Pkg.API.__installed()[TEST_PKG.name] == old_v end end end @@ -221,7 +221,7 @@ temp_pkg_dir() do project_path @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) + @test haskey(Pkg.API.__installed(), uuid_pkg.name) Pkg.update() # Disable until fixed in Base # Pkg.test("CRC32c") @@ -298,7 +298,7 @@ temp_pkg_dir() do project_path cd(joinpath(dir, "UnregisteredWithProject")) do with_current_env() do Pkg.update() - @test haskey(Pkg.installed(), "Example") + @test haskey(Pkg.API.__installed(), "Example") end end end @@ -308,12 +308,12 @@ end temp_pkg_dir() do project_path @testset "libgit2 downloads" begin Pkg.add(TEST_PKG.name; use_libgit2_for_all_downloads=true) - @test haskey(Pkg.installed(), TEST_PKG.name) + @test haskey(Pkg.API.__installed(), TEST_PKG.name) Pkg.rm(TEST_PKG.name) end @testset "tarball downloads" begin Pkg.add("JSON"; use_only_tarballs_for_downloads=true) - @test haskey(Pkg.installed(), "JSON") + @test haskey(Pkg.API.__installed(), "JSON") Pkg.rm("JSON") end end diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index c29c5ff165a84..600e11db3d049 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -103,7 +103,7 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path pkg"activate ." pkg"add Example" @test isinstalled(TEST_PKG) - v = Pkg.installed()[TEST_PKG.name] + v = Pkg.API.__installed()[TEST_PKG.name] pkg"rm Example" pkg"add Example#master" @@ -117,12 +117,12 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path pkg"test Example" @test isinstalled(TEST_PKG) - @test Pkg.installed()[TEST_PKG.name] > v + @test Pkg.API.__installed()[TEST_PKG.name] > v pkg = "UnregisteredWithoutProject" p = git_init_package(tmp_pkg_path, joinpath(@__DIR__, "test_packages/$pkg")) Pkg.REPLMode.pkgstr("add $p; precompile") @eval import $(Symbol(pkg)) - @test Pkg.installed()[pkg] == v"0.0" + @test Pkg.API.__installed()[pkg] == v"0.0" Pkg.test("UnregisteredWithoutProject") pkg2 = "UnregisteredWithProject" @@ -133,7 +133,7 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path # FIXME: why isn't this testing the Pkg after importing, rather than after freeing it #@eval import Example #@eval import $(Symbol(pkg2)) - @test Pkg.installed()[pkg2] == v"0.1.0" + @test Pkg.API.__installed()[pkg2] == v"0.1.0" Pkg.REPLMode.pkgstr("free $pkg2") @test_throws PkgError Pkg.REPLMode.pkgstr("free $pkg2") Pkg.test("UnregisteredWithProject") @@ -148,7 +148,7 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path LibGit2.add!(repo, "*") LibGit2.commit(repo, "bump version"; author = TEST_SIG, committer=TEST_SIG) pkg"update" - @test Pkg.installed()[pkg2] == v"0.2.0" + @test Pkg.API.__installed()[pkg2] == v"0.2.0" Pkg.REPLMode.pkgstr("rm $pkg2") c = LibGit2.commit(repo, "empty commit"; author = TEST_SIG, committer=TEST_SIG) @@ -173,7 +173,7 @@ temp_pkg_dir() do project_path; cd(project_path) do; mktempdir() do tmp_pkg_path mktempdir() do depot_dir pushfirst!(DEPOT_PATH, depot_dir) pkg"instantiate" - @test Pkg.installed()[pkg2] == v"0.2.0" + @test Pkg.API.__installed()[pkg2] == v"0.2.0" end finally empty!(DEPOT_PATH) @@ -207,8 +207,8 @@ temp_pkg_dir() do project_path; cd(project_path) do Pkg.REPLMode.pkgstr("build; precompile") @test Base.find_package("UnregisteredWithProject") == joinpath(p1_new_path, "src", "UnregisteredWithProject.jl") @test Base.find_package("UnregisteredWithoutProject") == joinpath(p2_new_path, "src", "UnregisteredWithoutProject.jl") - @test Pkg.installed()["UnregisteredWithProject"] == v"0.1.0" - @test Pkg.installed()["UnregisteredWithoutProject"] == v"0.0.0" + @test Pkg.API.__installed()["UnregisteredWithProject"] == v"0.1.0" + @test Pkg.API.__installed()["UnregisteredWithoutProject"] == v"0.0.0" Pkg.test("UnregisteredWithoutProject") Pkg.test("UnregisteredWithProject") @@ -235,8 +235,8 @@ temp_pkg_dir() do project_path; cd(project_path) do mkdir("tests") cd("tests") pkg"develop ../SubModule2" - @test Pkg.installed()["SubModule1"] == v"0.1.0" - @test Pkg.installed()["SubModule2"] == v"0.1.0" + @test Pkg.API.__installed()["SubModule1"] == v"0.1.0" + @test Pkg.API.__installed()["SubModule2"] == v"0.1.0" # make sure paths to SubModule1 and SubModule2 are relative manifest = Pkg.Types.Context().env.manifest @test manifest["SubModule1"][1]["path"] == "SubModule1" @@ -454,7 +454,9 @@ temp_pkg_dir() do project_path setup_package(parent_dir, pkg_name) = begin mkdir(parent_dir) cd(parent_dir) do - Pkg.generate(pkg_name) + withenv("USER" => "Test User") do + Pkg.generate(pkg_name) + end cd(pkg_name) do LibGit2.with(LibGit2.init(joinpath(project_path, parent_dir, pkg_name))) do repo LibGit2.add!(repo, "*") @@ -833,9 +835,7 @@ end @test_throws PkgError Pkg.REPLMode.pkgstr("-x add Example") # malformed, but registered meta option @test_throws PkgError Pkg.REPLMode.pkgstr("--env Example") - end - end - end + end end end end @testset "activate" begin @@ -847,9 +847,7 @@ end @test Base.active_project() == joinpath(pwd(), "Foo", "Project.toml") pkg"activate" @test Base.active_project() == default - end - end - end + end end end end @testset "subcommands" begin @@ -858,9 +856,7 @@ end @test isinstalled(TEST_PKG) Pkg.REPLMode.pkg"package rm Example" @test !isinstalled(TEST_PKG) - end - end - end + end end end end @testset "`parse_quotes` unit tests" begin @@ -880,9 +876,7 @@ end @test_throws PkgError pkg"pin Example#foo" @test_throws PkgError pkg"test Example#foo" @test_throws PkgError pkg"test Example@v0.0.1" - end - end - end + end end end end end # module From 43a0285191e77b7859b7571743a5d5c045a3ad5a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 11:37:32 +0200 Subject: [PATCH 19/22] remove ability to give a git revision to devved packages (#581) * remove ability to give a git revision to devved packages * wip --- stdlib/Pkg/docs/src/index.md | 6 +++--- stdlib/Pkg/src/API.jl | 7 ++++++- stdlib/Pkg/src/REPLMode.jl | 5 ++++- stdlib/Pkg/src/Types.jl | 11 ++++------- stdlib/Pkg/test/pkg.jl | 1 + stdlib/Pkg/test/repl.jl | 15 +-------------- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/stdlib/Pkg/docs/src/index.md b/stdlib/Pkg/docs/src/index.md index 34c8a570aae97..e905a126fc195 100644 --- a/stdlib/Pkg/docs/src/index.md +++ b/stdlib/Pkg/docs/src/index.md @@ -347,13 +347,13 @@ If we try to `dev` a package at some branch that already exists at `~/.julia/dev For example: ``` -(v0.7) pkg> dev Example#master +(v0.7) pkg> dev Example Updating git-repo `https://github.com/JuliaLang/Example.jl.git` [ Info: Path `/Users/kristoffer/.julia/dev/Example` exists and looks like the correct package, using existing path instead of cloning ``` -Note the info message saying that it is using the existing path. This means that you cannot use `dev` to e.g. change branches of -an already developed package. +Note the info message saying that it is using the existing path. As a general rule, the package manager will +never touch files that are tracking a path. If `dev` is used on a local path, that path to that package is recorded and used when loading that package. The path will be recorded relative to the project file, unless it is given as an absolute path. diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index 76d067cce29c8..a4cc2a363f682 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -33,7 +33,12 @@ function add_or_develop(ctx::Context, pkgs::Vector{PackageSpec}; mode::Symbol, s # 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()) + if mode == :develop + pkg.repo == nothing && (pkg.repo = Types.GitRepo()) + if !isempty(pkg.repo.rev) + pkgerror("git revision cannot be given to `develop`") + end + end end # if julia is passed as a package the solver gets tricked; diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index 6d18bca325a59..e3803371282b9 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -397,6 +397,9 @@ function package_args(args::Vector{Token}, spec::CommandSpec)::Vector{PackageSpe elseif arg isa VersionRange pkgs[end].version = arg elseif arg isa Rev + if spec.kind == CMD_DEVELOP + pkgerror("a git revision cannot be given to `develop`") + end pkg = pkgs[end] if pkg.repo == nothing pkg.repo = Types.GitRepo("", arg.rev) @@ -1025,7 +1028,7 @@ pkg> add Example=7876af07-990d-54b4-ab0e-23690620f79a ("shared", OPT_SWITCH, :shared => true), ], md""" - develop [--shared|--local] pkg[=uuid] [#rev] ... + develop [--shared|--local] pkg[=uuid] ... Make a package available for development. If `pkg` is an existing local path that path will be recorded in the manifest and used. Otherwise, a full git clone of `pkg` at rev `rev` is made. The location of the clone is diff --git a/stdlib/Pkg/src/Types.jl b/stdlib/Pkg/src/Types.jl index b867186ef89ad..fcda7988b676f 100644 --- a/stdlib/Pkg/src/Types.jl +++ b/stdlib/Pkg/src/Types.jl @@ -545,13 +545,10 @@ function handle_repos_develop!(ctx::Context, pkgs::AbstractVector{PackageSpec}, project_path = mktempdir() cp(repo_path, project_path; force=true) LibGit2.with(LibGit2.GitRepo(project_path)) do repo - rev = pkg.repo.rev - if isempty(rev) - if LibGit2.isattached(repo) - rev = LibGit2.branch(repo) - else - rev = string(LibGit2.GitHash(LibGit2.head(repo))) - end + if LibGit2.isattached(repo) + rev = LibGit2.branch(repo) + else + rev = string(LibGit2.GitHash(LibGit2.head(repo))) end gitobject, isbranch = get_object_branch(repo, rev) try diff --git a/stdlib/Pkg/test/pkg.jl b/stdlib/Pkg/test/pkg.jl index 00f846619d5f9..32e1f8d18bb5c 100644 --- a/stdlib/Pkg/test/pkg.jl +++ b/stdlib/Pkg/test/pkg.jl @@ -181,6 +181,7 @@ temp_pkg_dir() do project_path Pkg.rm(TEST_PKG.name) mktempdir() do devdir withenv("JULIA_PKG_DEVDIR" => devdir) do + @test_throws PkgError Pkg.develop(PackageSpec(url="bleh", rev="blurg")) Pkg.develop(TEST_PKG.name) @test isinstalled(TEST_PKG) @test Pkg.API.__installed()[TEST_PKG.name] > old_v diff --git a/stdlib/Pkg/test/repl.jl b/stdlib/Pkg/test/repl.jl index 600e11db3d049..20ebc5395c64c 100644 --- a/stdlib/Pkg/test/repl.jl +++ b/stdlib/Pkg/test/repl.jl @@ -42,16 +42,7 @@ temp_pkg_dir() do project_path Pkg.test("PackageWithBuildSpecificTestDeps") end - pkg"dev Example" - devdir = joinpath(DEPOT_PATH[1], "dev", "Example") - @test isdir(devdir) - rm(devdir; recursive=true) - @test !isdir(devdir) - pkg"dev Example#DO_NOT_REMOVE" - @test isdir(devdir) - LibGit2.with(LibGit2.GitRepo(devdir)) do repo - @test LibGit2.branch(repo) == "DO_NOT_REMOVE" - end + @test_throws PkgError pkg"dev Example#blergh" pkg"generate Foo" pkg"dev Foo" @@ -211,10 +202,6 @@ temp_pkg_dir() do project_path; cd(project_path) do @test Pkg.API.__installed()["UnregisteredWithoutProject"] == v"0.0.0" Pkg.test("UnregisteredWithoutProject") Pkg.test("UnregisteredWithProject") - - pkg"develop Example#c37b675" - @test Base.find_package("Example") == joinpath(tmp, "Example", "src", "Example.jl") - Pkg.test("Example") end finally empty!(DEPOT_PATH) From afbba1a5537fe5840a47d90008673ac35505accd Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 11:11:09 +0200 Subject: [PATCH 20/22] update precompilation for Pkg --- contrib/generate_precompile.jl | 19 +- stdlib/Pkg/src/Pkg.jl | 29 ++- stdlib/Pkg/src/precompile.jl | 423 ++++++++++++++++++++++++++++++--- 3 files changed, 417 insertions(+), 54 deletions(-) diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 30aaa085d568c..67885582754f8 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -35,19 +35,12 @@ cd("complet_path\t\t$CTRL_C julia_cmd() = (julia = joinpath(Sys.BINDIR, Base.julia_exename()); `$julia`) have_repl = haskey(Base.loaded_modules, Base.PkgId(Base.UUID("3fa0cd96-eef1-5676-8a61-b3b8758bbffb"), "REPL")) -have_pkg = haskey(Base.loaded_modules, - Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg")) - -if have_pkg - precompile_script *= """ - tmp = mktempdir() - cd(tmp) - touch("Project.toml") - ] activate . - st - $CTRL_C - rm(tmp; recursive=true) - """ +Pkg = get(Base.loaded_modules, + Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg"), + nothing) + +if Pkg !== nothing + precompile_script *= Pkg.precompile_script end function generate_precompile_statements() diff --git a/stdlib/Pkg/src/Pkg.jl b/stdlib/Pkg/src/Pkg.jl index e1551c0e0369e..f5e34961758e0 100644 --- a/stdlib/Pkg/src/Pkg.jl +++ b/stdlib/Pkg/src/Pkg.jl @@ -14,7 +14,7 @@ export UpgradeLevel, UPLEVEL_MAJOR, UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH depots() = Base.DEPOT_PATH function depots1() d = depots() - isempty(d) && pkgerror("no depots found in DEPOT_PATH") + isempty(d) && Pkg.Types.pkgerror("no depots found in DEPOT_PATH") return d[1] end @@ -42,6 +42,7 @@ import .REPLMode: @pkg_str import .Types: UPLEVEL_MAJOR, UPLEVEL_MINOR, UPLEVEL_PATCH, UPLEVEL_FIXED import .Types: PKGMODE_MANIFEST, PKGMODE_PROJECT + """ PackageMode @@ -347,6 +348,30 @@ function __init__() 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 + ] st + $CTRL_C + rm(tmp; recursive=true)""" + module PrecompileArea import ..Pkg using ..Types @@ -357,6 +382,4 @@ module PrecompileArea include("precompile.jl") end -METADATA_compatible_uuid(pkg::String) = Types.uuid5(Types.uuid_package, pkg) - end # module diff --git a/stdlib/Pkg/src/precompile.jl b/stdlib/Pkg/src/precompile.jl index b6f5c152b3d0a..75b1b05e48827 100644 --- a/stdlib/Pkg/src/precompile.jl +++ b/stdlib/Pkg/src/precompile.jl @@ -1,82 +1,429 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - +precompile(Tuple{Type{Base.Dict{K, V} where V where K}, Array{Base.Pair{A, B} where B where A, 1}}) +precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}}}) +precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}}}) +precompile(Tuple{Type{Base.Dict{String, Any}}, Base.Pair{String, String}}) +precompile(Tuple{Type{Base.Dict{String, Base.UUID}}}) +precompile(Tuple{Type{Base.Dict{String, Pkg.Types.VersionSpec}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, String}}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Base.close), Array{LibGit2.GitAnnotated, 1}}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Pkg.TOML.is_tabular), Base.ValueIterator{Base.Dict{String, Any}}}) precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Pkg.TOML.table2dict), Array{Any, 1}}) precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.TTY}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.UUID, Int64}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.UUID, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Base.VersionNumber, Base.SHA1}) +precompile(Tuple{Type{Base.Pair{A, B} where B where A}, String, Base.UUID}) precompile(Tuple{Type{Base.SHA1}, Base.SubString{String}}) precompile(Tuple{Type{Base.SHA1}, String}) -precompile(Tuple{Type{NamedTuple{(:env,), Tuple{Pkg.Types.EnvCache}}}, Tuple{Pkg.Types.EnvCache}}) -precompile(Tuple{Type{Pkg.Display.DiffEntry}, Base.UUID, String, Nothing, Pkg.Display.VerInfo}) +precompile(Tuple{Type{Char}, Int32}) +precompile(Tuple{Type{NamedTuple{(:by,), T} where T<:Tuple}, Tuple{typeof(Base.identity)}}) +precompile(Tuple{Type{NamedTuple{(:header, :color), T} where T<:Tuple}, Tuple{String, Symbol}}) +precompile(Tuple{Type{NamedTuple{(:indent, :region_active), T} where T<:Tuple}, Tuple{Int64, Bool}}) +precompile(Tuple{Type{NamedTuple{(:indent, :sorted, :by), T} where T<:Tuple}, Tuple{Int64, Bool, typeof(Base.identity)}}) +precompile(Tuple{Type{NamedTuple{(:init,), T} where T<:Tuple}, Tuple{Int64}}) +precompile(Tuple{Type{NamedTuple{(:mode,), T} where T<:Tuple}, Tuple{Symbol}}) +precompile(Tuple{Type{NamedTuple{(:transfer_progress, :credentials), T} where T<:Tuple}, Tuple{Ptr{Nothing}, Ptr{Nothing}}}) +precompile(Tuple{Type{Pkg.Display.DiffEntry}, Base.UUID, String, Pkg.Display.VerInfo, Pkg.Display.VerInfo}) precompile(Tuple{Type{Pkg.Display.VerInfo}, Base.SHA1, Nothing, Base.VersionNumber, Bool, Nothing}) precompile(Tuple{Type{Pkg.Display.VerInfo}, Base.SHA1, Nothing, Base.VersionNumber, Bool, Pkg.Types.GitRepo}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Nothing, Nothing, Nothing, Bool, Nothing}) +precompile(Tuple{Type{Pkg.Display.VerInfo}, Nothing, String, Base.VersionNumber, Bool, Nothing}) +precompile(Tuple{Type{Pkg.Types.EnvCache}, Nothing, Nothing, String, String, Nothing, Base.Dict{String, Any}, Base.Dict{String, Any}, Base.Dict{String, Array{Base.UUID, 1}}, Base.Dict{Base.UUID, Array{String, 1}}, Base.Dict{Base.UUID, Array{String, 1}}}) +precompile(Tuple{Type{Pkg.Types.GitRepo}, String, String, Base.SHA1}) precompile(Tuple{Type{Pkg.Types.GitRepo}, String, String}) -precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:env,), Tuple{Pkg.Types.EnvCache}}, Type{Pkg.Types.Context}}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, Base.SubString{String}, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, Base.SubString{String}}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, String, Base.UUID, Pkg.Types.VersionSpec}) +precompile(Tuple{Type{Pkg.Types.PackageSpec}, String}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Base.SubString{String}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Int64, Int64}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{Int64, Int64, Int64}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{Int64, Int64}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, Tuple{UInt32, UInt32}}) +precompile(Tuple{Type{Pkg.Types.VersionBound}, UInt32, UInt32}) +precompile(Tuple{Type{Pkg.Types.VersionRange}, Base.VersionNumber}) +precompile(Tuple{Type{Pkg.Types.VersionSpec}, String}) +precompile(Tuple{Type{REPL.LineEdit.PrefixSearchState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixHistoryPrompt, String, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{Type{REPL.LineEdit.PromptState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.Prompt, Base.GenericIOBuffer{Array{UInt8, 1}}, Symbol, Array{Base.GenericIOBuffer{Array{UInt8, 1}}, 1}, Int64, REPL.LineEdit.InputAreaState, Int64, Base.Threads.TatasLock, Float64}) +precompile(Tuple{Type{REPL.LineEdit.SearchState}, REPL.Terminals.TTYTerminal, REPL.LineEdit.HistoryPrompt, Bool, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.GenericIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{Type{REPL.REPLHistoryProvider}, Array{String, 1}, Nothing, Int64, Int64, Int64, Base.GenericIOBuffer{Array{UInt8, 1}}, Nothing, Base.Dict{Symbol, Any}, Array{UInt8, 1}}) +precompile(Tuple{Type{REPL.REPLHistoryProvider}, Base.Dict{Symbol, Any}}) +precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), Base.TTY, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##sort!")), NamedTuple{(:by,), Tuple{typeof(Base.Unicode.lowercase)}}, typeof(Base.sort!), Array{String, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##sort!")), NamedTuple{(:by,), Tuple{typeof(Base.identity)}}, typeof(Base.sort!), Array{String, 1}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nloops")), LineNumberNode, Module, Int64, Symbol, Expr, Expr, Expr}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:header, :color), Tuple{String, Symbol}}, Type{Pkg.GitTools.MiniProgressBar}}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:payload, :transfer_progress, :credentials), Tuple{Base.Dict{Symbol, Any}, Ptr{Nothing}, Ptr{Nothing}}}, Type{LibGit2.RemoteCallbacks}}) +precompile(Tuple{getfield(Pkg.API, Symbol("#kw##add_or_develop")), NamedTuple{(:mode,), Tuple{Symbol}}, typeof(Pkg.API.add_or_develop), Pkg.Types.Context, Array{Pkg.Types.PackageSpec, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##_print")), NamedTuple{(:indent, :sorted, :by), Tuple{Int64, Bool, typeof(Base.identity)}}, typeof(Pkg.TOML._print), Base.IOStream, Base.Dict{String, Any}, Array{String, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##print")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.print), Base.IOStream, Base.Dict{String, Any}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##printvalue")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.printvalue), Base.IOStream, Array{String, 1}}) +precompile(Tuple{getfield(Pkg.TOML, Symbol("#kw##printvalue")), NamedTuple{(:sorted,), Tuple{Bool}}, typeof(Pkg.TOML.printvalue), Base.IOStream, String}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##add_nested_key!")), NamedTuple{(:override,), Tuple{Bool}}, typeof(REPL.LineEdit.add_nested_key!), Base.Dict{Char, Any}, String, Nothing}) +precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##refresh_multi_line")), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, Base.GenericIOBuffer{Array{UInt8, 1}}, REPL.LineEdit.InputAreaState, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.:(!=)), Base.SubString{String}, Nothing}) +precompile(Tuple{typeof(Base.:(!=)), Base.UUID, Base.UUID}) +precompile(Tuple{typeof(Base.:(==)), Base.Dict{String, Any}, Nothing}) precompile(Tuple{typeof(Base.:(==)), Base.SHA1, Nothing}) precompile(Tuple{typeof(Base.:(==)), Base.UUID, Base.UUID}) +precompile(Tuple{typeof(Base.:(==)), Expr, Int64}) precompile(Tuple{typeof(Base.:(==)), Nothing, Base.UUID}) precompile(Tuple{typeof(Base.:(==)), Nothing, Nothing}) -precompile(Tuple{typeof(Base.:(==)), Pkg.REPLMode.CommandKind, Pkg.REPLMode.CommandKind}) precompile(Tuple{typeof(Base.:(==)), String, Nothing}) -precompile(Tuple{typeof(Base.append!), Array{String, 1}, Array{Base.SubString{String}, 1}}) +precompile(Tuple{typeof(Base.:(==)), Symbol, Int64}) +precompile(Tuple{typeof(Base.Cartesian._nloops), Int64, Symbol, Expr, Expr, Expr}) +precompile(Tuple{typeof(Base.Cartesian.exprresolve), LineNumberNode}) +precompile(Tuple{typeof(Base.Cartesian.lreplace!), Int64, Base.Cartesian.LReplace{String}}) +precompile(Tuple{typeof(Base.Filesystem.ispath), String}) +precompile(Tuple{typeof(Base.Filesystem.mtime), String}) +precompile(Tuple{typeof(Base.Iterators.enumerate), Array{Base.VersionNumber, 1}}) +precompile(Tuple{typeof(Base._array_for), Type{Array{Base.BitArray{2}, 1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Array{Base.VersionNumber, 1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.BitArray{1}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.BitArray{2}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.Dict{Base.VersionNumber, Int64}}, Base.UnitRange{Int64}, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._array_for), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}, Base.HasLength}) +precompile(Tuple{typeof(Base._collect), Array{Pkg.REPLMode.Statement, 1}, Base.Generator{Array{Pkg.REPLMode.Statement, 1}, Type{Pkg.REPLMode.PkgCommand}}, Base.EltypeUnknown, Base.HasShape{1}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Array{String, 1}, LibGit2.CachedCredentials}}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Bool, LibGit2.CachedCredentials}}}) +precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Int32, Base.Cstring, Ptr{Nothing}}}}) +precompile(Tuple{typeof(Base._deepcopy_array_t), Array{Base.Dict{String, Any}, 1}, Type{Base.Dict{String, Any}}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base._getindex), Base.IndexLinear, Base.BitArray{2}, Base.LogicalIndex{Int64, Base.BitArray{1}}, Int64}) +precompile(Tuple{typeof(Base._iterate), Base.Dict{String, Any}, Int64}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Any}, Type{Ptr{Nothing}}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Array{String, 1}}, Type{LibGit2.CachedCredentials}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Bool}, Type{LibGit2.CachedCredentials}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Int32}, Type{Base.Cstring}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Array{String, 1}}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Bool}}) +precompile(Tuple{typeof(Base._promote_typejoin), Type{Union{}}, Type{Int32}}) +precompile(Tuple{typeof(Base._shrink), typeof(Base.setdiff!), Array{Base.UUID, 1}, Tuple{Array{Base.UUID, 1}}}) +precompile(Tuple{typeof(Base.add_sum), Int64, Int64}) +precompile(Tuple{typeof(Base.afoldl), typeof(Base.:(+)), Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.all), Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, typeof(Pkg.TOML.is_tabular)}}) +precompile(Tuple{typeof(Base.close), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.close), LibGit2.GitAnnotated}) +precompile(Tuple{typeof(Base.close), LibGit2.GitConfig}) +precompile(Tuple{typeof(Base.close), LibGit2.GitDiff}) +precompile(Tuple{typeof(Base.close), LibGit2.GitReference}) +precompile(Tuple{typeof(Base.close), LibGit2.GitRemote}) precompile(Tuple{typeof(Base.close), LibGit2.GitRepo}) +precompile(Tuple{typeof(Base.close), LibGit2.GitTree}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{Base.Cmd}}}) precompile(Tuple{typeof(Base.collect), Base.Generator{Array{Any, 1}, typeof(Pkg.TOML.table2dict)}}) +precompile(Tuple{typeof(Base.collect), Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, Type{Base.UUID}}}) +precompile(Tuple{typeof(Base.collect), Base.Generator{Base.ValueIterator{Base.Dict{String, String}}, Type{Base.UUID}}}) +precompile(Tuple{typeof(Base.collect), Base.KeySet{String, Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.collect_similar), Array{LibGit2.GitAnnotated, 1}, Base.Generator{Array{LibGit2.GitAnnotated, 1}, typeof(Base.close)}}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{Base.UUID, 1}, Base.UUID, Base.Generator{Base.ValueIterator{Base.Dict{String, Any}}, Type{Base.UUID}}, Int64}) +precompile(Tuple{typeof(Base.collect_to_with_first!), Array{String, 1}, String, Base.Generator{Array{String, 1}, typeof(Pkg.REPLMode.word2token)}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Base.BitArray{2}, 1}, 1}}, Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Base.VersionNumber, 1}, 1}}, Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Array{Int64, 1}, 1}}, Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.BitArray{1}, 1}}, Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.Dict{Base.VersionNumber, Int64}, 1}}, Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Base.UUID, 1}}, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Char, 1}}, Array{Char, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Int64, 1}}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Symbol, 1}}, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Union{Pkg.Types.VersionRange, String, Pkg.REPLMode.Rev}, 1}}, Array{String, 1}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Base.UUID, Int64}}, Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}, Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{K, V} where V where K}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Dict{Symbol, Any}}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.UUID}, Base.UUID}) +precompile(Tuple{typeof(Base.convert), Type{REPL.LineEdit.TextInterface}, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.convert), Type{REPL.Terminals.AbstractTerminal}, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.convert), Type{REPL.Terminals.TextTerminal}, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, IO}}, Base.IOStream}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, IO}}, Nothing}) +precompile(Tuple{typeof(Base.convert), Type{Union{Nothing, REPL.LineEdit.Prompt}}, Nothing}) +precompile(Tuple{typeof(Base.convert), Type{Union{Pkg.Types.UpgradeLevel, Base.VersionNumber, Pkg.Types.VersionSpec}}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.copy_chunks!), Array{UInt64, 1}, Int64, Array{UInt64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.count), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.deepcopy), Base.Dict{String, Any}}) precompile(Tuple{typeof(Base.deepcopy_internal), Array{Base.Dict{String, Any}, 1}, Base.IdDict{Any, Any}}) precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{Any, Any}, Base.IdDict{Any, Any}}) -precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol, Symbol, Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) -precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol, Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) -precompile(Tuple{typeof(Base.diff_names), Tuple{Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) -precompile(Tuple{typeof(Base.eachmatch), Base.Regex, String}) -precompile(Tuple{typeof(Base.empty), Array{Union{Nothing, Base.SubString{String}}, 1}, Type{Base.SubString{String}}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{String, Any}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), Base.Dict{String, String}, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.deepcopy_internal), String, Base.IdDict{Any, Any}}) +precompile(Tuple{typeof(Base.delete!), Base.Dict{String, Any}, String}) +precompile(Tuple{typeof(Base.delete!), Base.IdDict{Any, Any}, Symbol}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{Base.UUID}, Type{Int64}}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{String}, Type{Base.UUID}}) +precompile(Tuple{typeof(Base.empty), Base.Dict{Any, Any}, Type{String}, Type{String}}) +precompile(Tuple{typeof(Base.eof), Base.IOStream}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Base.UUID, Array{String, 1}}, Base.UUID, Array{String, 1}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}, Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}, Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{String, Any}, String, Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.get!), Base.Dict{String, Array{Base.UUID, 1}}, String, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.get), Base.Dict{String, Any}, String, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.get), Base.Dict{String, Pkg.REPLMode.CommandSpec}, String, Nothing}) +precompile(Tuple{typeof(Base.getindex), Array{Array{Base.VersionNumber, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Array{Int64, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Array{UInt64, 1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.BitArray{1}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.BitArray{2}, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.Dict{Int64, Int64}, 1}, Int64}) precompile(Tuple{typeof(Base.getindex), Array{Base.Dict{String, Any}, 1}, Int64}) -precompile(Tuple{typeof(Base.getproperty), Pkg.REPLMode.Command, Symbol}) +precompile(Tuple{typeof(Base.getindex), Array{Base.UUID, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Array{Base.VersionNumber, 1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.getindex), Array{Int64, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.BitArray{1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.getindex), Base.BitArray{2}, Base.BitArray{1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Int64, Int64}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{String, Base.UUID}, String}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Symbol, Function}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Symbol}) +precompile(Tuple{typeof(Base.getindex), Pkg.TOML.Table, String}) +precompile(Tuple{typeof(Base.getindex), Type{Pkg.Types.VersionRange}, Pkg.Pkg2.Pkg2Types.VersionInterval}) precompile(Tuple{typeof(Base.getproperty), Pkg.TOML.Table, Symbol}) +precompile(Tuple{typeof(Base.getproperty), Pkg.Types.PackageSpec, Symbol}) +precompile(Tuple{typeof(Base.getproperty), REPL.Terminals.TerminalBuffer, Symbol}) +precompile(Tuple{typeof(Base.hash), Tuple{String, UInt64}, UInt64}) +precompile(Tuple{typeof(Base.hash), Tuple{String}, UInt64}) precompile(Tuple{typeof(Base.haskey), Base.Dict{Base.UUID, Base.Dict{K, V} where V where K}, Base.UUID}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{String, Base.UUID}, String}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{String, Pkg.Types.VersionSpec}, String}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Symbol}) +precompile(Tuple{typeof(Base.haskey), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Symbol}) precompile(Tuple{typeof(Base.haskey), Pkg.TOML.Table, String}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, UInt64}, Tuple{String, UInt64}}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{String}, Tuple{String}}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{}, Tuple{}}) +precompile(Tuple{typeof(Base.identity), Int64}) +precompile(Tuple{typeof(Base.in), Base.UUID, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.in), Base.VersionNumber, Pkg.Types.VersionSpec}) +precompile(Tuple{typeof(Base.in), String, Array{String, 1}}) +precompile(Tuple{typeof(Base.in), String, Base.KeySet{String, Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.in), String, Base.KeySet{String, Base.Dict{String, Base.Dict{String, Pkg.REPLMode.CommandSpec}}}}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{Any, Any}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, Any}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Base.Pair{String, Any}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Char, Bool}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{Char, Bool}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Array{String, 1}, Array{String, 1}}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{String, Array{String, 1}, Array{String, 1}}, Int64}) +precompile(Tuple{typeof(Base.input_color)}) +precompile(Tuple{typeof(Base.invokelatest), typeof(Pkg.REPLMode.do_status!), Base.Dict{Symbol, Any}, Array{String, 1}, Base.Dict{Symbol, Any}}) precompile(Tuple{typeof(Base.isempty), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.isempty), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.isempty), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.isempty), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.isempty), NamedTuple{(:mode,), Tuple{Symbol}}}) +precompile(Tuple{typeof(Base.isopen), Base.Channel{Any}}) precompile(Tuple{typeof(Base.iterate), Array{Base.Dict{String, Any}, 1}, Int64}) precompile(Tuple{typeof(Base.iterate), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.iterate), Array{Base.UUID, 1}, Int64}) +precompile(Tuple{typeof(Base.iterate), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.iterate), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, Any}, Int64}) +precompile(Tuple{typeof(Base.iterate), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.iterate), Tuple{Base.BitArray{1}}, Int64}) +precompile(Tuple{typeof(Base.iterate), Tuple{Base.BitArray{1}}}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{String}, Char}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{Symbol, Symbol}, String}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{UInt32, UInt32, UInt32}, Char}) +precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{UInt32, UInt32}, Char}) +precompile(Tuple{typeof(Base.join), Tuple{Symbol, Symbol}, String}) +precompile(Tuple{typeof(Base.keys), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.keys), Base.Dict{String, Base.Dict{String, Pkg.REPLMode.CommandSpec}}}) +precompile(Tuple{typeof(Base.lastindex), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.Dict{Int64, Int64}, 1}}) precompile(Tuple{typeof(Base.length), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Base.length), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.length), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.length), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.length), Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.length), Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.length), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.map), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, Any}}}) +precompile(Tuple{typeof(Base.map), Type{Base.UUID}, Base.ValueIterator{Base.Dict{String, String}}}) +precompile(Tuple{typeof(Base.map), typeof(Base.close), Array{LibGit2.GitAnnotated, 1}}) +precompile(Tuple{typeof(Base.mapreduce_first), typeof(Base.identity), typeof(Base.add_sum), Int64}) +precompile(Tuple{typeof(Base.match), Base.Regex, String}) +precompile(Tuple{typeof(Base.merge!), Base.Dict{String, Any}, Base.Dict{String, Any}}) precompile(Tuple{typeof(Base.merge), Base.Dict{String, Any}, Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, NamedTuple{(:mode,), Tuple{Symbol}}}) +precompile(Tuple{typeof(Base.merge), NamedTuple{(:payload,), Tuple{Base.Dict{Symbol, Any}}}, NamedTuple{(:transfer_progress, :credentials), Tuple{Ptr{Nothing}, Ptr{Nothing}}}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol, Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol}, Tuple{Symbol, Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol, Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{Symbol, Symbol}}) precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{Symbol}}) -precompile(Tuple{typeof(Base.merge_types), Tuple{Symbol, Symbol}, Type{NamedTuple{(:callbacks,), Tuple{Base.Dict{Symbol, Tuple{Ptr{Nothing}, Any}}}}}, Type{NamedTuple{(:credentials,), Tuple{LibGit2.CachedCredentials}}}}) -precompile(Tuple{typeof(Base.push!), Array{Base.SubString{String}, 1}, Base.SubString{String}}) -precompile(Tuple{typeof(Base.read), Base.IOStream, Type{String}}) +precompile(Tuple{typeof(Base.merge_names), Tuple{Symbol}, Tuple{}}) +precompile(Tuple{typeof(Base.notify_error), Base.Channel{Any}, Base.InvalidStateException}) +precompile(Tuple{typeof(Base.peek), Base.IOStream}) +precompile(Tuple{typeof(Base.prepend!), Array{Base.Dict{Any, Any}, 1}, Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Pkg.Types.VersionSpec}) +precompile(Tuple{typeof(Base.print), Base.IOStream, String, String, String, Char}) +precompile(Tuple{typeof(Base.print), Base.TTY, String, String, Char}) +precompile(Tuple{typeof(Base.promote_eltype), Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}}) +precompile(Tuple{typeof(Base.push!), Array{Base.UUID, 1}, Base.UUID}) +precompile(Tuple{typeof(Base.push!), Array{Int64, 1}, Int64}) +precompile(Tuple{typeof(Base.push!), Array{Pkg.Types.VersionRange, 1}, Pkg.Types.VersionRange}) +precompile(Tuple{typeof(Base.push!), Array{Tuple{Base.UUID, String}, 1}, Tuple{Base.UUID, String}}) +precompile(Tuple{typeof(Base.push!), Base.Set{Base.VersionNumber}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.push!), Base.Set{Symbol}, Symbol}) +precompile(Tuple{typeof(Base.push!), Pkg.GraphType.ResolveLogEntry, Tuple{Nothing, String}}) +precompile(Tuple{typeof(Base.push!), Pkg.GraphType.ResolveLogEntry, Tuple{Pkg.GraphType.ResolveLogEntry, String}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{String, Array{String, 1}, Array{String, 1}}}) +precompile(Tuple{typeof(Base.rethrow), Base.InvalidStateException}) +precompile(Tuple{typeof(Base.rstrip), String}) +precompile(Tuple{typeof(Base.seek), Base.IOStream, Int64}) +precompile(Tuple{typeof(Base.setdiff!), Base.Set{Base.UUID}, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.BitArray{1}, 1}, Base.BitArray{1}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.BitArray{1}, Bool, Int64}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Base.Dict{K, V} where V where K}, Base.Dict{String, Any}, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Int64}, Int64, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, Pkg.Types.VersionSpec}, Pkg.Types.VersionSpec, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.UUID, String}, String, Base.UUID}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Base.VersionNumber, Base.SHA1}, Base.SHA1, Base.VersionNumber}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Int64, Int64}, Int64, Int64}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{Any, 1}, String}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{Base.Dict{String, Any}, 1}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Array{String, 1}, String}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.Dict{Any, Any}, String}) -precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Pkg.TOML.Table, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.Dict{String, String}, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Any}, Base.UUID, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Base.UUID}, Base.UUID, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Pkg.Types.VersionSpec}, Pkg.Types.VersionSpec, String}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, LibGit2.CredentialPayload, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, Pkg.GitTools.MiniProgressBar, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.EnvDict, String, String}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Array{Base.BitArray{2}, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Array{Int64, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Base.BitArray{1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.Graph, Symbol, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Array{Base.VersionNumber, 1}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Base.Dict{Base.VersionNumber, Int64}, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.GraphData, Symbol, Base.Dict{Base.UUID, Int64}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.GraphType.ResolveLog, Symbol, Base.Dict{Base.UUID, Pkg.GraphType.ResolveLogEntry}}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.REPLMode.Statement, Symbol, Pkg.REPLMode.CommandSpec}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, Base.UUID}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, Base.VersionNumber}) +precompile(Tuple{typeof(Base.setproperty!), Pkg.Types.PackageSpec, Symbol, String}) precompile(Tuple{typeof(Base.similar), Array{Base.Dict{String, Any}, 1}}) -precompile(Tuple{typeof(Base.string), String, Base.UUID}) -precompile(Tuple{typeof(Base.string), String, Module, String, String, String, Int64}) +precompile(Tuple{typeof(Base.skip_deleted_floor!), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.string), String, Base.SubString{String}, String, String}) +precompile(Tuple{typeof(Base.string), Symbol, Int64}) +precompile(Tuple{typeof(Base.strip), Base.SubString{String}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:indent, :region_active), Tuple{Int64, Bool}}, Type{NamedTuple{(:indent, :region_active), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:prompt_prefix, :prompt_suffix, :complete, :sticky), Tuple{String, String, Pkg.REPLMode.PkgCompletionProvider, Bool}}, Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :keymap_dict, :repl, :complete, :on_enter, :on_done, :hist, :sticky), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.structdiff), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :keymap_dict, :repl, :complete, :on_enter, :on_done, :hist, :sticky), T} where T<:Tuple}}) +precompile(Tuple{typeof(Base.sum), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{Symbol, Symbol}}) precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.sym_in), Symbol, Tuple{}}) +precompile(Tuple{typeof(Base.to_indices), Base.BitArray{2}, Tuple{Base.OneTo{Int64}}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.trues), Int64}) +precompile(Tuple{typeof(Base.union!), Base.Set{Base.UUID}, Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.Fixed}}}) +precompile(Tuple{typeof(Base.union!), Base.Set{Base.UUID}, Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}}) +precompile(Tuple{typeof(Base.unique!), Array{Base.UUID, 1}}) +precompile(Tuple{typeof(Base.unique!), Array{String, 1}}) +precompile(Tuple{typeof(Base.values), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.values), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{1}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{2}, Base.BitArray{2}, Base.BitArray{2}, Base.BitArray{2}}) +precompile(Tuple{typeof(Base.vcat), Base.BitArray{2}, Base.BitArray{2}}) +precompile(Tuple{typeof(Base.vect), Base.Cmd, Base.Cmd}) +precompile(Tuple{typeof(Base.vect), Base.VersionNumber}) +precompile(Tuple{typeof(Base.vect), Nothing}) precompile(Tuple{typeof(Base.write), Base.TTY, Array{UInt8, 1}}) -precompile(Tuple{typeof(Core.Compiler.vect), Tuple{Nothing, Int64}}) -precompile(Tuple{typeof(Core.Compiler.vect), Tuple{Pkg.REPLMode.OptionKind, Int64}}) +precompile(Tuple{typeof(Base.write), REPL.Terminals.TTYTerminal, Array{UInt8, 1}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Base.BitArray{2}, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Base.KeySet{Base.UUID, Base.Dict{Base.UUID, Pkg.Types.VersionSpec}}, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Pkg.Pkg2.Pkg2Types.VersionInterval, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{UInt32, 1}}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), Nothing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Pkg.REPLMode.do_help!)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.Pkg2.Reqs.read)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.TOML.parse)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.IteratorsMD.CartesianIndex{0}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Missing, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Missing}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Val{1}, typeof(Base.cat_t), Union}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Bool, typeof(Pkg.Types.parse_toml)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Int64, Tuple{Int64, Tuple{Int64, Tuple{Int64, Tuple{}}}}}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{NamedTuple{(:dims,), Tuple{Base.Val{1}}}, typeof(Base.cat_t), Union}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Int64, typeof(Base.sprint), typeof(Base.showerror)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Int64, typeof(Base.sprint), typeof(Pkg.GraphType.showlog)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Pkg.REPLMode.CommandKind, Int64}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(!))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(&))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(+))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(-))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(==))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(>))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(~))}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.Unicode.lowercase)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.abs)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.first)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.identity)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.maximum)}, Int64}) +precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Pkg.BinaryProvider.parse_tar_list)}, Int64}) precompile(Tuple{typeof(Pkg.Display.filter_manifest), Pkg.Display.InProject{Base.Dict{String, Any}}, Base.Dict{String, Any}}) precompile(Tuple{typeof(Pkg.Display.in_project), Base.Dict{String, Any}}) precompile(Tuple{typeof(Pkg.Display.manifest_diff), Pkg.Types.Context, Base.Dict{String, Any}, Base.Dict{String, Any}}) precompile(Tuple{typeof(Pkg.Display.name_ver_info), Base.Dict{String, Any}}) precompile(Tuple{typeof(Pkg.Display.not_in_project), Base.Dict{String, Any}}) precompile(Tuple{typeof(Pkg.Display.print_diff), Base.TTY, Pkg.Types.Context, Array{Pkg.Display.DiffEntry, 1}, Bool}) -precompile(Tuple{typeof(Pkg.GitTools.showprogress), Base.TTY, Pkg.GitTools.MiniProgressBar}) -precompile(Tuple{typeof(Pkg.GitTools.transfer_progress), Ptr{LibGit2.TransferProgress}, Base.Dict{Symbol, Any}}) -precompile(Tuple{typeof(Pkg.REPLMode.do_status!), Pkg.Types.Context, Array{Union{Pkg.Types.VersionRange, String, Pkg.REPLMode.Command, Pkg.REPLMode.Option, Pkg.REPLMode.Rev}, 1}}) +precompile(Tuple{typeof(Pkg.Operations.load_package_data_raw), Type{Base.UUID}, String}) +precompile(Tuple{typeof(Pkg.REPLMode.do_add!), Base.Dict{Symbol, Any}, Array{Pkg.Types.PackageSpec, 1}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Pkg.REPLMode.do_status!), Base.Dict{Symbol, Any}, Array{String, 1}, Base.Dict{Symbol, Any}}) precompile(Tuple{typeof(Pkg.REPLMode.promptf)}) precompile(Tuple{typeof(Pkg.TOML.SOME), Array{String, 1}}) precompile(Tuple{typeof(Pkg.TOML.SOME), Pkg.TOML.Table}) precompile(Tuple{typeof(Pkg.TOML.insertpair), Pkg.TOML.Parser{Base.IOStream}, Pkg.TOML.Table, String, Array{String, 1}, Int64}) -precompile(Tuple{typeof(Pkg.TOML.insertpair), Pkg.TOML.Parser{Base.IOStream}, Pkg.TOML.Table, String, String, Int64}) +precompile(Tuple{typeof(Pkg.TOML.insertpair), Pkg.TOML.Parser{Base.IOStream}, Pkg.TOML.Table, String, Pkg.TOML.Table, Int64}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), Array{String, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_array_of_tables), String}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Array{Base.Dict{String, Any}, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Array{String, 1}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Pkg.TOML.is_tabular), String}) +precompile(Tuple{typeof(Pkg.TOML.parsefile), String}) precompile(Tuple{typeof(Pkg.Types.printpkgstyle), Base.TTY, Symbol, String}) -precompile(Tuple{typeof(REPL.LineEdit.complete_line), Pkg.REPLMode.PkgCompletionProvider, REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.write_prompt), REPL.Terminals.TerminalBuffer, typeof(Pkg.REPLMode.promptf)}) - -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_help!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}, REPL.LineEditREPL}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_status!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_add_or_develop!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}, Pkg.REPLMode.CommandKind}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_rm!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_up!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_pin!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_free!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_test!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) -@assert precompile(Tuple{typeof(Pkg.REPLMode.do_build!), Pkg.Types.Context, Vector{Pkg.REPLMode.Token}}) - +precompile(Tuple{typeof(Pkg.Types.semver_interval), Base.RegexMatch}) +precompile(Tuple{typeof(Pkg.Types.write_env_usage), String}) +precompile(Tuple{typeof(REPL.LineEdit._clear_input_area), REPL.Terminals.TerminalBuffer, REPL.LineEdit.InputAreaState}) +precompile(Tuple{typeof(REPL.LineEdit.add_history), REPL.REPLHistoryProvider, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.clear_input_area), REPL.Terminals.TerminalBuffer, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.edit_abort), REPL.LineEdit.MIState, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.edit_insert), REPL.LineEdit.MIState, String}) +precompile(Tuple{typeof(REPL.LineEdit.edit_insert), REPL.LineEdit.PromptState, String}) +precompile(Tuple{typeof(REPL.LineEdit.fixup_keymaps!), Base.Dict{Char, Any}, Int64, Char, Nothing}) +precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.move_input_end), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.normalize_key), Int64}) +precompile(Tuple{typeof(REPL.LineEdit.normalize_key), String}) +precompile(Tuple{typeof(REPL.LineEdit.on_enter), REPL.LineEdit.MIState}) +precompile(Tuple{typeof(REPL.LineEdit.postprocess!), Base.Dict{Char, Any}}) +precompile(Tuple{typeof(REPL.LineEdit.prompt_string), String}) +precompile(Tuple{typeof(REPL.LineEdit.push_undo), REPL.LineEdit.PromptState, Bool}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_line), REPL.LineEdit.PromptState, REPL.Terminals.TTYTerminal}) +precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.LineEdit.PromptState}) +precompile(Tuple{typeof(REPL.LineEdit.state), REPL.LineEdit.MIState, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.update_key_repeats), REPL.LineEdit.MIState, Array{Char, 1}}) +precompile(Tuple{typeof(REPL.LineEdit.write_prompt), REPL.Terminals.TerminalBuffer, REPL.LineEdit.Prompt}) +precompile(Tuple{typeof(REPL.LineEdit.write_prompt), REPL.Terminals.TerminalBuffer, String}) From d5890e6f0eafd43102402f18e0d8229092e03c1b Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 11:54:34 +0200 Subject: [PATCH 21/22] add licenses to files --- stdlib/Pkg/src/REPLMode.jl | 2 ++ stdlib/Pkg/src/precompile.jl | 2 ++ stdlib/Pkg/test/api.jl | 2 ++ stdlib/Pkg/test/test_packages/x1/src/x1.jl | 2 ++ stdlib/Pkg/test/test_packages/x2/src/x2.jl | 2 ++ stdlib/Pkg/test/test_packages/x3/src/x3.jl | 2 ++ stdlib/Pkg/test/test_packages/x3/test/runtests.jl | 2 ++ 7 files changed, 14 insertions(+) diff --git a/stdlib/Pkg/src/REPLMode.jl b/stdlib/Pkg/src/REPLMode.jl index e3803371282b9..db18d952e538e 100644 --- a/stdlib/Pkg/src/REPLMode.jl +++ b/stdlib/Pkg/src/REPLMode.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module REPLMode using Markdown diff --git a/stdlib/Pkg/src/precompile.jl b/stdlib/Pkg/src/precompile.jl index 75b1b05e48827..adfebb709a63f 100644 --- a/stdlib/Pkg/src/precompile.jl +++ b/stdlib/Pkg/src/precompile.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + precompile(Tuple{Type{Base.Dict{K, V} where V where K}, Array{Base.Pair{A, B} where B where A, 1}}) precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Base.UUID}}}}) precompile(Tuple{Type{Base.Dict{Pkg.Types.VersionRange, Base.Dict{String, Pkg.Types.VersionSpec}}}}) diff --git a/stdlib/Pkg/test/api.jl b/stdlib/Pkg/test/api.jl index 452eca69126c5..5ead22ccc9bf8 100644 --- a/stdlib/Pkg/test/api.jl +++ b/stdlib/Pkg/test/api.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module APITests using Pkg, Test diff --git a/stdlib/Pkg/test/test_packages/x1/src/x1.jl b/stdlib/Pkg/test/test_packages/x1/src/x1.jl index bd929422af3f4..61d85d63da27f 100644 --- a/stdlib/Pkg/test/test_packages/x1/src/x1.jl +++ b/stdlib/Pkg/test/test_packages/x1/src/x1.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module x1 greet() = print("Hello World!") diff --git a/stdlib/Pkg/test/test_packages/x2/src/x2.jl b/stdlib/Pkg/test/test_packages/x2/src/x2.jl index 8afcc2e013477..e4530c034da07 100644 --- a/stdlib/Pkg/test/test_packages/x2/src/x2.jl +++ b/stdlib/Pkg/test/test_packages/x2/src/x2.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module x2 greet() = print("Hello World!") diff --git a/stdlib/Pkg/test/test_packages/x3/src/x3.jl b/stdlib/Pkg/test/test_packages/x3/src/x3.jl index a9b26ef703c75..28b4ff3b9d16c 100644 --- a/stdlib/Pkg/test/test_packages/x3/src/x3.jl +++ b/stdlib/Pkg/test/test_packages/x3/src/x3.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module x3 greet() = print("Hello World!") diff --git a/stdlib/Pkg/test/test_packages/x3/test/runtests.jl b/stdlib/Pkg/test/test_packages/x3/test/runtests.jl index 85b0336d373e1..9540e3095e5d5 100644 --- a/stdlib/Pkg/test/test_packages/x3/test/runtests.jl +++ b/stdlib/Pkg/test/test_packages/x3/test/runtests.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + module X3Tests using x2 From fee0392482b84ea8c44923098652361354821887 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 4 Aug 2018 22:42:45 +0100 Subject: [PATCH 22/22] increase isolation of test --- stdlib/Pkg/test/api.jl | 62 ++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/stdlib/Pkg/test/api.jl b/stdlib/Pkg/test/api.jl index 5ead22ccc9bf8..e8b7c7ccb7716 100644 --- a/stdlib/Pkg/test/api.jl +++ b/stdlib/Pkg/test/api.jl @@ -4,37 +4,41 @@ module APITests using Pkg, Test +include("utils.jl") + @testset "Pkg.activate" begin - cd(mktempdir()) do - path = pwd() - Pkg.activate(".") - mkdir("Foo") - cd(mkdir("modules")) do - Pkg.generate("Foo") + temp_pkg_dir() do project_path + cd(mktempdir()) do + path = pwd() + Pkg.activate(".") + mkdir("Foo") + cd(mkdir("modules")) do + Pkg.generate("Foo") + end + Pkg.develop(Pkg.Types.PackageSpec(path="modules/Foo")) # to avoid issue #542 + Pkg.activate("Foo") # activate path Foo over deps Foo + @test Base.active_project() == joinpath(path, "Foo", "Project.toml") + Pkg.activate(".") + rm("Foo"; force=true, recursive=true) + Pkg.activate("Foo") # activate path from developed Foo + @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + Pkg.activate(".") + Pkg.activate("./Foo") # activate empty directory Foo (sidestep the developed Foo) + @test Base.active_project() == joinpath(path, "Foo", "Project.toml") + Pkg.activate(".") + Pkg.activate("Bar") # activate empty directory Bar + @test Base.active_project() == joinpath(path, "Bar", "Project.toml") + Pkg.activate(".") + Pkg.add("Example") # non-deved deps should not be activated + Pkg.activate("Example") + @test Base.active_project() == joinpath(path, "Example", "Project.toml") + Pkg.activate(".") + cd(mkdir("tests")) + Pkg.activate("Foo") # activate developed Foo from another directory + @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + Pkg.activate() # activate home project + @test Base.ACTIVE_PROJECT[] === nothing end - Pkg.develop(Pkg.Types.PackageSpec(path="modules/Foo")) # to avoid issue #542 - Pkg.activate("Foo") # activate path Foo over deps Foo - @test Base.active_project() == joinpath(path, "Foo", "Project.toml") - Pkg.activate(".") - rm("Foo"; force=true, recursive=true) - Pkg.activate("Foo") # activate path from developed Foo - @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") - Pkg.activate(".") - Pkg.activate("./Foo") # activate empty directory Foo (sidestep the developed Foo) - @test Base.active_project() == joinpath(path, "Foo", "Project.toml") - Pkg.activate(".") - Pkg.activate("Bar") # activate empty directory Bar - @test Base.active_project() == joinpath(path, "Bar", "Project.toml") - Pkg.activate(".") - Pkg.add("Example") # non-deved deps should not be activated - Pkg.activate("Example") - @test Base.active_project() == joinpath(path, "Example", "Project.toml") - Pkg.activate(".") - cd(mkdir("tests")) - Pkg.activate("Foo") # activate developed Foo from another directory - @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") - Pkg.activate() # activate home project - @test Base.ACTIVE_PROJECT[] === nothing end end