mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-02-06 05:49:23 +00:00
Compare commits
5 Commits
26.2.5
...
renovate/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec17b125da | ||
| 13dd701eb7 | |||
| cfde007494 | |||
| ed4aa2ffe1 | |||
| bcf11406b6 |
@@ -1 +1 @@
|
||||
3.14.2
|
||||
3.14.3
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
export DOTFILES="$HOME/.dotfiles"
|
||||
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
|
||||
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
|
||||
export SHARED_SCRIPTS_SOURCED=0
|
||||
|
||||
@@ -11,7 +12,7 @@ source "$DOTFILES/config/shared.sh"
|
||||
[ -f "${DOTFILES}/config/fzf/fzf.bash" ] &&
|
||||
source "${DOTFILES}/config/fzf/fzf.bash"
|
||||
|
||||
# Import ssh keys in keychain
|
||||
# Import ssh keys in keychain (macOS-specific -A flag, silently fails on Linux)
|
||||
ssh-add -A 2>/dev/null
|
||||
|
||||
x-have antidot && {
|
||||
@@ -22,5 +23,3 @@ PROMPT_DIRTRIM=3
|
||||
PROMPT_COMMAND='PS1_CMD1=$(git branch --show-current 2>/dev/null)'
|
||||
PS1='\[\e[95m\]\u\[\e[0m\]@\[\e[38;5;22;2m\]\h\[\e[0m\] \[\e[38;5;33m\]\w\[\e[0m\] \[\e[92;2m\]${PS1_CMD1}\n\[\e[39m\]➜\[\e[0m\] '
|
||||
|
||||
# Added by LM Studio CLI (lms)
|
||||
export PATH="$PATH:$HOME/.lmstudio/bin"
|
||||
|
||||
15
base/zshrc
15
base/zshrc
@@ -7,18 +7,13 @@
|
||||
autoload -U promptinit; promptinit
|
||||
|
||||
export DOTFILES="$HOME/.dotfiles"
|
||||
LOCAL_SHARE="$HOME/.local/share"
|
||||
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$LOCAL_SHARE/nvim/mason/bin:$LOCAL_SHARE/bob/nvim-bin:$LOCAL_SHARE/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
||||
# Minimal PATH for x-have and utilities; full PATH set in shared.sh/exports
|
||||
export PATH="$HOME/.local/bin:$DOTFILES/local/bin:$PATH"
|
||||
export SHARED_SCRIPTS_SOURCED=0
|
||||
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
|
||||
# zsh completions directory
|
||||
[ -z "$ZSH_COMPLETIONS" ] && export ZSH_COMPLETIONS="$XDG_CONFIG_HOME/zsh/completion"
|
||||
|
||||
# Add zsh completions to FPATH, compinit will be called later
|
||||
FPATH="$ZSH_COMPLETIONS:$FPATH"
|
||||
|
||||
# zsh completions directory (ZSH_CUSTOM_COMPLETION_PATH set in shared.sh)
|
||||
ZSH_COMPDUMP="$XDG_CACHE_HOME/zsh/zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
|
||||
|
||||
source "$DOTFILES/config/zsh/antidote.zsh"
|
||||
@@ -37,12 +32,10 @@ source_fzf_config
|
||||
x-have antidot && eval "$(antidot init)"
|
||||
|
||||
autoload -Uz compinit bashcompinit
|
||||
compinit -d $ZSH_COMPDUMP
|
||||
compinit -d "$ZSH_COMPDUMP"
|
||||
bashcompinit
|
||||
|
||||
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
|
||||
export P10K_CONFIG="$DOTFILES/config/zsh/p10k.zsh"
|
||||
[[ ! -f "$P10K_CONFIG" ]] || source "$P10K_CONFIG"
|
||||
|
||||
# Added by LM Studio CLI (lms)
|
||||
export PATH="$PATH:$HOME/.lmstudio/bin"
|
||||
|
||||
@@ -7,8 +7,6 @@ x-have eza && {
|
||||
alias ls="eza -h -s=type --git --icons --group-directories-first"
|
||||
}
|
||||
|
||||
alias vim='vim -u "$XDG_CONFIG_HOME/vim/vimrc"'
|
||||
|
||||
# Easier navigation: .., ..., ....
|
||||
alias ..="cd .."
|
||||
alias ...="cd ../.."
|
||||
|
||||
@@ -282,7 +282,8 @@ export LESSHISTFILE="$XDG_STATE_HOME"/less/history
|
||||
export MANPAGER="less -X"
|
||||
|
||||
# Always enable colored `grep` output
|
||||
export GREP_OPTIONS="--color=auto"
|
||||
# Note: GREP_OPTIONS is deprecated since GNU grep 2.21
|
||||
# Color is handled via alias in config/alias
|
||||
|
||||
# check the window size after each command and, if necessary,
|
||||
# update the values of LINES and COLUMNS.
|
||||
@@ -436,6 +437,10 @@ msg "Setting up Wakatime configuration"
|
||||
export WAKATIME_HOME="$XDG_STATE_HOME/wakatime"
|
||||
x-dc "$WAKATIME_HOME"
|
||||
|
||||
# LM Studio CLI
|
||||
msg "Setting up LM Studio configuration"
|
||||
export PATH="$PATH:$HOME/.lmstudio/bin"
|
||||
|
||||
# Misc
|
||||
msg "Setting up miscellaneous configuration"
|
||||
export ZSHZ_DATA="$XDG_STATE_HOME/z"
|
||||
|
||||
274
local/bin/a
274
local/bin/a
@@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# A script for encrypting and decrypting files or directories with age and SSH keys
|
||||
|
||||
VERSION="1.0.0"
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="1.1.0"
|
||||
|
||||
# Default ENV values
|
||||
KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}"
|
||||
@@ -9,14 +11,49 @@ KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}"
|
||||
LOG_FILE="${AGE_LOGFILE:-$HOME/.cache/a.log}"
|
||||
|
||||
VERBOSE=false
|
||||
DELETE_ORIGINAL=false
|
||||
FORCE=false
|
||||
|
||||
# Parse flags for verbosity
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "-v" || "$arg" == "--verbose" ]]; then
|
||||
VERBOSE=true
|
||||
break
|
||||
# Check for required dependencies
|
||||
check_dependencies()
|
||||
{
|
||||
if ! command -v age &> /dev/null; then
|
||||
echo "Error: 'age' is not installed. Please install it first." >&2
|
||||
echo " brew install age # macOS" >&2
|
||||
echo " apt install age # Debian/Ubuntu" >&2
|
||||
echo " dnf install age # Fedora" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! command -v curl &> /dev/null; then
|
||||
echo "Error: 'curl' is not installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse flags
|
||||
parse_flags()
|
||||
{
|
||||
local args=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
-v | --verbose)
|
||||
VERBOSE=true
|
||||
;;
|
||||
--delete)
|
||||
DELETE_ORIGINAL=true
|
||||
;;
|
||||
-f | --force)
|
||||
FORCE=true
|
||||
;;
|
||||
*)
|
||||
args+=("$arg")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# Return remaining arguments
|
||||
printf '%s\n' "${args[@]}"
|
||||
}
|
||||
|
||||
# Ensure log directory and file exist with correct permissions
|
||||
prepare_log_file()
|
||||
@@ -38,8 +75,6 @@ prepare_log_file()
|
||||
chmod 0600 "$LOG_FILE"
|
||||
}
|
||||
|
||||
prepare_log_file
|
||||
|
||||
# Logging function
|
||||
log_message()
|
||||
{
|
||||
@@ -56,7 +91,7 @@ log_message()
|
||||
print_help()
|
||||
{
|
||||
cat << EOF
|
||||
Usage: a [command] [file_or_directory] [options]
|
||||
Usage: a [options] [command] [file_or_directory]
|
||||
|
||||
Commands:
|
||||
e, enc, encrypt Encrypt the specified file or directory
|
||||
@@ -65,12 +100,14 @@ Commands:
|
||||
version, --version Show version information
|
||||
|
||||
Options:
|
||||
-v, --verbose Print log messages to console in addition to writing to log file
|
||||
-v, --verbose Print log messages to console
|
||||
--delete Delete original files after successful encryption
|
||||
-f, --force Overwrite existing output files without prompting
|
||||
|
||||
Environment Variables:
|
||||
AGE_KEYSFILE Path to the SSH keys file (default: $HOME/.ssh/keys.txt)
|
||||
AGE_KEYSFILE Path to the SSH keys file (default: \$HOME/.ssh/keys.txt)
|
||||
AGE_KEYSSOURCE URL to fetch SSH keys if keys file does not exist
|
||||
AGE_LOGFILE Path to the log file (default: $HOME/.cache/a.log)
|
||||
AGE_LOGFILE Path to the log file (default: \$HOME/.cache/a.log)
|
||||
|
||||
Examples:
|
||||
Encrypt a file:
|
||||
@@ -79,14 +116,21 @@ Examples:
|
||||
Encrypt a directory:
|
||||
a e /path/to/directory
|
||||
|
||||
Encrypt and delete originals:
|
||||
a --delete e file.txt
|
||||
|
||||
Decrypt a file:
|
||||
a d file.txt.age
|
||||
|
||||
Force overwrite existing files:
|
||||
a -f e file.txt
|
||||
|
||||
Specify a custom keys file:
|
||||
AGE_KEYSFILE=/path/to/keys.txt a e file.txt
|
||||
|
||||
Specify a custom keys source and log file:
|
||||
AGE_KEYSSOURCE=https://example.com/keys.txt AGE_LOGFILE=/tmp/a.log a d file.txt.age
|
||||
Requirements:
|
||||
- age (encryption tool): https://github.com/FiloSottile/age
|
||||
- curl (for fetching keys)
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -115,26 +159,104 @@ fetch_keys_if_missing()
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to encrypt a single file
|
||||
encrypt_single_file()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
# Skip already encrypted files
|
||||
if [[ "$file" == *.age ]]; then
|
||||
log_message "Skipping already encrypted file: $file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local output_file="${file}.age"
|
||||
|
||||
# Check if output file exists
|
||||
if [[ -f "$output_file" && "$FORCE" != true ]]; then
|
||||
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
|
||||
return 1
|
||||
fi
|
||||
|
||||
fetch_keys_if_missing
|
||||
|
||||
local temp_file
|
||||
temp_file="$(mktemp -p "$(dirname "$file")")"
|
||||
|
||||
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
|
||||
log_message "File encrypted successfully: $output_file"
|
||||
|
||||
if [[ "$DELETE_ORIGINAL" == true ]]; then
|
||||
rm -f "$file"
|
||||
log_message "Original file deleted: $file"
|
||||
fi
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
log_message "Error: Failed to encrypt file '$file'."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to encrypt files or directories
|
||||
encrypt_file_or_directory()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
if [[ -d "$file" ]]; then
|
||||
for f in "$file"/*; do
|
||||
# Enable dotglob to include hidden files
|
||||
shopt -s dotglob nullglob
|
||||
local files=("$file"/*)
|
||||
shopt -u dotglob nullglob
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
log_message "Warning: Directory '$file' is empty."
|
||||
return 0
|
||||
fi
|
||||
|
||||
for f in "${files[@]}"; do
|
||||
encrypt_file_or_directory "$f"
|
||||
done
|
||||
elif [[ -f "$file" ]]; then
|
||||
fetch_keys_if_missing
|
||||
local output_file="${file}.age"
|
||||
local temp_file
|
||||
temp_file="$(mktemp -p "$(dirname "$file")")"
|
||||
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
|
||||
log_message "File encrypted successfully: $output_file"
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
log_message "Error: Failed to encrypt file '$file'."
|
||||
exit 1
|
||||
encrypt_single_file "$file"
|
||||
else
|
||||
log_message "Warning: '$file' is not a file or directory, skipping."
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to decrypt a single file
|
||||
decrypt_single_file()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
if [[ ! "$file" == *.age ]]; then
|
||||
log_message "Skipping non-.age file: $file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local output_file="${file%.age}"
|
||||
|
||||
# Check if output file exists
|
||||
if [[ -f "$output_file" && "$FORCE" != true ]]; then
|
||||
log_message "Error: Output file '$output_file' already exists. Use --force to overwrite."
|
||||
return 1
|
||||
fi
|
||||
|
||||
fetch_keys_if_missing
|
||||
|
||||
local temp_file
|
||||
temp_file="$(mktemp -p "$(dirname "$file")")"
|
||||
|
||||
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
|
||||
log_message "File decrypted successfully: $output_file"
|
||||
|
||||
if [[ "$DELETE_ORIGINAL" == true ]]; then
|
||||
rm -f "$file"
|
||||
log_message "Encrypted file deleted: $file"
|
||||
fi
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
log_message "Error: Failed to decrypt file '$file'."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -142,54 +264,76 @@ encrypt_file_or_directory()
|
||||
decrypt_file_or_directory()
|
||||
{
|
||||
local file="$1"
|
||||
|
||||
if [[ -d "$file" ]]; then
|
||||
for f in "$file"/*.age; do
|
||||
decrypt_file_or_directory "$f"
|
||||
# Enable nullglob to handle no matches gracefully
|
||||
shopt -s nullglob
|
||||
local files=("$file"/*.age)
|
||||
shopt -u nullglob
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
log_message "Warning: No .age files found in directory '$file'."
|
||||
return 0
|
||||
fi
|
||||
|
||||
for f in "${files[@]}"; do
|
||||
decrypt_single_file "$f"
|
||||
done
|
||||
elif [[ -f "$file" ]]; then
|
||||
fetch_keys_if_missing
|
||||
local output_file="${file%.age}"
|
||||
local temp_file
|
||||
temp_file="$(mktemp -p "$(dirname "$file")")"
|
||||
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
|
||||
log_message "File decrypted successfully: $output_file"
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
log_message "Error: Failed to decrypt file '$file'."
|
||||
exit 1
|
||||
fi
|
||||
decrypt_single_file "$file"
|
||||
else
|
||||
log_message "Warning: '$file' is not a file or directory, skipping."
|
||||
fi
|
||||
}
|
||||
|
||||
# Main logic
|
||||
case "$1" in
|
||||
e | enc | encrypt)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
log_message "Error: No file or directory specified for encryption."
|
||||
# Main entry point
|
||||
main()
|
||||
{
|
||||
check_dependencies
|
||||
|
||||
# Parse flags and get remaining arguments
|
||||
mapfile -t ARGS < <(parse_flags "$@")
|
||||
|
||||
prepare_log_file
|
||||
|
||||
local command="${ARGS[0]:-}"
|
||||
local target="${ARGS[1]:-}"
|
||||
|
||||
case "$command" in
|
||||
e | enc | encrypt)
|
||||
if [[ -z "$target" ]]; then
|
||||
log_message "Error: No file or directory specified for encryption."
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
encrypt_file_or_directory "$target"
|
||||
;;
|
||||
d | dec | decrypt)
|
||||
if [[ -z "$target" ]]; then
|
||||
log_message "Error: No file or directory specified for decryption."
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
decrypt_file_or_directory "$target"
|
||||
;;
|
||||
help | --help | -h)
|
||||
print_help
|
||||
;;
|
||||
version | --version)
|
||||
print_version
|
||||
;;
|
||||
"")
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
encrypt_file_or_directory "$2"
|
||||
;;
|
||||
d | dec | decrypt)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
log_message "Error: No file or directory specified for decryption."
|
||||
;;
|
||||
*)
|
||||
log_message "Error: Unknown command '$command'"
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
decrypt_file_or_directory "$2"
|
||||
;;
|
||||
help | --help)
|
||||
print_help
|
||||
;;
|
||||
version | --version)
|
||||
print_version
|
||||
;;
|
||||
*)
|
||||
log_message "Error: Unknown command '$1'"
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
# vim: ft=bash:syn=sh:ts=2:sw=2:et:ai:nowrap
|
||||
|
||||
@@ -2,28 +2,76 @@
|
||||
|
||||
Encrypt or decrypt files and directories using `age` and your GitHub SSH keys.
|
||||
|
||||
## Requirements
|
||||
|
||||
- [age](https://github.com/FiloSottile/age) - encryption tool
|
||||
- curl - for fetching SSH keys
|
||||
|
||||
Install age:
|
||||
|
||||
```bash
|
||||
brew install age # macOS
|
||||
apt install age # Debian/Ubuntu
|
||||
dnf install age # Fedora
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
a encrypt <file|dir>
|
||||
a decrypt <file.age|dir>
|
||||
a [options] <command> <file|directory>
|
||||
```
|
||||
|
||||
Commands:
|
||||
|
||||
- `e`, `enc`, `encrypt` - encrypt files
|
||||
- `d`, `dec`, `decrypt` - decrypt files
|
||||
- `help`, `--help`, `-h` - show help
|
||||
- `version`, `--version` - show version
|
||||
|
||||
Options:
|
||||
|
||||
- `-v`, `--verbose` – show log output
|
||||
- `-v`, `--verbose` - show log output
|
||||
- `--delete` - delete original files after successful operation
|
||||
- `-f`, `--force` - overwrite existing output files
|
||||
|
||||
Environment variables:
|
||||
|
||||
- `AGE_KEYSFILE` – location of the keys file
|
||||
- `AGE_KEYSSOURCE` – URL to fetch keys if missing
|
||||
- `AGE_LOGFILE` – log file path
|
||||
- `AGE_KEYSFILE` - location of the keys file (default: `~/.ssh/keys.txt`)
|
||||
- `AGE_KEYSSOURCE` - URL to fetch keys if missing (default: GitHub keys)
|
||||
- `AGE_LOGFILE` - log file path (default: `~/.cache/a.log`)
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Encrypt a file
|
||||
a encrypt secret.txt
|
||||
|
||||
# Encrypt with short command
|
||||
a e secret.txt
|
||||
|
||||
# Decrypt a file
|
||||
a decrypt secret.txt.age
|
||||
a d secret.txt.age
|
||||
|
||||
# Encrypt a directory (includes hidden files)
|
||||
a e /path/to/secrets/
|
||||
|
||||
# Encrypt and delete originals
|
||||
a --delete e secret.txt
|
||||
|
||||
# Force overwrite existing .age file
|
||||
a -f e secret.txt
|
||||
|
||||
# Verbose output
|
||||
a -v e secret.txt
|
||||
```
|
||||
|
||||
## Behavior
|
||||
|
||||
- Encrypting a directory processes all files recursively, including hidden files
|
||||
- Already encrypted files (`.age`) are skipped during encryption
|
||||
- Only `.age` files are processed during directory decryption
|
||||
- Original files are preserved by default (use `--delete` to remove them)
|
||||
- Output files are not overwritten by default (use `--force` to overwrite)
|
||||
|
||||
<!-- vim: set ft=markdown spell spelllang=en_us cc=80 : -->
|
||||
|
||||
75
scripts/install-apt-packages.sh
Executable file
75
scripts/install-apt-packages.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# @description Install essential apt packages for development.
|
||||
#
|
||||
# shellcheck source=shared.sh
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
|
||||
msgr run "Starting to install apt packages"
|
||||
|
||||
if ! command -v apt &> /dev/null; then
|
||||
msgr warn "apt not found (not a Debian-based system)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
packages=(
|
||||
# Build essentials
|
||||
build-essential # gcc, g++, make
|
||||
cmake # Cross-platform build system
|
||||
pkg-config # Helper for compiling against libraries
|
||||
autoconf # Automatic configure script builder
|
||||
automake # Makefile generator
|
||||
libtool # Generic library support script
|
||||
|
||||
# Libraries for compiling languages
|
||||
libssl-dev # SSL development headers
|
||||
libffi-dev # Foreign function interface
|
||||
zlib1g-dev # Compression library
|
||||
libreadline-dev # Command-line editing
|
||||
libbz2-dev # Bzip2 compression
|
||||
libsqlite3-dev # SQLite database
|
||||
libncurses-dev # Terminal UI library
|
||||
|
||||
# CLI utilities (not in cargo/go/npm)
|
||||
jq # JSON processor
|
||||
tmux # Terminal multiplexer
|
||||
tree # Directory listing
|
||||
unzip # Archive extraction
|
||||
shellcheck # Shell script linter
|
||||
socat # Multipurpose network relay
|
||||
gnupg # GPG encryption/signing
|
||||
software-properties-common # add-apt-repository command
|
||||
)
|
||||
|
||||
install_packages()
|
||||
{
|
||||
local to_install=()
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
pkg="${pkg%%#*}"
|
||||
pkg="${pkg// /}"
|
||||
[[ -z "$pkg" ]] && continue
|
||||
|
||||
if dpkg -s "$pkg" &> /dev/null; then
|
||||
msgr ok "$pkg already installed"
|
||||
else
|
||||
to_install+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#to_install[@]} -gt 0 ]]; then
|
||||
msgr run "Installing ${#to_install[@]} packages: ${to_install[*]}"
|
||||
sudo apt update
|
||||
sudo apt install -y "${to_install[@]}"
|
||||
else
|
||||
msgr ok "All packages already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
install_packages
|
||||
msgr yay "apt package installations complete"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
83
scripts/install-dnf-packages.sh
Executable file
83
scripts/install-dnf-packages.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# @description Install essential dnf packages for development.
|
||||
#
|
||||
# shellcheck source=shared.sh
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
|
||||
msgr run "Starting to install dnf packages"
|
||||
|
||||
if ! command -v dnf &> /dev/null; then
|
||||
msgr warn "dnf not found (not a Fedora/RHEL-based system)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
packages=(
|
||||
# Build essentials (individual packages, group handled separately)
|
||||
cmake # Cross-platform build system
|
||||
pkgconfig # Helper for compiling against libraries
|
||||
autoconf # Automatic configure script builder
|
||||
automake # Makefile generator
|
||||
libtool # Generic library support script
|
||||
|
||||
# Libraries for compiling languages
|
||||
openssl-devel # SSL development headers
|
||||
libffi-devel # Foreign function interface
|
||||
zlib-devel # Compression library
|
||||
readline-devel # Command-line editing
|
||||
bzip2-devel # Bzip2 compression
|
||||
sqlite-devel # SQLite database
|
||||
ncurses-devel # Terminal UI library
|
||||
|
||||
# CLI utilities (not in cargo/go/npm)
|
||||
jq # JSON processor
|
||||
tmux # Terminal multiplexer
|
||||
tree # Directory listing
|
||||
unzip # Archive extraction
|
||||
ShellCheck # Shell script linter
|
||||
socat # Multipurpose network relay
|
||||
gnupg2 # GPG encryption/signing
|
||||
)
|
||||
|
||||
install_dev_tools_group()
|
||||
{
|
||||
if dnf group list installed 2>/dev/null | grep -q "Development Tools"; then
|
||||
msgr ok "@development-tools group already installed"
|
||||
else
|
||||
msgr run "Installing @development-tools group"
|
||||
sudo dnf group install -y "Development Tools"
|
||||
fi
|
||||
}
|
||||
|
||||
install_packages()
|
||||
{
|
||||
local to_install=()
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
pkg="${pkg%%#*}"
|
||||
pkg="${pkg// /}"
|
||||
[[ -z "$pkg" ]] && continue
|
||||
|
||||
if rpm -q "$pkg" &> /dev/null; then
|
||||
msgr ok "$pkg already installed"
|
||||
else
|
||||
to_install+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#to_install[@]} -gt 0 ]]; then
|
||||
msgr run "Installing ${#to_install[@]} packages: ${to_install[*]}"
|
||||
sudo dnf install -y "${to_install[@]}"
|
||||
else
|
||||
msgr ok "All packages already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
install_dev_tools_group
|
||||
install_packages
|
||||
msgr yay "dnf package installations complete"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user