@@ -824,9 +824,19 @@ function require(into::Module, mod::Symbol)
824
824
return require (uuidkey, cache)
825
825
end
826
826
827
+ struct PkgOrigin
828
+ # version::VersionNumber
829
+ # path::String
830
+ cachepath:: Union{String,Nothing}
831
+ end
832
+ const pkgorigins = Dict {PkgId,PkgOrigin} ()
833
+
827
834
function require (uuidkey:: PkgId , cache:: TOMLCache = TOMLCache ())
828
835
if ! root_module_exists (uuidkey)
829
- _require (uuidkey, cache)
836
+ cachefile = _require (uuidkey, cache)
837
+ if cachefile != = nothing
838
+ pkgorigins[uuidkey] = PkgOrigin (cachefile)
839
+ end
830
840
# After successfully loading, notify downstream consumers
831
841
for callback in package_callbacks
832
842
invokelatest (callback, uuidkey)
@@ -881,6 +891,7 @@ function unreference_module(key::PkgId)
881
891
end
882
892
end
883
893
894
+ # Returns `nothing` or the name of the newly-created cachefile
884
895
function _require (pkg:: PkgId , cache:: TOMLCache )
885
896
# handle recursive calls to require
886
897
loading = get (package_locks, pkg, false )
@@ -942,7 +953,7 @@ function _require(pkg::PkgId, cache::TOMLCache)
942
953
if isa (m, Exception)
943
954
@warn " The call to compilecache failed to create a usable precompiled cache file for $pkg " exception= m
944
955
else
945
- return
956
+ return cachefile
946
957
end
947
958
end
948
959
end
@@ -1257,6 +1268,13 @@ module_build_id(m::Module) = ccall(:jl_module_build_id, UInt64, (Any,), m)
1257
1268
isvalid_cache_header (f:: IOStream ) = (0 != ccall (:jl_read_verify_header , Cint, (Ptr{Cvoid},), f. ios))
1258
1269
isvalid_file_crc (f:: IOStream ) = (_crc32c (seekstart (f), filesize (f) - 4 ) == read (f, UInt32))
1259
1270
1271
+ struct CacheHeaderIncludes
1272
+ id:: PkgId
1273
+ filename:: String
1274
+ mtime:: Float64
1275
+ modpath:: Vector{String} # seemingly not needed in Base, but used by Revise
1276
+ end
1277
+
1260
1278
function parse_cache_header (f:: IO )
1261
1279
modules = Vector {Pair{PkgId, UInt64}} ()
1262
1280
while true
@@ -1270,7 +1288,7 @@ function parse_cache_header(f::IO)
1270
1288
totbytes = read (f, Int64) # total bytes for file dependencies
1271
1289
# read the list of requirements
1272
1290
# and split the list into include and requires statements
1273
- includes = Tuple{PkgId, String, Float64} []
1291
+ includes = CacheHeaderIncludes []
1274
1292
requires = Pair{PkgId, PkgId}[]
1275
1293
while true
1276
1294
n2 = read (f, Int32)
@@ -1280,20 +1298,21 @@ function parse_cache_header(f::IO)
1280
1298
n1 = read (f, Int32)
1281
1299
# map ids to keys
1282
1300
modkey = (n1 == 0 ) ? PkgId (" " ) : modules[n1]. first
1301
+ modpath = String[]
1283
1302
if n1 != 0
1284
- # consume (and ignore) the module path too
1303
+ # determine the complete module path
1285
1304
while true
1286
1305
n1 = read (f, Int32)
1287
1306
totbytes -= 4
1288
1307
n1 == 0 && break
1289
- skip (f, n1) # String(read(f, n1))
1308
+ push! (modpath, String (read (f, n1) ))
1290
1309
totbytes -= n1
1291
1310
end
1292
1311
end
1293
1312
if depname[1 ] == ' \0 '
1294
1313
push! (requires, modkey => binunpack (depname))
1295
1314
else
1296
- push! (includes, (modkey, depname, mtime))
1315
+ push! (includes, CacheHeaderIncludes (modkey, depname, mtime, modpath ))
1297
1316
end
1298
1317
totbytes -= 4 + 4 + n2 + 8
1299
1318
end
@@ -1312,19 +1331,28 @@ function parse_cache_header(f::IO)
1312
1331
return modules, (includes, requires), required_modules, srctextpos
1313
1332
end
1314
1333
1315
- function parse_cache_header (cachefile:: String )
1334
+ function parse_cache_header (cachefile:: String ; srcfiles_only :: Bool = false )
1316
1335
io = open (cachefile, " r" )
1317
1336
try
1318
1337
! isvalid_cache_header (io) && throw (ArgumentError (" Invalid header in cache file $cachefile ." ))
1319
- return parse_cache_header (io)
1338
+ ret = parse_cache_header (io)
1339
+ srcfiles_only || return ret
1340
+ modules, (includes, requires), required_modules, srctextpos = ret
1341
+ srcfiles = srctext_files (io, srctextpos)
1342
+ delidx = Int[]
1343
+ for (i, chi) in enumerate (includes)
1344
+ chi. filename ∈ srcfiles || push! (delidx, i)
1345
+ end
1346
+ deleteat! (includes, delidx)
1347
+ return modules, (includes, requires), required_modules, srctextpos
1320
1348
finally
1321
1349
close (io)
1322
1350
end
1323
1351
end
1324
1352
1325
1353
function cache_dependencies (f:: IO )
1326
1354
defs, (includes, requires), modules = parse_cache_header (f)
1327
- return modules, map (mod_fl_mt -> (mod_fl_mt[ 2 ], mod_fl_mt[ 3 ] ), includes) # discard the module
1355
+ return modules, map (chi -> (chi . filename, chi . mtime ), includes) # return just filename and mtime
1328
1356
end
1329
1357
1330
1358
function cache_dependencies (cachefile:: String )
@@ -1368,6 +1396,21 @@ function read_dependency_src(cachefile::String, filename::AbstractString)
1368
1396
end
1369
1397
end
1370
1398
1399
+ function srctext_files (f:: IO , srctextpos:: Int64 )
1400
+ files = Set {String} ()
1401
+ srctextpos == 0 && return files
1402
+ seek (f, srctextpos)
1403
+ while ! eof (f)
1404
+ filenamelen = read (f, Int32)
1405
+ filenamelen == 0 && break
1406
+ fn = String (read (f, filenamelen))
1407
+ len = read (f, UInt64)
1408
+ push! (files, fn)
1409
+ seek (f, position (f) + len)
1410
+ end
1411
+ return files
1412
+ end
1413
+
1371
1414
# returns true if it "cachefile.ji" is stale relative to "modpath.jl"
1372
1415
# otherwise returns the list of dependencies to also check
1373
1416
stale_cachefile (modpath:: String , cachefile:: String ) = stale_cachefile (modpath, cachefile, TOMLCache ())
@@ -1379,6 +1422,7 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
1379
1422
return true # invalid cache file
1380
1423
end
1381
1424
(modules, (includes, requires), required_modules) = parse_cache_header (io)
1425
+ id = isempty (modules) ? nothing : first (modules). first
1382
1426
modules = Dict {PkgId, UInt64} (modules)
1383
1427
1384
1428
# Check if transitive dependencies can be fulfilled
@@ -1423,8 +1467,8 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
1423
1467
1424
1468
# now check if this file is fresh relative to its source files
1425
1469
if ! skip_timecheck
1426
- if ! samefile (includes[1 ][ 2 ] , modpath)
1427
- @debug " Rejecting cache file $cachefile because it is for file $(includes[1 ][ 2 ] ) ) not file $modpath "
1470
+ if ! samefile (includes[1 ]. filename , modpath)
1471
+ @debug " Rejecting cache file $cachefile because it is for file $(includes[1 ]. filename ) ) not file $modpath "
1428
1472
return true # cache file was compiled from a different path
1429
1473
end
1430
1474
for (modkey, req_modkey) in requires
@@ -1434,7 +1478,8 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
1434
1478
return true
1435
1479
end
1436
1480
end
1437
- for (_, f, ftime_req) in includes
1481
+ for chi in includes
1482
+ f, ftime_req = chi. filename, chi. mtime
1438
1483
# Issue #13606: compensate for Docker images rounding mtimes
1439
1484
# Issue #20837: compensate for GlusterFS truncating mtimes to microseconds
1440
1485
ftime = mtime (f)
@@ -1450,6 +1495,10 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
1450
1495
return true
1451
1496
end
1452
1497
1498
+ if isa (id, PkgId)
1499
+ pkgorigins[id] = PkgOrigin (cachefile)
1500
+ end
1501
+
1453
1502
return depmods # fresh cachefile
1454
1503
finally
1455
1504
close (io)
0 commit comments