Coverage for src/moai_adk/cli/commands/backup.py: 30.77%

26 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-20 15:28 +0900

1"""Backup command 

2 

3Create a backup of the current project including: 

4- .claude/ (entire directory) 

5- .moai/ (excluding specs and reports) 

6- CLAUDE.md 

7 

8Backup location: .moai-backups/YYYYMMDD-HHMMSS/ 

9 

10## Skill Invocation Guide (English-Only) 

11 

12### Related Skills 

13- **moai-foundation-git**: For Git workflow and backup management 

14 - Trigger: Before creating critical backups, review Git state 

15 - Invocation: `Skill("moai-foundation-git")` for backup naming conventions 

16 

17### When to Invoke Skills in Related Workflows 

181. **Before backup creation**: 

19 - Run `Skill("moai-foundation-git")` to document current Git branch state 

20 - Tag backup with feature branch name for easier recovery 

21 

222. **After restoration from backup**: 

23 - Run `Skill("moai-foundation-trust")` to validate toolchain 

24""" 

25 

26from pathlib import Path 

27 

28import click 

29from rich.console import Console 

30 

31from moai_adk.core.template.processor import TemplateProcessor 

32 

33console = Console() 

34 

35 

36@click.command() 

37@click.option( 

38 "--path", 

39 type=click.Path(exists=True), 

40 default=".", 

41 help="Project path (default: current directory)", 

42) 

43def backup(path: str) -> None: 

44 """Create a backup of the current project. 

45 

46 Includes: 

47 - .claude/ (entire directory) 

48 - .moai/ (excluding specs and reports) 

49 - CLAUDE.md 

50 

51 Backup location: .moai-backup/YYYYMMDD-HHMMSS/ 

52 """ 

53 try: 

54 project_path = Path(path).resolve() 

55 

56 # Verify the project has been initialized 

57 if not (project_path / ".moai").exists(): 

58 console.print("[yellow]⚠ Project not initialized[/yellow]") 

59 raise click.Abort() 

60 

61 # Create the backup 

62 console.print("[cyan]💾 Creating backup...[/cyan]") 

63 processor = TemplateProcessor(project_path) 

64 backup_path = processor.create_backup() 

65 

66 # Success message 

67 console.print( 

68 f"[green]✓ Backup completed: {backup_path.relative_to(project_path)}[/green]" 

69 ) 

70 

71 # Show backup contents 

72 backup_items = list(backup_path.iterdir()) 

73 for item in backup_items: 

74 if item.is_dir(): 

75 file_count = len(list(item.rglob("*"))) 

76 console.print(f" ├─ {item.name}/ ({file_count} files)") 

77 else: 

78 console.print(f" └─ {item.name}") 

79 

80 except Exception as e: 

81 console.print(f"[red]✗ Backup failed: {e}[/red]") 

82 raise click.ClickException(str(e)) from e