@@ -436,15 +436,50 @@ function write_env_usage(source_file::AbstractString, usage_filepath::AbstractSt
436436 # Ensure that log dir exists
437437 ! ispath (logdir ()) && mkpath (logdir ())
438438
439- # Generate entire entry as a string first
440- entry = sprint () do io
441- TOML. print (io, Dict (source_file => [Dict (" time" => now ())]))
442- end
443-
444- # Append entry to log file in one chunk
445439 usage_file = joinpath (logdir (), usage_filepath)
446- open (usage_file, append= true ) do io
447- write (io, entry)
440+ timestamp = now ()
441+
442+ # # Atomically write usage file
443+ while true
444+ # read existing usage file
445+ usage = if isfile (usage_file)
446+ TOML. parsefile (usage_file)
447+ else
448+ Dict {String, Any} ()
449+ end
450+
451+ # record new usage
452+ usage[source_file] = [Dict (" time" => timestamp)]
453+
454+ # keep only latest usage info
455+ for k in keys (usage)
456+ times = map (d -> Dates. DateTime (d[" time" ]), usage[k])
457+ usage[k] = [Dict (" time" => maximum (times))]
458+ end
459+
460+ # Write to a temp file in the same directory as the destination
461+ temp_usage_file = tempname (logdir ())
462+ open (temp_usage_file, " w" ) do io
463+ TOML. print (io, usage, sorted= true )
464+ end
465+
466+ # Move the temp file into place, replacing the original
467+ mv (temp_usage_file, usage_file, force = true )
468+
469+ # Check that the new file has what we want in it
470+ new_usage = if isfile (usage_file)
471+ TOML. parsefile (usage_file)
472+ else
473+ Dict {String, Any} ()
474+ end
475+ if haskey (new_usage, source_file)
476+ for e in new_usage[source_file]
477+ if Dates. DateTime (e[" time" ]) >= timestamp
478+ return
479+ end
480+ end
481+ end
482+ # If not, try again
448483 end
449484end
450485
0 commit comments