11"""
2- Script to compare configs from SANDAG/ABM release with configs from ActivitySim/sandag-abm3-example repo
2+ Script to compare configs from SANDAG/ABM release or branch with configs from ActivitySim/sandag-abm3-example repo
33"""
44
55import os
@@ -43,13 +43,13 @@ def run_command(cmd, cwd=None):
4343 sys .exit (1 )
4444
4545
46- def download_release (url , dest_dir ):
47- """Download the release from GitHub"""
48- print (f"Downloading release from { url } ..." )
46+ def download_archive (url , dest_dir ):
47+ """Download the archive from GitHub releases """
48+ print (f"Downloading archive from { url } ..." )
4949 response = requests .get (url , stream = True )
5050 response .raise_for_status ()
5151
52- zip_path = dest_dir / "release .zip"
52+ zip_path = dest_dir / "archive .zip"
5353 with open (zip_path , 'wb' ) as f :
5454 for chunk in response .iter_content (chunk_size = 8192 ):
5555 f .write (chunk )
@@ -58,6 +58,15 @@ def download_release(url, dest_dir):
5858 return zip_path
5959
6060
61+ def clone_production_repo (repo_url , dest_dir , branch ):
62+ """Clone the production repository at a specific branch"""
63+ clone_cmd = f"git clone { repo_url } --branch { branch } production_repo"
64+
65+ print (f"Cloning production repo { repo_url } (branch: { branch } )..." )
66+ run_command (clone_cmd , cwd = dest_dir )
67+ return dest_dir / "production_repo"
68+
69+
6170def extract_configs (zip_path , extract_dir ):
6271 """Extract src/asim/configs folder from the release"""
6372 print ("Extracting configs folder..." )
@@ -98,79 +107,79 @@ def extract_configs(zip_path, extract_dir):
98107 return configs_path
99108
100109
101- def clone_comparison_repo (repo_url , dest_dir , branch = None ):
102- """Clone the comparison repository"""
103- clone_cmd = f"git clone { repo_url } comparison_repo "
110+ def clone_example_repo (repo_url , dest_dir , branch = None ):
111+ """Clone the example repository"""
112+ clone_cmd = f"git clone { repo_url } example_repo "
104113 if branch :
105114 clone_cmd += f" --branch { branch } "
106-
107- print (f"Cloning comparison repo { repo_url } " + (f" (branch: { branch } )" if branch else " (default branch)" ) + "..." )
115+
116+ print (f"Cloning example repo { repo_url } " + (f" (branch: { branch } )" if branch else " (default branch)" ) + "..." )
108117 run_command (clone_cmd , cwd = dest_dir )
109- return dest_dir / "comparison_repo "
118+ return dest_dir / "example_repo "
110119
111120
112- def perform_diff (source_dir , target_repo_dir , summary_only = True , subdir = None ):
121+ def perform_diff (production_dir , example_dir , summary_only = True , subdir = None ):
113122 """Perform git diff between the two directories"""
114123 print ("\n " + "=" * 80 )
115124 print ("PERFORMING DIFF" )
116125 print ("=" * 80 + "\n " )
117126
118- # Copy source configs to target repo for comparison
119- # Find a suitable subdirectory in target repo to compare against
120- target_configs = target_repo_dir / "configs"
121-
122- if not target_configs .exists ():
123- print (f"Warning: { target_configs } does not exist in comparison repo" )
127+ # Copy production configs to example repo for comparison
128+ # Find a suitable subdirectory in example repo to compare against
129+ example_configs = example_dir / "configs"
130+
131+ if not example_configs .exists ():
132+ print (f"Warning: { example_configs } does not exist in example repo" )
124133 print ("Available directories:" )
125- for item in target_repo_dir .iterdir ():
134+ for item in example_dir .iterdir ():
126135 if item .is_dir ():
127136 print (f" { item .name } " )
128137 return
129138
130139 # If subdirectory specified, navigate to it
131140 if subdir :
132- source_dir = source_dir / subdir
133- target_configs = target_configs / subdir
134-
135- if not source_dir .exists ():
136- print (f"Error: Subdirectory '{ subdir } ' not found in source configs at { source_dir } " )
137- print (f"Available subdirectories in source :" )
138- parent = source_dir .parent
141+ production_dir = production_dir / subdir
142+ example_configs = example_configs / subdir
143+
144+ if not production_dir .exists ():
145+ print (f"Error: Subdirectory '{ subdir } ' not found in production configs at { production_dir } " )
146+ print (f"Available subdirectories in production :" )
147+ parent = production_dir .parent
139148 for item in parent .iterdir ():
140149 if item .is_dir ():
141150 print (f" { item .name } " )
142151 return
143-
144- if not target_configs .exists ():
145- print (f"Error: Subdirectory '{ subdir } ' not found in target configs at { target_configs } " )
146- print (f"Available subdirectories in target :" )
147- parent = target_configs .parent
152+
153+ if not example_configs .exists ():
154+ print (f"Error: Subdirectory '{ subdir } ' not found in example configs at { example_configs } " )
155+ print (f"Available subdirectories in example :" )
156+ parent = example_configs .parent
148157 for item in parent .iterdir ():
149158 if item .is_dir ():
150159 print (f" { item .name } " )
151160 return
152161
153162 # Use git diff to compare
154163 print (f"Comparing:" )
155- print (f" Source : { source_dir } " )
156- print (f" Target : { target_configs } " )
164+ print (f" Production : { production_dir } " )
165+ print (f" Example : { example_configs } " )
157166 print ("\n " + "-" * 80 + "\n " )
158167
159168 # Perform diff using git directly on both directories
160169 try :
161170 if summary_only :
162171 # Show only file names and status
163172 result = subprocess .run (
164- ['git' , 'diff' , '--no-index' , '--name-status' , str (target_configs ), str (source_dir )],
165- cwd = target_repo_dir ,
173+ ['git' , 'diff' , '--no-index' , '--name-status' , str (example_configs ), str (production_dir )],
174+ cwd = example_dir ,
166175 capture_output = True ,
167176 text = True
168177 )
169178 else :
170179 # Show full diff
171180 result = subprocess .run (
172- ['git' , 'diff' , '--no-index' , str (target_configs ), str (source_dir )],
173- cwd = target_repo_dir ,
181+ ['git' , 'diff' , '--no-index' , str (example_configs ), str (production_dir )],
182+ cwd = example_dir ,
174183 capture_output = True ,
175184 text = True
176185 )
@@ -195,25 +204,25 @@ def main():
195204 formatter_class = argparse .RawDescriptionHelpFormatter ,
196205 epilog = """
197206 Examples:
198- %(prog)s # Use latest release, default branch, summary mode, all configs
199- %(prog)s -r v15.3.1 # Use specific release, summary mode, all configs
200- %(prog)s -r v15.3.1 -f # Use specific release, full diff output
201- %(prog)s -r v15.3.1 -d resident # Diff only the resident subdirectory
202- %(prog)s -d commercial --full # Diff commercial subdirectory with full output
203- %(prog)s -r v15.3.1 -b develop -d resident # Specific release, branch, and subdirectory
207+ %(prog)s # Use latest production release vs default example branch
208+ %(prog)s -p v15.3.1 # Use specific production release
209+ %(prog)s -p develop # Use production develop branch
210+ %(prog)s -p main -e develop # Compare production main vs example develop
211+ %(prog)s -p v15.3.1 -e main -d resident # Specific release vs example main, resident subdir only
212+ %(prog)s -p develop -d resident -f # Production develop branch, full diff output
204213 """
205214 )
206215 parser .add_argument (
207- '-r ' , '--release ' ,
216+ '-p ' , '--production ' ,
208217 type = str ,
209218 default = None ,
210- help = 'Release tag/version to compare (e.g., v15.3.1). If not specified, uses the latest release.'
219+ help = 'SANDAG/ABM reference to compare: release tag (e.g., v15.3.1) or branch name (e.g., develop, main ). If not specified, uses the latest release.'
211220 )
212221 parser .add_argument (
213- '-b ' , '--branch ' ,
222+ '-e ' , '--example ' ,
214223 type = str ,
215224 default = None ,
216- help = 'Branch of the comparison repo to diff against (e.g., main, develop). If not specified, uses the default branch.'
225+ help = 'ActivitySim/sandag-abm3-example branch to diff against (e.g., main, develop). If not specified, uses the default branch.'
217226 )
218227 parser .add_argument (
219228 '-f' , '--full' ,
@@ -232,41 +241,58 @@ def main():
232241 # Configuration
233242 REPO_OWNER = "SANDAG"
234243 REPO_NAME = "ABM"
235- COMPARISON_REPO = "https://github.com/ActivitySim/sandag-abm3-example.git"
244+ PRODUCTION_REPO_URL = f"https://github.com/{ REPO_OWNER } /{ REPO_NAME } .git"
245+ EXAMPLE_REPO_URL = "https://github.com/ActivitySim/sandag-abm3-example.git"
236246
237- # Determine which release to use
238- if args .release :
239- release_tag = args .release
240- print (f"Using specified release: { release_tag } " )
247+ # Determine production: release or branch
248+ # Check if it's a release tag (starts with 'v') or a branch name
249+ if args .production :
250+ source_ref = args .production
251+ # Heuristic: if it starts with 'v' and contains numbers, likely a release tag
252+ use_release = source_ref .startswith ('v' ) and any (char .isdigit () for char in source_ref )
253+
254+ if use_release :
255+ print (f"Using production release: { source_ref } " )
256+ else :
257+ print (f"Using production branch: { source_ref } " )
241258 else :
259+ # Default: fetch latest release
242260 print ("Fetching latest release..." )
243- release_tag = get_latest_release (REPO_OWNER , REPO_NAME )
244- if not release_tag :
245- print ("Error: Could not fetch latest release. Please specify a release with -r " )
261+ source_ref = get_latest_release (REPO_OWNER , REPO_NAME )
262+ if not source_ref :
263+ print ("Error: Could not fetch latest release. Please specify with -p/--production " )
246264 sys .exit (1 )
247- print (f"Using latest release: { release_tag } " )
248-
249- # Construct release URL
250- RELEASE_URL = f"https://github.com/{ REPO_OWNER } /{ REPO_NAME } /archive/refs/tags/{ release_tag } .zip"
251-
265+ print (f"Using latest release: { source_ref } " )
266+ use_release = True
252267 # Create temporary working directory
253268 with tempfile .TemporaryDirectory () as temp_dir :
254269 temp_path = Path (temp_dir )
255270 print (f"Working directory: { temp_path } \n " )
256271
257272 try :
258- # Step 1: Download release
259- zip_path = download_release (RELEASE_URL , temp_path )
260-
261- # Step 2: Extract configs
262- configs_dir = extract_configs (zip_path , temp_path )
263-
264- # Step 3: Clone comparison repo
265- comparison_repo = clone_comparison_repo (COMPARISON_REPO , temp_path , args .branch )
266-
273+ if use_release :
274+ # Step 1: Download release
275+ ARCHIVE_URL = f"https://github.com/{ REPO_OWNER } /{ REPO_NAME } /archive/refs/tags/{ source_ref } .zip"
276+ zip_path = download_archive (ARCHIVE_URL , temp_path )
277+
278+ # Step 2: Extract configs
279+ configs_dir = extract_configs (zip_path , temp_path )
280+ else :
281+ # Step 1: Clone production repo at specific branch
282+ production_repo = clone_production_repo (PRODUCTION_REPO_URL , temp_path , source_ref )
283+
284+ # Step 2: Find configs directory
285+ configs_dir = production_repo / "src" / "asim" / "configs"
286+ if not configs_dir .exists ():
287+ print (f"Error: Could not find configs at { configs_dir } " )
288+ sys .exit (1 )
289+ print (f"Using configs from { configs_dir } " )
290+
291+ # Step 3: Clone example repo
292+ example_repo = clone_example_repo (EXAMPLE_REPO_URL , temp_path , args .example )
267293 # Step 4: Perform diff
268- perform_diff (configs_dir , comparison_repo , summary_only = not args .full , subdir = args .subdir )
269-
294+ perform_diff (configs_dir , example_repo , summary_only = not args .full , subdir = args .subdir )
295+
270296 print ("\n " + "=" * 80 )
271297 print ("DIFF COMPLETE" )
272298 print ("=" * 80 )
0 commit comments