From 248a1e1cfc36673fbdf673323fed7814256acebc Mon Sep 17 00:00:00 2001
From: Edoardo Ferrari <43927507+archetipico@users.noreply.github.com>
Date: Tue, 14 Apr 2026 11:37:23 +0200
Subject: [PATCH 1/3] new version
---
.github/workflows/ci.yml | 34 +
CONTRIBUTING.md | 111 ++-
README.md | 1125 ++++++++++++++++++++++++++--
VERSION | 1 +
completions/_up | 74 ++
completions/up.bash | 30 +
completions/up.fish | 38 +
doc/documentation.pdf | Bin 103726 -> 217082 bytes
doc/documentation.tex | 749 +++++++++++++++---
man/up.1 | 85 +++
setup.ps1 | 69 ++
setup.sh | 143 +++-
share/plugins/example.sh | 23 +
share/profiles/home.ps1 | 2 +
share/profiles/home.sh | 5 +
share/profiles/safe.ps1 | 5 +
share/profiles/safe.sh | 6 +
share/profiles/server.ps1 | 8 +
share/profiles/server.sh | 10 +
share/profiles/work.ps1 | 5 +
share/profiles/work.sh | 6 +
src/emerger.ps1 | 178 +++++
src/emerger.sh | 376 ++++++++--
src/lib/args.sh | 155 ++++
src/lib/changelog.sh | 36 +
src/lib/clean.sh | 70 ++
src/lib/diff.sh | 83 ++
src/lib/disk.sh | 24 +
src/lib/doctor.sh | 109 +++
src/lib/estimate.sh | 21 +
src/lib/help.txt | 95 +++
src/lib/hooks.sh | 20 +
src/lib/ignore.sh | 33 +
src/lib/lock.sh | 22 +
src/lib/log.sh | 21 +
src/lib/metrics.sh | 62 ++
src/lib/mirrors.sh | 33 +
src/lib/notify.sh | 15 +
src/lib/packages.sh | 337 +++++++++
src/lib/plugins.sh | 78 ++
src/lib/profiles.sh | 49 ++
src/lib/progress.sh | 37 +
src/lib/reboot.sh | 48 ++
src/lib/report.sh | 37 +
src/lib/resume.sh | 30 +
src/lib/retry.sh | 25 +
src/lib/run.sh | 65 ++
src/lib/snapshot.sh | 81 ++
src/lib/summary.sh | 160 ++++
src/lib/sys.sh | 59 ++
src/lib/tui.sh | 54 ++
src/lib/ui.sh | 220 ++++++
src/lib/update.sh | 78 ++
src/lib/wizard.sh | 32 +
src/logo/logo.txt | 6 +
src/package/Linux/arch.sh | 25 -
src/package/Linux/debian.sh | 66 --
src/package/Linux/flatpak.sh | 21 -
src/package/Linux/gentoo.sh | 22 -
src/package/Linux/nix.sh | 17 -
src/package/Linux/opensuse.sh | 25 -
src/package/Linux/rpm.sh | 39 -
src/package/Linux/snap.sh | 13 -
src/package/Linux/termux.sh | 21 -
src/package/MacOS/MacOSUpdate.sh | 29 -
src/package/Windows/privileges.ps1 | 3 -
src/package/Windows/winUpdate.ps1 | 48 --
src/pslib/Args.ps1 | 107 +++
src/pslib/Clean.ps1 | 54 ++
src/pslib/Doctor.ps1 | 45 ++
src/pslib/Help.txt | 70 ++
src/pslib/Hooks.ps1 | 18 +
src/pslib/Log.ps1 | 25 +
src/pslib/Notify.ps1 | 13 +
src/pslib/Packages.ps1 | 148 ++++
src/pslib/Profiles.ps1 | 45 ++
src/pslib/Summary.ps1 | 130 ++++
src/pslib/Sys.ps1 | 55 ++
src/pslib/UI.ps1 | 115 +++
src/pslib/Update.ps1 | 54 ++
src/test/argument_check.sh | 29 -
src/test/integrity_check.sh | 71 --
src/test/list/.packages | 9 -
src/test/list/.tests | 1 -
src/test/list/.utils | 7 -
src/utils/.logo | 15 -
src/utils/cache.sh | 19 -
src/utils/cache_gen.sh | 64 --
src/utils/check_pwr.sh | 8 -
src/utils/global.sh | 65 --
src/utils/help | 10 -
src/utils/privileges.sh | 12 -
src/utils/trash.sh | 19 -
tests/emerger.bats | 91 +++
uninstall.ps1 | 45 ++
uninstall.sh | 69 +-
update.ps1 | 5 +
update.sh | 25 +-
98 files changed, 5992 insertions(+), 1058 deletions(-)
create mode 100644 .github/workflows/ci.yml
create mode 100644 VERSION
create mode 100644 completions/_up
create mode 100644 completions/up.bash
create mode 100644 completions/up.fish
create mode 100644 man/up.1
create mode 100644 setup.ps1
create mode 100644 share/plugins/example.sh
create mode 100644 share/profiles/home.ps1
create mode 100644 share/profiles/home.sh
create mode 100644 share/profiles/safe.ps1
create mode 100644 share/profiles/safe.sh
create mode 100644 share/profiles/server.ps1
create mode 100644 share/profiles/server.sh
create mode 100644 share/profiles/work.ps1
create mode 100644 share/profiles/work.sh
create mode 100644 src/emerger.ps1
create mode 100644 src/lib/args.sh
create mode 100644 src/lib/changelog.sh
create mode 100644 src/lib/clean.sh
create mode 100644 src/lib/diff.sh
create mode 100644 src/lib/disk.sh
create mode 100644 src/lib/doctor.sh
create mode 100644 src/lib/estimate.sh
create mode 100644 src/lib/help.txt
create mode 100644 src/lib/hooks.sh
create mode 100644 src/lib/ignore.sh
create mode 100644 src/lib/lock.sh
create mode 100644 src/lib/log.sh
create mode 100644 src/lib/metrics.sh
create mode 100644 src/lib/mirrors.sh
create mode 100644 src/lib/notify.sh
create mode 100644 src/lib/packages.sh
create mode 100644 src/lib/plugins.sh
create mode 100644 src/lib/profiles.sh
create mode 100644 src/lib/progress.sh
create mode 100644 src/lib/reboot.sh
create mode 100644 src/lib/report.sh
create mode 100644 src/lib/resume.sh
create mode 100644 src/lib/retry.sh
create mode 100644 src/lib/run.sh
create mode 100644 src/lib/snapshot.sh
create mode 100644 src/lib/summary.sh
create mode 100644 src/lib/sys.sh
create mode 100644 src/lib/tui.sh
create mode 100644 src/lib/ui.sh
create mode 100644 src/lib/update.sh
create mode 100644 src/lib/wizard.sh
create mode 100644 src/logo/logo.txt
delete mode 100755 src/package/Linux/arch.sh
delete mode 100755 src/package/Linux/debian.sh
delete mode 100755 src/package/Linux/flatpak.sh
delete mode 100755 src/package/Linux/gentoo.sh
delete mode 100755 src/package/Linux/nix.sh
delete mode 100755 src/package/Linux/opensuse.sh
delete mode 100755 src/package/Linux/rpm.sh
delete mode 100755 src/package/Linux/snap.sh
delete mode 100755 src/package/Linux/termux.sh
delete mode 100644 src/package/MacOS/MacOSUpdate.sh
delete mode 100644 src/package/Windows/privileges.ps1
delete mode 100644 src/package/Windows/winUpdate.ps1
create mode 100644 src/pslib/Args.ps1
create mode 100644 src/pslib/Clean.ps1
create mode 100644 src/pslib/Doctor.ps1
create mode 100644 src/pslib/Help.txt
create mode 100644 src/pslib/Hooks.ps1
create mode 100644 src/pslib/Log.ps1
create mode 100644 src/pslib/Notify.ps1
create mode 100644 src/pslib/Packages.ps1
create mode 100644 src/pslib/Profiles.ps1
create mode 100644 src/pslib/Summary.ps1
create mode 100644 src/pslib/Sys.ps1
create mode 100644 src/pslib/UI.ps1
create mode 100644 src/pslib/Update.ps1
delete mode 100755 src/test/argument_check.sh
delete mode 100755 src/test/integrity_check.sh
delete mode 100644 src/test/list/.packages
delete mode 100644 src/test/list/.tests
delete mode 100644 src/test/list/.utils
delete mode 100644 src/utils/.logo
delete mode 100755 src/utils/cache.sh
delete mode 100755 src/utils/cache_gen.sh
delete mode 100755 src/utils/check_pwr.sh
delete mode 100755 src/utils/global.sh
delete mode 100644 src/utils/help
delete mode 100755 src/utils/privileges.sh
delete mode 100755 src/utils/trash.sh
create mode 100644 tests/emerger.bats
create mode 100644 uninstall.ps1
create mode 100644 update.ps1
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..899ce25
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,34 @@
+name: CI
+on:
+ push:
+ branches: [main, dev]
+ pull_request:
+
+jobs:
+ shellcheck:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install shellcheck
+ run: sudo apt-get update && sudo apt-get install -y shellcheck
+ - name: Lint (errors)
+ run: |
+ shopt -s globstar nullglob
+ shellcheck -S error \
+ setup.sh uninstall.sh update.sh \
+ src/emerger.sh src/lib/*.sh
+ - name: Lint (warnings, non-blocking)
+ run: |
+ shopt -s globstar nullglob
+ shellcheck -S warning \
+ setup.sh uninstall.sh update.sh \
+ src/emerger.sh src/lib/*.sh || true
+
+ tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install bats
+ run: sudo apt-get update && sudo apt-get install -y bats
+ - name: Run bats
+ run: bats tests/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 14dc49c..0c95530 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,59 +1,52 @@
-Contributions to this project are very appreciated, though we require some formalisms:
-
- -
- You are not required to explain everything you did inside code comments. But when you are creating code that spans between multiple files, or it requires more than basic knowledge to be understood, help everyone understand what you are doing by leaving small comments inside your code or by explaining the stream of consciousness inside the pull request.
-
- -
- When creating a pull request, point to an issue or explain what you did using few words (this is an extension of what was said in rule 1).
-
- -
- Not following step 1 and step 2, will not exclude your contribution but it will slow the development process because we will have to make questions before accepting your request.
-
- -
- We will not accept contributions containing shady code or any form of crime.
- Examples of shady code is, but not limited to:
-
- -
- References and links to servers we don't own or that are not certified
-
- -
- Exposing users to external or internal vulnerabilities
-
- -
- Using code tricks to bypass privileges or access reserved memory areas
-
-
- Examples of crimes are, but not limited to:
-
- -
- Discrimination based on ethnicity, sex, religion, physical aspect, sexual orientation or any other individual right protected by Human Rights or by simple logic and maturity
-
- -
- Cybercrimes
-
-
-
- -
- It's not mandatory, but try to follow the already existing code indentation.
-
- -
- Since we believe in a friendly enviroment, memes are permitted in comments. Just don't abuse them and respect rule 4.
-
- -
- You can contribute using your licensed code, though we will have to check few things before:
-
- -
- You are the real author
-
- -
- The contribution respects rule 4
-
- -
- If you propose someone else's code to be integrated, the integration will have to respect the author's needs and will. Basically we have to respect its license.
-
-
-
- -
- Last but not least, no one on this planet is born knowning everything. If you respect all the rules above but your pull request is rejected because of the nature of your code, your contribution will not be vain. Your help may give someone else ideas, or the possibility to refactor your code and make it more readable. This is the meaning of open source. Also remember that even us, the creators, started all of this knowing almost nothing, so don't be afraid to be judged.
-
-
\ No newline at end of file
+# Contributing
+
+First of all, thanks for being here! Contributions are very appreciated, but we ask you to follow a few simple rules so everyone can enjoy the ride.
+
+## 1. Comment your code (just a little)
+
+You don't need to explain every single line. But if your change spans multiple files, or it takes more than basic knowledge to understand, please leave a few small comments or share your stream of consciousness in the pull request. Future us (and you) will be grateful.
+
+## 2. Write meaningful pull requests
+
+When opening a PR, link to an issue or describe what you did in a few words. Think of it as an extension of rule 1.
+
+## 3. About rules 1 and 2
+
+Skipping them won't get your contribution rejected, but it will slow things down, since we'll have to ask questions before merging.
+
+## 4. No shady code, no crimes
+
+We will not accept contributions containing *shady code* or any form of *crime*.
+
+Examples of *shady code* (not limited to):
+
+- References and links to servers we don't own or that are not certified
+- Exposing users to external or internal vulnerabilities
+- Code tricks to bypass privileges or access reserved memory areas
+
+Examples of *crimes* (not limited to):
+
+- Discrimination based on ethnicity, sex, religion, physical aspect, sexual orientation, or any other individual right protected by Human Rights or by simple logic and maturity
+- Cybercrimes
+
+## 5. Mind the indentation
+
+Not mandatory, but please try to match the existing code style. It keeps the codebase tidy.
+
+## 6. Memes are welcome
+
+We believe in a friendly environment, so memes in comments are totally fine. Just don't overdo it, and always respect rule 4.
+
+## 7. Licensed code
+
+You can contribute with your licensed code, but we'll have to check a few things first:
+
+1. You are the real author.
+2. The contribution respects rule 4.
+3. If you propose someone else's code, the integration must respect the author's needs and license.
+
+## 8. Don't be afraid
+
+No one on this planet is born knowing everything. If you follow all the rules above but your PR gets rejected because of the nature of your code, your effort won't be in vain: your work may give someone else ideas, or the chance to refactor it into something even better. That's the beauty of open source.
+
+And remember, even us, the creators, started out knowing almost nothing. So really, don't be afraid of being judged. Just jump in.
diff --git a/README.md b/README.md
index 7aaecae..69af492 100644
--- a/README.md
+++ b/README.md
@@ -1,86 +1,1047 @@
-[](https://img.shields.io/github/languages/code-size/MasterCruelty/eMerger)
+# eMerger
+
+[](https://github.com/MasterCruelty/eMerger/actions/workflows/ci.yml)
[](https://sonarcloud.io/summary/new_code?id=TheMergers_eMerger)
-[](https://img.shields.io/github/issues/MasterCruelty/eMerger)
-[](https://img.shields.io/github/languages/top/MasterCruelty/eMerger)
-[](https://sonarcloud.io/summary/new_code?id=TheMergers_eMerger)
-[](https://sonarcloud.io/summary/new_code?id=TheMergers_eMerger)
-[](https://img.shields.io/github/commit-activity/w/MasterCruelty/eMerger)
-[](https://img.shields.io/github/commits-since/MasterCruelty/emerger/latest?color=44CC11&style=flat-square)
-
-eMerger
+[](https://sonarcloud.io/summary/new_code?id=TheMergers_eMerger)
+
-
+
-What is it?
-eMerger is a simple script to clean update your system and your packages by just typing up in your terminal!
-
-Systems tested and working
-
- - Arch Linux
- - Debian
- - EndeavourOS
- - Fedora
- - Kali
- - Manjaro
- - Raspbian
- - Termux
- - Ubuntu
-
-
-Systems tested and not working (help wanted)
-
-
-Supported package managers
-
- - apt
- - apt-get
- - dnf
- - emerge
- - flatpak
- - nixos
- - pacman
- - pkg
- - rpm
- - snap
- - yay
- - yum
- - zypper
-
-
----
-
-Install
-
- - Run
./setup.sh
- - Run
up
-
-If you cloned using root privileges, and you want to execute without them, remember to run: sudo chown -R yourusername .
-Uninstall
-
- - Run
./uninstall.sh
-
-Update
-You have three options:
-
- - Run
./update.sh
- - Run
up -up
- - Run
up -au to set a cronjob
-
-Usage
-eMerger comes with inline arguments: just type up -help to explore them.
-
----
-
-Contribute
-How to contribute
-Issue
-Is there a problem? 🖥️
-Your package manager is not listed? 🖥️
-Feel free to open an issue. Try to explain exactly what happens and if possible post errors or outputs you managed to retrieve.
-License
- This project license can be found in ./LICENSE
-External projects used
-wttr.in
+**One command - `up` - refreshes, upgrades and cleans your whole system.**
+Works on **Linux**, **macOS** and **Windows**. Auto-detects every package
+manager you have, runs them in the right order, gives you one clean summary
+at the end. No YAML, no daemons.
+
+---
+
+## Table of contents
+
+1. [Platforms at a glance](#platforms-at-a-glance)
+2. [Quickstart](#quickstart)
+3. [Requirements](#requirements)
+4. [Installation](#installation)
+ - [Linux](#install-linux)
+ - [macOS](#install-macos)
+ - [Windows](#install-windows)
+5. [Uninstallation](#uninstallation)
+6. [Update / self-update](#update--self-update)
+7. [User manual](#user-manual)
+ - [Running](#running)
+ - [Flags, quick reference](#flags-quick-reference)
+ - [Combining flags](#combining-flags)
+ - [Interactive mode](#interactive-mode)
+ - [Dry-run & verbose](#dry-run--verbose)
+ - [Quiet levels](#quiet-levels)
+ - [Security-only updates](#security-only-updates)
+ - [Dev toolchains](#dev-toolchains)
+ - [Firmware (Linux)](#firmware-linux)
+ - [Parallel mode](#parallel-mode)
+ - [Snapshots (Linux)](#snapshots-linux)
+ - [Mirrors refresh (Linux)](#mirrors-refresh-linux)
+ - [Reboot handling](#reboot-handling)
+ - [Resume after interruption](#resume-after-interruption)
+ - [Package diff & changelog](#package-diff--changelog)
+ - [Reports](#reports)
+ - [History & errors](#history--errors)
+ - [Doctor](#doctor)
+8. [Configuration](#configuration)
+ - [config file](#config-file)
+ - [Profiles](#profiles)
+ - [Hooks](#hooks)
+ - [Ignore list (Linux)](#ignore-list-linux)
+ - [Quiet hours](#quiet-hours)
+ - [Manager plugins](#manager-plugins)
+9. [Integration](#integration)
+ - [JSON output](#json-output)
+ - [Prometheus metrics](#prometheus-metrics)
+ - [Reboot exit code](#reboot-exit-code)
+ - [Download-only / offline](#download-only--offline)
+ - [Manager filtering](#manager-filtering)
+ - [Rollback](#rollback)
+ - [Short flag bundling](#short-flag-bundling)
+10. [Auto-update (unattended)](#auto-update-unattended)
+11. [Files & paths](#files--paths)
+12. [Supported package managers](#supported-package-managers)
+13. [Exit codes](#exit-codes)
+14. [Troubleshooting](#troubleshooting)
+15. [Development](#development)
+16. [License](#license)
+
+---
+
+## Platforms at a glance
+
+| | Linux | macOS | Windows |
+|---|---|---|---|
+| Entry point | `src/emerger.sh` | `src/emerger.sh` | `src/emerger.ps1` |
+| Shell | bash 3.2+ | bash 3.2+ (system default) | PowerShell 5.1+ |
+| Setup | `./setup.sh` | `./setup.sh` | `.\setup.ps1` |
+| Uninstall | `./uninstall.sh` | `./uninstall.sh` | `.\uninstall.ps1` |
+| Auto-update | systemd user timer / cron | launchd-compat cron | Task Scheduler |
+| Elevation | `sudo` | `sudo` | UAC relaunch |
+| Config dir | `~/.config/emerger/` | `~/.config/emerger/` | `%APPDATA%\emerger\` |
+| State dir | `~/.local/state/emerger/` | `~/.local/state/emerger/` | `%LOCALAPPDATA%\emerger\state\` |
+
+Feature parity is kept for the core flow (detect → upgrade → clean → summary).
+Platform-specific features are documented below.
+
+---
+
+## Quickstart
+
+**Linux / macOS**
+```sh
+git clone https://github.com/MasterCruelty/eMerger
+cd eMerger
+./setup.sh
+# open a new shell (or: source ~/.bashrc)
+up --help
+up -n
+up
+```
+
+**Windows** (PowerShell)
+```powershell
+git clone https://github.com/MasterCruelty/eMerger
+cd eMerger
+.\setup.ps1
+# open a new PowerShell window (or: . $PROFILE)
+up --help
+up -n
+up
+```
+
+---
+
+## Requirements
+
+**Linux**
+- bash ≥ 3.2, coreutils, git, sudo.
+- Optional: `gum`/`whiptail`, `notify-send`, `curl`, `flock`, `reflector`,
+ `netselect-apt`, `snapper`/`timeshift`/`btrfs-progs`, `fwupdmgr`.
+
+**macOS**
+- bash ≥ 3.2 (the system `/bin/bash` works out of the box; no Homebrew bash needed).
+- Xcode Command Line Tools (for git).
+- Optional: Homebrew, `mas` (`brew install mas`).
+
+**Windows**
+- PowerShell 5.1 (built-in on Win10+) or 7+.
+- Git for Windows (for `up --self-update`).
+- Optional: `winget`, `scoop`, `choco`, `PSWindowsUpdate`
+ (`Install-Module PSWindowsUpdate -Scope CurrentUser`), `BurntToast`
+ (`Install-Module BurntToast`) for toast notifications.
+
+eMerger never installs these for you - it only uses what's there.
+
+---
+
+## Installation
+
+### Install (Linux)
+
+```sh
+git clone https://github.com/MasterCruelty/eMerger
+cd eMerger
+./setup.sh
+```
+
+`setup.sh` does exactly this:
+
+1. Adds `alias up='bash /path/to/eMerger/src/emerger.sh'` to your shell rc
+ (bash, zsh, fish - whichever you use).
+2. Makes `src/emerger.sh` executable.
+3. Installs shell completions under:
+ - `~/.local/share/bash-completion/completions/up`
+ - `~/.zsh/completions/_up`
+ - `~/.config/fish/completions/up.fish`
+4. Creates `~/.config/emerger/{config.sh,ignore.list,hooks/,profiles.d/}`.
+
+After install, **open a new shell** (or `source ~/.bashrc`).
+
+### Install (macOS)
+
+Identical script, same flow:
+
+```sh
+git clone https://github.com/MasterCruelty/eMerger
+cd eMerger
+./setup.sh
+```
+
+macOS specifics handled automatically:
+- The alias is written to `~/.zshrc` first (zsh is the default shell since Catalina).
+- If Homebrew is installed, completions go to
+ `$(brew --prefix)/etc/bash_completion.d/` and
+ `$(brew --prefix)/share/zsh/site-functions/`.
+- `softwareupdate` (native macOS updater) is auto-detected alongside `brew`,
+ `brew --cask`, and `mas`.
+
+### Install (Windows)
+
+```powershell
+git clone https://github.com/MasterCruelty/eMerger
+cd eMerger
+.\setup.ps1
+```
+
+`setup.ps1` does:
+
+1. Sets `ExecutionPolicy` to `RemoteSigned` for `CurrentUser` if it was
+ `Restricted` or `Undefined`. No admin needed for this.
+2. Adds a `function up { & "…\emerger.ps1" @args }` block to your
+ `$PROFILE.CurrentUserAllHosts` (so `up` works from any host: cmd-hosted
+ PS, ISE, Terminal…).
+3. Scaffolds `%APPDATA%\emerger\{config.ps1,hooks\,profiles.d\}`.
+
+After install, **open a new PowerShell window** (or `. $PROFILE`).
+
+> **Important**: `setup.ps1` does **not** require admin. Package manager
+> runs that need admin will trigger a UAC prompt via automatic elevation.
+
+### Manual install
+
+All three platforms: just point an alias/function at the entry point.
+
+```sh
+# bash/zsh/fish - macOS or Linux
+alias up='bash /absolute/path/to/eMerger/src/emerger.sh'
+```
+
+```powershell
+# PowerShell - Windows
+function up { & "C:\path\to\eMerger\src\emerger.ps1" @args }
+```
+
+---
+
+## Uninstallation
+
+```sh
+# Linux / macOS
+./uninstall.sh
+```
+
+```powershell
+# Windows
+.\uninstall.ps1
+```
+
+Removes the shell alias / `up` function, any cronjob, systemd user timer or
+scheduled task. **Keeps** your config and state directories so you don't
+lose history or hooks. Delete those paths manually if you want a clean
+wipe.
+
+The repo itself is not removed - `rm -rf` or `Remove-Item` the directory
+when you're done.
+
+---
+
+## Update / self-update
+
+Three equivalent ways:
+
+```sh
+up -up # flag form
+```
+or
+```sh
+up --self-update
+```
+or
+```sh
+./update.sh # Linux / macOS
+.\update.ps1 # Windows
+```
+
+This does a `git pull --ff-only` inside the repo and shows the commit range.
+Refuses non-fast-forward pulls so local changes never silently vanish.
+
+For automatic updates of eMerger itself, put it in `post.d` hook (see
+[Hooks](#hooks)).
+
+---
+
+## User manual
+
+### Running
+
+```sh
+up # Linux / macOS
+```
+```powershell
+up # Windows
+```
+
+What happens:
+
+1. Show logo + OS info + timestamp (skippable with `-nl`/`-ni`).
+2. Warn on low battery.
+3. Warn on low disk space (`/` on Unix, `C:` on Windows).
+4. Cache sudo credentials (Unix) or relaunch elevated (Windows) if any
+ detected manager needs it.
+5. Snapshot installed packages (for diff).
+6. Run `pre.d` hooks.
+7. For each detected manager, run refresh → upgrade → clean.
+8. Optionally clean user cache / `%TEMP%` and trash / recycle bin.
+9. Run `post.d` hooks.
+10. Compute diff.
+11. Print boxed summary + reboot advisory.
+12. Emit desktop notification (if session has a display / BurntToast is
+ installed on Windows).
+
+### Flags, quick reference
+
+Authoritative list: `up --help`. Highlights:
+
+| Flag | Meaning | Platforms |
+|---|---|---|
+| `-n`, `--dry-run` | Preview, don't run | all |
+| `-v`, `--verbose` | Stream output live | all |
+| `-q` / `-qq` / `-qqq` | Quieter | all |
+| `-y`, `--yes` | Assume yes | all |
+| `-i`, `--interactive` | Menu UI | Linux/macOS |
+| `--security` | Security-only | all (where supported) |
+| `--dev` | Include dev toolchains | all |
+| `--firmware` | `fwupdmgr` | Linux |
+| `--parallel` | Run user-space concurrently | Linux/macOS |
+| `--profile NAME` | Load a profile | all |
+| `--snapshot` | snapper/timeshift/btrfs | Linux |
+| `--refresh-mirrors` | re-rank mirrors | Linux |
+| `--resume` | Skip completed managers | Linux/macOS |
+| `--reboot` | Reboot if required | all |
+| `--changed` | Package diff | Linux/macOS |
+| `--changelog PKG` | Upstream changelog | Linux/macOS |
+| `--report FILE` | Export Markdown | Linux/macOS |
+| `--doctor` | Health check | all |
+| `--history` | Recent runs | all |
+| `--errors` / `-err` | Log tail | all |
+| `--no-emoji` | ASCII only | all |
+| `--json` | Machine-readable summary | all |
+| `--reboot-exit` | Exit 4 if reboot is required | all |
+| `--rollback` | Revert last snapshot | Linux |
+| `--download-only` / `--offline` | Prefetch, don't install | Linux/macOS (apt/dnf/pacman/zypper) |
+| `--only LIST` | Keep only these managers | all |
+| `--except LIST` | Skip these managers | all |
+| `--metrics FILE` | Prometheus textfile export | all |
+| `-up` | Self-update | all |
+| `-au` | Install auto-update | all |
+
+### Combining flags
+
+Flags are independent tokens - mix and match as many as you need, in any
+order. Short bundling (`-nv` for `-n -v`) is **not** supported; keep them
+space-separated.
+
+```sh
+up -n -v # dry-run + live stream (preview a full run)
+up -y -q --security # unattended security-only, minimal output
+up --dev --parallel -v # dev toolchains + user-space concurrency, verbose
+up --snapshot --reboot -y # snapshot first, reboot at the end if needed
+up --profile server --resume # resume an interrupted headless run
+up -n --dev --firmware # preview a full dev + firmware run, no side effects
+up -qq -y -nl -ni --security # exactly what the scheduled timer does
+up --refresh-mirrors -y -v # re-rank mirrors then upgrade, watch it live
+up --changed --report out.md # show diff and export it in one shot
+```
+
+```powershell
+up -y -q --security # Windows, unattended security-only
+up --dev -v # Windows, include dev toolchains, verbose
+up -n --security # Windows, preview a security-only run
+```
+
+Flags that take a value (`--profile NAME`, `--changelog PKG`,
+`--report FILE`) must keep their argument adjacent; everything else is
+position-free. CLI flags always win over config file and profile defaults,
+so you can override a profile on the fly:
+
+```sh
+up --profile work --dev # work profile, but force dev toolchains this run
+```
+
+### Interactive mode
+
+```sh
+up -i
+```
+
+Menu via `gum` (pretty), `whiptail` (classic), or plain read-loop.
+Windows does not ship a TUI - use flags directly or a profile.
+
+### Dry-run & verbose
+
+```sh
+up -n # see what would happen (safe, no sudo)
+up -v # stream pkg-manager output live
+up -n -v # both
+```
+
+### Quiet levels
+
+- default - full UI
+- `-q` - hide muted/info lines
+- `-qq` - only step titles + one-line summary
+- `-qqq` - exit code only
+
+### Security-only updates
+
+```sh
+up --security -y
+```
+
+- Linux: `apt` (via `unattended-upgrade`), `dnf` (`--security`),
+ `zypper` (`patch --category security`).
+- macOS: `softwareupdate --install --recommended`.
+- Windows: `PSWindowsUpdate` respects KB severity if the module supports it.
+
+Other managers ignore the flag.
+
+### Dev toolchains
+
+Opt-in (every platform):
+
+```sh
+up --dev
+```
+
+Updates `rustup`, `cargo install-update -a`, `npm update -g`, `pnpm -g update`,
+`pip` (user), `gem update`.
+
+### Firmware (Linux)
+
+```sh
+up --firmware
+```
+
+Runs `fwupdmgr refresh && fwupdmgr update -y --no-reboot-check`. Windows
+firmware is handled by vendor tools (Dell Command Update, Lenovo Vantage)
+and is out of scope. macOS firmware is handled by `softwareupdate`.
+
+### Parallel mode
+
+```sh
+up --parallel
+```
+
+User-space managers that don't touch `/` run concurrently (`flatpak`,
+`snap`, `brew`, `mas`, dev tools). System managers stay serial. Windows
+side is currently always serial.
+
+### Snapshots (Linux)
+
+```sh
+up --snapshot
+```
+
+Tries in order: `snapper`, `timeshift`, `btrfs subvolume snapshot`. Windows
+users: enable **System Restore** manually; eMerger doesn't trigger it.
+
+### Mirrors refresh (Linux)
+
+```sh
+up --refresh-mirrors
+```
+
+- Arch: `reflector --latest 20 --sort rate`.
+- Debian/Ubuntu: `netselect-apt`.
+- Fedora: handled by `fastestmirror` plugin automatically; no-op here.
+
+### Reboot handling
+
+After a run, eMerger checks for reboot flags:
+
+- Linux: `/var/run/reboot-required`, `needs-restarting -r`.
+- Windows: registry keys (`CBS RebootPending`, `WindowsUpdate\RebootRequired`,
+ `PendingFileRenameOperations`).
+
+To reboot on demand:
+
+```sh
+up --reboot # reboots if required, no-op otherwise
+```
+
+### Resume after interruption
+
+If you kill a run mid-way:
+
+```sh
+up --resume
+```
+
+skips every manager that successfully completed in the last interrupted run.
+State lives in `~/.local/state/emerger/resume`. Linux/macOS only.
+
+### Package diff & changelog
+
+Every run records installed packages before/after. View it:
+
+```sh
+up --changed
+```
+
+Legend: `+` added, `-` removed, `~` upgraded. Linux/macOS.
+
+Read a single package's upstream changelog:
+
+```sh
+up --changelog firefox
+```
+
+Dispatches to `apt changelog`, `dnf changelog`/`updateinfo`, `pacman -Qi`,
+or `brew log`.
+
+### Reports
+
+```sh
+up --report report.md
+```
+
+Markdown export of the last run: JSON summary, managers, reboot advisory,
+full package diff as a table.
+
+### History & errors
+
+```sh
+up --history # last 10 runs
+up --errors # tail of ERROR lines from the log
+```
+
+### Doctor
+
+```sh
+up --doctor
+```
+
+Audits:
+- shell / PowerShell version
+- sudo cache / admin status
+- disk space
+- network reachability
+- state dir writability
+- per-manager native health (`dpkg --audit`, `pacman -Dk`, `brew doctor`, …)
+- pending reboot flag
+- (Windows) ExecutionPolicy
+
+Exits non-zero if issues are found.
+
+---
+
+## Configuration
+
+### config file
+
+**Linux / macOS** - `~/.config/emerger/config.sh` (sourced before arg parsing):
+
+```sh
+ARG_DEV=1 # always include dev toolchains
+ARG_WEATHER=1 # always show weather
+DISK_MIN_FREE_MB=2048 # require >= 2 GB on /
+QUIET_HOURS="23:00-07:00" # skip scheduled runs inside this window
+RETRY_MAX=3 # transient-error retries
+```
+
+**Windows** - `%APPDATA%\emerger\config.ps1` (dot-sourced before arg parsing):
+
+```powershell
+$script:ArgsGlobal.Dev = $true
+$script:ArgsGlobal.Security = $true
+$script:ArgsGlobal.NoTrash = $true
+```
+
+### Profiles
+
+Profiles are config snippets scoped to a name.
+
+```sh
+up --profile work
+up --list-profiles
+```
+
+Shipped defaults in `share/profiles/`:
+
+| Profile | Meant for |
+|---|---|
+| `work` | laptop al lavoro - security, unattended, no cache/trash |
+| `home` | PC fisso - tutto, dev toolchains, parallel |
+| `server` | headless - `-qq`, security, no prompts |
+| `safe` | pre-presentation - security only, no big downloads |
+
+Each platform looks for its own extension:
+
+- Unix → `share/profiles/.sh`
+- Windows → `share/profiles/.ps1`
+
+User profiles go in `~/.config/emerger/profiles.d/` (Unix) or
+`%APPDATA%\emerger\profiles.d\` (Windows) and shadow the shipped ones.
+
+### Hooks
+
+Drop executable scripts in `hooks/pre.d/` (before updates) or
+`hooks/post.d/` (after). They run alphabetically. A failing hook emits a
+warning but never aborts the run.
+
+- Unix: `*.sh`, run under bash.
+- Windows: `*.ps1`, dot-sourced under PowerShell.
+
+Example:
+
+```sh
+# ~/.config/emerger/hooks/pre.d/10-backup-dotfiles.sh
+#!/usr/bin/env bash
+rsync -a ~/.config/ ~/backups/dotfiles/
+```
+
+```powershell
+# %APPDATA%\emerger\hooks\post.d\10-log-to-gist.ps1
+Get-Content (Join-Path $env:LOCALAPPDATA 'emerger\state\emerger.log') -Tail 20 |
+ Set-Clipboard
+```
+
+### Ignore list (Linux)
+
+`~/.config/emerger/ignore.list` - one package per line, `#` comments ok.
+Honored natively by **pacman** (`--ignore=`). For others it is
+**advisory** - you still need to hold them via:
+
+- apt: `sudo apt-mark hold `
+- dnf: `sudo dnf versionlock add `
+- zypper: `sudo zypper al `
+
+### Quiet hours
+
+Set `QUIET_HOURS="HH:MM-HH:MM"` in `config.sh`. When a scheduled run starts
+inside that window **and** `-y` is set (i.e. from the timer), eMerger exits
+immediately. Interactive runs always proceed. Linux/macOS.
+
+### Manager plugins
+
+Drop a bash script in `~/.config/emerger/managers.d/.sh` to add support
+for a package manager without touching the repo. A minimal plugin:
+
+```sh
+PM_PLUGIN_SLUG=mytool
+
+pm_mytool_detect() { command -v mytool >/dev/null 2>&1; }
+pm_mytool_needs_sudo() { return 1; } # optional, default: no sudo
+pm_mytool_parallel() { return 0; } # optional, default: serial
+pm_mytool_dev() { return 1; } # optional, default: not gated by --dev
+pm_mytool_icon() { printf '🔌'; } # optional
+pm_mytool_run() {
+ run_cmd "mytool update" mytool update || return 1
+ run_cmd "mytool upgrade" mytool upgrade -y || return 1
+}
+```
+
+A complete, copy-pasteable template lives in
+[`share/plugins/example.sh`](share/plugins/example.sh).
+
+Plugins are registered at the same level as native managers: they honour
+`--only`, `--except`, `--parallel`, `--dev`, the detection cache, hooks and
+the summary. They are invoked from inside `pkg_run`, so `run_cmd` automatically
+gives them `--dry-run`, retry, logging and live-log handling for free.
+
+The detection cache is keyed by manager slug and lives at
+`~/.cache/emerger/detected`. TTL defaults to 1 day; override via
+`EMERGER_CACHE_TTL=` in `config.sh` (0 disables caching).
+
+Linux/macOS only. Windows plugins are not yet supported.
+
+---
+
+## Integration
+
+### JSON output
+
+```sh
+up --json
+```
+
+Emits a single-line JSON object on stdout. The logo, info line and summary
+box are all suppressed, so the output is safe to pipe into `jq` or consume
+from a CI job:
+
+```json
+{"ts":"2026-04-14T07:24:31Z","duration":42,"freed_kb":15360,
+ "errors":0,"reboot":0,
+ "managers":[{"name":"apt","result":"ok"},{"name":"flatpak","result":"ok"}]}
+```
+
+The same schema is what `history.jsonl` stores one per line.
+
+### Prometheus metrics
+
+```sh
+up --metrics /var/lib/node_exporter/textfile_collector/emerger.prom
+```
+
+Reads the most recent entry from `history.jsonl` and renders a Prometheus
+textfile-collector snapshot. Exported gauges:
+
+- `emerger_last_run_timestamp_seconds`
+- `emerger_last_run_duration_seconds`
+- `emerger_last_run_freed_bytes`
+- `emerger_last_run_errors`
+- `emerger_reboot_required`
+- `emerger_manager_ok{manager="..."}` (one per manager from the last run)
+
+Does not trigger a run - invoke it from a `post.d` hook or from your timer
+after `up` completes.
+
+### Reboot exit code
+
+By default eMerger always exits 0 on success even when a reboot is pending
+(the summary box prints `REBOOT RECOMMENDED`). Pass `--reboot-exit` to turn
+that into exit code **4** instead, so an orchestrator can react:
+
+```sh
+up -y --reboot-exit
+rc=$?
+case $rc in
+ 0) ;; # done, no reboot needed
+ 3) notify-send "eMerger: some managers failed" ;;
+ 4) systemctl reboot ;; # clean, reboot required
+esac
+```
+
+### Download-only / offline
+
+```sh
+up --download-only -y # or --offline
+```
+
+Refreshes indexes and **downloads** the pending upgrade set but does not
+install it. Supported natively on `pacman` (`-Syuw`), `apt`/`apt-get`
+(`--download-only`), `dnf` (`--downloadonly`) and `zypper`
+(`update --download-only`). Other managers ignore the flag.
+
+Typical use cases:
+
+- laptop on a slow/metered connection at a café: prefetch while online,
+ install later at the office
+- servers in a maintenance window: prestage packages, then flip to
+ install-only when the change ticket opens
+- pre-flight for `--snapshot`: confirm the whole update set is downloaded
+ before taking a snapshot
+
+### Manager filtering
+
+```sh
+up --only apt,flatpak # only these managers (comma-separated)
+up --except snap,fwupd # everything that would run, minus these
+```
+
+The filters are applied after detection and after `--dev`/`--firmware`
+gating, so:
+
+- `--only X` with `X` not detected is a no-op (nothing runs).
+- `--except` wins over `--only` when both mention the same name.
+
+Compose with profiles (`up --profile work --only apt`) to restrict a
+profile on the fly.
+
+### Rollback
+
+```sh
+up --rollback
+```
+
+Reverts to the most recent eMerger-created snapshot. Dispatches to:
+
+- **snapper**: native `snapper -c root rollback `. Grep-finds the last
+ snapshot whose description starts with `eMerger pre-update`. A reboot is
+ required to apply the rollback (snapper semantics, not ours).
+- **timeshift**: hands off to `timeshift --restore` (interactive by design;
+ we don't pass `--yes` - rollback is too destructive for that).
+- **raw btrfs**: refuses to swap subvolumes automatically, prints the path
+ of the latest snapshot under `/.snapshots/emerger/` so you can do it
+ manually.
+
+Combine with `--snapshot` for a safe update cycle:
+
+```sh
+up --snapshot -y || up --rollback
+```
+
+### Short flag bundling
+
+Single-letter short flags can be bundled:
+
+```sh
+up -nv # == up -n -v
+up -ynv # == up -y -n -v
+up -qv # == up -q -v
+```
+
+Only flags whose letters are all in the set `{h V n v q y i w}` bundle.
+Compound short flags (`-nl`, `-ni`, `-nc`, `-nt`, `-qq`, `-qqq`, `-up`,
+`-au`, `-err`, `-rc`) and long flags (`--foo`) pass through unchanged.
+
+---
+
+## Auto-update (unattended)
+
+```sh
+up -au # Linux / macOS
+```
+```powershell
+up -au # Windows
+```
+
+- **Linux**: systemd user timer (preferred) at
+ `~/.config/systemd/user/emerger.{service,timer}`; cron fallback.
+- **macOS**: cron fallback (`crontab -l`), or use `launchd` manually.
+- **Windows**: `Register-ScheduledTask -TaskName eMerger`. Weekly, Sunday
+ 10:00, ±1h randomized delay.
+
+The scheduled run always uses `-y -q -nl -ni`.
+
+Manage:
+
+```sh
+# Linux
+systemctl --user status emerger.timer
+systemctl --user disable emerger.timer
+
+# Windows
+Get-ScheduledTask eMerger
+Unregister-ScheduledTask eMerger
+```
+
+To avoid night-time runs, pair with `QUIET_HOURS` in `config.sh`.
+
+---
+
+## Files & paths
+
+### Linux / macOS
+
+| Path | Purpose |
+|---|---|
+| `~/.config/emerger/config.sh` | User defaults |
+| `~/.config/emerger/profiles.d/` | User profiles |
+| `~/.config/emerger/hooks/pre.d/`, `post.d/` | Hooks |
+| `~/.config/emerger/ignore.list` | Ignore list (pacman native) |
+| `~/.config/emerger/managers.d/*.sh` | User-defined manager plugins |
+| `~/.cache/emerger/detected` | Detection cache (TTL: `EMERGER_CACHE_TTL`, default 86400s) |
+| `~/.local/state/emerger/emerger.log` | Log (rotated at 2000 lines) |
+| `~/.local/state/emerger/history.jsonl` | One JSON per run |
+| `~/.local/state/emerger/resume` | Resume cursor |
+| `/tmp/emerger.lock` | Global lock (`flock`) |
+
+### Windows
+
+| Path | Purpose |
+|---|---|
+| `%APPDATA%\emerger\config.ps1` | User defaults |
+| `%APPDATA%\emerger\profiles.d\` | User profiles |
+| `%APPDATA%\emerger\hooks\pre.d\`, `post.d\` | Hooks |
+| `%LOCALAPPDATA%\emerger\cache\` | Detection cache |
+| `%LOCALAPPDATA%\emerger\state\emerger.log` | Log |
+| `%LOCALAPPDATA%\emerger\state\history.jsonl` | Run history |
+
+---
+
+## Supported package managers
+
+**Linux - system (need sudo):**
+`pacman`, `apt`/`apt-get`, `dnf`, `yum`, `zypper`, `xbps`, `apk`, `eopkg`,
+`emerge`, `nixos-rebuild`, `fwupdmgr`, `snap`.
+
+**Linux - AUR (no sudo):** `yay`, `paru`.
+
+**Linux - user-space:** `flatpak`, `nix-env`.
+
+**macOS:** `softwareupdate` (native), `brew`, `brew --cask`, `mas`.
+
+**Windows:** `winget`, `scoop`, `choco`, `PSWindowsUpdate`, `wsl --update`.
+
+**Dev toolchains** (all platforms, opt-in with `--dev`): `rustup`,
+`cargo install-update`, `npm`, `pnpm`, `pip` (user), `gem`.
+
+Want another one? Add a case branch to
+[`src/lib/packages.sh`](src/lib/packages.sh) (Unix) or
+[`src/pslib/Packages.ps1`](src/pslib/Packages.ps1) (Windows) - they're
+simple table-driven dispatchers.
+
+---
+
+## Exit codes
+
+| Code | Meaning |
+|---|---|
+| 0 | success |
+| 1 | runtime failure (sudo, lock, disk, interrupted) |
+| 2 | argument parsing error |
+| 3 | one or more package managers returned non-zero |
+| 4 | reboot required (only emitted with `--reboot-exit`) |
+
+Useful for CI / cron wrappers:
+
+```sh
+up -y -q || case $? in
+ 3) notify-send "eMerger: some managers failed" ;;
+ *) logger -t eMerger "fatal $?" ;;
+esac
+```
+
+```powershell
+up -y -q
+if ($LASTEXITCODE -eq 3) { Write-Warning "Some managers failed" }
+```
+
+---
+
+## Troubleshooting
+
+**"Another eMerger run is in progress"** - stale `flock` on
+`/tmp/emerger.lock`. Check `ps` for stragglers then remove it.
+
+**Emoji renders as boxes** - `--no-emoji`, or set `LANG` / Windows Terminal
+font to a Unicode-capable one.
+
+**Spinner disappears on terminal resize** - harmless; the live-log width
+recomputes every 120ms.
+
+**`up --self-update` aborts with "non fast-forward"** - you have local
+commits on top of `main`. Rebase or reset manually; eMerger refuses to
+clobber them.
+
+**`notify-send` (Linux) doesn't appear** - no `DISPLAY` /
+`WAYLAND_DISPLAY` in the environment (typical for cron). Use systemd user
+timer instead; it inherits the session.
+
+**(Windows) "up : The term 'up' is not recognized"** - your PowerShell
+profile didn't load. Run `. $PROFILE` or open a new window. If still
+missing, re-run `.\setup.ps1`.
+
+**(Windows) "cannot be loaded because running scripts is disabled"** -
+`ExecutionPolicy` is `Restricted`. Run as user:
+```powershell
+Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
+```
+
+**(Windows) Elevation fails silently** - you canceled the UAC prompt. The
+script logs `relaunching elevated` then exits; the elevated window does
+the actual work.
+
+**Pacman keeps asking about ignored packages** - `ignore.list` is passed
+as `--ignore=`; pacman still prints the warning line. Upstream behavior.
+
+---
+
+## Development
+
+### Repo layout
+
+```text
+eMerger/
+├── src/
+│ ├── emerger.sh # Unix entry (Linux + macOS)
+│ ├── emerger.ps1 # Windows entry
+│ ├── lib/ # bash libs
+│ ├── pslib/ # PowerShell libs
+│ └── logo/
+├── share/profiles/ # shipped profiles (*.sh + *.ps1)
+├── completions/ # bash/zsh/fish completions
+├── tests/ # bats tests
+├── man/up.1 # man page
+├── setup.sh setup.ps1
+├── uninstall.sh uninstall.ps1
+├── update.sh update.ps1
+├── VERSION
+└── .github/workflows/ci.yml
+```
+
+### Unix lib modules (`src/lib/`)
+
+| File | Role |
+|---|---|
+| `ui.sh` | Colors, glyphs, spinner, box, live-log monitor |
+| `log.sh` | Structured logging (rotated) |
+| `sys.sh` | OS/shell/battery/disk detection |
+| `run.sh` | Command runner (dry-run, retry, progress) |
+| `args.sh` | Argument parser |
+| `packages.sh` | Per-manager dispatcher |
+| `clean.sh` | Cache and trash cleaners |
+| `hooks.sh` | User hook runner |
+| `update.sh` | Self-update + cron/timer setup |
+| `notify.sh` | Desktop notifications |
+| `summary.sh` | Final banner, history persistence |
+| `tui.sh` | Interactive menu |
+| `lock.sh` | Global `flock` |
+| `retry.sh` | Retry on transient failures |
+| `reboot.sh` | Reboot-required detection |
+| `diff.sh` | Package snapshots + diff |
+| `disk.sh` | Disk-space precheck |
+| `snapshot.sh` | snapper/timeshift/btrfs |
+| `mirrors.sh` | Mirror rank/refresh |
+| `resume.sh` | Resume cursor |
+| `doctor.sh` | `--doctor` |
+| `changelog.sh` | `--changelog PKG` |
+| `report.sh` | Markdown export |
+| `wizard.sh` | First-run wizard |
+| `profiles.sh` | Profile loader |
+| `progress.sh` | Output summary + highlight |
+| `estimate.sh` | Step ETA from history |
+| `ignore.sh` | Ignore list loader |
+
+### PowerShell lib modules (`src/pslib/`)
+
+| File | Role |
+|---|---|
+| `UI.ps1` | Colors, glyphs, box, step |
+| `Log.ps1` | Structured logging |
+| `Sys.ps1` | OS, admin, battery, disk, UAC elevation |
+| `Args.ps1` | Arg parser (shift + regex) |
+| `Packages.ps1` | Manager dispatcher + `Run-Cmd` |
+| `Clean.ps1` | `%TEMP%` and Recycle Bin |
+| `Hooks.ps1` | `hooks\{pre,post}.d\*.ps1` |
+| `Update.ps1` | `git pull` self-update + Task Scheduler |
+| `Notify.ps1` | BurntToast (optional) |
+| `Summary.ps1` | Final box, history, reboot detection |
+| `Doctor.ps1` | `--doctor` |
+| `Profiles.ps1` | Profile loader |
+| `Help.txt` | Help text |
+
+### Running tests
+
+```sh
+sudo apt-get install bats shellcheck
+bats tests/
+shellcheck -S error src/emerger.sh src/lib/*.sh setup.sh uninstall.sh update.sh
+```
+
+Both run on push via `.github/workflows/ci.yml`.
+
+### Adding a package manager
+
+**Unix** - edit [`src/lib/packages.sh`](src/lib/packages.sh):
+1. Add its name to `PKG_MANAGERS`.
+2. Add a branch in `_pkg_detect_raw`.
+3. Add a branch in `pkg_run` with `run_cmd` calls.
+4. If it doesn't need sudo, exclude it from `pkg_needs_sudo`.
+5. Optional: emoji in `pkg_icon`, output parser in `progress.sh`.
+
+**Windows** - edit [`src/pslib/Packages.ps1`](src/pslib/Packages.ps1):
+1. Add its name to `$script:PKG_MANAGERS` (or `PKG_DEV`).
+2. Add a `Pkg-Detect` case.
+3. Add a `Pkg-Run` case with `Run-Cmd` calls.
+4. If it needs admin, add it to `Pkg-Need-Admin`.
+
+### Contributing
+
+See [CONTRIBUTING.md](./CONTRIBUTING.md). Open issues and PRs against
+`dev`. Include `up --doctor` output and the relevant chunk of the log when
+reporting bugs.
+
+---
+
+## License
+
+See [LICENSE](./LICENSE).
+
+## Credits
+
+Weather line via [wttr.in](https://github.com/chubin/wttr.in).
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..227cea2
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+2.0.0
diff --git a/completions/_up b/completions/_up
new file mode 100644
index 0000000..6cf8ad6
--- /dev/null
+++ b/completions/_up
@@ -0,0 +1,74 @@
+#compdef up
+# zsh completion for eMerger
+
+_up() {
+ local -a opts
+ opts=(
+ '-h[show help]'
+ '--help[show help]'
+ '-V[show version]'
+ '--version[show version]'
+ '-i[interactive menu]'
+ '--interactive[interactive menu]'
+ '--doctor[environment health check]'
+ '-n[dry-run]'
+ '--dry-run[dry-run]'
+ '-v[verbose]'
+ '--verbose[verbose]'
+ '-q[quiet (repeat for more)]'
+ '-qq[quieter]'
+ '-qqq[quietest]'
+ '--quiet[quiet]'
+ '-y[assume yes]'
+ '--yes[assume yes]'
+ '--security[security only]'
+ '--firmware[include firmware]'
+ '--no-firmware[skip firmware]'
+ '--dev[include dev toolchains]'
+ '--parallel[parallel user-space managers]'
+ '--no-emoji[ASCII glyphs only]'
+ '--profile[load named profile]:profile:_up_profiles'
+ '--list-profiles[list profiles]'
+ '--snapshot[pre-update snapshot]'
+ '--refresh-mirrors[refresh mirrors]'
+ '--resume[skip completed managers]'
+ '--reboot[reboot if required]'
+ '-nl[no logo]'
+ '--no-logo[no logo]'
+ '-ni[no system info]'
+ '--no-info[no system info]'
+ '-nc[no cache clean]'
+ '--no-cache[no cache clean]'
+ '-nt[no trash clean]'
+ '--no-trash[no trash clean]'
+ '-w[weather]'
+ '--weather[weather]'
+ '--changed[show package diff]'
+ '--changelog[show changelog]:package'
+ '--history[run history]'
+ '--report[export markdown]:file:_files'
+ '-err[show errors]'
+ '--errors[show errors]'
+ '-up[self-update]'
+ '--self-update[self-update]'
+ '-au[install auto-update]'
+ '--auto-update[install auto-update]'
+ '-rc[rebuild cache]'
+ '--rebuild-cache[rebuild cache]'
+ )
+ _arguments -s $opts
+}
+
+_up_profiles() {
+ local -a p
+ local dir
+ for dir in "$HOME/.config/emerger/profiles.d" "${0:A:h}/../share/profiles"; do
+ [[ -d $dir ]] || continue
+ for f in "$dir"/*.sh; do
+ [[ -f $f ]] && p+=(${f:t:r})
+ done
+ done
+ _values profile $p
+}
+
+compdef _up up
diff --git a/completions/up.bash b/completions/up.bash
new file mode 100644
index 0000000..0fe1166
--- /dev/null
+++ b/completions/up.bash
@@ -0,0 +1,30 @@
+# bash completion for eMerger
+_up_completion() {
+ local cur prev opts profiles
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+ case "$prev" in
+ --profile)
+ profiles=$(for d in "$HOME/.config/emerger/profiles.d" "$(dirname "$(command -v up 2>/dev/null || echo)")/../share/profiles"; do
+ [ -d "$d" ] && for f in "$d"/*.sh; do [ -f "$f" ] && basename "$f" .sh; done
+ done | sort -u)
+ COMPREPLY=( $(compgen -W "$profiles" -- "$cur") )
+ return 0
+ ;;
+ --report)
+ COMPREPLY=( $(compgen -f -- "$cur") )
+ return 0
+ ;;
+ esac
+
+ opts="-h --help -V --version -i --interactive --doctor
+ -n --dry-run -v --verbose -q -qq -qqq --quiet -y --yes
+ --security --firmware --no-firmware --dev --parallel --no-emoji
+ --profile --list-profiles --snapshot --refresh-mirrors --resume --reboot
+ -nl --no-logo -ni --no-info -nc --no-cache -nt --no-trash -w --weather
+ --changed --changelog --history --report -err --errors
+ -up --self-update -au --auto-update -rc --rebuild-cache"
+ COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
+}
+complete -F _up_completion up
diff --git a/completions/up.fish b/completions/up.fish
new file mode 100644
index 0000000..3c8261e
--- /dev/null
+++ b/completions/up.fish
@@ -0,0 +1,38 @@
+# fish completion for eMerger
+function __up_profiles
+ for d in ~/.config/emerger/profiles.d (status dirname)/../share/profiles
+ test -d $d; and for f in $d/*.sh
+ basename $f .sh
+ end
+ end | sort -u
+end
+
+complete -c up -s h -l help -d 'show help'
+complete -c up -s V -l version -d 'show version'
+complete -c up -s i -l interactive -d 'interactive menu'
+complete -c up -l doctor -d 'environment health check'
+complete -c up -s n -l dry-run -d 'dry-run'
+complete -c up -s v -l verbose -d 'verbose output'
+complete -c up -s q -l quiet -d 'quieter output'
+complete -c up -s y -l yes -d 'assume yes'
+complete -c up -l security -d 'security updates only'
+complete -c up -l firmware -d 'include firmware'
+complete -c up -l no-firmware -d 'skip firmware'
+complete -c up -l dev -d 'include dev toolchains'
+complete -c up -l parallel -d 'parallel user-space'
+complete -c up -l no-emoji -d 'ASCII glyphs only'
+complete -c up -l profile -d 'load profile' -xa '(__up_profiles)'
+complete -c up -l list-profiles -d 'list profiles'
+complete -c up -l snapshot -d 'pre-update snapshot'
+complete -c up -l refresh-mirrors -d 'refresh mirrors'
+complete -c up -l resume -d 'resume interrupted run'
+complete -c up -l reboot -d 'reboot if required'
+complete -c up -s w -l weather -d 'weather line'
+complete -c up -l changed -d 'show package diff'
+complete -c up -l changelog -d 'show changelog' -x
+complete -c up -l history -d 'run history'
+complete -c up -l report -d 'export markdown' -r
+complete -c up -l errors -d 'show errors'
+complete -c up -l self-update -d 'update eMerger'
+complete -c up -l auto-update -d 'install auto-update'
+complete -c up -l rebuild-cache -d 'clear detection cache'
diff --git a/doc/documentation.pdf b/doc/documentation.pdf
index 3e458245a4867f4f65c4872589f1077c566929e8..5ee542f167df57fa980ef765722cc115343def83 100644
GIT binary patch
literal 217082
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