diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index 1f274fd118..77ff1a1c63 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -1,7 +1,7 @@ module WorkspaceManager import UUIDs: UUID import ..Pluto: Configuration, Notebook, Cell, ProcessStatus, ServerSession, ExpressionExplorer, pluto_filename, Token, withtoken, Promise, tamepath, project_relative_path, putnotebookupdates!, UpdateMessage -import ..Pluto.PkgCompat +import ..Pluto.PkgCompat: PkgCompat, AbstractPackageManagement, FullyManaged, ParentProject, NotManaged import ..Configuration: CompilerOptions, _merge_notebook_compiler_options, _resolve_notebook_project_path, _convert_to_flags import ..Pluto.ExpressionExplorer: FunctionName import ..PlutoRunner @@ -79,7 +79,7 @@ function make_workspace((session, notebook)::SN; force_offline::Bool=false)::Wor end function use_nbpkg_environment((session, notebook)::SN, workspace=nothing) - enabled = notebook.nbpkg_ctx !== nothing + enabled = (notebook.nbpkg_ctx isa FullyManaged) if workspace.nbpkg_was_active == enabled return end diff --git a/src/notebook/Notebook.jl b/src/notebook/Notebook.jl index 4326427b99..65e9de6f92 100644 --- a/src/notebook/Notebook.jl +++ b/src/notebook/Notebook.jl @@ -1,8 +1,7 @@ import UUIDs: UUID, uuid1 import .ExpressionExplorer: SymbolsState, FunctionNameSignaturePair, FunctionName import .Configuration -import .PkgCompat: PkgCompat, PkgContext -import Pkg +import .PkgCompat: PkgCompat, PkgContext, AbstractPackageManagement, FullyManaged, ParentProject, NotManaged mutable struct BondValue value::Any @@ -42,7 +41,7 @@ Base.@kwdef mutable struct Notebook # nothing means to use global session compiler options compiler_options::Union{Nothing,Configuration.CompilerOptions}=nothing # nbpkg_ctx::Union{Nothing,PkgContext}=nothing - nbpkg_ctx::Union{Nothing,PkgContext}=PkgCompat.create_empty_ctx() + nbpkg_ctx::AbstractPackageManagement=FullyManaged() nbpkg_ctx_instantiated::Bool=false nbpkg_restart_recommended_msg::Union{Nothing,String}=nothing nbpkg_restart_required_msg::Union{Nothing,String}=nothing @@ -126,7 +125,7 @@ function save_notebook(io, notebook::Notebook) end - using_plutopkg = notebook.nbpkg_ctx !== nothing + using_plutopkg = notebook.nbpkg_ctx isa FullyManaged write_package = if using_plutopkg ptoml_path = joinpath(PkgCompat.env_dir(notebook.nbpkg_ctx), "Project.toml") @@ -267,7 +266,7 @@ function load_notebook_nobackup(io, path)::Notebook end else PkgCompat.create_empty_ctx() - end + end |> FullyManaged appeared_order = setdiff(cell_order ∩ keys(collected_cells), [_ptoml_cell_id, _mtoml_cell_id]) appeared_cells_dict = filter(collected_cells) do (k, v) @@ -350,7 +349,9 @@ function move_notebook!(notebook::Notebook, newpath::String; disable_writing_not if isdir("$oldpath_tame.assets") mv("$oldpath_tame.assets", "$newpath_tame.assets") end - notebook + return ( + dir_changed=(dirname(oldpath_tame) == dirnmae(newpath_tame)), + ) end function sample_notebook(name::String) diff --git a/src/notebook/PathHelpers.jl b/src/notebook/PathHelpers.jl index 544a3f7ccf..344f33f87c 100644 --- a/src/notebook/PathHelpers.jl +++ b/src/notebook/PathHelpers.jl @@ -48,9 +48,14 @@ function cutename() titlecase(rand(adjectives)) * " " * rand(nouns) end +const default_notebook_dir = joinpath(first(DEPOT_PATH), "pluto_notebooks") +const default_notebook_dirs = [ + default_notebook_dir +] + function new_notebooks_directory() try - path = joinpath(first(DEPOT_PATH), "pluto_notebooks") + path = default_notebook_dir if !isdir(path) mkdir(path) end diff --git a/src/packages/Packages.jl b/src/packages/Packages.jl index ce5038ffc1..de21882284 100644 --- a/src/packages/Packages.jl +++ b/src/packages/Packages.jl @@ -1,7 +1,7 @@ import .ExpressionExplorer: external_package_names import .PkgCompat -import .PkgCompat: select, is_stdlib +import .PkgCompat: select, is_stdlib, AbstractPackageManagement, FullyManaged, ParentProject, NotManaged const tiers = [ Pkg.PRESERVE_ALL, @@ -13,8 +13,8 @@ const tiers = [ const pkg_token = Token() -function use_plutopkg(topology::NotebookTopology) - !any(values(topology.nodes)) do node +function is_manually_activated(topology::NotebookTopology) + any(values(topology.nodes)) do node Symbol("Pkg.activate") ∈ node.references || Symbol("Pkg.API.activate") ∈ node.references || Symbol("Pkg.add") ∈ node.references || @@ -22,6 +22,20 @@ function use_plutopkg(topology::NotebookTopology) end end +function which_management(topology::NotebookTopology, path::String) + if is_manually_activated(topology) + NotManaged, nothing + else + new_parent_dir = PkgCompat.find_parent_project(path) + if new_parent_dir !== nothing + ParentProject, new_parent_dir + else + FullyManaged, nothing + end + end +end +which_management(notebook::Notebook) = which_management(notebook.topology, notebook.path) + function external_package_names(topology::NotebookTopology)::Set{Symbol} union!(Set{Symbol}(), external_package_names.(c.module_usings_imports for c in values(topology.codes))...) end @@ -45,17 +59,21 @@ Update the notebook package environment to match the notebook's code. This will: function sync_nbpkg_core(notebook::Notebook; on_terminal_output::Function=((args...) -> nothing)) 👺 = false + + new_management_type, new_parent_dir = which_management(notebook) + + use_parent_project_old = notebook.nbpkg_ctx isa ParentProject + use_parent_project_new = new_management_type === ParentProject - use_plutopkg_old = notebook.nbpkg_ctx !== nothing - use_plutopkg_new = use_plutopkg(notebook.topology) + use_plutopkg_old = notebook.nbpkg_ctx isa FullyManaged + use_plutopkg_new = new_management_type === FullyManaged if !use_plutopkg_old && use_plutopkg_new @info "Started using PlutoPkg!! HELLO reproducibility!" 👺 = true - notebook.nbpkg_ctx = PkgCompat.create_empty_ctx() - end - if use_plutopkg_old && !use_plutopkg_new + notebook.nbpkg_ctx = FullyManaged() + elseif use_plutopkg_old && !use_plutopkg_new @info "Stopped using PlutoPkg 💔😟😢" no_packages_loaded_yet = ( @@ -64,11 +82,32 @@ function sync_nbpkg_core(notebook::Notebook; on_terminal_output::Function=((args all(PkgCompat.is_stdlib, keys(PkgCompat.project(notebook.nbpkg_ctx).dependencies)) ) 👺 = !no_packages_loaded_yet - notebook.nbpkg_ctx = nothing + notebook.nbpkg_ctx = if use_parent_project_new + ParentProject(new_parent_dir) + else + NotManaged() + end + elseif !use_plutopkg_old && !use_plutopkg_new + if use_parent_project_new + if use_parent_project_old + if notebook.nbpkg_ctx.dir != new_parent_dir + 👺 = true + notebook.nbpkg_ctx = ParentProject(new_parent_dir) + end + else + 👺 = true + notebook.nbpkg_ctx = ParentProject(new_parent_dir) + end + else + if use_parent_project_old + 👺 = true + notebook.nbpkg_ctx = NotManaged() + end + end end - if notebook.nbpkg_ctx !== nothing + if notebook.nbpkg_ctx isa FullyManaged PkgCompat.mark_original!(notebook.nbpkg_ctx) old_packages = String.(keys(PkgCompat.project(notebook.nbpkg_ctx).dependencies)) @@ -101,11 +140,11 @@ function sync_nbpkg_core(notebook::Notebook; on_terminal_output::Function=((args PkgCompat.withio(notebook.nbpkg_ctx, IOContext(iolistener.buffer, :color => true)) do withinteractive(false) do try - Pkg.resolve(notebook.nbpkg_ctx) + Pkg.resolve(notebook.nbpkg_ctx.ctx) catch e @warn "Failed to resolve Pkg environment. Removing Manifest and trying again..." exception=e reset_nbpkg(notebook; keep_project=true, save=false, backup=false) - Pkg.resolve(notebook.nbpkg_ctx) + Pkg.resolve(notebook.nbpkg_ctx.ctx) end end end @@ -120,7 +159,7 @@ function sync_nbpkg_core(notebook::Notebook; on_terminal_output::Function=((args mkeys() = Set(filter(!is_stdlib, [m.name for m in values(PkgCompat.dependencies(notebook.nbpkg_ctx))])) old_manifest_keys = mkeys() - Pkg.rm(notebook.nbpkg_ctx, [ + Pkg.rm(notebook.nbpkg_ctx.ctx, [ Pkg.PackageSpec(name=p) for p in to_remove ]) @@ -156,7 +195,7 @@ function sync_nbpkg_core(notebook::Notebook; on_terminal_output::Function=((args used_tier = tier try - Pkg.add(notebook.nbpkg_ctx, [ + Pkg.add(notebook.nbpkg_ctx.ctx, [ Pkg.PackageSpec(name=p) for p in to_add ]; preserve=used_tier) @@ -313,23 +352,29 @@ end function reset_nbpkg(notebook::Notebook; keep_project::Bool=false, backup::Bool=true, save::Bool=true) backup && save && writebackup(notebook) - if notebook.nbpkg_ctx !== nothing + if notebook.nbpkg_ctx isa FullyManaged p = PkgCompat.project_file(notebook) m = PkgCompat.manifest_file(notebook) keep_project || (isfile(p) && rm(p)) isfile(m) && rm(m) - notebook.nbpkg_ctx = PkgCompat.load_ctx(PkgCompat.env_dir(notebook.nbpkg_ctx)) + notebook.nbpkg_ctx = FullyManaged(PkgCompat.load_ctx(PkgCompat.env_dir(notebook.nbpkg_ctx))) else - notebook.nbpkg_ctx = use_plutopkg(notebook.topology) ? PkgCompat.create_empty_ctx() : nothing + new_management_type, new_parent_dir = which_management(notebook) + new_parent_dir = PkgCompat.find_parent_project(notebook.path) + use_parent_project_new = new_parent_dir !== nothing + + notebook.nbpkg_ctx = new_management_type === ParentProject ? + ParentProject(new_parent_dir) : + new_management_type() end save && save_notebook(notebook) end function update_nbpkg_core(notebook::Notebook; level::Pkg.UpgradeLevel=Pkg.UPLEVEL_MAJOR, on_terminal_output::Function=((args...) -> nothing)) - if notebook.nbpkg_ctx !== nothing - PkgCompat.mark_original!(notebook.nbpkg_ctx) + if notebook.nbpkg_ctx isa FullyManaged + PkgCompat.mark_original!(notebook.nbpkg_ctx.ctx) old_packages = String.(keys(PkgCompat.project(notebook.nbpkg_ctx).dependencies)) @@ -354,11 +399,11 @@ function update_nbpkg_core(notebook::Notebook; level::Pkg.UpgradeLevel=Pkg.UPLEV PkgCompat.withio(notebook.nbpkg_ctx, IOContext(iolistener.buffer, :color => true)) do withinteractive(false) do try - Pkg.resolve(notebook.nbpkg_ctx) + Pkg.resolve(notebook.nbpkg_ctx.ctx) catch e @warn "Failed to resolve Pkg environment. Removing Manifest and trying again..." exception=e reset_nbpkg(notebook; keep_project=true, save=false, backup=false) - Pkg.resolve(notebook.nbpkg_ctx) + Pkg.resolve(notebook.nbpkg_ctx.ctx) end end end @@ -372,7 +417,7 @@ function update_nbpkg_core(notebook::Notebook; level::Pkg.UpgradeLevel=Pkg.UPLEV try ### - Pkg.update(notebook.nbpkg_ctx; level=level) + Pkg.update(notebook.nbpkg_ctx.ctx; level=level) ### finally notebook.nbpkg_ctx = PkgCompat.write_auto_compat_entries(notebook.nbpkg_ctx) @@ -440,6 +485,8 @@ end nbpkg_cache(ctx::Union{Nothing,PkgContext}) = ctx === nothing ? Dict{String,String}() : Dict{String,String}( x => string(PkgCompat.get_manifest_version(ctx, x)) for x in keys(PkgCompat.project(ctx).dependencies) ) +nbpkg_cache(ctx::FullyManaged) = nbpkg_cache(ctx.ctx) +nbpkg_cache(ctx::AbstractPackageManagement) = nbpkg_cache(nothing) function update_nbpkg_cache!(notebook::Notebook) notebook.nbpkg_installed_versions_cache = nbpkg_cache(notebook.nbpkg_ctx) diff --git a/src/packages/PkgCompat.jl b/src/packages/PkgCompat.jl index e2d4872862..582836bc1f 100644 --- a/src/packages/PkgCompat.jl +++ b/src/packages/PkgCompat.jl @@ -42,14 +42,10 @@ I tried to only use public API, except: =# - - - ### -# CONTEXT +# TYPES ### - const PkgContext = if isdefined(Pkg, :Context) Pkg.Context elseif isdefined(Pkg, :Types) && isdefined(Pkg.Types, :Context) @@ -60,6 +56,38 @@ else Pkg.Types.Context end + +abstract type AbstractPackageManagement end + +struct FullyManaged <: AbstractPackageManagement + ctx::PkgContext +end +FullyManaged() = FullyManaged(create_empty_ctx()) + +struct ParentProject <: AbstractPackageManagement + dir::String +end + +struct NotManaged <: AbstractPackageManagement +end + + +function find_parent_project(start_dir::String) + found = start_dir |> Pluto.tamepath |> current_project + if found === nothing + found + else + dirname(found) + end +end + + + +### +# CONTEXT +### + + # 🐸 "Public API", but using PkgContext load_ctx(env_dir)::PkgContext = PkgContext(env=Pkg.Types.EnvCache(joinpath(env_dir, "Project.toml"))) @@ -89,6 +117,7 @@ function mark_original!(ctx::PkgContext) @warn "Pkg compat: failed to set original_project" exception=(e,catch_backtrace()) end end +mark_original!(ctx::FullyManaged) = mark_original!(ctx.ctx) # ⚠️ Internal API with fallback function is_original(ctx::PkgContext)::Bool @@ -100,6 +129,7 @@ function is_original(ctx::PkgContext)::Bool false end end +is_original(ctx::FullyManaged) = is_original(ctx.ctx) @@ -112,6 +142,13 @@ project_file(ctx::PkgContext) = joinpath(env_dir(ctx), "Project.toml") manifest_file(ctx::PkgContext) = joinpath(env_dir(ctx), "Manifest.toml") +env_dir(ctx::FullyManaged) = env_dir(ctx.ctx) +dependencies(ctx::FullyManaged) = dependencies(ctx.ctx) +project(ctx::FullyManaged) = project(ctx.ctx) +project_file(ctx::FullyManaged) = project_file(ctx.ctx) +manifest_file(ctx::FullyManaged) = manifest_file(ctx.ctx) + + # ⚠️ Internal API with fallback function withio(f::Function, ctx::PkgContext, io::IO) @static if :io ∈ fieldnames(PkgContext) @@ -129,6 +166,8 @@ function withio(f::Function, ctx::PkgContext, io::IO) end end +withio(f::Function, ctx::FullyManaged, io::IO) = withio(f, ctx.ctx, io) + ### # REGISTRIES @@ -180,6 +219,8 @@ function update_registries(ctx) end end end +update_registries(ctx::FullyManaged; kwargs...) = update_registries(ctx.ctx; kwargs...) + # ⚠️✅ Internal API with fallback function instantiate(ctx; update_registry::Bool) @@ -189,6 +230,7 @@ function instantiate(ctx; update_registry::Bool) Pkg.instantiate(ctx) end end +instantiate(ctx::FullyManaged; kwargs...) = instantiate(ctx.ctx; kwargs...) @@ -363,6 +405,7 @@ function get_manifest_version(ctx::PkgContext, package_name::AbstractString) entry === nothing ? nothing : entry.version end end +get_manifest_version(ctx::FullyManaged, package_name::AbstractString) = get_manifest_version(ctx.ctx, package_name) ### # WRITING COMPAT ENTRIES @@ -445,5 +488,42 @@ function clear_stdlib_compat_entries(ctx::PkgContext)::PkgContext end end +write_auto_compat_entries(ctx::FullyManaged) = FullyManaged(write_auto_compat_entries(ctx.ctx)) +clear_auto_compat_entries(ctx::FullyManaged) = FullyManaged(clear_auto_compat_entries(ctx.ctx)) +clear_stdlib_compat_entries(ctx::FullyManaged) = FullyManaged(clear_stdlib_compat_entries(ctx.ctx)) + + +## some Base compat + + + +# copied from julia/base/initdefs.jl with some changes: +const project_names = ("JuliaProject.toml", "Project.toml") + +function current_project(dir::AbstractString) + # look for project file in current dir and parents + home = homedir() + while true + for proj in project_names + file = joinpath(dir, proj) + isfile(file) && return file + end + # bail at home directory + (dir == home || Pluto.tamepath(dir) ∈ Pluto.default_notebook_dirs) && break + old, dir = dir, dirname(dir) + dir == old && break + end +end + +# compat +function isfile_casesensitive(path) + @static if isdefined(Base, :isfile_casesensitive) && hasmethod(Base.isfile_casesensitive, (String,)) + Base.isfile_casesensitive(path) + else + isfile(path) + end +end + + end \ No newline at end of file diff --git a/src/packages/PkgUtils.jl b/src/packages/PkgUtils.jl index 52f3d91662..460dd394bf 100644 --- a/src/packages/PkgUtils.jl +++ b/src/packages/PkgUtils.jl @@ -10,7 +10,7 @@ using Markdown export activate_notebook -ensure_has_nbpkg(notebook::Notebook) = if notebook.nbpkg_ctx === nothing +ensure_has_nbpkg(notebook::Notebook) = if (notebook.nbpkg_ctx isa FullyManaged) # TODO: update_save the notebook to init packages and stuff? error(""" @@ -63,7 +63,7 @@ end function write_dir_to_nb(dir::String, notebook::Notebook) assert_has_manifest(dir) - notebook.nbpkg_ctx = Pluto.PkgCompat.create_empty_ctx() + notebook.nbpkg_ctx = Pluto.PkgCompat.FullyManaged() readwrite(dir |> project_file, notebook |> project_file) readwrite(dir |> manifest_file, notebook |> manifest_file) diff --git a/src/webserver/Dynamic.jl b/src/webserver/Dynamic.jl index 7868a47d0c..7a9cd898e8 100644 --- a/src/webserver/Dynamic.jl +++ b/src/webserver/Dynamic.jl @@ -149,12 +149,14 @@ function notebook_to_js(notebook::Notebook) for (key, bondvalue) in notebook.bonds), "nbpkg" => let ctx = notebook.nbpkg_ctx + enabled = ctx isa PkgCompat.FullyManaged Dict{String,Any}( - "enabled" => ctx !== nothing, + "enabled" => enabled, + "parent_project" => (ctx isa PkgCompat.ParentProject) ? ctx.dir : nothing, "restart_recommended_msg" => notebook.nbpkg_restart_recommended_msg, "restart_required_msg" => notebook.nbpkg_restart_required_msg, # TODO: cache this - "installed_versions" => ctx === nothing ? Dict{String,String}() : notebook.nbpkg_installed_versions_cache, + "installed_versions" => enabled ? notebook.nbpkg_installed_versions_cache : Dict{String,String}(), "terminal_outputs" => notebook.nbpkg_terminal_outputs, "busy_packages" => notebook.nbpkg_busy_packages, "instantiated" => notebook.nbpkg_ctx_instantiated, @@ -230,9 +232,10 @@ const effects_of_changed_state = Dict( if isfile(newpath) error("File exists already - you need to delete the old file manually.") else - move_notebook!(request.notebook, newpath; disable_writing_notebook_files=request.session.options.server.disable_writing_notebook_files) + (dir_changed,) = move_notebook!(request.notebook, newpath; disable_writing_notebook_files=request.session.options.server.disable_writing_notebook_files) putplutoupdates!(request.session, clientupdate_notebook_list(request.session.notebooks)) WorkspaceManager.cd_workspace((request.session, request.notebook), newpath) + dir_changed && sync_nbpkg(request.session, request.notebook) end return no_changes end, diff --git a/test/packages/Basic.jl b/test/packages/Basic.jl index 3c8aa60e9e..b077908b83 100644 --- a/test/packages/Basic.jl +++ b/test/packages/Basic.jl @@ -5,7 +5,7 @@ using Pluto.Configuration: CompilerOptions using Pluto.WorkspaceManager: _merge_notebook_compiler_options import Pluto: update_save_run!, update_run!, WorkspaceManager, ClientSession, ServerSession, Notebook, Cell, project_relative_path, SessionActions, load_notebook import Pluto.PkgUtils -import Pluto.PkgCompat +import Pluto.PkgCompat: PkgCompat, AbstractPackageManagement, FullyManaged, ParentProject, NotManaged import Distributed const pluto_test_registry_spec = Pkg.RegistrySpec(; @@ -50,7 +50,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test notebook.cells[7].errored == false @test notebook.cells[8].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @test notebook.nbpkg_ctx_instantiated @@ -79,7 +79,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test notebook.cells[3].errored == false @test notebook.cells[4].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -97,7 +97,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test notebook.cells[5].errored == false @test notebook.cells[6].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test ( notebook.nbpkg_restart_recommended_msg !== nothing || notebook.nbpkg_restart_required_msg !== nothing ) @@ -125,7 +125,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test notebook.cells[7].errored == false @test notebook.cells[8].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -139,7 +139,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; update_save_run!(🍭, notebook, notebook.cells[9]) @test notebook.cells[9].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -188,7 +188,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; # removing a stdlib does not require a restart @test notebook.cells[9].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -200,7 +200,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; update_save_run!(🍭, notebook, notebook.cells[7]) @test notebook.cells[7].errored == false - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg !== nothing # recommend restart @test notebook.nbpkg_restart_required_msg === nothing @@ -228,7 +228,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test num_backups_in(dir) == 0 - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -269,7 +269,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test notebook.cells[1].errored == false @test notebook.cells[2].errored == false - @test notebook.nbpkg_ctx === nothing + @test notebook.nbpkg_ctx isa NotManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @test !has_embedded_pkgfiles(notebook) @@ -291,7 +291,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; setcode(notebook.cells[3], "3") update_save_run!(🍭, notebook, notebook.cells[2:3]) - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_required_msg !== nothing @test has_embedded_pkgfiles(notebook) @@ -326,7 +326,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test length(post_pkg_notebook) > length(pre_pkg_notebook) + 50 @test has_embedded_pkgfiles(notebook) - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing @@ -461,7 +461,7 @@ const pluto_test_registry_spec = Pkg.RegistrySpec(; @test !Pluto.only_versions_differ(notebook.path, original_path) - @test notebook.nbpkg_ctx !== nothing + @test notebook.nbpkg_ctx isa FullyManaged @test notebook.nbpkg_restart_recommended_msg === nothing @test notebook.nbpkg_restart_required_msg === nothing