mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-02-08 00:50:44 +00:00
* fix(ci): replace broad permissions with specific scopes in workflows
Replace read-all/write-all with minimum required permission scopes
across all GitHub Actions workflows to follow the principle of least
privilege (SonarCloud rule githubactions:S8234).
* fix(shell): use [[ instead of [ for conditional tests
Replace single brackets with double brackets in bash conditional
expressions across 14 files (28 changes). All scripts use bash
shebangs so [[ is safe everywhere (SonarCloud rule shelldre:S7688).
* fix(shell): add explicit return statements to functions
Add return 0 as the last statement in ~46 shell functions across
17 files that previously relied on implicit return codes
(SonarCloud rule shelldre:S7682).
* fix(shell): assign positional parameters to local variables
Replace direct $1/$2/$3 usage with named local variables in _log(),
msg(), msg_err(), msg_done(), msg_run(), msg_ok(), and array_diff()
(SonarCloud rule shelldre:S7679).
* fix(python): replace dict() constructor with literal
Use {} instead of dict() for empty dictionary initialization
(SonarCloud rule python:S7498).
* fix(shell): fix husky shebang and tolerate npm outdated exit code
* docs(shell): add function docstring comments
* fix(shell): fix heredoc indentation in x-sonarcloud
* feat(python): add ruff linter and formatter configuration
* fix(ci): align megalinter config with biome, ruff, and shfmt settings
* fix(ci): disable black and yaml-prettier in megalinter config
* chore(ci): update ruff-pre-commit to v0.15.0 and fix hook name
* fix(scripts): check for .git dir before skipping clone in install-fonts
* fix(shell): address code review issues in scripts and shared.sh
- Guard wezterm show-keys failure in create-wezterm-keymaps.sh
- Stop masking git failures with return 0 in install-cheat-purebashbible.sh
- Add missing shared.sh source in install-xcode-cli-tools.sh
- Replace exit 1 with return 1 in sourced shared.sh
* fix(scripts): address code review and security findings
- Guard wezterm show-keys failure in create-wezterm-keymaps.sh
- Stop masking git failures with return 0 in install-cheat-purebashbible.sh
- Add missing shared.sh source in install-xcode-cli-tools.sh
- Replace exit 1 with return 1 in sourced shared.sh
- Remove shell=True subprocess calls in x-git-largest-files.py
* style(shell): apply shfmt formatting and add args to pre-commit hook
* fix(python): suppress bandit false positives in x-git-largest-files
* fix(python): add nosemgrep suppression for check_output call
* feat(format): add prettier for YAML formatting
Install prettier, add .prettierrc.json config (200-char width, 2-space
indent, LF endings), .prettierignore, yarn scripts (lint:prettier,
fix:prettier, format:yaml), and pre-commit hook scoped to YAML files.
* style(yaml): apply prettier formatting
* fix(scripts): address remaining code review findings
- Python: use list comprehension to filter empty strings instead of
slicing off the last element
- create-wezterm-keymaps: write to temp file and mv for atomic updates
- install-xcode-cli-tools: fix shellcheck source directive path
* fix(python): sort imports alphabetically in x-git-largest-files
* fix(lint): disable PYTHON_ISORT in MegaLinter, ruff handles it
* chore(git): add __pycache__ to gitignore
* fix(python): rename ambiguous variable l to line (E741)
* style: remove trailing whitespace and blank lines
* style(fzf): apply shfmt formatting
* style(shell): apply shfmt formatting
* docs(plans): add design documents
* style(docs): add language specifier to fenced code block
* feat(lint): add markdown-table-formatter to dev tooling
Add markdown-table-formatter as a dev dependency with yarn scripts
(lint:md-table, fix:md-table) and a local pre-commit hook to
automatically format markdown tables on commit.
141 lines
3.8 KiB
Python
141 lines
3.8 KiB
Python
"""
|
|
To be used with a companion fish function like this:
|
|
|
|
function refish
|
|
set -l _x (python /tmp/bass.py source ~/.nvm/nvim.sh ';' nvm use iojs); source $_x; and rm -f $_x
|
|
end
|
|
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
|
|
BASH = "bash"
|
|
|
|
FISH_READONLY = [
|
|
"PWD",
|
|
"SHLVL",
|
|
"history",
|
|
"pipestatus",
|
|
"status",
|
|
"version",
|
|
"FISH_VERSION",
|
|
"fish_pid",
|
|
"hostname",
|
|
"_",
|
|
"fish_private_mode",
|
|
]
|
|
|
|
IGNORED = ["PS1", "XPC_SERVICE_NAME"]
|
|
|
|
|
|
def ignored(name):
|
|
if name == "PWD": # this is read only, but has special handling
|
|
return False
|
|
# ignore other read only variables
|
|
if name in FISH_READONLY:
|
|
return True
|
|
if name in IGNORED or name.startswith("BASH_FUNC"):
|
|
return True
|
|
return name.startswith("%")
|
|
|
|
|
|
def escape(string):
|
|
# use json.dumps to reliably escape quotes and backslashes
|
|
return json.dumps(string).replace(r"$", r"\$")
|
|
|
|
|
|
def escape_identifier(word):
|
|
return escape(word.replace("?", "\\?"))
|
|
|
|
|
|
def comment(string):
|
|
return "\n".join(["# " + line for line in string.split("\n")])
|
|
|
|
|
|
def gen_script():
|
|
# Use the following instead of /usr/bin/env to read environment so we can
|
|
# deal with multi-line environment variables (and other odd cases).
|
|
env_reader = f"{sys.executable} -c 'import os,json; print(json.dumps({{k:v for k,v in os.environ.items()}}))'"
|
|
args = [BASH, "-c", env_reader]
|
|
output = subprocess.check_output(args, universal_newlines=True)
|
|
old_env = output.strip()
|
|
|
|
pipe_r, pipe_w = os.pipe()
|
|
os.set_inheritable(pipe_w, True)
|
|
command = f"eval $1 && ({env_reader}; alias) >&{pipe_w}"
|
|
args = [BASH, "-c", command, "bass", " ".join(sys.argv[1:])]
|
|
p = subprocess.Popen(args, universal_newlines=True, close_fds=False)
|
|
os.close(pipe_w)
|
|
with os.fdopen(pipe_r) as f:
|
|
new_env = f.readline()
|
|
alias_str = f.read()
|
|
if p.wait() != 0:
|
|
raise subprocess.CalledProcessError(
|
|
returncode=p.returncode, cmd=" ".join(sys.argv[1:]), output=new_env + alias_str
|
|
)
|
|
new_env = new_env.strip()
|
|
|
|
old_env = json.loads(old_env)
|
|
new_env = json.loads(new_env)
|
|
|
|
script_lines = []
|
|
|
|
for k, v in new_env.items():
|
|
if ignored(k):
|
|
continue
|
|
v1 = old_env.get(k)
|
|
if not v1:
|
|
script_lines.append(comment(f"adding {k}={v}"))
|
|
elif v1 != v:
|
|
script_lines.append(comment(f"updating {k}={v1} -> {v}"))
|
|
# process special variables
|
|
if k == "PWD":
|
|
script_lines.append(f"cd {escape(v)}")
|
|
continue
|
|
else:
|
|
continue
|
|
if k == "PATH": # noqa: SIM108
|
|
value = " ".join([escape(directory) for directory in v.split(":")])
|
|
else:
|
|
value = escape(v)
|
|
script_lines.append(f"set -g -x {k} {value}")
|
|
|
|
for var in set(old_env.keys()) - set(new_env.keys()):
|
|
script_lines.append(comment(f"removing {var}"))
|
|
script_lines.append(f"set -e {var}")
|
|
|
|
script = "\n".join(script_lines)
|
|
|
|
alias_lines = []
|
|
for line in alias_str.splitlines():
|
|
_, rest = line.split(None, 1)
|
|
k, v = rest.split("=", 1)
|
|
alias_lines.append("alias " + escape_identifier(k) + "=" + v)
|
|
alias = "\n".join(alias_lines)
|
|
|
|
return script + "\n" + alias
|
|
|
|
|
|
script_file = os.fdopen(3, "w")
|
|
|
|
if not sys.argv[1:]:
|
|
print("__bass_usage", file=script_file, end="")
|
|
sys.exit(0)
|
|
|
|
try:
|
|
script = gen_script()
|
|
except subprocess.CalledProcessError as e:
|
|
sys.exit(e.returncode)
|
|
except Exception:
|
|
print("Bass internal error!", file=sys.stderr)
|
|
raise # traceback will output to stderr
|
|
except KeyboardInterrupt:
|
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
os.kill(os.getpid(), signal.SIGINT)
|
|
else:
|
|
script_file.write(script)
|