Merged in feature/add-git-exec-options (pull request #31)

feature: add git exec options

Approved-by: Jonathan Teran
This commit is contained in:
JonathanGitFlow
2025-11-22 15:08:46 +00:00
committed by jt
7 changed files with 77 additions and 72 deletions
+9 -9
View File
@@ -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()
+13 -12
View File
@@ -45,13 +45,10 @@ 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"
)
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")
@@ -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"
)
+15 -9
View File
@@ -29,14 +29,17 @@ 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)
@@ -45,9 +48,9 @@ class MergeCommand(Command):
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", check=False)
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"""
+1 -1
View File
@@ -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(
+5 -11
View File
@@ -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:
@@ -77,11 +75,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)
+30 -26
View File
@@ -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):
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: str|None = None, check: bool = True):
process = subprocess.run(self.command, capture_output=True, text=True)
self.__print_process(process.stdout, process.stderr)
if print is not None:
self._print_process(process.stdout, process.stderr, print)
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: str|None = None, check: bool = True):
process = subprocess.run(self.command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def without_checking(self):
self.check_returncode = False
if print is not None:
self._print_process("", "", title=print)
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, title: str):
command = []
for arg in self.command:
@@ -164,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)
+1 -1
View File
@@ -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)