@@ -113,31 +113,42 @@ def calc_md5(fname):
113113 return hash_md5 .hexdigest ()
114114
115115def zipdir (path , ziph ):
116+ """
117+ Adds a path (folder or file) to the zip file handle `ziph`.
118+ Preserves the directory name in the archive.
119+ """
116120 if not os .path .exists (path ):
117121 print (f"Warning: { path } does not exist, skipping" )
118122 return
119123
120- if os .path .isdir (path ):
121- for root , dirs , files in os .walk (path ):
124+ # Remove trailing slash if present, otherwise dirname might return the path itself
125+ clean_path = path .rstrip (os .sep )
126+
127+ # Calculate the base directory (parent of the target path)
128+ # This ensures that if we zip '/repo/lua', the archive entry starts with 'lua/...'
129+ base_dir = os .path .dirname (clean_path )
130+
131+ if os .path .isdir (clean_path ):
132+ for root , dirs , files in os .walk (clean_path ):
122133 files .sort () # deterministic order
123134 dirs .sort () # deterministic order
124135 for file in files :
125136 full_path = os .path .join (root , file )
126- arcname = os .path .relpath (full_path , start = path ) # preserve folder structure
137+ # Relpath relative to base_dir (parent) ensures folder structure is kept
138+ arcname = os .path .relpath (full_path , start = base_dir )
127139 info = zipfile .ZipInfo (arcname , FIXED_ZIP_TIMESTAMP )
128140 with open (full_path , "rb" ) as f :
129141 data = f .read ()
130142 ziph .writestr (info , data , compress_type = zipfile .ZIP_DEFLATED )
131143 else :
132144 # single file outside a directory
133- arcname = os .path .basename ( path )
145+ arcname = os .path .relpath ( clean_path , start = base_dir )
134146 info = zipfile .ZipInfo (arcname , FIXED_ZIP_TIMESTAMP )
135- with open (path , "rb" ) as f :
147+ with open (clean_path , "rb" ) as f :
136148 data = f .read ()
137149 ziph .writestr (info , data , compress_type = zipfile .ZIP_DEFLATED )
138150
139151
140-
141152def create_file (conn , mod , fileId , version , name , source , target_dir , old_md5 , dryrun ):
142153 """Pack or copy files, compare MD5, update DB if changed."""
143154 target_dir = os .path .join (target_dir , f"updates_{ mod } _files" )
@@ -238,8 +249,12 @@ def download_vo_assets(version, target_dir):
238249
239250 # 1. Get latest release JSON from GitHub
240251 api_url = f"https://api.github.com/repos/FAForever/fa-coop/releases/tags/v{ version } "
241- with urllib .request .urlopen (api_url ) as response :
242- release_info = json .load (response )
252+ try :
253+ with urllib .request .urlopen (api_url ) as response :
254+ release_info = json .load (response )
255+ except urllib .error .HTTPError as e :
256+ print (f"Failed to fetch release info: { e } " )
257+ return
243258
244259 # 2. Filter assets ending with .nx2
245260 nx2_urls = [
0 commit comments