From 338b48988bbb1fc9ecec067e823bb20bb64c503d Mon Sep 17 00:00:00 2001 From: David Varela <00.varela.david@gmail.com> Date: Tue, 18 Feb 2020 13:59:45 -0800 Subject: [PATCH] refactor `pkgs` handling --- src/API.jl | 66 +++---- src/Operations.jl | 273 ++++++++++++--------------- src/Pkg.jl | 2 +- src/REPLMode/command_declarations.jl | 2 +- src/Types.jl | 3 +- 5 files changed, 156 insertions(+), 190 deletions(-) diff --git a/src/API.jl b/src/API.jl index a1e6c0da8c..35ee214a61 100644 --- a/src/API.jl +++ b/src/API.jl @@ -89,7 +89,7 @@ function develop(ctx::Context, pkgs::Vector{PackageSpec}; shared::Bool=true, end end - new_git = handle_repos_develop!(ctx, pkgs, shared) + new = handle_repos_develop!(ctx, pkgs, shared) for pkg in pkgs if Types.collides_with_project(ctx, pkg) @@ -100,7 +100,8 @@ function develop(ctx::Context, pkgs::Vector{PackageSpec}; shared::Bool=true, end end - Operations.develop(ctx, pkgs, new_git; preserve=preserve, platform=platform) + Operations.assert_can_add(ctx, pkgs) + Operations.develop(ctx, pkgs, new; preserve=preserve, platform=platform) return end @@ -145,7 +146,7 @@ function add(ctx::Context, pkgs::Vector{PackageSpec}; preserve::PreserveLevel=PR end repo_pkgs = [pkg for pkg in pkgs if (pkg.repo.source !== nothing || pkg.repo.rev !== nothing)] - new_git = handle_repos_add!(ctx, repo_pkgs) + new = handle_repos_add!(ctx, repo_pkgs) # repo + unpinned -> name, uuid, repo.rev, repo.source, tree_hash # repo + pinned -> name, uuid, tree_hash @@ -162,7 +163,8 @@ function add(ctx::Context, pkgs::Vector{PackageSpec}; preserve::PreserveLevel=PR end end - Operations.add(ctx, pkgs, new_git; preserve=preserve, platform=platform) + Operations.assert_can_add(ctx, pkgs) + Operations.add(ctx, pkgs, new; preserve=preserve, platform=platform) return end @@ -195,50 +197,45 @@ function rm(ctx::Context, pkgs::Vector{PackageSpec}; mode=PKGMODE_PROJECT, kwarg return end -up(ctx::Context; kwargs...) = up(ctx, PackageSpec[]; kwargs...) -up(; kwargs...) = up(PackageSpec[]; kwargs...) -up(pkg::Union{AbstractString, PackageSpec}; kwargs...) = up([pkg]; kwargs...) -up(pkgs::Vector{<:AbstractString}; kwargs...) = up([PackageSpec(pkg) for pkg in pkgs]; kwargs...) -up(pkgs::Vector{PackageSpec}; kwargs...) = up(Context(), pkgs; kwargs...) +update(ctx::Context; kwargs...) = update(ctx, PackageSpec[]; kwargs...) +update(; kwargs...) = update(PackageSpec[]; kwargs...) +update(pkg::Union{AbstractString, PackageSpec}; kwargs...) = update([pkg]; kwargs...) +update(pkgs::Vector{<:AbstractString}; kwargs...) = update([PackageSpec(pkg) for pkg in pkgs]; kwargs...) +update(pkgs::Vector{PackageSpec}; kwargs...) = update(Context(), pkgs; kwargs...) -function up(ctx::Context, pkgs::Vector{PackageSpec}; +function update(ctx::Context, pkgs::Vector{PackageSpec}; level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode=PKGMODE_PROJECT, update_registry::Bool=true, kwargs...) pkgs = deepcopy(pkgs) # deepcopy for avoid mutating PackageSpec members - foreach(pkg -> pkg.mode = mode, pkgs) - Context!(ctx; kwargs...) + if update_registry Types.clone_default_registries(ctx) Types.update_registries(ctx; force=true) end + + new = UUID[] if isempty(pkgs) - if mode == PKGMODE_PROJECT - for (name::String, uuid::UUID) in ctx.env.project.deps - repo = haskey(ctx.env.project.source, name) ? GitRepo(;source=ctx.env.project.source[name]) : GitRepo() - push!(pkgs, PackageSpec(name=name, uuid=uuid, repo=repo)) - end - elseif mode == PKGMODE_MANIFEST - for (uuid, entry) in ctx.env.manifest - repo = GitRepo() - if uuid in values(ctx.env.project.deps) && haskey(ctx.env.project.source, entry.name) - repo = GitRepo(;source=ctx.env.project.source[entry.name]) - end - push!(pkgs, PackageSpec(name=entry.name, uuid=uuid, repo=repo)) - end + if mode === PKGMODE_PROJECT + pkgs = Operations.load_direct_deps(ctx, pkgs, new) + else + pkgs = Operations.load_all_deps(ctx, pkgs, new) end else + foreach(pkg -> pkg.mode = PKGMODE_PROJECT, pkgs) project_deps_resolve!(ctx, pkgs) - manifest_resolve!(ctx, pkgs) ensure_resolved(ctx, pkgs) + uuids = UUID[pkg.uuid for pkg in pkgs] + pkgs = filter(pkg -> pkg.uuid in uuids, Operations.load_direct_deps(ctx, PackageSpec[], new)) end - Operations.up(ctx, pkgs, level) + + Operations.update(ctx, pkgs, new, level) return end resolve(; kwargs...) = resolve(Context(); kwargs...) function resolve(ctx::Context; kwargs...) - up(ctx; level=UPLEVEL_FIXED, mode=PKGMODE_MANIFEST, update_registry=false, kwargs...) + update(ctx; level=UPLEVEL_FIXED, mode=PKGMODE_MANIFEST, update_registry=false, kwargs...) return nothing end @@ -758,9 +755,8 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, platform::Platform=platform_key_abi(), kwargs...) Context!(ctx; kwargs...) if !isfile(ctx.env.project_file) && isfile(ctx.env.manifest_file) - _manifest = Pkg.Types.read_manifest(ctx.env.manifest_file) deps = Dict() - for (uuid, pkg) in _manifest + for (uuid, pkg) in Pkg.Types.read_manifest(ctx.env.manifest_file) if pkg.name in keys(deps) # TODO, query what package to put in Project when in interactive mode? pkgerror("cannot instantiate a manifest without project file when the manifest has multiple packages with the same name ($(pkg.name))") @@ -771,7 +767,7 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, return instantiate(Context(); manifest=manifest, update_registry=update_registry, verbose=verbose, kwargs...) end if (!isfile(ctx.env.manifest_file) && manifest === nothing) || manifest == false - up(ctx; update_registry=update_registry) + update(ctx; update_registry=update_registry) return end if !isfile(ctx.env.manifest_file) && manifest == true @@ -792,7 +788,7 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, Types.update_registries(ctx) pkgs = Operations.load_all_deps(ctx) Operations.check_registered(ctx, pkgs) - new_git = UUID[] + new = UUID[] # Handling packages tracking repos for pkg in pkgs pkg.repo.source !== nothing || continue @@ -821,15 +817,15 @@ function instantiate(ctx::Context; manifest::Union{Bool, Nothing}=nothing, end mkpath(sourcepath) GitTools.checkout_tree_to_path(repo, tree_hash_object, sourcepath) - push!(new_git, pkg.uuid) + push!(new, pkg.uuid) end end # Ensure artifacts are installed for the dependent packages, and finally this overall project Operations.download_artifacts(ctx, pkgs; platform=platform, verbose=verbose) - new_apply = Operations.download_source(ctx, pkgs) - Operations.build_versions(ctx, union(UUID[pkg.uuid for pkg in new_apply], new_git); verbose=verbose) + union!(new, Operations.uuids(Operations.download_source(ctx, pkgs))) + Operations.build_versions(ctx, new; verbose=verbose) end diff --git a/src/Operations.jl b/src/Operations.jl index a601a712dd..1d46351ad2 100644 --- a/src/Operations.jl +++ b/src/Operations.jl @@ -18,6 +18,7 @@ import ...Pkg: pkg_server ######### # Utils # ######### +uuids(pkgs::Vector{PackageSpec}) = UUID[pkg.uuid for pkg in pkgs] projectdir(ctx::Context) = dirname(ctx.env.project_file) function find_installed(name::String, uuid::UUID, sha1::SHA1) slug_default = Base.version_slug(uuid, sha1) @@ -60,25 +61,36 @@ function load_version(version, fixed, preserve::PreserveLevel) end end -function load_direct_deps(ctx::Context, pkgs::Vector{PackageSpec}=PackageSpec[]; - preserve::PreserveLevel=PRESERVE_DIRECT) - pkgs = copy(pkgs) +# TODO should preserve_none nuke the git revision? +function load_direct_deps(ctx::Context, pkgs::Vector{PackageSpec}=PackageSpec[], new::Vector{UUID}=UUID[]; + download::Bool=true, preserve::PreserveLevel=PRESERVE_DIRECT) + pkgs = copy(pkgs) # TODO this is needed for resolve tiers, but perhaps does not belong here for (name::String, uuid::UUID) in ctx.env.project.deps findfirst(pkg -> pkg.uuid == uuid, pkgs) === nothing || continue # do not duplicate packages entry = manifest_info(ctx, uuid) - source = get(ctx.env.project.source, name, nothing) - repo = GitRepo(; source=(source === nothing ? nothing : source)) - push!(pkgs, entry === nothing ? - PackageSpec(; uuid=uuid, name=name, repo=repo) : - PackageSpec(; + pkg = nothing + if entry === nothing + source = get(ctx.env.project.source, name, nothing) + if source !== nothing && download + pkg = handle_unregistered_pkg(ctx, projectdir(ctx), source, new) + else + # TODO do we have to normalize the source here? + # TODO I think we have to do relpath abspath trick + # TODO or maybe `handle_unregistered_pkg` will handle it downstream? + pkg = PackageSpec(; uuid = uuid, name = name, repo = GitRepo(; source = source)) + end + else + pkg = PackageSpec(; uuid = uuid, name = name, path = entry.path, repo = entry.repo, pinned = entry.pinned, - tree_hash = entry.tree_hash, # TODO should tree_hash be changed too? + tree_hash = entry.tree_hash, version = load_version(entry.version, isfixed(entry), preserve), - )) + ) + end + push!(pkgs, pkg) end return pkgs end @@ -94,17 +106,17 @@ function load_manifest_deps(ctx::Context, pkgs::Vector{PackageSpec}=PackageSpec[ path = entry.path, pinned = entry.pinned, repo = entry.repo, - tree_hash = entry.tree_hash, # TODO should tree_hash be changed too? + tree_hash = entry.tree_hash, version = load_version(entry.version, isfixed(entry), preserve), )) end return pkgs end -function load_all_deps(ctx::Context, pkgs::Vector{PackageSpec}=PackageSpec[]; +function load_all_deps(ctx::Context, pkgs::Vector{PackageSpec}=PackageSpec[], new::Vector{UUID}=UUID[]; preserve::PreserveLevel=PRESERVE_ALL) - pkgs = load_manifest_deps(ctx, pkgs; preserve=preserve) - return load_direct_deps(ctx, pkgs; preserve=preserve) + pkgs = load_direct_deps(ctx, pkgs, new; preserve=preserve) + return load_manifest_deps(ctx, pkgs; preserve=preserve) end function is_instantiated(ctx::Context)::Bool @@ -967,31 +979,6 @@ function rm(ctx::Context, pkgs::Vector{PackageSpec}) write_env(ctx.env) end -add_package(ctx::Context, pkg::PackageSpec, ::Nothing) = pkg -function add_package(ctx::Context, pkg::PackageSpec, entry::PackageEntry) - if entry.pinned - if pkg.version == VersionSpec() - println(ctx.io, "`$(pkg.name)` is pinned at `v$(entry.version)`: maintaining pinned version") - end - return PackageSpec(; uuid=pkg.uuid, name=pkg.name, pinned=true, - version=entry.version, tree_hash=entry.tree_hash) - end - if !is_tracking_registry(entry) || !is_tracking_registry(pkg) - return pkg # overwrite everything, nothing to copy over - end - if is_stdlib(pkg.uuid) - return pkg # stdlibs are not versioned like other packages - elseif any(==(pkg.uuid), [uuid for (name, uuid) in ctx.env.project.deps]) && - ((isa(pkg.version, VersionNumber) && entry.version == pkg.version) || - (!isa(pkg.version, VersionNumber) && entry.version ∈ pkg.version)) - # leave the package as is at the installed version - return PackageSpec(; uuid=pkg.uuid, name=pkg.name, version=entry.version, - tree_hash=entry.tree_hash) - end - # adding a new version not compatible with the old version, so we just overwrite - return pkg -end - is_registered(ctx::Context, uuid::UUID) = !isempty(registered_paths(ctx, uuid)) function check_registered(ctx::Context, pkgs::Vector{PackageSpec}) pkgs = filter(tracking_registered_version, pkgs) @@ -1025,49 +1012,49 @@ function assert_can_add(ctx::Context, pkgs::Vector{PackageSpec}) end end -function tiered_resolve(ctx::Context, pkgs::Vector{PackageSpec}) - try # do not modify existing subgraph - return targeted_resolve(ctx, pkgs, PRESERVE_ALL) - catch err - err isa Resolve.ResolverError || rethrow() +function tiered_resolve(ctx::Context, pkgs::Vector{PackageSpec}, new::Vector{UUID}, should_preserve_all::Bool) + if should_preserve_all + try # do not modify existing subgraph + return targeted_resolve(ctx, pkgs, PRESERVE_ALL, new) + catch err + err isa Resolve.ResolverError || rethrow() + end end try # do not modify existing direct deps - return targeted_resolve(ctx, pkgs, PRESERVE_DIRECT) + return targeted_resolve(ctx, pkgs, PRESERVE_DIRECT, new) catch err err isa Resolve.ResolverError || rethrow() end try - return targeted_resolve(ctx, pkgs, PRESERVE_SEMVER) + return targeted_resolve(ctx, pkgs, PRESERVE_SEMVER, new) catch err err isa Resolve.ResolverError || rethrow() end - return targeted_resolve(ctx, pkgs, PRESERVE_NONE) + return targeted_resolve(ctx, pkgs, PRESERVE_NONE, new) end -function targeted_resolve(ctx::Context, pkgs::Vector{PackageSpec}, preserve::PreserveLevel) +function targeted_resolve(ctx::Context, pkgs::Vector{PackageSpec}, preserve::PreserveLevel, new::Vector{UUID}) if preserve == PRESERVE_ALL - pkgs = load_all_deps(ctx, pkgs) + pkgs = load_all_deps(ctx, pkgs, new) elseif preserve == PRESERVE_DIRECT - pkgs = load_direct_deps(ctx, pkgs) + pkgs = load_direct_deps(ctx, pkgs, new) elseif preserve == PRESERVE_SEMVER - pkgs = load_direct_deps(ctx, pkgs; preserve=preserve) + pkgs = load_direct_deps(ctx, pkgs, new; preserve=preserve) elseif preserve == PRESERVE_NONE - pkgs = load_direct_deps(ctx, pkgs; preserve=preserve) + pkgs = load_direct_deps(ctx, pkgs, new; preserve=preserve) end check_registered(ctx, pkgs) resolve_versions!(ctx, pkgs) return pkgs end -function resolve(ctx::Context, pkgs::Vector{PackageSpec}, preserve::PreserveLevel) +function resolve(ctx::Context, pkgs::Vector{PackageSpec}, new::Vector{UUID}, preserve::PreserveLevel, should_preserve_all::Bool) printpkgstyle(ctx, :Resolving, "package versions...") return preserve == PRESERVE_TIERED ? - tiered_resolve(ctx, pkgs) : - targeted_resolve(ctx, pkgs, preserve) + tiered_resolve(ctx, pkgs, new, should_preserve_all) : + targeted_resolve(ctx, pkgs, preserve, new) end -has_unregistered_source(project::Project, pkg::PackageSpec) = pkg.uuid in keys(project.deps) && pkg.name in values(project.source) - function is_valid_repo(path) valid = nothing if isdir(joinpath(path, ".git")) @@ -1079,7 +1066,7 @@ function is_valid_repo(path) return false end -function handle_unregistered_pkg(ctx::Context, project_path::String, source::String, new_git) +function handle_unregistered_pkg(ctx::Context, project_path::String, source::String, new::Vector{UUID}) if !isurl(source) use_abspath = isabspath(source) source = project_rel_path(project_path, source) @@ -1087,14 +1074,14 @@ function handle_unregistered_pkg(ctx::Context, project_path::String, source::Str end new_pkg = PackageSpec(; repo=GitRepo(;source=source)) if isurl(source) || is_valid_repo(source) - Types.handle_repo_add!(ctx, new_pkg) && push!(new_git, new_pkg.uuid) + Types.handle_repo_add!(ctx, new_pkg) && push!(new, new_pkg.uuid) else - Types.handle_repo_develop!(ctx, new_pkg, false) && push!(new_git, new_pkg.uuid) + Types.handle_repo_develop!(ctx, new_pkg, false) && push!(new, new_pkg.uuid) end return new_pkg end -function collect_unregistered!(ctx::Context, pkg::PackageSpec, new_git::Vector{UUID}, pkgs::Vector{PackageSpec}) +function collect_unregistered!(ctx::Context, pkg::PackageSpec, pkgs::Vector{PackageSpec}, new::Vector{UUID}) project_path = project_rel_path(ctx, source_path(pkg)) projectfile = projectfile_path(project_path; strict=true) if projectfile === nothing @@ -1104,135 +1091,115 @@ function collect_unregistered!(ctx::Context, pkg::PackageSpec, new_git::Vector{U for (name, uuid) in src_project.deps source = get(src_project.source, name, nothing) if source !== nothing - new_pkg = handle_unregistered_pkg(ctx, project_path, source, new_git) + new_pkg = handle_unregistered_pkg(ctx, project_path, source, new) findfirst(pkg -> pkg.uuid == new_pkg.uuid, pkgs) === nothing || continue push!(pkgs, new_pkg) - collect_unregistered!(ctx, new_pkg, new_git, pkgs) + collect_unregistered!(ctx, new_pkg, pkgs, new) end end end -function collect_unregistered!(ctx::Context, pkgs::Vector{PackageSpec}, new_git) +function collect_unregistered!(ctx::Context, pkgs::Vector{PackageSpec}, new::Vector{UUID}) for pkg in filter(!is_tracking_registry, pkgs) - if pkg.tree_hash === nothing && is_tracking_repo(pkg) - new_pkg = handle_unregistered_pkg(ctx, projectdir(ctx), pkg.repo.source, new_git) - pkg.name, pkg.uuid, pkg.repo, pkg.path = new_pkg.name, new_pkg.uuid, new_pkg.repo, new_pkg.path - pkg.tree_hash = new_pkg.tree_hash - end - collect_unregistered!(ctx, pkg, new_git, pkgs) + collect_unregistered!(ctx, pkg, pkgs, new) end return pkgs end -function add(ctx::Context, pkgs::Vector{PackageSpec}, new_git=UUID[]; +add_package(ctx::Context, pkg::PackageSpec, ::Nothing) = pkg +function add_package(ctx::Context, pkg::PackageSpec, entry::PackageEntry) + if entry.pinned + if pkg.version == VersionSpec() + println(ctx.io, "`$(pkg.name)` is pinned at `v$(entry.version)`: maintaining pinned version") + end + return PackageSpec(; uuid=pkg.uuid, name=pkg.name, pinned=true, + version=entry.version, tree_hash=entry.tree_hash) + end + if !is_tracking_registry(entry) || !is_tracking_registry(pkg) + return pkg # overwrite everything, nothing to copy over + end + if is_stdlib(pkg.uuid) + return pkg # stdlibs are not versioned like other packages + elseif any(==(pkg.uuid), [uuid for (name, uuid) in ctx.env.project.deps]) && + ((isa(pkg.version, VersionNumber) && entry.version == pkg.version) || + (!isa(pkg.version, VersionNumber) && entry.version ∈ pkg.version)) + # leave the package as is at the installed version + return PackageSpec(; uuid=pkg.uuid, name=pkg.name, version=entry.version, + tree_hash=entry.tree_hash) + end + # adding a new version not compatible with the old version, so we just overwrite + return pkg +end + +function add(ctx::Context, pkgs::Vector{PackageSpec}, new=UUID[]; preserve::PreserveLevel=PRESERVE_TIERED, platform::Platform=platform_key_abi()) - assert_can_add(ctx, pkgs) - # load manifest data + should_preserve_all = isempty(intersect(values(ctx.env.project.deps), uuids(pkgs))) pkgs = map(pkg -> add_package(ctx, pkg, manifest_info(ctx, pkg.uuid)), pkgs) foreach(pkg -> ctx.env.project.deps[pkg.name] = pkg.uuid, pkgs) # update set of deps - # handle unregistered deps - # TODO why aren't we doing load_direct_deps here like in `dev`? - collect_unregistered!(ctx, pkgs, new_git) - # resolve - pkgs = resolve(ctx, pkgs, preserve) + collect_unregistered!(ctx, pkgs, new) + pkgs = resolve(ctx, pkgs, new, preserve, should_preserve_all) update_env!(ctx, pkgs) - new_apply = download_source(ctx, pkgs) + union!(new, uuids(download_source(ctx, pkgs))) # After downloading resolutionary packages, search for (Julia)Artifacts.toml files # and ensure they are all downloaded and unpacked as well: download_artifacts(ctx, pkgs; platform=platform) show_update(ctx) write_env(ctx.env) # write env before building - build_versions(ctx, union(UUID[pkg.uuid for pkg in new_apply], new_git)) + build_versions(ctx, new) end # Input: name, uuid, and path -function develop(ctx::Context, pkgs::Vector{PackageSpec}, new_git::Vector{UUID}; +function develop(ctx::Context, pkgs::Vector{PackageSpec}, new::Vector{UUID}; preserve::PreserveLevel=PRESERVE_TIERED, platform::Platform=platform_key_abi()) - assert_can_add(ctx, pkgs) + should_preserve_all = isempty(intersect(values(ctx.env.project.deps), uuids(pkgs))) # no need to look at manifest.. dev will just nuke whatever is there before - for pkg in pkgs - ctx.env.project.deps[pkg.name] = pkg.uuid - end - pkgs = load_direct_deps(ctx, pkgs) - # handle unregistered dependencies - # TODO make sure filter is working well with invariants - collect_unregistered!(ctx, pkgs, new_git) - check_registered(ctx, pkgs) - # resolve & apply package versions - pkgs = resolve(ctx, pkgs, preserve) + foreach(pkg -> ctx.env.project.deps[pkg.name] = pkg.uuid, pkgs) + collect_unregistered!(ctx, pkgs, new) + pkgs = resolve(ctx, pkgs, new, preserve, should_preserve_all) update_env!(ctx, pkgs) - new_apply = download_source(ctx, pkgs; readonly=true) + union!(new, uuids(download_source(ctx, pkgs; readonly=true))) download_artifacts(ctx, pkgs; platform=platform) show_update(ctx) write_env(ctx.env) # write env before building - build_versions(ctx, union(UUID[pkg.uuid for pkg in new_apply], new_git)) + build_versions(ctx, new) end -# load version constraint -# if version isa VersionNumber -> set tree_hash too -up_load_versions!(ctx::Context, pkg::PackageSpec, ::Nothing, level::UpgradeLevel) = false -function up_load_versions!(ctx::Context, pkg::PackageSpec, entry::PackageEntry, level::UpgradeLevel) - entry.version !== nothing || return false # no version to set - if entry.pinned || level == UPLEVEL_FIXED - pkg.version = entry.version - pkg.tree_hash = entry.tree_hash - elseif is_tracking_repo(entry) # repo packages have a version but are treated special - pkg.repo = entry.repo +function update_package!(ctx::Context, pkg::PackageSpec, level::UpgradeLevel, new::Vector{UUID}) + if pkg.pinned || level == UPLEVEL_FIXED + return pkg + end + if is_tracking_repo(pkg) # repo packages have a version but are treated special if level == UPLEVEL_MAJOR - # Updating a repo package is equivalent to adding it - new = Types.handle_repo_add!(ctx, pkg) - pkg.version = entry.version - if pkg.tree_hash != entry.tree_hash - # TODO parse find_installed and set new version - end - return new + Types.handle_repo_add!(ctx, pkg) && push!(new, pkg.uuid) + return pkg else - pkg.version = entry.version - pkg.tree_hash = entry.tree_hash + return pkg end else - ver = entry.version - r = level == UPLEVEL_PATCH ? VersionRange(ver.major, ver.minor) : - level == UPLEVEL_MINOR ? VersionRange(ver.major) : - level == UPLEVEL_MAJOR ? VersionRange() : - error("unexpected upgrade level: $level") - pkg.version = VersionSpec(r) + # TODO pkg.version should only by a number or an empty VersionSpec by this point + if pkg.version isa VersionNumber + r = level == UPLEVEL_PATCH ? VersionRange(pkg.version.major, pkg.version.minor) : + level == UPLEVEL_MINOR ? VersionRange(pkg.version.major) : + VersionRange() + pkg.version = VersionSpec(r) + end + return pkg end - return false -end - -up_load_manifest_info!(pkg::PackageSpec, ::Nothing) = nothing -function up_load_manifest_info!(pkg::PackageSpec, entry::PackageEntry) - pkg.name = entry.name # TODO check name is same - pkg.repo = entry.repo # TODO check that repo is same - pkg.path = entry.path - pkg.pinned = entry.pinned - # `pkg.version` and `pkg.tree_hash` is set by `up_load_versions!` end -function up(ctx::Context, pkgs::Vector{PackageSpec}, level::UpgradeLevel) - new_git = UUID[] - # TODO check all pkg.version == VersionSpec() - # set version constraints according to `level` - for pkg in pkgs - new = up_load_versions!(ctx, pkg, manifest_info(ctx, pkg.uuid), level) - new && push!(new_git, pkg.uuid) #TODO put download + push! in utility function - end - # load rest of manifest data (except for version info) - for pkg in pkgs - up_load_manifest_info!(pkg, manifest_info(ctx, pkg.uuid)) - end - pkgs = load_direct_deps(ctx, pkgs; preserve = (level == UPLEVEL_FIXED ? PRESERVE_NONE : PRESERVE_DIRECT)) - collect_unregistered!(ctx, pkgs, new_git) +function update(ctx::Context, pkgs::Vector{PackageSpec}, new::Vector{UUID}, level::UpgradeLevel) + pkgs = map(pkg -> update_package!(ctx, pkg, level, new), pkgs) + pkgs = load_direct_deps(ctx, pkgs, new; preserve = (level == UPLEVEL_FIXED ? PRESERVE_NONE : PRESERVE_DIRECT)) check_registered(ctx, pkgs) + collect_unregistered!(ctx, pkgs, new) resolve_versions!(ctx, pkgs) prune_manifest(ctx) update_env!(ctx, pkgs) - new_apply = download_source(ctx, pkgs) + union!(new, uuids(download_source(ctx, pkgs))) download_artifacts(ctx, pkgs) show_update(ctx) write_env(ctx.env) # write env before building - build_versions(ctx, union(UUID[pkg.uuid for pkg in new_apply], new_git)) + build_versions(ctx, new) end function pin_package!(ctx::Context, pkg::PackageSpec, entry::PackageEntry) @@ -1265,11 +1232,11 @@ function pin(ctx::Context, pkgs::Vector{PackageSpec}) check_registered(ctx, pkgs) resolve_versions!(ctx, pkgs) update_env!(ctx, pkgs) - new = download_source(ctx, pkgs) + new = uuids(download_source(ctx, pkgs)) download_artifacts(ctx, pkgs) show_update(ctx) write_env(ctx.env) # write env before building - build_versions(ctx, UUID[pkg.uuid for pkg in new]) + build_versions(ctx, new) end function free_package!(ctx::Context, pkg::PackageSpec, entry::PackageEntry) @@ -1303,10 +1270,11 @@ function free(ctx::Context, pkgs::Vector{PackageSpec}) resolve_versions!(ctx, pkgs) update_env!(ctx, pkgs) new = download_source(ctx, pkgs) + # TODO suspicious that this uses `new` instead of pkgs, is this intended? download_artifacts(ctx, new) show_update(ctx) write_env(ctx.env) # write env before building - build_versions(ctx, UUID[pkg.uuid for pkg in new]) + build_versions(ctx, uuids(new)) else foreach(pkg -> manifest_info(ctx, pkg.uuid).pinned = false, pkgs) show_update(ctx) @@ -1583,7 +1551,7 @@ function package_info(ctx::Context, pkg::PackageSpec, entry::PackageEntry)::Pack info = PackageInfo( name = pkg.name, version = pkg.version != VersionSpec() ? pkg.version : nothing, - tree_hash = pkg.tree_hash === nothing ? nothing : string(pkg.tree_hash), # TODO or should it just be a SHA? + tree_hash = pkg.tree_hash === nothing ? nothing : string(pkg.tree_hash), is_direct_dep = pkg.uuid in values(ctx.env.project.deps), is_pinned = pkg.pinned, is_tracking_path = pkg.path !== nothing, @@ -1605,8 +1573,9 @@ function stat_rep(x::PackageSpec; name=true) rev = "" if x.repo.rev !== nothing rev = occursin(r"\b([a-f0-9]{40})\b", x.repo.rev) ? x.repo.rev[1:7] : x.repo.rev + rev = "#$rev" end - repo = Operations.is_tracking_repo(x) ? "`$(x.repo.source)#$(rev)`" : "" + repo = Operations.is_tracking_repo(x) ? "`$(x.repo.source)$(rev)`" : "" path = Operations.is_tracking_path(x) ? "$(pathrepr(x.path))" : "" pinned = x.pinned ? "⚲" : "" return join(filter(!isempty, [name,version,repo,path,pinned]), " ") @@ -1638,11 +1607,11 @@ function diff_array(old_ctx::Union{Context,Nothing}, new_ctx::Context; manifest= return idx === nothing ? nothing : pkgs[idx] end - new = manifest ? load_manifest_deps(new_ctx) : load_direct_deps(new_ctx) + new = manifest ? load_manifest_deps(new_ctx) : load_direct_deps(new_ctx; download=false) if old_ctx === nothing return [(pkg.uuid, nothing, pkg) for pkg in new] end - old = manifest ? load_manifest_deps(old_ctx) : load_direct_deps(old_ctx) + old = manifest ? load_manifest_deps(old_ctx) : load_direct_deps(old_ctx; download=false) all_uuids = union([pkg.uuid for pkg in old], [pkg.uuid for pkg in new]) return [(uuid, index_pkgs(old, uuid), index_pkgs(new, uuid)) for uuid in all_uuids] diff --git a/src/Pkg.jl b/src/Pkg.jl index 37f0d06981..5f239c6498 100644 --- a/src/Pkg.jl +++ b/src/Pkg.jl @@ -167,7 +167,7 @@ If no positional argument is given, `level` can be used to control by how much p See also [`PackageSpec`](@ref), [`PackageMode`](@ref), [`UpgradeLevel`](@ref). """ -const update = API.up +const update = API.update """ Pkg.test(; kwargs...) diff --git a/src/REPLMode/command_declarations.jl b/src/REPLMode/command_declarations.jl index e6722f9613..b53a02f1e8 100644 --- a/src/REPLMode/command_declarations.jl +++ b/src/REPLMode/command_declarations.jl @@ -242,7 +242,7 @@ it will be placed in the first depot of the stack. """ , ],[ :name => "update", :short_name => "up", - :api => API.up, + :api => API.update, :should_splat => false, :arg_count => 0 => Inf, :arg_parser => parse_package, diff --git a/src/Types.jl b/src/Types.jl index 9241be05f1..1dba83cfa7 100644 --- a/src/Types.jl +++ b/src/Types.jl @@ -626,7 +626,6 @@ function handle_repos_add!(ctx::Context, pkgs::AbstractVector{PackageSpec}) end function resolve_projectfile!(ctx, pkg, project_path) - env = ctx.env project_file = projectfile_path(project_path; strict=true) project_file === nothing && pkgerror("could not find project file at `$(project_path)` for package $(err_rep(pkg))") project_data = read_package(project_file) @@ -640,6 +639,8 @@ function resolve_projectfile!(ctx, pkg, project_path) else pkgerror("name `$(project_data.name)` given by project file `$project_file` does not match given name `$(pkg.name)`") end + # TODO should we warn here if no version, make a dummy version, ....? + pkg.version = project_data.version end get_object_or_branch(repo, rev::SHA1) =