Skip to content

Commit

Permalink
Use cache to detect modifications to Base
Browse files Browse the repository at this point in the history
  • Loading branch information
timholy committed Oct 13, 2017
1 parent 4fecd57 commit 3d08650
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 21 deletions.
45 changes: 31 additions & 14 deletions src/Revise.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__precompile__()
__precompile__(true)

module Revise

Expand Down Expand Up @@ -29,6 +29,9 @@ const module2files = Dict{Symbol,Vector{String}}()
# to track non-precompiled packages.
const included_files = Tuple{Module,String}[] # (module, filename)

# Full path to the running Julia's cache of source code defining Base
const basesrccache = joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "base.cache")

## For excluding packages from tracking by Revise
const dont_watch_pkgs = Set{Symbol}()
const silence_pkgs = Set{Symbol}()
Expand Down Expand Up @@ -122,7 +125,6 @@ function parse_pkg_files(modsym::Symbol)
mod = Base.root_module(Symbol(modname))
# For precompiled packages, we can read the source later (whenever we need it)
# from the *.ji cachefile.
fname = normpath(fname)
push!(file2modules, fname=>FileModules(mod, ModDict(), paths[1]))
push!(files, fname)
end
Expand All @@ -149,7 +151,7 @@ function parse_pkg_files(modsym::Symbol)
if isa(pr, Pair)
push!(file2modules, pr)
end
push!(files, normpath(fname))
push!(files, fname)
deleteat!(included_files, i)
else
i += 1
Expand Down Expand Up @@ -246,16 +248,15 @@ function revise_dir_queued(dirname)
@schedule revise_dir_queued(dirname)
end

function revise_file_now(file0)
file = normpath(file0)
function revise_file_now(file)
if !haskey(file2modules, file)
println("Revise is currently tracking the following files: ", keys(file2modules))
error(file, " is not currently being tracked.")
end
oldmd = file2modules[file]
if isempty(oldmd.md)
# Source was never parsed, get it from the precompile cache
src = Base.read_dependency_src(oldmd.cachefile, file)
src = read_from_cache(oldmd, file)
push!(oldmd.md, oldmd.topmod=>OrderedSet{RelocatableExpr}())
if !parse_source!(oldmd.md, src, Symbol(file), 1, oldmd.topmod)
warn("failed to parse cache file source text for ", file)
Expand All @@ -276,6 +277,15 @@ function revise_file_now(file0)
nothing
end

function read_from_cache(fm::FileModules, file::AbstractString)
if fm.cachefile == basesrccache
return open(basesrccache) do io
Base._read_dependency_src(io, file)
end
end
Base.read_dependency_src(fm.cachefile, file)
end

"""
revise()
Expand Down Expand Up @@ -320,9 +330,6 @@ function track(mod::Module, file::AbstractString)
end
track(file::AbstractString) = track(Main, file)

const sysimg_path = # where `baremodule Base` is defined
realpath(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "base", "sysimg.jl"))

"""
Revise.track(Base)
Expand All @@ -334,10 +341,20 @@ At present some files in Base are not trackable, see the README.
"""
function track(mod::Module)
if mod == Base
error("Base tracking is currently broken")
# empty!(new_files)
# parse_source(sysimg_path, Main, dirname(sysimg_path))
# process_parsed_files(new_files)
# Determine when the basesrccache was built
mtcache = mtime(basesrccache)
# Initialize expression-tracking for files, and
# note any modified since Base was built
files = String[]
for (submod, filename) in Base._included_files
push!(file2modules, filename=>FileModules(submod, ModDict(), basesrccache))
push!(files, filename)
if mtime(filename) > mtcache
push!(revision_queue, filename)
end
end
# Add the files to the watch list
process_parsed_files(files)
else
error("no Revise.track recipe for module ", mod)
end
Expand Down Expand Up @@ -437,7 +454,7 @@ function __init__()
end
push!(Base.package_callbacks, watch_package)
push!(Base.include_callbacks,
(mod::Module, fn::AbstractString) -> push!(included_files, (mod, String(fn))))
(mod::Module, fn::AbstractString) -> push!(included_files, (mod, normpath(abspath(fn)))))
mode = get(ENV, "JULIA_REVISE", "auto")
if mode == "auto"
if isdefined(Base, :active_repl_backend)
Expand Down
3 changes: 1 addition & 2 deletions src/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ If parsing `file` fails, `nothing` is returned.
function parse_source(file::AbstractString, mod::Module)
# Create a blank ModDict to store the expressions. Parsing will "fill" this.
md = ModDict(mod=>OrderedSet{RelocatableExpr}())
nfile = normpath(file)
parse_source!(md, file, mod) || return nothing
fm = FileModules(mod, md)
nfile => fm
String(file) => fm
end

"""
Expand Down
7 changes: 2 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,6 @@ end
end
@test li_f() == 1 # unless the include is at toplevel it is not found

@test isfile(Revise.sysimg_path)

pop!(LOAD_PATH)
end

Expand Down Expand Up @@ -569,9 +567,8 @@ revise_f(x) = 2
cd(curdir)

# Tracking Base
# FIXME
# Revise.track(Base)
# @test any(k->endswith(k, "number.jl"), keys(Revise.file2modules))
Revise.track(Base)
@test any(k->endswith(k, "number.jl"), keys(Revise.file2modules))
end

@testset "Cleanup" begin
Expand Down

0 comments on commit 3d08650

Please sign in to comment.