Closed skyfaller closed 2 years ago
Nested conditionals work. I think what's happening in your case is that the {{-
template tags are consuming whitespace (including the previous newline) and so you'll ending up with corrupted patterns in your .chezmoiignore
file.
Try replacing the {{-
s with {{
s. You can use chezmoi execute-template
to check the template is correct.
Hm, nesting doesn't work the way I thought it did in .chezmoiignore
. Here's what I get:
> chezmoi execute-template < .chezmoiignore
Library # only manage Library folder on macOS
None of the Linux stuff shows up at all, because it's all in Linux. All that gets ignored is the Mac stuff. I think I need a different approach to selectively ignore some Linux stuff.
Replacing the {{-
with {{
seems to have no effect, aside from an extra line of whitespace at the end of the file:
{{ if ne .chezmoi.os "darwin" }}
Library # only manage Library folder on macOS
{{ else if ne .chezmoi.os "linux" }}
.config/Code/ # VS Code settings live here on Linux
{{ if ne .chezmoi.osrelease.id "fedora" }}
.config/fish/functions/theme-konsole.fish # KDE only on Linux
.config/mako/
.config/sway/
{{ end }}
{{ end }}
> chezmoi execute-template < .chezmoiignore
Library # only manage Library folder on macOS
None of the Linux stuff shows up at all, because it's all in Linux. All that gets ignored is the Mac stuff. I think I need a different approach to selectively ignore some Linux stuff.
You're on the right track. Your if-else statement is testing for .chezmoi.os
not equal to the specified values, so all Linux distros will activate the first branch only. They will never see the nested conditional at all.
Also, due to the negative logic, the second conditional (ne .chezmoi.os "linux"
) is redundant; that is, if the OS is darwin (i.e. the first conditional evaluates to false
), it will inherently not be linux (i.e. the second conditional will always evaluate to true
).
Finally, you're trying to test if the OS is not Linux, and only then checking to see if it's not Fedora. This will always be true, as any OS that isn't Linux is also guaranteed to not be Fedora.
Long story short, you need to put the "fedora" check inside the "not Darwin" branch:
{{- if ne .chezmoi.os "darwin" }}
darwin-only stuff goes here
{{- if eq .chezmoi.os "linux" }}
{{- if ne .chezmoi.osRelease.id "fedora" }}
fedora-only stuff goes here
{{- end }}
{{- end }}
{{- end }}
Long story short, you need to put the "fedora" check inside the "not Darwin" branch:
Thank you for writing out a solution! It seems inelegant somehow, but the whole negating the thing you want to ignore is confusing as heck anyway, this is just another counterintuitive wrinkle.
At any rate, your suggestion worked for me. When run on Fedora, it gives the desired result:
{{ if ne .chezmoi.os "darwin" -}}
Library # only manage Library folder on macOS
{{- if eq .chezmoi.os "linux" }}
.config/Code/ # VS Code settings live here on Linux
{{- if eq .chezmoi.osRelease.id "fedora" }}
.config/fish/functions/theme-konsole.fish # KDE only on Linux
.config/mako/
.config/sway/
{{- end }}
{{- end }}
{{- end }}
> chezmoi execute-template < .chezmoiignore
Library # only manage Library folder on macOS
.config/Code/ # VS Code settings live here on Linux
.config/fish/functions/theme-konsole.fish # KDE only on Linux
.config/mako/
.config/sway/
Wait, no, that's not what I want. Now both the Mac (stored in the Library) and Linux copies of my VS Code config files are ignored. I guess I have to do a separate branch for the generic (non-Fedora) Linux stuff:
{{ if ne .chezmoi.os "darwin" -}}
Library # only manage Library folder on macOS
{{- if eq .chezmoi.os "linux" }}
{{- if eq .chezmoi.osRelease.id "fedora" }}
.config/fish/functions/theme-konsole.fish # KDE on Linux but not Fedora
.config/mako/
.config/sway/
{{- end }}
{{- end }}
{{- end }}
{{- if ne .chezmoi.os "linux" }}
.config/Code/ # VS Code settings live here on Linux
{{- end }}
> chezmoi execute-template < .chezmoiignore
Library # only manage Library folder on macOS
.config/fish/functions/theme-konsole.fish # KDE on Linux but not Fedora
.config/mako/
.config/sway/
This is getting really confusing and inelegant, but I think it actually works now. Good enough.
I just tested it on Mac and found a further wrinkle: now the stuff I want ignored on Fedora doesn't get ignored on Mac.
> chezmoi execute-template < .chezmoiignore
.config/Code/ # VS Code settings live here on Linux
I guess I have to copy and paste it to the stuff I want Mac to ignore? I don't like duplicating code. I'm leaving this issue open because there must be a better way to do this. That said, here's my current solution:
{{- if ne .chezmoi.os "darwin" -}}
Library # only manage Library folder on macOS
{{- if eq .chezmoi.os "linux" }}
{{- if eq .chezmoi.osRelease.id "fedora" }}
.config/fish/functions/theme-konsole.fish # KDE on Linux but not Fedora
.config/mako/
.config/sway/
{{- end }}
{{- end }}
{{- end }}
{{- if ne .chezmoi.os "linux" -}}
.config/Code/ # VS Code settings live here on Linux
.config/fish/functions/theme-konsole.fish # KDE only on Linux
.config/mako/
.config/sway/
{{- end }}
> chezmoi execute-template < .chezmoiignore
.config/Code/ # VS Code settings live here on Linux
.config/fish/functions/theme-konsole.fish # KDE only on Linux
.config/mako/
.config/sway/
Ah, I think I see where I wasn't understanding what you're after. In order to avoid duplication of ignore lines, you must be willing to accept some redundancy of logic blocks. (As a convenience I use a custom variable in chezmoi.conf [I call it .system.id
, but the name doesn't matter] that contains both .chezmoi.os
and .chezmoi.osRelease.id
[if it exists]. You can reference my .chezmoiignore for a more involved example.)
{{- if ne .chezmoi.os "darwin" }}
Library/ # only manage Library folder on macOS
{{- end }}
{{- if ne .chezmoi.os "linux" }}
.config/Code/ # VS Code settings live here on Linux
{{- end }}
{{- if or (ne .chezmoi.os "linux") (eq .system.id "linux-fedora") }}
.config/fish/functions/theme-konsole.fish # KDE only on Linux but not Fedora
.config/mako/
.config/sway/
{{- end }}
Thank you @dragonmaus for all your help here.
(As a convenience I use a custom variable in chezmoi.conf [I call it
.system.id
, but the name doesn't matter] that contains both.chezmoi.os
and.chezmoi.osRelease.id
[if it exists]. You can reference my .chezmoiignore for a more involved example.)
This is a stroke of genius. Thank you so much for the examples! This will make my code much more compact and readable, I can stop nesting .chezmoi.osRelease.id
inside of tests for Linux everywhere. I am using your code verbatim.
I think this abstraction ought to be in Chezmoi itself, so long as testing for specific Linux distros fails on any OS like macOS that does not have distro IDs: https://github.com/twpayne/chezmoi/issues/969
But I suppose I can open another feature request for that.
Thanks, this is a great trick. For now I've documented it in dca459b22754ddaab30bda152ed4d07119488cb2.
What exactly are you trying to do?
I have a Mac and several Linux computers. I find that I generally cannot test for specific Linux distributions unless the conditionals are nested within a conditional testing whether we're running Linux, because Mac does not have .chezmoi.osRelease.id and Chezmoi will error out.
I want to have some files that appear on certain Linux distributions and not others (for example, configuration files for window managers like KDE or Sway that I only use on specific distros / computers).
What have you tried so far?
Here is the .chezmoiignore file I'm trying to use:
I don't use Sway or KDE on Fedora, so don't want those config files. But this code does not seem to work. Chezmoi wants to create those files on Fedora anyway when I run
chezmoi apply
. This code previously worked fine for differentiating between Mac and Linux, before I tried nesting conditionals in .chezmoiignore.Where else have you checked for solutions?
Output of
chezmoi doctor