feat: add bash shell utility functions

12 funciones Bash del dominio shell: utilidades de scripting (bash_log,
bash_colors, bash_check_deps, bash_confirm, bash_handle_error, bash_safe_run),
manipulacion de texto (convert_text_case), estructura de proyectos
(create_project_structure), y operaciones git (git_clean_branches,
git_log_visual, git_push_all_remotes, git_repo_status). Cada una con su
.sh y .md de frontmatter.
This commit is contained in:
2026-04-12 13:54:15 +02:00
parent 61c9042392
commit 61d8460149
24 changed files with 1522 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
---
name: bash_check_deps
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "check_command(cmd: string, [error_code: string], [description: string]) -> void; check_commands(cmd...: string) -> void; check_directory(dir: string, [msg: string]) -> void; check_file(file: string, [msg: string]) -> void"
description: "Verifica existencia de comandos, directorios y archivos con output formateado. Complementa assert_command_exists con mensajes de error detallados y logging."
tags: [bash, check, dependency, command, exists, validation]
uses_functions: [bash_log_bash_shell]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: cmd
desc: "nombre del comando a verificar en PATH"
- name: error_code
desc: "codigo identificador del error; default COMMAND_NOT_FOUND"
- name: description
desc: "mensaje de error personalizado; default 'El comando CMD no esta disponible'"
- name: dir
desc: "ruta del directorio a verificar"
- name: file
desc: "ruta del archivo a verificar"
output: "exit code 0 si todas las verificaciones pasan; exit code 1 en caso de fallo con mensaje de error formateado"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_check_deps.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_check_deps.sh
check_command "docker" "DOCKER_NOT_FOUND" "Docker no esta instalado"
check_commands "git" "curl" "jq"
check_directory "/var/data" "El directorio de datos no existe"
check_file "/etc/config.yaml" "Falta el archivo de configuracion"
```
## Notas
`check_command` acepta un error_code y descripcion opcionales para mensajes mas descriptivos que `assert_command_exists`. Usa `debug` internamente para loggear cada verificacion.
`check_commands` verifica multiples comandos en una sola llamada y reporta todos los faltantes antes de retornar 1.
Sourcea `bash_log.sh` automaticamente, que a su vez sourcea `bash_colors.sh`. No es necesario sourcea dependencias por separado.
+75
View File
@@ -0,0 +1,75 @@
# bash_check_deps
# ---------------
# Verifica existencia de comandos, directorios y archivos.
# Output formateado con colores via bash_log.
#
# USO (sourced):
# source bash_check_deps.sh
# check_command "docker" "DOCKER_NOT_FOUND" "Docker no esta instalado"
# check_commands "git" "curl" "jq"
# check_directory "/path/to/dir"
# check_file "/path/to/file"
SCRIPT_DIR_BASH_CHECK="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR_BASH_CHECK/bash_log.sh"
bash_log_init
check_command() {
local cmd="$1"
local error_code="${2:-COMMAND_NOT_FOUND}"
local description="${3:-El comando '$cmd' no esta disponible}"
debug "Verificando comando: $cmd"
if ! command -v "$cmd" &> /dev/null; then
error "$description ($error_code)"
return 1
fi
return 0
}
check_commands() {
local failed=0
for cmd in "$@"; do
if ! command -v "$cmd" &> /dev/null; then
error "Comando no encontrado: $cmd"
failed=1
fi
done
if [ $failed -eq 1 ]; then
error "Faltan multiples dependencias requeridas"
return 1
fi
return 0
}
check_directory() {
local dir="$1"
local error_msg="${2:-El directorio '$dir' no existe}"
debug "Verificando directorio: $dir"
if [ ! -d "$dir" ]; then
error "$error_msg"
return 1
fi
return 0
}
check_file() {
local file="$1"
local error_msg="${2:-El archivo '$file' no existe}"
debug "Verificando archivo: $file"
if [ ! -f "$file" ]; then
error "$error_msg"
return 1
fi
return 0
}
+47
View File
@@ -0,0 +1,47 @@
---
name: bash_colors
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: pure
signature: "bash_colors() -> void"
description: "Exporta variables ANSI de colores, caracteres box drawing y simbolos unicode para uso en scripts de terminal."
tags: [bash, colors, ansi, terminal, symbols, box]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params: []
output: "exporta variables de entorno con codigos ANSI: colores (RED, GREEN, BLUE, etc.), box drawing (BOX_TL, BOX_H, etc.) y simbolos (CHECKMARK, CROSS, ARROW, etc.)"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_colors.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_colors.sh
bash_colors
echo -e "${GREEN}Todo bien${NC}"
echo -e "${RED}${CROSS} Error detectado${NC}"
echo -e "${BOX_TL}${BOX_H}${BOX_TR}"
```
## Notas
Funcion pura: solo define y exporta variables de entorno, sin I/O ni efectos secundarios. Debe llamarse una vez antes de usar cualquier variable de color o simbolo.
Variables de color disponibles: PURPLE, MAGENTA, GREEN, BLUE, YELLOW, RED, CYAN, ORANGE, GRAY, DIM_GRAY, BOLD, DIM, NC.
Variables box drawing: BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_ML, BOX_MR, BOX_SEP.
Simbolos unicode: CHECKMARK, CROSS, ARROW, BULLET, WARNING, INFO.
+41
View File
@@ -0,0 +1,41 @@
# bash_colors
# -----------
# Variables ANSI de color, caracteres box drawing y simbolos para scripts.
# Diseñado para ser sourced por otros scripts.
#
# USO (sourced):
# source bash_colors.sh
# bash_colors
bash_colors() {
export PURPLE='\033[35m'
export MAGENTA='\033[35m'
export GREEN='\033[0;32m'
export BLUE='\033[0;34m'
export YELLOW='\033[1;33m'
export RED='\033[0;31m'
export CYAN='\033[0;36m'
export ORANGE='\033[0;33m'
export GRAY='\033[0;90m'
export DIM_GRAY='\033[2;37m'
export BOLD='\033[1m'
export DIM='\033[2m'
export NC='\033[0m'
export BOX_TL="╔"
export BOX_TR="╗"
export BOX_BL="╚"
export BOX_BR="╝"
export BOX_H="═"
export BOX_V="║"
export BOX_ML="╠"
export BOX_MR="╣"
export BOX_SEP="─"
export CHECKMARK="✓"
export CROSS="✗"
export ARROW="→"
export BULLET="•"
export WARNING="⚠"
export INFO=""
}
+52
View File
@@ -0,0 +1,52 @@
---
name: bash_confirm
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "bash_confirm(prompt: string, [default: string]) -> exit_code"
description: "Dialogo interactivo de confirmacion y/n con valor por defecto configurable. Soporta respuestas yes/y/si."
tags: [bash, confirm, prompt, interactive, dialog]
uses_functions: [bash_colors_bash_shell]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: prompt
desc: "pregunta a mostrar al usuario; default '¿Continuar?'"
- name: default
desc: "valor por defecto cuando el usuario presiona Enter sin escribir nada; 'y' o 'n'; default 'n'"
output: "exit code 0 si el usuario confirma (y/yes/si), exit code 1 si niega o acepta el default negativo"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_confirm.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_confirm.sh
# Con default no (muestra [y/N])
if bash_confirm "¿Deseas continuar?"; then
echo "Continuando..."
fi
# Con default yes (muestra [Y/n])
bash_confirm "¿Eliminar archivos temporales?" "y" && rm -rf /tmp/cache
```
## Notas
El prompt muestra el default en mayuscula: `[Y/n]` cuando default=y, `[y/N]` cuando default=n. Si el usuario presiona Enter sin escribir, se usa el valor por defecto.
Acepta variantes: y, Y, yes, YES, si, SI como afirmativo. Cualquier otra respuesta se trata como negativo.
Usa colores de `bash_colors` para el prompt en amarillo. Requiere terminal interactiva (lee de stdin con `read -r`).
+36
View File
@@ -0,0 +1,36 @@
# bash_confirm
# ------------
# Dialogo de confirmacion y/n con valor por defecto.
#
# USO (sourced):
# source bash_confirm.sh
# bash_confirm "Continuar?" && echo "Si" || echo "No"
# bash_confirm "Eliminar?" "y" # default yes
SCRIPT_DIR_BASH_CONFIRM="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR_BASH_CONFIRM/bash_colors.sh"
bash_colors
bash_confirm() {
local prompt="${1:-¿Continuar?}"
local default="${2:-n}"
if [ "$default" = "y" ]; then
prompt="$prompt [Y/n]"
else
prompt="$prompt [y/N]"
fi
echo -ne "${YELLOW}$prompt ${NC}"
read -r response
response=${response:-$default}
case "$response" in
[yY][eE][sS]|[yY]|[sS][iI])
return 0
;;
*)
return 1
;;
esac
}
+57
View File
@@ -0,0 +1,57 @@
---
name: bash_handle_error
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "handle_error(error_code: string, error_description: string, [solution: string]) -> exit_code"
description: "Muestra un box de error formateado con contexto del fallo: script, linea, funcion, directorio y usuario. Registra en log."
tags: [bash, error, handler, box, formatted, context]
uses_functions: [bash_colors_bash_shell, bash_log_bash_shell]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: error_code
desc: "codigo identificador del error, ej: BUILD_FAILED, DB_CONNECTION_ERROR"
- name: error_description
desc: "descripcion legible del error para mostrar al usuario"
- name: solution
desc: "solucion sugerida; opcional; si se provee se muestra en seccion separada"
output: "box de error formateado en stdout con contexto (script, linea, funcion, directorio, usuario) + registro en log; retorna exit code 1"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_handle_error.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_handle_error.sh
build_project() {
go build ./... || handle_error "BUILD_FAILED" \
"La compilacion del proyecto fallo" \
"Ejecuta 'go mod tidy' y verifica que todas las dependencias esten instaladas"
}
connect_db() {
psql "$DB_URL" -c '\q' 2>/dev/null || handle_error "DB_CONNECTION_ERROR" \
"No se pudo conectar a la base de datos"
}
```
## Notas
El box usa caracteres unicode de `bash_colors` (BOX_TL, BOX_H, etc.) para el borde en rojo. La informacion de contexto se extrae de `BASH_SOURCE`, `BASH_LINENO` y `FUNCNAME` con offset 2 para apuntar al caller del caller.
La funcion siempre retorna 1, permitiendo usarla como `cmd || handle_error ...` en pipelines de error.
Usa `bash_colors` y `bash_log` como dependencias. Sourcea ambas automaticamente al cargarse.
+47
View File
@@ -0,0 +1,47 @@
# bash_handle_error
# -----------------
# Muestra un box de error formateado con contexto del fallo.
# Incluye script, linea, funcion y directorio.
#
# USO (sourced):
# source bash_handle_error.sh
# handle_error "BUILD_FAILED" "La compilacion fallo" "Verifica las dependencias"
SCRIPT_DIR_BASH_HANDLE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR_BASH_HANDLE/bash_colors.sh"
source "$SCRIPT_DIR_BASH_HANDLE/bash_log.sh"
bash_colors
bash_log_init
handle_error() {
local error_code="$1"
local error_description="$2"
local solution="$3"
echo ""
echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}${CROSS} ERROR DETECTADO ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${RED}${BOLD}Error:${NC} ${error_description}"
echo -e "${GRAY}Codigo: ${error_code}${NC}"
echo ""
if [ -n "$solution" ]; then
echo -e "${YELLOW}${INFO} Solucion sugerida:${NC}"
echo -e " ${solution}"
echo ""
fi
echo -e "${GRAY}${INFO} Informacion adicional:${NC}"
echo -e " ${GRAY}${BULLET} Script: ${BASH_SOURCE[2]:-desconocido}${NC}"
echo -e " ${GRAY}${BULLET} Linea: ${BASH_LINENO[1]:-desconocido}${NC}"
echo -e " ${GRAY}${BULLET} Funcion: ${FUNCNAME[2]:-main}${NC}"
echo -e " ${GRAY}${BULLET} Directorio: $(pwd)${NC}"
echo -e " ${GRAY}${BULLET} Usuario: $(whoami)${NC}"
echo ""
log "ERROR" "Code: $error_code | Description: $error_description | Script: ${BASH_SOURCE[2]} | Line: ${BASH_LINENO[1]}"
return 1
}
+52
View File
@@ -0,0 +1,52 @@
---
name: bash_log
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "bash_log_init() -> void; success(msg: string) -> void; info(msg: string) -> void; warning(msg: string) -> void; error(msg: string) -> void; debug(msg: string) -> void; progress(msg: string) -> void"
description: "Funciones de logging con colores para scripts bash. Incluye niveles success/info/warning/error/debug/progress con escritura a archivo de log."
tags: [bash, log, logging, colors, terminal]
uses_functions: [bash_colors_bash_shell]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: msg
desc: "mensaje a mostrar y registrar en el archivo de log"
output: "mensaje formateado con colores en stdout/stderr y registro con timestamp en archivo de log (ERROR_LOG_FILE)"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_log.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_log.sh
bash_log_init
success "Servicio iniciado correctamente"
info "Procesando 42 registros..."
warning "El puerto 8080 ya esta en uso"
error "No se pudo conectar a la base de datos"
debug "Valor de variable: $VAR"
progress "Descargando imagen Docker..."
```
## Notas
Llama a `bash_log_init` una vez al inicio para configurar ERROR_LOG_FILE y DEBUG_MODE. Por defecto el log va a `/tmp/script-errors-YYYYMMDD.log`.
La variable de entorno `DEBUG_MODE=1` activa los mensajes de debug a stderr y muestra timestamps en todos los logs.
`error` escribe a stderr; el resto a stdout. Todos los niveles escriben al archivo de log independientemente de DEBUG_MODE.
Fuente: sourcea `bash_colors.sh` automaticamente al cargarse.
+64
View File
@@ -0,0 +1,64 @@
# bash_log
# --------
# Funciones de logging con colores para scripts.
# Incluye: log, success, info, warning, error, debug, progress.
#
# USO (sourced):
# source bash_log.sh
# bash_log_init
# success "Operacion completada"
# info "Procesando..."
# error "Algo fallo"
SCRIPT_DIR_BASH_LOG="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR_BASH_LOG/bash_colors.sh"
bash_colors
bash_log_init() {
export ERROR_LOG_FILE="${ERROR_LOG_FILE:-/tmp/script-errors-$(date +%Y%m%d).log}"
export DEBUG_MODE="${DEBUG_MODE:-0}"
}
log() {
local level="$1"
shift
local message="$@"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" >> "${ERROR_LOG_FILE:-/tmp/script-errors.log}"
if [ "${DEBUG_MODE:-0}" = "1" ]; then
echo -e "${GRAY}[$timestamp] [$level] $message${NC}" >&2
fi
}
success() {
echo -e "${GREEN}${CHECKMARK} $*${NC}"
log "SUCCESS" "$*"
}
info() {
echo -e "${BLUE}${INFO} $*${NC}"
log "INFO" "$*"
}
warning() {
echo -e "${YELLOW}${WARNING} $*${NC}"
log "WARNING" "$*"
}
error() {
echo -e "${RED}${CROSS} Error: $*${NC}" >&2
log "ERROR" "$*"
}
debug() {
if [ "${DEBUG_MODE:-0}" = "1" ]; then
echo -e "${GRAY}[DEBUG] $*${NC}" >&2
fi
log "DEBUG" "$*"
}
progress() {
echo -e "${CYAN}${ARROW} $*${NC}"
}
+52
View File
@@ -0,0 +1,52 @@
---
name: bash_safe_run
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "safe_run(cmd: string, [error_code: string], [error_desc: string]) -> void; setup_error_trap() -> void; error_trap_handler(exit_code: int, line_number: int) -> void"
description: "Ejecuta comandos con manejo de errores integrado. Incluye trap handler que captura fallos con numero de linea y codigo de salida."
tags: [bash, safe, run, error, trap, handler]
uses_functions: [bash_log_bash_shell]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: cmd
desc: "comando a ejecutar via eval"
- name: error_code
desc: "codigo identificador del error en caso de fallo; default COMMAND_FAILED"
- name: error_desc
desc: "descripcion del error a mostrar; default 'El comando fallo: CMD'"
output: "exit code 0 si el comando tuvo exito; exit code 1 con mensaje de error formateado si fallo"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/bash_safe_run.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/lib/common.sh"
---
## Ejemplo
```bash
source bash/functions/shell/bash_safe_run.sh
bash_log_init
setup_error_trap
safe_run "go build ./..." "BUILD_FAILED" "La compilacion fallo"
safe_run "docker compose up -d" "DOCKER_FAILED" "No se pudo iniciar Docker Compose"
safe_run "npm install" "NPM_FAILED"
```
## Notas
`safe_run` usa `eval` internamente para ejecutar el comando, lo que permite pasar comandos con pipes y redirecciones como string. Usar con precaucion en entornos con input no confiable.
`setup_error_trap` instala un trap `ERR` que llama a `error_trap_handler` automaticamente en cualquier comando fallido del script, mostrando numero de linea y codigo de salida.
`error_trap_handler` no llama a `exit` — el caller decide si continuar o abortar. Muestra la ruta al log para debugging.
+44
View File
@@ -0,0 +1,44 @@
# bash_safe_run
# -------------
# Ejecutar comandos con manejo de errores y trap.
# Incluye safe_run, setup_error_trap y error_trap_handler.
#
# USO (sourced):
# source bash_safe_run.sh
# setup_error_trap
# safe_run "go build ./..." "BUILD_FAILED" "La compilacion fallo"
SCRIPT_DIR_BASH_SAFE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR_BASH_SAFE/bash_log.sh"
bash_log_init
safe_run() {
local cmd="$1"
local error_code="${2:-COMMAND_FAILED}"
local error_desc="${3:-El comando fallo: $cmd}"
debug "Ejecutando: $cmd"
if ! eval "$cmd"; then
error "$error_desc ($error_code)"
return 1
fi
return 0
}
setup_error_trap() {
trap 'error_trap_handler $? $LINENO' ERR
}
error_trap_handler() {
local exit_code=$1
local line_number=$2
if [ "$exit_code" -ne 0 ]; then
echo ""
error "El script fallo en la linea $line_number con codigo de salida $exit_code"
echo -e "${GRAY}Consulta el log: ${ERROR_LOG_FILE:-/tmp/script-errors.log}${NC}"
echo ""
fi
}
+54
View File
@@ -0,0 +1,54 @@
---
name: convert_text_case
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "convert_text_case(mode: string, file: string, [output_file: string]) -> void"
description: "Convierte el contenido de un archivo de texto. Modos: upper (todo mayúsculas), lower (todo minúsculas), lf (normaliza saltos de línea a LF eliminando \\r), crlf (normaliza saltos a CRLF). Sin output_file imprime a stdout."
tags: [bash, text, convert, case, encoding]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: mode
desc: "transformación a aplicar: upper|lower|lf|crlf (requerido)"
- name: file
desc: "ruta al archivo de entrada (requerido)"
- name: output_file
desc: "ruta al archivo de salida (opcional; default: stdout)"
output: "texto convertido a stdout o escrito en output_file; exit code 1 si el modo o archivo son inválidos"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/convert_text_case.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/conversores/conversor_texto.sh"
---
## Ejemplo
```bash
source bash/functions/shell/convert_text_case.sh
# Convertir a mayúsculas y mostrar en stdout
convert_text_case upper mi_archivo.txt
# Convertir a minúsculas y guardar en archivo
convert_text_case lower input.txt output_lower.txt
# Normalizar saltos de línea CRLF a LF
convert_text_case lf archivo_windows.txt archivo_unix.txt
# Añadir CRLF (para Windows)
convert_text_case crlf unix.txt windows.txt
```
## Notas
Usa `awk` para las conversiones de case (portable) y `sed` para los saltos de línea. La función no modifica el archivo original si se provee `output_file`. Sin `output_file` imprime directamente a stdout, útil para pipes.
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# convert_text_case
# -----------------
# Convierte el contenido de texto de un archivo aplicando transformaciones:
# upper (mayúsculas), lower (minúsculas), lf (normalizar saltos a LF),
# crlf (normalizar saltos a CRLF).
#
# USO:
# source convert_text_case.sh
# convert_text_case mode file [output_file]
#
# ARGUMENTOS:
# mode Transformación a aplicar: upper|lower|lf|crlf (requerido)
# file Archivo de entrada (requerido)
# output_file Archivo de salida (opcional; por defecto imprime a stdout)
convert_text_case() {
local mode="${1:-}"
local input_file="${2:-}"
local output_file="${3:-}"
# Validar argumentos requeridos
if [[ -z "$mode" ]]; then
echo "convert_text_case: modo requerido (upper|lower|lf|crlf)" >&2
return 1
fi
if [[ -z "$input_file" ]]; then
echo "convert_text_case: archivo de entrada requerido" >&2
return 1
fi
if [[ ! -f "$input_file" ]]; then
echo "convert_text_case: archivo no encontrado: ${input_file}" >&2
return 1
fi
# Función auxiliar que aplica la conversión y escribe a stdout o archivo
_apply_conversion() {
local src="$1"
local op="$2"
case "$op" in
upper)
awk '{ print toupper($0) }' "$src"
;;
lower)
awk '{ print tolower($0) }' "$src"
;;
lf)
sed 's/\r$//' "$src"
;;
crlf)
sed 's/\r$//' "$src" | sed 's/$/\r/'
;;
*)
echo "convert_text_case: modo no soportado: ${op}. Usa: upper|lower|lf|crlf" >&2
return 1
;;
esac
}
if [[ -n "$output_file" ]]; then
_apply_conversion "$input_file" "$mode" > "$output_file"
echo "convert_text_case: ${input_file}${output_file} (modo: ${mode})"
else
_apply_conversion "$input_file" "$mode"
fi
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
convert_text_case "$@"
fi
@@ -0,0 +1,44 @@
---
name: create_project_structure
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "create_project_structure(project_name: string) -> void"
description: "Crea la estructura de directorios estándar de un proyecto funcional en el directorio indicado: database (attachments, data, models), dist (desktop/mobile/docker), docker, docs, frontend, logs, notebooks, robots, scripts, src (application/core/middleware con tests y tipos)."
tags: [bash, project, structure, scaffold, init]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: project_name
desc: "nombre del proyecto o ruta destino donde crear la estructura (requerido)"
output: "crea los directorios a stdout con conteo final; exit code 1 si no se proporciona nombre"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/create_project_structure.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/inicializar_repos/functional_structure.sh"
---
## Ejemplo
```bash
source bash/functions/shell/create_project_structure.sh
# Crear estructura en un directorio nuevo
create_project_structure mi-proyecto
# Usar una ruta
create_project_structure /home/user/projects/nuevo-proyecto
```
## Notas
Crea 68 directorios organizados en la estructura funcional de DevLauncher. La estructura separa claramente application (orquestación), core (lógica pura) y middleware (efectos/I/O) bajo `src/`. No crea archivos, solo directorios. Idempotente: si los directorios ya existen, no falla.
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# create_project_structure
# ------------------------
# Crea la estructura de directorios estándar de un proyecto funcional
# (database, dist, docker, docs, frontend, logs, notebooks, robots,
# scripts, src con application/core/middleware) en el directorio indicado.
#
# USO:
# source create_project_structure.sh
# create_project_structure project_name
#
# ARGUMENTOS:
# project_name Nombre del proyecto / ruta destino (requerido)
create_project_structure() {
local project_name="${1:-}"
if [[ -z "$project_name" ]]; then
echo "create_project_structure: se requiere el nombre del proyecto" >&2
echo " Uso: create_project_structure <project_name>" >&2
return 1
fi
local destino="$project_name"
local directories=(
"database"
"database/attachments"
"database/attachments/audio"
"database/attachments/docs"
"database/attachments/images"
"database/attachments/video"
"database/data"
"database/data/01_raw"
"database/data/02_clean"
"database/data/03_objects"
"database/data/04_answers"
"database/models"
"dist"
"dist/desktop"
"dist/desktop/linux"
"dist/desktop/mac"
"dist/desktop/win"
"dist/docker"
"dist/mobile"
"dist/mobile/android"
"dist/mobile/ios"
"docker"
"docs"
"docs/documentation"
"docs/pdf"
"frontend"
"logs"
"notebooks"
"robots"
"scripts"
"src"
"src/application"
"src/application/event"
"src/application/jobs"
"src/application/pipes"
"src/application/sandbox"
"src/application/simulation"
"src/application/tasks"
"src/application/tests"
"src/application/tests/benchmark"
"src/application/tests/fuzzers"
"src/application/tests/mocks"
"src/application/tests/mutation"
"src/core"
"src/core/base"
"src/core/functions"
"src/core/rules"
"src/core/tests"
"src/core/tests/benchmark"
"src/core/tests/fuzzers"
"src/core/tests/mocks"
"src/core/tests/mutation"
"src/core/types"
"src/core/utils"
"src/middleware"
"src/middleware/api"
"src/middleware/backend"
"src/middleware/browser"
"src/middleware/config"
"src/middleware/connection"
"src/middleware/controller"
"src/middleware/i18n"
"src/middleware/interfaces"
"src/middleware/queue"
"src/middleware/servers"
"src/middleware/tests"
"src/middleware/tests/benchmark"
"src/middleware/tests/fuzzers"
"src/middleware/tests/mocks"
"src/middleware/tests/mutation"
"src/middleware/types"
"src/modules"
)
echo "Creando estructura del proyecto: ${destino}"
for dir in "${directories[@]}"; do
mkdir -p "${destino%/}/${dir}"
done
echo "Estructura creada en: ${destino%/}"
echo " ${#directories[@]} directorios creados."
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
create_project_structure "$@"
fi
@@ -0,0 +1,51 @@
---
name: git_clean_branches
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "git_clean_branches([base_branch: string], [--remote], [--force]) -> void"
description: "Elimina ramas locales ya mergeadas en la rama base (autodetecta main/master). Con --remote también borra las ramas en todos los remotes. Con --force omite la confirmación interactiva."
tags: [bash, git, branches, clean, merge]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: base_branch
desc: "rama base para detectar merges (opcional; autodetecta main o master)"
- name: --remote
desc: "flag para también eliminar ramas en todos los remotes"
- name: --force
desc: "flag para omitir confirmación interactiva"
output: "lista de ramas eliminadas a stdout; exit code 1 si no es repo Git o no se detecta la rama base"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/git_clean_branches.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/git_utils/limpiar_ramas.sh"
---
## Ejemplo
```bash
source bash/functions/shell/git_clean_branches.sh
# Limpieza básica con confirmación
git_clean_branches
# Sin confirmación, sobre rama base "develop"
git_clean_branches develop --force
# Eliminar también en remotes
git_clean_branches main --remote --force
```
## Notas
Ramas protegidas que nunca se eliminan: `main`, `master`, `develop`, `dev`, `staging`, `release`. Siempre hace prune de referencias remotas obsoletas antes de buscar candidatos.
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env bash
# git_clean_branches
# ------------------
# Elimina ramas locales ya mergeadas en la rama base (main/master por defecto).
# Opcionalmente también elimina las ramas en remotes.
#
# USO:
# source git_clean_branches.sh
# git_clean_branches [base_branch] [--remote] [--force]
#
# ARGUMENTOS:
# base_branch Rama base (opcional; autodetecta main/master si se omite)
# --remote Elimina también las ramas en todos los remotes
# --force Omite confirmación interactiva
git_clean_branches() {
local base_branch=""
local delete_remote=false
local force=false
# Parsear argumentos
for arg in "$@"; do
case "$arg" in
--remote) delete_remote=true ;;
--force) force=true ;;
*) [[ -z "$base_branch" ]] && base_branch="$arg" ;;
esac
done
# Validar repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "git_clean_branches: el directorio actual no es un repositorio Git" >&2
return 1
fi
# Detectar rama base
if [[ -z "$base_branch" ]]; then
if git show-ref --verify --quiet refs/heads/main; then
base_branch="main"
elif git show-ref --verify --quiet refs/heads/master; then
base_branch="master"
else
echo "git_clean_branches: no se detectó main/master; pasa la rama base como argumento" >&2
return 1
fi
fi
echo "git_clean_branches: rama base = ${base_branch}"
# Hacer prune de referencias remotas obsoletas
echo "Haciendo prune de referencias remotas..."
git remote | while IFS= read -r remote; do
git remote prune "$remote" 2>/dev/null && echo " Pruned: ${remote}"
done
echo ""
# Buscar ramas locales mergeadas
local candidates
candidates="$(git branch --merged "$base_branch" \
| grep -v -E "^\*|^\s*(main|master|develop|dev|staging|release)$" \
| sed 's/^[[:space:]]*//' \
| grep -v "^$" || true)"
if [[ -z "$candidates" ]]; then
echo "No hay ramas locales mergeadas para eliminar."
return 0
fi
echo "Ramas candidatas a eliminar:"
echo "$candidates" | while IFS= read -r b; do
echo " - ${b}"
done
echo ""
# Confirmación (omitir si --force)
if [[ "$force" != true ]]; then
echo -n "¿Eliminar estas ramas locales? [y/N] "
read -r answer
[[ "$answer" != "y" && "$answer" != "Y" ]] && { echo "Operación cancelada."; return 0; }
fi
# Eliminar ramas locales
local deleted=0
local failed=0
while IFS= read -r branch; do
if git branch -d "$branch"; then
echo " Eliminada local: ${branch}"
deleted=$((deleted + 1))
else
echo " No se pudo eliminar: ${branch}" >&2
failed=$((failed + 1))
fi
done <<< "$candidates"
echo ""
echo "Resumen: ${deleted} eliminada(s), ${failed} fallida(s)"
# Eliminar en remotes si se solicitó
if [[ "$delete_remote" == true ]]; then
local remotes
remotes="$(git remote 2>/dev/null || true)"
if [[ -n "$remotes" ]]; then
echo ""
echo "Eliminando ramas en remotes..."
while IFS= read -r branch; do
while IFS= read -r remote; do
if git ls-remote --heads "$remote" "$branch" 2>/dev/null | grep -q "$branch"; then
if git push "$remote" --delete "$branch"; then
echo " Eliminada remota: ${remote}/${branch}"
else
echo " No se pudo eliminar remota: ${remote}/${branch}" >&2
fi
fi
done <<< "$remotes"
done <<< "$candidates"
fi
fi
echo ""
echo "Limpieza completada."
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
git_clean_branches "$@"
fi
+56
View File
@@ -0,0 +1,56 @@
---
name: git_log_visual
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "git_log_visual([--count N: int], [--author X: string], [--since D: string], [--all]) -> void"
description: "Muestra el historial de commits Git con grafo visual, colores y formato legible (hash, fecha, autor, mensaje, ramas). Soporta filtros por cantidad, autor, fecha y modo todas-las-ramas. Pagina con less."
tags: [bash, git, log, history, graph]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: --count
desc: "número de commits a mostrar (default: 20)"
- name: --author
desc: "filtrar por nombre o email del autor (parcial, igual que git --author)"
- name: --since
desc: "mostrar solo commits desde esta fecha (ej: '1 week ago', '2025-01-01')"
- name: --all
desc: "incluir commits de todas las ramas, no solo la actual"
output: "historial de commits paginado con less -R; exit code 1 si no es un repo Git"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/git_log_visual.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/git_utils/historial_commits.sh"
---
## Ejemplo
```bash
source bash/functions/shell/git_log_visual.sh
# Últimos 20 commits (default)
git_log_visual
# Últimos 50 commits de todas las ramas
git_log_visual --count 50 --all
# Commits de un autor esta semana
git_log_visual --author "lucas" --since "1 week ago"
# Commits de hoy en todas las ramas
git_log_visual --since "00:00:00" --all --count 100
```
## Notas
Usa `less -R --quit-if-one-screen` para paginar: si el log cabe en pantalla, no abre el paginador. El formato incluye hash corto (amarillo), fecha (cyan), autor (verde), mensaje y refs de ramas (rojo).
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# git_log_visual
# --------------
# Muestra el historial de commits con grafo visual, colores y formato legible.
# Soporta filtros por cantidad, autor, fecha y todas las ramas.
#
# USO:
# source git_log_visual.sh
# git_log_visual [--count N] [--author X] [--since D] [--all]
#
# ARGUMENTOS:
# --count N Número de commits a mostrar (default: 20)
# --author X Filtrar por nombre o email del autor
# --since D Mostrar commits desde fecha (ej: "1 week ago", "2025-01-01")
# --all Incluir todas las ramas
git_log_visual() {
local count=20
local author=""
local since=""
local all_branches=false
# Parsear argumentos
while [[ $# -gt 0 ]]; do
case "$1" in
--count|-n)
count="$2"
shift 2
;;
--author|-a)
author="$2"
shift 2
;;
--since|-s)
since="$2"
shift 2
;;
--all)
all_branches=true
shift
;;
*)
shift
;;
esac
done
# Validar repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "git_log_visual: el directorio actual no es un repositorio Git" >&2
return 1
fi
local log_format="%C(yellow)%h%C(reset) %C(cyan)%ad%C(reset) %C(green)%an%C(reset) %s%C(red)%d%C(reset)"
# Construir argumentos del comando
local args=()
args+=("--graph")
args+=("--color=always")
args+=("--date=short")
args+=("--format=${log_format}")
args+=("-n" "${count}")
[[ -n "$author" ]] && args+=("--author=${author}")
[[ -n "$since" ]] && args+=("--since=${since}")
[[ "$all_branches" == true ]] && args+=("--all")
# Ejecutar
git log "${args[@]}" 2>/dev/null | less -R --quit-if-one-screen
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
git_log_visual "$@"
fi
@@ -0,0 +1,44 @@
---
name: git_push_all_remotes
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "git_push_all_remotes([--message msg: string]) -> void"
description: "Hace commit de todos los cambios pendientes (git add -A + git commit) y pushea la rama actual a todos los remotes configurados. Si no hay cambios solo pushea. Requiere --message si hay cambios sin commitear."
tags: [bash, git, push, remote, all]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: --message
desc: "mensaje de commit a usar si hay cambios pendientes (requerido cuando hay cambios)"
output: "progreso del push a stdout por cada remote; exit code 1 si algún push falla"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/git_push_all_remotes.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/git_utils/push_todos_remotes.sh"
---
## Ejemplo
```bash
source bash/functions/shell/git_push_all_remotes.sh
# Solo push (sin cambios pendientes)
git_push_all_remotes
# Commit + push a todos los remotes
git_push_all_remotes --message "feat: nueva funcionalidad"
```
## Notas
Usa `--set-upstream` automáticamente si la rama no existe en el remote. Sale con exit code 1 si hay cambios pero no se pasa `--message`, o si algún push falla.
@@ -0,0 +1,127 @@
#!/usr/bin/env bash
# git_push_all_remotes
# --------------------
# Hace commit de todos los cambios pendientes (si los hay) y pushea
# a todos los remotes configurados en el repositorio.
#
# USO:
# source git_push_all_remotes.sh
# git_push_all_remotes [--message "mensaje"]
#
# ARGUMENTOS:
# --message "msg" Mensaje de commit (si hay cambios). Si se omite y hay
# cambios, sale con error.
git_push_all_remotes() {
local commit_msg=""
# Parsear argumentos
while [[ $# -gt 0 ]]; do
case "$1" in
--message|-m)
commit_msg="$2"
shift 2
;;
*)
shift
;;
esac
done
# Validar repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "git_push_all_remotes: el directorio actual no es un repositorio Git" >&2
return 1
fi
local branch
branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
local remotes
remotes="$(git remote 2>/dev/null || true)"
if [[ -z "$remotes" ]]; then
echo "git_push_all_remotes: no hay remotes configurados en este repositorio" >&2
return 1
fi
echo "Rama actual: ${branch}"
echo "Remotes:"
echo "$remotes" | while IFS= read -r r; do
local url
url="$(git remote get-url "$r" 2>/dev/null || echo "?")"
echo " ${r}${url}"
done
echo ""
# Gestión del commit si hay cambios
local has_changes=false
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
has_changes=true
fi
if [[ "$has_changes" == true ]]; then
if [[ -z "$commit_msg" ]]; then
echo "git_push_all_remotes: hay cambios pero no se proporcionó --message" >&2
echo " Usa: git_push_all_remotes --message \"tu mensaje\"" >&2
return 1
fi
echo "Cambios detectados:"
git status --short | while IFS= read -r line; do
echo " ${line}"
done
echo ""
echo "Añadiendo todos los cambios..."
git add -A
echo "Haciendo commit: \"${commit_msg}\""
git commit -m "$commit_msg"
echo ""
else
echo "Directorio de trabajo limpio. Se empujarán commits existentes."
echo ""
fi
# Push a cada remote
local ok_count=0
local fail_count=0
local failed_remotes=()
local remote_count
remote_count="$(echo "$remotes" | wc -l | tr -d ' ')"
while IFS= read -r remote; do
# Verificar si la rama existe en el remote
local push_flags=""
if ! git ls-remote --heads "$remote" "$branch" 2>/dev/null | grep -q "$branch"; then
push_flags="--set-upstream"
echo "La rama '${branch}' no existe en '${remote}', se creará"
fi
echo "Push → ${remote} (${branch})..."
# shellcheck disable=SC2086
if git push $push_flags "$remote" "$branch" 2>&1; then
echo " Push completado → ${remote}/${branch}"
ok_count=$((ok_count + 1))
else
echo " Falló el push a ${remote}/${branch}" >&2
fail_count=$((fail_count + 1))
failed_remotes+=("$remote")
fi
echo ""
done <<< "$remotes"
echo "=== Resumen ==="
echo "Push completado en ${ok_count}/${remote_count} remote(s)"
if [[ $fail_count -gt 0 ]]; then
echo "Fallaron ${fail_count} remote(s): ${failed_remotes[*]}" >&2
return 1
fi
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
git_push_all_remotes "$@"
fi
+41
View File
@@ -0,0 +1,41 @@
---
name: git_repo_status
kind: function
lang: bash
domain: shell
version: "1.0.0"
purity: impure
signature: "git_repo_status() -> void"
description: "Muestra el estado completo de un repositorio Git: rama actual, upstream (ahead/behind), cambios pendientes, stash, remotes y últimos 8 commits. Sale con exit code 1 si el directorio actual no es un repo Git."
tags: [bash, git, status, repo, branch]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: "(ninguno)"
desc: "opera sobre el directorio de trabajo actual (cwd)"
output: "imprime el estado completo del repo a stdout; exit code 1 si no es un repo Git"
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/shell/git_repo_status.sh"
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/egutierrez/DevLauncher.git"
source_license: "MIT"
source_file: "scripts/linux/git_utils/estado_repo.sh"
---
## Ejemplo
```bash
# Desde un directorio con repo git
cd /home/user/my-project
source bash/functions/shell/git_repo_status.sh
git_repo_status
```
## Notas
No requiere dependencias externas más allá de git. Los colores del log de commits usan `--color=always` de git directamente. No produce output en stdout en caso de error — los mensajes de error van a stderr.
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
# git_repo_status
# ---------------
# Muestra el estado completo de un repositorio Git: rama actual, upstream,
# cambios pendientes, stash, remotes y últimos commits.
# Sale con exit code 1 si el directorio actual no es un repositorio Git.
#
# USO:
# source git_repo_status.sh
# git_repo_status
#
# O como script directo:
# bash git_repo_status.sh
git_repo_status() {
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "git_repo_status: el directorio actual no es un repositorio Git" >&2
return 1
fi
local branch
branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
# Upstream
local upstream
upstream="$(git rev-parse --abbrev-ref "${branch}@{upstream}" 2>/dev/null || echo "")"
local upstream_info
if [[ -z "$upstream" ]]; then
upstream_info="sin upstream"
else
local ahead behind
ahead="$(git rev-list "${upstream}..HEAD" --count 2>/dev/null || echo 0)"
behind="$(git rev-list "HEAD..${upstream}" --count 2>/dev/null || echo 0)"
upstream_info="${ahead}${behind} (${upstream})"
fi
echo "=== Rama & Upstream ==="
echo " Rama actual: ${branch}"
echo " Upstream: ${upstream_info}"
echo ""
# Cambios
echo "=== Cambios ==="
local changes
changes="$(git status --short 2>/dev/null)"
if [[ -z "$changes" ]]; then
echo " Directorio de trabajo limpio"
else
echo " Cambios pendientes:"
echo "$changes" | while IFS= read -r line; do
echo " ${line}"
done
fi
echo ""
# Stash
echo "=== Stash ==="
local stash_count
stash_count="$(git stash list 2>/dev/null | wc -l | tr -d ' ')"
if [[ "$stash_count" -eq 0 ]]; then
echo " Sin entradas en stash"
else
echo " ${stash_count} entrada(s) en stash:"
git stash list | head -5 | while IFS= read -r line; do
echo " ${line}"
done
fi
echo ""
# Remotes
echo "=== Remotes ==="
local remotes
remotes="$(git remote -v 2>/dev/null | grep '(fetch)' || true)"
if [[ -z "$remotes" ]]; then
echo " Sin remotes configurados"
else
echo "$remotes" | while IFS= read -r line; do
local name url
name="$(echo "$line" | awk '{print $1}')"
url="$(echo "$line" | awk '{print $2}')"
echo " ${name}${url}"
done
fi
echo ""
# Últimos commits
echo "=== Últimos commits ==="
git log --oneline --decorate --color=always -8 2>/dev/null || true
echo ""
}
# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
git_repo_status "$@"
fi