Compare commits

..
Author SHA1 Message Date
home-manager-ci[bot] 40e3b99d82 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/68d8aa3d661f0e6bd5862291b5bb263b2a6595c9?narHash=sha256-vPKLpjhIVWdDrfiUM8atW6YkIggCEKdSAlJPzzhkQlw%3D' (2026-04-05)
  → 'github:NixOS/nixpkgs/4c1018dae018162ec878d42fec712642d214fdfa?narHash=sha256-ar3rofg%2BawPB8QXDaFJhJ2jJhu%2BKqN/PRCXeyuXR76E%3D' (2026-04-09)
2026-04-12 05:47:34 +00:00
1406 changed files with 9204 additions and 34286 deletions
-4
View File
@@ -55,7 +55,3 @@ f2f1076c1f789595c2a2b18b76466fbd691025dd
11ad9d2e42ebf6d00db4d7bae252f1c6b7dd36a4
74b0e979375b0ed469e2394820aa50ba2114800b
de90ee24082bb8dd44145f5c733b807467856820
# Deadnix cleanup
71402c5df34df5ee7b6c10d738018f9f0c8bde2b
a93d80bcec089abf80894c25ee3934b7e196bbd9
+2 -2
View File
@@ -24,8 +24,8 @@ Also make sure to read the guidelines found at
- [ ] Code formatted with `nix fmt` or
`nix-shell -A dev --run treefmt`.
- [ ] Code tested through `nix build .#test-all`
or a targeted `nix run .#tests -- <pattern>`.
- [ ] Code tested through `nix run .#tests -- test-all` or
`nix-shell --pure tests -A run.all`.
- [ ] Test cases updated/added. See [example](https://github.com/nix-community/home-manager/commit/f3fbb50b68df20da47f9b0def5607857fcc0d021#diff-b61a6d542f9036550ba9c401c80f00ef).
+1 -15
View File
@@ -9,22 +9,8 @@ updates:
prefix: "ci:"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-26.05"
target-branch: "release-25.11"
schedule:
interval: "weekly"
commit-message:
prefix: "ci:"
- package-ecosystem: "nix"
directory: "/"
target-branch: "master"
schedule:
interval: "weekly"
commit-message:
prefix: "flake:"
- package-ecosystem: "nix"
directory: "/"
target-branch: "release-26.05"
schedule:
interval: "weekly"
commit-message:
prefix: "flake:"
+2 -5
View File
@@ -1,16 +1,13 @@
"release":
- base-branch:
- '^release-.*'
"ai":
- changed-files:
- any-glob-to-any-file:
- modules/programs/aiac.nix
- modules/programs/aichat.nix
- modules/programs/aider-chat.nix
- modules/programs/claude-code/**/*
- modules/programs/claude-code.nix
- modules/programs/codex.nix
- modules/programs/fabric-ai.nix
- modules/programs/antigravity-cli.nix
- modules/programs/gemini-cli.nix
- modules/programs/mcp.nix
- modules/programs/mistral-vibe.nix
- modules/programs/mods.nix
+2 -2
View File
@@ -31,10 +31,10 @@ jobs:
with:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
ref: ${{ github.event.pull_request.base.sha }}
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
id: backport
uses: korthout/backport-action@v4
+2 -2
View File
@@ -12,10 +12,10 @@ jobs:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v17
with:
name: nix-community
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
COUNT=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' | grep -c '^modules/' || true)
COUNT=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' | grep '^modules/' | wc -l || echo 0)
echo "Found $COUNT changed module files."
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
+6 -6
View File
@@ -23,7 +23,7 @@ jobs:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- name: Checkout code
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.base.sha }}
- name: Get Nixpkgs revision from flake.lock
@@ -42,12 +42,12 @@ jobs:
GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only | grep '^modules/' | grep -v '^modules/\(po\|.*\/news\)/' || true)
CHANGED_FILES=$(gh pr diff $PR_NUMBER --name-only | grep '^modules/' | grep -v '^modules/\(po\|.*\/news\)/' || true)
echo "Changed files:"
echo "$CHANGED_FILES"
echo "changed_files<<EOF" >> "$GITHUB_OUTPUT"
echo "$CHANGED_FILES" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Extract Maintainers
id: extract-maintainers
env:
@@ -58,7 +58,7 @@ jobs:
MAINTAINERS=$(lib/python/extract-maintainers.py \
--changed-files "$CHANGED_FILES" \
--pr-author "$PR_AUTHOR")
echo "maintainers=$MAINTAINERS" >> "$GITHUB_OUTPUT"
echo "maintainers=$MAINTAINERS" >> $GITHUB_OUTPUT
echo "Found maintainers: $MAINTAINERS"
- name: Manage Reviewers
env:
+16 -38
View File
@@ -6,19 +6,16 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.run_id }}
cancel-in-progress: true
permissions: {}
jobs:
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
docs: ${{ steps.changes.outputs.docs }}
format: ${{ steps.changes.outputs.format }}
hm: ${{ steps.changes.outputs.hm }}
parse: ${{ steps.changes.outputs.parse }}
tests: ${{ steps.changes.outputs.tests }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v4
id: changes
with:
@@ -42,41 +39,28 @@ jobs:
- 'flake.lock'
- 'flake.nix'
- 'home-manager/**'
parse:
- '**/*.nix'
- 'flake.lock'
tests:
needs: changes
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Get Nixpkgs revision from flake.lock
id: get-nixpkgs
run: |
echo "rev=$(jq -r '.nodes.nixpkgs.locked.rev' flake.lock)" >> "$GITHUB_OUTPUT"
- uses: cachix/install-nix-action@v31
if: github.event_name == 'schedule' || needs.changes.outputs.docs == 'true' || needs.changes.outputs.tests == 'true' || needs.changes.outputs.hm == 'true' || needs.changes.outputs.parse == 'true' || needs.changes.outputs.format == 'true'
if: github.event_name == 'schedule' || needs.changes.outputs.docs == 'true' || needs.changes.outputs.tests == 'true' || needs.changes.outputs.hm == 'true' || needs.changes.outputs.format == 'true'
with:
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/${{ steps.get-nixpkgs.outputs.rev }}.tar.gz
extra_nix_config: |
sandbox = true
- name: Build docs
if: github.event_name == 'schedule' || needs.changes.outputs.docs == 'true'
run: nix build --show-trace .#docs-jsonModuleMaintainers
- name: Parse Nix files with nix and Lix
if: >-
matrix.os == 'ubuntu-latest' &&
(github.event_name == 'schedule' || needs.changes.outputs.parse == 'true')
run: nix build --show-trace --keep-going .#ci-parse .#ci-parse-lix
- name: Format Check
if: >-
matrix.os == 'ubuntu-latest' &&
(github.event_name == 'schedule' || needs.changes.outputs.format == 'true')
if: github.event_name == 'schedule' || needs.changes.outputs.format == 'true'
run: nix fmt -- --ci
- name: Test init --switch with locked inputs
if: github.event_name == 'schedule' || needs.changes.outputs.hm == 'true'
@@ -92,37 +76,31 @@ jobs:
if: github.event_name == 'pull_request'
shell: bash
run: |
echo "### Test Job Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "A summary of tasks triggered by file changes in this PR:" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "### Test Job Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "A summary of tasks triggered by file changes in this PR:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.changes.outputs.docs }}" == "true" ]]; then
echo "- ✅ **Docs Build:** Triggered" >> "$GITHUB_STEP_SUMMARY"
echo "- ✅ **Docs Build:** Triggered" >> $GITHUB_STEP_SUMMARY
else
echo "- ☑️ **Docs Build:** Skipped (no relevant files changed)" >> "$GITHUB_STEP_SUMMARY"
echo "- ☑️ **Docs Build:** Skipped (no relevant files changed)" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.changes.outputs.format }}" == "true" ]]; then
echo "- ✅ **Format Check:** Triggered" >> "$GITHUB_STEP_SUMMARY"
echo "- ✅ **Format Check:** Triggered" >> $GITHUB_STEP_SUMMARY
else
echo "- ☑️ **Format Check:** Skipped (no relevant files changed)" >> "$GITHUB_STEP_SUMMARY"
fi
if [[ "${{ needs.changes.outputs.parse }}" == "true" ]]; then
echo "- ✅ **Nix Parse (nix + Lix):** Triggered" >> "$GITHUB_STEP_SUMMARY"
else
echo "- ☑️ **Nix Parse (nix + Lix):** Skipped (no relevant files changed)" >> "$GITHUB_STEP_SUMMARY"
echo "- ☑️ **Format Check:** Skipped (no relevant files changed)" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.changes.outputs.hm }}" == "true" ]]; then
echo "- ✅ **Home Manager Tests:** Triggered" >> "$GITHUB_STEP_SUMMARY"
echo "- ✅ **Home Manager Tests:** Triggered" >> $GITHUB_STEP_SUMMARY
else
echo "- ☑️ **Home Manager Tests:** Skipped (no relevant files changed)" >> "$GITHUB_STEP_SUMMARY"
echo "- ☑️ **Home Manager Tests:** Skipped (no relevant files changed)" >> $GITHUB_STEP_SUMMARY
fi
if [[ "${{ needs.changes.outputs.tests }}" == "true" ]]; then
echo "- ✅ **General Tests:** Triggered" >> "$GITHUB_STEP_SUMMARY"
echo "- ✅ **General Tests:** Triggered" >> $GITHUB_STEP_SUMMARY
else
echo "- ☑️ **General Tests:** Skipped (no relevant files changed)" >> "$GITHUB_STEP_SUMMARY"
echo "- ☑️ **General Tests:** Skipped (no relevant files changed)" >> $GITHUB_STEP_SUMMARY
fi
+66
View File
@@ -0,0 +1,66 @@
name: Update flake inputs
on:
schedule:
# Update every Sunday and Wednesday
- cron: "51 3 * * 0,3"
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository_owner == 'nix-community'
strategy:
fail-fast: false
matrix:
branch: [master, release-25.11]
steps:
- name: Create GitHub App token
uses: actions/create-github-app-token@v3
if: vars.CI_APP_ID
id: app-token
with:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- name: Get GitHub App user info
if: vars.CI_APP_ID
id: user-info
env:
GH_TOKEN: ${{ steps.app-token.outputs.token}}
slug: ${{ steps.app-token.outputs.app-slug }}
run: |
name="$slug[bot]"
id=$(gh api "/users/$name" --jq .id)
{
echo "id=$id"
echo "name=$name"
echo "email=$id+$name@users.noreply.github.com"
} >> "$GITHUB_OUTPUT"
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ matrix.branch }}
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
- name: Install Nix
uses: cachix/install-nix-action@v31
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v28
with:
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
git-committer-name: ${{ steps.user-info.outputs.name || 'github-actions[bot]' }}
git-committer-email: ${{ steps.user-info.outputs.email || '41898282+github-actions[bot]@users.noreply.github.com' }}
git-author-name: ${{ steps.user-info.outputs.name || 'github-actions[bot]' }}
git-author-email: ${{ steps.user-info.outputs.email || '41898282+github-actions[bot]@users.noreply.github.com' }}
pr-labels: dependencies
pr-title: "[${{ matrix.branch }}] flake.lock: Update"
pr-body: |
Automated update by the [update-flake-lock] GitHub Action.
```
{{ env.GIT_COMMIT_MESSAGE }}
```
This PR was most recently updated by workflow run [${{ github.run_id }}].
[update-flake-lock]: https://github.com/DeterminateSystems/update-flake-lock
[${{ github.run_id }}]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
base: ${{ matrix.branch }}
branch: update/${{ matrix.branch }}
+10 -10
View File
@@ -48,7 +48,7 @@ jobs:
echo "email=$id+$name@users.noreply.github.com"
} >> "$GITHUB_OUTPUT"
- name: Checkout repository
uses: actions/checkout@v7
uses: actions/checkout@v6
with:
token: ${{ steps.app-token.outputs.token || github.token }}
- name: Get Nixpkgs revision from flake.lock
@@ -184,7 +184,7 @@ jobs:
if [[ -n "$info" ]]; then
echo "PR info:"
echo "$info"
echo "$info" >> "$GITHUB_OUTPUT"
echo "$info" >> $GITHUB_OUTPUT
else
echo "No PR is currently open"
fi
@@ -266,21 +266,21 @@ jobs:
echo "✅ Successfully updated PR with new changes."
echo "$changes"
echo "🔗 PR URL: $pr_url"
echo "### ✅ PR Updated" >> "$GITHUB_STEP_SUMMARY"
echo "[$pr_url]($pr_url)" >> "$GITHUB_STEP_SUMMARY"
echo "### ✅ PR Updated" >> $GITHUB_STEP_SUMMARY
echo "[$pr_url]($pr_url)" >> $GITHUB_STEP_SUMMARY
elif [[ -n "$pr_url" ]]; then
echo "✅ Successfully created PR with maintainer updates."
echo "$changes"
echo "🔗 PR URL: $pr_url"
echo "### ✅ PR Created" >> "$GITHUB_STEP_SUMMARY"
echo "[$pr_url]($pr_url)" >> "$GITHUB_STEP_SUMMARY"
echo "### ✅ PR Created" >> $GITHUB_STEP_SUMMARY
echo "[$pr_url]($pr_url)" >> $GITHUB_STEP_SUMMARY
else
echo "❌ Failed to create or update pull request."
echo "### ❌ PR Operation Failed" >> "$GITHUB_STEP_SUMMARY"
echo "A pull request was intended but the URL was not captured. Please check the logs." >> "$GITHUB_STEP_SUMMARY"
echo "### ❌ PR Operation Failed" >> $GITHUB_STEP_SUMMARY
echo "A pull request was intended but the URL was not captured. Please check the logs." >> $GITHUB_STEP_SUMMARY
fi
else
echo "️ No changes detected - maintainers list is up to date."
echo "### ️ No Changes" >> "$GITHUB_STEP_SUMMARY"
echo "The maintainers list is up-to-date. No PR was created." >> "$GITHUB_STEP_SUMMARY"
echo "### ️ No Changes" >> $GITHUB_STEP_SUMMARY
echo "The maintainers list is up-to-date. No PR was created." >> $GITHUB_STEP_SUMMARY
fi
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
if: github.repository_owner == 'nix-community'
steps:
- name: Checkout repository
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Get Nixpkgs revision from flake.lock
id: get-nixpkgs
run: |
-1
View File
@@ -1 +0,0 @@
Noah Biewesch <dev@noahbiewesch.com> <90870942+trueNAHO@users.noreply.github.com>
-8
View File
@@ -1,8 +0,0 @@
# Contributing
Home Manager contribution guidelines live in the manual:
- [`docs/manual/contributing.md`](docs/manual/contributing.md)
- <https://nix-community.github.io/home-manager/#ch-contributing>
Read those docs before changing modules, tests, news entries, or release notes.
+1 -5
View File
@@ -11,13 +11,9 @@ list *pattern:
test *pattern:
nix run .#tests -- {{pattern}}
# List integration tests
list_integration_tests:
nix run .#tests -- -t -l
# Run integration tests
integration_tests:
nix run .#tests -- -t integration-test-
nix run .#tests -- -t -l
# Create a news entry
create-news-entry:
+2 -2
View File
@@ -125,7 +125,7 @@ Reference commits:
- Update the nixpkgs input to track the corresponding stable branch
- Example: For `release-25.11`, change from:
```nix
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
```
to:
```nix
@@ -135,7 +135,7 @@ Reference commits:
- Commit the flake.nix and flake.lock changes
**Note**: The release branch should track the stable NixOS release channel
(e.g., `nixos-25.11`), while master continues to track `nixpkgs-unstable`.
(e.g., `nixos-25.11`), while master continues to track `nixos-unstable`.
#### Step 3.5: On master - Update CI for the New Release Branch
+1 -1
View File
@@ -1,5 +1,5 @@
.PHONY: all all-tests test test-install format
NIXPKGS_REV := nixpkgs-unstable
NIXPKGS_REV := nixos-unstable
NIX_PATH := nixpkgs=https://github.com/NixOS/nixpkgs/archive/${NIXPKGS_REV}.tar.gz
all: all-tests test-install
+4 -5
View File
@@ -25,11 +25,10 @@ If you would like to contribute to Home Manager, then please have a look at
Releases
--------
Home Manager is developed against the `nixpkgs-unstable` branch, which often
causes it to contain tweaks for changes/packages not yet released in stable
[NixOS][].
Home Manager is developed against `nixos-unstable` branch, which often causes
it to contain tweaks for changes/packages not yet released in stable [NixOS][].
To avoid breaking users' configurations, Home Manager is released in branches
corresponding to NixOS releases (e.g. `release-26.05`). These branches get
corresponding to NixOS releases (e.g. `release-25.11`). These branches get
fixes, but usually not new modules. If you need a module to be backported, then
feel free to open an issue.
@@ -50,7 +49,7 @@ dconf store and cannot tell whether a configuration that is about to be
overwritten was from a previous Home Manager generation or from manual
configuration.
Home Manager targets `nixpkgs-unstable` and NixOS version 26.05 (the current
Home Manager targets [NixOS][] unstable and NixOS version 25.11 (the current
stable version), it may or may not work on other Linux distributions and NixOS
versions.
+61 -188
View File
@@ -21,13 +21,6 @@
name = "0xda157";
source = "nixpkgs";
};
"0xdsqr" = {
email = "me@dsqr.dev";
github = "0xdsqr";
githubId = 99584622;
name = "Dave Dennis";
source = "home-manager";
};
"3ulalia" = {
email = "3ulalia@proton.me";
github = "3ulalia";
@@ -39,14 +32,8 @@
email = "git.t@betsumei.com";
github = "74k1";
githubId = 49000471;
keys = [
{
fingerprint = "46F3 422F 63A3 1369 7EAB 83D5 1CF1 55F7 6F21 3503";
}
];
matrix = "@74k1:matrix.org";
name = "Tim";
source = "nixpkgs";
source = "home-manager";
};
"9p4" = {
email = "vcs@ersei.net";
@@ -81,14 +68,14 @@
github = "AndreasMager";
githubId = 5646732;
name = "Andreas Mager";
source = "home-manager";
source = "nixpkgs";
};
Austreelis = {
email = "github@accounts.austreelis.net";
github = "Austreelis";
githubId = 56743515;
name = "Morgane Austreelis";
source = "home-manager";
source = "nixpkgs";
};
CarlosLoboxyz = {
email = "86011416+CarlosLoboxyz@users.noreply.github.com";
@@ -125,27 +112,12 @@
name = "Denis Kaynar";
source = "home-manager";
};
ErinaYip = {
email = "erinayip@outlook.com";
github = "ErinaYip";
githubId = 227132255;
name = "erina";
source = "home-manager";
};
Eveeifyeve = {
email = "eveeg1971@gmail.com";
github = "Eveeifyeve";
githubId = 88671402;
matrix = "@eveeifyeve:matrix.org";
name = "Eveeifyeve";
source = "nixpkgs";
};
Fendse = {
email = "46252070+Fendse@users.noreply.github.com";
github = "Fendse";
githubId = 46252070;
name = "Sara Johnsson";
source = "home-manager";
source = "nixpkgs";
};
Flameopathic = {
email = "flameopathic@gmail.com";
@@ -208,7 +180,7 @@
githubId = 80165193;
matrix = "@janik0:matrix.org";
name = "Janik";
source = "home-manager";
source = "nixpkgs";
};
JasmineLowen = {
email = "robwalter96@gmail.com";
@@ -234,7 +206,7 @@
github = "Joker9944";
githubId = 9194199;
name = "Felix von Arx";
source = "home-manager";
source = "nixpkgs";
};
JustinLovinger = {
email = "git@justinlovinger.com";
@@ -311,7 +283,7 @@
github = "MForster";
githubId = 4067975;
name = "Michael Forster";
source = "home-manager";
source = "nixpkgs";
};
Misterio77 = {
email = "eu@misterio.me";
@@ -390,25 +362,12 @@
name = "Philipp Mildenberger";
source = "nixpkgs";
};
ReStranger = {
github = "ReStranger";
githubId = 69393944;
name = "ReStranger";
source = "nixpkgs";
};
ReeSilva = {
email = "reesilva@proton.me";
github = "ReeSilva";
githubId = 3605032;
name = "Renato da Silva";
source = "home-manager";
};
Rosuavio = {
email = "RosarioPulella@gmail.com";
github = "Rosuavio";
githubId = 7164552;
name = "Rosario Pulella";
source = "home-manager";
source = "nixpkgs";
};
S0AndS0 = {
email = "S0AndS0@digital-mercenaries.com";
@@ -431,6 +390,13 @@
name = "Sefa Eyeoglu";
source = "nixpkgs";
};
SebTM = {
email = "mail@sebastian-sellmeier.de";
github = "SebTM";
githubId = 17243347;
name = "Sebastian Sellmeier";
source = "nixpkgs";
};
ShamrockLee = {
email = "shamrocklee@posteo.net";
github = "ShamrockLee";
@@ -451,12 +417,6 @@
name = "Mel Bourgeois";
source = "nixpkgs";
};
SunOfLife1 = {
github = "SunOfLife1";
githubId = 30405063;
name = "SunOfLife1";
source = "home-manager";
};
Swarsel = {
email = "leon@swarsel.win";
github = "Swarsel";
@@ -492,6 +452,13 @@
name = "Vincent Breitmoser";
source = "nixpkgs";
};
Vortriz = {
email = "vorarishi22+nix@gmail.com";
github = "Vortriz";
githubId = 97402159;
name = "Rishi Vora";
source = "nixpkgs";
};
WGUNDERWOOD = {
email = "wg.underwood13@gmail.com";
github = "WGUNDERWOOD";
@@ -548,6 +515,14 @@
name = "David Chocholatý";
source = "nixpkgs";
};
adisbladis = {
email = "adisbladis@gmail.com";
github = "adisbladis";
githubId = 63286;
matrix = "@adis:blad.is";
name = "Adam Hose";
source = "nixpkgs";
};
afresquet = {
email = "alvarofresquet@gmail.com";
github = "afresquet";
@@ -597,13 +572,6 @@
name = "Alin";
source = "nixpkgs";
};
amadejkastelic = {
email = "amadejkastelic7@gmail.com";
github = "amadejkastelic";
githubId = 26391003;
name = "Amadej Kastelic";
source = "nixpkgs";
};
ambroisie = {
email = "bruno.nixpkgs@belanyi.fr";
github = "ambroisie";
@@ -671,7 +639,7 @@
github = "b1kku";
githubId = 77858854;
name = "Bikku";
source = "home-manager";
source = "nixpkgs";
};
bamhm182 = {
email = "bamhm182@gmail.com";
@@ -711,13 +679,6 @@
name = "Filippo Berto";
source = "nixpkgs";
};
bittner = {
email = "peter@painless.software";
github = "bittner";
githubId = 665072;
name = "Peter Bittner";
source = "home-manager";
};
bjpbakker = {
email = "bart@thesoftwarecraft.com";
github = "bjpbakker";
@@ -881,7 +842,7 @@
github = "ckgxrg-salt";
githubId = 165614491;
name = "ckgxrg";
source = "home-manager";
source = "nixpkgs";
};
cmacrae = {
email = "hi@cmacr.ae";
@@ -910,13 +871,6 @@
name = "Phillip Cloud";
source = "nixpkgs";
};
csanthiago = {
email = "git@csanthiago.dev";
github = "csanthiago";
githubId = 8346803;
name = "csanthiago";
source = "home-manager";
};
cwyc = {
email = "hello@cwyc.page";
github = "cwyc";
@@ -997,6 +951,13 @@
name = "Robin Stumm";
source = "nixpkgs";
};
diniamo = {
email = "diniamo53@gmail.com";
github = "diniamo";
githubId = 55629891;
name = "diniamo";
source = "nixpkgs";
};
donovanglover = {
github = "donovanglover";
githubId = 2374245;
@@ -1176,13 +1137,6 @@
name = "Fugi";
source = "nixpkgs";
};
garklein = {
email = "garklein97@gmail.com";
github = "garklein";
githubId = 63201615;
name = "Garklein";
source = "home-manager";
};
gauthsvenkat = {
email = "gauthsvenkat+home-manager@gmail.com";
github = "gauthsvenkat";
@@ -1284,18 +1238,6 @@
name = "Bhe Hongtyu";
source = "nixpkgs";
};
iamanaws = {
email = "iamanaws@httpd.dev";
github = "iamanaws";
githubId = 78835633;
keys = [
{
fingerprint = "CF10 DCBB 9318 BE1D 6040 4222 272C 61AB 190D ED28";
}
];
name = "Angel J";
source = "nixpkgs";
};
ilaumjd = {
email = "ilaumjd@gmail.com";
github = "ilaumjd";
@@ -1317,13 +1259,6 @@
name = "Ilya Savitsky";
source = "nixpkgs";
};
isaacST08 = {
email = "isaacst.nix@proton.me";
github = "isaacST08";
githubId = 106057977;
name = "Isaac Shiells Thomas";
source = "home-manager";
};
iynaix = {
email = "iynaix@gmail.com";
github = "iynaix";
@@ -1471,7 +1406,7 @@
github = "kaleocheng";
githubId = 7939352;
name = "Kaleo Cheng";
source = "home-manager";
source = "nixpkgs";
};
kalhauge = {
email = "kalhauge@users.noreply.github.com";
@@ -1499,13 +1434,6 @@
name = "Nikolaos Karaolidis";
source = "nixpkgs";
};
kayskayskays = {
email = "115312476+kayskayskays@users.noreply.github.com";
github = "kayskayskays";
githubId = 115312476;
name = "Kays";
source = "home-manager";
};
khaneliman = {
email = "khaneliman12@gmail.com";
github = "khaneliman";
@@ -1528,13 +1456,6 @@
name = "Knut Magnus Aasrud";
source = "home-manager";
};
kpbaks = {
email = "kristoffer.pbs@gmail.com";
github = "kpbaks";
githubId = 57013304;
name = "Kristoffer Plagborg Bak Sørensen";
source = "nixpkgs";
};
kubukoz = {
email = "kubukoz@gmail.com";
github = "kubukoz";
@@ -1657,13 +1578,6 @@
name = "Manaiki Laut";
source = "nixpkgs";
};
marijanp = {
email = "marijan.petricevic94@gmail.com";
github = "marijanp";
githubId = 13599169;
name = "Marijan Petričević";
source = "nixpkgs";
};
mateusauler = {
email = "mateus@auler.dev";
github = "mateusauler";
@@ -1765,7 +1679,7 @@
github = "miku4k";
githubId = 89653242;
name = "Miku B";
source = "home-manager";
source = "nixpkgs";
};
minijackson = {
email = "minijackson@riseup.net";
@@ -1864,7 +1778,7 @@
github = "natecox";
githubId = 2782695;
name = "Nate Cox";
source = "home-manager";
source = "nixpkgs";
};
nbp = {
email = "nixos@nbp.name";
@@ -1911,9 +1825,21 @@
email = "nukdokplex@nukdokplex.ru";
github = "nukdokplex";
githubId = 25458915;
keys = [
{
fingerprint = "7CE2 4C42 942D 58EA 99F6 F00A A47E 7374 3EF6 FCC4";
}
];
name = "Viktor Titov";
source = "nixpkgs";
};
nurelin = {
email = "nurelin@users.noreply.github.com";
github = "nurelin";
githubId = 5276274;
name = "nurelin";
source = "home-manager";
};
nyarly = {
email = "nyarly@gmail.com";
github = "nyarly";
@@ -1921,13 +1847,6 @@
name = "Judson Lester";
source = "nixpkgs";
};
ojsef39 = {
email = "me+github@jhofer.de";
github = "ojsef39";
githubId = 43563019;
name = "Josef Hofer";
source = "nixpkgs";
};
olmokramer = {
email = "olmokramer@users.noreply.github.com";
github = "olmokramer";
@@ -2018,6 +1937,13 @@
name = "Myles Wirth";
source = "nixpkgs";
};
pinage404 = {
email = "pinage404+nixpkgs@gmail.com";
github = "pinage404";
githubId = 6325757;
name = "pinage404";
source = "nixpkgs";
};
pjones = {
email = "pjones@devalot.com";
github = "pjones";
@@ -2085,18 +2011,6 @@
name = "Rasmus Kirk";
source = "home-manager";
};
ratakor = {
email = "ratakor@disroot.org";
github = "ratakor";
githubId = 45130910;
keys = [
{
fingerprint = "B60F 8F80 D6CD C5D2 58CF 14C3 241B 1CBE 567B 287E";
}
];
name = "Ratakor";
source = "nixpkgs";
};
ravenjoad = {
email = "raven@hallsby.com";
github = "ravenjoad";
@@ -2203,13 +2117,6 @@
name = "Robert Helgesson";
source = "nixpkgs";
};
s0racat = {
email = "125882337+s0racat@users.noreply.github.com";
github = "s0racat";
githubId = 125882337;
name = "soracat";
source = "home-manager";
};
sableseyler = {
email = "sable@seyleri.us";
github = "sableseyler";
@@ -2222,20 +2129,6 @@
name = "Sable Seyler";
source = "nixpkgs";
};
sei40kr = {
email = "sei40kr@gmail.com";
github = "sei40kr";
githubId = 11665236;
name = "Seong Yong-ju";
source = "nixpkgs";
};
semi710 = {
email = "nik.singh710@gmail.com";
github = "semi710";
githubId = 60490474;
name = "Nikhil Singh";
source = "nixpkgs";
};
shikanime = {
email = "william.phetsinorath@shikanime.studio";
github = "shikanime";
@@ -2315,13 +2208,6 @@
name = "Sumner Evans";
source = "nixpkgs";
};
superflash41 = {
email = "saymon.nicho@pucp.edu.pe";
github = "superflash41";
githubId = 102434258;
name = "Saymon Nicho";
source = "home-manager";
};
surfaceflinger = {
email = "nat@nekopon.pl";
github = "surfaceflinger";
@@ -2496,13 +2382,6 @@
name = "Xavier Lambein";
source = "nixpkgs";
};
yaaaarn = {
email = "nix@yarncat.moe";
github = "yaaaarn";
githubId = 30006414;
name = "yarncat";
source = "nixpkgs";
};
yethal = {
github = "yethal";
githubId = 26117918;
@@ -2521,12 +2400,6 @@
name = "Jona Abdinghoff";
source = "nixpkgs";
};
zh4ngx = {
github = "zh4ngx";
githubId = 1329212;
name = "Andy Zhang";
source = "nixpkgs";
};
zorrobert = {
email = "118135271+zorrobert@users.noreply.github.com";
github = "zorrobert";
-45
View File
@@ -1,45 +0,0 @@
{
lib,
nix,
runCommand,
}:
let
home-manager =
with lib.fileset;
toSource {
root = ../.;
fileset = (fileFilter (file: file.hasExt "nix") ../.);
};
parseLog = "$TMPDIR/nix-parse.log";
in
runCommand "nix-parse-${nix.name}"
{
nativeBuildInputs = [
nix
];
}
''
export NIX_STORE_DIR=$TMPDIR/store
export NIX_STATE_DIR=$TMPDIR/state
nix-store --init
cd "${home-manager}"
# This will only show the first parse error, not all of them. That's fine, because
# the other CI jobs will report in more detail. This job is about checking parsing
# across different implementations / versions, not about providing the best DX.
# Returning all parse errors requires significantly more resources.
if ! find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse 2> "${parseLog}" > /dev/null; then
cat "${parseLog}" >&2
echo "Parse failed in nix-instantiate." >&2
exit 1
fi
if grep "warning" "${parseLog}"; then
cat "${parseLog}" >&2
echo "Failing due to warnings in stderr" >&2
exit 1
fi
touch $out
''
+3 -9
View File
@@ -253,15 +253,9 @@ let
# Generate the HTML manual pages
home-manager-manual = pkgs.callPackage ./home-manager-manual.nix {
home-manager-options = {
home-manager = {
json = hmOptionsDocs.optionsJSON;
};
nixos = {
json = nixosOptionsDocs.optionsJSON;
};
nix-darwin = {
json = nixDarwinOptionsDocs.optionsJSON;
};
home-manager = hmOptionsDocs.optionsJSON;
nixos = nixosOptionsDocs.optionsJSON;
nix-darwin = nixDarwinOptionsDocs.optionsJSON;
};
inherit revision;
};
+4 -4
View File
@@ -2,16 +2,16 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1779877693,
"narHash": "sha256-NOF9NAREhxr50bbBfVcVOq+ArCMSoe8dP79Pk2uyARk=",
"lastModified": 1773821835,
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4100e830e085863741bc69b156ec4ccd53ab5be0",
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
+1 -1
View File
@@ -2,7 +2,7 @@
description = "Support developing Home Manager documentation";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
scss-reset = {
url = "github:andreymatin/scss-reset/1.4.2";
flake = false;
+39 -53
View File
@@ -1,75 +1,63 @@
{
stdenv,
lib,
callPackage,
mdbook,
python3,
documentation-highlighter,
revision,
home-manager-options,
nixos-render-docs,
}:
let
outputPath = "share/doc/home-manager";
mdbookOptions = callPackage ./mdbook/options.nix {
manpageUrls = ./manual/manpage-urls.json;
inherit revision;
optionDocs = {
home-manager = {
title = "Home Manager Configuration Options";
path = "home-manager";
prefix = "opt-";
json = "${home-manager-options.home-manager.json}";
};
nixos = {
title = "NixOS Configuration Options";
path = "nixos";
prefix = "nixos-opt-";
json = "${home-manager-options.nixos.json}";
};
nix-darwin = {
title = "nix-darwin Configuration Options";
path = "nix-darwin";
prefix = "nix-darwin-opt-";
json = "${home-manager-options.nix-darwin.json}";
};
};
};
in
stdenv.mkDerivation {
name = "home-manager-manual";
nativeBuildInputs = [
mdbook
python3
];
nativeBuildInputs = [ nixos-render-docs ];
src = ./.;
src = ./manual;
buildPhase = ''
runHook preBuild
mkdir -p out/{highlightjs,media}
mkdir -p source
python3 ${./mdbook/convert-markup.py} "$src/manual" source
python3 ${./mdbook/convert-markup.py} \
--base-depth 1 \
"$src/release-notes" \
source/release-notes
cp -t out/highlightjs \
${documentation-highlighter}/highlight.pack.js \
${documentation-highlighter}/LICENSE \
${documentation-highlighter}/mono-blue.css \
${documentation-highlighter}/loader.js
cp -r ${mdbookOptions}/options source/options
substituteInPlace ./options.md \
--subst-var-by \
OPTIONS_JSON \
${home-manager-options.home-manager}/share/doc/nixos/options.json
python3 ${./mdbook/substitute-summary.py} \
source/SUMMARY.md \
${mdbookOptions}/summary/home-manager.md \
${mdbookOptions}/summary/nixos.md \
${mdbookOptions}/summary/nix-darwin.md
substituteInPlace ./nixos-options.md \
--subst-var-by \
OPTIONS_JSON \
${home-manager-options.nixos}/share/doc/nixos/options.json
mdbook build source --dest-dir book
substituteInPlace ./nix-darwin-options.md \
--subst-var-by \
OPTIONS_JSON \
${home-manager-options.nix-darwin}/share/doc/nixos/options.json
mkdir -p out
cp -r book/* out/
cp ${./options.html} out/options.html
python3 ${./mdbook/legacy-redirects.py} source out
cp ${./static/style.css} out/style.css
cp ${./static/anchor-links.js} out/anchor-links.js
runHook postBuild
cp -r ${./release-notes} release-notes
nixos-render-docs manual html \
--manpage-urls ./manpage-urls.json \
--revision ${lib.trivial.revisionWithDefault revision} \
--stylesheet style.css \
--script highlightjs/highlight.pack.js \
--script highlightjs/loader.js \
--script anchor-links.js \
--toc-depth 1 \
--section-toc-depth 1 \
manual.md \
out/index.xhtml
'';
installPhase = ''
@@ -81,9 +69,7 @@ stdenv.mkDerivation {
echo "doc manual $dest index.html" >> $out/nix-support/hydra-build-products
'';
passthru = {
inherit home-manager-options mdbookOptions;
};
passthru = { inherit home-manager-options; };
meta = {
maintainers = [ lib.maintainers.considerate ];
+2 -7
View File
@@ -25,14 +25,9 @@ let
if [[ ! -v BROWSER || -z $BROWSER ]]; then
echo "$0: unable to start a web browser; please set \$BROWSER"
exit 1
else
exec "$BROWSER" "${html}/share/doc/${pathName}/index.xhtml"
fi
manualPath="${html}/share/doc/${pathName}/index.html"
if [[ ! -e $manualPath ]]; then
manualPath="${html}/share/doc/${pathName}/index.xhtml"
fi
exec "$BROWSER" "$manualPath"
'';
desktopItem = makeDesktopItem {
-64
View File
@@ -1,64 +0,0 @@
# Summary
- [Preface](preface.md)
- [Introduction to Home Manager](introduction.md)
- [Installing Home Manager](installation.md)
- [Standalone installation](installation/standalone.md)
- [NixOS module](installation/nixos.md)
- [nix-darwin module](installation/nix-darwin.md)
- [Using Home Manager](usage.md)
- [Configuration Example](usage/configuration.md)
- [Rollbacks](usage/rollbacks.md)
- [Keeping your ~ safe from harm](usage/dotfiles.md)
- [Graphical services](usage/graphical.md)
- [GPU on non-NixOS systems](usage/gpu-non-nixos.md)
- [Modular Services](usage/modular-services.md)
- [Updating](usage/updating.md)
- [Upgrading to a new Home Manager release](usage/upgrading.md)
- [Nix Flakes](nix-flakes.md)
- [Prerequisites](nix-flakes/prerequisites.md)
- [Standalone setup](nix-flakes/standalone.md)
- [NixOS module](nix-flakes/nixos.md)
- [nix-darwin module](nix-flakes/nix-darwin.md)
- [flake-parts module](nix-flakes/flake-parts.md)
- [Writing Home Manager Modules](writing-modules.md)
- [Option Types](writing-modules/types.md)
- [Contributing](contributing.md)
- [Getting started](contributing/getting-started.md)
- [Guidelines](contributing/guidelines.md)
- [Release Notes](contributing/release-notes.md)
- [News](contributing/news.md)
- [Tests](contributing/tests.md)
- [Home Manager Internals](internals.md)
- [Activation](internals/activation.md)
- [Third-Party Tools and Extensions](3rd-party.md)
- [Module Collections](3rd-party/collections.md)
- [Frequently Asked Questions (FAQ)](faq.md)
- [Why is there a collision error when switching generation?](faq/collision.md)
- [Why are the session variables not set?](faq/session-variables.md)
- [How to set up a configuration for multiple users/machines?](faq/multiple-users-machines.md)
- [Why do I get an error message about `ca.desrt.dconf` or `dconf.service`?](faq/ca-desrt-dconf.md)
- [How do I install packages from Nixpkgs unstable?](faq/unstable.md)
- [How do I change the package used by a module?](faq/change-package-module.md)
- [Options](options.md)
@HOME_MANAGER_OPTIONS@
@NIXOS_OPTIONS@
@NIX_DARWIN_OPTIONS@
- [Release Notes](release-notes/release-notes.md)
- [Release 26.11](release-notes/rl-2611.md)
- [Release 26.05](release-notes/rl-2605.md)
- [Release 25.11](release-notes/rl-2511.md)
- [Release 25.05](release-notes/rl-2505.md)
- [Release 24.11](release-notes/rl-2411.md)
- [Release 24.05](release-notes/rl-2405.md)
- [Release 23.11](release-notes/rl-2311.md)
- [Release 23.05](release-notes/rl-2305.md)
- [Release 22.11](release-notes/rl-2211.md)
- [Release 22.05](release-notes/rl-2205.md)
- [Release 21.11](release-notes/rl-2111.md)
- [Release 21.05](release-notes/rl-2105.md)
- [Release 20.09](release-notes/rl-2009.md)
- [Release 20.03](release-notes/rl-2003.md)
- [Release 19.09](release-notes/rl-1909.md)
- [Release 19.03](release-notes/rl-1903.md)
- [Release 18.09](release-notes/rl-1809.md)
-11
View File
@@ -1,11 +0,0 @@
[book]
title = "Home Manager Manual"
language = "en"
src = "."
[output.html]
git-repository-url = "https://github.com/nix-community/home-manager"
[output.html.fold]
enable = true
level = 0
+2 -3
View File
@@ -3,8 +3,8 @@
Contributions to Home Manager are very welcome. To make the process as
smooth as possible for both you and the Home Manager maintainers we
provide some guidelines that we ask you to follow. See [Getting
started](contributing/getting-started.md#sec-contrib-getting-started) for information on how to set up
a suitable development environment and [Guidelines](contributing/guidelines.md#sec-guidelines) for
started](#sec-contrib-getting-started) for information on how to set up
a suitable development environment and [Guidelines](#sec-guidelines) for
the actual guidelines.
This text is mainly directed at those who would like to make code
@@ -22,7 +22,6 @@ configuration.
```{=include=} sections
contributing/getting-started.md
contributing/guidelines.md
contributing/release-notes.md
contributing/news.md
contributing/tests.md
```
+2 -2
View File
@@ -8,7 +8,7 @@ how to do this.
Once you have a fork of Home Manager you should create a branch starting
at the most recent `master` branch. Give your branch a reasonably
descriptive name. Commit your changes to this branch and when you are
happy with the result and it fulfills [Guidelines](guidelines.md#sec-guidelines) then
happy with the result and it fulfills [Guidelines](#sec-guidelines) then
push the branch to GitHub and [create a pull
request](https://help.github.com/articles/creating-a-pull-request/).
@@ -21,7 +21,7 @@ the `home-manager` command use it by either
$ home-manager -I home-manager=$HOME/devel/home-manager
```
or, if using [flakes](../nix-flakes/standalone.md#sec-flakes-standalone):
or, if using [flakes](#sec-flakes-standalone):
``` shell
$ home-manager --override-input home-manager ~/devel/home-manager
+8 -51
View File
@@ -58,38 +58,11 @@ YAML, INI, TOML, or even a plain list of key/value pairs then consider
using a `settings` option as described in [Nix RFC
42](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md).
These guidelines describe the minimum option design requirements. Before
submitting a module, compare it against the upstream documentation or
source code and verify that the generated files, services, environment
variables, and command line arguments all match the upstream behavior
you intend to expose.
If a module installs a package, try to make the package option nullable,
for example
``` nix
package = lib.mkPackageOption pkgs "xdg-terminal-exec" { nullable = true; };
```
This lets users keep installation outside Home Manager, for example via
`apt` or because the program is built into macOS, while still using the
module for configuration. Keeping the package non-nullable is fine when
the enabled behavior structurally requires the executable or when
package-less support would make the module significantly more complex.
Avoid generating files for empty settings, null packages, or optional
features that are not configured.
If upstream does not use XDG paths by default but supports changing the
configuration location with an environment variable, for example
`FOO_HOME`, expose a `configDir` option and use it to respect
`home.preferXdgDirectories`.
## Add relevant tests {#sec-guidelines-add-tests}
If at all possible, make sure to add new tests and expand existing tests
so that your change will keep working in the future. See
[Tests](tests.md#sec-tests) for more information about the Home Manager test
[Tests](#sec-tests) for more information about the Home Manager test
suite.
All contributed code *must* pass the test suite.
@@ -108,7 +81,7 @@ Manager Git repository:
``` shell
$ nix-build -A docs.html
$ xdg-open ./result/share/doc/home-manager/index.html
$ xdg-open ./result/share/doc/home-manager/index.xhtml
```
When you have made changes to a module, it is a good idea to check that
@@ -116,7 +89,7 @@ the man page version of the module options looks good:
``` shell
$ nix-build -A docs.manPages
$ man ./result/share/man/man5/home-configuration.nix.5
$ man ./result/share/man/man5/home-configuration.nix.5.gz
```
## Module Auto-importing {#sec-module-auto-importing}
@@ -182,17 +155,10 @@ consistent commit message format as described in
If your contribution includes a change that should be communicated to
users of Home Manager then you can add a news entry. The entry must be
formatted as described in [News](news.md#sec-news).
formatted as described in [News](#sec-news).
When new modules are added a news entry should be included.
News entries and release notes serve different purposes. Release notes
should be updated separately when a change affects users migrating
between stable releases, such as state version default changes, required
migration steps, or broad behavior changes. See
[Release Notes](release-notes.md#sec-contributing-release-notes) and [News](news.md#sec-news)
for more details.
## Use conditional modules and news {#sec-guidelines-conditional-modules}
Home Manager includes a number of modules that are only usable on some
@@ -200,16 +166,12 @@ of the supported platforms. The most common example of platform specific
modules are those that define systemd user services, which only works on
Linux systems.
If you add a module that is platform specific then make sure the module
guards platform-specific configuration with an appropriate condition, for
example `pkgs.stdenv.hostPlatform.isLinux` or
`pkgs.stdenv.hostPlatform.isDarwin`. Modules in `modules/programs/` and
`modules/services/` are auto-imported, so the platform condition should live
in the module behavior and in any platform-specific tests rather than in a
separate module discovery call.
If you add a module that is platform specific then make sure to include
a condition in the `loadModule` function call. This will make the module
accessible only on systems where the condition evaluates to `true`.
Similarly, if you are adding a news entry then it should be shown only
to users that may find it relevant, see [News](news.md#sec-news) for a
to users that may find it relevant, see [News](#sec-news) for a
description of conditional news.
## Mind the license {#sec-guidelines-licensing}
@@ -232,11 +194,6 @@ that is, each commit should make sense in isolation. In particular, you
will be asked to amend any commit that introduces syntax errors or
similar problems even if they are fixed in a later commit.
Keep commits atomic and separated by concern. For example, a new
maintainer entry should be a separate first commit, and a shared module
should be committed separately from integrations in existing modules.
Pull requests should not include merge commits or fixup commits.
The commit messages should follow the [seven
rules](https://chris.beams.io/posts/git-commit/#seven-rules), except for
\"Capitalize the subject line\". We also ask you to include the affected
+6 -23
View File
@@ -6,17 +6,8 @@ associated news entry. In general, a news entry should only be added for
truly noteworthy news. For example, a bug fix or new option does
generally not need a news entry.
Release notes and news entries serve different purposes. A news entry is
shown during Home Manager activation and is useful for day-to-day
communication about noteworthy changes, such as a new module, a new
feature, or a specific deprecation. Release notes are read from the
website documentation and should summarize what users need to know before
or during a stable-release upgrade. See
[Release Notes](release-notes.md#sec-contributing-release-notes) for guidance on changes
that affect stable-release upgrades.
If you do have a change worthy of a news entry then please add one in
[`news`](https://github.com/nix-community/home-manager/blob/master/modules/misc/news)
[`news.nix`](https://github.com/nix-community/home-manager/blob/master/modules/misc/news.nix)
but you should follow some basic guidelines:
- Use the included news entry generator to create a news entry file:
@@ -34,12 +25,9 @@ but you should follow some basic guidelines:
This will create a new file inside the `modules/misc/news` directory
with some placeholder information that you can edit.
- The entry condition should be as specific as possible for changes
affecting existing functionality. For example, if you are changing
or deprecating a specific option then you could restrict the news to
those users who actually use this option. Prefer a targeted
condition over skipping useful news only to avoid notifying
unaffected users.
- The entry condition should be as specific as possible. For example,
if you are changing or deprecating a specific option then you could
restrict the news to those users who actually use this option.
- Wrap the news message so that it will fit in the typical terminal,
that is, at most 80 characters wide. Ideally a bit less.
@@ -65,10 +53,6 @@ but you should follow some basic guidelines:
A new module is available: 'services.foo'.
Since this news announces newly available functionality, its
condition should not require `config.services.foo.enable`; otherwise
users who may want the new module will not see the news.
If the module is platform specific, e.g., a service module using
systemd, then a condition like
@@ -76,6 +60,5 @@ but you should follow some basic guidelines:
condition = hostPlatform.isLinux;
```
should be added to avoid showing the news on unsupported platforms.
Use the `create-news-entry` generator described above to scaffold
this entry as part of your contribution.
should be added. If you contribute a module then you don't need to
add this entry, the merger will create an entry for you.
-24
View File
@@ -1,24 +0,0 @@
# Release Notes {#sec-contributing-release-notes}
Home Manager release notes are published as part of the website documentation in
`docs/release-notes/rl-*.md`. They are intended for users migrating from one
stable release to another.
A change should be mentioned in the release notes when it affects migration
between stable releases. This includes changes that require user action or
awareness during an upgrade, such as:
- breaking changes;
- default changes guarded by `home.stateVersion`;
- required migration steps;
- broad behavior changes across platform or integration boundaries;
- compatibility changes that can affect existing configurations.
Do not use the presence or absence of a news entry to decide whether a change
belongs in the release notes. A change can require a news entry, a release note,
both, or neither.
When preparing a release, review the commits since the previous stable release
and update the upcoming release note file with the migration impact. Prefer
concise user-facing descriptions that name the affected option paths and explain
required action.
+5 -24
View File
@@ -54,13 +54,6 @@ The `default.nix` file should list all test cases:
}
```
Prefer keeping related assertions in as few test files as practical.
Exercising several cases in one evaluation keeps the test suite cheaper
to evaluate and reduces maintenance burden. Split cases into separate
files when they need incompatible module configuration, platform
conditions, expected assertion failures, or otherwise cannot share one
evaluation.
### Common NMT Assertions {#sec-tests-assertions}
NMT provides several assertion functions:
@@ -169,12 +162,6 @@ For cross-platform modules that have packages which need to be stubbed on Darwin
add the package names to `tests/darwinScrublist.nix` to prevent build failures
during cross-platform test runs.
On Linux, packages are automatically scrubbed by the test infrastructure,
so tests should normally use the module's default package. Use
`test.stubs` or `config.lib.test.mkStubPackage` only when the automatic
scrubbing does not model the behavior that the test needs, such as a
package with additional files or a non-default executable layout.
## Using the tests command {#sec-tests-command}
Home Manager provides a convenient `tests` command for discovering and running tests:
@@ -192,22 +179,16 @@ $ nix run .#tests -- alacritty
# Run a specific test
$ nix run .#tests -- test-alacritty-empty-settings
# List integration tests
# Run integration tests
$ nix run .#tests -- -t -l
# Run all integration tests
$ nix run .#tests -- -t integration-test-
# Interactive test selection (requires fzf)
$ nix run .#tests -- -i
$ python3 tests/tests.py -i
# Pass additional nix build flags
$ nix run .#tests -- alacritty -- --verbose
```
Integration tests are only exposed on Linux. On other platforms, integration
test discovery may report no matching tests.
## Manual test commands {#sec-tests-manual}
For advanced usage or CI environments, you can also run tests manually using nix build commands.
@@ -221,7 +202,7 @@ $ nix-build --pure --option allow-import-from-derivation false tests -A build.al
in the project root. List all test cases through
``` shell
$ nix run .#tests -- -l
$ nix-build --pure tests --option allow-import-from-derivation false -A list
```
and run an individual test, for example `alacritty-empty-settings`,
@@ -236,13 +217,13 @@ and may cause failures. To run against the Nixpkgs from the `flake.lock` file,
use instead e.g.
``` shell
$ nix build .#test-all
$ nix build --option allow-import-from-derivation false .#test-all
```
or
``` shell
$ nix build .#test-alacritty-empty-settings
$ nix build --option allow-import-from-derivation false .#test-alacritty-empty-settings
```
Some tests may be marked with `enableLegacyIfd`, those may be run by run with e.g.
+8 -59
View File
@@ -20,22 +20,10 @@ this package. This can typically be done in two ways.
{ pkgs, config, ... }:
let
pkgsUnstable = import <nixpkgs-unstable> {};
in
{
programs.beets.package = pkgsUnstable.beets;
# …
}
```
should work OK. With flakes, pass the unstable package set as
described in
[How do I install packages from Nixpkgs unstable?](unstable.md#_how_do_i_install_packages_from_nixpkgs_unstable)
and then use the extra module argument:
``` nix
{ pkgsUnstable, ... }:
{
programs.beets.package = pkgsUnstable.beets;
@@ -44,7 +32,9 @@ this package. This can typically be done in two ways.
}
```
2. If no `package` option is available then you can typically change
should work OK.
3. If no `package` option is available then you can typically change
the relevant package using an
[overlay](https://nixos.org/nixpkgs/manual/#chap-overlays).
@@ -55,14 +45,16 @@ this package. This can typically be done in two ways.
{ pkgs, config, ... }:
let
pkgsUnstable = import <nixpkgs-unstable> {};
in
{
programs.skim.enable = true;
nixpkgs.overlays = [
(_final: _prev: {
(self: super: {
skim = pkgsUnstable.skim;
})
];
@@ -72,46 +64,3 @@ this package. This can typically be done in two ways.
```
should work OK.
The same Home Manager overlay works in a flake-based standalone
configuration if `pkgsUnstable` is passed to the Home Manager
module:
``` nix
{ pkgsUnstable, ... }:
{
programs.skim.enable = true;
nixpkgs.overlays = [
(_final: _prev: {
skim = pkgsUnstable.skim;
})
];
# …
}
```
This also works when Home Manager is used as a NixOS or nix-darwin
module without `home-manager.useGlobalPkgs = true`. If
`home-manager.useGlobalPkgs = true` is enabled, Home Manager uses
the system package set and the `nixpkgs.*` options inside Home
Manager are disabled. In that case, put the overlay in the system
configuration instead, for example:
``` nix
{ pkgsUnstable, ... }:
{
nixpkgs.overlays = [
(_final: _prev: {
skim = pkgsUnstable.skim;
})
];
}
```
In a flake-based NixOS or nix-darwin configuration, pass
`pkgsUnstable` to `nixosSystem` or `darwinSystem` with
`specialArgs`.
+7 -82
View File
@@ -3,20 +3,22 @@
If you are using a stable version of Nixpkgs but would like to install
some particular packages from Nixpkgs unstable -- or some other channel
-- then you can import the unstable Nixpkgs and refer to its packages
within your configuration.
With channels, something like
within your configuration. Something like
``` nix
{ pkgs, config, ... }:
let
pkgsUnstable = import <nixpkgs-unstable> {};
in
{
home.packages = [
pkgsUnstable.foo
];
# …
}
```
@@ -30,82 +32,5 @@ $ nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable
$ nix-channel --update
```
With flakes, add another Nixpkgs input and pass its packages to your
Home Manager modules. For example, a standalone Home Manager flake can
define the following. Replace 25.11 with the release branch your
configuration follows.
``` nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager/release-25.11";
};
outputs =
{ nixpkgs, nixpkgs-unstable, home-manager, ... }:
let
# Replace this with the system of your Home Manager configuration.
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
pkgsUnstable = nixpkgs-unstable.legacyPackages.${system};
in
{
homeConfigurations.jdoe = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
extraSpecialArgs = { inherit pkgsUnstable; };
modules = [ ./home.nix ];
};
};
}
```
and then use the extra argument in `home.nix`:
``` nix
{ pkgsUnstable, ... }:
{
home.packages = [
pkgsUnstable.foo
];
}
```
When Home Manager is used as a NixOS or nix-darwin module, pass the
extra package set with `home-manager.extraSpecialArgs` in the system
configuration:
``` nix
outputs =
{ nixpkgs, nixpkgs-unstable, home-manager, ... }:
let
# Replace this with the system of your NixOS or nix-darwin configuration.
system = "x86_64-linux";
in
{
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
home-manager.nixosModules.home-manager
({ config, ... }: {
home-manager.extraSpecialArgs = {
pkgsUnstable = import nixpkgs-unstable {
inherit system;
config = config.nixpkgs.config;
overlays = config.nixpkgs.overlays;
};
# If you use a stock Nixpkgs configuration, you can use:
# pkgsUnstable = nixpkgs-unstable.legacyPackages.${system};
};
})
];
};
};
```
The nix-darwin setup is the same pattern with
`darwin.lib.darwinSystem` and
`home-manager.darwinModules.home-manager`.
Note, the package will not be affected by any package overrides,
overlays, etc.
+4 -4
View File
@@ -6,26 +6,26 @@ Home Manager can be used in three primary ways:
NixOS and Darwin, this is the only available choice. It is also
recommended for people on NixOS or Darwin that want to manage their
home directory independently of the system as a whole. See
[Standalone installation](installation/standalone.md#sec-install-standalone) for instructions
[Standalone installation](#sec-install-standalone) for instructions
on how to perform this installation.
2. As a module within a NixOS system configuration. This allows the
user profiles to be built together with the system when running
`nixos-rebuild`. See [NixOS module](installation/nixos.md#sec-install-nixos-module) for a
`nixos-rebuild`. See [NixOS module](#sec-install-nixos-module) for a
description of this setup.
3. As a module within a
[nix-darwin](https://github.com/nix-darwin/nix-darwin/) system
configuration. This allows the user profiles to be built together
with the system when running `darwin-rebuild`. See [nix-darwin
module](installation/nix-darwin.md#sec-install-nix-darwin-module) for a description of this
module](#sec-install-nix-darwin-module) for a description of this
setup.
:::{.note}
In this chapter we describe how to install Home Manager in the standard
way using channels. If you prefer to use [Nix
Flakes](https://wiki.nixos.org/wiki/Flakes) then please see the instructions
in [nix flakes](nix-flakes.md#ch-nix-flakes).
in [nix flakes](#ch-nix-flakes).
:::
```{=include=} sections
+13 -26
View File
@@ -5,9 +5,9 @@ environments directly from the
[nix-darwin](https://github.com/nix-darwin/nix-darwin/) configuration file,
which often is more convenient than using the `home-manager` tool.
To make the nix-darwin module available for use you must `import` it
into your system configuration. This is most conveniently done by adding
a Home Manager channel. For example, if you are following Nixpkgs master
To make the NixOS module available for use you must `import` it into
your system configuration. This is most conveniently done by adding a
Home Manager channel. For example, if you are following Nixpkgs master
or an unstable channel, you can run
``` shell
@@ -15,10 +15,10 @@ $ nix-channel --add https://github.com/nix-community/home-manager/archive/master
$ nix-channel --update
```
and if you follow a Nixpkgs version 26.05 channel, you can run
and if you follow a Nixpkgs version 25.11 channel, you can run
``` shell
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-26.05.tar.gz home-manager
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ nix-channel --update
```
@@ -28,9 +28,9 @@ It is then possible to add
imports = [ <home-manager/nix-darwin> ];
```
to your nix-darwin `configuration.nix` file, which will introduce a
`home-manager.users` option whose type is an attribute set that maps
user names to Home Manager configurations.
to your nix-darwin `configuration.nix` file, which will introduce a new
NixOS option called `home-manager` whose type is an attribute set that
maps user names to Home Manager configurations.
For example, a nix-darwin configuration may include the lines
@@ -45,16 +45,13 @@ home-manager.users.eve = { pkgs, ... }: {
# The state version is required and should stay at the version you
# originally installed.
home.stateVersion = "26.05";
home.stateVersion = "25.11";
};
```
and after a `darwin-rebuild switch` the user eve's environment should
include a basic Bash configuration and the packages atool and httpie.
Home Manager activation runs as part of nix-darwin activation for each
configured user.
If you do not plan on having Home Manager manage your shell
configuration then you must add either
@@ -106,23 +103,13 @@ Nixpkgs.
:::
:::{.note}
Home Manager passes extra module arguments to each
`home-manager.users.<name>` module:
Home Manager will pass `osConfig` as a module argument to any modules
you create. This contains the system's nix-darwin configuration.
``` nix
{ lib, pkgs, osConfig, darwinConfig, osClass, modulesPath, ... }:
{ lib, pkgs, osConfig, ... }:
```
Here `osConfig` contains the system's nix-darwin configuration and
`darwinConfig` is a Darwin-specific alias for the same value. The `lib`
argument is Home Manager's extended library. You can pass additional module
arguments with `home-manager.extraSpecialArgs`.
:::
:::{.note}
Use `home-manager.sharedModules` to add Home Manager modules to every user
declared under `home-manager.users`.
:::
Once installed you can see [Using Home Manager](../usage.md#ch-usage) for a more detailed
Once installed you can see [Using Home Manager](#ch-usage) for a more detailed
description of Home Manager and how to use it.
+12 -30
View File
@@ -17,10 +17,10 @@ $ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/m
$ sudo nix-channel --update
```
and if you follow a Nixpkgs version 26.05 channel, you can run
and if you follow a Nixpkgs version 25.11 channel, you can run
``` shell
$ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-26.05.tar.gz home-manager
$ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ sudo nix-channel --update
```
@@ -39,7 +39,7 @@ Alternatively, home-manager installation can be done declaratively through confi
{ config, pkgs, lib, ... }:
let
home-manager = builtins.fetchTarball https://github.com/nix-community/home-manager/archive/release-26.05.tar.gz;
home-manager = builtins.fetchTarball https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz;
in
{
imports =
@@ -54,7 +54,7 @@ in
# The state version is required and should stay at the version you
# originally installed.
home.stateVersion = "26.05";
home.stateVersion = "25.11";
};
}
```
@@ -74,7 +74,7 @@ home-manager.users.eve = { pkgs, ... }: {
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
home.stateVersion = "26.05"; # Please read the comment before changing.
home.stateVersion = "25.11"; # Please read the comment before changing.
};
```
@@ -85,21 +85,12 @@ httpie.
:::{.note}
If `nixos-rebuild switch` does not result in the environment you expect,
then the service to inspect depends on the activation mode.
By default, Home Manager activates each configured user during boot and
system rebuilds through a NixOS system service:
you can take a look at the output of the Home Manager activation script
output using
``` shell
$ systemctl status "home-manager-$USER.service"
```
If `home-manager.startAsUserService = true` is set, Home Manager instead
activates through the user's systemd service:
``` shell
$ systemctl --user status home-manager.service
```
:::
If you do not plan on having Home Manager manage your shell
@@ -153,23 +144,14 @@ Nixpkgs.
:::
:::{.note}
Home Manager passes extra module arguments to each
`home-manager.users.<name>` module:
Home Manager will pass `osConfig` as a module argument to any modules
you create. This contains the system's NixOS configuration.
``` nix
{ lib, pkgs, osConfig, nixosConfig, osClass, modulesPath, ... }:
{ lib, pkgs, osConfig, ... }:
```
Here `osConfig` contains the system's NixOS configuration and `nixosConfig`
is a NixOS-specific alias for the same value. The `lib` argument is Home
Manager's extended library. You can pass additional module arguments with
`home-manager.extraSpecialArgs`.
:::
:::{.note}
Use `home-manager.sharedModules` to add Home Manager modules to every user
declared under `home-manager.users`.
:::
Once installed you can see [Using Home Manager](../usage.md#ch-usage) for a more detailed
Once installed you can see [Using Home Manager](#ch-usage) for a more detailed
description of Home Manager and how to use it.
+3 -3
View File
@@ -19,10 +19,10 @@
$ nix-channel --update
```
and if you follow a Nixpkgs version 26.05 channel you can run
and if you follow a Nixpkgs version 25.11 channel you can run
``` shell
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-26.05.tar.gz home-manager
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ nix-channel --update
```
@@ -71,5 +71,5 @@ checkout of the repository then you can use the
[home-manager.path](#opt-programs.home-manager.path) option to specify the absolute
path to the repository.
Once installed you can see [Using Home Manager](../usage.md#ch-usage) for a more detailed
Once installed you can see [Using Home Manager](#ch-usage) for a more detailed
description of Home Manager and how to use it.
+1 -1
View File
@@ -1,6 +1,6 @@
# Home Manager Manual {#home-manager-manual}
## Version 26.11 (unstable)
## Version 26.05 (unstable)
```{=include=} preface
+8 -28
View File
@@ -12,40 +12,18 @@ flake in three ways:
NixOS and Darwin, this is the only available choice. It is also
recommended for people on NixOS or Darwin that want to manage their
home directory independently of the system as a whole. See
[Standalone setup](nix-flakes/standalone.md#sec-flakes-standalone) for instructions on how
[Standalone setup](#sec-flakes-standalone) for instructions on how
to perform this installation.
2. As a module within a NixOS system configuration. This allows the
user profiles to be built together with the system when running
`nixos-rebuild`. See [NixOS module](nix-flakes/nixos.md#sec-flakes-nixos-module) for a
`nixos-rebuild`. See [NixOS module](#sec-flakes-nixos-module) for a
description of this setup.
3. As a module within a [nix-darwin](https://github.com/nix-darwin/nix-darwin/)
system configuration. This allows the user profiles to be built
together with the system when running `darwin-rebuild`. See
[nix-darwin module](nix-flakes/nix-darwin.md#sec-flakes-nix-darwin-module) for a
description of this setup.
Advanced users may want Home Manager's `nixpkgs` input to follow the
same Nixpkgs input as the rest of their flake. This avoids a second
Nixpkgs input and makes Home Manager use the same pinned Nixpkgs source
revision as the rest of the configuration:
``` nix
home-manager.inputs.nixpkgs.follows = "nixpkgs";
```
This removes the compatibility assumption between Home Manager and the
Nixpkgs revision in Home Manager's own lock file, so use it carefully,
especially when tracking unstable branches.
This does not by itself make Home Manager use the same `pkgs` value as
your NixOS or nix-darwin system. In NixOS and nix-darwin module setups,
`home-manager.useGlobalPkgs = true` controls that behavior by making
Home Manager modules receive the system `pkgs` value. When
`home-manager.useGlobalPkgs` is enabled, configure Nixpkgs overlays and
configuration at the system level instead of through Home Manager
`nixpkgs.*` options.
3. This allows the user profiles to be built together with the system
when running `darwin-rebuild`. See [nix-darwin
module](#sec-flakes-nix-darwin-module) for a description of this
setup.
```{=include=} sections
nix-flakes/prerequisites.md
@@ -54,3 +32,5 @@ nix-flakes/nixos.md
nix-flakes/nix-darwin.md
nix-flakes/flake-parts.md
```
+2 -1
View File
@@ -8,8 +8,9 @@ Manager's flake module, `flakeModules.home-manager`.
description = "flake-parts configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
flake-parts.url = "github:hercules-ci/flake-parts";
};
+7 -19
View File
@@ -8,10 +8,11 @@ to that of NixOS. The `flake.nix` would be:
description = "Darwin configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
darwin.url = "github:nix-darwin/nix-darwin";
darwin.inputs.nixpkgs.follows = "nixpkgs";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ nixpkgs, home-manager, darwin, ... }: {
@@ -24,8 +25,10 @@ to that of NixOS. The `flake.nix` would be:
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.jdoe = ./home.nix;
# Optionally, use home-manager.extraSpecialArgs to pass
# arguments to home.nix
}
];
};
@@ -34,23 +37,8 @@ to that of NixOS. The `flake.nix` would be:
}
```
Use `home-manager.extraSpecialArgs` to pass arguments from your flake to
`home.nix` and any imported Home Manager modules. For example, the
configuration above makes the complete `inputs` attrset available to modules,
so they can declare arguments such as `{ inputs, ... }:`.
The lower-level mechanism behind this is `_module.args`. Set
`_module.args.<name>` from inside a module only when you need to provide a
module argument from within the module graph itself. For values that originate
outside the module graph, such as flake inputs, prefer
`home-manager.extraSpecialArgs`.
Use `home-manager.sharedModules` for Home Manager modules or settings that
should be imported by every user declared in `home-manager.users`.
The Home Manager configuration is also rebuilt with the nix-darwin
generations. The rebuild command here may be
`darwin-rebuild switch --flake ~/.config/darwin`.
and it is also rebuilt with the nix-darwin generations. The rebuild
command here may be `darwin-rebuild switch --flake <flake-uri>`.
You can use the above `flake.nix` as a template in `~/.config/darwin` by
+6 -20
View File
@@ -8,8 +8,9 @@ be as follows:
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ nixpkgs, home-manager, ... }: {
@@ -22,8 +23,10 @@ be as follows:
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.jdoe = ./home.nix;
# Optionally, use home-manager.extraSpecialArgs to pass
# arguments to home.nix
}
];
};
@@ -32,27 +35,10 @@ be as follows:
}
```
Use `home-manager.extraSpecialArgs` to pass arguments from your flake to
`home.nix` and any imported Home Manager modules. For example, the
configuration above makes the complete `inputs` attrset available to modules,
so they can declare arguments such as `{ inputs, ... }:`.
The lower-level mechanism behind this is `_module.args`. Set
`_module.args.<name>` from inside a module only when you need to provide a
module argument from within the module graph itself. For values that originate
outside the module graph, such as flake inputs, prefer
`home-manager.extraSpecialArgs`.
Use `home-manager.sharedModules` for Home Manager modules or settings that
should be imported by every user declared in `home-manager.users`.
The Home Manager configuration is then part of the NixOS configuration
and is automatically rebuilt with the system when using the appropriate
command for the system, such as
``` shell
$ nixos-rebuild switch --flake /etc/nixos
```
`nixos-rebuild switch --flake <flake-uri>`.
You can use the above `flake.nix` as a template in `/etc/nixos` by
+1 -1
View File
@@ -33,5 +33,5 @@
Unlike the channel-based setup, `home.nix` will be evaluated when
the flake is built, so it must be present before bootstrap of Home
Manager from the flake. See [Configuration Example](../usage/configuration.md#sec-usage-configuration) for
Manager from the flake. See [Configuration Example](#sec-usage-configuration) for
introduction about writing a Home Manager configuration.
+11 -39
View File
@@ -11,44 +11,15 @@ then to generate and activate a basic configuration run the command
$ nix run home-manager/master -- init --switch
```
For Nixpkgs or NixOS version 26.05 run
For Nixpkgs or NixOS version 25.11 run
``` shell
$ nix run home-manager/release-26.05 -- init --switch
$ nix run home-manager/release-25.11 -- init --switch
```
This will generate a `flake.nix` and a `home.nix` file in
`~/.config/home-manager`, creating the directory if it does not exist.
If you need to pass additional values from your flake to `home.nix` or any
imported Home Manager modules, use `extraSpecialArgs` in the call to
`home-manager.lib.homeManagerConfiguration`:
``` nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager";
};
outputs = inputs@{ nixpkgs, home-manager, ... }: {
homeConfigurations.jdoe = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
extraSpecialArgs = { inherit inputs; };
modules = [ ./home.nix ];
};
};
}
```
Any attribute in `extraSpecialArgs` becomes a module argument, so `home.nix`
or imported modules can declare arguments such as `{ inputs, ... }:`.
The lower-level mechanism behind this is `_module.args`. Set
`_module.args.<name>` from inside a module only when you need to provide a
module argument from within the module graph itself. For values that originate
outside the module graph, such as flake inputs, prefer `extraSpecialArgs`.
If you omit the `--switch` option then the activation will not happen.
This is useful if you want to inspect and edit the configuration before
activating it.
@@ -59,7 +30,7 @@ $ # Edit files in ~/.config/home-manager
$ nix run home-manager/$branch -- init --switch
```
Where `$branch` is one of `master` or `release-26.05`.
Where `$branch` is one of `master` or `release-25.11`.
After the initial activation has completed successfully then building
and activating your flake-based configuration is as simple as
@@ -78,13 +49,14 @@ $ home-manager switch --flake ~/hmconf
```
::: {.note}
The flake inputs are not automatically updated by Home Manager. Update
the lock file with `nix flake update` before switching if you want to
use newer input revisions.
The flake inputs are not automatically updated by Home Manager. You need
to use the standard `nix flake update` command for that.
If you only want to update specific flake inputs, name them explicitly,
for example `nix flake update nixpkgs home-manager`.
If you only want to update a single flake input, then the command
`nix flake lock --update-input <input>` can be used.
These commands assume that your current directory is the flake. If not,
pass the flake path or URI with `--flake <flake-uri>`.
You can also pass flake-related options such as `--recreate-lock-file`
or `--update-input <input>` to `home-manager` when building or
switching, and these options will be forwarded to `nix build`. See the
[NixOS Wiki page](https://wiki.nixos.org/wiki/Flakes) for details.
:::
+1 -2
View File
@@ -43,7 +43,7 @@ option will state the expected type, for
[programs.emacs.enable](#opt-programs.emacs.enable) you will see "Type: boolean". You
there also find information about the default value and a description of
the option. You can find the complete option documentation in
[Home Manager Configuration Options](options.md#ch-options) or directly in the terminal by running
[Home Manager Configuration Options](#ch-options) or directly in the terminal by running
``` shell
man home-configuration.nix
@@ -60,7 +60,6 @@ usage/rollbacks.md
usage/dotfiles.md
usage/graphical.md
usage/gpu-non-nixos.md
usage/modular-services.md
usage/updating.md
usage/upgrading.md
```
+2 -2
View File
@@ -20,7 +20,7 @@ A fresh install of Home Manager will generate a minimal
# You can update Home Manager without changing this value. See
# the Home Manager release notes for a list of state version
# changes in each release.
home.stateVersion = "26.05";
home.stateVersion = "25.11";
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
@@ -65,7 +65,7 @@ follows:
# You can update Home Manager without changing this value. See
# the Home Manager release notes for a list of state version
# changes in each release.
home.stateVersion = "26.05";
home.stateVersion = "25.11";
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
-133
View File
@@ -34,136 +34,3 @@ Activating checkLinkTargets
Existing file '/home/jdoe/.config/git/config' is in the way
Please move the above files and try again
```
This error is about a file that Home Manager wants to manage as a
symbolic link in your home directory. It is separate from package
profile collisions, which usually mention `installPackages` or a
`collision between .../bin/...` path. For package collisions, see
[Why is there a collision error when switching generation?](../faq/collision.md#_why_is_there_a_collision_error_when_switching_generation).
## Resolving file collisions {#sec-usage-dotfiles-collisions}
The safest resolution is to inspect the existing path, move any
settings you want Home Manager to manage into your configuration, and
remove or move the unmanaged file before switching again.
For a standalone Home Manager installation, you can ask Home Manager to
move unmanaged non-symlink paths out of the way during activation:
``` shell
home-manager switch -b backup
```
With the command above, a colliding `~/.config/git/config` is moved to
`~/.config/git/config.backup` before Home Manager links the managed
file. If the backup path already exists then activation still aborts, so
choose an extension whose backup path does not already exist.
Standalone activation can also run a custom command for each collision:
``` shell
home-manager switch -B trash-put
```
The command receives the colliding path as an argument and must move or
remove that path. If both `-B` and `-b` are set, the custom command takes
precedence; the command may still use the
`HOME_MANAGER_BACKUP_EXT` environment variable set by `-b`.
When Home Manager is used as a NixOS or nix-darwin module, configure the
corresponding module options instead of passing standalone command line
flags:
``` nix
{
home-manager.backupFileExtension = "backup";
}
```
or
``` nix
{
home-manager.backupCommand = "${pkgs.trash-cli}/bin/trash-put";
}
```
If both {option}`home-manager.backupCommand` and
{option}`home-manager.backupFileExtension` are set, the command takes
precedence. The extension is still exported to the command as
`HOME_MANAGER_BACKUP_EXT`, so the command can use it when implementing
its own backup naming. With
{option}`home-manager.backupFileExtension`, Home Manager refuses to
replace an existing backup path unless
{option}`home-manager.overwriteBackup` is enabled:
``` nix
{
home-manager.backupFileExtension = "backup";
home-manager.overwriteBackup = true;
}
```
::: {.warning}
{option}`home-manager.overwriteBackup` allows activation to clobber
existing backup files. Only enable it when those backup paths are
disposable.
:::
For individual files, many file options also support `force = true`:
``` nix
{
home.file.".config/example" = {
source = ./example;
force = true;
};
}
```
This skips the collision check for the affected target and lets Home
Manager replace the existing file or link. Use it sparingly; it can
silently delete local changes.
Backup commands and backup extensions are intended for unmanaged
non-symlink paths. If the colliding target is an unmanaged symbolic
link, move it manually or use `force = true` after checking that the
link target is safe to replace.
## Advanced file behavior {#sec-usage-dotfiles-advanced}
The notes below apply to {option}`home.file` and to options based on the
same file type, such as {option}`xdg.configFile`.
When a file source is a directory, {option}`home.file.<name>.recursive`
changes how the directory is linked. With the default `recursive =
false`, the target is one symbolic link to the source directory. With
`recursive = true`, Home Manager creates a matching directory tree and
links each leaf file into it.
Recursive directory linking has special overlap behavior. A direct
duplicate target, such as two managed files both targeting `foo`, is an
error. If a recursively linked directory provides `foo/bar` and another
managed file also targets `foo/bar`, Home Manager keeps the recursive
file by default and ignores the overlapping regular file.
The {option}`home.file.<name>.onChange` hook runs after the new files
are linked. For recursive file entries, the hook is always run, so it
should be written to be safe even when no leaf file actually changed.
Normally a path assigned to {option}`home.file.<name>.source` is copied
or linked through the Nix store. To make Home Manager create a link to a
live path outside the store, use
`config.lib.file.mkOutOfStoreSymlink`:
``` nix
{ config, ... }:
{
home.file.".config/example".source =
config.lib.file.mkOutOfStoreSymlink ./example;
}
```
This is useful when the target should follow changes to a mutable file
or directory outside the store.
+5 -6
View File
@@ -38,17 +38,16 @@ GPU drivers require an update, run
Because the `/run` directory is volatile and disappears on reboot, libraries
cannot be simply copied or linked there. The `non-nixos-gpu-setup` script
installs a
[`tmpfiles.d`](https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html)
config which ensures that the drivers are linked to `/run/opengl-driver` on
boot. Home Manager will always check and warn you when this setup needs to be
refreshed.
installs a Systemd service which ensures that the drivers are linked to
`/run/opengl-driver` on boot. Home Manager will always check and warn you when
this setup needs to be refreshed.
If you ever wish to uninstall these drivers, all you need to do is
```sh
sudo rm /run/opengl-driver
sudo rm /etc/tmpfiles.d/non-nixos-gpu.conf
sudo systemctl disable --now non-nixos-gpu.service
sudo rm /etc/systemd/system/non-nixos-gpu.service
```
-119
View File
@@ -1,119 +0,0 @@
# Modular Services {#sec-usage-modular-services}
Home Manager supports nixpkgs
[modular services](https://nixos.org/manual/nixos/unstable/#modular-services)
under [](#opt-home.services). This is the Home Manager analog to the
NixOS `system.services` namespace: each entry is an abstract service
sourced from `<nixpkgs/lib/services/lib.nix>` with the upstream portable
systemd module loaded into it, so service modules shipped with packages
(e.g. `pkgs.<name>.passthru.services.default`) drop in unchanged --
the same module evaluates on NixOS and on Home Manager.
A minimal example -- run mpd as a user service:
```nix
{ pkgs, ... }: {
home.services.mpd = {
process.argv = [ "${pkgs.mpd}/bin/mpd" "--no-daemon" ];
};
}
```
This produces `~/.config/systemd/user/mpd.service` with `ExecStart` set
to the mpd binary and `WantedBy=default.target`.
Each service exposes the upstream NixOS-style schema: [`process.argv`],
`systemd.lib`, `systemd.mainExecStart`, `systemd.service`,
`systemd.services`, `systemd.sockets`. Lifted units are translated from
NixOS-style attrs (`wantedBy`, `serviceConfig`, `unitConfig`,
`environment`, ...) into the section-based INI shape
(`{ Unit; Service; Install; }`) that Home Manager's
[](#opt-systemd.user.services) consumes. Only common keys are mapped
explicitly; uncommon options remain reachable via `unitConfig`,
`serviceConfig`, or `socketConfig`.
Sub-services (nested `services.<sub>` inside another service) and their
units are dashed under the parent service name. The empty unit key
`""` denotes the service's *primary* unit (lifted to a unit named
after the service itself); [`process.argv`] becomes the default
`ExecStart` for that unit, which defaults to `WantedBy=default.target`.
## Reusing upstream package modules {#sec-usage-modular-services-upstream}
Modular services exposed by packages under
`pkgs.<name>.passthru.services.default` can be imported directly.
For example, `pkgs.php`'s [`php-fpm`]:
```nix
{ pkgs, ... }: {
home.services."php-fpm" = {
imports = [ pkgs.php.passthru.services.default ];
configData."php-fpm.conf".source = builtins.elemAt config.home.services.php-fpm.process.argv 2;
php-fpm.settings.mypool = {
listen = "127.0.0.1:9000";
# FIXME: required by upstream modular service, but ignored when run as user
"user" = "";
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.min_spare_servers" = 5;
"pm.max_spare_servers" = 20;
};
};
}
```
Some packages ship modules written for system services that include
directives the user-session manager cannot honour (`DynamicUser`,
`AmbientCapabilities`, ...). The unit is still generated with those
directives -- user systemd silently ignores what it cannot apply.
`WantedBy=multi-user.target` is automatically normalized to
`WantedBy=default.target`. Other directives can be overridden per
service:
```nix
home.services."tunnel" = {
imports = [ pkgs.ghostunnel.passthru.services.default ];
# ...
systemd.services."tunnel".serviceConfig.DynamicUser = lib.mkForce false;
};
```
## Configuration data {#sec-usage-modular-services-configdata}
Each service can declare configuration files via `configData.<name>`.
These are materialized at `$XDG_CONFIG_HOME/home-services/<service>/<name>`
(mirroring how NixOS lifts `configData` to `environment.etc`), with the
absolute path injected back into `configData.<name>.path` so the service
can refer to its files at a stable location:
```nix
{ config, ... }:
{
home.services.demo = {
process.argv = [ "/bin/myapp" "--config" config.home.services.demo.configData."app.toml".path ];
configData."app.toml".text = ''
port = 1234
'';
};
}
```
The store paths of all enabled `configData` entries are automatically
added to the primary unit's `X-Reload-Triggers`, so `home-manager switch`
restarts the service whenever any of its configuration files change. To
reload instead of restart, override `X-SwitchMethod`:
```nix
home.services.demo.systemd.services."".unitConfig.X-SwitchMethod = "reload";
```
## Scope notes {#sec-usage-modular-services-scope}
Home Manager mirrors the surface of nixpkgs' portable systemd module:
services and sockets only. Other unit kinds Home Manager supports
natively under [](#opt-systemd.user.services) (timers, paths, mounts, ...)
are intentionally not modeled on `home.services` until upstream grows them,
to keep both surfaces aligned.
[`process.argv`]: https://nixos.org/manual/nixos/unstable/#service-opt-process.argv
[`php-fpm`]: https://nixos.org/manual/nixos/stable/options#opt-_imports_=___pkgs.php.services.default___
+3 -75
View File
@@ -1,64 +1,8 @@
# Updating {#sec-updating}
Updating means moving to a newer revision of the Home Manager branch
that your configuration already follows. For example, a configuration
using `release-25.11` can update to a newer revision of `release-25.11`
without changing release branches.
If you want to move from one release branch to another, such as
`release-25.05` to `release-25.11`, or between a release branch and
`master`, see
[Upgrading to a new Home Manager release](upgrading.md#sec-upgrade-release).
## Flake-Based Configurations {#sec-updating-flakes}
Flake inputs are pinned in `flake.lock`, and Home Manager will keep using
the pinned revisions until you update that lock file.
To update all inputs in the flake:
``` shell
$ nix flake update
```
To update only specific inputs, name them explicitly:
``` shell
$ nix flake update home-manager nixpkgs
```
These commands assume that your current directory is the flake. If not,
pass the flake path or URI with `--flake <flake-uri>`.
After updating the lock file, rebuild with the command for your
installation method.
For a standalone Home Manager flake:
``` shell
$ home-manager switch --flake .
```
For Home Manager as a NixOS module:
``` shell
$ sudo nixos-rebuild switch --flake .
```
For Home Manager as a nix-darwin module:
``` shell
$ darwin-rebuild switch --flake .
```
## Channel-Based Configurations {#sec-updating-channels}
Channels are mutable references outside the Home Manager configuration
itself. Updating a channel moves it to a newer revision of the same
channel or branch.
For a standalone Home Manager channel installation, update the user's
channels and then switch:
If you have installed Home Manager using the Nix channel method then
updating Home Manager is done by first updating the channel. You can
then switch to the updated Home Manager environment.
``` shell
$ nix-channel --update
@@ -66,19 +10,3 @@ $ nix-channel --update
unpacking channels...
$ home-manager switch
```
For Home Manager as a NixOS module, update the root user's Home Manager
channel and rebuild the system:
``` shell
$ sudo nix-channel --update home-manager
$ sudo nixos-rebuild switch
```
For Home Manager as a nix-darwin module, update the Home Manager channel
used by your nix-darwin configuration and rebuild the system:
``` shell
$ nix-channel --update home-manager
$ darwin-rebuild switch
```
+60 -114
View File
@@ -2,47 +2,66 @@
## Overview {#sec-upgrade-release-overview}
When moving your configuration to a new Nixpkgs release branch, you
should also move Home Manager to the matching release branch. On NixOS
this usually means upgrading Home Manager together with NixOS. On
standalone and nix-darwin installations, match Home Manager to the
Nixpkgs branch used by your configuration. The examples below use 25.11;
replace this with the release branch you are upgrading to.
If your configuration follows `nixos-unstable` or `nixpkgs-unstable`,
use Home Manager's `master` branch.
When upgrading NixOS to a new major version (e.g., from 24.11 to
25.05), you also need to upgrade your Home Manager channel to maintain
compatibility. This guide covers the proper steps to upgrade Home
Manager channels for NixOS 25.05.
## Understanding Home Manager Versioning {#sec-upgrade-release-understanding-versioning}
Home Manager follows NixOS release cycles and provides corresponding branches:
- **release-\<version\>**: Stable branch for the matching NixOS or
Nixpkgs release, such as `release-25.11`.
- **release-##.##**: Stable branch for NixOS ##.## (current stable)
- **master**: Development branch (tracks nixpkgs-unstable)
- **master**: Development branch (tracks nixos-unstable)
:::{.note}
Use the Home Manager branch that matches the Nixpkgs branch used to
evaluate your Home Manager configuration. For stable NixOS
configurations, this is normally the same as your NixOS version.
Always use the Home Manager version that matches your NixOS version to
avoid compatibility issues.
:::
## Flake-Based Installation {#sec-upgrade-release-understanding-flake}
## Channel-Based Installation (Traditional) {#sec-upgrade-release-understanding-channel}
If you are using Home Manager with Nix flakes, update your `nixpkgs` and
`home-manager` inputs together:
1. First, verify your current Home Manager channel:
``` shell
$ nix-channel --list
```
You should see something like:
```
home-manager https://github.com/nix-community/home-manager/archive/release-24.11.tar.gz
```
1. Update the Home Manager channel to a NixOS 25.05 compatible version:
``` shell
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.05.tar.gz home-manager
$ nix-channel --update
```
1. Apply the changes:
``` shell
$ home-manager switch
```
## Flake-Based Installation (Modern) {#sec-upgrade-release-understanding-flake}
If you're using Home Manager with Nix flakes, update your `flake.nix`:
```nix
{
description = "Home Manager configuration";
inputs = {
# Match the Nixpkgs branch to the release you are using.
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
# Increment release branch for NixOS
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
home-manager = {
# Match the Home Manager branch to the Nixpkgs branch above.
url = "github:nix-community/home-manager/release-25.11";
# Follow corresponding `release` branch from Home Manager
url = "github:nix-community/home-manager/release-25.05";
inputs.nixpkgs.follows = "nixpkgs";
};
};
@@ -55,126 +74,54 @@ If you are using Home Manager with Nix flakes, update your `nixpkgs` and
}
```
For `nixos-unstable` or `nixpkgs-unstable`, use the `master` branch
instead:
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
home-manager = {
url = "github:nix-community/home-manager";
};
};
}
```
Then update the lock file and rebuild using the command for your
installation method.
For a standalone Home Manager flake:
Then update and rebuild. If you are using Home Manager standalone:
``` shell
$ nix flake update
$ home-manager switch --flake .
```
For Home Manager as a NixOS module:
And if you are using Home Manager as a NixOS module then you will need
to update your system configuration instead and run
``` shell
$ nix flake update
$ sudo nixos-rebuild switch --flake .
```
For Home Manager as a nix-darwin module:
``` shell
$ nix flake update
$ darwin-rebuild switch --flake .
```
These commands assume that your current directory is the flake. If not,
pass the flake path or URI with `--flake <flake-uri>`.
## Channel-Based Installation {#sec-upgrade-release-understanding-channel}
For a standalone channel-based installation, first verify your current
Home Manager channel:
``` shell
$ nix-channel --list
```
The entry identifies the Home Manager branch currently in use. For
example:
```
home-manager https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz
```
Update the Home Manager channel to the branch matching your Nixpkgs
release, then switch:
``` shell
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ nix-channel --update
$ home-manager switch
```
When Home Manager is installed as a NixOS module with channels, update
the root user's Home Manager channel and rebuild the system:
``` shell
$ sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ sudo nix-channel --update
$ sudo nixos-rebuild switch
```
When Home Manager is installed as a nix-darwin module with channels,
update the Home Manager channel used by your nix-darwin configuration
and rebuild the system:
``` shell
$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
$ nix-channel --update
$ darwin-rebuild switch
```
## State Version Management {#sec-upgrade-release-state-version}
:::{.warning}
Careful updating your `home.stateVersion` when upgrading Home Manager.
:::
The `stateVersion` should remain set to the Home Manager release you
first used for this home configuration.
The `stateVersion` is best to remain set to the NixOS version you
**first installed** Home Manager
```nix
{
# Example: if this home configuration was first created on 24.11.
home.stateVersion = "24.11";
home.stateVersion = "24.11"; # Example: if you first installed on 24.11
}
```
**Why?** The `stateVersion` ensures backward compatibility and
prevents breaking changes from affecting your existing configuration.
**Remember:** Channel or flake input version is not the same as state
version. Update Home Manager, keep `home.stateVersion` unchanged, and
only change it after reading the release notes and migrating any
affected configuration.
**Remember:** Channel version is not the same as State version. Update
the channel, keep the `stateVersion` unchanged. Advanced users can
view the changes between releases and see if any of the `stateVersion`
changes will affect them and increment, if they migrate their
configurations to follow the changed evaluation.
## Troubleshooting {#sec-upgrade-release-state-troubleshooting}
### Common Issues {#sec-upgrade-release-state-troubleshooting-common-issues}
Check the [Home Manager Release Notes](../release-notes/release-notes.md#ch-release-notes) for breaking changes.
Check the [Home Manager Release Notes](#ch-release-notes) for breaking changes.
1. **Version Mismatch Warning**: If you see warnings about version
mismatches, ensure your Home Manager branch matches the Nixpkgs
branch used by your configuration. For NixOS stable releases, this
usually means matching your NixOS version.
mismatches, ensure your Home Manager version matches your NixOS
version.
1. **Module Changes**: Modules are constantly being updated with new
features to keep up with changes in upstream packaging or to fix
@@ -182,8 +129,8 @@ Check the [Home Manager Release Notes](../release-notes/release-notes.md#ch-rele
there was something noted in the release notes or news entries.
1. **Channel Not Found**: If `nix-channel --list` shows no channels,
you might be using a different installation method, such as flakes,
or Home Manager may be imported through your system configuration.
you might be using a different installation method (like flakes or
NixOS module).
### Verification {#sec-upgrade-release-state-troubleshooting-verification}
@@ -193,10 +140,9 @@ After upgrading, verify the installation:
$ home-manager --version
```
This should show the Home Manager version or indicate that it is using
the expected release branch.
This should show version 25.05 or indicate it's using the release-25.05 branch.
## Additional Resources {#sec-upgrade-release-resources}
- [NixOS Stable Release Notes](https://nixos.org/manual/nixos/stable/release-notes)
- [Home Manager Release Notes](../release-notes/release-notes.md#ch-release-notes)
- [Home Manager Release Notes](#ch-release-notes)
+1 -1
View File
@@ -4,7 +4,7 @@ Overall the basic option types are the same in Home Manager as NixOS. A
few Home Manager options, however, make use of custom types that are
worth describing in more detail. These are the option types `dagOf` and
`gvariant` that are used, for example, by
[programs.ssh.settings](#opt-programs.ssh.settings) and [dconf.settings](#opt-dconf.settings).
[programs.ssh.matchBlocks](#opt-programs.ssh.matchBlocks) and [dconf.settings](#opt-dconf.settings).
[]{#sec-option-types-dag}`hm.types.dagOf`
-231
View File
@@ -1,231 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import html
import re
import shutil
import sys
from pathlib import Path
SIMPLE_ROLES = (
"command",
"component",
"description",
"file",
"index",
"system",
"type",
)
HEADING_ANCHOR = re.compile(r"^(#{1,6}\s+)(.*)\s+\{#([^}]+)\}\s*$")
INLINE_ANCHOR = re.compile(r"\[\]\{#([^}]+)\}")
OPTION_ROLE = re.compile(r"(?<![$`])\{option\}`([^`]*)`")
SIMPLE_ROLE = re.compile(r"(?<![$`])\{(" + "|".join(SIMPLE_ROLES) + r")\}`([^`]*)`")
OPTION_LINK = re.compile(
r"\[(?P<label>[^\]]*)\]\(#(?P<anchor>(?:opt|nixos-opt|nix-darwin-opt)-[^)]+)\)"
)
LEFTOVER_ROLE = re.compile(
r"(?<![$`])\{(" + "|".join(("option", *SIMPLE_ROLES)) + r")\}`[^`]*`"
)
FENCE = re.compile(r"^\s*(`{3,})(.*)$")
FENCE_CLOSE = re.compile(r"^\s*`{3,}\s*$")
ADMONITION_OPEN = re.compile(r"^\s*:::\s*\{\.(note|warning|example)\}\s*$")
ADMONITION_CLOSE = re.compile(r"^\s*:::\s*$")
DEEP_SPLIT_NAMESPACES = {"programs", "services"}
def option_target(anchor: str, current_file: Path, base_depth: int) -> str:
if anchor.startswith("nix-darwin-opt-"):
option = anchor.removeprefix("nix-darwin-opt-")
option = option.replace("<", "_").replace(">", "_")
anchor = f"nix-darwin-opt-{option}"
base = "options/nix-darwin"
elif anchor.startswith("nixos-opt-"):
option = anchor.removeprefix("nixos-opt-")
option = option.replace("<", "_").replace(">", "_")
anchor = f"nixos-opt-{option}"
base = "options/nixos"
else:
option = anchor.removeprefix("opt-")
option = option.replace("<", "_").replace(">", "_")
anchor = f"opt-{option}"
base = "options/home-manager"
page_parts = option_page_parts(option)
prefix = "../" * (base_depth + len(current_file.parent.parts))
return f"{prefix}{base}/{'/'.join(page_parts)}.md#{anchor}"
def option_page_parts(option_name: str) -> list[str]:
parts = option_name.split(".")
namespace = parts[0]
if namespace in DEEP_SPLIT_NAMESPACES and len(parts) > 1:
return parts[:2]
return [namespace]
def option_label(anchor: str) -> str:
if anchor.startswith("nix-darwin-opt-"):
return anchor.removeprefix("nix-darwin-opt-")
if anchor.startswith("nixos-opt-"):
return anchor.removeprefix("nixos-opt-")
return anchor.removeprefix("opt-")
def markdown_label(value: str) -> str:
return value.replace("<", "&lt;").replace(">", "&gt;")
def convert_inline(line: str, current_file: Path, base_depth: int) -> str:
line = line.replace("index.xhtml", "index.html")
line = INLINE_ANCHOR.sub(
lambda match: f'<a id="{html.escape(match.group(1), quote=True)}"></a>',
line,
)
line = OPTION_ROLE.sub(
lambda match: (
f"[{markdown_label(match.group(1))}]"
f"({option_target(f'opt-{match.group(1)}', current_file, base_depth)})"
),
line,
)
line = OPTION_LINK.sub(
lambda match: (
f"[{markdown_label(match.group('label') or option_label(match.group('anchor')))}]"
f"({option_target(match.group('anchor'), current_file, base_depth)})"
),
line,
)
return SIMPLE_ROLE.sub(lambda match: f"`{match.group(2)}`", line)
def convert_heading(line: str, current_file: Path, base_depth: int) -> str:
match = HEADING_ANCHOR.match(line)
if match is None:
return convert_inline(line, current_file, base_depth)
prefix, title, anchor = match.groups()
return (
f'<a id="{html.escape(anchor, quote=True)}"></a>\n'
f"{prefix}{convert_inline(title, current_file, base_depth)}"
)
def is_include_fence(line: str) -> tuple[bool, str]:
match = FENCE.match(line)
if match is None:
return False, ""
info = match.group(2).strip()
return info.startswith(("{=include=}", "include")), match.group(1)
def convert_markdown(
text: str,
source: Path,
current_file: Path,
base_depth: int,
) -> str:
output: list[str] = []
in_code_fence = False
code_fence = ""
in_include = False
include_fence = ""
in_admonition = False
for raw_line in text.splitlines(keepends=True):
line = raw_line[:-1] if raw_line.endswith("\n") else raw_line
newline = "\n" if raw_line.endswith("\n") else ""
if in_include:
if FENCE_CLOSE.match(line) and len(line.strip()) >= len(include_fence):
in_include = False
include_fence = ""
continue
if in_code_fence:
output.append(raw_line)
if FENCE_CLOSE.match(line) and len(line.strip()) >= len(code_fence):
in_code_fence = False
code_fence = ""
continue
include, fence = is_include_fence(line)
if include:
in_include = True
include_fence = fence
continue
fence_match = FENCE.match(line)
if fence_match is not None:
in_code_fence = True
code_fence = fence_match.group(1)
output.append(raw_line)
continue
if in_admonition:
if ADMONITION_CLOSE.match(line):
in_admonition = False
continue
converted = convert_inline(line, current_file, base_depth)
output.append(f"> {converted}{newline}" if converted else ">\n")
continue
admonition = ADMONITION_OPEN.match(line)
if admonition is not None:
in_admonition = True
output.append(f"> **{admonition.group(1).title()}**\n")
continue
output.append(convert_heading(line, current_file, base_depth) + newline)
if in_include:
raise ValueError(f"{source}: unterminated include block")
converted = "".join(output)
if LEFTOVER_ROLE.search(converted):
raise ValueError(f"{source}: unconverted NixOS-render-docs role remains")
if "```{=include=}" in converted:
raise ValueError(f"{source}: unconverted include block remains")
return converted
def convert_tree(source: Path, destination: Path, base_depth: int) -> None:
for path in source.rglob("*"):
if not path.is_file():
continue
target = destination / path.relative_to(source)
target.parent.mkdir(parents=True, exist_ok=True)
if path.suffix == ".md":
text = path.read_text(encoding="utf-8")
target.write_text(
convert_markdown(text, path, path.relative_to(source), base_depth),
encoding="utf-8",
)
else:
shutil.copy2(path, target)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--base-depth", type=int, default=0)
parser.add_argument("source", type=Path)
parser.add_argument("destination", type=Path)
args = parser.parse_args()
if not args.source.is_dir():
print(f"missing source directory: {args.source}", file=sys.stderr)
return 1
args.destination.mkdir(parents=True, exist_ok=True)
convert_tree(args.source, args.destination, args.base_depth)
return 0
if __name__ == "__main__":
raise SystemExit(main())
-132
View File
@@ -1,132 +0,0 @@
#!/usr/bin/env python3
import html
import json
import re
import sys
from pathlib import Path
ANCHOR = re.compile(r'<a id="([^"]+)"></a>')
SPECIAL_PAGES = {
Path("manual.md"): "index.html",
Path("preface.md"): "index.html",
Path("options.md"): "options/home-manager/index.html",
Path("nixos-options.md"): "options/nixos/index.html",
Path("nix-darwin-options.md"): "options/nix-darwin/index.html",
}
OPTION_PREFIXES = {
"opt-": "options/home-manager",
"nixos-opt-": "options/nixos",
"nix-darwin-opt-": "options/nix-darwin",
}
ROUTER = """
(function () {
var h = location.hash || "", a = h.slice(1), t = __DEFAULT__;
var m = __ANCHORS__, p = __PREFIXES__;
function o(a) {
for (var k in p) {
if (a.indexOf(k) !== 0) continue;
var s = a.slice(k.length).replace(/[<>]/g, "_").split("."), q = s[0];
if ((q === "programs" || q === "services") && s.length > 1) q += "/" + s[1];
return p[k] + "/" + q + ".html";
}
return null;
}
if (a) t = Object.prototype.hasOwnProperty.call(m, a) ? m[a] : o(a) || t;
if (t === null) return;
var n = t + (location.search || "") + h;
var c = location.pathname.split("/").pop() + location.search + h;
if (n !== c) location.replace(n);
}());
""".strip()
def page_for(source, path):
relative = path.relative_to(source)
return SPECIAL_PAGES.get(relative, relative.with_suffix(".html").as_posix())
def anchors_for(source, roots):
anchors = {}
for root in roots:
files = [root] if root.is_file() else sorted(root.rglob("*.md"))
for path in files:
page = page_for(source, path)
for anchor in ANCHOR.findall(path.read_text(encoding="utf-8")):
anchors.setdefault(anchor, page)
return anchors
def script(default, anchors):
js = (
ROUTER.replace("__DEFAULT__", json.dumps(default))
.replace(
"__ANCHORS__", json.dumps(anchors, sort_keys=True, separators=(",", ":"))
)
.replace("__PREFIXES__", json.dumps(OPTION_PREFIXES, separators=(",", ":")))
)
return "\n".join(
[
" <script>",
" //<![CDATA[",
*[f" {line}" for line in js.splitlines()],
" //]]>",
" </script>",
]
)
def write_redirect(output, name, destination, anchors=None):
escaped = html.escape(destination, quote=True)
(output / name).write_text(
f"""<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
{script(destination, anchors or {})}
<meta http-equiv="refresh" content="0; url={escaped}" />
<link rel="canonical" href="{escaped}" />
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to <a href="{escaped}">{escaped}</a>.</p>
</body>
</html>
""",
encoding="utf-8",
)
def inject_root_router(output, anchors):
index = output / "index.html"
text = index.read_text(encoding="utf-8")
index.write_text(text.replace("<head>", f"<head>\n{script(None, anchors)}", 1))
def main():
source, output = map(Path, sys.argv[1:])
manual_roots = [
path
for path in source.iterdir()
if path.name != "options" and (path.is_dir() or path.suffix == ".md")
]
manual_anchors = anchors_for(source, manual_roots)
release_anchors = anchors_for(source, [source / "release-notes"])
inject_root_router(output, manual_anchors)
for name, destination, anchors in [
("index.xhtml", "index.html", manual_anchors),
("options.html", "options/home-manager/index.html", {}),
("options.xhtml", "options/home-manager/index.html", {}),
("nixos-options.xhtml", "options/nixos/index.html", {}),
("nix-darwin-options.xhtml", "options/nix-darwin/index.html", {}),
("release-notes.xhtml", "release-notes/release-notes.html", release_anchors),
]:
write_redirect(output, name, destination, anchors)
if __name__ == "__main__":
main()
-23
View File
@@ -1,23 +0,0 @@
{
pkgs,
optionDocs,
manpageUrls,
revision,
}:
pkgs.runCommand "home-manager-mdbook-options"
{
nativeBuildInputs = [
pkgs.buildPackages.nixos-render-docs
pkgs.buildPackages.python3
];
optionDocsJson = builtins.toJSON optionDocs;
passAsFile = [ "optionDocsJson" ];
}
''
python3 ${./render-options.py} \
"$optionDocsJsonPath" \
${manpageUrls} \
${revision} \
"$out"
''
-221
View File
@@ -1,221 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import json
import re
import subprocess
import sys
from pathlib import Path
OPTION_LINK = re.compile(
r"\[(?P<label>[^\]]*)\]\(#(?P<anchor>(?:opt|nixos-opt|nix-darwin-opt)-[^)]+)\)"
)
OPTION_HREF = re.compile(r'href="#(?P<anchor>(?:opt|nixos-opt|nix-darwin-opt)-[^"]+)"')
DEEP_SPLIT_NAMESPACES = {"programs", "services"}
def option_label(anchor: str) -> str:
if anchor.startswith("nix-darwin-opt-"):
return anchor.removeprefix("nix-darwin-opt-")
if anchor.startswith("nixos-opt-"):
return anchor.removeprefix("nixos-opt-")
return anchor.removeprefix("opt-")
def option_target(anchor: str, current_file: Path) -> str:
if anchor.startswith("nix-darwin-opt-"):
option = anchor.removeprefix("nix-darwin-opt-")
base = "options/nix-darwin"
elif anchor.startswith("nixos-opt-"):
option = anchor.removeprefix("nixos-opt-")
base = "options/nixos"
else:
option = anchor.removeprefix("opt-")
base = "options/home-manager"
page_parts = option_page_parts(option)
prefix = "../" * len(current_file.parent.parts)
return f"{prefix}{base}/{'/'.join(page_parts)}.md#{anchor}"
def rewrite_option_links(text: str, current_file: Path) -> str:
text = OPTION_LINK.sub(
lambda match: (
f"[{match.group('label') or option_label(match.group('anchor'))}]"
f"({option_target(match.group('anchor'), current_file)})"
),
text,
)
return OPTION_HREF.sub(
lambda match: f'href="{option_target(match.group("anchor"), current_file)}"',
text,
)
def namespace_for(option_name: str) -> str:
return option_name.split(".", 1)[0]
def option_page_parts(option_name: str) -> list[str]:
parts = option_name.split(".")
namespace = parts[0]
if namespace in DEEP_SPLIT_NAMESPACES and len(parts) > 1:
return parts[:2]
return [namespace]
def option_group_for(option_name: str) -> str:
return "/".join(option_page_parts(option_name))
def render_namespace(
options: dict[str, object],
destination: Path,
manpage_urls: Path,
revision: str,
anchor_prefix: str,
current_file: Path,
) -> None:
destination.parent.mkdir(parents=True, exist_ok=True)
source = destination.with_suffix(".json")
source.write_text(json.dumps(options, sort_keys=True), encoding="utf-8")
subprocess.run(
[
"nixos-render-docs",
"options",
"commonmark",
"--manpage-urls",
str(manpage_urls),
"--revision",
revision,
"--anchor-style",
"legacy",
"--anchor-prefix",
anchor_prefix,
str(source),
str(destination),
],
check=True,
)
source.unlink()
destination.write_text(
rewrite_option_links(destination.read_text(encoding="utf-8"), current_file),
encoding="utf-8",
)
def write_doc(
name: str,
doc: dict[str, str],
manpage_urls: Path,
revision: str,
output: Path,
) -> None:
options_json = Path(doc["json"]) / "share/doc/nixos/options.json"
options = json.loads(options_json.read_text(encoding="utf-8"))
grouped: dict[str, dict[str, object]] = {}
for option_name, option in options.items():
group = option_group_for(option_name)
grouped.setdefault(group, {})[option_name] = option
doc_dir = output / "options" / doc["path"]
doc_dir.mkdir(parents=True, exist_ok=True)
groups = sorted(grouped)
namespaces = sorted({group.split("/", 1)[0] for group in groups})
nested = {
namespace: sorted(
group for group in groups if group.startswith(f"{namespace}/")
)
for namespace in namespaces
}
index = [
f"# {doc['title']}\n",
"\n",
"Generated from Home Manager option definitions.\n",
"\n",
"## Namespaces\n",
"\n",
]
for namespace in namespaces:
if nested[namespace]:
index.append(f"- [{namespace}]({namespace}/index.md)\n")
else:
index.append(f"- [{namespace}]({namespace}.md)\n")
(doc_dir / "index.md").write_text("".join(index), encoding="utf-8")
summary_dir = output / "summary"
summary_dir.mkdir(parents=True, exist_ok=True)
summary = [f" - [{doc['title']}](options/{doc['path']}/index.md)\n"]
for namespace in namespaces:
if nested[namespace]:
namespace_index = doc_dir / namespace / "index.md"
namespace_index.parent.mkdir(parents=True, exist_ok=True)
namespace_index.write_text(
"".join(
[
f"# {namespace}\n",
"\n",
"## Modules\n",
"\n",
*(
f"- [{group.split('/', 1)[1]}]({group.split('/', 1)[1]}.md)\n"
for group in nested[namespace]
),
]
),
encoding="utf-8",
)
summary.append(
f" - [{namespace}](options/{doc['path']}/{namespace}/index.md)\n"
)
for group in nested[namespace]:
module_name = group.split("/", 1)[1]
summary.append(
f" - [{module_name}](options/{doc['path']}/{namespace}/{module_name}.md)\n"
)
else:
summary.append(
f" - [{namespace}](options/{doc['path']}/{namespace}.md)\n"
)
for group in groups:
page = doc_dir / f"{group}.md"
current_file = Path("options") / doc["path"] / f"{group}.md"
render_namespace(
grouped[group],
page,
manpage_urls,
revision,
doc["prefix"],
current_file,
)
(summary_dir / f"{name}.md").write_text("".join(summary), encoding="utf-8")
def main() -> int:
if len(sys.argv) != 5:
print(
"usage: render-options.py OPTION_DOCS MANPAGE_URLS REVISION OUT",
file=sys.stderr,
)
return 1
option_docs = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
manpage_urls = Path(sys.argv[2])
revision = sys.argv[3]
output = Path(sys.argv[4])
for name, doc in option_docs.items():
write_doc(name, doc, manpage_urls, revision, output)
return 0
if __name__ == "__main__":
raise SystemExit(main())
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
import sys
from pathlib import Path
def main() -> int:
if len(sys.argv) != 5:
print(
"usage: substitute-summary.py SUMMARY HM_SUMMARY NIXOS_SUMMARY DARWIN_SUMMARY",
file=sys.stderr,
)
return 1
summary = Path(sys.argv[1])
replacements = {
"@HOME_MANAGER_OPTIONS@": Path(sys.argv[2]).read_text(encoding="utf-8"),
"@NIXOS_OPTIONS@": Path(sys.argv[3]).read_text(encoding="utf-8"),
"@NIX_DARWIN_OPTIONS@": Path(sys.argv[4]).read_text(encoding="utf-8"),
}
text = summary.read_text(encoding="utf-8")
for needle, replacement in replacements.items():
text = text.replace(needle, replacement.rstrip())
summary.write_text(text, encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+2 -3
View File
@@ -1,10 +1,9 @@
# Release Notes {#ch-release-notes}
This section lists the release notes for stable versions of Home Manager and the
current unstable version.
This section lists the release notes for stable versions of Home Manager
and the current unstable version.
```{=include=} chapters
rl-2611.md
rl-2605.md
rl-2511.md
rl-2505.md
+1 -1
View File
@@ -71,7 +71,7 @@ This release has the following notable changes:
no longer packages compton, and instead packages the (mostly)
compatible fork called picom.
- The list form of the `programs.ssh.matchBlocks` option has
- The list form of the [programs.ssh.matchBlocks](#opt-programs.ssh.matchBlocks) option has
been deprecated and configurations requiring match blocks in a
defined order should switch to using DAG entries instead. For
example, a configuration
+1 -1
View File
@@ -36,7 +36,7 @@ This release has the following notable changes:
optionally also activate it. The recommended installation method for
a standalone Home Manager setup with Nix flakes uses this new
command. The standard installation method remains the same but uses
the new command internally. See [sec-flakes-standalone](../nix-flakes/standalone.md#sec-flakes-standalone) for
the new command internally. See [sec-flakes-standalone](#sec-flakes-standalone) for
more.
## State Version Changes {#sec-release-23.05-state-version-changes}
+1 -1
View File
@@ -19,7 +19,7 @@ This release has the following notable changes:
- The Home Manager test suite has been removed from the main Nix Flake
since it caused unnecessary evaluations and downloads. Instead the
tests are available through a Nix Flake file inside the `tests`
directory. See [Tests](../contributing/tests.md#sec-tests) for example commands.
directory. See [](#sec-tests) for example commands.
## State Version Changes {#sec-release-25.05-state-version-changes}
+2 -2
View File
@@ -16,7 +16,7 @@ This release has the following notable changes:
term removed all together. If you have developed tooling that
directly call the generated activation script, then you are
encouraged to adapt to the new behavior. See the
[Activation](../internals/activation.md#sec-internals-activation) section in the manual for
[Activation](#sec-internals-activation) section in the manual for
details on how to call the activation script.
- The `home-manager switch` command now offers a `--rollback` option.
@@ -25,7 +25,7 @@ This release has the following notable changes:
previously possible to accomplish this by manually activating an old
generation, it always created a new profile generation. The new
behavior mirrors the behavior of `nixos-rebuild switch --rollback`.
See the [Rollbacks](../usage/rollbacks.md#sec-usage-rollbacks) section for more.
See the [Rollbacks](#sec-usage-rollbacks) section for more.
- The `home-manager switch` command now offers a
`--specialisation NAME` option. When given, the switch activates the
+27 -161
View File
@@ -1,146 +1,40 @@
# Release 26.05 {#sec-release-26.05}
The 26.05 release branch became stable in May, 2026.
This is the current unstable branch and the information in this
section is therefore not final.
## Highlights {#sec-release-26.05-highlights}
This release has the following notable changes:
- Home Manager now supports RFC 42-style SSH configuration through
[](#opt-programs.ssh.settings). The legacy `programs.ssh.matchBlocks` format
is deprecated and migrated automatically.
- The new `home-manager.startAsUserService` option runs user activation on
demand at login instead of doing all setup during system boot, which helps on
systems where home directories are mounted later (for example, pam_mount).
- New options were added for `services.podman.useDefaultMachine` and podman
machine management on Darwin.
- The [](#opt-programs.rclone.enable) module now supports launchd-backed config,
mount, and serve agents on Darwin. The new
`programs.rclone.remotes.<name>.serve` option can manage `rclone serve`
sidecar services on both Linux and Darwin. On non-systemd platforms,
`programs.rclone.requiresUnit` is read-only and always `null` because there is
no systemd ordering unit to depend on.
- The Syncthing credentials flow now uses `services.syncthing.guiCredentials`
instead of the removed `services.syncthing.passwordFile` option.
- Firefox extensions are now managed per-profile through the
`programs.firefox.profiles.<name>.extensions.packages` and
`programs.firefox.profiles.<name>.extensions.settings` options. The top-level
`programs.firefox.extensions = [ ... ]` list was removed; migrate it to
`programs.firefox.profiles.<name>.extensions.packages`.
- Thunderbird now supports `accounts.email.accounts.<name>.ews`, the
`outlook.office365.com-ews` account flavor, declarative language packs, and
enterprise policies. Thunderbird accounts using the `outlook.office365.com`
flavor now default IMAP and SMTP authentication to OAuth2 when the account
does not set an authentication method explicitly.
- A new `systemd.user.packages` option provides a user-level equivalent of
`systemd.packages` for installing unit files from packages.
- WezTerm now supports declarative configuration via
[](#opt-programs.wezterm.settings). Settings are expressed as a Nix attribute
set and serialized to Lua using `lib.generators.toLua`. Raw Lua expressions
such as `wezterm.font` and `wezterm.action.*` can be embedded using
`lib.generators.mkLuaInline`. The existing
[](#opt-programs.wezterm.extraConfig) option remains fully supported and can
be combined with [](#opt-programs.wezterm.settings).
[](#opt-programs.wezterm.settings). Settings are expressed as a Nix
attribute set and serialized to Lua using `lib.generators.toLua`.
Raw Lua expressions such as `wezterm.font` and `wezterm.action.*`
can be embedded using `lib.generators.mkLuaInline`. The existing
[](#opt-programs.wezterm.extraConfig) option remains fully supported
and can be combined with [](#opt-programs.wezterm.settings).
- The [](#opt-programs.anki.uiScale) option now expects a value in the range
1.02.0, previously it erroneously expected values in the range `0.01.0`.
Anki sync options moved from `programs.anki.sync.*` to
`programs.anki.profiles."User 1".sync.*`, and
`programs.anki.sync.passwordFile` is migrated to
`programs.anki.profiles."User 1".sync.keyFile`.
- New [](#opt-home.services) namespace for nixpkgs
[modular services](https://nixos.org/manual/nixos/unstable/#modular-services).
Service modules shipped with packages (e.g.
`pkgs.<name>.passthru.services.default`) drop in unchanged and are lifted to
user systemd units. See [Modular Services](../usage/modular-services.md#sec-usage-modular-services) for
details.
- Dedicated modules were added for several VSCode forks (`programs.cursor`,
`programs.vscodium`, `programs.windsurf`, `programs.kiro`, and
`programs.antigravity`), built from a shared `mkVscodeModule` factory. Each
fork can now be configured independently and simultaneously. Users who
previously selected a fork by setting `programs.vscode.package` should migrate
to the matching module; the `programs.vscode.pname` option was removed.
- The AI coding-assistant modules ([](#opt-programs.claude-code.enable),
[](#opt-programs.codex.enable), and [](#opt-programs.opencode.enable)) now
share a unified `context` option for providing global instructions. The
previous per-module options (`claude-code.memory`,
`codex.custom-instructions`, and `opencode.rules`) are deprecated and migrated
automatically. MCP server configuration via `programs.mcp.servers` was also
extended to more assistant and editor modules through an
`enableMcpIntegration` option.
- The `programs.man` module was split so the man viewer can be selected through
the [](#opt-programs.man.man-db.enable) and
[](#opt-programs.man.mandoc.enable) submodules, which are mutually exclusive.
- The `programs.neovim.extraLuaConfig` option was renamed to
[](#opt-programs.neovim.initLua). Home Manager now writes generated Lua
initialization to {file}`$XDG_CONFIG_HOME/nvim/init.lua` by default. If you
manage that file outside Home Manager, set
[](#opt-programs.neovim.sideloadInitLua) to `true` to load the generated Lua
through the Neovim wrapper instead.
- A new `sshAuthSock` module manages the `SSH_AUTH_SOCK`
environment variable. It is implicitly configured by the
SSH-agent-providing modules (e.g. `services.ssh-agent`, `services.gpg-agent`).
The old `services.ssh-agent.enable{Bash,Zsh,Fish,Nushell}Integration` options
were removed; shell initialization is now provided through `sshAuthSock`.
- A new [](#opt-services.pipewire.enable) module provides client-side
configuration for PipeWire, WirePlumber, and the PulseAudio/JACK compatibility
layers. It does not install or manage the PipeWire daemon itself.
- The `services.swww` module was renamed to [](#opt-services.awww.enable)
following the upstream project rename. The `enable`, `package`, and
`extraArgs` options are migrated automatically from `services.swww.*` to
`services.awww.*`.
- Several modules dropped their freeform `extraConfig` escape hatches in favor
of RFC 42-style `settings`: `programs.aerospace.extraConfig` (and
`userSettings`) and `programs.aria2.extraConfig` were removed.
`programs.mise.settings` was renamed to `programs.mise.globalConfig.settings`.
The `programs.eww.configDir` and
`programs.eww.enable{Bash,Zsh,Fish}Integration` options were removed; use
[](#opt-programs.eww.yuckConfig) and [](#opt-programs.eww.scssConfig) for
declarative Eww config files. The `programs.niriswitcher` options were also
removed.
- Darwin integration received several behavior changes. Home Manager launchd
agents now wait for `/nix/store` before starting and use
`launchctl bootout --wait` when replacing agents. nix-darwin activations now
propagate dry-run mode into Home Manager user activations. On Darwin, Home
Manager also exports `TERMINFO_DIRS` so terminfo entries from Home
Manager-installed packages are visible to shells.
- The [](#opt-nix.assumeXdg) option was added for installations where Nix is
configured to use XDG base directories outside Home Manager. Home Manager also
detects `osConfig.nix.settings.use-xdg-base-directories` when deciding where
to place declarative channel entries.
- The [](#opt-programs.anki.uiScale) option now expects a value in the
range 1.02.0, previously it erroneously expected values in the
range `0.01.0`.
## State Version Changes {#sec-release-26.05-state-version-changes}
The state version in this release includes the changes below. These changes are
only active if the `home.stateVersion` option is set to \"26.05\" or later.
The state version in this release includes the changes below. These
changes are only active if the `home.stateVersion` option is set to
\"26.05\" or later.
- The [](#opt-gtk.gtk4.theme) option does not mirror [](#opt-gtk.theme) by
default anymore.
- The [](#opt-gtk.gtk4.theme) option does not mirror
[](#opt-gtk.theme) by default anymore.
- The [](#opt-programs.zsh.dotDir) option now defaults to the XDG configuration
directory (usually `~/.config/zsh`) when [](#opt-xdg.enable) is true.
- The [](#opt-programs.zsh.dotDir) option now defaults to the XDG
configuration directory (usually `~/.config/zsh`) when
[](#opt-xdg.enable) is true.
- The [](#opt-programs.yazi.shellWrapperName) option now defaults to `y` instead
of `yy`.
- The [](#opt-programs.yazi.shellWrapperName) option now defaults to
`y` instead of `yy`. For users with older `home.stateVersion` values,
the legacy default `yy` is retained.
- The [](#opt-xdg.userDirs.setSessionVariables) option now defaults to `false`
instead of `true`.
@@ -151,39 +45,11 @@ only active if the `home.stateVersion` option is set to \"26.05\" or later.
`DESKTOP`. Home Manager 26.05 introduced a warning when the `XDG_<name>_DIR`
form is used.
- The [](#opt-programs.man.package) option now defaults to `null` on Darwin
because the GNU `man` from nixpkgs ships `apropos`/`man -k` and
`whatis`/`man -f` binaries that don't work on Darwin. Nix-installed manual
pages still work with macOS's built-in `man` via
- The [](#opt-programs.man.package) option now defaults to `null` on
Darwin because the GNU `man` from nixpkgs ships `apropos`/`man -k`
and `whatis`/`man -f` binaries that don't work on Darwin. Nix-installed
manual pages still work with macOS's built-in `man` via
[](#opt-home.extraOutputsToInstall).
- The options [](#opt-programs.neovim.withPython3) and
[](#opt-programs.neovim.withRuby) now default to `false` following nixpkgs.
- Neovim plugin `config` fragments are assumed to be Lua by default through
`programs.neovim.plugins.<name>.type = "lua"`, instead of the previous `viml`
default.
- On Linux, `programs.firefox.configPath` now defaults to
`"${config.xdg.configHome}/mozilla/firefox"`, instead of the legacy
`".mozilla/firefox"`.
- The [](#opt-wayland.windowManager.hyprland.configType) option now defaults to
`"lua"`, instead of the legacy `"hyprlang"`. Set
`wayland.windowManager.hyprland.configType = "hyprlang"` to keep generating
{file}`$XDG_CONFIG_HOME/hypr/hyprland.conf`.
- The [](#opt-programs.docker-cli.configDir) option now defaults to
`"${config.xdg.configHome}/docker"` when [](#opt-xdg.enable) is true, instead
of `~/.docker`. Similarly, [](#opt-services.colima.profiles) now sets
`$DOCKER_HOST` for the default context.
- The [](#opt-services.home-manager.autoUpgrade.preSwitchCommands) option now
defaults to an empty list. Previously, when
[](#opt-services.home-manager.autoUpgrade.useFlake) was `true`, it defaulted
to `[ "nix flake update" ]`. Set `preSwitchCommands = [ "nix flake update" ]`
to keep updating flake inputs before each automatic switch.
- The [](#opt-programs.mergiraf.enableGitIntegration) and
[](#opt-programs.mergiraf.enableJujutsuIntegration) options now default to
`false`, so the integrations must be enabled explicitly.
[](#opt-programs.neovim.withRuby) now default to `false` following nixpkgs
-35
View File
@@ -1,35 +0,0 @@
# Release 26.11 {#sec-release-26.11}
This is the current unstable branch and the information in this
section is therefore not final.
## Highlights {#sec-release-26.11-highlights}
This release has the following notable changes:
- The [](#opt-programs.uv.enable) module can now install uv-managed Python
versions and tools through the new `programs.uv.python.versions`,
`programs.uv.python.default`, and `programs.uv.tool.packages` options. Unpinned
entries track the latest release on each activation while pinned ones stay put,
and `programs.uv.python.prune` / `programs.uv.tool.prune` make the managed set
fully declarative by removing versions and tools that are no longer listed.
- On Darwin, Home Manager launchd agents now support
[](#opt-launchd.agents._name_.domain) to choose either the user's GUI or
background launchd domain. Agents use the GUI domain by default. Set the
domain to `user` for agents that should run without an active graphical login
session.
## State Version Changes {#sec-release-26.11-state-version-changes}
The state version in this release includes the changes below. These
changes are only active if the `home.stateVersion` option is set to
"26.11" or later.
- The KDL options under `programs.zellij` will now correctly escape backslashes
in string values. For example, the Nix string `"\\"` will now correctly
generate the KDL string `"\\"`. Previously, this would have generated `"\"`,
which is invalid KDL. The following options are affected:
- `programs.zellij.settings`
- `programs.zellij.themes`
- `programs.zellij.layouts`
Generated
+4 -4
View File
@@ -2,16 +2,16 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1783604885,
"narHash": "sha256-tzMgSkV7kljEkqIjlgV6F+n+xD+/a35Db8bs7a4BFAo=",
"lastModified": 1775710090,
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "767b0d3ec98a143ad9ed7dfc0d5553510ac27133",
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
+16 -50
View File
@@ -1,7 +1,7 @@
{
description = "Home Manager for Nix";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs =
{
@@ -45,34 +45,15 @@
}
// (
let
supportedSystems = [
"aarch64-darwin"
"aarch64-linux"
"i686-linux"
"x86_64-darwin"
"x86_64-linux"
];
forSystems = systems: f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
forAllPkgs = forSystems nixpkgs.lib.systems.flakeExposed;
forSupportedPkgs = forSystems supportedSystems;
forAllPkgs =
f:
nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed (system: f nixpkgs.legacyPackages.${system});
forCI = nixpkgs.lib.genAttrs [
"aarch64-darwin"
"x86_64-linux"
];
releaseInfo = nixpkgs.lib.importJSON ./release.json;
docsFor =
pkgs:
import ./docs {
inherit pkgs;
inherit (releaseInfo) release isReleaseBranch;
};
testChunks =
system:
let
@@ -82,7 +63,8 @@
# Create chunked test packages for better CI parallelization
tests = import ./tests {
inherit pkgs;
enableBig = true;
# Disable big tests since this is only used for CI
enableBig = false;
};
allTests = lib.attrNames tests.build;
# Remove 'all' from the test list as it's a meta-package
@@ -175,13 +157,12 @@
lib.mapAttrs' renameTestPkg tests;
in
{
formatter = forSupportedPkgs (pkgs: pkgs.callPackage ./home-manager/formatter.nix { });
formatter = forAllPkgs (pkgs: pkgs.callPackage ./home-manager/formatter.nix { });
# TODO: increase buildbot testing scope
buildbot = forCI (
system:
let
docs = docsFor nixpkgs.legacyPackages.${system};
allIntegrationTests = integrationTests system;
workingIntegrationTests = nixpkgs.lib.filterAttrs (
name: _:
@@ -191,43 +172,28 @@
]
) allIntegrationTests;
in
(testChunks system)
// workingIntegrationTests
// {
docs-html = docs.manual.html;
docs-json = docs.options.json;
docs-jsonModuleMaintainers = docs.jsonModuleMaintainers;
docs-manpages = docs.manPages;
}
(testChunks system) // workingIntegrationTests
);
packages = forAllPkgs (
pkgs:
let
docs = docsFor pkgs;
releaseInfo = nixpkgs.lib.importJSON ./release.json;
docs = import ./docs {
inherit pkgs;
inherit (releaseInfo) release isReleaseBranch;
};
hmPkg = pkgs.callPackage ./home-manager { path = "${self}"; };
in
{
default = hmPkg;
home-manager = hmPkg;
}
// nixpkgs.lib.optionalAttrs (nixpkgs.lib.elem pkgs.stdenv.hostPlatform.system supportedSystems) {
ci-parse = pkgs.callPackage ./ci/parse.nix { nix = pkgs.nixVersions.latest; };
ci-parse-lix = pkgs.callPackage ./ci/parse.nix {
nix = pkgs.lixPackageSets.latest.lix;
};
create-news-entry = pkgs.writeShellScriptBin "create-news-entry" ''
./modules/misc/news/create-news-entry.sh
'';
tests = pkgs.callPackage ./tests/package.nix {
flake = self;
inputOverrides = {
inherit nixpkgs;
};
};
tests = pkgs.callPackage ./tests/package.nix { flake = self; };
docs-html = docs.manual.html;
docs-htmlOpenTool = docs.manual.htmlOpenTool;
@@ -237,11 +203,11 @@
}
);
devShells = forSupportedPkgs (pkgs: {
devShells = forAllPkgs (pkgs: {
default = pkgs.callPackage ./home-manager/devShell.nix { };
});
legacyPackages = forSupportedPkgs (
legacyPackages = forAllPkgs (
pkgs:
let
inherit (pkgs.stdenv.hostPlatform) system;
-1
View File
@@ -18,7 +18,6 @@ pkgs.treefmt.withConfig {
deadnix
keep-sorted
nixf-diagnose
ruff
];
settings = pkgs.lib.importTOML ../treefmt.toml;
}
+4 -5
View File
@@ -291,7 +291,6 @@ function doInspectOption() {
for path in "${paths[@]}"; do
nix-instantiate --eval --json \
--arg nixos "$modulesExpr" \
"${extraArgs[@]}" \
--argstr path "$path" \
--arg recursive "$recursive" \
"$NIXOS_OPTION_NIX" \
@@ -314,7 +313,7 @@ function doInit() {
fi
local homeManagerUrl="github:nix-community/home-manager"
local nixpkgsUrl="github:nixos/nixpkgs/nixpkgs-unstable"
local nixpkgsUrl="github:nixos/nixpkgs/nixos-unstable"
while (( $# > 0 )); do
local opt="$1"
@@ -404,7 +403,7 @@ $xdgVars
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
home.stateVersion = "26.05"; # Please read the comment before changing.
home.stateVersion = "25.11"; # Please read the comment before changing.
# The home.packages option allows you to install Nix packages into your
# environment.
@@ -1042,7 +1041,7 @@ function doUninstall() {
uninstall = true;
home.username = "$(escapeForNix "$USER")";
home.homeDirectory = "$(escapeForNix "$HOME")";
home.stateVersion = "26.05";
home.stateVersion = "25.11";
}
EOF
# shellcheck disable=2064
@@ -1280,7 +1279,7 @@ while [[ $# -gt 0 ]]; do
export VERBOSE=1
;;
--version)
echo 26.11-pre
echo 26.05-pre
exit 0
;;
*)
+6 -6
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-04-30 04:09+0000\n"
"Last-Translator: Troy <radiohotline@disroot.org>\n"
"PO-Revision-Date: 2026-03-31 16:16+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/home-manager/cli/"
"ar/>\n"
"Language: ar\n"
@@ -18,17 +18,17 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 5.17.1-dev\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr "%s: معطيات مفقودة ل %s"
msgstr "%s: معطيات مفقوة ل %s"
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
msgid "%s: %s can only be used after %s"
msgstr "%s%: s يمكن استخدامه فقط بعد %s"
msgstr "%s: %s يمكن استخدامه فقط بعد %s"
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
@@ -212,7 +212,7 @@ msgstr "لا يمكن تشغيل البناء في مجلد قراءة فقط"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "لا يتضمن ملف الاعدادات التخصص \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
-261
View File
@@ -1,261 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Home Manager contributors
# This file is distributed under the same license as the Home Manager package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-05-31 21:01+0000\n"
"Last-Translator: Tofaa <tofig.adigozalov.180904@gmail.com>\n"
"Language-Team: Azerbaijani <https://hosted.weblate.org/projects/home-manager/"
"cli/az/>\n"
"Language: az\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.6.dev0\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr "%s: {s} üçün tələb olunan arqument verilməyib"
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
msgid "%s: %s can only be used after %s"
msgstr "%s: %s ancaq %s'dən sonra işlənə bilər"
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
msgstr "%s-də konfiqurasiya faylı tapılmadı"
#. translators: The first '%s' specifier will be replaced by either
#. 'home.nix' or 'flake.nix'.
#: home-manager/home-manager:88 home-manager/home-manager:92
#: home-manager/home-manager:191
msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"Home Manager %s faylının %s daxilində saxlanılması artıq dəstəklənmir.\n"
"Zəhmət olmasa onu %s ünvanına köçürün"
#: home-manager/home-manager:99
msgid "No configuration file found. Please create one at %s"
msgstr "Konfiqurasiya faylı tapılmadı. Zəhmət olmasa fayli %s'də yaradin"
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."
msgstr "Home Manager %s'də tapılmadı."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:122
msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr ""
"Ehtiyat Home Manager yolu %s artıq köhnəlmişdir və həmin ünvanda fayl və ya "
"qovluq tapıldı."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:125
msgid ""
"To remove this warning, do one of the following.\n"
"\n"
"1. Explicitly tell Home Manager to use the path, for example by adding\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" to your configuration.\n"
"\n"
" If you import Home Manager directly, you can use the `path` parameter\n"
"\n"
" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
" when calling the Home Manager package.\n"
"\n"
"2. Remove the deprecated path.\n"
"\n"
" $ rm -r \"%s\""
msgstr ""
"Bu xəbərdarlığı aradan qaldırmaq üçün aşağıdakılardan birini edin.\n"
"\n"
"1. Home Manager-ə bu yolu istifadə etməsini açıq şəkildə bildirin. Məsələn, "
"konfiqurasiyanıza aşağıdakı sətri əlavə edin:\n"
"\n"
"{ programs.home-manager.path = \"%s\"; }\n"
"\n"
" Əgər Home Manager-i birbaşa import edirsinizsə, Home Manager paketini\n"
" çağırarkən `path` parametrindən istifadə edə bilərsiniz:\n"
"\n"
" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
"2. Köhnəlmiş yolu silin.\n"
"\n"
" $ rm -r \"%s\""
#: home-manager/home-manager:153
msgid "Sanity checking Nix"
msgstr "Nix yoxlanılır"
#: home-manager/home-manager:173
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr "Uyğun profil qovluğu tapılmadı; %s və %s yolları yoxlanıldı"
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:230
msgid "Can't inspect options of a flake configuration"
msgstr "Flake konfiqurasiyasının seçimlərinə baxış keçirmək mümkün deyil"
#: home-manager/home-manager:340 home-manager/home-manager:363
#: home-manager/home-manager:769 home-manager/home-manager:1289
msgid "%s: unknown option '%s'"
msgstr "%s: bilinməyən seçim '%s'"
#: home-manager/home-manager:345 home-manager/home-manager:1290
msgid "Run '%s --help' for usage help"
msgstr "İstifadə köməyi üçün '%s --help' işlədin"
#: home-manager/home-manager:371 home-manager/home-manager:476
msgid "The file %s already exists, leaving it unchanged..."
msgstr "%s faylı artıq mövcuddur, dəyişdirilmədən saxlanılır..."
#: home-manager/home-manager:373 home-manager/home-manager:478
msgid "Creating %s..."
msgstr "%s yaradılır..."
#: home-manager/home-manager:522
msgid "Creating initial Home Manager generation..."
msgstr "Ilkin Home Manager nəsili yaradılır..."
#. translators: The "%s" specifier will be replaced by a file path.
#: home-manager/home-manager:527
msgid ""
"All done! The home-manager tool should now be installed and you can edit\n"
"\n"
" %s\n"
"\n"
"to configure Home Manager. Run 'man home-configuration.nix' to\n"
"see all available options."
msgstr ""
"Hər şey tamamlandı! İndi home-manager aləti quraşdırılıb və Home Manager-i "
"konfiqurasiya etmək üçün %s faylını redaktə edə bilərsiniz.\n"
"\n"
"Mövcud bütün seçimləri görmək üçün 'man home-configuration.nix' əmrini icra "
"edin."
#. translators: The "%s" specifier will be replaced by a URL.
#: home-manager/home-manager:532
msgid ""
"Uh oh, the installation failed! Please create an issue at\n"
"\n"
" %s\n"
"\n"
"if the error seems to be the fault of Home Manager."
msgstr ""
"Quraşdırma uğursuz oldu! Əgər xəta Home Manager-in səbəbindən baş veribsə, "
"%s ünvanında issue yaradın."
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:543
msgid "Can't instantiate a flake configuration"
msgstr "Flake konfiqurasiyasını yaratmaq mümkün deyil"
#: home-manager/home-manager:619
msgid ""
"There is %d unread and relevant news item.\n"
"Read it by running the command \"%s news\"."
msgid_plural ""
"There are %d unread and relevant news items.\n"
"Read them by running the command \"%s news\"."
msgstr[0] ""
"Oxunmamış və uyğun %d xəbər var.\n"
"\n"
"Onu oxumaq üçün \"%s news\" əmrini icra edin."
msgstr[1] ""
"Oxunmamış və uyğun %d xəbər var.\n"
"\n"
"Onları oxumaq üçün \"%s news\" əmrini icra edin."
#: home-manager/home-manager:633
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr "Naməlum \"news.display\" ayarı: \"%s\"."
#: home-manager/home-manager:641
#, sh-format
msgid "Please set the $EDITOR or $VISUAL environment variable"
msgstr "Zəhmət olmasa $EDITOR və ya $VISUAL mühit dəyişənini təyin edin"
#: home-manager/home-manager:659
msgid "Cannot run build in read-only directory"
msgstr "Yalnız oxuma rejimində qovluqda build icra etmək mümkün deyil"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "Konfiqurasiya \"%s\" specialisation-ını ehtiva etmir"
#: home-manager/home-manager:876
msgid "No generation with ID %s"
msgstr "%s ID-li nəsil mövcud deyil"
#: home-manager/home-manager:878
msgid "Cannot remove the current generation %s"
msgstr "Cari nəsli (%s) silmək mümkün deyil"
#: home-manager/home-manager:880
msgid "Removing generation %s"
msgstr "%s nəsli silinir"
#: home-manager/home-manager:901
msgid "No generations to expire"
msgstr "Müddəti bitəcək heç bir nəsil yoxdur"
#: home-manager/home-manager:912
msgid "No home-manager packages seem to be installed."
msgstr "Heç bir home-manager paketi quraşdırılmış görünmür."
#: home-manager/home-manager:997
msgid "Unknown argument %s"
msgstr "Naməlum arqument: %s"
#: home-manager/home-manager:1022
msgid "This will remove Home Manager from your system."
msgstr "Bu, Home Manager-i sisteminizdən siləcək."
#: home-manager/home-manager:1025
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr "Bu sınaq icrasıdır, heç nə faktiki olaraq silinməyəcək."
#: home-manager/home-manager:1029
msgid "Really uninstall Home Manager?"
msgstr "Home Manager-i həqiqətən silmək istəyirsiniz?"
#: home-manager/home-manager:1035
msgid "Switching to empty Home Manager configuration..."
msgstr "Boş Home Manager konfiqurasiyasına keçid edilir..."
#: home-manager/home-manager:1050
msgid "Yay!"
msgstr "Əla!"
#: home-manager/home-manager:1055
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr "Home Manager silindi, lakin home.nix faylınız dəyişdirilmədi."
#: home-manager/home-manager:1334
msgid "expire-generations expects one argument, got %d."
msgstr "expire-generations bir arqument gözləyir, lakin %d arqument verilib."
#: home-manager/home-manager:1359
msgid "Unknown command: %s"
msgstr "Naməlum əmr: %s"
#: home-manager/install.nix:21
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr ""
"Bu derivasiya build edilə bilən deyil, zəhmət olmasa onu nix-shell ilə icra "
"edin."
+15 -15
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-05-05 10:30+0000\n"
"Last-Translator: Ludovic Pagès <nanucq@proton.me>\n"
"PO-Revision-Date: 2026-03-31 16:16+0000\n"
"Last-Translator: TheBlackBeans <adrien.mathieu.net@gmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/home-manager/cli/"
"fr/>\n"
"Language: fr\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 5.17.1\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -52,7 +52,7 @@ msgstr ""
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."
msgstr "Home Manager absent dans %s."
msgstr "Home Manager indisponible à %s."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:122
@@ -84,15 +84,15 @@ msgid ""
"\n"
" $ rm -r \"%s\""
msgstr ""
"Pour supprimer cet avertissement, exécutez l'une des actions suivantes :\n"
" \n"
"Pour supprimer cet avertissement, exécutez l'une des actions suivantes:\n"
"\n"
"1. Préciser explicitement à Home Manager d'utiliser le chemin d'accès, par "
"exemple en ajoutant ceci à votre configuration :\n"
"exemple en ajoutant ceci à votre configuration:\n"
"\n"
"\t{ programs.home-manager.path = \"%s\"; }\n"
"\n"
"Si vous importez Home Manager directement, vous pouvez utiliser le paramètre "
"`path` au lancement du package :\n"
"`path` au lancement du package:\n"
"\n"
"\tpkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
@@ -120,7 +120,7 @@ msgstr "%s : l'option '%s' est inconnue"
#: home-manager/home-manager:345 home-manager/home-manager:1290
msgid "Run '%s --help' for usage help"
msgstr "Exécuter '%s --help' pour de l'aide sur l'utilisation"
msgstr "Exécuter « %s --help » pour de l'aide sur l'utilisation"
#: home-manager/home-manager:371 home-manager/home-manager:476
msgid "The file %s already exists, leaving it unchanged..."
@@ -144,13 +144,13 @@ msgid ""
"to configure Home Manager. Run 'man home-configuration.nix' to\n"
"see all available options."
msgstr ""
"Terminé ! Home Manager devrait désormais être installé et vous pouvez "
"Tout est fait! Home Manager devrait désormais être installé et vous pouvez "
"éditer\n"
"\n"
" %s\n"
"\n"
"pour configurer Home Manager. Pour avoir une liste des options disponibles,\n"
"lancez 'man home-configuration.nix'."
"essayez 'man home-configuration.nix'."
#. translators: The "%s" specifier will be replaced by a URL.
#: home-manager/home-manager:532
@@ -161,8 +161,8 @@ msgid ""
"\n"
"if the error seems to be the fault of Home Manager."
msgstr ""
"Uh oh, l'installation a échoué! Veuillez signaler cette erreur à l'adresse "
"suivante\n"
"Uh oh, l'installation n'a pas réussi! Veuillez signaler cette erreur à "
"l'adresse suivante\n"
"\n"
" %s\n"
"\n"
@@ -198,11 +198,11 @@ msgstr "Veuillez remplir la variable d'environnement $EDITOR ou VISUAL"
#: home-manager/home-manager:659
msgid "Cannot run build in read-only directory"
msgstr "Impossible de lancer une compilation dans un dossier en lecture seule"
msgstr "Impossible de lancer une compilation dans un dossier en écriture seule"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "La configuration ne contient pas la spécialisation \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+5 -5
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-07-19 08:01+0000\n"
"Last-Translator: Artur Sannikov <weblate.rbpxz@8shield.net>\n"
"PO-Revision-Date: 2026-03-31 16:16+0000\n"
"Last-Translator: Lorenzo Bevilacqua <lorenzobevilacqua02@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/home-manager/cli/"
"it/>\n"
"Language: it\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.8.dev0\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -104,7 +104,7 @@ msgstr ""
#: home-manager/home-manager:153
msgid "Sanity checking Nix"
msgstr "Verifica di correttezza di Nix"
msgstr "Controllando Nix"
#: home-manager/home-manager:173
msgid "Could not find suitable profile directory, tried %s and %s"
@@ -204,7 +204,7 @@ msgstr "Impossibile eseguire la build in una cartella in sola lettura"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "La configurazione non contiene la specializzazione \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+4 -4
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-05-21 21:11+0000\n"
"Last-Translator: jay <jj8z@proton.me>\n"
"PO-Revision-Date: 2026-03-31 16:15+0000\n"
"Last-Translator: Erwin Mintiens <erwin.mintiens@protonmail.com>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/home-manager/cli/"
"nl/>\n"
"Language: nl\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.6.dev0\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -185,7 +185,7 @@ msgstr "Het is niet mogelijk om te bouwen in een read-only map"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "De configuratie bevat niet de specialisatie \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+13 -12
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-04-26 13:09+0000\n"
"Last-Translator: Nikodem <35564466+x1pper@users.noreply.github.com>\n"
"PO-Revision-Date: 2026-03-31 16:15+0000\n"
"Last-Translator: Mateusz Kubica <mw.kubica@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/home-manager/cli/"
"pl/>\n"
"Language: pl\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.17.1-dev\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -83,24 +83,25 @@ msgid ""
"\n"
" $ rm -r \"%s\""
msgstr ""
"Zrób jedną z tych rzeczy aby pozbyć się tego ostrzeżenia:\n"
"Zrób jedną z tych rzeczy aby aby pozbyć się tego ostrzeżenia:\n"
"\n"
"1. Jednoznacznie skonfiguruj Home Manager żeby używał konkretnej ścieżki, "
"np. dodając\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" do twojej konfiguracji.\n"
" do twojej konfiguracji.\n"
"\n"
" Jeśli importujesz Home Manager bezpośrednio, możesz użyć parametru `path`\n"
" Jeśli importujesz Home Manager bezpośrednio, możesz użyć parametru "
"`path`\n"
"\n"
" pkgs.callPackage /ścieżka/do/pakiet-home-manager { path = \"%s\"; }\n"
" pkgs.callPackage /ścieżka/do/pakiet-home-manager { path = \"%s\"; }\n"
"\n"
" przy wywołaniu pakietu Home Manager.\n"
" przy wywołaniu pakietu Home Manager.\n"
"\n"
"2. Usuń przestarzałą ścieżkę:\n"
"2. Usuń przestarzałą ścieżkę.\n"
"\n"
" $ rm -r \"%s\""
" $ rm -r \"%s\""
#: home-manager/home-manager:153
msgid "Sanity checking Nix"
@@ -206,7 +207,7 @@ msgstr "Nie mogę uruchomić budowania w katalogu tylko-do-odczytu"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "Konfiguracja nie zawiera specjalizacji o nazwie \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+4 -4
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-07-19 08:01+0000\n"
"Last-Translator: Artur Sannikov <weblate.rbpxz@8shield.net>\n"
"PO-Revision-Date: 2026-03-31 16:16+0000\n"
"Last-Translator: NikSne <commits@niksne.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/home-manager/cli/"
"ru/>\n"
"Language: ru\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 2026.8.dev0\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -205,7 +205,7 @@ msgstr "Не могу начать сборку в директории, защ
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "В конфигурации отсутствует специализация «%s»"
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+31 -58
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-05-27 11:11+0000\n"
"Last-Translator: qb114514 <GNUqb114514@outlook.com>\n"
"PO-Revision-Date: 2026-03-31 16:14+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"Language-Team: Toki Pona <https://hosted.weblate.org/projects/home-manager/"
"cli/tok/>\n"
"Language: tok\n"
@@ -17,21 +17,21 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.6.dev0\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr "%s: nimi %s li wile nimi poka"
msgstr ""
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
msgid "%s: %s can only be used after %s"
msgstr "%s: %s li ken lon poka pini %s"
msgstr ""
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
msgstr "lipu lawa li lon ala %s"
msgstr ""
#. translators: The first '%s' specifier will be replaced by either
#. 'home.nix' or 'flake.nix'.
@@ -41,16 +41,14 @@ msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"lipu %s pi ilo Home Manager li wile ala lon %s.\n"
"o tawa %s e ona"
#: home-manager/home-manager:99
msgid "No configuration file found. Please create one at %s"
msgstr "mi ken ala alasa e lipu lawa. o pali e lipu lawa lon %s"
msgstr ""
#: home-manager/home-manager:114
msgid "Home Manager not found at %s."
msgstr "ilo Home Manager li lon ala %s."
msgstr ""
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:122
@@ -58,8 +56,6 @@ msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr ""
"tenpo pini la, ilo Home Manager li kepeken nasin %s. taso, tenpo ni la ilo "
"Home Manager li wile ale e nasin ni. lipu anu kulupu lipu li lon nasin ni."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:125
@@ -85,40 +81,37 @@ msgstr ""
#: home-manager/home-manager:153
msgid "Sanity checking Nix"
msgstr "mi alasa ilo Nix tan ni: ilo Nix li lon ala la ni li ike mute li nasa"
msgstr ""
#: home-manager/home-manager:173
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr ""
"mi wile pana e kulupu lipu sina lon poki sona. taso mi ken ala alasa e ma "
"pona lon %s lon %s"
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:230
msgid "Can't inspect options of a flake configuration"
msgstr "mi ken ala lukin e lipu lawa pi ilo Nix Flakes"
msgstr ""
#: home-manager/home-manager:340 home-manager/home-manager:363
#: home-manager/home-manager:769 home-manager/home-manager:1289
msgid "%s: unknown option '%s'"
msgstr "%s: mi ken ala sona e nimi '%s'"
msgstr ""
#: home-manager/home-manager:345 home-manager/home-manager:1290
msgid "Run '%s --help' for usage help"
msgstr "sina wile kama sona pali e ilo Home Manager la o toki e '%s --help'"
msgstr ""
#: home-manager/home-manager:371 home-manager/home-manager:476
msgid "The file %s already exists, leaving it unchanged..."
msgstr "lipu %s li lon. mi ante ala e ona."
msgstr ""
#: home-manager/home-manager:373 home-manager/home-manager:478
msgid "Creating %s..."
msgstr "mi pali e \"%s\"."
msgstr ""
#: home-manager/home-manager:522
msgid "Creating initial Home Manager generation..."
msgstr ""
"tenpo ni la mi pali e kulupu nanpa wan pi lipu lawa tan ilo Home Manager..."
#. translators: The "%s" specifier will be replaced by a file path.
#: home-manager/home-manager:527
@@ -130,12 +123,6 @@ msgid ""
"to configure Home Manager. Run 'man home-configuration.nix' to\n"
"see all available options."
msgstr ""
"pini a! ilo \"home-manager\" li lon. sina wile lawa e ilo Home Manager la "
"sina ken ante e lipu ni:\n"
"\n"
" lipu.%s\n"
"\n"
"sina wile kama sona e nasin lawa o toki e ni: 'man home-configuration.nix'."
#. translators: The "%s" specifier will be replaced by a URL.
#: home-manager/home-manager:532
@@ -146,17 +133,11 @@ msgid ""
"\n"
"if the error seems to be the fault of Home Manager."
msgstr ""
"ike li lon! mi ken ala pana e ilo Home Manager tawa sina. ken la sina pilin "
"e ni: ike ni li tan ilo Home Manager. ni la o pana e sona lon\n"
"\n"
" %s\n"
"\n"
"ni la sina pona e mi mute."
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:543
msgid "Can't instantiate a flake configuration"
msgstr "mi ken ala pali e lipu lawa pi ilo Nix Flakes"
msgstr ""
#: home-manager/home-manager:619
msgid ""
@@ -166,88 +147,80 @@ msgid_plural ""
"There are %d unread and relevant news items.\n"
"Read them by running the command \"%s news\"."
msgstr[0] ""
"sona sin %d li lon.\n"
"sina wile lukin la o toki: \"%s news\"."
#: home-manager/home-manager:633
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr ""
"sina pana e \"%s\" tawa nimi lawa \"news.display\". nimi lawa ni li ken ala "
"jo e nimi ni li ken jo e \"silent\" anu \"notify\" anu \"show\"."
#: home-manager/home-manager:641
#, sh-format
msgid "Please set the $EDITOR or $VISUAL environment variable"
msgstr "o pana e ilo tawa poki sona $EDITOR anu poki sona $VISUAL"
msgstr ""
#: home-manager/home-manager:659
msgid "Cannot run build in read-only directory"
msgstr "ma ni li ken ala ante. mi ken ala pali \"build\" lon ma ni"
msgstr ""
#: home-manager/home-manager:822
#, fuzzy
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "lipu lawa jo ala lipu Specialisation \"%s\""
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
msgstr "kulupu pi lipu lawa pi ilo Home Manager pi nimi %s li lon ala"
msgstr ""
#: home-manager/home-manager:878
msgid "Cannot remove the current generation %s"
msgstr ""
"mi ken ala weka e kulupu pi lipu lawa %s tan ni: tenpo ni la ona li lon tomo "
"sina"
#: home-manager/home-manager:880
msgid "Removing generation %s"
msgstr "mi weka e kulupu lawa pi nimi %s"
msgstr ""
#: home-manager/home-manager:901
msgid "No generations to expire"
msgstr "kulupu ale pi lipu lawa li majuna ala. mi wile ala weka e ona"
msgstr ""
#: home-manager/home-manager:912
msgid "No home-manager packages seem to be installed."
msgstr "ilo Home Manager li pana ala e ilo ante."
msgstr ""
#: home-manager/home-manager:997
msgid "Unknown argument %s"
msgstr "mi sona ala e nimi '%s'"
msgstr ""
#: home-manager/home-manager:1022
msgid "This will remove Home Manager from your system."
msgstr "ni li weka e ilo Home Manager."
msgstr ""
#: home-manager/home-manager:1025
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr "tenpo ni la mi weka e ala li toki taso."
msgstr ""
#: home-manager/home-manager:1029
msgid "Really uninstall Home Manager?"
msgstr "sina wile ala wile weka e ilo Home Manager?"
msgstr ""
#: home-manager/home-manager:1035
msgid "Switching to empty Home Manager configuration..."
msgstr "tenpo ni la mi lon e lipu lawa pi ijo ala..."
msgstr ""
#: home-manager/home-manager:1050
msgid "Yay!"
msgstr "pona mute a!"
msgstr ""
#: home-manager/home-manager:1055
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr "ilo Home Manager li weka. taso, lipu home.nix li awen lon."
msgstr ""
#: home-manager/home-manager:1334
msgid "expire-generations expects one argument, got %d."
msgstr ""
"sina pana e nimi %d tawa ilo expire-generations. o pana e nimi wan taso."
#: home-manager/home-manager:1359
msgid "Unknown command: %s"
msgstr "mi sona ala pali %s"
msgstr ""
#: home-manager/install.nix:21
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr "mi ken ala pali e ni. sina ken pali e ona kepeken ilo nix-shell."
msgstr ""
+5 -6
View File
@@ -8,9 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2026-01-21 09:53+0100\n"
"PO-Revision-Date: 2026-07-19 08:01+0000\n"
"Last-Translator: reducedradius "
"<137701630+flytothehighest@users.noreply.github.com>\n"
"PO-Revision-Date: 2026-03-31 16:13+0000\n"
"Last-Translator: Zexin Yuan <yuan.zx@outlook.com>\n"
"Language-Team: Chinese (Simplified Han script) <https://hosted.weblate.org/"
"projects/home-manager/cli/zh_Hans/>\n"
"Language: zh_Hans\n"
@@ -18,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 2026.8.dev0\n"
"X-Generator: Weblate 5.17-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@@ -28,7 +27,7 @@ msgstr "%s:缺少参数 %s"
#. translators: For example: "home-manager: --rollback can only be used after switch"
#: home-manager/home-manager:22
msgid "%s: %s can only be used after %s"
msgstr "%s: %s 只能在 %s 后使用"
msgstr ""
#: home-manager/home-manager:71
msgid "No configuration file found at %s"
@@ -195,7 +194,7 @@ msgstr "无法在只读目录中运行构建"
#: home-manager/home-manager:822
msgid "The configuration does not contain the specialisation \"%s\""
msgstr "配置不包含专门化的 “%s”"
msgstr ""
#: home-manager/home-manager:876
msgid "No generation with ID %s"
+34 -1
View File
@@ -2,5 +2,38 @@
{
inherit ((import ../modules/lib/stdlib-extended.nix lib)) hm;
homeManagerConfiguration = import ./eval-config.nix;
homeManagerConfiguration =
{
check ? true,
extraSpecialArgs ? { },
lib ? pkgs.lib,
modules ? [ ],
pkgs,
minimal ? false,
}:
import ../modules {
inherit
check
extraSpecialArgs
lib
pkgs
minimal
;
configuration = {
imports = modules ++ [
{
programs.home-manager.path = builtins.path {
path = ../.;
name = "source";
};
}
];
nixpkgs = {
config = lib.mkDefault pkgs.config;
inherit (pkgs) overlays;
};
};
};
}
-33
View File
@@ -1,33 +0,0 @@
{
check ? true,
extraSpecialArgs ? { },
lib ? pkgs.lib,
modules ? [ ],
pkgs,
minimal ? false,
}:
import ../modules {
inherit
check
extraSpecialArgs
lib
pkgs
minimal
;
configuration = {
imports = modules ++ [
{
programs.home-manager.path = builtins.path {
path = ../.;
name = "source";
};
}
];
nixpkgs = {
config = lib.mkDefault pkgs.config;
inherit (pkgs) overlays;
};
};
}
+20 -35
View File
@@ -1,14 +1,7 @@
# Extract maintainers from Home Manager modules using meta.maintainers
# This script evaluates all Home Manager modules and extracts the merged maintainer information
let
flakeLock = builtins.fromJSON (builtins.readFile ../../flake.lock);
nixpkgsNodeName = flakeLock.nodes.root.inputs.nixpkgs;
nixpkgsLocked = flakeLock.nodes.${nixpkgsNodeName}.locked;
pkgs = import (fetchTarball {
url = "https://github.com/${nixpkgsLocked.owner}/${nixpkgsLocked.repo}/archive/${nixpkgsLocked.rev}.tar.gz";
sha256 = nixpkgsLocked.narHash;
}) { };
pkgs = import <nixpkgs> { };
lib = import ../../modules/lib/stdlib-extended.nix pkgs.lib;
releaseInfo = pkgs.lib.importJSON ../../release.json;
@@ -32,23 +25,18 @@ let
file:
let
fileContent = import file;
# Arguments expected by docs/home-manager-manual.nix.
evaluated =
if lib.isFunction fileContent then
fileContent {
inherit lib;
inherit (pkgs)
callPackage
mdbook
python3
stdenv
;
inherit (pkgs) stdenv lib;
documentation-highlighter = { };
revision = "unknown";
home-manager-options = {
home-manager = { };
nixos = { };
nix-darwin = { };
};
nixos-render-docs = { };
}
else
fileContent;
@@ -71,30 +59,27 @@ let
allMaintainerObjects = extractMaintainerObjects maintainers ++ additionalMaintainerObjects;
getMaintainerName = maintainer: maintainer.github or maintainer.name or null;
allMaintainerNames = lib.filter (name: name != null) (map getMaintainerName allMaintainerObjects);
allMaintainerNames = lib.filter (name: name != null) (
map (maintainer: maintainer.github or maintainer.name or null) allMaintainerObjects
);
hmMaintainers = import ../../modules/lib/maintainers.nix;
hmMaintainerNames = lib.filter (name: name != null) (
map getMaintainerName (lib.attrValues hmMaintainers)
);
hmMaintainerNames = lib.attrNames hmMaintainers;
maintainerDetails = lib.pipe allMaintainerObjects [
(lib.filter (obj: (obj.github or obj.name or null) != null))
(map (
obj:
let
maintainerName = obj.github or obj.name;
in
{
name = maintainerName;
value = obj // {
source =
if categorizedMaintainers.home-manager ? ${maintainerName} then "home-manager" else "nixpkgs";
};
}
))
(map (obj: {
name = obj.github or obj.name;
value = obj // {
source =
if categorizedMaintainers.home-manager ? ${obj.github} then
"home-manager"
else if categorizedMaintainers.nixpkgs ? ${obj.github} then
"nixpkgs"
else
throw "${obj.github} is neither a home-manager or nixpkgs maintainer";
};
}))
lib.listToAttrs
];
+17 -32
View File
@@ -17,67 +17,52 @@ def main():
print("🔍 Checking for duplicate maintainers between HM and nixpkgs...")
# Get home-manager maintainers
hm_result = subprocess.run(
["nix", "eval", "--file", "modules/lib/maintainers.nix", "--json"],
capture_output=True,
text=True,
check=True,
)
hm_result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'],
capture_output=True, text=True, check=True)
hm_maintainers = json.loads(hm_result.stdout)
hm_github_users = set()
for name, data in hm_maintainers.items():
if "github" in data:
hm_github_users.add(data["github"])
if 'github' in data:
hm_github_users.add(data['github'])
# Read nixpkgs revision from flake.lock to ensure consistency between local and CI
flake_lock_path = Path("flake.lock")
with open(flake_lock_path, "r") as f:
flake_lock_path = Path('flake.lock')
with open(flake_lock_path, 'r') as f:
flake_lock = json.load(f)
nixpkgs_rev = flake_lock["nodes"]["nixpkgs"]["locked"]["rev"]
nixpkgs_rev = flake_lock['nodes']['nixpkgs']['locked']['rev']
print(f"📌 Using nixpkgs from flake.lock: {nixpkgs_rev[:7]}")
# Get nixpkgs maintainers from the locked revision
nixpkgs_result = subprocess.run(
[
"nix",
"eval",
f"github:NixOS/nixpkgs/{nixpkgs_rev}#lib.maintainers",
"--json",
],
capture_output=True,
text=True,
check=True,
['nix', 'eval', f'github:NixOS/nixpkgs/{nixpkgs_rev}#lib.maintainers', '--json'],
capture_output=True, text=True, check=True
)
nixpkgs_maintainers = json.loads(nixpkgs_result.stdout)
nixpkgs_github_users = set()
for name, data in nixpkgs_maintainers.items():
if isinstance(data, dict) and "github" in data:
nixpkgs_github_users.add(data["github"])
if isinstance(data, dict) and 'github' in data:
nixpkgs_github_users.add(data['github'])
# Find duplicates
duplicates = hm_github_users.intersection(nixpkgs_github_users)
if duplicates:
print(
f"❌ Found {len(duplicates)} duplicate maintainers between HM and nixpkgs:"
)
print(f'❌ Found {len(duplicates)} duplicate maintainers between HM and nixpkgs:')
for github_user in sorted(duplicates):
# Find the HM attribute name for this github user
hm_attr = None
for attr_name, data in hm_maintainers.items():
if data.get("github") == github_user:
if data.get('github') == github_user:
hm_attr = attr_name
break
print(f" - {github_user} (HM attribute: {hm_attr})")
print(f' - {github_user} (HM attribute: {hm_attr})')
print()
print(
"These maintainers should be removed from HM maintainers file to avoid duplication."
)
print("They can be referenced directly from nixpkgs instead.")
print('These maintainers should be removed from HM maintainers file to avoid duplication.')
print('They can be referenced directly from nixpkgs instead.')
sys.exit(1)
else:
print("✅ No duplicate maintainers found")
print('✅ No duplicate maintainers found')
if __name__ == "__main__":
+1 -4
View File
@@ -16,7 +16,6 @@ from pathlib import Path
class NixEvalError(Exception):
"""Custom exception for errors during Nix evaluation."""
pass
@@ -40,9 +39,7 @@ def run_nix_eval(nix_file: Path, *args: str) -> str:
)
return result.stdout.strip()
except FileNotFoundError:
logging.error(
"'nix-instantiate' command not found. Is Nix installed and in your PATH?"
)
logging.error("'nix-instantiate' command not found. Is Nix installed and in your PATH?")
raise NixEvalError("'nix-instantiate' not found")
except subprocess.CalledProcessError as e:
logging.error(f"Nix evaluation failed with exit code {e.returncode}")
+11 -18
View File
@@ -40,7 +40,6 @@ def get_project_root() -> Path:
# Assumes this script is at: <root>/flake/dev/generate-all-maintainers/
return Path(__file__).parent.parent.parent.parent.resolve()
class MetaMaintainerGenerator:
"""Generates maintainers list using meta.maintainers from Home Manager evaluation."""
@@ -55,12 +54,9 @@ class MetaMaintainerGenerator:
print("🔍 Extracting maintainers using meta.maintainers...")
try:
result = subprocess.run(
["nix", "eval", "--file", str(self.extractor_script), "--json"],
capture_output=True,
text=True,
timeout=60,
)
result = subprocess.run([
"nix", "eval", "--file", str(self.extractor_script), "--json"
], capture_output=True, text=True, timeout=60)
if result.returncode == 0:
data = json.loads(result.stdout)
@@ -91,7 +87,7 @@ class MetaMaintainerGenerator:
print(f"🏠 Home Manager maintainers: {len(hm_maintainers)}")
print(f"📦 Nixpkgs maintainers: {len(nixpkgs_maintainers)}")
with open(self.output_file, "w") as f:
with open(self.output_file, 'w') as f:
f.write(
inspect.cleandoc("""
# Home Manager all maintainers list.
@@ -118,12 +114,9 @@ class MetaMaintainerGenerator:
def validate_generated_file(self) -> bool:
"""Validate the generated Nix file syntax."""
try:
result = subprocess.run(
["nix-instantiate", "--eval", str(self.output_file), "--strict"],
capture_output=True,
text=True,
timeout=10,
)
result = subprocess.run([
'nix-instantiate', '--eval', str(self.output_file), '--strict'
], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
print("✅ Generated file has valid Nix syntax")
@@ -155,16 +148,16 @@ def main():
description="Generate Home Manager all-maintainers.nix using meta.maintainers"
)
parser.add_argument(
"--root",
'--root',
type=Path,
default=None,
help="Path to Home Manager root (default: auto-detect)",
help='Path to Home Manager root (default: auto-detect)'
)
parser.add_argument(
"--output",
'--output',
type=Path,
default=None,
help="Output file path (default: <root>/all-maintainers.nix)",
help='Output file path (default: <root>/all-maintainers.nix)'
)
args = parser.parse_args()
+41 -108
View File
@@ -60,7 +60,6 @@ query($owner: String!, $repo: String!, $prNumber: Int!) {
class GHError(Exception):
"""Custom exception for errors related to 'gh' CLI commands."""
pass
@@ -95,28 +94,15 @@ def get_manual_reviewer_actions(
tuple: (manually_requested, manually_removed) sets of usernames
"""
try:
result = run_gh_command(
[
"api",
"graphql",
"-f",
f"query={MANUAL_REVIEW_REQUEST_QUERY}",
"-F",
f"owner={owner}",
"-F",
f"repo={repo}",
"-F",
f"prNumber={pr_number}",
]
)
result = run_gh_command([
"api", "graphql",
"-f", f"query={MANUAL_REVIEW_REQUEST_QUERY}",
"-F", f"owner={owner}",
"-F", f"repo={repo}",
"-F", f"prNumber={pr_number}",
])
data = json.loads(result.stdout)
nodes = (
data.get("data", {})
.get("repository", {})
.get("pullRequest", {})
.get("timelineItems", {})
.get("nodes", [])
)
nodes = data.get("data", {}).get("repository", {}).get("pullRequest", {}).get("timelineItems", {}).get("nodes", [])
manually_requested = set()
manually_removed = set()
@@ -157,15 +143,7 @@ def get_users_from_gh(args: list[str], error_message: str) -> set[str]:
def get_pending_reviewers(pr_number: int) -> set[str]:
"""Gets the set of currently pending reviewers for a PR."""
return get_users_from_gh(
[
"pr",
"view",
str(pr_number),
"--json",
"reviewRequests",
"--jq",
".reviewRequests[].login",
],
["pr", "view", str(pr_number), "--json", "reviewRequests", "--jq", ".reviewRequests[].login"],
"Error getting pending reviewers",
)
@@ -173,12 +151,7 @@ def get_pending_reviewers(pr_number: int) -> set[str]:
def get_past_reviewers(owner: str, repo: str, pr_number: int) -> set[str]:
"""Gets the set of users who have already reviewed the PR."""
return get_users_from_gh(
[
"api",
f"repos/{owner}/{repo}/pulls/{pr_number}/reviews",
"--jq",
".[].user.login",
],
["api", f"repos/{owner}/{repo}/pulls/{pr_number}/reviews", "--jq", ".[].user.login"],
"Error getting past reviewers",
)
@@ -189,14 +162,17 @@ def is_collaborator(owner: str, repo: str, username: str) -> bool:
Handles 404 as a non-collaborator, while other errors are raised.
"""
result = run_gh_command(
["api", f"repos/{owner}/{repo}/collaborators/{username}"], check=False
["api", f"repos/{owner}/{repo}/collaborators/{username}"],
check=False
)
if result.returncode == 0:
return True
if "HTTP 404" in result.stderr:
logging.error("'%s' is not a collaborator in this repository.", username)
logging.error(
"'%s' is not a collaborator in this repository.", username
)
return False
else:
logging.error(
@@ -219,32 +195,22 @@ def update_reviewers(
if reviewers_to_add:
logging.info("Requesting reviews from: %s", ", ".join(reviewers_to_add))
try:
run_gh_command(
[
"pr",
"edit",
str(pr_number),
"--add-reviewer",
",".join(reviewers_to_add),
]
)
run_gh_command([
"pr", "edit", str(pr_number),
"--add-reviewer", ",".join(reviewers_to_add)
])
except GHError as e:
logging.error("Failed to add reviewers: %s", e)
if reviewers_to_remove and owner and repo:
logging.info(
"Removing review requests from: %s", ", ".join(reviewers_to_remove)
)
logging.info("Removing review requests from: %s", ", ".join(reviewers_to_remove))
payload = json.dumps({"reviewers": list(reviewers_to_remove)})
try:
run_gh_command(
[
"api",
"--method",
"DELETE",
"api", "--method", "DELETE",
f"repos/{owner}/{repo}/pulls/{pr_number}/requested_reviewers",
"--input",
"-",
"--input", "-",
],
input_data=payload,
)
@@ -254,33 +220,15 @@ def update_reviewers(
def main() -> None:
"""Main function to handle command-line arguments and manage reviewers."""
parser = argparse.ArgumentParser(
description="Manage pull request reviewers for Home Manager."
)
parser = argparse.ArgumentParser(description="Manage pull request reviewers for Home Manager.")
parser.add_argument("--owner", required=True, help="Repository owner.")
parser.add_argument("--repo", required=True, help="Repository name.")
parser.add_argument(
"--pr-number", type=int, required=True, help="Pull request number."
)
parser.add_argument("--pr-number", type=int, required=True, help="Pull request number.")
parser.add_argument("--pr-author", required=True, help="PR author's username.")
parser.add_argument(
"--current-maintainers",
default="",
help="Space-separated list of maintainers for the changed files.",
)
parser.add_argument(
"--changed-files", default="", help="Newline-separated list of changed files."
)
parser.add_argument(
"--bot-user-name",
default="",
help="Bot user name to distinguish manual vs automated review requests.",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Show what would be done without making actual changes.",
)
parser.add_argument("--current-maintainers", default="", help="Space-separated list of maintainers for the changed files.")
parser.add_argument("--changed-files", default="", help="Newline-separated list of changed files.")
parser.add_argument("--bot-user-name", default="", help="Bot user name to distinguish manual vs automated review requests.")
parser.add_argument("--dry-run", action="store_true", help="Show what would be done without making actual changes.")
args = parser.parse_args()
no_changed_files = not args.changed_files.strip()
@@ -289,15 +237,13 @@ def main() -> None:
maintainers: set[str] = set(args.current_maintainers.split())
pending_reviewers = get_pending_reviewers(args.pr_number)
past_reviewers = get_past_reviewers(args.owner, args.repo, args.pr_number)
manually_requested, manually_removed = get_manual_reviewer_actions(
args.owner, args.repo, args.pr_number, args.bot_user_name
)
manually_requested, manually_removed = get_manual_reviewer_actions(args.owner, args.repo, args.pr_number, args.bot_user_name)
logging.info("File Maintainers: %s", " ".join(maintainers) or "None")
logging.info("Pending Reviewers: %s", " ".join(pending_reviewers) or "None")
logging.info("Past Reviewers: %s", " ".join(past_reviewers) or "None")
logging.info("Manually Requested: %s", " ".join(manually_requested) or "None")
logging.info("Manually Removed: %s", " ".join(manually_removed) or "None")
logging.info("File Maintainers: %s", ' '.join(maintainers) or "None")
logging.info("Pending Reviewers: %s", ' '.join(pending_reviewers) or "None")
logging.info("Past Reviewers: %s", ' '.join(past_reviewers) or "None")
logging.info("Manually Requested: %s", ' '.join(manually_requested) or "None")
logging.info("Manually Removed: %s", ' '.join(manually_removed) or "None")
# --- 2. Determine reviewers to remove ---
reviewers_to_remove: set[str] = set()
@@ -311,15 +257,13 @@ def main() -> None:
if reviewers_to_remove:
if args.dry_run:
logging.info(
"DRY RUN: Would remove reviewers: %s", ", ".join(reviewers_to_remove)
)
logging.info("DRY RUN: Would remove reviewers: %s", ", ".join(reviewers_to_remove))
else:
update_reviewers(
args.pr_number,
owner=args.owner,
repo=args.repo,
reviewers_to_remove=reviewers_to_remove,
reviewers_to_remove=reviewers_to_remove
)
else:
logging.info("No reviewers to remove.")
@@ -334,29 +278,20 @@ def main() -> None:
MAX_MAINTAINERS_THRESHOLD,
)
else:
users_to_exclude = (
{args.pr_author} | past_reviewers | pending_reviewers | manually_removed
)
users_to_exclude = {args.pr_author} | past_reviewers | pending_reviewers | manually_removed
potential_reviewers = maintainers - users_to_exclude
reviewers_to_add = {
user
for user in potential_reviewers
if is_collaborator(args.owner, args.repo, user)
user for user in potential_reviewers if is_collaborator(args.owner, args.repo, user)
}
non_collaborators = potential_reviewers - reviewers_to_add
if non_collaborators:
logging.warning(
"Ignoring non-collaborators: %s", ", ".join(non_collaborators)
)
logging.warning("Ignoring non-collaborators: %s", ", ".join(non_collaborators))
manually_removed_maintainers = reviewers_to_add & manually_removed
if manually_removed_maintainers:
logging.info(
"Not re-adding manually removed maintainers: %s",
", ".join(manually_removed_maintainers),
)
logging.info("Not re-adding manually removed maintainers: %s", ", ".join(manually_removed_maintainers))
reviewers_to_add -= manually_removed
if len(reviewers_to_add) > MAX_REVIEWERS:
@@ -369,9 +304,7 @@ def main() -> None:
if reviewers_to_add:
if args.dry_run:
logging.info(
"DRY RUN: Would add reviewers: %s", ", ".join(reviewers_to_add)
)
logging.info("DRY RUN: Would add reviewers: %s", ", ".join(reviewers_to_add))
else:
update_reviewers(args.pr_number, reviewers_to_add=reviewers_to_add)
else:
+12 -18
View File
@@ -14,38 +14,32 @@ import sys
def main():
print("🔍 Validating maintainer entries...")
result = subprocess.run(
["nix", "eval", "--file", "modules/lib/maintainers.nix", "--json"],
capture_output=True,
text=True,
check=True,
)
result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'],
capture_output=True, text=True, check=True)
maintainers = json.loads(result.stdout)
errors = []
for name, data in maintainers.items():
if "github" not in data:
if 'github' not in data:
errors.append(f'{name}: Missing required field "github"')
if "githubId" not in data:
if 'githubId' not in data:
errors.append(f'{name}: Missing required field "githubId"')
if "githubId" in data:
github_id = data["githubId"]
if 'githubId' in data:
github_id = data['githubId']
if not isinstance(github_id, int):
errors.append(
f"{name}: githubId must be a number, not a string: {github_id} (type: {type(github_id).__name__})"
)
errors.append(f'{name}: githubId must be a number, not a string: {github_id} (type: {type(github_id).__name__})')
elif github_id <= 0:
errors.append(f"{name}: githubId must be positive: {github_id}")
errors.append(f'{name}: githubId must be positive: {github_id}')
if errors:
print("❌ Validation errors found:")
print('❌ Validation errors found:')
for error in errors:
print(f" - {error}")
print(f' - {error}')
sys.exit(1)
else:
print("✅ All maintainer entries are valid")
print(f"✅ Validated {len(maintainers)} maintainer entries")
print('✅ All maintainer entries are valid')
print(f'✅ Validated {len(maintainers)} maintainer entries')
if __name__ == "__main__":
+2 -6
View File
@@ -13,12 +13,8 @@ def main():
print("🔍 Validating maintainers.nix syntax...")
try:
subprocess.run(
["nix", "eval", "--file", "modules/lib/maintainers.nix", "--json"],
capture_output=True,
text=True,
check=True,
)
subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'],
capture_output=True, text=True, check=True)
print("✅ Valid Nix syntax")
except subprocess.CalledProcessError:
print("❌ Invalid Nix syntax")
+4 -36
View File
@@ -9,7 +9,7 @@ let
;
cfg = config.accounts.email;
enabledAccounts = lib.filterAttrs (_n: v: v.enable) cfg.accounts;
enabledAccounts = lib.filterAttrs (n: v: v.enable) cfg.accounts;
gpgModule = types.submodule {
options = {
@@ -80,18 +80,6 @@ let
default = "none";
description = "Method to communicate the signature.";
};
htmlFormat = mkOption {
type = types.bool;
default = false;
description = ''
Whether Thunderbird should interpret {option}`text` as an HTML signature.
This maps to Thunderbird's `mail.identity.id_*.htmlSigFormat`
preference. The signature content itself is still written through
`mail.identity.id_*.htmlSigText`.
'';
};
};
};
@@ -109,9 +97,7 @@ let
type = types.bool;
default = false;
description = ''
Whether to use STARTTLS. This is discouraged and should be avoided if
possible. See <https://datatracker.ietf.org/doc/html/rfc8314> for
more.
Whether to use STARTTLS.
'';
};
@@ -414,7 +400,6 @@ let
"gmail.com"
"mailbox.org"
"migadu.com"
"outlook.office365.com-ews"
"outlook.office365.com"
"plain"
"posteo.de"
@@ -626,17 +611,6 @@ let
};
})
(mkIf (config.flavor == "outlook.office365.com-ews") {
userName = mkDefault config.address;
ews = {
host = "outlook.office365.com";
serviceDescriptionURL = "https://outlook.office365.com/EWS/Exchange.asmx";
authentication = "xoauth2";
tls.enable = true;
};
})
(mkIf (config.flavor == "fastmail.com") {
userName = mkDefault config.address;
@@ -659,14 +633,8 @@ let
(mkIf (config.flavor == "mailbox.org") {
userName = mkDefault config.address;
folders.inbox = mkDefault "INBOX";
imap = {
host = "imap.mailbox.org";
port = 993;
};
smtp = {
host = "smtp.mailbox.org";
port = 465;
};
imap.host = "imap.mailbox.org";
smtp.host = "smtp.mailbox.org";
})
(mkIf (config.flavor == "migadu.com") {
+74 -10
View File
@@ -13,10 +13,12 @@ let
mkIf
mkMerge
mkDefault
mkAliasOptionModule
types
literalExpression
escapeShellArg
hm
getAttrFromPath
any
optional
;
@@ -138,10 +140,46 @@ in
{
meta.maintainers = [ lib.maintainers.league ];
imports = [
(mkAliasOptionModule
[ "xsession" "pointerCursor" "package" ]
[
"home"
"pointerCursor"
"package"
]
)
(mkAliasOptionModule
[ "xsession" "pointerCursor" "name" ]
[
"home"
"pointerCursor"
"name"
]
)
(mkAliasOptionModule
[ "xsession" "pointerCursor" "size" ]
[
"home"
"pointerCursor"
"size"
]
)
(mkAliasOptionModule
[ "xsession" "pointerCursor" "defaultCursor" ]
[
"home"
"pointerCursor"
"x11"
"defaultCursor"
]
)
];
options = {
home.pointerCursor = mkOption {
type = pointerCursorModule;
default = { };
type = types.nullOr pointerCursorModule;
default = null;
description = ''
Cursor configuration.
@@ -166,10 +204,9 @@ in
let
# Check if enable option was explicitly defined by the user
enableDefined = any (x: x ? enable) opts.definitions;
pointerCursorDefined = opts.highestPrio != (lib.mkOptionDefault { }).priority;
# Determine if cursor configuration should be enabled
enable = if enableDefined then cfg.enable else pointerCursorDefined;
enable = if enableDefined then cfg.enable else cfg != null;
in
mkMerge [
(mkIf enable (mkMerge [
@@ -203,7 +240,7 @@ in
(mkIf cfg.dotIcons.enable {
# Add symlink of cursor icon directory to $HOME/.icons, needed for
# backwards compatibility with some applications. See:
# https://specifications.freedesktop.org/icon-theme/latest/#directory_layout
# https://specifications.freedesktop.org/icon-theme-spec/latest/ar01s03.html
home.file.".icons/default/index.theme".source =
"${defaultIndexThemePackage}/share/icons/default/index.theme";
home.file.".icons/${cfg.name}".source = "${cfg.package}/share/icons/${cfg.name}";
@@ -248,12 +285,39 @@ in
]))
{
warnings = optional (pointerCursorDefined && !enableDefined) ''
Relying on `home.pointerCursor` to enable cursor config generation is deprecated.
Please update your configuration to explicitly set:
warnings =
(optional
(any
(
x:
getAttrFromPath (
[
"xsession"
"pointerCursor"
]
++ [ x ]
++ [ "isDefined" ]
) options
)
[
"package"
"name"
"size"
"defaultCursor"
]
)
''
The option `xsession.pointerCursor` has been merged into `home.pointerCursor` and will be removed
in the future. Please change to set `home.pointerCursor` directly and enable `home.pointerCursor.x11.enable`
to generate x11 specific cursor configurations. You can refer to the documentation for more details.
''
)
++ (optional (opts.highestPrio != (lib.mkOptionDefault { }).priority && cfg == null) ''
Setting home.pointerCursor to null is deprecated.
Please update your configuration to explicitly set:
home.pointerCursor.enable = ${lib.boolToString enable};
'';
home.pointerCursor.enable = false;
'');
}
];
}
+7 -6
View File
@@ -16,10 +16,9 @@
# https://github.com/NixOS/nixpkgs/blob/nixpkgs-unstable/pkgs/development/libraries/glibc/nix-locale-archive.patch
{
config,
lib,
nixosConfig,
pkgs,
config,
...
}:
@@ -56,8 +55,9 @@ in
This option only applies to the Linux platform.
If Home Manager is installed as a NixOS submodule, this
option defaults to NixOS' {var}`i18n.glibcLocales`.
When Home Manager is configured with NixOS, the default value
will be set to {var}`i18n.glibcLocales` from the
system configuration.
'';
example = lib.literalExpression ''
pkgs.glibcLocales.override {
@@ -65,8 +65,9 @@ in
locales = [ "en_US.UTF-8/UTF-8" ];
}
'';
default = nixosConfig.i18n.glibcLocales or pkgs.glibcLocales;
defaultText = lib.literalExpression "nixosConfig.i18n.glibcLocales or pkgs.glibcLocales";
# NB. See nixos/default.nix for NixOS default.
default = pkgs.glibcLocales;
defaultText = lib.literalExpression "pkgs.glibcLocales";
};
};
+69 -220
View File
@@ -34,7 +34,7 @@ let
inherit
(
(import ./lib/file-type.nix {
(import lib/file-type.nix {
inherit homeDirectory lib pkgs;
})
)
@@ -55,8 +55,6 @@ let
name = sourceName;
};
putterStatePath = "${config.xdg.stateHome}/home-manager/putter-state.json";
in
{
@@ -90,44 +88,11 @@ in
'';
};
home.fileActivator = lib.mkOption {
type =
with lib.types;
enum [
"legacy"
"putter"
];
default = "legacy";
example = "putter";
visible = false;
description = ''
The tooling to use to place files during activation.
The legacy option (currently the default) is the built-in tooling that
is very robust, but is limited in future potential.
The putter option is a new external tool that may replace the legacy
alternative in the future. It is not as hardened as the legacy
alternative but will allow future features such as file copying.
This option should be considered experimental and is therefore hidden
from documentation at this time.
'';
};
home-files = lib.mkOption {
type = lib.types.package;
internal = true;
description = "Package to contain all home files";
};
home.internal = {
filePutterConfig = lib.mkOption {
type = lib.types.package;
internal = true;
description = "Putter configuration.";
};
};
};
config = {
@@ -135,7 +100,7 @@ in
(
let
dups = lib.attrNames (
lib.filterAttrs (_n: v: v > 1) (
lib.filterAttrs (n: v: v > 1) (
lib.foldAttrs (acc: v: acc + v) 0 (map (v: { ${v.target} = 1; }) cfg)
)
);
@@ -184,29 +149,21 @@ in
storeDir = lib.escapeShellArg builtins.storeDir;
legacyCheckScript = pkgs.replaceVars ./files/check-link-targets.sh {
check = pkgs.replaceVars ./files/check-link-targets.sh {
inherit (config.lib.bash) initHomeManagerLib;
inherit forcedPaths storeDir;
};
legacyCheckLinkTargets = ''
function checkNewGenCollision() {
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${legacyCheckScript} "$newGenFiles" {} +
}
checkNewGenCollision || exit 1
'';
putterCheckLinkTargets = ''
${lib.getExe pkgs.putter} check $VERBOSE_ARG \
--state-file "${putterStatePath}" \
${config.home.internal.filePutterConfig}
'';
in
if config.home.fileActivator == "putter" then putterCheckLinkTargets else legacyCheckLinkTargets
''
function checkNewGenCollision() {
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${check} "$newGenFiles" {} +
}
checkNewGenCollision || exit 1
''
);
# This activation script will
@@ -229,9 +186,7 @@ in
# source and target generation.
home.activation.linkGeneration = lib.hm.dag.entryAfter [ "writeBoundary" ] (
let
storeDir = lib.escapeShellArg builtins.storeDir;
legacyLink = pkgs.writeShellScript "link" ''
link = pkgs.writeShellScript "link" ''
${config.lib.bash.initHomeManagerLib}
newGenFiles="$1"
@@ -241,8 +196,8 @@ in
targetPath="$HOME/$relativePath"
if [[ -e "$targetPath" && ! -L "$targetPath" ]] ; then
if [[ -n "$HOME_MANAGER_BACKUP_COMMAND" ]] ; then
verboseEcho "Running '$HOME_MANAGER_BACKUP_COMMAND' on '$targetPath'."
run $HOME_MANAGER_BACKUP_COMMAND "$targetPath" || errorEcho "Running '$HOME_MANAGER_BACKUP_COMMAND' on '$targetPath' failed."
verboseEcho "Running $HOME_MANAGER_BACKUP_COMMAND $targetPath."
run $HOME_MANAGER_BACKUP_COMMAND "$targetPath" || errorEcho "Running `$HOME_MANAGER_BACKUP_COMMAND` on '$targetPath' failed."
elif [[ -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
# The target exists, back it up
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
@@ -265,12 +220,12 @@ in
done
'';
legacyCleanup = pkgs.writeShellScript "cleanup" ''
cleanup = pkgs.writeShellScript "cleanup" ''
${config.lib.bash.initHomeManagerLib}
# A symbolic link whose target path matches this pattern will be
# considered part of a Home Manager generation.
homeFilePattern="$(readlink -e ${storeDir})/*-home-manager-files/*"
homeFilePattern="$(readlink -e ${lib.escapeShellArg builtins.storeDir})/*-home-manager-files/*"
newGenFiles="$1"
shift 1
@@ -301,86 +256,38 @@ in
fi
done
'';
# If Putter is not enabled, then generate a fake state file to allow
# switching to Putter in the future.
putterCompatState =
let
putter = import ./lib/putter.nix { inherit lib; };
manifest = putter.mkPutterCompatState {
sourceBaseDirectory = config.home-files;
targetBaseDirectory = config.home.homeDirectory;
fileEntries = cfg;
};
in
pkgs.writeText "hm-putter-state.json" manifest;
# This activation script will
#
# 1. Remove files from the old generation that are not in the new
# generation.
#
# 2. Symlink files from the new generation into $HOME.
#
# This order is needed to ensure that we always know which links
# belong to which generation. Specifically, if we're moving from
# generation A to generation B having sets of home file links FA
# and FB, respectively then cleaning before linking produces state
# transitions similar to
#
# FA → FA ∩ FB → (FA ∩ FB) FB = FB
#
# and a failure during the intermediate state FA ∩ FB will not
# result in lost links because this set of links are in both the
# source and target generation.
legacyLinkGeneration = ''
function linkNewGen() {
_i "Creating home file links in %s" "$HOME"
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${legacyLink} "$newGenFiles" {} +
# Copy in the Putter compatible state file. This is to allow a later
# switchover to Putter.
run install -Dp -m600 $VERBOSE_ARG ${
lib.escapeShellArgs [
putterCompatState
putterStatePath
]
}
}
function cleanOldGen() {
if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then
return
fi
_i "Cleaning up orphan links from %s" "$HOME"
local newGenFiles oldGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
# Apply the cleanup script on each leaf in the old
# generation. The find command below will print the
# relative path of the entry.
find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \
| xargs -0 bash ${legacyCleanup} "$newGenFiles"
}
cleanOldGen
linkNewGen
'';
putterLinkGeneration = ''
${lib.getExe pkgs.putter} apply $VERBOSE_ARG ''${DRY_RUN:+--dry-run} \
--state-file "${putterStatePath}" \
${config.home.internal.filePutterConfig}
'';
in
if config.home.fileActivator == "putter" then putterLinkGeneration else legacyLinkGeneration
''
function linkNewGen() {
_i "Creating home file links in %s" "$HOME"
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${link} "$newGenFiles" {} +
}
function cleanOldGen() {
if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then
return
fi
_i "Cleaning up orphan links from %s" "$HOME"
local newGenFiles oldGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
# Apply the cleanup script on each leaf in the old
# generation. The find command below will print the
# relative path of the entry.
find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \
| xargs -0 bash ${cleanup} "$newGenFiles"
}
cleanOldGen
linkNewGen
''
);
home.activation.checkFilesChanged = lib.hm.dag.entryBefore [ "linkGeneration" ] (
@@ -427,18 +334,6 @@ in
'') (lib.filter (v: v.onChange != "") cfg)
);
home.internal.filePutterConfig =
let
putter = import ./lib/putter.nix { inherit lib; };
manifest = putter.mkPutterManifest {
inherit putterStatePath;
sourceBaseDirectory = config.home-files;
targetBaseDirectory = config.home.homeDirectory;
fileEntries = cfg;
};
in
pkgs.writeText "hm-putter.json" manifest;
# Symlink directories and files that have the right execute bit.
# Copy files that need their execute bit changed.
home-files =
@@ -459,63 +354,6 @@ in
# contain the recursion root, not the visited files.
declare -A seenTargets
function setExecutableBit() {
local target="$1"
local executable="$2"
if [[ $executable == inherit ]]; then
# Don't change file mode if it should match the source.
:
elif [[ $executable ]]; then
chmod +x "$target"
else
chmod -x "$target"
fi
}
function insertFileEntry() {
local source="$1"
local target="$2"
local executable="$3"
local isExecutable
[[ -x $source ]] && isExecutable=1 || isExecutable=""
# Link the file into the home file directory if possible,
# i.e., if the executable bit of the source is the same we
# expect for the target. Otherwise, we copy the file and
# set the executable bit to the expected value.
if [[ $executable == inherit || $isExecutable == $executable ]]; then
ln -s "$source" "$target"
else
cp "$source" "$target"
setExecutableBit "$target" "$executable"
fi
}
function setLinkedFileExecutableBit() {
local target="$1"
local executable="$2"
local isExecutable
if [[ -d $target || ! -e $target ]]; then
return
fi
[[ -x $target ]] && isExecutable=1 || isExecutable=""
if [[ $executable == inherit || $isExecutable == $executable ]]; then
return
fi
local tmp
tmp="$(mktemp "$target.XXXXXX")"
cp "$target" "$tmp"
setExecutableBit "$tmp" "$executable"
mv -f "$tmp" "$target"
}
function insertFile() {
local source="$1"
local relTarget="$2"
@@ -571,19 +409,30 @@ in
else
lndir -silent "$source" "$target"
fi
if [[ $executable != inherit ]]; then
local linkedFile
while IFS= read -r -d "" linkedFile; do
setLinkedFileExecutableBit "$linkedFile" "$executable"
done < <(find "$target" \( -type f -or -type l \) -print0)
fi
else
ln -s "$source" "$target"
fi
else
insertFileEntry "$source" "$target" "$executable"
[[ -x $source ]] && isExecutable=1 || isExecutable=""
# Link the file into the home file directory if possible,
# i.e., if the executable bit of the source is the same we
# expect for the target. Otherwise, we copy the file and
# set the executable bit to the expected value.
if [[ $executable == inherit || $isExecutable == $executable ]]; then
ln -s "$source" "$target"
else
cp "$source" "$target"
if [[ $executable == inherit ]]; then
# Don't change file mode if it should match the source.
:
elif [[ $executable ]]; then
chmod +x "$target"
else
chmod -x "$target"
fi
fi
fi
}
''
+1 -1
View File
@@ -32,7 +32,7 @@ for sourcePath in "$@" ; do
warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be skipped since they are the same"
elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_COMMAND" ]] ; then
# Next, try to run the custom backup command. Assume this always succeeds.
verboseEcho "Existing file '$targetPath' exists and differs from '$sourcePath'. '$HOME_MANAGER_BACKUP_COMMAND' will be used to backup the file."
verboseEcho "Existing file '$targetPath' exists and differs from '$sourcePath'. `$HOME_MANAGER_BACKUP_COMMAND` will be used to backup the file."
elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
# Next, try to move the file to a backup location if configured and possible
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
+39 -51
View File
@@ -184,62 +184,38 @@ in
options = {
home.username = mkOption {
type = types.nonEmptyStr;
defaultText = lib.literalMD ''
`$USER`, for state version < 20.09,
undefined, otherwise.
type = types.str;
defaultText = literalExpression ''
"$USER" for state version < 20.09,
undefined for state version 20.09
'';
example = "jane.doe";
description = ''
The user's username.
If Home Manager is installed as a NixOS or nix-darwin submodule, it is
set to `osConfig.users.users.<name>.name`.
'';
description = "The user's username.";
};
home.uid = mkOption {
type = types.nullOr types.ints.unsigned;
default = null;
example = 1000;
description = ''
The user's uid.
If Home Manager is installed as a NixOS or nix-darwin submodule, it is
set to `osConfig.users.users.<name>.uid`.
'';
description = "The user's uid.";
};
home.homeDirectory = mkOption {
type = types.path;
defaultText = lib.literalMD ''
`$HOME`, for state version < 20.09
undefined, otherwise.
defaultText = literalExpression ''
"$HOME" for state version < 20.09,
undefined for state version 20.09
'';
apply = toString;
example = "/home/jane.doe";
description = ''
The user's home directory. Must be an absolute path.
If Home Manager is installed as a NixOS or nix-darwin submodule, it is
set to `osConfig.users.users.<name>.home`.
'';
description = "The user's home directory. Must be an absolute path.";
};
home.profileDirectory = mkOption {
type = types.path;
default =
if config.submoduleSupport.enable && config.submoduleSupport.externalPackageInstall then
"/etc/profiles/per-user/${cfg.username}"
else if config.nix.useXdg then
"${config.xdg.stateHome}/nix/profile"
else
cfg.homeDirectory + "/.nix-profile";
defaultText = lib.literalMD ''
- `/etc/profiles/per-user/''${home.username}`, if Home Manager is installed as
a submodule and `home-manager.useUserPackages` is enabled, else
- `''${xdg.stateHome}/nix/profile`, if `nix.useXdg` is enabled, else
- `''${home.homeDirectory}/.nix-profile`.
defaultText = literalExpression ''
"''${home.homeDirectory}/.nix-profile" or
"/etc/profiles/per-user/''${home.username}"
'';
readOnly = true;
description = ''
@@ -290,15 +266,12 @@ in
default = { };
type =
with types;
lazyAttrsOf (
nullOr (oneOf [
str
path
int
float
bool
])
);
lazyAttrsOf (oneOf [
str
path
int
float
]);
example = {
EDITOR = "emacs";
GS_OPTIONS = "-sPAPERSIZE=a4";
@@ -334,9 +307,6 @@ in
BAR = "''${config.home.sessionVariables.FOO} World!";
};
```
Setting a value to `null` will skip setting the variable at all, which
may be useful when overriding.
'';
};
@@ -593,6 +563,17 @@ in
};
config = {
assertions = [
{
assertion = config.home.username != "";
message = "Username could not be determined";
}
{
assertion = config.home.homeDirectory != "";
message = "Home directory could not be determined";
}
];
warnings =
let
hmRelease = config.home.version.release;
@@ -634,6 +615,14 @@ in
lib.mkDefault (builtins.getEnv "HOME")
);
home.profileDirectory =
if config.submoduleSupport.enable && config.submoduleSupport.externalPackageInstall then
"/etc/profiles/per-user/${cfg.username}"
else if config.nix.useXdg then
"${config.xdg.stateHome}/nix/profile"
else
cfg.homeDirectory + "/.nix-profile";
programs.bash.shellAliases = cfg.shellAliases;
programs.zsh.shellAliases = cfg.shellAliases;
programs.fish.shellAliases = cfg.shellAliases;
@@ -662,7 +651,7 @@ in
destination = "/etc/profile.d/hm-session-vars.sh";
text = ''
# Only source this once.
if [ -n "''${__HM_SESS_VARS_SOURCED-}" ]; then return; fi
if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
export __HM_SESS_VARS_SOURCED=1
${config.lib.shell.exportAll cfg.sessionVariables}
@@ -917,7 +906,6 @@ in
--subst-var-by GENERATION_DIR $out
ln -s ${config.home-files} $out/home-files
ln -s ${config.home.internal.filePutterConfig} $out/putter.json
ln -s ${cfg.path} $out/home-path
cp "$extraDependenciesPath" "$out/extra-dependencies"
+1
View File
@@ -46,6 +46,7 @@ let
in
{
meta.maintainers = with lib.maintainers; [
da157
kranzes
];
+40 -43
View File
@@ -10,16 +10,6 @@ let
fcitx5Package = cfg.fcitx5-with-addons.override { inherit (cfg) addons; };
iniFormat = pkgs.formats.ini { };
iniGlobalFormat = pkgs.formats.iniWithGlobalSection { };
normalizeFcitx5Value =
value:
if lib.isAttrs value then
lib.mapAttrs (_: normalizeFcitx5Value) value
else if builtins.isList value then
map normalizeFcitx5Value value
else if builtins.isBool value then
if value then "True" else "False"
else
value;
in
{
options = {
@@ -53,10 +43,12 @@ in
quickPhrase = lib.mkOption {
type = with lib.types; attrsOf str;
default = { };
example = {
smile = "";
angry = "()";
};
example = lib.literalExpression ''
{
smile = "";
angry = "()";
}
'';
description = "Quick phrases.";
};
@@ -81,16 +73,18 @@ in
description = ''
The global options in `config` file in ini format.
'';
example = {
Behavior = {
ActiveByDefault = false;
};
Hotkey = {
EnumerateWithTriggerKeys = true;
EnumerateSkipFirst = false;
ModifierOnlyKeyTimeout = 250;
};
};
example = lib.literalExpression ''
{
Behavior = {
ActiveByDefault = false;
};
Hotkey = {
EnumerateWithTriggerKeys = true;
EnumerateSkipFirst = false;
ModifierOnlyKeyTimeout = 250;
};
}
'';
};
inputMethod = lib.mkOption {
type = lib.types.submodule {
@@ -100,16 +94,18 @@ in
description = ''
The input method configure in `profile` file in ini format.
'';
example = {
GroupOrder."0" = "Default";
"Groups/0" = {
Name = "Default";
"Default Layout" = "us";
DefaultIM = "pinyin";
};
"Groups/0/Items/0".Name = "keyboard-us";
"Groups/0/Items/1".Name = "pinyin";
};
example = lib.literalExpression ''
{
GroupOrder."0" = "Default";
"Groups/0" = {
Name = "Default";
"Default Layout" = "us";
DefaultIM = "pinyin";
};
"Groups/0/Items/0".Name = "keyboard-us";
"Groups/0/Items/1".Name = "pinyin";
}
'';
};
addons = lib.mkOption {
type = with lib.types; (attrsOf iniGlobalFormat.type);
@@ -118,10 +114,12 @@ in
The addon configures in `conf` folder in ini format with global sections.
Each item is written to the corresponding file.
'';
example = {
classicui.globalSection.Theme = "example";
pinyin.globalSection.EmojiEnabled = "True";
};
example = lib.literalExpression ''
{
classicui.globalSection.Theme = "example";
pinyin.globalSection.EmojiEnabled = "True";
}
'';
};
};
@@ -233,12 +231,11 @@ in
lib.optionalAttrs (v != { }) {
${p} = f "fcitx5-${builtins.replaceStrings [ "/" ] [ "-" ] p}" v;
};
entries = lib.attrsets.mergeAttrsList [
(optionalFile "config" iniFormat.generate (normalizeFcitx5Value cfg.settings.globalOptions))
(optionalFile "profile" iniFormat.generate (normalizeFcitx5Value cfg.settings.inputMethod))
(optionalFile "config" iniFormat.generate cfg.settings.globalOptions)
(optionalFile "profile" iniFormat.generate cfg.settings.inputMethod)
(lib.concatMapAttrs (
name: value: optionalFile "conf/${name}.conf" iniGlobalFormat.generate (normalizeFcitx5Value value)
name: value: optionalFile "conf/${name}.conf" iniGlobalFormat.generate value
) cfg.settings.addons)
];
in
@@ -261,7 +258,7 @@ in
else if builtins.isString attrs.theme then
pkgs.writeText "fcitx5-theme.conf" attrs.theme
else
iniFormat.generate "fcitx5-${name}-theme" (normalizeFcitx5Value attrs.theme)
iniFormat.generate "fcitx5-${name}-theme" attrs.theme
))
]
) cfg.themes;
+55 -275
View File
@@ -14,55 +14,33 @@ let
dstDir = "${config.home.homeDirectory}/Library/LaunchAgents";
launchdConfig =
{ name, config, ... }:
{ config, name, ... }:
{
options = {
enable = lib.mkEnableOption name;
domain = lib.mkOption {
type = lib.types.enum [
"gui"
"user"
];
default = "gui";
example = "user";
description = ''
The launchd domain to bootstrap this agent into.
The `gui` domain is appropriate for agents that need the user's
Aqua session, such as window managers, hotkey daemons, and other
graphical tools. The `user` domain is appropriate for background
services that do not require a graphical login session.
'';
};
config = lib.mkOption {
type = lib.types.submodule (import ./launchd.nix);
default = { };
example = {
ProgramArguments = [
"/usr/bin/say"
"Good afternoon"
];
StartCalendarInterval = [
{
Hour = 12;
Minute = 0;
}
];
};
example = lib.literalExpression ''
{
ProgramArguments = [ "/usr/bin/say" "Good afternoon" ];
StartCalendarInterval = [
{
Hour = 12;
Minute = 0;
}
];
}
'';
description = ''
Define a launchd job. See {manpage}`launchd.plist(5)` for details.
'';
};
};
config = lib.mkMerge [
{
config.Label = lib.mkDefault "${labelPrefix}${name}";
}
(lib.mkIf (config.domain == "user") {
config.LimitLoadToSessionType = lib.mkDefault "Background";
})
];
config = {
config.Label = lib.mkDefault "${labelPrefix}${name}";
};
};
# mutateConfig calls /bin/sh with /bin/wait4path to wait for /nix/store before
@@ -91,16 +69,9 @@ let
toAgent =
config: pkgs.writeText "${config.Label}.plist" (toPlist { escape = true; } (mutateConfig config));
agentPlists = lib.mapAttrs' (
_n: v: lib.nameValuePair "${v.config.Label}.plist" (toAgent v.config)
) (lib.filterAttrs (_n: v: v.enable) cfg.agents);
agentDomains = lib.mapAttrs' (
_n: v:
lib.nameValuePair "${v.config.Label}.domain" (
pkgs.writeText "${v.config.Label}.domain" "${v.domain}\n"
)
) (lib.filterAttrs (_n: v: v.enable) cfg.agents);
agentPlists = lib.mapAttrs' (n: v: lib.nameValuePair "${v.config.Label}.plist" (toAgent v.config)) (
lib.filterAttrs (n: v: v.enable) cfg.agents
);
agentsDrv = pkgs.runCommand "home-manager-agents" { } ''
mkdir -p "$out"
@@ -115,20 +86,6 @@ let
ln -s "$src" "$out/$dest"
done
'';
agentDomainsDrv = pkgs.runCommand "home-manager-agent-domains" { } ''
mkdir -p "$out"
declare -A domains
domains=(${
lib.concatStringsSep " " (lib.mapAttrsToList (name: value: "['${name}']='${value}'") agentDomains)
})
for dest in "''${!domains[@]}"; do
src="''${domains[$dest]}"
ln -s "$src" "$out/$dest"
done
'';
in
{
meta.maintainers = with lib.maintainers; [
@@ -171,7 +128,6 @@ in
(lib.mkIf isDarwin {
home.extraBuilderCommands = ''
ln -s "${agentsDrv}" $out/LaunchAgents
ln -s "${agentDomainsDrv}" $out/LaunchAgentDomains
'';
# NOTE: Launch Agent configurations can't be symlinked from the Nix store
@@ -179,53 +135,9 @@ in
home.activation.setupLaunchAgents =
lib.hm.dag.entryAfter [ "writeBoundary" ] # Bash
''
# Get the OS version to see if we can use --wait
version="$(/usr/bin/sw_vers --productVersion | cut -d. -f 1)"
# Disable errexit to ensure we process all agents even if some fail
set +e
readAgentDomain() {
local domainsDir="$1"
local agentName="$2"
local domainFile="$domainsDir/$agentName.domain"
if [[ -n "$domainsDir" && -f "$domainFile" ]]; then
local domainName
domainName="$(<"$domainFile")"
case "$domainName" in
gui|user)
printf '%s\n' "$domainName"
;;
*)
printf 'gui\n'
;;
esac
else
printf 'gui\n'
fi
}
resolveDomain() {
local domainName="$1"
case "$domainName" in
gui)
printf 'gui/%s\n' "$UID"
;;
user)
printf 'user/%s\n' "$UID"
;;
esac
}
agentIsLoaded() {
local domain="$1"
local agentName="$2"
run /bin/launchctl print "$domain/$agentName" >/dev/null 2>&1
}
# Stop an agent if it's running
bootoutAgent() {
local domain="$1"
@@ -233,37 +145,24 @@ in
verboseEcho "Stopping agent '$domain/$agentName'..."
local bootout_output
if [[ "$version" -ge "26" ]]; then
if bootout_output=$(run /bin/launchctl bootout --wait "$domain/$agentName" 2>&1); then
# --wait already makes sure it was unloaded (BUT we can only use it in >=26)
return 0
bootout_output=$(run /bin/launchctl bootout "$domain/$agentName" 2>&1) || {
# Only show warning if it's not the common "No such process" error
if [[ "$bootout_output" != *"No such process"* ]]; then
warnEcho "Failed to stop agent '$domain/$agentName': $bootout_output"
else
verboseEcho "Agent '$domain/$agentName' was not running"
fi
else
if bootout_output=$(run /bin/launchctl bootout "$domain/$agentName" 2>&1); then
# Otherwise on <26 give the system a moment to fully unload the agent
run sleep 1
return 0
fi
fi
}
# At this point we know exit code is not 0 because otherwise we
# would have returned by now
# Only show warning if it's not a common harmless error
if [[ "$bootout_output" != *"No such process"* && "$bootout_output" != *"Domain does not support specified action"* ]]; then
warnEcho "Failed to stop agent '$domain/$agentName': $bootout_output"
return 1
else
verboseEcho "Agent '$domain/$agentName' was not running"
return 2
fi
# Give the system a moment to fully unload the agent
sleep 1
}
installAgentFile() {
installAndBootstrapAgent() {
local srcPath="$1"
local dstPath="$2"
local agentName="$3"
local domain="$3"
local agentName="$4"
verboseEcho "Installing agent file to $dstPath"
if ! run install -Dm444 -T "$srcPath" "$dstPath"; then
@@ -271,17 +170,11 @@ in
return 1
fi
return 0
}
bootstrapAgent() {
local domain="$1"
local dstPath="$2"
local agentName="$3"
verboseEcho "Starting agent '$domain/$agentName'"
local bootstrap_output
bootstrap_output=$(run /bin/launchctl bootstrap "$domain" "$dstPath" 2>&1) || {
local error_code=$?
if [[ "$bootstrap_output" == *"Bootstrap failed: 5: Input/output error"* ]]; then
errorEcho "Failed to start agent '$domain/$agentName' with I/O error (code 5)"
errorEcho "This typically happens when the agent wasn't unloaded before attempting to bootstrap the new agent."
@@ -296,120 +189,42 @@ in
return 0
}
restoreAgent() {
local oldSrcPath="$1"
local dstPath="$2"
local oldDomain="$3"
local agentName="$4"
if [[ ! -f "$oldSrcPath" ]]; then
warnEcho "Cannot restore previous agent '$oldDomain/$agentName', old file '$oldSrcPath' is missing"
return 1
fi
warnEcho "Restoring previous agent '$oldDomain/$agentName'"
installAgentFile "$oldSrcPath" "$dstPath" "$agentName" \
&& bootstrapAgent "$oldDomain" "$dstPath" "$agentName"
}
processAgent() {
local srcPath="$1"
local dstDir="$2"
local oldDir="$3"
local oldDomainsDir="$4"
local newDomainsDir="$5"
local domain="$3"
local agentFile="''${srcPath##*/}"
local agentName="''${agentFile%.plist}"
local dstPath="$dstDir/$agentFile"
local oldSrcPath=""
local oldDomainName
local newDomainName
local oldDomain
local newDomain
local oldAgentBootedOut=0
oldDomainName="$(readAgentDomain "$oldDomainsDir" "$agentName")"
newDomainName="$(readAgentDomain "$newDomainsDir" "$agentName")"
oldDomain="$(resolveDomain "$oldDomainName")"
newDomain="$(resolveDomain "$newDomainName")"
if [[ -n "$oldDir" ]]; then
oldSrcPath="$oldDir/$agentFile"
fi
# Skip if unchanged
if cmp -s "$srcPath" "$dstPath" && [[ "$oldDomainName" == "$newDomainName" ]]; then
if agentIsLoaded "$newDomain" "$agentName"; then
verboseEcho "Agent '$newDomain/$agentName' is already up-to-date"
return 0
else
verboseEcho "Agent '$newDomain/$agentName' is up-to-date but not loaded"
fi
fi
verboseEcho "Processing agent '$newDomain/$agentName'"
# Stop/Unload agent if it's already running
if [[ -f "$dstPath" ]]; then
bootoutAgent "$oldDomain" "$agentName"
case "$?" in
0)
oldAgentBootedOut=1
;;
2)
;;
*)
return 1
;;
esac
fi
if [[ "$oldDomainName" != "$newDomainName" ]]; then
bootoutAgent "$newDomain" "$agentName"
case "$?" in
0|2)
;;
*)
if [[ "$oldAgentBootedOut" -eq 1 ]]; then
restoreAgent "$oldSrcPath" "$dstPath" "$oldDomain" "$agentName"
fi
return 1
;;
esac
fi
if ! installAgentFile "$srcPath" "$dstPath" "$agentName"; then
if [[ "$oldAgentBootedOut" -eq 1 ]]; then
restoreAgent "$oldSrcPath" "$dstPath" "$oldDomain" "$agentName"
fi
return 1
fi
if bootstrapAgent "$newDomain" "$dstPath" "$agentName"; then
if cmp -s "$srcPath" "$dstPath"; then
verboseEcho "Agent '$agentName' is already up-to-date"
return 0
fi
if [[ "$oldAgentBootedOut" -eq 1 ]]; then
restoreAgent "$oldSrcPath" "$dstPath" "$oldDomain" "$agentName"
verboseEcho "Processing agent '$agentName'"
# Stop/Unload agent if it's already running
if [[ -f "$dstPath" ]]; then
bootoutAgent "$domain" "$agentName"
fi
return 1
installAndBootstrapAgent "$srcPath" "$dstPath" "$domain" "$agentName"
# Note: We continue processing even if this agent fails
return 0
}
removeAgent() {
local srcPath="$1"
local dstDir="$2"
local newDir="$3"
local oldDomainsDir="$4"
local domain="$4"
local agentFile="''${srcPath##*/}"
local agentName="''${agentFile%.plist}"
local dstPath="$dstDir/$agentFile"
local domainName
local domain
domainName="$(readAgentDomain "$oldDomainsDir" "$agentName")"
domain="$(resolveDomain "$domainName")"
if [[ -e "$newDir/$agentFile" ]]; then
verboseEcho "Agent '$agentName' still exists in new generation, skipping cleanup"
@@ -428,32 +243,23 @@ in
# Stop and remove the agent
bootoutAgent "$domain" "$agentName"
case "$?" in
0|2)
;;
*)
return 1
;;
esac
verboseEcho "Removing agent file '$dstPath'"
if run rm -f $VERBOSE_ARG "$dstPath"; then
verboseEcho "Successfully removed agent file for '$agentName'"
else
warnEcho "Failed to remove agent file '$dstPath'"
return 1
fi
return 0
}
setupLaunchAgents() {
local oldDir newDir oldDomainsDir newDomainsDir dstDir launchdStatus
local oldDir newDir dstDir domain
newDir="$(readlink -m "$newGenPath/LaunchAgents")"
newDomainsDir="$(readlink -m "$newGenPath/LaunchAgentDomains")"
dstDir=${lib.escapeShellArg dstDir}
launchdStatus=0
domain="gui/$UID"
if [[ -n "''${oldGenPath:-}" ]]; then
oldDir="$(readlink -m "$oldGenPath/LaunchAgents")"
@@ -461,60 +267,34 @@ in
verboseEcho "No previous LaunchAgents directory found"
oldDir=""
fi
oldDomainsDir="$(readlink -m "$oldGenPath/LaunchAgentDomains")"
if [[ ! -d "$oldDomainsDir" ]]; then
oldDomainsDir=""
fi
else
oldDir=""
oldDomainsDir=""
fi
verboseEcho "Setting up LaunchAgents in $dstDir"
if [[ ! -d "$dstDir" ]] && ! run mkdir -p "$dstDir"; then
errorEcho "Failed to create LaunchAgents directory '$dstDir'"
return 1
fi
[[ -d "$dstDir" ]] || run mkdir -p "$dstDir"
verboseEcho "Processing new/updated LaunchAgents..."
while IFS= read -r srcPath; do
processAgent "$srcPath" "$dstDir" "$oldDir" "$oldDomainsDir" "$newDomainsDir" \
|| launchdStatus=1
done < <(find -L "$newDir" -maxdepth 1 -name '*.plist' -type f)
find -L "$newDir" -maxdepth 1 -name '*.plist' -type f | while read -r srcPath; do
processAgent "$srcPath" "$dstDir" "$domain"
done
# Skip cleanup if there's no previous generation
if [[ -z "$oldDir" || ! -d "$oldDir" ]]; then
if [[ "$launchdStatus" -ne 0 ]]; then
errorEcho "Failed to activate one or more LaunchAgents"
fi
verboseEcho "LaunchAgents setup complete"
return "$launchdStatus"
return
fi
verboseEcho "Cleaning up removed LaunchAgents..."
while IFS= read -r srcPath; do
removeAgent "$srcPath" "$dstDir" "$newDir" "$oldDomainsDir" \
|| launchdStatus=1
done < <(find -L "$oldDir" -maxdepth 1 -name '*.plist' -type f)
if [[ "$launchdStatus" -ne 0 ]]; then
errorEcho "Failed to activate one or more LaunchAgents"
fi
return "$launchdStatus"
find -L "$oldDir" -maxdepth 1 -name '*.plist' -type f | while read -r srcPath; do
removeAgent "$srcPath" "$dstDir" "$newDir" "$domain"
done
}
launchdStatus=0
setupLaunchAgents || launchdStatus=$?
setupLaunchAgents
# Restore errexit
set -e
if [[ "$launchdStatus" -ne 0 ]]; then
exit "$launchdStatus"
fi
'';
})
];
+1
View File
@@ -1,3 +1,4 @@
{ lib }:
{
# Converts a boolean to a yes/no string. This is used in lots of
# configuration formats.
+24 -40
View File
@@ -12,32 +12,20 @@
let
inherit (lib)
all
attrNames
attrValues
elem
filter
filterAttrs
head
hm
isAttrs
mapAttrs
length
tail
toposort
;
inherit (hm.dag)
empty
entriesBetween
entryAfter
entryBetween
isEntry
;
in
{
empty = { };
isEntry = e: e ? data && e ? after && e ? before;
isDag = dag: isAttrs dag && all isEntry (attrValues dag);
isDag = dag: builtins.isAttrs dag && all hm.dag.isEntry (builtins.attrValues dag);
# Takes an attribute set containing entries built by entryAnywhere,
# entryAfter, and entryBefore to a topologically sorted list of
@@ -96,19 +84,16 @@ in
# }
# true
topoSort =
let
before = a: b: elem a.name b.after;
in
dag:
let
names = attrNames dag;
dagBefore = name: filter (n: elem name dag.${n}.before) names;
dagBefore = dag: name: builtins.attrNames (filterAttrs (n: v: builtins.elem name v.before) dag);
normalizedDag = mapAttrs (n: v: {
name = n;
inherit (v) data;
after = v.after ++ dagBefore n;
after = v.after ++ dagBefore dag n;
}) dag;
sorted = toposort before (attrValues normalizedDag);
before = a: b: builtins.elem a.name b.after;
sorted = toposort before (builtins.attrValues normalizedDag);
in
if sorted ? result then
{
@@ -123,10 +108,10 @@ in
entryBetween = before: after: data: { inherit data before after; };
# Create a DAG entry with no particular dependency information.
entryAnywhere = entryBetween [ ] [ ];
entryAnywhere = hm.dag.entryBetween [ ] [ ];
entryAfter = entryBetween [ ];
entryBefore = before: entryBetween before [ ];
entryAfter = hm.dag.entryBetween [ ];
entryBefore = before: hm.dag.entryBetween before [ ];
# Given a list of entries, this function places them in order within the DAG.
# Each entry is labeled "${tag}-${entry index}" and other DAG entries can be
@@ -139,25 +124,24 @@ in
let
go =
i: before: after: entries:
let
name = "${tag}-${toString i}";
in
if entries == [ ] then
empty
hm.dag.empty
else if length entries == 1 then
{
"${name}" = hm.dag.entryBetween before after (head entries);
}
else
let
name = "${tag}-${toString i}";
in
if length entries == 1 then
{
"${name}" = entryBetween before after (head entries);
}
else
{
"${name}" = entryAfter after (head entries);
}
// go (i + 1) before [ name ] (tail entries);
{
"${name}" = hm.dag.entryAfter after (head entries);
}
// go (i + 1) before [ name ] (tail entries);
in
go 0;
entriesAnywhere = tag: entriesBetween tag [ ] [ ];
entriesAfter = tag: entriesBetween tag [ ];
entriesBefore = tag: before: entriesBetween tag before [ ];
entriesAnywhere = tag: hm.dag.entriesBetween tag [ ] [ ];
entriesAfter = tag: hm.dag.entriesBetween tag [ ];
entriesBefore = tag: before: hm.dag.entriesBetween tag before [ ];
}
+1 -3
View File
@@ -5,14 +5,12 @@ rec {
assertions = import ./assertions.nix { inherit lib; };
booleans = import ./booleans.nix;
booleans = import ./booleans.nix { inherit lib; };
darwin = import ./darwin.nix { inherit lib; };
deprecations = import ./deprecations.nix { inherit lib; };
generators = import ./generators.nix { inherit lib; };
git = import ./git.nix { inherit lib; };
gvariant = import ./gvariant.nix { inherit lib; };
maintainers = import ./maintainers.nix;
mcp = import ./mcp.nix { inherit lib; };
strings = import ./strings.nix { inherit lib; };
types = import ./types.nix { inherit gvariant lib; };

Some files were not shown because too many files have changed in this diff Show More