Coverage for src / rhiza / commands / migrate.py: 100%

71 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2025-12-29 01:59 +0000

1"""Command for migrating to the new .rhiza folder structure. 

2 

3This module implements the `migrate` command. It helps transition projects to use 

4the new `.rhiza/` folder structure for storing Rhiza state and configuration files, 

5separate from `.github/rhiza/` which contains template configuration. 

6""" 

7 

8import shutil 

9from pathlib import Path 

10 

11from loguru import logger 

12 

13from rhiza.models import RhizaTemplate 

14 

15 

16def migrate(target: Path) -> None: 

17 """Migrate project to use the new .rhiza folder structure. 

18 

19 This command performs the following actions: 

20 1. Creates the `.rhiza/` directory in the project root 

21 2. Moves template.yml from `.github/rhiza/` or `.github/` to `.rhiza/template.yml` 

22 3. Moves `.rhiza.history` to `.rhiza/history` if it exists 

23 4. Provides instructions for next steps 

24 

25 The `.rhiza/` folder will contain: 

26 - `template.yml` - Template configuration (replaces `.github/rhiza/template.yml`) 

27 - `history` - List of files managed by Rhiza templates (replaces `.rhiza.history`) 

28 - Future: Additional state, cache, or metadata files 

29 

30 Args: 

31 target (Path): Path to the target repository. 

32 """ 

33 # Resolve to absolute path 

34 target = target.resolve() 

35 

36 logger.info(f"Migrating Rhiza structure in: {target}") 

37 logger.info("This will create the .rhiza folder and migrate configuration files") 

38 

39 # Create .rhiza directory 

40 rhiza_dir = target / ".rhiza" 

41 if not rhiza_dir.exists(): 

42 logger.info(f"Creating .rhiza directory at: {rhiza_dir.relative_to(target)}") 

43 rhiza_dir.mkdir(exist_ok=True) 

44 logger.success(f"✓ Created {rhiza_dir.relative_to(target)}") 

45 else: 

46 logger.debug(f".rhiza directory already exists at: {rhiza_dir.relative_to(target)}") 

47 

48 # Track what was migrated for summary 

49 migrations_performed = [] 

50 

51 # Migrate template.yml from .github to .rhiza if it exists 

52 github_dir = target / ".github" 

53 new_template_file = rhiza_dir / "template.yml" 

54 

55 # Check possible locations for template.yml in .github 

56 possible_template_locations = [ 

57 github_dir / "rhiza" / "template.yml", 

58 github_dir / "template.yml", 

59 ] 

60 

61 template_migrated = False 

62 for old_template_file in possible_template_locations: 

63 if old_template_file.exists(): 

64 if new_template_file.exists(): 

65 logger.info(".rhiza/template.yml already exists") 

66 logger.info(f"Skipping migration of {old_template_file.relative_to(target)}") 

67 logger.info(f"Note: Old file at {old_template_file.relative_to(target)} still exists") 

68 else: 

69 logger.info(f"Found template.yml at: {old_template_file.relative_to(target)}") 

70 logger.info(f"Moving to new location: {new_template_file.relative_to(target)}") 

71 

72 # Move the template file to new location (not copy) 

73 shutil.move(str(old_template_file), str(new_template_file)) 

74 logger.success("✓ Moved template.yml to .rhiza/template.yml") 

75 migrations_performed.append("Moved template.yml to .rhiza/template.yml") 

76 template_migrated = True 

77 break 

78 

79 if not template_migrated: 

80 if new_template_file.exists(): 

81 logger.info(".rhiza/template.yml already exists (no migration needed)") 

82 else: 

83 logger.warning("No existing template.yml file found in .github") 

84 logger.info("You may need to run 'rhiza init' to create a template configuration") 

85 

86 # Ensure the .rhiza folder is included in template.yml include list (if template exists) 

87 template_file = new_template_file 

88 if template_file.exists(): 

89 # Load existing template configuration 

90 template = RhizaTemplate.from_yaml(template_file) 

91 template_include = template.include or [] 

92 if ".rhiza" not in template_include: 

93 logger.warning("The .rhiza folder is not included in your template.yml") 

94 template_include.append(".rhiza") 

95 logger.info("The .rhiza folder is added to your template.yml to ensure it's included in your repository") 

96 

97 # Save the updated template.yml 

98 template.include = template_include 

99 template.to_yaml(template_file) 

100 else: 

101 logger.debug("No template.yml present in .rhiza; skipping include update") 

102 

103 # Migrate .rhiza.history to .rhiza/history if it exists 

104 old_history_file = target / ".rhiza.history" 

105 new_history_file = rhiza_dir / "history" 

106 

107 if old_history_file.exists(): 

108 if new_history_file.exists(): 

109 logger.info(".rhiza/history already exists") 

110 logger.info(f"Skipping migration of {old_history_file.relative_to(target)}") 

111 logger.info(f"Note: Old file at {old_history_file.relative_to(target)} still exists") 

112 else: 

113 logger.info("Found existing .rhiza.history file") 

114 logger.info(f"Moving to new location: {new_history_file.relative_to(target)}") 

115 

116 # Move the history file to new location 

117 shutil.move(str(old_history_file), str(new_history_file)) 

118 logger.success("✓ Moved history file to .rhiza/history") 

119 migrations_performed.append("Moved history tracking to .rhiza/history") 

120 else: 

121 if new_history_file.exists(): 

122 logger.debug(".rhiza/history already exists (no migration needed)") 

123 else: 

124 logger.debug("No existing .rhiza.history file to migrate") 

125 

126 # Summary 

127 logger.success("✓ Migration completed successfully") 

128 

129 if migrations_performed: 

130 logger.info("\nMigration Summary:") 

131 logger.info(" - Created .rhiza/ folder") 

132 for migration in migrations_performed: 

133 logger.info(f" - {migration}") 

134 else: 

135 logger.info("\nNo files needed migration (already using .rhiza structure)") 

136 

137 logger.info( 

138 "\nNext steps:\n" 

139 " 1. Review changes:\n" 

140 " git status\n" 

141 " git diff\n\n" 

142 " 2. Update other commands to use new .rhiza/ location\n" 

143 " (Future rhiza versions will automatically use .rhiza/)\n\n" 

144 " 3. Commit the migration:\n" 

145 " git add .\n" 

146 ' git commit -m "chore: migrate to .rhiza folder structure"\n' 

147 )