|
15 | 15 |
|
16 | 16 | from .interfaces import ExtraFilesDiscoveryStrategy, SecretDiscoveryStrategy |
17 | 17 | from .models import DiscoveredExtraFile, DiscoveredPath, SecretConfig |
18 | | -from .utils import is_quiet_mode |
| 18 | +from .utils import is_quiet_mode, prompt_choice, prompt_value, prompt_yes_no |
19 | 19 |
|
20 | 20 | logger = logging.getLogger("migration") |
21 | 21 |
|
@@ -247,117 +247,111 @@ def prompt_for_missing_files(self) -> None: |
247 | 247 | self.pretty_logger.info(" 2. Skip these files and continue") |
248 | 248 | self.pretty_logger.info(" 3. Provide a directory to search for files") |
249 | 249 |
|
250 | | - while True: |
251 | | - try: |
252 | | - choice = input(" Enter your choice (1/2/3): ").strip() |
253 | | - |
254 | | - if choice == "1": |
255 | | - # Provide alternative paths |
256 | | - self._prompt_for_individual_alternatives(file_path) |
257 | | - break |
258 | | - elif choice == "2": |
259 | | - # Skip missing files |
260 | | - self.pretty_logger.info(" ⚠️ Skipping missing files...") |
261 | | - file_path.skipped_reason = "Skipped by user" |
262 | | - break |
263 | | - elif choice == "3": |
264 | | - # Provide directory to search |
265 | | - self._prompt_for_directory_search(file_path) |
266 | | - break |
267 | | - else: |
268 | | - self.pretty_logger.info(" ❌ Invalid choice. Please enter 1, 2, or 3.") |
269 | | - |
270 | | - except KeyboardInterrupt as err: |
271 | | - self.pretty_logger.info("\n ❌ Operation cancelled by user") |
272 | | - raise ExtraFilesError("User cancelled file input") from err |
273 | | - except EOFError as err: |
274 | | - self.pretty_logger.info("\n ❌ End of input reached") |
275 | | - raise ExtraFilesError("End of input reached during file prompt") from err |
| 250 | + choice = prompt_choice( |
| 251 | + self.pretty_logger, |
| 252 | + "Enter your choice (1/2/3):", |
| 253 | + [ |
| 254 | + "Provide alternative path for this file", |
| 255 | + "Skip these files and continue", |
| 256 | + "Provide a directory to search for files", |
| 257 | + ], |
| 258 | + ) |
| 259 | + |
| 260 | + if choice == "Provide alternative path for this file": |
| 261 | + # Provide alternative paths |
| 262 | + self._prompt_for_individual_alternatives(file_path) |
| 263 | + elif choice == "Skip these files and continue": |
| 264 | + # Skip missing files |
| 265 | + self.pretty_logger.info(" ⚠️ Skipping missing files...") |
| 266 | + file_path.skipped_reason = "Skipped by user" |
| 267 | + elif choice == "Provide a directory to search for files": |
| 268 | + # Provide directory to search |
| 269 | + self._prompt_for_directory_search(file_path) |
276 | 270 |
|
277 | 271 | def _prompt_for_individual_alternatives(self, discovered_path: DiscoveredPath) -> None: |
278 | 272 | """ |
279 | 273 | Prompt user for alternative paths for each missing file. |
280 | 274 | """ |
281 | | - while True: |
| 275 | + |
| 276 | + def validate_file_path(path: str) -> tuple[bool, str]: |
| 277 | + if path.lower() == "skip": |
| 278 | + return True, "" # Special case for skip |
| 279 | + if not path: |
| 280 | + return False, "File path cannot be empty. Please try again." |
282 | 281 | try: |
283 | | - new_path = input(" Please enter the correct file path (or 'skip' to ignore): ").strip() |
| 282 | + new_path_obj = Path(path) |
| 283 | + if new_path_obj.is_dir(): |
| 284 | + return False, "Targetted file is a directory." |
| 285 | + discovered_extra_file = self._discover_extra_file(discovered_path, new_path_obj) |
| 286 | + if not discovered_extra_file: |
| 287 | + return False, "File not found or invalid." |
| 288 | + return True, "" |
| 289 | + except ExtraFilesError as e: |
| 290 | + return False, str(e) |
284 | 291 |
|
285 | | - if new_path.lower() == "skip": |
286 | | - self.pretty_logger.info(f" ⚠️ Skipping file: {discovered_path.source_path}") |
287 | | - break |
| 292 | + while True: |
| 293 | + new_path = prompt_value( |
| 294 | + self.pretty_logger, |
| 295 | + "Please enter the correct file path (or 'skip' to ignore):", |
| 296 | + validator=validate_file_path, |
| 297 | + ) |
288 | 298 |
|
289 | | - if not new_path: |
290 | | - self.pretty_logger.info(" ❌ File path cannot be empty. Please try again.") |
291 | | - continue |
292 | | - |
293 | | - # Validate the new path |
294 | | - try: |
295 | | - new_path_obj = Path(new_path) |
296 | | - if new_path_obj.is_dir(): |
297 | | - raise ExtraFilesError("Targetted file is a directory.") |
298 | | - else: |
299 | | - discovered_extra_file = self._discover_extra_file(discovered_path, new_path_obj) |
300 | | - if discovered_extra_file: |
301 | | - self.discovered_extra_files[new_path_obj] = discovered_extra_file |
302 | | - self.pretty_logger.info(f" ✅ File validated: {new_path}") |
303 | | - break |
304 | | - except ExtraFilesError as e: |
305 | | - self.pretty_logger.info(f" ❌ Invalid file path: {e}") |
306 | | - self.pretty_logger.info(" Please try again or enter 'skip' to ignore.") |
307 | | - |
308 | | - except KeyboardInterrupt as err: |
309 | | - self.pretty_logger.info("\n ❌ Operation cancelled by user") |
310 | | - raise ExtraFilesError("User cancelled file input") from err |
311 | | - except EOFError as err: |
312 | | - self.pretty_logger.info("\n ❌ End of input reached") |
313 | | - raise ExtraFilesError("End of input reached during file prompt") from err |
| 299 | + if new_path.lower() == "skip": |
| 300 | + self.pretty_logger.info(f" ⚠️ Skipping file: {discovered_path.source_path}") |
| 301 | + break |
| 302 | + |
| 303 | + new_path_obj = Path(new_path) |
| 304 | + discovered_extra_file = self._discover_extra_file(discovered_path, new_path_obj) |
| 305 | + if discovered_extra_file: |
| 306 | + self.discovered_extra_files[new_path_obj] = discovered_extra_file |
| 307 | + self.pretty_logger.info(f" ✅ File validated: {new_path}") |
| 308 | + break |
314 | 309 |
|
315 | 310 | def _prompt_for_directory_search(self, discovered_path: DiscoveredPath) -> None: |
316 | 311 | """ |
317 | 312 | Prompt user for a directory to search for missing files. |
318 | 313 | """ |
319 | 314 | self.pretty_logger.info("\n📁 Please provide a directory to search for missing files:") |
320 | 315 |
|
321 | | - while True: |
| 316 | + def validate_directory(path: str) -> tuple[bool, str]: |
| 317 | + if not path: |
| 318 | + return False, "Directory path cannot be empty. Please try again." |
322 | 319 | try: |
323 | | - search_dir = input(" Enter directory path: ").strip() |
324 | | - |
325 | | - if not search_dir: |
326 | | - self.pretty_logger.info(" ❌ Directory path cannot be empty. Please try again.") |
327 | | - continue |
328 | | - |
329 | | - # Validate the directory |
330 | | - try: |
331 | | - dir_path = Path(search_dir) |
332 | | - if not dir_path.is_dir(): |
333 | | - raise ExtraFilesError(f"Path is not a directory: {search_dir}") |
334 | | - |
335 | | - # Search for missing files in the directory |
336 | | - found_files = self._handle_directory(discovered_path, dir_path) |
337 | | - |
338 | | - if found_files: |
339 | | - self.pretty_logger.info(f" ✅ Found {len(found_files)} matching files in {search_dir}") |
340 | | - for file_path in found_files: |
341 | | - self.pretty_logger.info(f" 📄 {Path(file_path).name}") |
342 | | - break |
343 | | - else: |
344 | | - self.pretty_logger.info(f" ⚠️ No matching files found in {search_dir}") |
345 | | - self.pretty_logger.info(" Would you like to try another directory?") |
346 | | - retry = input(" Enter 'yes' to try again or any other key to skip: ").strip().lower() |
347 | | - if retry != "yes": |
348 | | - self.pretty_logger.info(" ⚠️ Skipping directory search...") |
349 | | - break |
350 | | - |
351 | | - except Exception as e: |
352 | | - self.pretty_logger.info(f" ❌ Error searching directory: {e}") |
353 | | - self.pretty_logger.info(" Please try again.") |
354 | | - |
355 | | - except KeyboardInterrupt as err: |
356 | | - self.pretty_logger.info("\n ❌ Operation cancelled by user") |
357 | | - raise ExtraFilesError("User cancelled file input") from err |
358 | | - except EOFError as err: |
359 | | - self.pretty_logger.info("\n ❌ End of input reached") |
360 | | - raise ExtraFilesError("End of input reached during file prompt") from err |
| 320 | + dir_path = Path(path) |
| 321 | + if not dir_path.is_dir(): |
| 322 | + return False, f"Path is not a directory: {path}" |
| 323 | + return True, "" |
| 324 | + except Exception as e: |
| 325 | + return False, str(e) |
| 326 | + |
| 327 | + while True: |
| 328 | + search_dir = prompt_value( |
| 329 | + self.pretty_logger, |
| 330 | + "Enter directory path:", |
| 331 | + validator=validate_directory, |
| 332 | + ) |
| 333 | + |
| 334 | + dir_path = Path(search_dir) |
| 335 | + |
| 336 | + # Search for missing files in the directory |
| 337 | + found_files = self._handle_directory(discovered_path, dir_path) |
| 338 | + |
| 339 | + if found_files: |
| 340 | + self.pretty_logger.info(f" ✅ Found {len(found_files)} matching files in {search_dir}") |
| 341 | + for file_path in found_files: |
| 342 | + self.pretty_logger.info(f" 📄 {Path(file_path).name}") |
| 343 | + break |
| 344 | + else: |
| 345 | + self.pretty_logger.info(f" ⚠️ No matching files found in {search_dir}") |
| 346 | + self.pretty_logger.info(" Would you like to try another directory?") |
| 347 | + retry = prompt_yes_no( |
| 348 | + self.pretty_logger, |
| 349 | + "Try another directory?", |
| 350 | + default=False, |
| 351 | + ) |
| 352 | + if not retry: |
| 353 | + self.pretty_logger.info(" ⚠️ Skipping directory search...") |
| 354 | + break |
361 | 355 |
|
362 | 356 | def validate_extra_files(self) -> None: |
363 | 357 | """ |
|
0 commit comments