From 7346cfd1a8ae5a69b48b5711c3422056edb81a0e Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 11:23:24 -0300 Subject: [PATCH 1/6] feature: muevo opciones para check y print a metodos para ejecutar git --- src/git_flow/command/tag.py | 6 +---- src/git_flow/git.py | 48 +++++++++++++++++++------------------ src/git_flow/main.py | 2 +- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/git_flow/command/tag.py b/src/git_flow/command/tag.py index c4cb1b3..79233a7 100644 --- a/src/git_flow/command/tag.py +++ b/src/git_flow/command/tag.py @@ -77,11 +77,7 @@ class TagCommand(Command): return commit def check_not_tagged(self, commit: str): - tag = ( - Git("describe", commit, tags=True, exact_match=True) - .without_checking() - .firstline() - ) + tag = Git("describe", commit, tags=True, exact_match=True).firstline(check=False) if tag: raise GitFlowError("El commit a taggear ya tiene tag: " + tag) diff --git a/src/git_flow/git.py b/src/git_flow/git.py index 3408378..5ca7b0d 100644 --- a/src/git_flow/git.py +++ b/src/git_flow/git.py @@ -22,7 +22,6 @@ class Git: self.file = line[3:].strip("\n") command: list[str] - check_returncode: bool = True @staticmethod def get_config(file: str | None = None): @@ -60,7 +59,7 @@ class Git: @staticmethod def get_current_tag(): - return Git("describe", abbrev="0", tags=True).without_checking().firstline() + return Git("describe", abbrev="0", tags=True).firstline(check=False) @staticmethod def get_first_fork_point(branch: str, env: str): @@ -115,44 +114,47 @@ class Git: self.command += args - def lines(self, strip: bool = True): - process = subprocess.run(self.command, capture_output=True, text=True) - - self.__print_process(process.stdout, process.stderr) - - if self.check_returncode: - process.check_returncode() - + def lines(self, strip: bool = True, **kwargs: bool): + process = self._get(**kwargs) lines = process.stdout.splitlines() return lines if not strip else list(map(lambda l: l.strip(), lines)) - def firstline(self): - lines = self.lines() + def firstline(self, **kwargs: bool): + lines = self.lines(**kwargs) return lines[0] if lines else "" - def exec(self): + def code(self, **kwargs): + return self._run(check=False, **kwargs).returncode + + def exec(self, **kwargs): + self._run(**kwargs) + + def _get(self, print: bool = False, check: bool = True): process = subprocess.run(self.command, capture_output=True, text=True) - self.__print_process(process.stdout, process.stderr) + if print: + self._print_process(process.stdout, process.stderr) - if self.check_returncode: + if check: process.check_returncode() - def code(self): - process = subprocess.run(self.command, capture_output=True, text=True) + return process - self.__print_process(process.stdout, process.stderr) - return process.returncode + def _run(self, print: bool = False, check: bool = True): + process = subprocess.run(self.command) - def without_checking(self): - self.check_returncode = False + if print: + self._print_process("", "") - return self + if check: + process.check_returncode() - def __print_process(self, stdout: str, stderr: str): + return process + + def _print_process(self, stdout: str, stderr: str): command = [] for arg in self.command: diff --git a/src/git_flow/main.py b/src/git_flow/main.py index 344df92..dfaa9c5 100755 --- a/src/git_flow/main.py +++ b/src/git_flow/main.py @@ -218,7 +218,7 @@ def tag_command(): message = output[pos+1:] merged_branch = None - output = Git("describe", commit, tags=True, exact_match=True).without_checking().firstline() + output = Git("describe", commit, tags=True, exact_match=True).firstline(check=False) if output: print_error("El ultimo merge ya tiene tag: " + output) From d133c480c5aefa3310be7c5dbce2ef439b2ee15d Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 11:28:51 -0300 Subject: [PATCH 2/6] bugfix: descartar output cuando el comando git se ejecuta con _run --- src/git_flow/git.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git_flow/git.py b/src/git_flow/git.py index 5ca7b0d..b5d9e7c 100644 --- a/src/git_flow/git.py +++ b/src/git_flow/git.py @@ -144,7 +144,7 @@ class Git: def _run(self, print: bool = False, check: bool = True): - process = subprocess.run(self.command) + process = subprocess.run(self.command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if print: self._print_process("", "") From 11e2a9daa9d4d1a60f590fa698ba1477642b87f0 Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 11:48:19 -0300 Subject: [PATCH 3/6] bugfix: cambiando tipo de print para agregar soporte de titulos --- src/git_flow/git.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/git_flow/git.py b/src/git_flow/git.py index b5d9e7c..b9606c1 100644 --- a/src/git_flow/git.py +++ b/src/git_flow/git.py @@ -114,7 +114,7 @@ class Git: self.command += args - def lines(self, strip: bool = True, **kwargs: bool): + def lines(self, strip: bool = True, **kwargs): process = self._get(**kwargs) lines = process.stdout.splitlines() @@ -131,11 +131,11 @@ class Git: def exec(self, **kwargs): self._run(**kwargs) - def _get(self, print: bool = False, check: bool = True): + def _get(self, print: str|None = None, check: bool = True): process = subprocess.run(self.command, capture_output=True, text=True) - if print: - self._print_process(process.stdout, process.stderr) + if print is not None: + self._print_process(process.stdout, process.stderr, print) if check: process.check_returncode() @@ -143,18 +143,18 @@ class Git: return process - def _run(self, print: bool = False, check: bool = True): + def _run(self, print: str|None = None, check: bool = True): process = subprocess.run(self.command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - if print: - self._print_process("", "") + if print is not None: + self._print_process("", "", title=print) if check: process.check_returncode() return process - def _print_process(self, stdout: str, stderr: str): + def _print_process(self, stdout: str, stderr: str, title: str): command = [] for arg in self.command: @@ -166,10 +166,12 @@ class Git: command.append(arg) - print(COLOR_YELLOW + "> " + " ".join(command) + COLOR_RESET) + title = title or "Ejecutando" + print(COLOR_YELLOW + "| " + title + COLOR_RESET) + print(COLOR_YELLOW + "| $ " + " ".join(command) + COLOR_RESET) for line in stdout.splitlines(): - print(COLOR_BLUE + "< " + line + COLOR_RESET) + print(COLOR_YELLOW + "| " + COLOR_RESET + "[out] " + line) for line in stderr.splitlines(): - print(COLOR_RED + "! " + line + COLOR_RESET) + print(COLOR_YELLOW + "| " + COLOR_RED + "[err] " + line + COLOR_RESET) From faea8c2d2a4749b2fee55bc9b5763a1b2a561181 Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 11:49:12 -0300 Subject: [PATCH 4/6] feature: agregando descripcion a ejecucion de comandos importantes en init y commit --- src/git_flow/command/commit.py | 18 +++++++++--------- src/git_flow/command/init.py | 29 +++++++++++++++-------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/git_flow/command/commit.py b/src/git_flow/command/commit.py index 55aebc1..2966fe3 100644 --- a/src/git_flow/command/commit.py +++ b/src/git_flow/command/commit.py @@ -18,8 +18,8 @@ class CommitCommand(Command): if not self._has_files_staged(): self.warning("No hay cambios en el indice para commitear.") - if self.confirm("¿Desea agregar la carpeta actual (`git add .`)?"): - Git("add", ".").exec() + if self.confirm("¿Desea agregar la carpeta actual?"): + Git("add", ".").exec(print="Agregando cambios") else: raise GitFlowError( "Debe agregar algún cambio al indice para continuar." @@ -33,19 +33,19 @@ class CommitCommand(Command): if branch.startswith("wip/"): original_branch = branch.removeprefix("wip/") - Git("commit", m=message).exec() + Git("commit", m=message).exec(print="Creando commit en rama WIP") if commit_type != "wip": suffix = datetime.now().strftime("%Y%m%dT%H%M") - Git("switch", original_branch).exec() - Git("merge", branch, squash=True).exec() - Git("commit", m=message).exec() - Git("branch", branch, "trash/" + branch + "/" + suffix, move=True).exec() + Git("switch", original_branch).exec(print="Volviendo a rama original") + Git("merge", branch, squash=True).exec(print="Squasheando commits WIP en uno solo") + Git("commit", m=message).exec(print="Creando commit final de rama WIP") + Git("branch", branch, "trash/" + branch + "/" + suffix, move=True).exec(print="Backup de rama WIP") else: if commit_type == "wip": - Git("switch", "wip/" + branch, create=True).exec() + Git("switch", "wip/" + branch, create=True).exec(print="Creando nueva rama WIP") - Git("commit", m=message).exec() + Git("commit", m=message).exec(print="Creando commit") def _has_files_staged(self): status = Git.status() diff --git a/src/git_flow/command/init.py b/src/git_flow/command/init.py index 2a425dd..2cbfab6 100644 --- a/src/git_flow/command/init.py +++ b/src/git_flow/command/init.py @@ -45,15 +45,12 @@ class InitCommand(Command): Git("init").exec() def _ensure_not_already_initialized(self): - if os.path.isfile(FLOWCONFIG_FILE): - flowconfig = Git.get_config(FLOWCONFIG_FILE) - - if flowconfig["flow.initialized"] == "true": - raise GitFlowError( - "El repositorio ya fue inicializado para usar git-flow" - ) - else: - raise GitFlowError("Valor de 'flow.initialized' es inválido") + 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( @@ -79,7 +76,7 @@ class InitCommand(Command): remote = None if self.confirm("¿Configurar repositorio remoto?"): - remotes = Git("remote").lines() + remotes = Git("remote").lines(print="Listando remotos disponibles") if not remotes: self.info("No tiene ningún repositorio remoto, se creará uno.") @@ -89,7 +86,7 @@ class InitCommand(Command): persistent=True, ) remote = "origin" - Git("remote", "add", remote, url).exec() + Git("remote", "add", remote, url).exec(print="Agregando remoto") elif len(remotes) == 1: remote = remotes[0] else: @@ -98,7 +95,7 @@ class InitCommand(Command): return remote - def _ensure_all_flow_branches_exist(self, branches: list[str], remote: str|None): + 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)): @@ -109,7 +106,11 @@ class InitCommand(Command): for branch in branches: if branch not in existing_branches: - Git("branch", branch, target_branch).exec() + Git("branch", branch, target_branch).exec( + print="Creando rama inexistente" + ) if remote: - Git("push", remote, branch, set_upstream=True).exec() + Git("push", remote, branch, set_upstream=True).exec( + print="Creando rama en remoto" + ) From 4135a789e3231efa5ac0e50d8fc889a20518d82a Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 12:02:39 -0300 Subject: [PATCH 5/6] feature: agregando descripcion a ejecucion de comandos importantes en new, tag y merge --- src/git_flow/command/merge.py | 26 ++++++++++++++++---------- src/git_flow/command/new.py | 2 +- src/git_flow/command/tag.py | 10 ++++------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/git_flow/command/merge.py b/src/git_flow/command/merge.py index 70d8f79..716e097 100644 --- a/src/git_flow/command/merge.py +++ b/src/git_flow/command/merge.py @@ -29,25 +29,28 @@ class MergeCommand(Command): def run_remote(self, remote: str, token: str, base: str, branch: str, target: str): self.check_pending_changes(True) - Git("switch", target).exec() - Git("pull").exec() - Git("switch", "-").exec() + Git("switch", target).exec(print="Cambiando a rama destino") + Git("pull").exec(print="Obteniendo ultimos cambios del remoto") + Git("switch", "-").exec(print="Volviendo a rama a mergear") self.check_merge_conflicts(target) self.show_commits_to_merge(base) - Git("push", remote, branch, set_upstream=True).exec() + if self.confirm(f"¿Crear PR de '{branch}' a '{target}'?"): + Git("push", remote, branch, set_upstream=True).exec( + print="Subiendo rama al remoto para crear PR" + ) - self.create_pull_request(token, base, branch, target) + self.create_pull_request(token, base, branch, target) def run_local(self, base: str, branch: str, target: str): self.check_pending_changes(False) self.check_merge_conflicts(target) self.show_commits_to_merge(base) - if self.confirm(f"Mergear rama '{target}' <= '{branch}'?"): - Git("switch", target).exec() - Git("merge", branch, ff=False).exec() + if self.confirm(f"¿Mergear rama '{branch}' a '{target}'?"): + Git("switch", target).exec(print="Cambiando a rama destino") + Git("merge", branch, ff=False).exec(print="Mergeando") def check_pending_changes(self, has_remote: bool): status = Git.status() @@ -78,10 +81,13 @@ class MergeCommand(Command): print("- " + commit) def check_merge_conflicts(self, target: str): - merge_conflicts = Git("merge", target, ff=False, commit=False).code() != 0 + merge_conflicts = Git("merge", target, ff=False, commit=False).code( + print="Realizando merge de prueba para verificar conflictos" + ) + + Git("merge", abort=True).exec(print="Abortando merge de prueba") if merge_conflicts: - Git("merge", abort=True).exec() self.error(f"La rama actual tiene conflictos con {target}") self.info( f"""Se recomienda mergear {target} a la rama actual, resolver los conflictos localmente, y ejecutar nuevamente este comando""" diff --git a/src/git_flow/command/new.py b/src/git_flow/command/new.py index e5df5e9..8f23f92 100644 --- a/src/git_flow/command/new.py +++ b/src/git_flow/command/new.py @@ -22,7 +22,7 @@ class NewCommand(Command): new_branch = self._get_unique_branch_name(branch_type) if self.confirm(f"¿Crear rama '{new_branch}' sobre la rama actual?"): - Git("switch", new_branch, create=True).exec() + Git("switch", new_branch, create=True).exec(print="Creando nueva rama") def _get_unique_branch_name(self, branch_type: str) -> str: self.info( diff --git a/src/git_flow/command/tag.py b/src/git_flow/command/tag.py index 79233a7..eecfdde 100644 --- a/src/git_flow/command/tag.py +++ b/src/git_flow/command/tag.py @@ -43,17 +43,15 @@ class TagCommand(Command): changelog = Changelog() changelog.update(next_tag, base, branch) - Git("add", Changelog.FILENAME).exec() - Git("commit", message=Changelog.COMMIT_MESSAGE).exec() + Git("add", Changelog.FILENAME).exec(print="Agregando nuevo CHANGELOG.md") + Git("commit", message=Changelog.COMMIT_MESSAGE).exec(print="Creando commit") tag_commit = Git("show", "HEAD", patch=False, format="%h").firstline() - self.check_not_tagged(tag_commit) - if ci: - Git("push").exec() + Git("push").exec(print="Subiendo commit al remoto para taggearlo") self.success(self.get_remote_api(token).create_tag(next_tag, tag_commit)) else: - Git("tag", next_tag, tag_commit).exec() + Git("tag", next_tag, tag_commit).exec(print="Creando tag localmente") def get_token_and_ci(self, args: Namespace): try: From 34aba71d324836f4746249f4193b9ffad188d8c8 Mon Sep 17 00:00:00 2001 From: Jonathan Teran Carballo Date: Sat, 22 Nov 2025 12:07:46 -0300 Subject: [PATCH 6/6] bugfix: deshabilito check en merge --abort al buscar conflictos --- src/git_flow/command/merge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git_flow/command/merge.py b/src/git_flow/command/merge.py index 716e097..b3faafb 100644 --- a/src/git_flow/command/merge.py +++ b/src/git_flow/command/merge.py @@ -85,7 +85,7 @@ class MergeCommand(Command): print="Realizando merge de prueba para verificar conflictos" ) - Git("merge", abort=True).exec(print="Abortando merge de prueba") + Git("merge", abort=True).exec(print="Abortando merge de prueba", check=False) if merge_conflicts: self.error(f"La rama actual tiene conflictos con {target}")