Compare commits
22 Commits
9477638a28
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee72ede116 | ||
|
|
f5244ac062 | ||
|
|
9a089112c3 | ||
|
|
e64a857a43 | ||
|
|
ddd7d4193a | ||
|
|
83a1c8ce48 | ||
|
|
b29fa3b30c | ||
|
|
cd0bcfd214 | ||
|
|
a91c41871a | ||
|
|
9698f0e506 | ||
|
|
9e22f007b9 | ||
|
|
d472fb61aa | ||
|
|
9108ee8266 | ||
|
|
a7f7452b2b | ||
|
|
bc67399ebc | ||
|
|
02b037d0fc | ||
|
|
e567957ea0 | ||
|
|
67bdd3e863 | ||
|
|
fa573bce8f | ||
|
|
241d53ebc4 | ||
|
|
1225230a07 | ||
|
|
9c43190202 |
52
README.md
52
README.md
@@ -10,12 +10,28 @@ current shell is not bash.
|
||||
|
||||
## 2. Getting started
|
||||
Download and extract (or use git clone) the profile archive into your home
|
||||
directory. You will have to modify your `~/.bashrc` and/or `~/.profile` file to
|
||||
add at the end (preferably):
|
||||
directory.
|
||||
|
||||
The profile is designed to be **sourced**, not executed directly.
|
||||
|
||||
Manual setup:
|
||||
```bash
|
||||
source <installpath>/profile/profile.sh
|
||||
```
|
||||
|
||||
Automatic setup (recommended):
|
||||
```bash
|
||||
bash <installpath>/profile/profile.sh --install
|
||||
```
|
||||
|
||||
`--install` appends the required `source` line to both `~/.bashrc` and
|
||||
`~/.profile` by default. You can target one file only:
|
||||
|
||||
```bash
|
||||
bash <installpath>/profile/profile.sh --install --bashrc
|
||||
bash <installpath>/profile/profile.sh --install --profile
|
||||
```
|
||||
|
||||
You may also set the `PROFILE_PATH` environment variable before sourcing if you
|
||||
want to override the automatic path detection:
|
||||
```bash
|
||||
@@ -49,18 +65,26 @@ A bar-style prompt showing current time, execution time of the last command
|
||||
| Function | Module | Description |
|
||||
|---|---|---|
|
||||
| `busy` | fun | Monitor /dev/urandom for a hex pattern — look busy |
|
||||
| `check_updates` | updates | Check whether a newer profile version is available online |
|
||||
| `check_updates` | updates | Check whether a newer profile version is available online; when called with `-q` at startup a 3-second network timeout is applied so a slow or absent network never delays the prompt |
|
||||
| `clean` | filefct | Erase backup files in given directories, optionally recursive |
|
||||
| `disp` | disp | Display formatted info / warning / error / debug messages |
|
||||
| `dwl` | net | Download a URL using curl, wget, or fetch transparently |
|
||||
| `disp` | disp | Display formatted info / warning / error / debug messages; long messages are word-wrapped and continuation lines are indented to align with the message text |
|
||||
| `dwl` | net | Download a URL using curl, wget, or fetch transparently; supports `-t <seconds>` / `--timeout <seconds>` to cap the transfer time |
|
||||
| `expandlist` | filefct | Expand glob expressions into a quoted, separated list |
|
||||
| `file_stats` | filefct | Display file size statistics for a path |
|
||||
| `findbig` | filefct | Find the biggest files in the given or current directory |
|
||||
| `finddead` | filefct | Find dead symbolic links in the given or current directory |
|
||||
| `findzero` | filefct | Find empty files in the given or current directory |
|
||||
| `gacp` | git | Add, commit and push changes; auto-pulls with rebase first if needed |
|
||||
| `genpwd` | pwd | Generate one or more random secure passwords with configurable constraints |
|
||||
| `ggraph` | git | Display a decorated git history graph |
|
||||
| `gpid` | processes | Give the list of PIDs matching the given process name(s) |
|
||||
| `help` | help | Display the list of available functions and basic usage |
|
||||
| `gprune` | git | Delete local branches already merged into the main branch |
|
||||
| `greset` | git | Reset the current branch to upstream, stashing local changes first |
|
||||
| `groot` | git | Display the repository root path, or change directory to it with `-g` |
|
||||
| `gsync` | git | Fetch and rebase the current branch onto its upstream |
|
||||
| `gst` | git | Display compact git status with branch tracking information |
|
||||
| `gwip` | git | Create a quick WIP checkpoint commit |
|
||||
| `help` | help | Display the list of available functions and basic usage; `help <command>` delegates to `<command> --help` |
|
||||
| `isipv4` | net | Tell if the given parameter is a valid IPv4 address |
|
||||
| `isipv6` | net | Tell if the given parameter is a valid IPv6 address |
|
||||
| `ku` | processes | Kill all processes owned by the given user name or ID |
|
||||
@@ -91,6 +115,13 @@ A bar-style prompt showing current time, execution time of the last command
|
||||
Locale shortcut functions (`setfr`, `setus`, etc.) are dynamically generated at
|
||||
startup from the `SET_LOCALE` configuration key (see section 4).
|
||||
|
||||
### 3.3. Bash completion
|
||||
|
||||
profile loads all `*.sh` files found under `profile.d/bash-completion/`
|
||||
automatically in interactive sessions. This directory is the right place to add
|
||||
any custom completion definitions. profile already ships completions for its git
|
||||
helper functions there (`git-completion.sh`).
|
||||
|
||||
## 4. Configuration
|
||||
profile uses an INI-style configuration file (`profile.conf`) located in the
|
||||
same directory as `profile.sh`. Sections are declared with `[section_name]` and
|
||||
@@ -171,6 +202,15 @@ change the default without having to pass flags every time.
|
||||
| `BUSY_DEFAULT_PATTERN` | `[0-9a-f]` | Hex pattern matched by `busy` |
|
||||
| `BUSY_DEFAULT_DELAY` | `0.1` | Polling delay (seconds) for `busy` |
|
||||
|
||||
**`[git]`**
|
||||
|
||||
| Key | Default | Description |
|
||||
|---|---|---|
|
||||
| `GIT_MAIN_BRANCH` | `main` | Fallback main branch name used when remote HEAD cannot be detected |
|
||||
| `GIT_DEFAULT_REMOTE` | `origin` | Default remote used by git helper functions |
|
||||
| `GIT_WIP_PREFIX` | `wip` | Prefix used by `gwip` when generating automatic checkpoint messages |
|
||||
| `GIT_GACP_AUTO_ADD` | `1` | Set to `1` to make `gacp` automatically add all modified files when no explicit file list is given; set to `0` to require explicit paths or the `-a` flag |
|
||||
|
||||
**`[info]`**
|
||||
|
||||
| Key | Default | Description |
|
||||
|
||||
204
doc/CHANGELOG.md
204
doc/CHANGELOG.md
@@ -7,6 +7,54 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
|
||||
---
|
||||
|
||||
## [4.1.0] — 2026-05-07
|
||||
|
||||
### Added
|
||||
- `profile.sh --install` command to automatically configure profile loading in
|
||||
shell startup files.
|
||||
- `--install --bashrc` and `--install --profile` target selectors for
|
||||
single-file installation.
|
||||
- **`git.sh`** — entirely new module providing git workflow helpers: `gst`,
|
||||
`ggraph`, `gsync`, `gacp`, `greset`, `gwip`, `gprune`, `groot`.
|
||||
- Dedicated git helper completions under `profile.d/bash-completion/`, loaded
|
||||
automatically in interactive sessions from `profile.d/bash-completion/*.sh`.
|
||||
|
||||
### Changed
|
||||
- `disp` now wraps long messages on terminal width, avoids mid-word splits, and
|
||||
aligns continuation lines with the message body after the prefix.
|
||||
- `help` now supports `help <command>` and delegates to `<command> --help`.
|
||||
|
||||
### Fixed
|
||||
- Startup responsiveness improved: `check_updates -q` now uses a short network
|
||||
timeout so unavailable/slow networks no longer delay prompt readiness.
|
||||
- `dwl` gained timeout support (`-t` / `--timeout`) and is now used by quiet
|
||||
startup update checks to enforce fast failure.
|
||||
- `profile.sh` now detects direct execution and warns that it is designed to be
|
||||
sourced.
|
||||
|
||||
## [4.0.0] — 2026-04-23
|
||||
|
||||
### Added
|
||||
- New `profile.conf` reference template at `doc/profile.conf.example`.
|
||||
- Dynamic locale shortcuts generated from `SET_LOCALE` and startup default
|
||||
language selection through `DEFAULT_LANG`.
|
||||
- Prompt theming system with bundled themes (`default`, `dark`, `light`,
|
||||
`solarized`, `solarized-light`, `monokai`, `monochrome`, `abyss`, `plasma`,
|
||||
`adwaita`) and per-key prompt color overrides.
|
||||
- Module defaults exposed as configuration keys in `profile.conf`.
|
||||
|
||||
### Changed
|
||||
- `utaz` now supports a wider range of archive formats.
|
||||
- Prompt and theme rendering improved, including better 24-bit color support.
|
||||
- Overall code quality and maintainability improved across modules.
|
||||
|
||||
### Documentation
|
||||
- README updated with full function reference and configuration tables.
|
||||
- New and expanded docs in `doc/` (`CONTRIBUTING.md`, `FAQ.md`, `todo.md`).
|
||||
- Historical releases imported from `history.txt` into this changelog.
|
||||
|
||||
---
|
||||
|
||||
## [3.99.2-4_rc_2] — 2026-04-21
|
||||
|
||||
### Fixed
|
||||
@@ -78,12 +126,6 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
> **Note:** Versions prior to `3.95.x-4_beta` did not maintain a formal
|
||||
> changelog. The full history of earlier changes is available through the git
|
||||
> log (`git log --oneline`).
|
||||
|
||||
## [3.95.3-4_beta_3] — 2024
|
||||
|
||||
### Added
|
||||
@@ -95,3 +137,153 @@ Versions follow `MAJOR.MINOR.PATCH-REVISION_STAGE_N` (e.g. `3.99.1-4_rc_1`).
|
||||
- `genpwd` / `pwdscore` password tools.
|
||||
- `matrix` / `rain` screensavers.
|
||||
- `profile_upgrade` with git and archive download support.
|
||||
|
||||
---
|
||||
|
||||
> **Note:** The section below was imported from `history.txt` to preserve
|
||||
> pre-`3.95.x-4_beta` release notes.
|
||||
|
||||
## Legacy releases (imported from `history.txt`)
|
||||
|
||||
### [3.6.1] — 2026-03-05
|
||||
- Fix typo in `compress.sh`.
|
||||
|
||||
### [3.6.0] — 2026-03-05
|
||||
- Improved `utaz` with broader multi-format support.
|
||||
- Introduced `ppu` and `ppn`.
|
||||
- Improved update system.
|
||||
|
||||
### [3.5.0] — 2026-03-04
|
||||
- `rain` now has configurable speed and color.
|
||||
- `showinfo` adapted to `fastfetch` (in addition to `neofetch`).
|
||||
|
||||
### [3.3.1] — 2022-02-24
|
||||
- Fixed version detection.
|
||||
- Added `busy`.
|
||||
- Fixed use of library functions before loading.
|
||||
|
||||
### [3.3.0] — 2022-11-28
|
||||
- Initial version update support.
|
||||
- Changed versioning code.
|
||||
- Added installation path detection.
|
||||
|
||||
### [3.2.3] — 2022-11-28
|
||||
- Improved README.
|
||||
|
||||
### [3.2.2] — 2022-11-21
|
||||
- Fixed `taz` compression level parsing.
|
||||
- Fixed typo in `dpkgs`.
|
||||
|
||||
### [3.2.1] — 2022-11-20
|
||||
- Fixed several messages.
|
||||
- Made `dpkgs` RPM-aware (initial support).
|
||||
- Removed version history from main script and reverted declaration order.
|
||||
- Added required license information in all files.
|
||||
- Completed `LICENSE` file.
|
||||
|
||||
### [3.2.0] — 2022-11-18
|
||||
- Created `disp` command and integrated it across the codebase.
|
||||
|
||||
### [3.1.1] — 2022-11-10
|
||||
- `genpwd`: added feasibility check for requested password constraints.
|
||||
|
||||
### [3.1.0] — 2022-11-08
|
||||
- Added password generator.
|
||||
|
||||
### [3.0.1] — 2022-11-07
|
||||
- Added concatenation option to `rmspc`.
|
||||
- Added `ku`.
|
||||
- Improved error handling in `meteo`.
|
||||
|
||||
### [3.0.0] — 2022-08-27
|
||||
- Split code into several files/modules.
|
||||
- Added `rain` screensaver.
|
||||
|
||||
### [2.8.2] — 2022-07-29
|
||||
- Added warning for non-bash users.
|
||||
|
||||
### [2.8.1] — 2022-07-19
|
||||
- Cleanup, fixes and optimizations.
|
||||
|
||||
### [2.8.0] — 2022-06-24
|
||||
- Added `backtrace`, `error` and `settrace`.
|
||||
- Bugfixes in `showinfo`.
|
||||
|
||||
### [2.7.1] — 2022-06-22
|
||||
- Minor corrections.
|
||||
- Added `help` command.
|
||||
|
||||
### [2.7.0] — 2022-06-21
|
||||
- Added `isipv4` and `isipv6`, integrated into `rmhost`.
|
||||
- Removed broken Konsole save/restore support.
|
||||
|
||||
### [2.6.3] — 2021-10-18
|
||||
- Changed PS1 to status-bar style.
|
||||
- Minor improvements.
|
||||
|
||||
### [2.6.2] — 2021-02-26
|
||||
- Bugfix in `taz` for directories with trailing slash.
|
||||
|
||||
### [2.6.1] — 2020-12-25
|
||||
- Added checks in `rmhost`.
|
||||
- Improved `rmspc`.
|
||||
- Created `expandlist`.
|
||||
|
||||
### [2.6.0] — 2020-10-24
|
||||
- Added Konsole session save/restore.
|
||||
|
||||
### [2.5.3] — 2020-09-11
|
||||
- Added aliases, improved code consistency and fixed typos.
|
||||
- Improved `utaz`, removed `showdiskmap`, removed remaining French text.
|
||||
- Added license information for future publication.
|
||||
|
||||
### [2.5.2] — 2020-03-06
|
||||
- Sorted and improved aliases.
|
||||
|
||||
### [2.5.1] — 2020-03-05
|
||||
- Language consistency fixes.
|
||||
- Added `pigz` support in `taz`.
|
||||
|
||||
### [2.5.0] — 2020-03-03
|
||||
- Added `taz` and `rmspc`.
|
||||
- Renamed `auzip` to `utaz` and improved it.
|
||||
|
||||
### [2.4.0] — 2020-03-02
|
||||
- Added `auzip`.
|
||||
|
||||
### [2.3.2] — 2020-01-31
|
||||
- `figlet`: changed default font to `ansi_shadow`.
|
||||
|
||||
### [2.3.1] — 2020-01-16
|
||||
- Bugfix: non-interactive shells were blocked by some functions.
|
||||
|
||||
### [2.3.0] — 2020-01-08
|
||||
- Added `figlet` and `neofetch` as MOTD replacement.
|
||||
|
||||
### [2.2.0] — 2019-12-16
|
||||
- Added `showinfo`.
|
||||
- First implementation of `showdiskmap`.
|
||||
|
||||
### [2.1.2] — 2019-09-24
|
||||
- Bugfix in profile version display.
|
||||
|
||||
### [2.1.1] — 2019-09-23
|
||||
- Bugfix in `dpkgs`.
|
||||
|
||||
### [2.1.0] — 2018-09-16
|
||||
- Added `rmhost`, `setc`, `setfr`.
|
||||
- Improved locale management.
|
||||
|
||||
### [2.0.1] — 2017-02-04
|
||||
- `clean` improvements (`--shell`).
|
||||
|
||||
### [2.0.0] — 2015-10-24
|
||||
- Added advanced functions (`clean`, `ssr`, etc.).
|
||||
|
||||
### [1.0.0] — 2013-02-16
|
||||
- Initial version.
|
||||
|
||||
### [Initial fork]
|
||||
Forked default Bash profile from Beyond Linux From Scratch by
|
||||
* James Robertson <jameswrobertson@earthlink.net>
|
||||
* Dagmar d'Surreal <rivyqntzne@pbzpnfg.arg>
|
||||
|
||||
120
doc/FAQ.md
120
doc/FAQ.md
@@ -4,6 +4,33 @@
|
||||
|
||||
## Installation & loading
|
||||
|
||||
**Q: How do I install profile automatically into my shell startup files?**
|
||||
|
||||
Run the installer directly (no need to source first):
|
||||
```bash
|
||||
bash <installpath>/profile/profile.sh --install
|
||||
```
|
||||
This appends the required `source` line to both `~/.bashrc` and `~/.profile`.
|
||||
To target only one file:
|
||||
```bash
|
||||
bash <installpath>/profile/profile.sh --install --bashrc
|
||||
bash <installpath>/profile/profile.sh --install --profile
|
||||
```
|
||||
The operation is idempotent — running it again will not add a duplicate line.
|
||||
|
||||
---
|
||||
|
||||
**Q: I ran `profile.sh` directly and got a warning about sourcing.**
|
||||
|
||||
profile.sh is designed to be *sourced*, not executed:
|
||||
```bash
|
||||
source <installpath>/profile/profile.sh
|
||||
```
|
||||
The only exception is `--install`, which must be passed to a direct execution
|
||||
(`bash profile.sh --install`) to set up the sourcing line automatically.
|
||||
|
||||
---
|
||||
|
||||
**Q: profile refuses to load and prints "This profile requires Bash 4.3 or higher."**
|
||||
|
||||
Your system's default shell is an older Bash (common on macOS, which ships
|
||||
@@ -84,7 +111,8 @@ Add to `profile.conf`:
|
||||
PROMPT_THEME = dark
|
||||
```
|
||||
Built-in names: `default`, `dark`, `light`, `solarized`, `solarized-light`,
|
||||
`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`.
|
||||
`monokai`, `monochrome`, `abyss`, `plasma`, `adwaita`, but you can create your
|
||||
own theme.
|
||||
|
||||
---
|
||||
|
||||
@@ -119,6 +147,55 @@ theme file cannot execute code. Values must be a colour variable reference
|
||||
|
||||
---
|
||||
|
||||
## Git helpers
|
||||
|
||||
**Q: What git helper functions does profile provide?**
|
||||
|
||||
All git helpers are defined in `profile.d/git.sh` (new in 4.1.0):
|
||||
|
||||
| Command | Purpose |
|
||||
|---|---|
|
||||
| `gst` | Compact status with branch tracking info |
|
||||
| `ggraph` | Decorated history graph |
|
||||
| `gsync` | Fetch and rebase onto upstream |
|
||||
| `gacp` | Add, commit and push in one command |
|
||||
| `greset` | Reset to upstream, stashing local changes first |
|
||||
| `gwip` | Quick WIP checkpoint commit |
|
||||
| `gprune` | Delete merged local branches |
|
||||
| `groot` | Print or cd to repository root |
|
||||
|
||||
All commands accept `-h` / `--help`.
|
||||
|
||||
---
|
||||
|
||||
**Q: Tab completion for `gacp` does not show modified files.**
|
||||
|
||||
Profile ships dedicated completions in `profile.d/bash-completion/git-completion.sh`,
|
||||
loaded automatically in interactive sessions. If completions are missing,
|
||||
check that the system git completion is installed:
|
||||
```bash
|
||||
# Debian / Ubuntu
|
||||
apt-get install bash-completion
|
||||
# Fedora / RHEL
|
||||
dnf install bash-completion
|
||||
```
|
||||
When the native git completion helpers are available, `gacp` path completion
|
||||
behaves exactly like `git add` (modified files, untracked files, directories).
|
||||
|
||||
---
|
||||
|
||||
**Q: `gacp` says "No files specified" even though I passed `-a`.**
|
||||
|
||||
The `-a` / `--auto` flag adds all modified files (equivalent to `git add -A`).
|
||||
The default depends on `GIT_GACP_AUTO_ADD` in `profile.conf`:
|
||||
```ini
|
||||
[git]
|
||||
GIT_GACP_AUTO_ADD = 1
|
||||
```
|
||||
Set to `1` to make `-a` the default.
|
||||
|
||||
---
|
||||
|
||||
## Functions
|
||||
|
||||
**Q: `meteo` prints "No city specified" even though I set a default.**
|
||||
@@ -147,11 +224,46 @@ Or set `DWL_PREFERRED_TOOL` in `[net]` to whichever tool you have.
|
||||
|
||||
---
|
||||
|
||||
**Q: How do I limit how long `dwl` waits for a download?**
|
||||
|
||||
Use the `-t` / `--timeout` option:
|
||||
```bash
|
||||
dwl -t 5 https://example.com/file.txt /tmp/file.txt
|
||||
```
|
||||
This sets a 5-second cap on both the connection and the overall transfer.
|
||||
The timeout is propagated to `curl` (`--max-time` + `--connect-timeout`),
|
||||
`wget` (`--timeout`), or `fetch` (`-T`) transparently.
|
||||
|
||||
---
|
||||
|
||||
**Q: The prompt takes a long time to appear when my network is unavailable.**
|
||||
|
||||
Fixed in 4.1.0. `check_updates -q` (called at startup) now enforces a
|
||||
3-second network timeout. If the update server is unreachable the check
|
||||
fails silently and the prompt appears immediately.
|
||||
|
||||
---
|
||||
|
||||
**Q: `help` only shows a list of functions. Can I get usage for a specific one?**
|
||||
|
||||
Yes — pass the command name as an argument:
|
||||
```bash
|
||||
help gacp
|
||||
help dwl
|
||||
help taz
|
||||
```
|
||||
This calls `<command> --help` and prints the full usage for that function.
|
||||
|
||||
---
|
||||
|
||||
**Q: `pkgs` does not find packages I know are installed.**
|
||||
|
||||
`pkgs` delegates to `dpkg -l` (Debian/Ubuntu) or `rpm -qa` (RHEL/Fedora).
|
||||
If your distribution uses a different package manager (pacman, apk, brew …)
|
||||
it is not yet supported. See `doc/todo.md` for the tracking issue.
|
||||
`pkgs` uses `get_pkgmgr` to detect the active package manager and delegates
|
||||
to the appropriate tool. Supported families: `apt` (Debian/Ubuntu),
|
||||
`dnf` / `yum` (RHEL/Fedora), `zypper` (openSUSE), `pacman` (Arch),
|
||||
`apk` (Alpine), `portage` (Gentoo), `xbps` (Void), `nix`, `brew` (macOS).
|
||||
If your distribution is not detected, run `get_pkgmgr` to see what is
|
||||
identified, and check that the package manager binary is in your `PATH`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -76,6 +76,21 @@ TERM=xterm-256color
|
||||
# busy: Delay between matched lines in milliseconds (0 = no delay).
|
||||
#BUSY_DEFAULT_DELAY=0
|
||||
|
||||
# ==============================================================================
|
||||
[git]
|
||||
# Fallback main branch name used when remote HEAD cannot be detected.
|
||||
#GIT_MAIN_BRANCH=main
|
||||
|
||||
# Default remote used by git helper functions.
|
||||
#GIT_DEFAULT_REMOTE=origin
|
||||
|
||||
# Prefix used by gwip when generating automatic checkpoint messages.
|
||||
#GIT_WIP_PREFIX=wip
|
||||
|
||||
# gacp: Automatically add all modified files (git add -A) when no explicit file
|
||||
# list is provided. Set to 0 to require explicit file paths or the -a flag.
|
||||
#GIT_GACP_AUTO_ADD=1
|
||||
|
||||
# ==============================================================================
|
||||
[info]
|
||||
# meteo: Default city when no argument is given. Leave unset to require an
|
||||
|
||||
@@ -12,7 +12,7 @@ version-bump.
|
||||
blockers are `local -A` (no associative arrays in ZSH without `typeset -A`)
|
||||
and `local -n` namerefs. A thin compatibility shim would open the project to
|
||||
ZSH users. **[hard]**
|
||||
- [ ] **Bash completion** — add a `profile.d/completion/` directory and write
|
||||
- [ ] **Bash completion** — add a more bash completion directory and write
|
||||
`_profile_upgrade`, `_taz`, `_utaz`, `_meteo`, etc. completions so that
|
||||
`<Tab>` works on all public functions. **[medium]**
|
||||
|
||||
|
||||
147
history.txt
147
history.txt
@@ -1,147 +0,0 @@
|
||||
------------------------------------------------------------------------------
|
||||
Initial version from Beyond Linux From Scratch by
|
||||
* James Robertson <jameswrobertson@earthlink.net>
|
||||
* Dagmar d'Surreal <rivyqntzne@pbzpnfg.arg>
|
||||
------------------------------------------------------------------------------
|
||||
Current version from Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
||||
------------------------------------------------------------------------------
|
||||
Version history:
|
||||
------------------------------------------------------------------------------
|
||||
# 05/03/2026 v3.6.1
|
||||
Fix a typo in compress.sh
|
||||
|
||||
# 05/03/2026 v3.6.0
|
||||
Improved utaz to make it multiformat with lot of it
|
||||
Introduced ppu and ppn
|
||||
Improved update system
|
||||
|
||||
# 04/03/2026 v3.5.0
|
||||
rain has now configurable speed and color
|
||||
showinfo adapted to fastfetch, replacing neofetch
|
||||
|
||||
# 24/02/2022 v3.3.1
|
||||
Fixed version detection
|
||||
Added "busy" function
|
||||
Fixed use of library functions before it's loaded
|
||||
|
||||
# 28/11/2022 v3.3.0
|
||||
Initial version update support
|
||||
Changed versioning code
|
||||
Added installation path detection
|
||||
|
||||
# 28/11/2022 v3.2.3
|
||||
Made proper readme file, to improve
|
||||
|
||||
# 21/11/2022 v3.2.2
|
||||
Fixed taz compression level analysis
|
||||
Fixed typo in dpkgs
|
||||
|
||||
# 20/11/2022 v3.2.1
|
||||
Fix some messages
|
||||
Make dpkgs rpm aware (more to come)
|
||||
Removed version history from main script and revert declaration order
|
||||
Added required license information in all files
|
||||
Completed LICENSE file
|
||||
|
||||
# 18/11/2022 v3.2.0
|
||||
Created disp command for display and make use of it
|
||||
|
||||
# 10/11/2022 v3.1.1
|
||||
genpwd: test if password is doable
|
||||
|
||||
# 08/11/2022 v3.1.0
|
||||
Added password generator
|
||||
|
||||
# 07/11/2022 v3.0.1
|
||||
Added concatenation to rmspc
|
||||
Added ku
|
||||
Error managed in meteo
|
||||
|
||||
# 27/08/2022 v3.0.0
|
||||
Splitted everything in several files
|
||||
Added rain screensaver
|
||||
|
||||
# 29/07/2022 v2.8.2
|
||||
Added warning for non bash or zsh users
|
||||
|
||||
# 19/07/2022 v2.8.1
|
||||
Few cleanups, fixes and optimizations
|
||||
|
||||
# 24/06/2022 v2.8.0
|
||||
Added backtrace, error and settrace
|
||||
[bugfix] corrected showinfo
|
||||
|
||||
# 22/06/2022 v2.7.1
|
||||
[bugfix] few minor corrections
|
||||
Added help command
|
||||
|
||||
# 21/06/2022 v2.7.0
|
||||
Added isipv4 and isipv6 and use it in rmhost as an improvement
|
||||
Removed konsole save and restore not working
|
||||
|
||||
# 18/10/2021 v2.6.3
|
||||
Changed PS1 for status bar style version
|
||||
Few minor improvements
|
||||
|
||||
# 26/02/2021 v2.6.2
|
||||
[bugfix] taz: corrected bug with trailing slash on directories
|
||||
|
||||
# 25/12/2020 v2.6.1
|
||||
Add check on rmhost
|
||||
Improvements rmspc
|
||||
Created expendlist
|
||||
|
||||
# 24/10/2020 v2.6.0
|
||||
Added session save and restore for Konsole
|
||||
|
||||
# 11/09/2020 v2.5.3
|
||||
Few more aliases, improved code consistancy and typo,
|
||||
Improved utaz, removed showdiskmap, removed remaining French,
|
||||
Added license information for future publication
|
||||
|
||||
# 06/03/2020 v2.5.2
|
||||
Few aliases sorted out
|
||||
|
||||
# 05/03/2020 v2.5.1
|
||||
Language consistancy fix
|
||||
Added pigz support in taz
|
||||
|
||||
# 03/03/2020 v2.5.0
|
||||
Added command taz and rmspc
|
||||
Renamed auzip => utaz and improved it
|
||||
|
||||
# 02/03/2020 v2.4.0
|
||||
Added command auzip
|
||||
|
||||
# 31/01/2020 v2.3.2
|
||||
Figlet: changed default font to ansi_shadow
|
||||
|
||||
# 16/01/2020 v2.3.1
|
||||
[bugfix] non-interactive were blocked with some functions
|
||||
|
||||
# 08/01/2020 v2.3.0
|
||||
Added use of figlet and neofetch as a motd replace
|
||||
|
||||
# 16/12/2019 v2.2.0
|
||||
Added showinfo
|
||||
Primary write of showdiskmap
|
||||
|
||||
# 24/09/2019 v2.1.2
|
||||
[bugfix] bug in profile version display
|
||||
|
||||
# 23/09/2019 v2.1.1
|
||||
[bugfix] dpkgs
|
||||
|
||||
# 16/09/2018 v2.1.0
|
||||
Added rmhost, setc, setfr
|
||||
More locales management
|
||||
|
||||
# 04/02/2017 v2.0.1
|
||||
clean improvements (--shell)
|
||||
|
||||
# 24/10/2015 v2.0.0
|
||||
Added advanced functionnalities (clean, srr, etc.)
|
||||
|
||||
# 16/02/2013 v1.0.0
|
||||
Initial version
|
||||
|
||||
220
profile.d/bash-completion/git-completion.sh
Normal file
220
profile.d/bash-completion/git-completion.sh
Normal file
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env bash
|
||||
# ------------------------------------------------------------------------------
|
||||
# Git helper completions for profile.d/git.sh shortcuts.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Return 0 when current directory is inside a git work tree.
|
||||
_profile_git_in_repo()
|
||||
{
|
||||
git rev-parse --is-inside-work-tree >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Load git completion helpers on demand if they are available on the system.
|
||||
_profile_git_load_completion_helpers()
|
||||
{
|
||||
declare -F __git_complete >/dev/null 2>&1 && return 0
|
||||
|
||||
local completion_file
|
||||
for completion_file in \
|
||||
/usr/share/bash-completion/completions/git \
|
||||
/usr/share/git/completion/git-completion.bash \
|
||||
/etc/bash_completion.d/git
|
||||
do
|
||||
if [[ -r "$completion_file" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
. "$completion_file"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
declare -F __git_complete >/dev/null 2>&1
|
||||
}
|
||||
|
||||
_profile_git_complete_remotes()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if ! _profile_git_in_repo; then
|
||||
COMPREPLY=()
|
||||
return 0
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W "$(git remote 2>/dev/null)" -- "$cur") )
|
||||
}
|
||||
|
||||
_profile_git_complete_refs()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if ! _profile_git_in_repo; then
|
||||
COMPREPLY=()
|
||||
return 0
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W "$(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes refs/tags 2>/dev/null)" -- "$cur") )
|
||||
}
|
||||
|
||||
_profile_git_complete_add_paths()
|
||||
{
|
||||
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
|
||||
local cur words cword prev __git_cmd_idx=0
|
||||
local complete_opt="--others --modified --directory --no-empty-directory"
|
||||
|
||||
if declare -F __git_complete_index_file >/dev/null 2>&1; then
|
||||
if declare -F _get_comp_words_by_ref >/dev/null 2>&1; then
|
||||
_get_comp_words_by_ref -n =: cur words cword prev
|
||||
else
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
if (( COMP_CWORD > 0 )); then
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
else
|
||||
prev=""
|
||||
fi
|
||||
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
|
||||
cword="$COMP_CWORD"
|
||||
# shellcheck disable=SC2034 # Used indirectly by git-completion helpers via dynamic scope.
|
||||
words=("${COMP_WORDS[@]}")
|
||||
fi
|
||||
|
||||
if [[ -n $(__git_find_on_cmdline "-u --update") ]]; then
|
||||
complete_opt="--modified"
|
||||
fi
|
||||
__git_complete_index_file "$complete_opt"
|
||||
return 0
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -f -- "${COMP_WORDS[COMP_CWORD]}") )
|
||||
}
|
||||
|
||||
_complete_gst()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $(compgen -d -- "$cur") )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_complete_ggraph()
|
||||
{
|
||||
local cur prev
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
case "$prev" in
|
||||
-n|--limit)
|
||||
COMPREPLY=()
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
COMPREPLY=( $(compgen -W "-h --help -n --limit" -- "$cur") )
|
||||
}
|
||||
|
||||
_complete_gsync()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
_profile_git_complete_remotes
|
||||
}
|
||||
|
||||
_complete_gacp()
|
||||
{
|
||||
local cur prev
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
case "$prev" in
|
||||
-m|--message)
|
||||
COMPREPLY=()
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "-h --help -a --auto -m --message" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
_profile_git_complete_add_paths
|
||||
}
|
||||
|
||||
_complete_greset()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "-h --help -x --with-ignored" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
_profile_git_complete_refs
|
||||
}
|
||||
|
||||
_complete_gwip()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
|
||||
else
|
||||
COMPREPLY=()
|
||||
fi
|
||||
}
|
||||
|
||||
_complete_gprune()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "-h --help" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
_profile_git_complete_refs
|
||||
}
|
||||
|
||||
_complete_groot()
|
||||
{
|
||||
local cur
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
COMPREPLY=( $(compgen -W "-h --help -g --go" -- "$cur") )
|
||||
}
|
||||
|
||||
_profile_git_register_completions()
|
||||
{
|
||||
complete -F _complete_gst gst
|
||||
complete -F _complete_ggraph ggraph
|
||||
complete -F _complete_gsync gsync
|
||||
complete -F _complete_gacp gacp
|
||||
complete -F _complete_greset greset
|
||||
complete -F _complete_gwip gwip
|
||||
complete -F _complete_gprune gprune
|
||||
complete -F _complete_groot groot
|
||||
}
|
||||
|
||||
# Register completions only in interactive bash sessions.
|
||||
if [[ $- == *i* && -n ${BASH_VERSION:-} ]]; then
|
||||
_profile_git_load_completion_helpers >/dev/null 2>&1 || true
|
||||
_profile_git_register_completions
|
||||
fi
|
||||
|
||||
# EOF
|
||||
@@ -422,7 +422,7 @@ taz()
|
||||
disp W "xz format is not suited for long term archiving."
|
||||
disp I "See https://www.nongnu.org/lzip/xz_inadequate.html for details."
|
||||
|
||||
# Compresse to xz (lzma2) - Deprecated
|
||||
# Compress with xz (lzma2) - Deprecated
|
||||
xz "${verb[@]}" --compress --keep "-$3" -T "$2" "$1"
|
||||
return $?
|
||||
}
|
||||
@@ -449,7 +449,7 @@ taz()
|
||||
[[ $4 ]] && opt=('-vv')
|
||||
opt+=("$procopt")
|
||||
|
||||
# Compresse au format lzip (lzma)
|
||||
# Compress with lzip (lzma)
|
||||
$command "${opt[@]}" --keep "-$3" "$1"
|
||||
return $?
|
||||
}
|
||||
@@ -476,7 +476,7 @@ taz()
|
||||
[[ $4 ]] && opt=('--verbose')
|
||||
opt+=("$procopt")
|
||||
|
||||
# Compresse au format bz2
|
||||
# Compress with gzip
|
||||
$command "${opt[@]}" --keep "-$3" "$1"
|
||||
return $?
|
||||
}
|
||||
@@ -503,7 +503,7 @@ taz()
|
||||
[[ $4 ]] && opt=('-v')
|
||||
opt+=("$procopt")
|
||||
|
||||
# Compresse au format bz2
|
||||
# Compress with bz2
|
||||
$command "${opt[@]}" --compress --keep "-$3" "$1"
|
||||
return $?
|
||||
}
|
||||
@@ -520,7 +520,7 @@ taz()
|
||||
[[ $4 ]] && verb=('-v')
|
||||
[[ $2 -gt 1 ]] && disp W "lzop doesn't support multithreading, falling back to 1 thread."
|
||||
|
||||
# Compresse au format lzo
|
||||
# Compress with lzo
|
||||
lzop "${verb[@]}" --keep "-$3" "$1"
|
||||
return $?
|
||||
}
|
||||
|
||||
@@ -128,52 +128,107 @@ export -f set_colors
|
||||
# D : debug (cyan)
|
||||
disp()
|
||||
{
|
||||
_disp_print_wrapped()
|
||||
{
|
||||
local prefix="$1"
|
||||
local prefix_len="$2"
|
||||
local target_fd="$3"
|
||||
shift 3
|
||||
local message="$*"
|
||||
|
||||
local cols="${COLUMNS:-}"
|
||||
if [[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]]; then
|
||||
cols=$(tput cols 2>/dev/null)
|
||||
fi
|
||||
[[ -z "$cols" || ! "$cols" =~ ^[0-9]+$ || "$cols" -lt 20 ]] && cols=80
|
||||
|
||||
local indent_len=0
|
||||
[[ "$prefix_len" =~ ^[0-9]+$ && "$prefix_len" -gt 0 ]] && indent_len=$((prefix_len + 1))
|
||||
|
||||
local width=$((cols - indent_len))
|
||||
(( width < 10 )) && width=10
|
||||
|
||||
local wrapped
|
||||
wrapped=$(printf "%s" "$message" | fold -s -w "$width")
|
||||
|
||||
local first_line=1
|
||||
local line
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
if (( first_line )); then
|
||||
if [[ -n "$prefix" ]]; then
|
||||
if [[ "$target_fd" -eq 2 ]]; then
|
||||
printf "%b\n" "${prefix} ${line}${RESETCOL}" >&2
|
||||
else
|
||||
printf "%b\n" "${prefix} ${line}${RESETCOL}"
|
||||
fi
|
||||
else
|
||||
if [[ "$target_fd" -eq 2 ]]; then
|
||||
printf "%b\n" "${line}${RESETCOL}" >&2
|
||||
else
|
||||
printf "%b\n" "${line}${RESETCOL}"
|
||||
fi
|
||||
fi
|
||||
first_line=0
|
||||
else
|
||||
if [[ "$target_fd" -eq 2 ]]; then
|
||||
printf "%*s%b\n" "$indent_len" "" "${line}${RESETCOL}" >&2
|
||||
else
|
||||
printf "%*s%b\n" "$indent_len" "" "${line}${RESETCOL}"
|
||||
fi
|
||||
fi
|
||||
done <<< "$wrapped"
|
||||
}
|
||||
|
||||
# Handle NO_COLOR: disable colors if set
|
||||
local color_enabled=1
|
||||
[[ -n $NO_COLOR ]] && color_enabled=0
|
||||
|
||||
case ${1^^} in
|
||||
"I")
|
||||
local heads_plain="[ info ]"
|
||||
if [[ $color_enabled -eq 1 ]]; then
|
||||
local heads="[ ${IGreen}info${DEFAULTFG} ]"
|
||||
else
|
||||
local heads="[ info ]"
|
||||
local heads="$heads_plain"
|
||||
fi
|
||||
shift
|
||||
[[ -z $QUIET || $QUIET -ne 1 ]] && \
|
||||
printf "%b\n" "${heads} $*${RESETCOL}"
|
||||
_disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*"
|
||||
;;
|
||||
"W")
|
||||
local heads_plain="[ Warning ]"
|
||||
if [[ $color_enabled -eq 1 ]]; then
|
||||
local heads="[ ${IYellow}Warning${DEFAULTFG} ]"
|
||||
else
|
||||
local heads="[ Warning ]"
|
||||
local heads="$heads_plain"
|
||||
fi
|
||||
shift
|
||||
printf "%b\n" "${heads} $*${RESETCOL}" >&2
|
||||
_disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*"
|
||||
;;
|
||||
"E")
|
||||
local heads_plain="[ ERROR ]"
|
||||
if [[ $color_enabled -eq 1 ]]; then
|
||||
local heads="[ ${IRed}ERROR${DEFAULTFG} ]"
|
||||
else
|
||||
local heads="[ ERROR ]"
|
||||
local heads="$heads_plain"
|
||||
fi
|
||||
shift
|
||||
printf "%b\n" "${heads} $*${RESETCOL}" >&2
|
||||
_disp_print_wrapped "$heads" "${#heads_plain}" 2 "$*"
|
||||
;;
|
||||
"D")
|
||||
local heads_plain="[ debug ]"
|
||||
if [[ $color_enabled -eq 1 ]]; then
|
||||
local heads="[ ${ICyan}debug${DEFAULTFG} ]"
|
||||
else
|
||||
local heads="[ debug ]"
|
||||
local heads="$heads_plain"
|
||||
fi
|
||||
shift
|
||||
[[ -n $DEBUG && $DEBUG -gt 1 ]] && \
|
||||
printf "%b\n" "${heads} $*${RESETCOL}"
|
||||
_disp_print_wrapped "$heads" "${#heads_plain}" 1 "$*"
|
||||
;;
|
||||
* )
|
||||
[[ -z $QUIET || $QUIET -ne 1 ]] && \
|
||||
printf "%b\n" "$*"
|
||||
_disp_print_wrapped "" 0 1 "$*"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
613
profile.d/git.sh
Executable file
613
profile.d/git.sh
Executable file
@@ -0,0 +1,613 @@
|
||||
#!/usr/bin/env bash
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
||||
# Protected by the BSD3 license. Please read bellow for details.
|
||||
#
|
||||
# * Redistribution and use in source and binary forms,
|
||||
# * with or without modification, are permitted provided
|
||||
# * that the following conditions are met:
|
||||
# *
|
||||
# * Redistributions of source code must retain the above
|
||||
# * copyright notice, this list of conditions and the
|
||||
# * following disclaimer.
|
||||
# *
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# * copyright notice, this list of conditions and the following
|
||||
# * disclaimer in the documentation and/or other materials
|
||||
# * provided with the distribution.
|
||||
# *
|
||||
# * Neither the name of the copyright holder nor the names
|
||||
# * of any other contributors may be used to endorse or
|
||||
# * promote products derived from this software without
|
||||
# * specific prior written permission.
|
||||
# *
|
||||
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# * OF SUCH DAMAGE.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Built-in defaults (can be overridden from [git] section in profile.conf)
|
||||
: "${GIT_MAIN_BRANCH:=main}"
|
||||
: "${GIT_DEFAULT_REMOTE:=origin}"
|
||||
: "${GIT_WIP_PREFIX:=wip}"
|
||||
: "${GIT_GACP_AUTO_ADD:=1}"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Internal helper: ensure git is available and cwd is a git worktree
|
||||
_git_require_repo()
|
||||
{
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
disp E "git command not found."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
disp E "Current directory is not inside a git repository."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Internal helper: return default branch from remote HEAD, fallback to config
|
||||
_git_default_branch()
|
||||
{
|
||||
local remote="${1:-$GIT_DEFAULT_REMOTE}"
|
||||
local head
|
||||
|
||||
head=$(git symbolic-ref --quiet --short "refs/remotes/${remote}/HEAD" 2>/dev/null) || true
|
||||
if [[ -n $head ]]; then
|
||||
printf "%s\n" "${head#${remote}/}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf "%s\n" "$GIT_MAIN_BRANCH"
|
||||
return 0
|
||||
}
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Display compact git status + branch tracking information
|
||||
# Usage: gst [path]
|
||||
gst()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o h --long help -n 'gst' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"gst --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "gst: Display short git status and branch tracking info.\n"
|
||||
printf "Usage: gst [path]\n"
|
||||
return 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"gst --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
local target="${1:-.}"
|
||||
git -C "$target" status --short --branch
|
||||
}
|
||||
export -f gst
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Show a readable commit graph
|
||||
# Usage: ggraph [-n limit]
|
||||
ggraph()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o hn: --long help,limit: -n 'ggraph' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"ggraph --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
local limit=30
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "ggraph: Display decorated git history graph.\n"
|
||||
printf "Usage: ggraph [-n limit]\n"
|
||||
printf "Options:\n"
|
||||
printf "\t-n, --limit\tNumber of commits to display (default: 30)\n"
|
||||
return 0
|
||||
;;
|
||||
-n|--limit)
|
||||
limit="$2"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"ggraph --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ $limit =~ ^[0-9]+$ ]] || {
|
||||
disp E "Invalid limit: must be a positive integer."
|
||||
return 1
|
||||
}
|
||||
|
||||
_git_require_repo || return 1
|
||||
git log --graph --decorate --oneline --all --max-count="$limit"
|
||||
}
|
||||
export -f ggraph
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sync current branch with remote (fetch + rebase)
|
||||
# Usage: gsync [remote]
|
||||
gsync()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o h --long help -n 'gsync' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"gsync --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "gsync: Fetch and rebase current branch onto its remote tracking branch.\n"
|
||||
printf "Usage: gsync [remote]\n"
|
||||
return 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"gsync --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
|
||||
local remote="${1:-$GIT_DEFAULT_REMOTE}"
|
||||
local branch upstream
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
||||
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
|
||||
|
||||
disp I "Fetching from $remote..."
|
||||
git fetch --prune "$remote" || return 1
|
||||
|
||||
if [[ -z $upstream ]]; then
|
||||
disp W "No upstream configured for $branch, skipping rebase."
|
||||
disp I "Set one with: git branch --set-upstream-to ${remote}/${branch} ${branch}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
disp I "Rebasing $branch onto $upstream..."
|
||||
git rebase "$upstream"
|
||||
}
|
||||
export -f gsync
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Add, commit, and push changes with automatic pull/rebase if needed
|
||||
# Usage: gacp -m "message" [file1 file2 ...]
|
||||
gacp()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o ham: --long help,auto,message: -n 'gacp' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"gacp --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
local msg="" auto_add="$GIT_GACP_AUTO_ADD"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "gacp: Run git add, git commit, and git push in one command.\n"
|
||||
printf "Usage: gacp [-a] -m \"message\" [file1 file2 ...]\n"
|
||||
printf "Options:\n"
|
||||
printf "\t-a, --auto\tAutomatically add all modified files (git add -A)\n"
|
||||
printf "\t-m, --message\tCommit message (mandatory)\n"
|
||||
printf "\n"
|
||||
printf "If files are provided, only those paths are added (-a is ignored).\n"
|
||||
printf "If no file is provided and -a is active, all changes are added with git add -A.\n"
|
||||
printf "Default for -a can be set via GIT_GACP_AUTO_ADD in profile.conf.\n"
|
||||
printf "If the remote branch moved forward, gacp pulls with rebase before pushing.\n"
|
||||
return 0
|
||||
;;
|
||||
-a|--auto)
|
||||
auto_add=1
|
||||
shift
|
||||
;;
|
||||
-m|--message)
|
||||
msg="$2"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"gacp --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
|
||||
if [[ -z $msg ]]; then
|
||||
disp E "Missing commit message. Use -m or --message."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local branch upstream remote tracking_branch behind counts
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
||||
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
auto_add=0
|
||||
disp I "Adding selected paths..."
|
||||
git add -- "$@" || return 1
|
||||
elif [[ $auto_add -eq 1 ]]; then
|
||||
disp I "Adding all changes..."
|
||||
git add -A || return 1
|
||||
else
|
||||
disp E "No files specified. Use -a/--auto or provide file paths."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
disp W "No staged changes to commit."
|
||||
return 1
|
||||
fi
|
||||
|
||||
disp I "Creating commit..."
|
||||
git commit -m "$msg" || return 1
|
||||
|
||||
if [[ -n $upstream ]]; then
|
||||
remote="${upstream%%/*}"
|
||||
tracking_branch="${upstream#*/}"
|
||||
else
|
||||
remote="$GIT_DEFAULT_REMOTE"
|
||||
tracking_branch="$branch"
|
||||
fi
|
||||
|
||||
disp I "Fetching from $remote..."
|
||||
git fetch --prune "$remote" || return 1
|
||||
|
||||
if git rev-parse --verify --quiet "refs/remotes/${remote}/${tracking_branch}" >/dev/null; then
|
||||
counts=$(git rev-list --left-right --count HEAD..."${remote}/${tracking_branch}" 2>/dev/null) || return 1
|
||||
read -r _ behind <<< "$counts"
|
||||
if [[ ${behind:-0} -gt 0 ]]; then
|
||||
disp I "Remote branch is ahead, rebasing before push..."
|
||||
git pull --rebase "$remote" "$tracking_branch" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $upstream ]]; then
|
||||
disp I "Pushing to $upstream..."
|
||||
git push || return 1
|
||||
else
|
||||
disp I "Pushing and setting upstream to ${remote}/${branch}..."
|
||||
git push -u "$remote" "$branch" || return 1
|
||||
fi
|
||||
|
||||
disp I "gacp complete."
|
||||
return 0
|
||||
}
|
||||
export -f gacp
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Reset local branch to exact upstream state (stash local changes first)
|
||||
# Usage: greset [target]
|
||||
greset()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o hx --long help,with-ignored -n 'greset' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"greset --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
local clean_ignored=0
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "greset: Reset current branch to upstream, stashing local changes first.\n"
|
||||
printf "Usage: greset [target]\n"
|
||||
printf "Options:\n"
|
||||
printf "\t-x, --with-ignored\tAlso remove ignored files (git clean -fdx)\n"
|
||||
printf "\n"
|
||||
printf "Default target is current branch upstream (@{u}).\n"
|
||||
printf "If no upstream exists, fallback target is <remote>/<branch>.\n"
|
||||
printf "This command stashes local modifications (tracked + untracked),\n"
|
||||
printf "drops local unpushed commits by hard-reset, and cleans untracked files.\n"
|
||||
return 0
|
||||
;;
|
||||
-x|--with-ignored)
|
||||
clean_ignored=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"greset --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
|
||||
local branch upstream target remote old_head stash_msg stash_out stash_created=0 dropped=0
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
||||
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null) || true
|
||||
target="$1"
|
||||
|
||||
if [[ -z $target ]]; then
|
||||
if [[ -n $upstream ]]; then
|
||||
target="$upstream"
|
||||
else
|
||||
remote="$GIT_DEFAULT_REMOTE"
|
||||
target="${remote}/${branch}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z $remote ]]; then
|
||||
remote="${target%%/*}"
|
||||
fi
|
||||
|
||||
old_head=$(git rev-parse HEAD 2>/dev/null) || return 1
|
||||
|
||||
if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then
|
||||
stash_msg="greset:${branch}:$(date +'%Y-%m-%d %H:%M:%S')"
|
||||
disp I "Stashing local changes as '$stash_msg'..."
|
||||
stash_out=$(git stash push -u -m "$stash_msg" 2>&1) || {
|
||||
disp E "Failed to stash local changes."
|
||||
printf "%s\n" "$stash_out"
|
||||
return 1
|
||||
}
|
||||
[[ $stash_out != "No local changes to save"* ]] && stash_created=1
|
||||
fi
|
||||
|
||||
disp I "Fetching from $remote..."
|
||||
git fetch --prune "$remote" || return 1
|
||||
|
||||
if ! git rev-parse --verify --quiet "$target" >/dev/null; then
|
||||
disp E "Target '$target' does not exist."
|
||||
return 1
|
||||
fi
|
||||
|
||||
dropped=$(git rev-list --count "${target}..${old_head}" 2>/dev/null || printf "0")
|
||||
|
||||
disp W "Hard-resetting $branch to $target..."
|
||||
git reset --hard "$target" || return 1
|
||||
|
||||
if (( clean_ignored )); then
|
||||
git clean -fdx || return 1
|
||||
else
|
||||
git clean -fd || return 1
|
||||
fi
|
||||
|
||||
if (( stash_created )); then
|
||||
disp I "Local changes were stashed. Use 'git stash list' and 'git stash pop' when needed."
|
||||
fi
|
||||
disp I "greset complete. Dropped local-only commits: $dropped"
|
||||
return 0
|
||||
}
|
||||
export -f greset
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Create a quick WIP commit for local checkpointing
|
||||
# Usage: gwip [message]
|
||||
gwip()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o h --long help -n 'gwip' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"gwip --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "gwip: Create a local checkpoint commit with all tracked/untracked changes.\n"
|
||||
printf "Usage: gwip [message]\n"
|
||||
return 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"gwip --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
|
||||
local msg
|
||||
if [[ $# -gt 0 ]]; then
|
||||
msg="$*"
|
||||
else
|
||||
msg="$GIT_WIP_PREFIX: $(date +'%Y-%m-%d %H:%M:%S')"
|
||||
fi
|
||||
|
||||
git add -A || return 1
|
||||
git commit -m "$msg"
|
||||
}
|
||||
export -f gwip
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Delete merged local branches (except protected branches)
|
||||
# Usage: gprune [main-branch]
|
||||
gprune()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o h --long help -n 'gprune' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"gprune --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "gprune: Delete local branches already merged into main branch.\n"
|
||||
printf "Usage: gprune [main-branch]\n"
|
||||
return 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"gprune --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
|
||||
local base="${1:-$(_git_default_branch "$GIT_DEFAULT_REMOTE")}" current deleted=0
|
||||
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
||||
|
||||
disp I "Pruning branches merged into $base..."
|
||||
|
||||
while IFS= read -r b; do
|
||||
[[ -z $b ]] && continue
|
||||
[[ $b == "$current" ]] && continue
|
||||
[[ $b == "$base" ]] && continue
|
||||
[[ $b == "master" || $b == "main" || $b == "develop" || $b == "dev" ]] && continue
|
||||
git branch -d "$b" >/dev/null 2>&1 && {
|
||||
printf "Deleted: %s\n" "$b"
|
||||
((deleted++))
|
||||
}
|
||||
done < <(git branch --merged "$base" | sed -E 's/^\*?\s*//')
|
||||
|
||||
(( deleted == 0 )) && disp I "No merged branches to delete."
|
||||
}
|
||||
export -f gprune
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Print repository root path
|
||||
# Usage: groot
|
||||
groot()
|
||||
{
|
||||
local PARSED
|
||||
PARSED=$(getopt -o hg --long help,go -n 'groot' -- "$@")
|
||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||
if [[ $? -ne 0 ]]; then
|
||||
disp E "Invalid options, use \"groot --help\" to display usage."
|
||||
return 1
|
||||
fi
|
||||
|
||||
eval set -- "$PARSED"
|
||||
local do_go=0
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
printf "groot: Display the absolute path of the current repository root.\n"
|
||||
printf "Usage: groot [-g|--go]\n"
|
||||
printf "Options:\n"
|
||||
printf "\t-g, --go\tChange current directory to repository root\n"
|
||||
return 0
|
||||
;;
|
||||
-g|--go)
|
||||
do_go=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
disp E "Invalid options, use \"groot --help\" to display usage."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
_git_require_repo || return 1
|
||||
local root
|
||||
root=$(git rev-parse --show-toplevel) || return 1
|
||||
|
||||
if (( do_go )); then
|
||||
cd "$root" || {
|
||||
disp E "Failed to move to repository root: $root"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf "%s\n" "$root"
|
||||
}
|
||||
export -f groot
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
load_conf git
|
||||
|
||||
# EOF
|
||||
@@ -36,9 +36,21 @@
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Display list of commands and general informations
|
||||
# Usage: help
|
||||
# Usage: help [command]
|
||||
help()
|
||||
{
|
||||
# If a command name is given, delegate to its --help output.
|
||||
if [[ $# -gt 0 && "$1" != "--help" && "$1" != "-h" ]]; then
|
||||
local cmd="$1"
|
||||
if declare -F "$cmd" >/dev/null 2>&1 || command -v "$cmd" >/dev/null 2>&1; then
|
||||
"$cmd" --help
|
||||
else
|
||||
disp E "Unknown command: $cmd"
|
||||
return 1
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154 # color code in disp.sh
|
||||
# shellcheck disable=SC2059 # printf format is a color variable
|
||||
printf "${BIWhite}Welcome to your profile! Here is a list of available commands:${DEFAULTCOL}\n\n"
|
||||
@@ -52,7 +64,15 @@ help()
|
||||
printf "findbig\t\tFind the biggest files in the given or current directory\n"
|
||||
printf "finddead\tFind dead symbolic links in the given or current directory\n"
|
||||
printf "findzero\tFind empty files in the given or current directory\n"
|
||||
printf "gacp\t\tAdd, commit and push changes (auto-pull if needed)\n"
|
||||
printf "genpwd\t\tGenerate one or more random secure passwords with configurable constraints\n"
|
||||
printf "ggraph\t\tDisplay decorated git history graph\n"
|
||||
printf "gprune\t\tDelete local branches already merged into main branch\n"
|
||||
printf "greset\t\tReset branch to upstream (stash local, drop local commits)\n"
|
||||
printf "groot\t\tDisplay repository root path (or cd to it with -g)\n"
|
||||
printf "gsync\t\tFetch and rebase current branch onto upstream\n"
|
||||
printf "gst\t\tDisplay short git status and branch tracking info\n"
|
||||
printf "gwip\t\tCreate a quick WIP checkpoint commit\n"
|
||||
printf "gpid\t\tGive the list of PIDs matching the given process name(s)\n"
|
||||
printf "isipv4\t\tTell if the given parameter is a valid IPv4 address\n"
|
||||
printf "isipv6\t\tTell if the given parameter is a valid IPv6 address\n"
|
||||
|
||||
@@ -36,27 +36,52 @@
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Download a resource using curl, wget, or fetch.
|
||||
# Usage: dwl <url> [output_file]
|
||||
# Usage: dwl [-t <seconds>] <url> [output_file]
|
||||
dwl()
|
||||
{
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
echo "Usage: dwl <url> [output_file]"
|
||||
echo "Downloads a resource using curl, wget, or fetch."
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " url The full URL to download (http/https/ftp)."
|
||||
echo " output_file (Optional) Path to save the file. If omitted, prints to stdout."
|
||||
return 0
|
||||
;;
|
||||
local timeout=""
|
||||
|
||||
# Parse leading options before the URL.
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
echo "Usage: dwl [-t <seconds>|--timeout <seconds>] <url> [output_file]"
|
||||
echo "Downloads a resource using curl, wget, or fetch."
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " -t, --timeout Maximum time in seconds to wait for the transfer."
|
||||
echo " url The full URL to download (http/https/ftp)."
|
||||
echo " output_file (Optional) Path to save the file. If omitted, prints to stdout."
|
||||
return 0
|
||||
;;
|
||||
-t|--timeout)
|
||||
[[ -z "${2:-}" || ! "${2:-}" =~ ^[0-9]+$ ]] && {
|
||||
echo "Error: --timeout requires a positive integer argument." >&2
|
||||
return 1
|
||||
}
|
||||
timeout="$2"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unknown option '$1'. Try 'dwl --help'." >&2
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "${1:-}" in
|
||||
"")
|
||||
echo "Error: URL argument is missing." >&2
|
||||
echo "Try 'get_resource --help' for usage." >&2
|
||||
echo "Try 'dwl --help' for usage." >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
http://*|https://*|ftp://*) ;;
|
||||
*)
|
||||
echo "Error: '$1' does not look like a valid URL. Must start with http://, https://, or ftp://" >&2
|
||||
@@ -65,35 +90,41 @@ dwl()
|
||||
esac
|
||||
|
||||
local url="$1"
|
||||
local output="$2"
|
||||
local output="${2:-}"
|
||||
|
||||
# Honour preferred tool from configuration; fall back to auto-detection.
|
||||
local preferred="${DWL_PREFERRED_TOOL:-}"
|
||||
|
||||
_try_curl()
|
||||
{
|
||||
local args=(-sL)
|
||||
[[ -n "$timeout" ]] && args+=(--max-time "$timeout" --connect-timeout "$timeout")
|
||||
if [[ -z "$output" ]]; then
|
||||
curl -sL "$url"
|
||||
curl "${args[@]}" "$url"
|
||||
else
|
||||
curl -sL -o "$output" "$url"
|
||||
curl "${args[@]}" -o "$output" "$url"
|
||||
fi
|
||||
}
|
||||
|
||||
_try_wget()
|
||||
{
|
||||
local args=(-q)
|
||||
[[ -n "$timeout" ]] && args+=(--timeout="$timeout")
|
||||
if [[ -z "$output" ]]; then
|
||||
wget -qO- "$url"
|
||||
wget "${args[@]}" -O- "$url"
|
||||
else
|
||||
wget -q -O "$output" "$url"
|
||||
wget "${args[@]}" -O "$output" "$url"
|
||||
fi
|
||||
}
|
||||
|
||||
_try_fetch()
|
||||
{
|
||||
local args=()
|
||||
[[ -n "$timeout" ]] && args+=(-T "$timeout")
|
||||
if [[ -z "$output" ]]; then
|
||||
fetch -o - "$url"
|
||||
fetch "${args[@]}" -o - "$url"
|
||||
else
|
||||
fetch -o "$output" "$url"
|
||||
fetch "${args[@]}" -o "$output" "$url"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
# checking available binaries in a fixed priority order.
|
||||
# Echoes one of: apt dnf yum zypper pacman apk portage xbps nix
|
||||
# Returns 1 if no known package manager could be identified.
|
||||
_get_pkgmgr()
|
||||
get_pkgmgr()
|
||||
{
|
||||
local distro_id="" distro_like=""
|
||||
if [[ -r /etc/os-release ]]; then
|
||||
@@ -56,30 +56,48 @@ _get_pkgmgr()
|
||||
for id in $distro_id $distro_like; do
|
||||
case "${id,,}" in
|
||||
debian|ubuntu|linuxmint|raspbian|pop|kali|elementary|zorin|neon|parrot)
|
||||
echo "apt"; return 0 ;;
|
||||
echo "apt"
|
||||
return 0
|
||||
;;
|
||||
fedora)
|
||||
echo "dnf"; return 0 ;;
|
||||
echo "dnf"
|
||||
return 0
|
||||
;;
|
||||
rhel|centos|rocky|almalinux|ol|scientific|amzn)
|
||||
command -v dnf >/dev/null 2>&1 && { echo "dnf"; return 0; }
|
||||
echo "yum"; return 0 ;;
|
||||
echo "yum"
|
||||
return 0
|
||||
;;
|
||||
opensuse*|sles|sled)
|
||||
echo "zypper"; return 0 ;;
|
||||
echo "zypper"
|
||||
return 0
|
||||
;;
|
||||
arch|manjaro|endeavouros|garuda|artix|cachyos)
|
||||
echo "pacman"; return 0 ;;
|
||||
echo "pacman"
|
||||
return 0
|
||||
;;
|
||||
alpine)
|
||||
echo "apk"; return 0 ;;
|
||||
echo "apk"
|
||||
return 0
|
||||
;;
|
||||
gentoo)
|
||||
echo "portage"; return 0 ;;
|
||||
echo "portage"
|
||||
return 0
|
||||
;;
|
||||
void)
|
||||
echo "xbps"; return 0 ;;
|
||||
echo "xbps"
|
||||
return 0
|
||||
;;
|
||||
nixos)
|
||||
echo "nix"; return 0 ;;
|
||||
echo "nix"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Fallback: check for binaries in priority order.
|
||||
local bin
|
||||
for bin in apt-get dnf yum zypper pacman apk emerge xbps-install nix-env; do
|
||||
for bin in apt apt-get dnf yum zypper pacman apk emerge xbps-install nix-env; do
|
||||
command -v "$bin" >/dev/null 2>&1 && {
|
||||
case "$bin" in
|
||||
apt-get) echo "apt" ;;
|
||||
@@ -94,7 +112,7 @@ _get_pkgmgr()
|
||||
|
||||
return 1
|
||||
}
|
||||
export -f _get_pkgmgr
|
||||
export -f get_pkgmgr
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -150,7 +168,7 @@ pkgs()
|
||||
(( ignore_case )) && grep_opt="-i"
|
||||
|
||||
local pkgmgr
|
||||
pkgmgr=$(_get_pkgmgr) || {
|
||||
pkgmgr=$(get_pkgmgr) || {
|
||||
disp E "No usable package manager could be detected on this system."
|
||||
return 2
|
||||
}
|
||||
|
||||
@@ -90,9 +90,14 @@ check_updates()
|
||||
return 4
|
||||
}
|
||||
|
||||
dwl "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || {
|
||||
# In quiet mode (startup), use a short timeout so a missing or slow network
|
||||
# never blocks the interactive prompt.
|
||||
local dwl_opts=()
|
||||
(( quiet == 1 )) && dwl_opts+=(-t 3)
|
||||
|
||||
dwl "${dwl_opts[@]}" "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || {
|
||||
rm -f "$vfile"
|
||||
disp E "Cannot download version file; unable to continue."
|
||||
(( quiet != 1 )) && disp E "Cannot download version file; unable to continue."
|
||||
return 5
|
||||
}
|
||||
|
||||
|
||||
135
profile.sh
135
profile.sh
@@ -35,10 +35,123 @@
|
||||
# * OF SUCH DAMAGE.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
_profile_is_sourced()
|
||||
{
|
||||
[[ "${BASH_SOURCE[0]}" != "$0" ]]
|
||||
}
|
||||
|
||||
_profile_finish()
|
||||
{
|
||||
local rc="${1:-0}"
|
||||
if _profile_is_sourced; then
|
||||
return "$rc"
|
||||
fi
|
||||
exit "$rc"
|
||||
}
|
||||
|
||||
_profile_install_in_file()
|
||||
{
|
||||
local rc_file="$1"
|
||||
local source_line="$2"
|
||||
|
||||
[[ -f "$rc_file" ]] || touch "$rc_file" || {
|
||||
printf "[ Error ] Cannot create %s\n" "$rc_file" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
if grep -Fqx "$source_line" "$rc_file"; then
|
||||
printf "[ Info ] Already configured in %s\n" "$rc_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf "\n%s\n" "$source_line" >> "$rc_file" || {
|
||||
printf "[ Error ] Cannot write to %s\n" "$rc_file" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
printf "[ Info ] Added profile source line to %s\n" "$rc_file"
|
||||
return 0
|
||||
}
|
||||
|
||||
_profile_install()
|
||||
{
|
||||
local install_bashrc=0
|
||||
local install_profile=0
|
||||
local target_selected=0
|
||||
local script_dir source_line rc=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--bashrc)
|
||||
install_bashrc=1
|
||||
target_selected=1
|
||||
;;
|
||||
--profile)
|
||||
install_profile=1
|
||||
target_selected=1
|
||||
;;
|
||||
-h|--help)
|
||||
printf "Usage: %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}"
|
||||
printf "If no target is specified, both ~/.bashrc and ~/.profile are configured.\n"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
printf "[ Error ] Unknown install option: %s\n" "$1" >&2
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if (( target_selected == 0 )); then
|
||||
install_bashrc=1
|
||||
install_profile=1
|
||||
fi
|
||||
|
||||
script_dir=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")")
|
||||
source_line="source \"$script_dir/profile.sh\""
|
||||
|
||||
if (( install_bashrc == 1 )); then
|
||||
_profile_install_in_file "$HOME/.bashrc" "$source_line" || rc=$?
|
||||
fi
|
||||
|
||||
if (( install_profile == 1 )); then
|
||||
_profile_install_in_file "$HOME/.profile" "$source_line" || rc=$?
|
||||
fi
|
||||
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
case "$1" in
|
||||
--install)
|
||||
shift
|
||||
_profile_install "$@"
|
||||
_profile_finish $?
|
||||
;;
|
||||
-h|--help)
|
||||
printf "Usage: source %s\n" "${BASH_SOURCE[0]}"
|
||||
printf " %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}"
|
||||
_profile_finish 0
|
||||
;;
|
||||
*)
|
||||
printf "[ Error ] Unknown option: %s\n" "$1" >&2
|
||||
_profile_finish 2
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! _profile_is_sourced; then
|
||||
printf "[ Warning ] profile.sh is designed to be sourced, not executed directly.\n" >&2
|
||||
printf "Use: source \"%s\"\n" "$(realpath -s "${BASH_SOURCE[0]}")" >&2
|
||||
printf "Or run: %s --install [--bashrc] [--profile]\n" "${BASH_SOURCE[0]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! $SHELL =~ bash ]]; then
|
||||
echo "That environment script is designed to be used with bash being the shell."
|
||||
echo "Please consider using bash to enjoy our features!"
|
||||
return 1
|
||||
_profile_finish 1
|
||||
fi
|
||||
|
||||
# Required for associative arrays (4.0+) and namerefs (4.3+)
|
||||
@@ -48,6 +161,8 @@ if ((BASH_VERSINFO[0] < 4)) || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1
|
||||
(return 0 2>/dev/null) && return 1 || exit 1
|
||||
fi
|
||||
|
||||
unset -f _profile_is_sourced _profile_finish _profile_install_in_file _profile_install
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# path* : private functions for PATH variable management
|
||||
pathremove()
|
||||
@@ -216,12 +331,12 @@ if [[ ! -e "$MYPATH/profile.sh" ]]; then
|
||||
echo "[ Warning ] Path detection failed, trying to use pwd..."
|
||||
MYPATH=$(pwd)
|
||||
if [[ ! -e "$MYPATH/profile.sh" ]]; then
|
||||
echo "[ Error ] Impossible to determine installation path, pretty much nothing will work."
|
||||
echo "[ Error ] Unable to determine installation path, pretty much nothing will work."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -s "$MYPATH/version" ]]; then
|
||||
echo "[ Warning ] Impossible to determine running version of profile, your installation might be broken."
|
||||
echo "[ Warning ] Unable to determine running profile version; your installation might be broken."
|
||||
fi
|
||||
PROFVERSION=$(cat "$MYPATH"/version)
|
||||
export PROFVERSION
|
||||
@@ -236,6 +351,10 @@ fi
|
||||
# Parse and load general configuration
|
||||
export PROFILE_CONF="$MYPATH/profile.conf"
|
||||
parse_conf "$PROFILE_CONF"
|
||||
# Overload with user configuration if it exists
|
||||
if [[ -f "$HOME/.profile.conf" ]]; then
|
||||
parse_conf "$HOME/.profile.conf"
|
||||
fi
|
||||
load_conf system # Load Bash system behavior configuration (history, pager, etc.)
|
||||
load_conf general # General purpose configuration (compilation flags, etc.)
|
||||
|
||||
@@ -255,6 +374,14 @@ shopt -u nullglob
|
||||
[[ $- == *i* ]] && export INTERACTIVE=1
|
||||
|
||||
if [[ $INTERACTIVE ]]; then
|
||||
# Load custom bash completions
|
||||
shopt -s nullglob
|
||||
for _compl in "$MYPATH/profile.d/bash-completion/"*.sh; do
|
||||
[[ -f "$_compl" && -r "$_compl" ]] && . "$_compl"
|
||||
done
|
||||
unset _compl
|
||||
shopt -u nullglob
|
||||
|
||||
# For compiling (as we often compile with LFS/0linux...)
|
||||
#Aliases
|
||||
load_alias aliases
|
||||
@@ -277,7 +404,7 @@ if [[ $INTERACTIVE ]]; then
|
||||
fi
|
||||
showinfo && printf "\n"
|
||||
check_updates -q
|
||||
disp I "Profile version $PROFVERSION chargé..."
|
||||
disp I "Profile version $PROFVERSION loaded..."
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
|
||||
Reference in New Issue
Block a user