twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
12.9k stars 478 forks source link

Possible to run scripts on "add" or "re-add" #2799

Closed alexjp closed 1 year ago

alexjp commented 1 year ago

Hi,

Is your feature request related to a problem? Please describe.

Currently I have a few (not many, but a few) folders with lots of files. The actual important files are not many, but I need all the folder. Adding this folder/managing it, is somewhat slow with chezmoi.

One idea to work around this would be to have scripts manage some folders with rsync.

Describe the solution you'd like

If it would be possible to have scripts run when "add"ing new files or "re-add"ing new files. With those scripts I could use the rsync functionality to either sync the "source" folder to "target" (which already works with apply), and sync the "target" folder to "source", by syncing with "add" or "re-add".

Example:

Describe alternatives you've considered

Currently I am just adding everything into managed state, which is kinda slow and unnecessary, since those files aren't important to be "managed by git", although I would like to already have them there.

Additional context

Maybe add a mechanism to know if the script would be ran as part of "apply" or "add"/"re-add".

As an ending note, in this issue I am thinking of using script to manage rsync in both ways.... but it could be probably be useful for other situations!

Thank you!

bradenhilton commented 1 year ago

From your example, are the "plugins/etc" maintained by you, or are they acquired from somewhere else?

If they are acquired from somewhere else, you could explore using .chezmoiexternal to acquire them. This allows chezmoi to manage them, without the need to add them to your dotfile repo.

alexjp commented 1 year ago

From your example, are the "plugins/etc" maintained by you, or are they acquired from somewhere else?

If they are acquired from somewhere else, you could explore using .chezmoiexternal to acquire them. This allows chezmoi to manage them, without the need to add them to your dotfile repo.

they are mantained by the app logseq, based on the plugins and settings I have. So, they are kinda automatic, but still based on the settings I have here on the app. (If I have more plugins, more files).

maybe for a more "known example", something like firefox profiles: I could mantain the profiles.ini / prefs.js / user.js / chrome file in chezmoi git, but the rest of the files could be rsync'hed.

In the case of the .chezmoiexternal, it could be usefull, but for the "apply" functionality. Meaning, for example, I do a re-add, the script updates an external, and then chezmoi updates through .chezmoiexternal. To be clear, kinda like I don't want to acquire from the external, I want to update the external.

Hope I am getting clear on my purpose... I guess its not a popular usecase.

bradenhilton commented 1 year ago

Could you give an example of what happens currently? e.g. directories filling up with files, file trees etc.

I've had an extremely brief look at the logseq docs, so I'm most likely wrong here, but it looks like the app manages the plugins.edn file. Perhaps Handle configuration files which are externally modified could work well here?

alexjp commented 1 year ago

Could you give an example of what happens currently? e.g. directories filling up with files, file trees etc.

I've had an extremely brief look at the logseq docs, so I'm most likely wrong here, but it looks like the app manages the plugins.edn file. Perhaps Handle configuration files which are externally modified could work well here?

The symlink unfortunatly doesn't work, because I want to copy the files (so that they are available to where chezmoi is used).

I will give what I currently have: on apply, I have this script:

File: run_10_rsync_plugins.sh
#!/usr/bin/env bash

rsync -ai $DOT_FILES_PLUGINS_FOLDER $DOT_LOGSEQ_FOLDER

Those env variables are set in the config toml file. That does is sync the plugins folder (i am using chezmoi-source/.files/plugins), which is the plugins code and node modules into ~/.logseq/plugins

So when I do chezmoi apply, it applys the git chezmoi changes, and syncs the plugins folder to its proper place.

What I wanted, is when I do an add or re-add (meaning that I added some plugin or I updated the plugins), I want to run some script like this:

File: run_10_rsync_plugins.sh
#!/usr/bin/env bash

rsync -ai $DOT_LOGSEQ_FOLDER $DOT_FILES_PLUGINS_FOLDER 

notice the inverting of the folders to rsync.... so synching ~/.logseq/plugins into the folder in chezmoi (I am using .files/plugins at chezmoi source root .. maybe instead of rsync I could so an tar.zst archive and save some space).

As to what happens right now, I have everything on chezmoi, which makes it kinda slow (well, lots of files) and in honest, i don't need those files in being managed by git really. (I have been here mentioning just the plugins folder to make it simple, but there is also the case of the logseq's chrome profile folder, since its an electron app)

does it make sense ?

twpayne commented 1 year ago

chezmoi is designed to manage files that are updated occasionally and vary a little from machine to machine, for example configuration files. Every change to a file managed by chezmoi needs to be committed to a git repository before it can be manifested on another machine.

chezmoi is not a general cross-platform synchronization mechanism for files that are regularly updated and are identical from machine to machine. Specifically, chezmoi is not a good fit for managing your logseq knowledge database or your shell history.

For your logseq history, I would encourage you to look at more appropriate tools, for example some kind of cross-platform shared folder, like Dropbox, OneDrive, or Google Drive. Of course, you can add the configuration of this tool as a chezmoi run_once_ script, so the setup of your shared logseq folder is automated.

alexjp commented 1 year ago

I have a feeling that I didn't explain my case or example very well, and really, only used logseq as an example.

Currently, its great having a "hook" for running scripts when "applying", would be great to have a hook for running scripts when "(re)adding". I mentioned logseq as I thought it could be a simple example to show the use.

Anyway, if the usecase is outside of the purpose of chezmoi then please close this issue (or should I do that?) and thank you both for your time and for chezmoi!!

twpayne commented 1 year ago

So, I think there's a way to do this. It's a bit of a hack, but it works.

tl;dr create ~/.local/share/chezmoi/run_after_hooks.sh.tmpl with the content:

{{ if has "apply" .chezmoi.args -}}
#!/bin/sh

echo apply hook
{{ end -}

This is a run_after_ script so chezmoi runs it after updating your dotfiles. It's a template which has non-empty contents if apply is one of the arguments to chezmoi. i.e., it's only run after chezmoi apply.

It's a bit fragile as it currently matches apply anywhere in chezmoi's arguments. For example, it will also run if you have a file called apply managed by chezmoi and run chezmoi diff apply. This is probably OK in the short term.

cc @felipecrs who has likely already implemented something similar

I propose to add a .chezmoi.command template variable that contains the exact chezmoi command being executed, which will make this more robust.

felipecrs commented 1 year ago

Some other way this can be optimized is to:

  1. Filter the .chezmoi.args excluding all items which starts with a dash like --options
  2. Take the first item from the resultant list

This should be reliable, and most likely doable in go-template.

I propose to add a .chezmoi.command template variable that contains the exact chezmoi command being executed, which will make this more robust.

I think this would be a really nice addition!

alexjp commented 1 year ago

I tried a test with the ~/.local/share/chezmoi/run_after_hooks.sh.tmpl and it does seems to work on apply command. But this issue was about running scripts when doing an "add" or "re-add" command. (maybe i am missing something??)

I propose to add a .chezmoi.command template variable that contains the exact chezmoi command being executed, which will make this more robust.

would be great, i guess i could then do a:

{{ if has "re-add" .chezmoi.command -}}
#!/bin/sh

echo running script on "re-add" hook
{{ end -}

thanks :)

twpayne commented 1 year ago

Ah, indeed, now I realize that anything involving scripts will not work because chezmoi only actually runs them when you run chezmoi apply.

2832 adds a hooks feature so your config file can contain:

[hooks.re-add.pre]
command = "echo"
args = ["pre-re-add-hook"]

Of course, replace command and args with whatever fits your purpose.

Note that I still recommend not using chezmoi to manage your logseq files. Your proposal to use rsync for these is likely to work much better.

alexjp commented 1 year ago

awesome!!!! this is a great solution!!! haven't tested it yet, but reading the doc on the pull request seems just what i needed :)

thank you for your patience and work!