from argparse import Namespace import os from git_flow import GitFlowError from git_flow.command.base import Command from git_flow.git import FLOWCONFIG_FILE, Git class InitCommand(Command): def name(self) -> str: return "init" def description(self) -> str: return """Inicializa el repositorio para utilizar git-flow""" def run(self, args: Namespace = Namespace()): self._ensure_is_repository() self._ensure_not_already_initialized() branches = self._setup_flow_branches() remote = self._setup_flow_remote() flowconfig = { "flow.initialized": "true", "flow.branches": ",".join(branches), } if remote: flowconfig["flow.remote"] = remote Git.set_config(flowconfig, FLOWCONFIG_FILE) Git("add", FLOWCONFIG_FILE).exec() Git("commit", message="feature: initialize git-flow").exec() self._ensure_all_flow_branches_exist(branches, remote) def _ensure_is_repository(self): if not Git.is_repository(): self.warning("El directorio actual no es un repositorio.") if not self.confirm("¿Desea inicializarlo?"): raise GitFlowError( "No se puede continuar sin inicializar el repositorio" ) Git("init").exec() def _ensure_not_already_initialized(self): if not self.flowconfig: return elif self.flowconfig.get("flow.initialized") == "true": raise GitFlowError("El repositorio ya fue inicializado para usar git-flow") else: raise GitFlowError("Valor de 'flow.initialized' es inválido") def _setup_flow_branches(self): self.info( """Ingrese las ramas que representan los entornos de deploy del proyecto en orden creciente de cercanía al entorno productivo, y separados por coma. Por ejemplo: "dev,test,prod".""" ) branches = list( map(lambda b: b.strip(), self.prompt("Ramas", "main").split(",")) ) if not all(branches): raise GitFlowError("No puede ingresar una rama vacia") return branches def _setup_flow_remote(self): self.info( """Puede elegir o crear un repositorio remoto para generar automáticamente PRs""" ) remote = None if self.confirm("¿Configurar repositorio remoto?"): remotes = Git("remote").lines(print="Listando remotos disponibles") if not remotes: self.info("No tiene ningún repositorio remoto, se creará uno.") url = self.prompt( "Ingrese la URL del repositorio (e.g. https://github.com/user/repo.git)", persistent=True, ) remote = "origin" Git("remote", "add", remote, url).exec(print="Agregando remoto") elif len(remotes) == 1: remote = remotes[0] else: self.info("Tiene más de un remoto, seleccione el que va a utilizar.") remote = self.choice("Remoto", remotes) return remote def _ensure_all_flow_branches_exist(self, branches: list[str], remote: str | None): existing_branches = Git.get_branches() if not all(map(lambda b: b in existing_branches, branches)): self.warning("Algunas de las ramas de entornos expecificadas no existen.") self.info("Debe indicar sobre que rama se crearán las ramas de entorno.") target_branch = self.choice("Rama", existing_branches) for branch in branches: if branch not in existing_branches: Git("branch", branch, target_branch).exec( print="Creando rama inexistente" ) if remote: Git("push", remote, branch, set_upstream=True).exec( print="Creando rama en remoto" )