@@ -464,15 +464,50 @@ function write_env_usage(source_file::AbstractString, usage_filepath::AbstractSt
464464 # Ensure that log dir exists
465465 ! ispath (logdir ()) && mkpath (logdir ())
466466
467- # Generate entire entry as a string first
468- entry = sprint () do io
469- TOML. print (io, Dict (source_file => [Dict (" time" => now ())]))
470- end
471-
472- # Append entry to log file in one chunk
473467 usage_file = joinpath (logdir (), usage_filepath)
474- open (usage_file, append= true ) do io
475- write (io, entry)
468+ timestamp = now ()
469+
470+ # # Atomically write usage file
471+ while true
472+ # read existing usage file
473+ usage = if isfile (usage_file)
474+ TOML. parsefile (usage_file)
475+ else
476+ Dict {String, Any} ()
477+ end
478+
479+ # record new usage
480+ usage[source_file] = [Dict (" time" => timestamp)]
481+
482+ # keep only latest usage info
483+ for k in keys (usage)
484+ times = map (d -> Dates. DateTime (d[" time" ]), usage[k])
485+ usage[k] = [Dict (" time" => maximum (times))]
486+ end
487+
488+ # Write to a temp file in the same directory as the destination
489+ temp_usage_file = tempname (logdir ())
490+ open (temp_usage_file, " w" ) do io
491+ TOML. print (io, usage, sorted= true )
492+ end
493+
494+ # Move the temp file into place, replacing the original
495+ mv (temp_usage_file, usage_file, force = true )
496+
497+ # Check that the new file has what we want in it
498+ new_usage = if isfile (usage_file)
499+ TOML. parsefile (usage_file)
500+ else
501+ Dict {String, Any} ()
502+ end
503+ if haskey (new_usage, source_file)
504+ for e in new_usage[source_file]
505+ if Dates. DateTime (e[" time" ]) >= timestamp
506+ return
507+ end
508+ end
509+ end
510+ # If not, try again
476511 end
477512end
478513
0 commit comments