@@ -144,41 +144,91 @@ def _create_batches(self, changed_files: list[GitFile]) -> list[list[GitFile]]:
144144 def process_files_in_batches (
145145 self , changed_files : list [GitFile ], auto_commit : bool = False
146146 ) -> list [dict ]:
147- """Process files in batches if needed."""
147+ """Process files in batches if needed.
148+
149+ This method implements a queue-based approach to process files in batches:
150+ 1. First unstages all files to start from a clean state (only if multiple batches)
151+ 2. Creates batches of files to process
152+ 3. For each batch:
153+ - Stages only the files in the current batch
154+ - Processes the batch
155+ - If successful, keeps the commit and moves to next batch
156+ - If failed, unstages and stops
157+ """
158+ console .print_debug ("Starting batch processing" )
159+
160+ # Create work queue
161+ console .print_debug (f"Creating batches from { len (changed_files )} files" )
148162 batches = self ._create_batches (changed_files )
149163 if not batches :
164+ console .print_debug ("No valid files to process" )
150165 return []
151166
152- results = []
167+ # Print batch processing plan
168+ total_files = len (changed_files )
153169 total_batches = len (batches )
154-
155170 console .print_info ("\n Processing files in batches..." )
156- console .print_batch_summary (len ( changed_files ) , total_batches )
171+ console .print_batch_summary (total_files , total_batches )
157172
158- try :
159- for i , batch in enumerate (batches , 1 ):
160- # Stage only the current batch files
173+ # Start with a clean state only if we have multiple batches
174+ if total_batches > 1 :
175+ console .print_debug ("Multiple batches detected, resetting staged changes" )
176+ self .git .reset_staged_changes ()
177+ else :
178+ console .print_debug ("Single batch detected, proceeding without reset" )
179+
180+ # Process each batch atomically
181+ results = []
182+ for batch_num , batch in enumerate (batches , 1 ):
183+ try :
184+ # 1. Stage current batch
161185 batch_files = [f .path for f in batch ]
186+ console .print_debug (
187+ f"Staging files for batch { batch_num } : { ', ' .join (batch_files )} "
188+ )
162189 self .git .stage_files (batch_files )
163-
164- # Process current batch
165- console .print_batch_start (i , total_batches , batch )
166- result = self ._handle_batch (batch , i , total_batches , auto_commit , False )
167-
190+ console .print_batch_start (batch_num , total_batches , batch )
191+
192+ # 2. Process batch
193+ console .print_debug (f"Processing batch { batch_num } /{ total_batches } " )
194+ result = self ._handle_batch (
195+ batch = batch ,
196+ batch_num = batch_num ,
197+ total_batches = total_batches ,
198+ auto_commit = auto_commit ,
199+ combine_commits = False ,
200+ )
201+
202+ # 3. Handle result
168203 if result :
204+ # Batch processed successfully
205+ console .print_debug (f"Batch { batch_num } processed successfully" )
169206 results .append (result )
170- # Only unstage if there are more batches to process
171- if i < total_batches :
207+ # Clean staged files if more batches pending
208+ if batch_num < total_batches :
209+ console .print_debug ("Cleaning staged files for next batch" )
172210 self .git .reset_staged_changes ()
173211 else :
212+ # Batch processing was cancelled or failed
213+ console .print_debug (f"Batch { batch_num } processing cancelled or failed" )
174214 # _handle_batch already called reset_staged_changes
175215 break
176216
177- return results
178- except GitError as e :
179- console .print_error (f"Error during batch processing: { str (e )} " )
180- self .git .reset_staged_changes ()
181- return []
217+ except GitError as e :
218+ console .print_error (f"Error processing batch { batch_num } : { str (e )} " )
219+ console .print_debug (f"Stack trace for batch { batch_num } error:" , exc_info = True )
220+ self .git .reset_staged_changes ()
221+ if not auto_commit and not console .confirm_action (
222+ "Continue with remaining batches?"
223+ ):
224+ console .print_debug ("User chose to stop batch processing after error" )
225+ break
226+ console .print_debug ("Continuing with next batch after error" )
227+
228+ console .print_debug (
229+ f"Batch processing completed. Processed { len (results )} /{ total_batches } batches"
230+ )
231+ return results
182232
183233 def _create_combined_commit (self , batches : list [dict ]) -> None :
184234 """Create a combined commit from all batches."""
@@ -214,18 +264,30 @@ def _create_combined_commit(self, batches: list[dict]) -> None:
214264 except GitError as e :
215265 console .print_error (f"Failed to create commit: { str (e )} " )
216266
217- def run (self , auto_commit : bool = False , combine_commits : bool = False ) -> None :
218- """Run the main application logic."""
267+ def run (
268+ self , auto_commit : bool = False , combine_commits : bool = False , debug : bool = False
269+ ) -> None :
270+ """Run the commit creation process.
271+
272+ Args:
273+ auto_commit: Whether to skip confirmation prompts
274+ combine_commits: Whether to combine all changes into a single commit
275+ debug: Whether to enable debug logging
276+ """
219277 try :
220- console .print_info ("Analyzing your changes..." )
278+ # Setup logging
279+ console .setup_logging (debug )
280+ console .print_debug ("Starting CommitLoom" )
221281
222282 # Get and validate changed files
283+ console .print_info ("Analyzing your changes..." )
223284 changed_files = self .git .get_changed_files ()
224285 if not changed_files :
225286 console .print_error ("No changes detected in the staging area." )
226287 return
227288
228289 # Get diff and analyze complexity
290+ console .print_debug ("Getting diff and analyzing complexity" )
229291 diff = self .git .get_diff (changed_files )
230292 analysis = self .analyzer .analyze_diff_complexity (diff , changed_files )
231293
@@ -238,23 +300,17 @@ def run(self, auto_commit: bool = False, combine_commits: bool = False) -> None:
238300
239301 # Process files in batches if needed
240302 if len (changed_files ) > config .max_files_threshold :
241- # Save current state and unstage all files
242- self .git .stash_changes ()
243- self .git .reset_staged_changes ()
303+ console .print_debug ("Processing files in batches" )
304+ batches = self .process_files_in_batches (changed_files , auto_commit )
305+ if not batches :
306+ return
244307
245- try :
246- # Process files in batches
247- batches = self .process_files_in_batches (changed_files , auto_commit )
248- if not batches :
249- return
250-
251- if combine_commits :
252- self ._create_combined_commit (batches )
253- finally :
254- # Restore any stashed changes
255- self .git .pop_stashed_changes ()
308+ if combine_commits :
309+ console .print_debug ("Combining commits" )
310+ self ._create_combined_commit (batches )
256311 else :
257312 # Process as single commit
313+ console .print_debug ("Processing as single commit" )
258314 suggestion , usage = self .ai_service .generate_commit_message (diff , changed_files )
259315 console .print_info ("\n Generated Commit Message:" )
260316 console .print_commit_message (suggestion .format_body ())
@@ -268,11 +324,15 @@ def run(self, auto_commit: bool = False, combine_commits: bool = False) -> None:
268324
269325 except GitError as e :
270326 console .print_error (f"An error occurred: { str (e )} " )
327+ if debug :
328+ console .print_debug ("Git error details:" , exc_info = True )
271329 except KeyboardInterrupt :
272330 console .print_warning ("\n Operation cancelled by user" )
273331 self .git .reset_staged_changes ()
274332 except Exception as e :
275333 console .print_error (f"An unexpected error occurred: { str (e )} " )
334+ if debug :
335+ console .print_debug ("Unexpected error details:" , exc_info = True )
276336 self .git .reset_staged_changes ()
277337 raise
278338
0 commit comments