Skip to content

Commit

Permalink
feat: Add .chezmoiroot to allow source state to be subdir of source dir
Browse files Browse the repository at this point in the history
Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
  • Loading branch information
twpayne and felipecrs committed Nov 14, 2021
1 parent 5d53e3c commit 8a6d4d7
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 1 deletion.
32 changes: 32 additions & 0 deletions docs/HOWTO.md
Expand Up @@ -54,6 +54,7 @@
* [Run a PowerShell script as admin on Windows](#run-a-powershell-script-as-admin-on-windows)
* [Use chezmoi with GitHub Codespaces, Visual Studio Codespaces, or Visual Studio Code Remote - Containers](#use-chezmoi-with-github-codespaces-visual-studio-codespaces-or-visual-studio-code-remote---containers)
* [Customize chezmoi](#customize-chezmoi)
* [Use a subdirectory of your dotfiles repo as the root of the source state](#use-a-subdirectory-of-your-dotfiles-repo-as-the-root-of-the-source-state)
* [Don't show scripts in the diff output](#dont-show-scripts-in-the-diff-output)
* [Customize the diff pager](#customize-the-diff-pager)
* [Use a custom diff tool](#use-a-custom-diff-tool)
Expand Down Expand Up @@ -1602,6 +1603,37 @@ sudo apt install -y vim-gtk

---

### Use a subdirectory of your dotfiles repo as the root of the source state

By default, chezmoi uses the root of your dotfiles repo as the root of the
source state. If your source state contains many entries in its root, then your
target directory (usually your home directory) will in turn be filled with many
entries in its root as well. You can reduce the number of entries by keeping
`.chezmoiignore` up to date, but this can become tiresome.

Instead, you can specify that chezmoi should read the source state from a
subdirectory of the source directory instead by creating a file called
`.chezmoiroot` containing the relative path to this subdirectory.

For example, if `.chezmoiroot` contains:

```
home
```

Then chezmoi will read the source state from the `home` subdirectory of your
source directory, for example the desired state of `~/.gitconfig` will be read
from `~/.local/share/chezmoi/home/dot_gitconfig` (instead of
`~/.local/share/chezmoi/dot_gitconfig`).

When migrating an existing chezmoi dotfiles repo to use `.chezmoiroot` you will
need to move the relevant files in to the new root subdirectory manually. You do
not need to move files that are ignored by chezmoi in all cases (i.e. are listed
in `.chezmoiignore` when executed as a template on all machines), and you can
afterwards remove their entries from `home/.chezmoiignore`.

---

### Don't show scripts in the diff output

By default, `chezmoi diff` will show all changes, including the contents of
Expand Down
10 changes: 10 additions & 0 deletions docs/REFERENCE.md
Expand Up @@ -50,6 +50,7 @@ Manage your dotfiles across multiple machines, securely.
* [`.chezmoiexternal.<format>`](#chezmoiexternalformat)
* [`.chezmoiignore`](#chezmoiignore)
* [`.chezmoiremove`](#chezmoiremove)
* [`.chezmoiroot`](#chezmoiroot)
* [`.chezmoitemplates`](#chezmoitemplates)
* [`.chezmoiversion`](#chezmoiversion)
* [Commands](#commands)
Expand Down Expand Up @@ -875,6 +876,15 @@ template.

---

### `.chezmoiroot`

If a file called `.chezmoiroot` exists in the root of the source directory then
the source state is read from the directory specified in `.chezmoiroot`
interpreted as a relative path to the source directory. `.chezmoiroot` is read
before all other files in the source directory.

---

### `.chezmoitemplates`

If a directory called `.chezmoitemplates` exists, then all files in this
Expand Down
2 changes: 2 additions & 0 deletions internal/chezmoi/chezmoi.go
Expand Up @@ -50,6 +50,7 @@ const (
const (
Prefix = ".chezmoi"

RootName = Prefix + "root"
dataName = Prefix + "data"
externalName = Prefix + "external"
ignoreName = Prefix + "ignore"
Expand All @@ -69,6 +70,7 @@ var knownPrefixedFiles = newStringSet(
Prefix+".json"+TemplateSuffix,
Prefix+".toml"+TemplateSuffix,
Prefix+".yaml"+TemplateSuffix,
RootName,
dataName,
externalName+".json",
externalName+".toml",
Expand Down
12 changes: 11 additions & 1 deletion internal/cmd/config.go
Expand Up @@ -1285,6 +1285,16 @@ func (c *Config) newRootCmd() (*cobra.Command, error) {
// newSourceState returns a new SourceState with options.
func (c *Config) newSourceState(ctx context.Context, options ...chezmoi.SourceStateOption) (*chezmoi.SourceState, error) {
sourceStateLogger := c.logger.With().Str(logComponentKey, logComponentValueSourceState).Logger()

sourceDirAbsPath := c.SourceDirAbsPath
switch data, err := c.sourceSystem.ReadFile(c.SourceDirAbsPath.JoinString(chezmoi.RootName)); {
case errors.Is(err, fs.ErrNotExist):
case err != nil:
return nil, err
default:
sourceDirAbsPath = c.SourceDirAbsPath.JoinString(string(bytes.TrimSpace(data)))
}

s := chezmoi.NewSourceState(append([]chezmoi.SourceStateOption{
chezmoi.WithBaseSystem(c.baseSystem),
chezmoi.WithCacheDir(c.CacheDirAbsPath),
Expand All @@ -1295,7 +1305,7 @@ func (c *Config) newSourceState(ctx context.Context, options ...chezmoi.SourceSt
chezmoi.WithLogger(&sourceStateLogger),
chezmoi.WithMode(c.Mode),
chezmoi.WithPriorityTemplateData(c.Data),
chezmoi.WithSourceDir(c.SourceDirAbsPath),
chezmoi.WithSourceDir(sourceDirAbsPath),
chezmoi.WithSystem(c.sourceSystem),
chezmoi.WithTemplateFuncs(c.templateFuncs),
chezmoi.WithTemplateOptions(c.Template.Options),
Expand Down
36 changes: 36 additions & 0 deletions internal/cmd/testdata/scripts/root.txt
@@ -0,0 +1,36 @@
# test that chezmoi apply uses .chezmoiroot
chezmoi apply
cmp $HOME/.file golden/.file

# test that chezmoi add uses .chezmoiroot
symlink $HOME/.symlink -> .file
chezmoi add $HOME${/}.symlink
cmp $CHEZMOISOURCEDIR/home/symlink_dot_symlink golden/symlink_dot_symlink

[!exec:git] skip 'git not found in $PATH'
[windows] skip 'go-git does not support file:// URLs on windows'

chhome home2/user
mkgitconfig

# create a git repo in home2/user/repo
exec git -C $HOME/repo init
exec git -C $HOME/repo add .
exec git -C $HOME/repo commit -m 'Initial commit'

# test that chezmoi init uses .chezmoiroot
chezmoi init --apply file://$HOME/repo
cmp $HOME/.file golden/.file

-- golden/.file --
# contents of .file
-- golden/symlink_dot_symlink --
.file
-- home/user/.local/share/chezmoi/.chezmoiroot --
home
-- home/user/.local/share/chezmoi/home/dot_file --
# contents of .file
-- home2/user/repo/.chezmoiroot --
home
-- home2/user/repo/home/dot_file --
# contents of .file

0 comments on commit 8a6d4d7

Please sign in to comment.