deadc0de6 / dotdrop

Save your dotfiles once, deploy them everywhere
https://dotdrop.readthedocs.io
GNU General Public License v3.0
1.78k stars 105 forks source link

[help] multiline bash if-else as an action #344

Closed DavidePatria closed 2 years ago

DavidePatria commented 2 years ago

What I am trying to achieve I am getting creative and I would like to try to use an action linked to a fake dotfile to check if $HOME/.pyenv exists, if not clone it, if it does pull it. This is just a tentative and I might change my mind in the future, of course

What I have tried so far I have tried making the command a one line command using && and ; and it works, but it is quite inelegant and messy. It would be really nice if there was a way to keep the commands as they are without any big modifications. So far I haven't found anything in the docs so I am here asking.

Here is how it worked. In this case it also contains the clone of some plugins. I kept these to show the need for &&, but I am removed them and created separate actions for each plugins.

    pyenv:
      if [ -d "$HOME/.pyenv/" ]; then echo "\nPYENV FOLDER ALREADY EXISTS\n";
      else echo "\nPYENV FOLDER NOT PRESENT, CLONING WITH PLUGINS.\n" &&
        git clone https://github.com/pyenv/pyenv.git ~/.pyenv &&
        git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv &&
        git clone https://github.com/jawshooah/pyenv-default-packages.git $(pyenv root)/plugins/pyenv-default-packages; fi

What I would like them the action to look close to

        pyenv-inst:
            if [ -d "$HOME/.pyenv/" ]; then 
                echo "\nPYENV FOLDER ALREADY EXISTS, PULLING\n";
                git -C "$HOME/.pyenv/" pull
            else 
                echo "\nPYENV FOLDER NOT PRESENT, CLONING FROM ITS REPO.\n" &&
                git clone https://github.com/pyenv/pyenv.git ~/.pyenv;
            fi

also, given that these actions are quite some code (more than a line) is there a way to simply show the name of the actions instead of printing its corpus when executing them? thank you

deadc0de6 commented 2 years ago

Well I see two ways to solve this. TBH I'm in favor of the first one since it keeps the config file clean and allows you to have a cleaner (and easier to support) script but it's all a question of taste.

Regarding your second question (printing action names instead of its content), it is currently not possible but I could of course add an option to control this. If you need this, let me know and I'll work on it.

script file solution

Install the script as part of a dotfile (for example under ~/scripts/pyenv-init.sh) containing the entire script to pull or clone and use a fake dotfile with action to run it each time

pyenv-init.sh

#!/usr/bin/env bash
if [ -d "$HOME/.pyenv/" ]; then
  echo -e "\nPYENV FOLDER ALREADY EXISTS\n"
else
  echo -e "\nPYENV FOLDER NOT PRESENT, CLONING WITH PLUGINS.\n"
  git clone https://github.com/pyenv/pyenv.git ~/.pyenv
  git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
  git clone https://github.com/jawshooah/pyenv-default-packages.git $(pyenv root)/plugins/pyenv-default-packages
fi

config

actions:
  post:
    pyenv: ~/scripts/pyenv-init.sh
dotfiles:
  fake:
    src:
    dst:
    actions:
    - pyenv
  f_pyenv_init:
    dst: ~/scripts/pyenv-init.sh
    src: scripts/pyenv-init.sh

multi-line action

something similar to this (see yaml multi-line possibilities: https://yaml-multiline.info/):

pyenv: >-
      [ -d "$HOME/.pyenv/" ] &&
      git -C "$HOME/.pyenv/" pull ||
      (git clone https://github.com/pyenv/pyenv.git ~/.pyenv &&
       git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv &&
       git clone https://github.com/jawshooah/pyenv-default-packages.git $(pyenv root)/plugins/pyenv-default-packages)
DavidePatria commented 2 years ago

thank you for your response. So, I tried solving the issues and read the doc more extensively trying out the possible solutions that exist. i ended up modifying the script as follows

    _pyenv-inst:
      if [ -d "$HOME/.pyenv/" ]; then
        echo "pyenv folder already exists, pulling";
        git -C "$HOME/.pyenv/" pull;
      else
        echo "pyenv folder not present, cloning from its repo.";
        git clone https://github.com/pyenv/pyenv.git ~/.pyenv;
      fi

because I understood that dotdrop passed the whole action codeblock as a single line, so I researched and found that the ; makes the code formatted as a one line expression on top of being executable as a multi line statement when copied in bash. I do like though the idea of executing a script, and I'm going to take it into consideration. The thing I have realised is that I have to keep stuff out my zshrc at any cost, since it slows down significantly if I start adding ifs and stuff (I wasn't pulling in my zshrc before, just checking the existance of the folder, still slow). The reason I am using such an action (and I linked it to a fake dotfile as you said) is to keep repos updated, but I might have to find a more clever way.

Rearding actions behaviour: using silent actions is fine enough, I get

 dotdrop install --profile=opensuse-tw
     _       _      _
  __| | ___ | |_ __| |_ __ ___  _ __
 / _` |/ _ \| __/ _` | '__/ _ \| '_ |
 \__,_|\___/ \__\__,_|_|  \___/| .__/  v1.8.2
                               |_|

        -> executing silent action "_pyenv-inst"
pyenv folder already exists, pulling
Già aggiornato.

which is more pleasant to see compared to a non silent action where the lines of the scripts are all printed in one messy merged line. I feel like there is no need to add features for this, the bash script is an excellent way to cleanly do it. I still need to play around with this package and find a comfortable way to do stuff exploring the possibilities.

thank you

DavidePatria commented 2 years ago

one last thing: the solution I tried is not that cool because I just noticed that importing a dotfiile refactores config.yaml

immagine

so I think I will find a way to execute those commands as external files, maybe finding a way to not import but only keep them in the dotfiles repo

deadc0de6 commented 2 years ago

@DavidePatria please try with yaml >- or any other multi-line yaml indicators (see https://yaml-multiline.info/) since I think your lines (unless too long) won't be refactored in case of import (or any other actions which modifies the yaml file).

For example

_pyenv-inst: >-
      if [ -d "$HOME/.pyenv/" ]; then
        echo "pyenv folder already exists, pulling";
        git -C "$HOME/.pyenv/" pull;
      else
        echo "pyenv folder not present, cloning from its repo.";
        git clone https://github.com/pyenv/pyenv.git ~/.pyenv;
      fi
DavidePatria commented 2 years ago

I didn't know about yaml formatting, thank you for pointing me to the docs. I found the scripts solution to be quite effective, since that pwd when launching the dotdrop command is always the main folder, therefore I don't even need to play around with paths.