2020UPLOAD_USER = os .getenv ("UPLOAD_USER" , "" )
2121NO_UPLOAD = os .getenv ("NO_UPLOAD" , "no" )[:1 ].lower () in "yt1"
2222LOCAL_INDEX = os .getenv ("LOCAL_INDEX" , "no" )[:1 ].lower () in "yt1"
23+ SIGN_COMMAND = os .getenv ("SIGN_COMMAND" , "" )
2324
2425
2526def find_cmd (env , exe ):
2627 cmd = os .getenv (env )
2728 if cmd :
28- return Path (cmd )
29+ cmd = Path (cmd )
30+ if not cmd .is_file ():
31+ raise RuntimeError (
32+ f"Could not find { cmd } to perform upload. Incorrect %{ env } % setting."
33+ )
34+ return cmd
2935 for p in os .getenv ("PATH" , "" ).split (";" ):
3036 if p :
3137 cmd = Path (p ) / exe
@@ -40,6 +46,7 @@ def find_cmd(env, exe):
4046
4147PLINK = find_cmd ("PLINK" , "plink.exe" )
4248PSCP = find_cmd ("PSCP" , "pscp.exe" )
49+ MAKECAT = find_cmd ("MAKECAT" , "makecat.exe" )
4350
4451
4552def _std_args (cmd ):
@@ -60,7 +67,9 @@ class RunError(Exception):
6067 pass
6168
6269
63- def _run (* args ):
70+ def _run (* args , single_cmd = False ):
71+ if single_cmd :
72+ args = args [0 ]
6473 with subprocess .Popen (
6574 args ,
6675 stdout = subprocess .PIPE ,
@@ -193,6 +202,43 @@ def calculate_uploads():
193202 )
194203
195204
205+ def sign_json (cat_file , * files ):
206+ if not MAKECAT :
207+ if not UPLOAD_HOST or NO_UPLOAD :
208+ print ("makecat.exe not found, but not uploading, so skip signing." )
209+ return
210+ raise RuntimeError ("No makecat.exe found" )
211+ if not SIGN_COMMAND :
212+ if not UPLOAD_HOST or NO_UPLOAD :
213+ print ("No signing command set, but not uploading, so skip signing." )
214+ return
215+ raise RuntimeError ("No SIGN_COMMAND set" )
216+
217+ cat = Path (cat_file ).absolute ()
218+ cdf = cat .with_suffix (".cdf" )
219+ cdf .parent .mkdir (parents = True , exist_ok = True )
220+
221+ with open (cdf , "w" , encoding = "ansi" ) as f :
222+ print ("[CatalogHeader]" , file = f )
223+ print ("Name=" , cat .name , sep = "" , file = f )
224+ print ("ResultDir=" , cat .parent , sep = "" , file = f )
225+ print ("PublicVersion=0x00000001" , file = f )
226+ print ("CatalogVersion=2" , file = f )
227+ print ("HashAlgorithms=SHA256" , file = f )
228+ print ("EncodingType=" , file = f )
229+ print (file = f )
230+ print ("[CatalogFiles]" , file = f )
231+ for a in map (Path , files ):
232+ print ("<HASH>" , a .name , "=" , a .absolute (), sep = "" , file = f )
233+
234+ _run (MAKECAT , "-v" , cdf )
235+ if not cat .is_file ():
236+ raise FileNotFoundError (cat )
237+ # Pass as a single arg because the command variable has its own arguments
238+ _run (f'{ SIGN_COMMAND } "{ cat } "' , single_cmd = True )
239+ cdf .unlink ()
240+
241+
196242def remove_and_insert (index , new_installs ):
197243 new = {(i ["id" ].casefold (), i ["sort-version" ].casefold ()) for i in new_installs }
198244 to_remove = [
@@ -274,6 +320,7 @@ def find_missing_from_index(url, installs):
274320 except FileNotFoundError :
275321 pass
276322
323+
277324print (INDEX_PATH , "mtime =" , INDEX_MTIME )
278325
279326
@@ -284,10 +331,20 @@ def find_missing_from_index(url, installs):
284331
285332if INDEX_FILE :
286333 INDEX_FILE = Path (INDEX_FILE ).absolute ()
334+ INDEX_CAT_FILE = INDEX_FILE .with_name (f"{ INDEX_FILE .name } .cat" )
287335 INDEX_FILE .parent .mkdir (parents = True , exist_ok = True )
288336 with open (INDEX_FILE , "w" , encoding = "utf-8" ) as f :
289337 json .dump (index , f )
290338
339+ sign_json (INDEX_CAT_FILE , INDEX_FILE )
340+ INDEX_CAT_URL = f"{ INDEX_URL } .cat"
341+ INDEX_CAT_PATH = f"{ INDEX_PATH } .cat"
342+ else :
343+ INDEX_CAT_FILE = None
344+ INDEX_CAT_URL = None
345+ INDEX_CAT_PATH = None
346+
347+
291348if MANIFEST_FILE :
292349 # Use the sort-version so that the manifest name includes prerelease marks
293350 MANIFEST_FILE = Path (MANIFEST_FILE ).absolute ()
@@ -323,33 +380,36 @@ def find_missing_from_index(url, installs):
323380 print ("Expecting mtime" , INDEX_MTIME , "but saw" , mtime )
324381 sys .exit (1 )
325382
383+ TO_PURGE = [i ["url" ] for i , * _ in UPLOADS ]
384+
385+ if MANIFEST_FILE :
386+ print ("Uploading" , MANIFEST_FILE , "to" , MANIFEST_URL )
387+ upload_ssh (MANIFEST_FILE , MANIFEST_PATH )
388+ TO_PURGE .append (MANIFEST_URL )
326389
327- if not NO_UPLOAD :
328- if MANIFEST_FILE :
329- print ("Uploading" , MANIFEST_FILE , "to" , MANIFEST_URL )
330- upload_ssh (MANIFEST_FILE , MANIFEST_PATH )
331-
332- if INDEX_FILE :
333- print ("Uploading" , INDEX_FILE , "to" , INDEX_URL )
334- upload_ssh (INDEX_FILE , INDEX_PATH )
335-
336- print ("Purging" , len (UPLOADS ), "uploaded files" )
337- parents = set ()
338- for i , * _ in UPLOADS :
339- purge (i ["url" ])
340- parents .add (i ["url" ].rpartition ("/" )[0 ] + "/" )
341- for i in parents :
342- purge (i )
343- if MANIFEST_URL :
344- purge (MANIFEST_URL )
345- purge (MANIFEST_URL .rpartition ("/" )[0 ] + "/" )
346- if INDEX_URL :
347- purge (INDEX_URL )
348- purge (INDEX_URL .rpartition ("/" )[0 ] + "/" )
349- missing = find_missing_from_index (INDEX_URL , [i for i , * _ in UPLOADS ])
350- if missing :
351- print ("##[error]Lost a race with another publish step!" )
352- print ("Index at" , INDEX_URL , "does not contain installs:" )
353- for m in missing :
354- print (m ["id" ], m ["sort-version" ])
355- sys .exit (1 )
390+ if INDEX_FILE :
391+ print ("Uploading" , INDEX_FILE , "to" , INDEX_URL )
392+ upload_ssh (INDEX_FILE , INDEX_PATH )
393+ TO_PURGE .append (INDEX_URL )
394+
395+ if INDEX_CAT_FILE :
396+ print ("Uploading" , INDEX_CAT_FILE , "to" , INDEX_CAT_URL )
397+ upload_ssh (INDEX_CAT_FILE , INDEX_CAT_PATH )
398+ TO_PURGE .append (INDEX_CAT_URL )
399+
400+ # Calculate directory parents for all files
401+ TO_PURGE .extend ({i .rpartition ("/" )[0 ] + "/" for i in TO_PURGE })
402+
403+ print ("Purging" , len (TO_PURGE ), "uploaded files, indexes and directories" )
404+
405+ for i in TO_PURGE :
406+ purge (i )
407+
408+ if INDEX_URL :
409+ missing = find_missing_from_index (INDEX_URL , [i for i , * _ in UPLOADS ])
410+ if missing :
411+ print ("##[error]Lost a race with another publish step!" )
412+ print ("Index at" , INDEX_URL , "does not contain installs:" )
413+ for m in missing :
414+ print (m ["id" ], m ["sort-version" ])
415+ sys .exit (1 )
0 commit comments