Remove a catalog source by index (0-based). Returns the removed name.
(self, index: int)
| 1155 | ) from exc |
| 1156 | |
| 1157 | def remove_catalog(self, index: int) -> str: |
| 1158 | """Remove a catalog source by index (0-based). Returns the removed name.""" |
| 1159 | config_path = self.project_root / ".specify" / "step-catalogs.yml" |
| 1160 | if not config_path.exists(): |
| 1161 | raise StepValidationError("No step catalog config file found.") |
| 1162 | |
| 1163 | try: |
| 1164 | data = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {} |
| 1165 | except (yaml.YAMLError, OSError, UnicodeDecodeError) as exc: |
| 1166 | raise StepValidationError( |
| 1167 | f"Catalog config file is unreadable or malformed: {exc}" |
| 1168 | ) from exc |
| 1169 | if not isinstance(data, dict): |
| 1170 | raise StepValidationError( |
| 1171 | "Catalog config file is corrupted (expected a mapping)." |
| 1172 | ) |
| 1173 | catalogs = data.get("catalogs", []) |
| 1174 | if not isinstance(catalogs, list): |
| 1175 | raise StepValidationError( |
| 1176 | "Catalog config 'catalogs' must be a list." |
| 1177 | ) |
| 1178 | |
| 1179 | if index < 0 or index >= len(catalogs): |
| 1180 | raise StepValidationError( |
| 1181 | f"Catalog index {index} out of range (0-{len(catalogs) - 1})." |
| 1182 | ) |
| 1183 | |
| 1184 | removed = catalogs.pop(index) |
| 1185 | data["catalogs"] = catalogs |
| 1186 | |
| 1187 | try: |
| 1188 | with open(config_path, "w", encoding="utf-8") as f: |
| 1189 | yaml.dump( |
| 1190 | data, f, default_flow_style=False, sort_keys=False, allow_unicode=True |
| 1191 | ) |
| 1192 | except OSError as exc: |
| 1193 | raise StepValidationError( |
| 1194 | f"Failed to write catalog config {config_path}: {exc}" |
| 1195 | ) from exc |
| 1196 | |
| 1197 | if isinstance(removed, dict): |
| 1198 | return removed.get("name", f"catalog-{index + 1}") |
| 1199 | return f"catalog-{index + 1}" |