Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ jobs:
julia --project --code-coverage=user -e 'ENV["JULIA_REVISE_POLL"]="1"; using Pkg, Revise; include(joinpath(dirname(pathof(Revise)), "..", "test", "polling.jl"))'
# The REPL wasn't initialized, so the "Methods at REPL" tests didn't run. Pick those up now.
TERM="xterm" julia --project --code-coverage=user -e 'using InteractiveUtils, REPL, Revise; @async(Base.run_main_repl(true, true, false, true, false)); sleep(2); Revise.async_steal_repl_backend(); include(joinpath("test", "runtests.jl")); REPL.eval_user_input(:(exit()), Base.active_repl_backend)' "Methods at REPL"
# Tests for out-of-process updates to manifest
bash test/envs/use_exputils/setup.sh
julia --project --code-coverage=user test/envs/use_exputils/switch_version.jl
# We also need to pick up the Git tests, but for that we need to `dev` the package
julia --code-coverage=user -e 'using Pkg; Pkg.develop(PackageSpec(path=".")); include(joinpath("test", "runtests.jl"))' "Git"
# # Running out of inotify storage (see #26)
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ docs/src/figures/diagram.pdf
Manifest.toml
src/aliasnewstruct.jl
.vscode
test/envs/use_exputils/Project.toml
19 changes: 15 additions & 4 deletions src/packagedef.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optle
@eval Base.Experimental.@optlevel 1
end

using FileWatching, REPL, Distributed, UUIDs
using FileWatching, REPL, Distributed, UUIDs, Pkg
import LibGit2
using Base: PkgId
using Base.Meta: isexpr
Expand Down Expand Up @@ -80,6 +80,13 @@ the OS.
"""
const watched_files = Dict{String,WatchList}()

"""
Revise.watched_manifests

Global variable, a set of `Manifest.toml` files from the active projects used during this session.
"""
const watched_manifests = Set{String}()

"""
Revise.revision_queue

Expand Down Expand Up @@ -1375,11 +1382,15 @@ function __init__()
CodeTracking.method_lookup_callback[] = get_def
CodeTracking.expressions_callback[] = get_expressions

# Register the active-project watcher
if isdefined(Pkg.Types, :active_project_watcher_thunks)
push!(Pkg.Types.active_project_watcher_thunks, active_project_watcher)
end

# Watch the manifest file for changes
mfile = manifest_file()
if mfile === nothing
@warn "no Manifest.toml file found, static paths used"
else
if mfile !== nothing
push!(watched_manifests, mfile)
wmthunk = TaskThunk(watch_manifest, (mfile,))
schedule(Task(wmthunk))
end
Expand Down
41 changes: 34 additions & 7 deletions src/pkgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ function watch_manifest(mfile)
# issue #459
(isa(e, InterruptException) && throwto_repl(e)) || throw(e)
end
manifest_file() == mfile || continue # process revisions only if this is the active manifest
try
with_logger(_debug_logger) do
@debug "Pkg" _group="manifest_update" manifest_file=mfile
Expand All @@ -522,12 +523,32 @@ function watch_manifest(mfile)
end
# Revise code as needed
files = String[]
mustnotify = false
for file in srcfiles(pkgdata)
maybe_extract_sigs!(maybe_parse_from_cache!(pkgdata, file))
fi = try
maybe_parse_from_cache!(pkgdata, file)
catch err
# https://github.com/JuliaLang/julia/issues/42404
# Get the source-text from the package source instead
fi = fileinfo(pkgdata, file)
if isempty(fi.modexsigs) && (!isempty(fi.cachefile) || !isempty(fi.cacheexprs))
filep = joinpath(basedir(pkgdata), file)
src = read(filep, String)
topmod = first(keys(fi.modexsigs))
if parse_source!(fi.modexsigs, src, filep, topmod) === nothing
@error "failed to parse source text for $filep"
end
add_modexs!(fi, fi.cacheexprs)
empty!(fi.cacheexprs)
end
fi
end
maybe_extract_sigs!(fi)
push!(revision_queue, (pkgdata, file))
push!(files, file)
notify(revision_event)
mustnotify = true
end
mustnotify && notify(revision_event)
# Update the directory
pkgdata.info.basedir = pkgdir
# Restart watching, if applicable
Expand All @@ -539,11 +560,17 @@ function watch_manifest(mfile)
end
end
catch err
@static if VERSION >= v"1.2.0-DEV.253"
put!(Base.active_repl_backend.response_channel, (Base.catch_stack(), true))
else
put!(Base.active_repl_backend.response_channel, (err, catch_backtrace()))
end
@error "Error watching manifest" exception=(err, trim_toplevel!(catch_backtrace()))
end
end
end

function active_project_watcher()
mfile = manifest_file()
if mfile ∉ watched_manifests
push!(watched_manifests, mfile)
wmthunk = TaskThunk(watch_manifest, (mfile,))
schedule(Task(wmthunk))
end
return
end
8 changes: 8 additions & 0 deletions test/envs/use_exputils/install.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This gets run by setup.sh

using Pkg

Pkg.activate(@__DIR__)
Pkg.add(name="ExponentialUtilities", version=ARGS[1])

using ExponentialUtilities
10 changes: 10 additions & 0 deletions test/envs/use_exputils/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# Ensure that packages that get updated indirectly by external
# manifest updates work as well as can be hoped.
# See https://github.com/timholy/Revise.jl/issues/647

# Install and compile two versions of ExponentialUtilities
dn=$(dirname "$BASH_SOURCE")
julia $dn/install.jl "1.10.0"
julia $dn/install.jl "1.9.0"
25 changes: 25 additions & 0 deletions test/envs/use_exputils/switch_version.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This test is intended to be run after `setup.sh` runs. ExponentialUtilities
# should be held at v1.9.0.

using Revise, Pkg, Test

const thisdir = dirname(@__FILE__)
Pkg.activate(thisdir)
# This is only needed on Pkg versions that don't notify
Revise.active_project_watcher()

using ExponentialUtilities
id = Base.PkgId(ExponentialUtilities)
pkgdata = Revise.pkgdatas[id]
A = rand(3, 3); A = A'*A; A = A' + A;
@test_throws UndefVarError exponential!(A) # not present on v1.9
# From a different process, switch the active version of ExponentialUtilities
run(Cmd(`julia -e 'using Pkg; Pkg.activate("."); Pkg.add(name="ExponentialUtilities", version="1.10.0")'`; dir=thisdir))
sleep(0.2)
revise()
@test exponential!(A) isa Matrix # present on v1.9
# ...and then switch back (check that it's bidirectional and also to reset state)
run(Cmd(`julia -e 'using Pkg; Pkg.activate("."); Pkg.add(name="ExponentialUtilities", version="1.9.0")'`; dir=thisdir))
sleep(0.2)
revise()
@test_throws MethodError exponential!(A) # not present on v1.9