@@ -217,11 +217,24 @@ function our_serialize_json(io::IO, dict::Union{VersionsJsonDocument, InternalJs
217217end
218218
219219function checkpoint (content:: OutputJsonContent , cfg:: Config )
220- open (cfg. versions_json_filename, " w" ) do io
221- our_serialize_json (io, content. versions_json)
222- end
223- open (cfg. internal_json_filename, " w" ) do io
224- our_serialize_json (io, content. internal_json)
220+ mktempdir () do tmpdir
221+ version_json_tempfile = joinpath (tmpdir, " version.json.temp" )
222+ internal_json_tempfile = joinpath (tmpdir, " internal.json.temp" )
223+
224+ version_json_truefile = cfg. versions_json_filename
225+ internal_json_truefile = cfg. internal_json_filename
226+
227+ open (version_json_tempfile, " w" ) do io
228+ our_serialize_json (io, content. versions_json)
229+ end
230+ open (internal_json_tempfile, " w" ) do io
231+ our_serialize_json (io, content. internal_json)
232+ end
233+
234+ # We don't move to the true location until we've completely finished serializing.
235+ # That way, if an error is thrown during serialization, we don't have a broken JSON file.
236+ mv (version_json_tempfile, version_json_truefile; force = true )
237+ mv (internal_json_tempfile, internal_json_truefile; force = true )
225238 end
226239 return nothing
227240end
@@ -468,8 +481,11 @@ function main!(content::OutputJsonContent, cfg::Config)
468481 return nothing
469482 end
470483
471- checkpoint (content, cfg)
472484 for version in tag_versions
485+ # Write out new versions of our versions.json every time we finish a version.
486+ # The fact that we wait until we've finished a version is intentional.
487+ # We don't want to write out a partial version - we want to wait until we've finished the version.
488+ checkpoint (content, cfg)
473489 for platform in julia_platforms
474490 url_probe_index += 1
475491 url = download_url (version, platform)
@@ -495,7 +511,6 @@ function main!(content::OutputJsonContent, cfg::Config)
495511 catch ex
496512 if (ex isa HTTP. Exceptions. StatusError) && (ex. status == 404 )
497513 mark_url_as_nonexistent! (content, version, url)
498- checkpoint (content, cfg)
499514 update_download_progress! (version, filename; advance = true )
500515 continue # skip the rest of this for-loop iteration
501516 else
@@ -561,8 +576,7 @@ function main!(content::OutputJsonContent, cfg::Config)
561576 # and make this an array of dictionaries that is easy to extensibly match
562577 push! (meta[version]. files, FileDict (file_dict))
563578
564- # Write out new versions of our versions.json as we go
565- checkpoint (content, cfg)
579+
566580
567581 # Delete downloaded file
568582 rm (filepath)
@@ -589,7 +603,6 @@ function main!(content::OutputJsonContent, cfg::Config)
589603 catch ex
590604 if (ex isa HTTP. Exceptions. StatusError) && (ex. status == 404 )
591605 mark_url_as_nonexistent! (content, version, url)
592- checkpoint (content, cfg)
593606 update_download_progress! (version, filename; advance = true )
594607 continue # skip the rest of this for-loop iteration
595608 else
@@ -601,7 +614,6 @@ function main!(content::OutputJsonContent, cfg::Config)
601614 # Add in `.asc` signature content, if applicable
602615 if ! isnothing (asc_signature)
603616 file_dict. asc = asc_signature
604- checkpoint (content, cfg)
605617 end
606618 end
607619 update_download_progress! (version, filename; advance = true )
0 commit comments