mud-git 1.1.8__tar.gz → 1.1.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. mud_git-1.1.9/.github/requirements-binary.txt +2 -0
  2. mud_git-1.1.9/.github/workflows/publish-aur.yaml +169 -0
  3. {mud_git-1.1.8 → mud_git-1.1.9}/AGENTS.md +17 -6
  4. {mud_git-1.1.8 → mud_git-1.1.9}/PKG-INFO +14 -12
  5. mud_git-1.1.9/PKGBUILD +21 -0
  6. {mud_git-1.1.8 → mud_git-1.1.9}/README.md +13 -11
  7. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/app.py +0 -1
  8. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/runner.py +7 -0
  9. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/settings.py +12 -8
  10. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/utils.py +0 -1
  11. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/PKG-INFO +14 -12
  12. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/SOURCES.txt +2 -0
  13. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/scm_file_list.json +2 -0
  14. mud_git-1.1.9/src/mud_git.egg-info/scm_version.json +8 -0
  15. {mud_git-1.1.8 → mud_git-1.1.9}/tests/helpers.py +8 -2
  16. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_completion.py +26 -3
  17. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_run.py +19 -0
  18. mud_git-1.1.9/tests/test_settings.py +79 -0
  19. mud_git-1.1.8/.github/workflows/publish-aur.yaml +0 -60
  20. mud_git-1.1.8/PKGBUILD +0 -37
  21. mud_git-1.1.8/src/mud_git.egg-info/scm_version.json +0 -8
  22. {mud_git-1.1.8 → mud_git-1.1.9}/.editorconfig +0 -0
  23. {mud_git-1.1.8 → mud_git-1.1.9}/.github/workflows/publish-pypi.yaml +0 -0
  24. {mud_git-1.1.8 → mud_git-1.1.9}/.github/workflows/test.yaml +0 -0
  25. {mud_git-1.1.8 → mud_git-1.1.9}/.gitignore +0 -0
  26. {mud_git-1.1.8 → mud_git-1.1.9}/LICENSE +0 -0
  27. {mud_git-1.1.8 → mud_git-1.1.9}/img.png +0 -0
  28. {mud_git-1.1.8 → mud_git-1.1.9}/pyproject.toml +0 -0
  29. {mud_git-1.1.8 → mud_git-1.1.9}/requirements.txt +0 -0
  30. {mud_git-1.1.8 → mud_git-1.1.9}/setup.cfg +0 -0
  31. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/__init__.py +0 -0
  32. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/__main__.py +0 -0
  33. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/commands.py +0 -0
  34. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/completion.py +0 -0
  35. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/config.py +0 -0
  36. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud/styles.py +0 -0
  37. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/dependency_links.txt +0 -0
  38. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/entry_points.txt +0 -0
  39. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/requires.txt +0 -0
  40. {mud_git-1.1.8 → mud_git-1.1.9}/src/mud_git.egg-info/top_level.txt +0 -0
  41. {mud_git-1.1.8 → mud_git-1.1.9}/tests/conftest.py +0 -0
  42. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_config.py +0 -0
  43. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_display.py +0 -0
  44. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_filters.py +0 -0
  45. {mud_git-1.1.8 → mud_git-1.1.9}/tests/test_states.py +0 -0
@@ -0,0 +1,2 @@
1
+ pyinstaller==6.22.3
2
+ pyinstaller-hooks-contrib==2026.7
@@ -0,0 +1,169 @@
1
+ name: Publish mud binary to AUR
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ tag:
9
+ description: "Published stable release tag (vX.Y.Z)"
10
+ required: true
11
+ type: string
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: publish-aur
18
+ cancel-in-progress: false
19
+
20
+ env:
21
+ RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }}
22
+
23
+ jobs:
24
+ build:
25
+ if: github.event_name == 'workflow_dispatch' || !github.event.release.prerelease
26
+ runs-on: ubuntu-22.04
27
+ outputs:
28
+ version: ${{ steps.release.outputs.version }}
29
+ steps:
30
+ - name: Validate release
31
+ id: release
32
+ env:
33
+ GH_TOKEN: ${{ github.token }}
34
+ run: |
35
+ [[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
36
+ stable=$(gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
37
+ --json isDraft,isPrerelease --jq '(.isDraft or .isPrerelease) | not')
38
+ [[ "$stable" == true ]]
39
+ echo "version=${RELEASE_TAG#v}" >> "$GITHUB_OUTPUT"
40
+
41
+ - name: Checkout release tag
42
+ uses: actions/checkout@v4
43
+ with:
44
+ ref: ${{ env.RELEASE_TAG }}
45
+ fetch-depth: 0
46
+
47
+ - name: Set up Python 3.13
48
+ uses: actions/setup-python@v5
49
+ with:
50
+ python-version: "3.13"
51
+
52
+ - name: Configure git
53
+ run: |
54
+ git config --global user.name "Test User"
55
+ git config --global user.email "test@example.com"
56
+
57
+ - name: Install dependencies and build wheel
58
+ run: |
59
+ python -m pip install build pytest -r .github/requirements-binary.txt
60
+ python -m build
61
+ python -m pip install dist/*.whl
62
+
63
+ - name: Test wheel
64
+ run: python -m pytest
65
+
66
+ - name: Build standalone executable
67
+ run: |
68
+ python -m PyInstaller --noconfirm --clean --onedir --name mud \
69
+ --distpath dist/binary --workpath build/pyinstaller --specpath build \
70
+ --collect-all pygit2 --hidden-import _cffi_backend \
71
+ --recursive-copy-metadata mud-git src/mud/__main__.py
72
+
73
+ - name: Test standalone executable
74
+ env:
75
+ MUD_EXECUTABLE: ${{ github.workspace }}/dist/binary/mud/mud
76
+ run: python -m pytest
77
+
78
+ - name: Prepare release archive and PKGBUILD
79
+ env:
80
+ VERSION: ${{ steps.release.outputs.version }}
81
+ run: |
82
+ mkdir -p dist/aur
83
+ install -m644 LICENSE dist/binary/LICENSE
84
+ archive="mud-${VERSION}-linux-x86_64.tar.gz"
85
+ tar -czf "dist/aur/$archive" -C dist/binary mud LICENSE
86
+ checksum=$(sha256sum "dist/aur/$archive" | cut -d ' ' -f 1)
87
+ sed -e "s/@VERSION@/$VERSION/" -e "s/@SHA256@/$checksum/" \
88
+ PKGBUILD > dist/aur/PKGBUILD
89
+
90
+ - uses: actions/upload-artifact@v4
91
+ with:
92
+ name: mud-aur
93
+ path: dist/aur/
94
+ if-no-files-found: error
95
+
96
+ test-package:
97
+ needs: build
98
+ runs-on: ubuntu-latest
99
+ container: archlinux:base-devel
100
+ steps:
101
+ - name: Install runtime dependencies
102
+ run: pacman -Syu --noconfirm git
103
+
104
+ - uses: actions/download-artifact@v4
105
+ with:
106
+ name: mud-aur
107
+ path: package
108
+
109
+ - name: Build and install Arch package
110
+ working-directory: package
111
+ run: |
112
+ useradd --create-home builder
113
+ chown -R builder:builder .
114
+ runuser -u builder -- makepkg --noconfirm
115
+ pacman -U --noconfirm mud-*.pkg.tar.zst
116
+
117
+ - name: Smoke test installed binary
118
+ shell: bash
119
+ run: |
120
+ HOME=$(mktemp -d)
121
+ export HOME
122
+ cd "$HOME"
123
+ mud completion carapace | grep -F 'mud'
124
+ test ! -e "$HOME/.config/mud/settings.ini"
125
+ mud --help
126
+ git init repo-a
127
+ git -C repo-a -c user.name=Test -c user.email=test@example.com \
128
+ commit --allow-empty -m Initial
129
+ mud init
130
+ mud status | grep -F 'repo-a'
131
+ mud -a -c='git rev-parse --is-inside-work-tree' | grep -F 'true'
132
+
133
+ publish:
134
+ needs: [build, test-package]
135
+ runs-on: ubuntu-latest
136
+ permissions:
137
+ contents: write
138
+ steps:
139
+ - uses: actions/download-artifact@v4
140
+ with:
141
+ name: mud-aur
142
+ path: package
143
+
144
+ - name: Upload binary to GitHub release
145
+ env:
146
+ GH_TOKEN: ${{ github.token }}
147
+ VERSION: ${{ needs.build.outputs.version }}
148
+ run: |
149
+ archive="mud-${VERSION}-linux-x86_64.tar.gz"
150
+ if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
151
+ --json assets --jq '.assets[].name' | grep -Fxq "$archive"; then
152
+ gh release download "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
153
+ --pattern "$archive" --dir "$RUNNER_TEMP/published"
154
+ cmp "package/$archive" "$RUNNER_TEMP/published/$archive"
155
+ else
156
+ gh release upload "$RELEASE_TAG" "package/$archive" --repo "$GITHUB_REPOSITORY"
157
+ fi
158
+
159
+ - name: Publish AUR package
160
+ uses: KSXGitHub/github-actions-deploy-aur@v4.1.2
161
+ with:
162
+ pkgname: mud
163
+ pkgbuild: ./package/PKGBUILD
164
+ test: true
165
+ commit_username: ${{ secrets.AUR_USERNAME }}
166
+ commit_email: ${{ secrets.AUR_EMAIL }}
167
+ ssh_private_key: ${{ secrets.AUR_SSH_KEY }}
168
+ commit_message: "Update mud to version ${{ needs.build.outputs.version }}"
169
+ ssh_keyscan_types: rsa,ecdsa,ed25519
@@ -15,6 +15,12 @@ pytest # run tests (verbose by default)
15
15
  pytest tests/test_run.py # run a single file
16
16
  ```
17
17
 
18
+ ## Binary releases and AUR
19
+
20
+ `.github/workflows/publish-aur.yaml` builds stable `vX.Y.Z` releases, with an explicit published tag required for manual runs. It checks out that exact tag, tests the wheel, freezes an x86_64 executable with PyInstaller on Ubuntu 22.04, and reruns the CLI tests against the executable. Build tools are pinned in `.github/requirements-binary.txt`.
21
+
22
+ The workflow fills `@VERSION@` and `@SHA256@` in the root `PKGBUILD` template, tests the package in Arch Linux, uploads `mud-X.Y.Z-linux-x86_64.tar.gz` to the release, then publishes `mud` and generated `.SRCINFO` to AUR using `AUR_USERNAME`, `AUR_EMAIL`, and `AUR_SSH_KEY`. Published assets are immutable; retry failed jobs with the original artifact. The package installs the bundled runtime under `/opt/mud` and links `/usr/bin/mud`, with no end-user Python build. `mud-git` is a provided/conflicting legacy AUR package; its listing is retired by requesting an AUR merge after `mud` is published. The PyPI distribution is still named `mud-git`.
23
+
18
24
  ## Entry point
19
25
 
20
26
  `mud` CLI → `mud:run` in `src/mud/__init__.py` → `App` in `src/mud/app.py`; `mud completion` is dispatched to `completion.complete()` before writable settings are initialised.
@@ -28,15 +34,17 @@ pytest tests/test_run.py # run a single file
28
34
  | `src/mud/completion.py` | Exports the Carapace spec and provides read-only dynamic completion via `C_ARG<n>` / `C_VALUE` |
29
35
  | `src/mud/runner.py` | All display commands and execution modes |
30
36
  | `src/mud/config.py` | `.mudconfig` TSV read/write; `init`, `add`, `remove`, `prune` |
31
- | `src/mud/settings.py` | `~/.config/mud/settings.ini` read/write; read-only initialisation for completion |
37
+ | `src/mud/settings.py` | `~/.config/mud/settings.ini` read/write; legacy settings migration; read-only initialisation for completion |
32
38
  | `src/mud/commands.py` | Constants for every command name and filter flag prefix |
33
39
  | `src/mud/styles.py` | ANSI escape codes and Nerd Font glyphs |
34
- | `src/mud/utils.py` | Shared helpers: table creation, error printing, configure wizard |
40
+ | `src/mud/utils.py` | Shared helpers: table creation, error printing, configure wizard, help banner (independent of source-file paths for frozen builds) |
35
41
 
36
42
  ## Architecture notes
37
43
 
38
44
  **Global settings instance** — `utils.settings` is a single `Settings` object created in `__init__.run()` and accessed across all modules.
39
45
 
46
+ **Settings location** — All settings writes target `~/.config/mud/settings.ini`; mud never creates `~/.mudsettings`. An existing modern file takes precedence and leaves the legacy file untouched; otherwise normal startup moves the legacy file to the modern location, preserving its contents, or creates defaults at the modern location if neither file exists. The legacy file is removed only after a successful move. Completion can read legacy settings as a fallback but never migrates them. Ordinary package imports and builds do not initialise settings.
47
+
40
48
  **Command dispatch** — `App.run()` routes to either a native `Runner` method (matched against constants in `commands.py`) or a shell pass-through. The `--` separator and `-c=<cmd>` flag both reach the shell path.
41
49
 
42
50
  **Carapace completion** — `mud completion carapace` exports a shell-independent spec; its fixed `mud completion values` callback handles mud's equals-only flags without executing user input. Command/flag descriptions come from the argparse definitions, aliases from settings, and label/path/branch values from the discovered config. Local and remote branch names reuse `Runner._get_unique_branch_names()`. Nothing is completed after `--`, inside `-c=`, or in arbitrary shell/alias arguments. Filters remain available after a completed `-c=` token. Neither spec export nor completion creates settings files.
@@ -45,24 +53,27 @@ pytest tests/test_run.py # run a single file
45
53
 
46
54
  **Execution modes** — three modes controlled by `run_async` + `run_table` settings (toggled by `-a` / `-t` flags): sequential, async streamed, async live-table.
47
55
 
56
+ **Frozen subprocesses** — `Runner` restores the original `LD_LIBRARY_PATH` (or removes it if originally unset) in the child-command environment when running under PyInstaller, so Git and arbitrary shell commands use system libraries rather than the bundled runtime.
57
+
48
58
  **Filter chain** — `App._filter_with_arguments()` applies up to nine filters in sequence (ignore label, include/exclude label, include/exclude branch, include/exclude name substring, modified, diverged). Each step removes non-matching repos. Repeated `-N=` / `--not-name=` values exclude any matching path substring; empty exclusions are ignored.
49
59
 
50
60
  **Nerd Fonts** — every glyph in `styles.GLYPHS` has an ASCII fallback. `utils.glyphs(key)` selects between them based on the `nerd_fonts` setting, so mud works with or without a patched font.
51
61
 
52
62
  ## Tests
53
63
 
54
- Tests are black-box CLI tests — each runs `python -m mud` as a subprocess against real git repos in a temporary directory.
64
+ Tests are black-box CLI tests — each runs `python -m mud` as a subprocess against real git repos in a temporary directory. Set `MUD_EXECUTABLE` to an absolute executable path to run CLI and completion tests against a frozen binary instead; import-only checks still use the Python environment.
55
65
 
56
66
  | File | Covers |
57
67
  |---|---|
58
68
  | `tests/test_config.py` | `init`, `add`, `remove`, `prune` |
69
+ | `tests/test_settings.py` | Import side effects, first-launch settings location, legacy moves and migration failures, modern-file precedence, and settings save destination |
59
70
  | `tests/test_display.py` | `status`, `info`, `log`, `labels`, `branches`, `tags` |
60
- | `tests/test_run.py` | Execution modes and flags |
71
+ | `tests/test_run.py` | Execution modes, flags, and preservation of the external-command library path in frozen builds |
61
72
  | `tests/test_filters.py` | `-l=`, `-L=`, `-b=`, `-B=`, `-n=`, `-N=` filter flags and native-command parsing regressions |
62
- | `tests/test_completion.py` | Completion callback, dynamic values, command boundaries, read-only discovery, and optional real Carapace/Nushell integration |
73
+ | `tests/test_completion.py` | Completion callback, dynamic values, command boundaries, read-only settings precedence/discovery, and optional real Carapace/Nushell integration |
63
74
  | `tests/test_states.py` | Edge-case repo states (unborn, detached, rebasing) |
64
75
 
65
- Carapace integration tests run when `carapace` is on `PATH`; the Nushell round-trip test also requires `nu`. Tests isolate `HOME`, Carapace config/cache directories, and use the current Python environment's `mud` executable.
76
+ Carapace integration tests run when `carapace` is on `PATH`; the Nushell round-trip test also requires `nu`. Tests isolate `HOME`, Carapace config/cache directories, and use `MUD_EXECUTABLE` or the current Python environment's `mud` executable.
66
77
 
67
78
  ## Knowledge base update rule
68
79
  After editing any file under `src/mud/`, update the affected sections of this file before finishing the task.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mud-git
3
- Version: 1.1.8
3
+ Version: 1.1.9
4
4
  Summary: Multi repository git utility. Manage multiple git-repositories simultaneously.
5
5
  Author-email: Jasur Sadikov <jasur@sadikoff.com>
6
6
  License-Expression: MIT
@@ -18,7 +18,7 @@ Dynamic: license-file
18
18
  # mud
19
19
 
20
20
  ![Version](https://img.shields.io/pypi/v/mud-git?logo=python)
21
- ![AUR Version](https://img.shields.io/aur/version/mud-git?logo=archlinux)
21
+ ![AUR Version](https://img.shields.io/aur/version/mud?logo=archlinux)
22
22
  [![Test projects integrity](https://github.com/jasursadikov/mud/actions/workflows/test.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/test.yaml)
23
23
  [![Publish Python Package](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml)
24
24
  [![Publish to AUR](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml)
@@ -28,14 +28,16 @@ Dynamic: license-file
28
28
  mud is CLI utility that allows you to run git commands in multiple repositories. It has multiple powerful filtering tools, native commands with an informative terminal output and support of aliasing. This tool is not limited to git commands only; you can run any commands you wish. However, this tool was primarily designed to be used with git, so each referenced directory should have a `.git` directory.
29
29
 
30
30
  ## Installing
31
- **PyPI**
32
- ```bash
33
- pip install mud-git
34
- ```
35
- **ArchLinux**
36
- ```bash
37
- yay -S mud-git
38
- ```
31
+ | Distribution | Installation |
32
+ |--------------|--------------|
33
+ | PyPI | `pip install mud-git` |
34
+ | Arch Linux (x86_64) | `yay -S mud` installs the prebuilt release executable with its bundled Python runtime and libraries. |
35
+ | Migrate from AUR `mud-git` | Run `yay -S mud` and accept removal of the conflicting `mud-git` package. Existing mud settings and repository configurations are preserved. |
36
+ | Linux binary (x86_64) | Download `mud-X.Y.Z-linux-x86_64.tar.gz` from [GitHub Releases](https://github.com/jasursadikov/mud/releases), extract it, and run `mud/mud`; keep its `_internal` directory beside the executable. Requires Git, glibc 2.35 or newer, and zlib. |
37
+ | AUR release automation | Publish a stable `vX.Y.Z` GitHub release, or run **Publish mud binary to AUR** with its published release tag. CI tests the wheel and frozen executable, tests installation on Arch Linux, uploads the binary, and publishes `mud` with a SHA-256 checksum. |
38
+ | AUR credentials | Configure repository secrets `AUR_USERNAME`, `AUR_EMAIL`, and `AUR_SSH_KEY`; the key must belong to an AUR account allowed to publish `mud`. GitHub release uploads use the workflow's automatic token. |
39
+ | Retire the old AUR listing | After the first successful `mud` publication, request that AUR merge `mud-git` into `mud`. New releases publish only to `mud`. |
40
+ | Retry AUR publication | Re-run failed jobs to reuse the tested artifact. Existing release binaries are never overwritten; rebuilding a published binary requires a new release version. |
39
41
 
40
42
  For requirements check [requirements.txt](requirements.txt).
41
43
 
@@ -66,9 +68,9 @@ mud --diverged git pull
66
68
  | Command | Description |
67
69
  |---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
68
70
  | `mud init` | creates `.mudconfig` and adds repositories beneath the current directory. |
69
- | `mud configure`/`mud config` | runs the interactive settings wizard. |
71
+ | `mud configure`/`mud config` | runs the interactive settings wizard, saving only to `~/.config/mud/settings.ini`. If the modern file is missing, normal startup moves `~/.mudsettings` there or creates defaults if neither exists. An existing modern file takes precedence and leaves the legacy file untouched; mud never creates `~/.mudsettings`. |
70
72
  | `mud help`/`mud --help`/`mud -h` | displays available commands and flags. |
71
- | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory. |
73
+ | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory; saves to `~/.config/mud/settings.ini`. |
72
74
  | `mud get-config` | prints the current `.mudconfig` location. |
73
75
  | `mud prune` | removes all invalid repositories from the `.mudconfig`. |
74
76
  | `mud info`/`mud i` | displays branch divergence and working directory changes. |
mud_git-1.1.9/PKGBUILD ADDED
@@ -0,0 +1,21 @@
1
+ # Maintainer: Jasur Sadikov <jasur@sadikoff.com>
2
+ pkgname=mud
3
+ pkgver=@VERSION@
4
+ pkgrel=1
5
+ pkgdesc="Multi repository git utility. Manage multiple git-repositories simultaneously."
6
+ arch=('x86_64')
7
+ url="https://github.com/jasursadikov/mud"
8
+ license=('MIT')
9
+ provides=("mud-git=$pkgver")
10
+ conflicts=('mud-git')
11
+ depends=('git' 'glibc' 'zlib')
12
+ options=('!strip')
13
+ source=("${url}/releases/download/v${pkgver}/mud-${pkgver}-linux-x86_64.tar.gz")
14
+ sha256sums=('@SHA256@')
15
+
16
+ package() {
17
+ install -d "$pkgdir/opt" "$pkgdir/usr/bin"
18
+ cp -a "$srcdir/mud" "$pkgdir/opt/mud"
19
+ ln -s /opt/mud/mud "$pkgdir/usr/bin/mud"
20
+ install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
21
+ }
@@ -1,7 +1,7 @@
1
1
  # mud
2
2
 
3
3
  ![Version](https://img.shields.io/pypi/v/mud-git?logo=python)
4
- ![AUR Version](https://img.shields.io/aur/version/mud-git?logo=archlinux)
4
+ ![AUR Version](https://img.shields.io/aur/version/mud?logo=archlinux)
5
5
  [![Test projects integrity](https://github.com/jasursadikov/mud/actions/workflows/test.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/test.yaml)
6
6
  [![Publish Python Package](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml)
7
7
  [![Publish to AUR](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml)
@@ -11,14 +11,16 @@
11
11
  mud is CLI utility that allows you to run git commands in multiple repositories. It has multiple powerful filtering tools, native commands with an informative terminal output and support of aliasing. This tool is not limited to git commands only; you can run any commands you wish. However, this tool was primarily designed to be used with git, so each referenced directory should have a `.git` directory.
12
12
 
13
13
  ## Installing
14
- **PyPI**
15
- ```bash
16
- pip install mud-git
17
- ```
18
- **ArchLinux**
19
- ```bash
20
- yay -S mud-git
21
- ```
14
+ | Distribution | Installation |
15
+ |--------------|--------------|
16
+ | PyPI | `pip install mud-git` |
17
+ | Arch Linux (x86_64) | `yay -S mud` installs the prebuilt release executable with its bundled Python runtime and libraries. |
18
+ | Migrate from AUR `mud-git` | Run `yay -S mud` and accept removal of the conflicting `mud-git` package. Existing mud settings and repository configurations are preserved. |
19
+ | Linux binary (x86_64) | Download `mud-X.Y.Z-linux-x86_64.tar.gz` from [GitHub Releases](https://github.com/jasursadikov/mud/releases), extract it, and run `mud/mud`; keep its `_internal` directory beside the executable. Requires Git, glibc 2.35 or newer, and zlib. |
20
+ | AUR release automation | Publish a stable `vX.Y.Z` GitHub release, or run **Publish mud binary to AUR** with its published release tag. CI tests the wheel and frozen executable, tests installation on Arch Linux, uploads the binary, and publishes `mud` with a SHA-256 checksum. |
21
+ | AUR credentials | Configure repository secrets `AUR_USERNAME`, `AUR_EMAIL`, and `AUR_SSH_KEY`; the key must belong to an AUR account allowed to publish `mud`. GitHub release uploads use the workflow's automatic token. |
22
+ | Retire the old AUR listing | After the first successful `mud` publication, request that AUR merge `mud-git` into `mud`. New releases publish only to `mud`. |
23
+ | Retry AUR publication | Re-run failed jobs to reuse the tested artifact. Existing release binaries are never overwritten; rebuilding a published binary requires a new release version. |
22
24
 
23
25
  For requirements check [requirements.txt](requirements.txt).
24
26
 
@@ -49,9 +51,9 @@ mud --diverged git pull
49
51
  | Command | Description |
50
52
  |---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
51
53
  | `mud init` | creates `.mudconfig` and adds repositories beneath the current directory. |
52
- | `mud configure`/`mud config` | runs the interactive settings wizard. |
54
+ | `mud configure`/`mud config` | runs the interactive settings wizard, saving only to `~/.config/mud/settings.ini`. If the modern file is missing, normal startup moves `~/.mudsettings` there or creates defaults if neither exists. An existing modern file takes precedence and leaves the legacy file untouched; mud never creates `~/.mudsettings`. |
53
55
  | `mud help`/`mud --help`/`mud -h` | displays available commands and flags. |
54
- | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory. |
56
+ | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory; saves to `~/.config/mud/settings.ini`. |
55
57
  | `mud get-config` | prints the current `.mudconfig` location. |
56
58
  | `mud prune` | removes all invalid repositories from the `.mudconfig`. |
57
59
  | `mud info`/`mud i` | displays branch divergence and working directory changes. |
@@ -91,7 +91,6 @@ class App:
91
91
  print()
92
92
  self.parser.print_help()
93
93
  return
94
- # Sets global repository in .mudsettings
95
94
  if sys.argv[1] in SET_GLOBAL:
96
95
  if len(sys.argv) > 2:
97
96
  config_path = sys.argv[2]
@@ -22,6 +22,13 @@ class Runner:
22
22
 
23
23
  def __init__(self, repos):
24
24
  self._force_color_env = self._force_color_env | os.environ.copy()
25
+ if getattr(sys, 'frozen', False):
26
+ # PyInstaller's bundled libraries must not override system command libraries.
27
+ library_path = self._force_color_env.pop('LD_LIBRARY_PATH_ORIG', None)
28
+ if library_path is None:
29
+ self._force_color_env.pop('LD_LIBRARY_PATH', None)
30
+ else:
31
+ self._force_color_env['LD_LIBRARY_PATH'] = library_path
25
32
  self._printed_lines_count = 0
26
33
  self.repos = repos
27
34
 
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import shutil
2
3
  import configparser
3
4
 
4
5
  MAIN_SCOPE = 'mud'
@@ -7,14 +8,11 @@ ALIAS_SCOPE = 'alias'
7
8
 
8
9
  class Settings:
9
10
  def __init__(self, file_name: str, old_file_name: str, read_only: bool = False) -> None:
10
- use_old = os.path.exists(os.path.join(os.path.expanduser('~'), old_file_name))
11
- file_name = old_file_name if use_old else file_name
12
- directory = os.path.expanduser('~' if use_old else '~/.config/mud')
13
-
14
11
  self.mud_settings = None
15
12
  self.alias_settings = None
16
13
  self.config = configparser.ConfigParser()
17
- self.settings_file = os.path.join(directory, file_name)
14
+ self.settings_file = os.path.join(os.path.expanduser('~/.config/mud'), file_name)
15
+ self.old_settings_file = os.path.join(os.path.expanduser('~'), old_file_name)
18
16
  self.read_only = read_only
19
17
  self.defaults = {
20
18
  'mud': {
@@ -38,9 +36,15 @@ class Settings:
38
36
 
39
37
  def load_settings(self) -> None:
40
38
  if not os.path.exists(self.settings_file):
41
- self.config.read_dict(self.defaults)
42
- if not self.read_only:
43
- self.save()
39
+ if os.path.exists(self.old_settings_file):
40
+ self.config.read(self.old_settings_file)
41
+ if not self.read_only:
42
+ os.makedirs(os.path.dirname(self.settings_file), exist_ok=True)
43
+ shutil.move(self.old_settings_file, self.settings_file)
44
+ else:
45
+ self.config.read_dict(self.defaults)
46
+ if not self.read_only:
47
+ self.save()
44
48
  else:
45
49
  self.config.read(self.settings_file)
46
50
 
@@ -21,7 +21,6 @@ def glyphs(key: str) -> str:
21
21
 
22
22
 
23
23
  def info() -> None:
24
- os.chdir(os.path.dirname(os.path.abspath(__file__)))
25
24
  colors = TEXT[3:]
26
25
  colors.remove(BRIGHT_WHITE)
27
26
  m = random.choice(colors)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mud-git
3
- Version: 1.1.8
3
+ Version: 1.1.9
4
4
  Summary: Multi repository git utility. Manage multiple git-repositories simultaneously.
5
5
  Author-email: Jasur Sadikov <jasur@sadikoff.com>
6
6
  License-Expression: MIT
@@ -18,7 +18,7 @@ Dynamic: license-file
18
18
  # mud
19
19
 
20
20
  ![Version](https://img.shields.io/pypi/v/mud-git?logo=python)
21
- ![AUR Version](https://img.shields.io/aur/version/mud-git?logo=archlinux)
21
+ ![AUR Version](https://img.shields.io/aur/version/mud?logo=archlinux)
22
22
  [![Test projects integrity](https://github.com/jasursadikov/mud/actions/workflows/test.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/test.yaml)
23
23
  [![Publish Python Package](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-pypi.yaml)
24
24
  [![Publish to AUR](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml/badge.svg)](https://github.com/jasursadikov/mud/actions/workflows/publish-aur.yaml)
@@ -28,14 +28,16 @@ Dynamic: license-file
28
28
  mud is CLI utility that allows you to run git commands in multiple repositories. It has multiple powerful filtering tools, native commands with an informative terminal output and support of aliasing. This tool is not limited to git commands only; you can run any commands you wish. However, this tool was primarily designed to be used with git, so each referenced directory should have a `.git` directory.
29
29
 
30
30
  ## Installing
31
- **PyPI**
32
- ```bash
33
- pip install mud-git
34
- ```
35
- **ArchLinux**
36
- ```bash
37
- yay -S mud-git
38
- ```
31
+ | Distribution | Installation |
32
+ |--------------|--------------|
33
+ | PyPI | `pip install mud-git` |
34
+ | Arch Linux (x86_64) | `yay -S mud` installs the prebuilt release executable with its bundled Python runtime and libraries. |
35
+ | Migrate from AUR `mud-git` | Run `yay -S mud` and accept removal of the conflicting `mud-git` package. Existing mud settings and repository configurations are preserved. |
36
+ | Linux binary (x86_64) | Download `mud-X.Y.Z-linux-x86_64.tar.gz` from [GitHub Releases](https://github.com/jasursadikov/mud/releases), extract it, and run `mud/mud`; keep its `_internal` directory beside the executable. Requires Git, glibc 2.35 or newer, and zlib. |
37
+ | AUR release automation | Publish a stable `vX.Y.Z` GitHub release, or run **Publish mud binary to AUR** with its published release tag. CI tests the wheel and frozen executable, tests installation on Arch Linux, uploads the binary, and publishes `mud` with a SHA-256 checksum. |
38
+ | AUR credentials | Configure repository secrets `AUR_USERNAME`, `AUR_EMAIL`, and `AUR_SSH_KEY`; the key must belong to an AUR account allowed to publish `mud`. GitHub release uploads use the workflow's automatic token. |
39
+ | Retire the old AUR listing | After the first successful `mud` publication, request that AUR merge `mud-git` into `mud`. New releases publish only to `mud`. |
40
+ | Retry AUR publication | Re-run failed jobs to reuse the tested artifact. Existing release binaries are never overwritten; rebuilding a published binary requires a new release version. |
39
41
 
40
42
  For requirements check [requirements.txt](requirements.txt).
41
43
 
@@ -66,9 +68,9 @@ mud --diverged git pull
66
68
  | Command | Description |
67
69
  |---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
68
70
  | `mud init` | creates `.mudconfig` and adds repositories beneath the current directory. |
69
- | `mud configure`/`mud config` | runs the interactive settings wizard. |
71
+ | `mud configure`/`mud config` | runs the interactive settings wizard, saving only to `~/.config/mud/settings.ini`. If the modern file is missing, normal startup moves `~/.mudsettings` there or creates defaults if neither exists. An existing modern file takes precedence and leaves the legacy file untouched; mud never creates `~/.mudsettings`. |
70
72
  | `mud help`/`mud --help`/`mud -h` | displays available commands and flags. |
71
- | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory. |
73
+ | `mud set-global [path]` | sets the current `.mudconfig`, or the specified configuration path, as the fallback configuration to run from any directory; saves to `~/.config/mud/settings.ini`. |
72
74
  | `mud get-config` | prints the current `.mudconfig` location. |
73
75
  | `mud prune` | removes all invalid repositories from the `.mudconfig`. |
74
76
  | `mud info`/`mud i` | displays branch divergence and working directory changes. |
@@ -7,6 +7,7 @@ README.md
7
7
  img.png
8
8
  pyproject.toml
9
9
  requirements.txt
10
+ .github/requirements-binary.txt
10
11
  .github/workflows/publish-aur.yaml
11
12
  .github/workflows/publish-pypi.yaml
12
13
  .github/workflows/test.yaml
@@ -35,4 +36,5 @@ tests/test_config.py
35
36
  tests/test_display.py
36
37
  tests/test_filters.py
37
38
  tests/test_run.py
39
+ tests/test_settings.py
38
40
  tests/test_states.py
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "files": [
3
3
  ".editorconfig",
4
+ ".github/requirements-binary.txt",
4
5
  ".github/workflows/publish-aur.yaml",
5
6
  ".github/workflows/publish-pypi.yaml",
6
7
  ".github/workflows/test.yaml",
@@ -29,6 +30,7 @@
29
30
  "tests/test_display.py",
30
31
  "tests/test_filters.py",
31
32
  "tests/test_run.py",
33
+ "tests/test_settings.py",
32
34
  "tests/test_states.py"
33
35
  ]
34
36
  }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.1.9",
3
+ "distance": 0,
4
+ "node": "gdb4b5e4fd8c581ed715cd599c29bb49187a9ef89",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-22"
8
+ }
@@ -85,8 +85,14 @@ def make_rebasing_repo(path: Path) -> None:
85
85
  # CLI runner
86
86
  # ---------------------------------------------------------------------------
87
87
 
88
+ def mud_command(*args: str) -> list[str]:
89
+ executable = os.environ.get('MUD_EXECUTABLE')
90
+ command = [executable] if executable else [sys.executable, '-m', 'mud']
91
+ return [*command, *args]
92
+
93
+
88
94
  def run_mud(*args: str, cwd: Path, home: Path) -> subprocess.CompletedProcess:
89
- """Run ``python -m mud <args>`` inside *cwd* and return the result.
95
+ """Run mud inside *cwd*, using MUD_EXECUTABLE when set.
90
96
 
91
97
  HOME is pointed at an empty temp directory so the subprocess gets
92
98
  clean default mud settings, isolated from the developer's own machine.
@@ -94,7 +100,7 @@ def run_mud(*args: str, cwd: Path, home: Path) -> subprocess.CompletedProcess:
94
100
  env = os.environ.copy()
95
101
  env["HOME"] = str(home)
96
102
  return subprocess.run(
97
- [sys.executable, "-m", "mud", *args],
103
+ mud_command(*args),
98
104
  cwd=cwd,
99
105
  capture_output=True,
100
106
  text=True,
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
 
8
8
  import pytest
9
9
 
10
- from helpers import make_detached_repo, make_empty_repo, make_git_repo, run_mud
10
+ from helpers import make_detached_repo, make_empty_repo, make_git_repo, mud_command, run_mud
11
11
 
12
12
 
13
13
  @pytest.fixture
@@ -18,7 +18,7 @@ def complete(repos_labeled: Path, home: Path):
18
18
  env['C_VALUE'] = arguments[-1]
19
19
  env.update({f'C_ARG{index}': argument for index, argument in enumerate(arguments[:-1])})
20
20
  result = subprocess.run(
21
- [sys.executable, '-m', 'mud', 'completion', 'values'],
21
+ mud_command('completion', 'values'),
22
22
  cwd=cwd, env=env, capture_output=True, text=True, check=True,
23
23
  )
24
24
  assert result.stderr == ''
@@ -101,6 +101,7 @@ def test_native_positionals(complete, repos_labeled: Path):
101
101
  def test_read_only_discovery(complete, repos_labeled: Path, home: Path, tmp_path_factory):
102
102
  assert complete('-l=', cwd=repos_labeled / 'repo_a') == ['-l=label_a', '-l=label_b']
103
103
  assert not (home / '.config').exists()
104
+ assert not (home / '.mudsettings').exists()
104
105
  settings = home / '.config' / 'mud' / 'settings.ini'
105
106
  settings.parent.mkdir(parents=True)
106
107
  settings.write_text(f'[mud]\nconfig_path = {repos_labeled / ".mudconfig"}\n[alias]\nto = git checkout\n')
@@ -108,6 +109,27 @@ def test_read_only_discovery(complete, repos_labeled: Path, home: Path, tmp_path
108
109
  assert 'to' in complete('')
109
110
 
110
111
 
112
+ @pytest.mark.parametrize('modern_exists', [False, True])
113
+ def test_settings_precedence_without_migration(complete, home: Path, modern_exists):
114
+ legacy = home / '.mudsettings'
115
+ legacy_contents = '[mud]\n[alias]\nlegacy = git status\n'
116
+ legacy.write_text(legacy_contents)
117
+ modern = home / '.config' / 'mud' / 'settings.ini'
118
+ modern_contents = '[mud]\n[alias]\nmodern = git diff\n'
119
+ if modern_exists:
120
+ modern.parent.mkdir(parents=True)
121
+ modern.write_text(modern_contents)
122
+
123
+ values = complete('')
124
+ assert ('modern' in values) == modern_exists
125
+ assert ('legacy' in values) != modern_exists
126
+ assert legacy.read_text() == legacy_contents
127
+ if modern_exists:
128
+ assert modern.read_text() == modern_contents
129
+ else:
130
+ assert not (home / '.config').exists()
131
+
132
+
111
133
  def test_invalid_and_empty_configs(complete, repos_labeled: Path, home: Path):
112
134
  config = repos_labeled / '.mudconfig'
113
135
  config.unlink()
@@ -135,6 +157,7 @@ def carapace(repos_labeled: Path, home: Path):
135
157
  spec = run_mud('completion', 'carapace', cwd=home, home=home)
136
158
  assert spec.returncode == 0, spec.stderr
137
159
  assert not (home / '.config').exists()
160
+ assert not (home / '.mudsettings').exists()
138
161
  spec_directory = home / '.config' / 'carapace' / 'specs'
139
162
  spec_directory.mkdir(parents=True)
140
163
  (spec_directory / 'mud.yaml').write_text(spec.stdout)
@@ -142,7 +165,7 @@ def carapace(repos_labeled: Path, home: Path):
142
165
  env.update({
143
166
  'HOME': str(home), 'XDG_CONFIG_HOME': str(home / '.config'),
144
167
  'XDG_CACHE_HOME': str(home / '.cache'), 'CARAPACE_BRIDGES': '',
145
- 'PATH': str(Path(sys.executable).parent) + os.pathsep + env['PATH'],
168
+ 'PATH': str(Path(mud_command()[0]).parent) + os.pathsep + env['PATH'],
146
169
  })
147
170
 
148
171
  def invoke(*arguments, shell='export'):
@@ -11,6 +11,9 @@ Default settings have both enabled, so:
11
11
  We test that all modes exit 0 and that the command actually ran in each repo.
12
12
  """
13
13
  from pathlib import Path
14
+
15
+ import pytest
16
+
14
17
  from helpers import run_mud
15
18
 
16
19
 
@@ -53,3 +56,19 @@ def test_run_command_runs_in_every_repo(repos: Path, home: Path):
53
56
  result = run_mud("-a", "echo", "hello", cwd=repos, home=home)
54
57
  # "hello" appears at least once per repo (the header also echoes the command name)
55
58
  assert result.stdout.count("hello") >= 2
59
+
60
+
61
+ @pytest.mark.parametrize('flags', [('-a',), ('-t',), ()])
62
+ @pytest.mark.parametrize('library_path', [None, '', '/external/libraries'])
63
+ def test_run_preserves_library_path(repos: Path, home: Path, monkeypatch, flags, library_path):
64
+ monkeypatch.delenv('LD_LIBRARY_PATH_ORIG', raising=False)
65
+ if library_path is None:
66
+ monkeypatch.delenv('LD_LIBRARY_PATH', raising=False)
67
+ else:
68
+ monkeypatch.setenv('LD_LIBRARY_PATH', library_path)
69
+ result = run_mud(
70
+ *flags, '-c=printf %s "${LD_LIBRARY_PATH-}" > library-path', cwd=repos, home=home,
71
+ )
72
+ assert result.returncode == 0, result.stderr
73
+ for name in ['repo_a', 'repo_b']:
74
+ assert (repos / name / 'library-path').read_text() == (library_path or '')
@@ -0,0 +1,79 @@
1
+ import configparser
2
+ import os
3
+ import subprocess
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ from helpers import run_mud
8
+
9
+
10
+ def test_import_does_not_create_settings(home: Path):
11
+ result = subprocess.run(
12
+ [sys.executable, '-c', 'import mud'], cwd=home,
13
+ env={**os.environ, 'HOME': str(home)}, capture_output=True, text=True,
14
+ )
15
+ assert result.returncode == 0, result.stderr
16
+ assert list(home.iterdir()) == []
17
+
18
+
19
+ def test_first_launch_creates_modern_settings(home: Path):
20
+ result = run_mud(cwd=home, home=home)
21
+ assert result.returncode == 0, result.stderr
22
+ settings = configparser.ConfigParser()
23
+ assert settings.read(home / '.config' / 'mud' / 'settings.ini')
24
+ assert settings.getboolean('mud', 'run_async') is True
25
+ assert settings['alias']['fetch'] == 'git fetch'
26
+ assert not (home / '.mudsettings').exists()
27
+ assert not (home / '.mudsetting').exists()
28
+
29
+
30
+ def test_legacy_settings_move_on_launch(home: Path, tmp_path: Path):
31
+ config = tmp_path / '.mudconfig'
32
+ config.write_text('')
33
+ legacy = home / '.mudsettings'
34
+ contents = f'# Personal settings\n[mud]\nconfig_path = {config}\nrun_async = False\n[alias]\ncustom = git status\n'
35
+ legacy.write_text(contents)
36
+
37
+ result = run_mud('get-config', cwd=home, home=home)
38
+ assert result.returncode == 0, result.stderr
39
+ assert result.stdout.strip() == str(config)
40
+ modern = home / '.config' / 'mud' / 'settings.ini'
41
+ assert modern.read_text() == contents
42
+ settings = configparser.ConfigParser()
43
+ assert settings.read(modern)
44
+ assert settings['mud']['config_path'] == str(config)
45
+ assert settings.getboolean('mud', 'run_async') is False
46
+ assert settings['alias']['custom'] == 'git status'
47
+ assert not legacy.exists()
48
+
49
+
50
+ def test_failed_migration_preserves_legacy_settings(home: Path):
51
+ legacy = home / '.mudsettings'
52
+ contents = '[mud]\nrun_async = False\n[alias]\ncustom = git status\n'
53
+ legacy.write_text(contents)
54
+ (home / '.config').write_text('not a directory\n')
55
+
56
+ result = run_mud('help', cwd=home, home=home)
57
+ assert result.returncode != 0
58
+ assert legacy.read_text() == contents
59
+ assert not (home / '.config' / 'mud' / 'settings.ini').exists()
60
+
61
+
62
+ def test_modern_settings_take_precedence_and_receive_updates(home: Path, tmp_path: Path):
63
+ config = tmp_path / '.mudconfig'
64
+ config.write_text('')
65
+ legacy = home / '.mudsettings'
66
+ contents = '[mud]\nrun_async = True\n[alias]\ncustom = git status\n'
67
+ legacy.write_text(contents)
68
+ modern = home / '.config' / 'mud' / 'settings.ini'
69
+ modern.parent.mkdir(parents=True)
70
+ modern.write_text('[mud]\nrun_async = False\n[alias]\ncustom = git diff\n')
71
+
72
+ result = run_mud('set-global', str(config), cwd=home, home=home)
73
+ assert result.returncode == 0, result.stderr
74
+ settings = configparser.ConfigParser()
75
+ settings.read(modern)
76
+ assert settings['mud']['config_path'] == str(config)
77
+ assert settings.getboolean('mud', 'run_async') is False
78
+ assert settings['alias']['custom'] == 'git diff'
79
+ assert legacy.read_text() == contents
@@ -1,60 +0,0 @@
1
- name: Upload to Arch Linux (AUR)
2
-
3
- on:
4
- release:
5
- types: [published]
6
- workflow_dispatch:
7
-
8
- jobs:
9
- test:
10
- runs-on: ubuntu-latest
11
- steps:
12
- - uses: actions/checkout@v4
13
-
14
- - name: Set up Python 3.13
15
- uses: actions/setup-python@v5
16
- with:
17
- python-version: "3.13"
18
-
19
- - name: Configure git
20
- run: |
21
- git config --global user.name "Test User"
22
- git config --global user.email "test@example.com"
23
-
24
- - name: Install dependencies and build
25
- run: |
26
- pip install -r requirements.txt pytest build
27
- python -m build
28
- pip install dist/*.whl
29
-
30
- - name: Run tests
31
- run: pytest -v
32
-
33
- aur-publish:
34
- needs: [test]
35
- runs-on: ubuntu-latest
36
- steps:
37
- - name: Checkout repository
38
- uses: actions/checkout@v4
39
- with:
40
- fetch-depth: 0
41
-
42
- - name: Update PKGBUILD with Tag Version
43
- run: |
44
- version=$(git describe --tags --abbrev=0 | sed 's/^v//')
45
- echo "latest_version=$version" >> $GITHUB_ENV
46
- sed -i "s/^pkgver=.*/pkgver=${version}/" PKGBUILD
47
- cat PKGBUILD
48
-
49
- - name: Publish AUR package
50
- uses: KSXGitHub/github-actions-deploy-aur@v4.1.2
51
- env:
52
- latest_version: ${{ env.latest_version }}
53
- with:
54
- pkgname: mud-git
55
- pkgbuild: ./PKGBUILD
56
- commit_username: ${{ secrets.AUR_USERNAME }}
57
- commit_email: ${{ secrets.AUR_EMAIL }}
58
- ssh_private_key: ${{ secrets.AUR_SSH_KEY }}
59
- commit_message: "Update AUR package to version ${{ env.latest_version }}"
60
- ssh_keyscan_types: rsa,ecdsa
mud_git-1.1.8/PKGBUILD DELETED
@@ -1,37 +0,0 @@
1
- # Maintainer: Jasur Sadikov <jasur@sadikoff.com>
2
- pkgname=mud-git
3
- _pkgname=mud
4
- pkgver=1.0.0
5
- pkgrel=1
6
- pkgdesc="Multi repository git utility. Manage multiple git-repositories simultaneously."
7
- arch=('any')
8
- url="https://github.com/jasursadikov/mud"
9
- license=('MIT')
10
- provides=("${pkgname}")
11
- conflicts=("${pkgname}")
12
- depends=(
13
- 'python'
14
- 'python-prettytable'
15
- 'python-pygit2'
16
- 'git')
17
- makedepends=(
18
- 'python-build'
19
- 'python-installer'
20
- 'python-wheel'
21
- 'python-hatchling'
22
- 'python-setuptools'
23
- 'python-setuptools-scm'
24
- )
25
- source=("${pkgname}::git+${url}#tag=v${pkgver}")
26
- md5sums=('SKIP')
27
-
28
- build() {
29
- cd "$srcdir/$pkgname"
30
- python -m build --wheel --no-isolation
31
- }
32
-
33
- package() {
34
- cd "$srcdir/$pkgname"
35
- python -m installer --destdir="$pkgdir" dist/*.whl
36
- install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
37
- }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "1.1.8",
3
- "distance": 0,
4
- "node": "g1cc3dd62f361e5e13d6c3979cc1a747db28a846d",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-09-14"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes