From d8ee1bd9df072b6294b2d03982612d3bb839d58b Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Sat, 12 Sep 2020 14:18:53 +0200 Subject: [PATCH] adding mkdocs --- docs/config/config-variables.md | 126 +++++ docs/config/config.md | 581 +++++++++++++++++++++ docs/config/ignore-pattern.md | 64 +++ docs/config/usage-actions.md | 165 ++++++ docs/config/usage-transformations.md | 58 ++ docs/howto/append.md | 31 ++ docs/howto/create-special-files.md | 54 ++ docs/howto/global-config-files.md | 26 + docs/howto/index.md | 1 + docs/howto/merge-files-when-installing.md | 69 +++ docs/howto/sensitive-dotfiles.md | 71 +++ docs/howto/sharing-content.md | 216 ++++++++ docs/howto/special-chars.md | 46 ++ docs/howto/store-compressed-directories.md | 36 ++ docs/howto/symlinked-dotfiles.md | 102 ++++ docs/index.md | 35 ++ docs/installation.md | 172 ++++++ docs/meta/dependencies.md | 8 + docs/meta/people-using-dotdrop.md | 12 + docs/misc/migrate-from-submodule.md | 70 +++ docs/template/templating.md | 242 +++++++++ docs/usage.md | 304 +++++++++++ mkdocs.yml | 18 + 23 files changed, 2507 insertions(+) create mode 100644 docs/config/config-variables.md create mode 100644 docs/config/config.md create mode 100644 docs/config/ignore-pattern.md create mode 100644 docs/config/usage-actions.md create mode 100644 docs/config/usage-transformations.md create mode 100644 docs/howto/append.md create mode 100644 docs/howto/create-special-files.md create mode 100644 docs/howto/global-config-files.md create mode 100644 docs/howto/index.md create mode 100644 docs/howto/merge-files-when-installing.md create mode 100644 docs/howto/sensitive-dotfiles.md create mode 100644 docs/howto/sharing-content.md create mode 100644 docs/howto/special-chars.md create mode 100644 docs/howto/store-compressed-directories.md create mode 100644 docs/howto/symlinked-dotfiles.md create mode 100644 docs/index.md create mode 100644 docs/installation.md create mode 100644 docs/meta/dependencies.md create mode 100644 docs/meta/people-using-dotdrop.md create mode 100644 docs/misc/migrate-from-submodule.md create mode 100644 docs/template/templating.md create mode 100644 docs/usage.md create mode 100644 mkdocs.yml diff --git a/docs/config/config-variables.md b/docs/config/config-variables.md new file mode 100644 index 0000000..12a1627 --- /dev/null +++ b/docs/config/config-variables.md @@ -0,0 +1,126 @@ +# Config variables + +* [Config available variables](available-variables) + * [Variables entry](#variables-entry) + * [Profile variables](#profile-variables) + * [Config variables in templates](#config-variables-in-templates) + * [Interpreted variables entry](#interpreted-variables-entry) + +--- + +# Config available variables + +Multiple variables can be used within the config file to +parametrize following elements of the config: + +* dotfiles `src` and `dst` paths (see [Dynamic dotfile paths](config#dynamic-dotfile-paths)) +* external path specifications + * `import_variables` + * `import_actions` + * `import_configs` + * profiles's `import` + +`actions` and `transformations` also support the use of variables +but those are resolved when the action/transformation is executed +(see [Dynamic actions](config#dynamic-actions), +[Dynamic transformations](config#dynamic-transformations) and [Templating](templating)). + +Following variables are available in the config files: + +* [variables defined in the config](#variables-entry) +* [interpreted variables defined in the config](#interpreted-variables-entry) +* [profile variables defined in the config](#profile-variables) +* environment variables: `{{@@ env['MY_VAR'] @@}}` +* dotdrop header: `{{@@ header() @@}}` (see [Dotdrop header](templating#dotdrop-header)) + +As well as all template methods (see [Available methods](templating#available-methods)) + +# Variables entry + +Variables defined in the `variables` entry are made available within the config file. + +Config variables are recursively evaluated what means that +a config like the below +```yaml +variables: + var1: "var1" + var2: "{{@@ var1 @@}} var2" + var3: "{{@@ var2 @@}} var3" + var4: "{{@@ dvar4 @@}}" +dynvariables: + dvar1: "echo dvar1" + dvar2: "{{@@ dvar1 @@}} dvar2" + dvar3: "{{@@ dvar2 @@}} dvar3" + dvar4: "echo {{@@ var3 @@}}" +``` + +will result in the following available variables: +* var1: `var1` +* var2: `var1 var2` +* var3: `var1 var2 var3` +* var4: `echo var1 var2 var3` +* dvar1: `dvar1` +* dvar2: `dvar1 dvar2` +* dvar3: `dvar1 dvar2 dvar3` +* dvar4: `var1 var2 var3` + +# Profile variables + +Profile variables will take precedence over globally defined variables. +This means that you could do something like this: +```yaml +variables: + git_email: home@email.com +dotfiles: + f_gitconfig: + dst: ~/.gitconfig + src: gitconfig +profiles: + work: + dotfiles: + - f_gitconfig + variables: + git_email: work@email.com + private: + dotfiles: + - f_gitconfig +``` + +# Config variables in templates + +`variables` and `dynvariables` are also made available in templates +(see [Template variables](templating#template-variables)). + +Variables in the config file +```yaml +variables: + var1: some variable content + var2: some other content +``` + +Can be used in any templates like this +``` +var1 value is: {{@@ var1 @@}} +``` + +# Interpreted variables entry + +It is also possible to have *dynamic* variables in the sense that their +content will be interpreted by the shell before being substituted. + +These need to be defined in the config file under the entry `dynvariables`. + +For example: +```yaml +dynvariables: + dvar1: head -1 /proc/meminfo + dvar2: "echo 'this is some test' | rev | tr ' ' ','" + dvar3: /tmp/my_shell_script.sh + user: "echo $USER" + config_file: test -f "{{@@ user_config @@}}" && echo "{{@@ user_config @@}}" || echo "{{@@ dfl_config @@}}" +variables: + user_config: "profile_{{@@ user @@}}_uid.yaml" + dfl_config: "profile_default.yaml" +``` + +They have the same properties as [Variables](#variables-entry). \ No newline at end of file diff --git a/docs/config/config.md b/docs/config/config.md new file mode 100644 index 0000000..8aa0617 --- /dev/null +++ b/docs/config/config.md @@ -0,0 +1,581 @@ +# Config + +The config file used by dotdrop is +[config.yaml](https://github.com/deadc0de6/dotdrop/blob/master/config.yaml). + +* [Location](#location) +* [Format](#format) + * [Actions](#actions) + * [Transformations](#transformations) + * [Variables](#variables) + * [Interpreted variables](#interpreted-variables) +* Config details on + * [Symlinking dotfiles](#symlinking-dotfiles) + * [All dotfiles for a profile](#all-dotfiles-for-a-profile) + * [Include dotfiles from another profile](#include-dotfiles-from-another-profile) + * [Import profile dotfiles from file](#import-profile-dotfiles-from-file) + * [Import variables from file](#import-variables-from-file) + * [Import actions from file](#import-actions-from-file) + * [Import config files](#import-config-files) +* Dynamic elements + * [Dynamic dotfile paths](#dynamic-dotfile-paths) + * [Dynamic actions](#dynamic-actions) + * [Dynamic transformations](#dynamic-transformations) + +--- + +# Location + +Unless specified dotdrop will look in following places for the config file (`config.yaml`) +and use the first one found + +* current/working directory or the directory where [dotdrop.sh](https://github.com/deadc0de6/dotdrop/blob/master/dotdrop.sh) is located if used +* `${XDG_CONFIG_HOME}/dotdrop/` +* `~/.config/dotdrop/` +* `/etc/xdg/dotdrop/` +* `/etc/dotdrop/` + +You can force dotdrop to use a different file either by using the `-c --cfg` cli switch +or by defining the `DOTDROP_CONFIG` environment variable. + +# Format + +Dotdrop config file uses [yaml](https://yaml.org/) syntax. + +Content Format: + +* **config** entry (mandatory): contains settings for the deployment + * `backup`: create a backup of the dotfile in case it differs from the + one that will be installed by dotdrop (default *true*) + * `banner`: display the banner (default *true*) + * `cmpignore`: list of patterns to ignore when comparing, apply to all dotfiles + (enclose in quotes when using wildcards, see [ignore patterns](ignore-pattern)) + * `create`: create directory hierarchy when installing dotfiles if + it doesn't exist (default *true*) + * `default_actions`: list of action's keys to execute for all installed dotfile + (see [Use actions](usage-actions)) + * `diff_command`: the diff command to use for diffing files (default `diff -r -u {0} {1}`) + * `dotpath`: path to the directory containing the dotfiles to be managed (default `dotfiles`) + by dotdrop (absolute path or relative to the config file location) + * `filter_file`: list of paths to load templating filters from + (see [Templating available filters](templating#available-filters)) + * `func_file`: list of paths to load templating functions from + (see [Templating available methods](templating#available-methods)) + * `ignoreempty`: do not deploy template if empty (default *false*) + * `import_actions`: list of paths to load actions from + (absolute path or relative to the config file location, + see [Import actions from file](#import-actions-from-file)) + * `import_configs`: list of config file paths to be imported in + the current config (absolute path or relative to the current config file location, + see [Import config files](#import-config-files)) + * `import_variables`: list of paths to load variables from + (absolute path or relative to the config file location, + see [Import variables from file](#import-variables-from-file)) + * `instignore`: list of patterns to ignore when installing, apply to all dotfiles + (enclose in quotes when using wildcards, see [ignore patterns](ignore-pattern)) + * `keepdot`: preserve leading dot when importing hidden file in the `dotpath` (default *false*) + * `link_dotfile_default`: set dotfile's `link` attribute to this value when undefined. + Possible values: *nolink*, *link*, *link_children* (default: *nolink*, + see [Symlinking dotfiles](#symlinking-dotfiles)) + * `link_on_import`: set dotfile's `link` attribute to this value when importing. + Possible values: *nolink*, *link*, *link_children* (default: *nolink*, + see [Symlinking dotfiles](#symlinking-dotfiles)) + * `longkey`: use long keys for dotfiles when importing (default *false*, + see [Import dotfiles](usage#import-dotfiles)) + * `minversion`: (*for internal use, do not modify*) provides the minimal dotdrop version to use + * `showdiff`: on install show a diff before asking to overwrite (see `--showdiff`) (default *false*) + * `upignore`: list of patterns to ignore when updating, apply to all dotfiles + (enclose in quotes when using wildcards, see [ignore patterns](ignore-pattern)) + * `workdir`: path to the directory where templates are installed before being symlinked + when using `link:link` or `link:link_children` + (absolute path or relative to the config file location, defaults to *~/.config/dotdrop*) + * DEPRECATED `link_by_default`: when importing a dotfile set `link` to that value per default (default *false*) + +* **dotfiles** entry (mandatory): a list of dotfiles + * `dst`: where this dotfile needs to be deployed + (dotfile with empty `dst` are ignored and considered installed, + can use `variables` and `dynvariables`, make sure to quote) + * `src`: dotfile path within the `dotpath` + (dotfile with empty `src` are ignored and considered installed, + can use `variables` and `dynvariables`, make sure to quote) + * `link`: define how this dotfile is installed. + Possible values: *nolink*, *link*, *link_children* (default: `link_dotfile_default`, + see [Symlinking dotfiles](#symlinking-dotfiles)) + * `actions`: list of action keys that need to be defined in the **actions** entry below + (see [Use actions](usage-actions)) + * `cmpignore`: list of patterns to ignore when comparing (enclose in quotes when using wildcards, + see [ignore patterns](ignore-pattern)) + * `ignoreempty`: if true empty template will not be deployed (defaults to the value of `ignoreempty` above) + * `instignore`: list of patterns to ignore when installing (enclose in quotes when using wildcards, + see [ignore patterns](ignore-pattern)) + * `trans_read`: transformation key to apply when installing this dotfile + (must be defined in the **trans_read** entry below, see [Use transformations](usage-transformations)) + * `trans_write`: transformation key to apply when updating this dotfile + (must be defined in the **trans_write** entry below, see [Use transformations](usage-transformations)) + * `upignore`: list of patterns to ignore when updating (enclose in quotes when using wildcards, + see [ignore patterns](ignore-pattern)) + * DEPRECATED `link_children`: replaced by `link: link_children` + * DEPRECATED `trans`: replaced by `trans_read` + +```yaml + : + dst: + src: + ## Optional + link: (nolink|link|link_children) + ignoreempty: (true|false) + cmpignore: + - "" + upignore: + - "" + instignore: + - "" + actions: + - + trans_read: + trans_write: +``` + +* **profiles** entry (mandatory): a list of profiles with the different dotfiles that + need to be managed + * `dotfiles`: the dotfiles associated to this profile + * `import`: list of paths containing dotfiles keys for this profile + (absolute path or relative to the config file location, + see [Import profile dotfiles from file](#import-profile-dotfiles-from-file)). + * `include`: include all elements (dotfiles, actions, (dyn)variables, etc) from another profile + (see [Include dotfiles from another profile](#include-dotfiles-from-another-profile)) + * `variables`: profile specific variables + (see [Variables](#variables)) + * `dynvariables`: profile specific interpreted variables + (see [Interpreted variables](#interpreted-variables)) + * `actions`: list of action keys that need to be defined in the **actions** entry below + (see [Use actions](usage-actions)) + +```yaml + : + dotfiles: + - + - + - ... + ## Optional + include: + - + - ... + variables: + : + dynvariables: + : + actions: + - + - ... + import: + - + - ... +``` + +* **actions** entry (optional): a list of actions (see [Use actions](usage-actions)) + +```yaml +actions: + : +``` + +* **trans_read** entry (optional): a list of transformations (see [Use transformations](usage-transformations)) + +```yaml +trans_read: + : +``` + +* **trans_write** entry (optional): a list of write transformations (see [Use transformations](usage-transformations)) + +```yaml +trans_write: + : +``` + +* **variables** entry (optional): a list of variables (see [Variables](#variables)) + +```yaml +variables: + : +``` + +* **dynvariables** entry (optional): a list of interpreted variables + (see [Interpreted variables](#interpreted-variables)) + +```yaml +dynvariables: + : +``` + +# Actions + +see [Actions](usage-actions) + +# Transformations + +see [Transformations](usage-transformations) + +# Variables + +see [Variables](config-variables) + +# Interpreted variables + +see [Interpreted variables](config-variables) + +# Symlinking dotfiles + +Dotdrop is able to install dotfiles in three different ways +which are controlled by the `link` attribute of each dotfile: + +* `link: nolink`: the dotfile (file or directory) is copied to its destination +* `link: link`: the dotfile (file or directory) is symlinked to its destination +* `link: link_children`: the files/directories found under the dotfile (directory) are symlinked to their destination + +For more see [this how-to](symlinked-dotfiles) + +# All dotfiles for a profile + +To use all defined dotfiles for a profile, simply use +the keyword `ALL`. + +For example: +```yaml +dotfiles: + f_xinitrc: + dst: ~/.xinitrc + src: xinitrc + f_vimrc: + dst: ~/.vimrc + src: vimrc +profiles: + host1: + dotfiles: + - ALL + host2: + dotfiles: + - f_vimrc +``` + +# Include dotfiles from another profile + +If one profile is using the entire set of another profile, one can use +the `include` entry to avoid redundancy. + +Note that everything from the included profile is made available +(actions, variables/dynvariables, etc). + +For example: +```yaml +profiles: + host1: + dotfiles: + - f_xinitrc + include: + - host2 + host2: + dotfiles: + - f_vimrc +``` +Here profile *host1* contains all the dotfiles defined for *host2* plus `f_xinitrc`. + +For more advanced use-cases variables +([variables](config-variables) and [dynvariables](config-variables)) +can be used to specify the profile to include in a profile + +For example: +```yaml +variables: + var1: "john" +dynvariables: + d_user: "echo $USER" +profiles: + profile_john: + dotfiles: + - f_john_dotfile + profile_bill: + dotfiles: + - f_bill_dotfile + p1: + include: + - "profile_{{@@ d_user @@}}" + p2: + include: + - "profile_{{@@ var1 @@}}" +``` + +# Import profile dotfiles from file + +Profile's dotfiles list can be loaded from external files +by specifying their paths in the config entry `import` under the specific profile. + +The paths can be absolute or relative to the config file location. + +`config.yaml` +```yaml +dotfiles: + f_abc: + dst: ~/.abc + src: abc + f_def: + dst: ~/.def + src: def + f_xyz: + dst: ~/.xyz + src: xyz +profiles: + p1: + dotfiles: + - f_abc + import: + - somedotfiles.yaml +``` + +`somedotfiles.yaml` +``` +dotfiles: + - f_def + - f_xyz +``` + +Variables can be used in `import` and would allow to do something like +```yaml +import: +- profiles.d/{{@@ profile @@}}.yaml +``` + +# Import variables from file + +It is possible to load variables/dynvariables from external files by providing their +paths in the config entry `import_variables`. + +The paths can be absolute or relative to the config file location. + +`config.yaml` +```yaml +config: + backup: true + create: true + dotpath: dotfiles + import_variables: + - variables.d/myvars.yaml +``` + +`variables.d/myvars.yaml` +```yaml +variables: + var1: "extvar1" +dynvariables: + dvar1: "echo extdvar1" +``` + +Dotdrop will fail if an imported path points to a non-existing file. +It is possible to make non-existing paths not fatal by appending the path with `:optional` +```yaml +import_variables: +- variables.d/myvars.yaml:optional +``` + +# Import actions from file + +It is possible to load actions from external files by providing their +paths in the config entry `import_actions`. + +The paths can be absolute or relative to the config file location. + +`config.yaml` +```yaml +config: + backup: true + create: true + dotpath: dotfiles + import_actions: + - actions.d/myactions.yaml +dotfiles: + f_abc: + dst: ~/.abc + src: abc + actions: + - dateme +``` + +`actions.d/myactions.yaml` +```yaml +actions: + dateme: date > /tmp/timestamp +``` + +External variables will take precedence over variables defined within +the source config file. + +Dotdrop will fail if an imported path points to a non-existing file. +It is possible to make non-existing paths not fatal by appending the path with `:optional` +```yaml +import_actions: +- actions.d/myactions.yaml:optional +``` + +# Import config files + +Entire config files can be imported. This means making the following available +from the imported config file in the original config file: + +- dotfiles +- profiles +- actions +- read/write transformations +- variables/dynvariables + +Paths to import can be absolute or relative to the importing config file +location. + +`config.yaml` +```yaml +config: + backup: true + create: true + dotpath: dotfiles + import_configs: + - other-config.yaml +dotfiles: + f_abc: + dst: ~/.abc + src: abc + actions: + - show +profiles: + my-host: + dotfiles: + - f_abc + - f_def + my-haskell: + include: + - other-host +``` + +`other-config.yaml` +```yaml +config: + backup: true + create: true + dotpath: dotfiles-other + import_actions: + - actions.yaml +dotfiles: + f_def: + dst: ~/.def + src: def + f_ghci: + dst: ~/.ghci + src: ghci +profiles: + other-host: + dotfiles: + - f_gchi +``` + +`actions.yaml` +```yaml +actions: + post: + show: less +``` + +In this example `config.yaml` imports `other-config.yaml`. The dotfile `f_def` +used in the profile `my-host` is defined in `other-config.yaml`, and so is the +profile `other-host` included from `my-haskell`. The action `show` is defined +in `actions.yaml`, which is in turn imported by `other-config.yaml`. + +Dotdrop will fail if an imported path points to a non-existing file. +It is possible to make non-existing paths not fatal by appending the path with `:optional` +```yaml +import_configs: +- other-config.yaml:optional +``` + +# Dynamic dotfile paths + +Dotfile source (`src`) and destination (`dst`) can be dynamically constructed using +defined variables ([variables and dynvariables](config-variables)). + +For example to have a dotfile deployed on the unique firefox profile where the +profile path is dynamically found using a shell oneliner stored in a dynvariable: +```yaml +dynvariables: + mozpath: find ~/.mozilla/firefox -name '*.default' +dotfiles: + f_somefile: + dst: "{{@@ mozpath @@}}/somefile" + src: firefox/somefile +profiles: + home: + dotfiles: + - f_somefile +``` + +Make sure to quote the path in the config file. + +# Dynamic actions + +Variables ([config variables and dynvariables](config-variables) +and [template variables](templating#template-variables)) can be used +in actions for more advanced use-cases. + +```yaml +dotfiles: + f_test: + dst: ~/.test + src: test + actions: + - cookie_mv_somewhere "/tmp/moved-cookie" +variables: + cookie_dir_available: (test -d /tmp/cookiedir || mkdir -p /tmp/cookiedir) + cookie_header: "{{@@ cookie_dir_available @@}} && echo 'header' > /tmp/cookiedir/cookie" + cookie_mv: "{{@@ cookie_header @@}} && mv /tmp/cookiedir/cookie" +actions: + cookie_mv_somewhere: "{{@@ cookie_mv @@}} {0}" +``` + +or even something like this: +```yaml +actions: + log: "echo {0} >> {1}" +config: + default_actions: + - preaction '{{@@ _dotfile_key @@}} installed' "/tmp/log" +... +``` + +Make sure to quote the actions using variables. + +# Dynamic transformations + +As for [dynamic actions](#dynamic-actions), transformations support +the use of variables ([variables and dynvariables](config-variables) +and [template variables](templating#template-variables)). + +A very dumb example: +```yaml +trans_read: + r_echo_abs_src: echo "{0}: {{@@ _dotfile_abs_src @@}}" > {1} + r_echo_var: echo "{0}: {{@@ r_var @@}}" > {1} +trans_write: + w_echo_key: echo "{0}: {{@@ _dotfile_key @@}}" > {1} + w_echo_var: echo "{0}: {{@@ w_var @@}}" > {1} +variables: + r_var: readvar + w_var: writevar +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc + trans_read: r_echo_abs_src + trans_write: w_echo_key + f_def: + dst: ${tmpd}/def + src: def + trans_read: r_echo_var + trans_write: w_echo_var +``` \ No newline at end of file diff --git a/docs/config/ignore-pattern.md b/docs/config/ignore-pattern.md new file mode 100644 index 0000000..788dd26 --- /dev/null +++ b/docs/config/ignore-pattern.md @@ -0,0 +1,64 @@ +* [ignore patterns](#ignore-patterns) +* [examples](#examples) + +--- + +# ignore patterns + +It is possible to ignore specific patterns when using dotdrop. For example for `compare` when temporary +files don't need to appear in the output. + +* for [install](usage#install-dotfiles) + * using `instignore` in [the config file](config) +* for [compare](usage#compare-dotfiles) + * using `cmpignore` in [the config file](config) + * using the command line switch `-i --ignore` +* for [update](usage#update-dotfiles) + * using `upignore` in [the config file](config) + * using the command line switch `-i --ignore` + +The ignore pattern must follow Unix shell-style wildcards like for example `*/path/to/file`. +Make sure to quote those when using wildcards in the config file. + +Patterns used on a specific dotfile can be specified relative to the dotfile destination (`dst`). + +```yaml +config: + cmpignore: + - '*/README.md' + upignore: + - '*/README.md' + instignore: + - '*/README.md' +... +dotfiles: + d_vim + dst: ~/.vim + src: vim + upignore: + - "*/undo-dir" + - "*/plugged" +... +``` + +# examples + +To completely ignore comparison of a specific dotfile: +```yaml +dotfiles: + d_vim + dst: ~/.vim + src: vim + cmpignore: + - "*" +``` + +To ignore specific directory when updating +```yaml +dotfiles: + d_colorpicker: + src: config/some_directory + dst: ~/.config/some_directory + upignore: + - '*sub_directory_to_ignore' +``` \ No newline at end of file diff --git a/docs/config/usage-actions.md b/docs/config/usage-actions.md new file mode 100644 index 0000000..9ac129b --- /dev/null +++ b/docs/config/usage-actions.md @@ -0,0 +1,165 @@ +* [Dotfile actions](#dotfile-actions) +* [Default actions](#default-actions) +* [Profile actions](#profile-actions) +* [Fake dotfile and actions](#fake-dotfile-and-actions) + +--- + +**Note**: any action with a key starting with an underscore (`_`) won't be shown in output. +This can be useful when working with sensitive data containing passwords for example. + +# Dotfile actions + +It is sometimes useful to execute some kind of action +when deploying a dotfile. + +Note that dotfile actions are only +executed when the dotfile is installed. + +For example let's consider +[Vundle](https://github.com/VundleVim/Vundle.vim) is used +to manage vim's plugins, the following action could +be set to update and install the plugins when `vimrc` is +deployed: + +```yaml +actions: + vundle: vim +VundleClean! +VundleInstall +VundleInstall! +qall +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + f_vimrc: + dst: ~/.vimrc + src: vimrc + actions: + - vundle +profiles: + home: + dotfiles: + - f_vimrc +``` + +Thus when `f_vimrc` is installed, the command +`vim +VundleClean! +VundleInstall +VundleInstall! +qall` will +be executed. + +Sometimes, you may even want to execute some action prior to deploying a dotfile. +Let's take another example with +[vim-plug](https://github.com/junegunn/vim-plug): + +```yaml +actions: + pre: + vim-plug-install: test -e ~/.vim/autoload/plug.vim || (mkdir -p ~/.vim/autoload; curl + -fLo ~/.vim/autoload/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim) + vim-plug: vim +PlugInstall +qall +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + f_vimrc: + dst: ~/.vimrc + src: vimrc + actions: + - vim-plug-install + - vim-plug +profiles: + home: + dotfiles: + - f_vimrc +``` + +This way, we make sure [vim-plug](https://github.com/junegunn/vim-plug) +is installed prior to deploying the `~/.vimrc` dotfile. + +You can also define `post` actions like this: + +```yaml +actions: + post: + some-action: echo "Hello, World!" >/tmp/log +``` + +If you don't specify neither `post` nor `pre`, the action will be executed +after the dotfile deployment (which is equivalent to `post`). +Actions cannot obviously be named `pre` or `post`. + +Actions can even be parameterized. For example: +```yaml +actions: + echoaction: echo '{0}' > {1} +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + f_vimrc: + dst: ~/.vimrc + src: vimrc + actions: + - echoaction "vim installed" /tmp/mydotdrop.log + f_xinitrc: + dst: ~/.xinitrc + src: xinitrc + actions: + - echoaction "xinitrc installed" /tmp/myotherlog.log +profiles: + home: + dotfiles: + - f_vimrc + - f_xinitrc +``` + +The above will execute `echo 'vim installed' > /tmp/mydotdrop.log` when +vimrc is installed and `echo 'xinitrc installed' > /tmp/myotherlog.log'` +when xinitrc is installed. + +# Default actions + +Dotdrop allows to execute an action for any dotfile installation. These actions work as any other action (*pre* or *post*). + +For example, the below action will log each dotfile installation to a file. + +```yaml +actions: + post: + loginstall: "echo {{@@ _dotfile_abs_src @@}} installed to {{@@ _dotfile_abs_dst @@}} >> {0}" +config: + backup: true + create: true + dotpath: dotfiles + default_actions: + - loginstall "/tmp/dotdrop-installation.log" +dotfiles: + f_vimrc: + dst: ~/.vimrc + src: vimrc +profiles: + hostname: + dotfiles: + - f_vimrc +``` + +# Profile actions + +Profile can be either `pre` or `post` actions. Those are executed before +any dotfile installation (for `pre`) and after all dotfiles installation (for `post`) +only if at least one dotfile has been installed. + +# Fake dotfile and actions + +*Fake* dotfile can be created by specifying no `dst` and no `src` (see [config format](https://github.com/deadc0de6/dotdrop/wiki/config#format)). By binding an action to such a *fake* dotfile, you make sure the action is always executed since *fake* dotfile are always considered installed. + +```yaml +actions: + always_action: 'date > ~/.dotdrop.log' +dotfiles: + fake: + src: + dst: + actions: + - always_action +``` diff --git a/docs/config/usage-transformations.md b/docs/config/usage-transformations.md new file mode 100644 index 0000000..f2ce828 --- /dev/null +++ b/docs/config/usage-transformations.md @@ -0,0 +1,58 @@ +* [Use transformations](#use-transformations) +* [Arguments and templating](#arguments-and-templating) +* [Examples](#examples) + +--- + +**Note**: any transformation with a key starting with an underscore (`_`) won't be shown in output. +This can be useful when working with sensitive data containing passwords for example. + +# Use transformations + +There are two types of transformations available: + +* **read transformations**: used to transform dotfiles before they are installed ([Config](config) key `trans_read`) + * Used for commands `install` and `compare` + * They have two arguments: + * **{0}** will be replaced with the dotfile to process + * **{1}** will be replaced with a temporary file to store the result of the transformation + * Happens **before** the dotfile is templated with jinja2 (see [templating](templating)) + +* **write transformations**: used to transform files before updating a dotfile ([Config](config) key `trans_write`) + * Used for command `update` + * They have two arguments: + * **{0}** will be replaced with the file path to update the dotfile with + * **{1}** will be replaced with a temporary file to store the result of the transformation + +A typical use-case for transformations is when dotfiles need to be +stored encrypted or compressed. For more see below [examples](#examples). + +Note that transformations cannot be used if the dotfiles is to be linked (when `link: link` or `link: link_children`). + +# Arguments and templating + +Transformations also support additional positional arguments that must start from 2 (since `{0}` and `{1}` are added automatically). The transformations itself as well as its arguments can also be templated. + +For example +```yaml +trans_read: + targ: echo "$(basename {0}); {{@@ _dotfile_key @@}}; {2}; {3}" > {1} +dotfiles: + f_abc: + dst: /tmp/abc + src: abc + trans_read: targ "{{@@ profile @@}}" lastarg +profiles: + p1: + dotfiles: + - f_abc +``` + +will result in `abc; f_abc; p1; lastarg` + +# Examples + +See + +* [Store compressed directories](store-compressed-directories) +* [Sensitive dotfiles](sensitive-dotfiles) diff --git a/docs/howto/append.md b/docs/howto/append.md new file mode 100644 index 0000000..11c3331 --- /dev/null +++ b/docs/howto/append.md @@ -0,0 +1,31 @@ +Sometimes it might be useful to be able to append some text to a +file. Dotdrop is able to do that with the help of +[actions](https://github.com/deadc0de6/dotdrop/wiki/usage-actions) +and a temporary file. + +Below is a config example to append to a file: +```yaml +dynvariables: + tmpfile: mktemp +variables: + somefile_final: ~/.somefile +dotfiles: + f_somefile: + dst: "{{@@ tmpfile @@}}" + src: somefile + actions: + - strip "{{@@ somefile_final @@}}" + - append "{{@@ tmpfile @@}}" "{{@@ somefile_final @@}}" +actions: + pre: + strip: "sed -i '/^# my pattern$/,$d' {0}" + post: + append: "cat {0} >> {1}; rm -f {0}" +``` +During installation, the `strip` action is executed before the installation and strips everything from the pattern `# my pattern` to the end of the file. Then the dotfile `somefile` is installed in a temporary location (here `tmpfile`) and finally the post action `append` will append the content of the `tmpfile` to the final dotfile pointed by `somefile_final` + +Obviously the dotfile in the dotpath should start with a unique pattern (here `# my pattern`): +``` +# my pattern +this is the end +``` \ No newline at end of file diff --git a/docs/howto/create-special-files.md b/docs/howto/create-special-files.md new file mode 100644 index 0000000..bd4d890 --- /dev/null +++ b/docs/howto/create-special-files.md @@ -0,0 +1,54 @@ +One way for creating symlinks (or any other special files) is to use a combination of +[actions](usage-actions) and a *fake* dotfile. + +Let's say for example you have a list of directories you want to link +from under `~/.original` to `~/symlinks`. +```bash +$ tree ~/.original +/home/user/.original +├── dir1 +├── dir2 +└── dir3 +``` + +First you would store these directories names in a text file in your `/links.txt` +``` +dir1 +dir2 +dir3 +``` + +The config file would contain different elements +* a `dynvariables` that will read the above text file +* a few `variables` for the source and destination +* an action that will create the destination directory and symlink those directories +* a *fake* dotfile (with no `src` and no `dst` values) that will be always installed with the above action + +```yaml +dynvariables: + links_list: "cat {{@@ _dotdrop_dotpath @@}}/links.txt | xargs" +... +variables: + links_dst: "{{@@ env['HOME'] @@}}/.symlinks" + links_src: "{{@@ env['HOME'] @@}}/.original" +... +actions: + symlink_them: 'mkdir -p "{1}" && for lnk in {0}; do ln -s "{{@@ links_src @@}}/$lnk" "{1}/$lnk"; done' +... + fake: + src: + dst: + actions: + - symlink_them '{{@@ links_list @@}}' '{{@@ links_dst @@}}' +``` + +The result would be +```bash +$ tree ~/.symlinks +/home/user/.symlinks +├── dir1 -> /home/user/.original/dir1 +├── dir2 -> /home/user/.original/dir2 +└── dir3 -> /home/user/.original/dir3 +``` + +For reference, see [issue 243](https://github.com/deadc0de6/dotdrop/issues/243) \ No newline at end of file diff --git a/docs/howto/global-config-files.md b/docs/howto/global-config-files.md new file mode 100644 index 0000000..7cf4e0f --- /dev/null +++ b/docs/howto/global-config-files.md @@ -0,0 +1,26 @@ +# How to manage system wide config files with dotdrop + +Dotdrop doesn't allow to handle file rights and permissions (at least not directly). Every operations (`mkdir`, `cp`, `mv`, `ln`, file creation) are executed with the rights of the user calling dotdrop. The rights of the stored dotfile are mirrored on the deployed dotfile (`chmod` like). It works well for local/user dotfiles but doesn't allow to manage global/system config files (`/etc` or `/var` for example) directly. + +Using dotdrop with `sudo` to handle local **and** global dotfiles in the same *session* is a bad idea as the resulting files will all have messed up owners. + +It is therefore recommended to have two different config files (and thus two different *dotpath*) for handling these two uses cases: + +* one `config.yaml` for the local/user dotfiles (with its dedicated *dotpath*) +* another config file for the global/system dotfiles (with its dedicated *dotpath*) + +The default config file (`config.yaml`) is used when installing the user dotfiles as usual +```bash +# default config file is config.yaml +$ ./dotdrop.sh import +$ ./dotdrop.sh install +... +``` + +A different config file (for example `global-config.yaml` and its associated *dotpath*) is used when installing/managing global dotfiles and is to be used with `sudo` or directly by the root user +```bash +# specifying explicitly the config file with the --cfg switch +$ sudo ./dotdrop.sh import --cfg=global-config.yaml +$ sudo ./dotdrop.sh install --cfg=global-config.yaml +... +``` \ No newline at end of file diff --git a/docs/howto/index.md b/docs/howto/index.md new file mode 100644 index 0000000..e1a23c8 --- /dev/null +++ b/docs/howto/index.md @@ -0,0 +1 @@ +**TODO** diff --git a/docs/howto/merge-files-when-installing.md b/docs/howto/merge-files-when-installing.md new file mode 100644 index 0000000..989b8c9 --- /dev/null +++ b/docs/howto/merge-files-when-installing.md @@ -0,0 +1,69 @@ +Dotdrop allows to merge multiple files into one using the jinja2's `include` directive. + +For example let's consider you want to keep your `vimrc` split into multiple parts in dotdrop +* `/vimrc.d/top`: top part of the file +* `/vimrc.d/bottom`: bottom part of the file + +And you want dotdrop to merge all those files into `~/.vimrc` whenever you process your vimrc with dotdrop. + +First make sure `~/.vimrc` is present in your config file +```yaml +... +dotfiles: + f_vimrc: + dst: ~/.vimrc + src: vimrc +profiles: + hostname: + dotfiles: + - f_vimrc +... +``` + +Note that the subfiles (`vimrc.d/top` and `vimrc.d/bottom`) +are not known to the config and do not need to be. + +Edit the stored vimrc file to include the other files, for example: +```bash +$ cat /vimrc +{%@@ include 'vimrc.d/top' @@%} +filetype on +set t_Co=256 +set tw=0 +set tabstop=2 +set shiftwidth=2 +set expandtab +set nocompatible +set nomodeline +syntax on +{%@@ include 'vimrc.d/bottom' @@%} +``` + +The `include` path parameter needs to be relative to your `dotpath`. + +Dotdrop will then automagically include the files into your vimrc when handling `f_vimrc`. + +# Merge all files in a directory + +To include all files in a directory, a combination of +[dynvariables](config-variables#interpreted-variables) +and [jinja2 directives](http://jinja.pocoo.org/docs/2.10/) have to be used. + +Let's say all files in `/toinclude` need to be included into a dotfile. + +First define a [dynvariables](config-variables#interpreted-variables) +in the config file which will look for files to include in the above directory: +```yaml +dynvariables: + allfiles: "cd {{@@ _dotdrop_dotpath @@}}; find toinclude/ -type f | xargs" +``` + +Note that `_dotdrop_dotpath` is part of the built-in variables +(for more see [template variables](templating#template-variables)). + +And then use the generated list in the dotfile template: +``` +{%@@ for f in allfiles.split() @@%} + {%@@ include f @@%} +{%@@ endfor @@%} +``` diff --git a/docs/howto/sensitive-dotfiles.md b/docs/howto/sensitive-dotfiles.md new file mode 100644 index 0000000..ada2a62 --- /dev/null +++ b/docs/howto/sensitive-dotfiles.md @@ -0,0 +1,71 @@ +# Sensitive dotfiles + +* [Available solutions](#available-solutions) +* [Store encrypted dotfiles](#store-encrypted-dotfiles) +* [Load passphrase from file](#load-passphrase-from-file) + +--- + +# Available solutions + +Two solutions exist, the first one using an unversioned file (see [Environment variables](templating#environment-variables)) +and the second using transformations (see [Store encrypted dotfiles](#store-encrypted-dotfiles)). + +# Store encrypted dotfiles + +Here's an example of part of a config file to use gpg encrypted dotfiles: +```yaml +dotfiles: + f_secret: + dst: ~/.secret + src: secret + trans_read: _gpg +trans_read: + _gpg: gpg2 -q --for-your-eyes-only --no-tty -d {0} > {1} +``` + +The above config allows to store the dotfile `~/.secret` encrypted in the *dotpath* +directory and uses gpg to decrypt it when `install` is run. + +Here's how to deploy above solution: + +* import the clear dotfile (what creates the correct entries in the config file) + +```bash +$ dotdrop import ~/.secret +``` + +* encrypt the original dotfile + +```bash +$ ~/.secret +``` + +* overwrite the dotfile with the encrypted version + +```bash +$ cp dotfiles/secret +``` + +* edit the config file and add the transformation to the dotfile + (as shown in the example above) + +* commit and push the changes + +# Load passphrase from file + +Passphrase is retrieved using a script: +```yaml +variables: + gpg_password: "./get-password.sh" +trans_read: + _gpg: "gpg2 --batch --yes --passphrase-file <({{@@ gpg_password @@}}) -q --for-your-eyes-only --no-tty -d {0} > {1}" +``` + +Passphrase is stored in a file directly +```yaml +variables: + gpg_password_file: "/tmp/the-password" +trans_read: + _gpg: "gpg2 --batch --yes --passphrase-file <(cat {{@@ gpg_password_file @@}}) -q --for-your-eyes-only --no-tty -d {0} > {1}" +``` \ No newline at end of file diff --git a/docs/howto/sharing-content.md b/docs/howto/sharing-content.md new file mode 100644 index 0000000..12e1b24 --- /dev/null +++ b/docs/howto/sharing-content.md @@ -0,0 +1,216 @@ +There are cases in which two or more dotfiles are very similar. For example, +two files exporting environment variables for two projects built with the same +technology (eg. two node.js web servers deployed on AWS). In these cases it's +nice to share as much code as possible across the dotfiles, by leveraging +templating and merging them in the same dotfile in Dotdrop's `dotpath`. Here +are a few suggestions about how to achieve this. + +* [Brute force templating](brute-force-templating) +* [Profile variables](profile-variables) +* [Jinja macros](jinja-macros) + +# Brute force templating + +The first approach is sheer use of templating and Dotdrop +[template variables](#template-variables). In order to do this, we need to: + +1. Create the merged dotfile with an arbitrary name somewhere in `dotpath`. +2. Create two `dotfile` entries in `config.yaml`, both having the merged + dotfile as `src`, but their own `dst`. + +Here we have an example: + +The merged dotfile in `dotpath` (`dotpath/projects/env`): +```bash +# .env + +{%@@ if _dotfile_key == 'server0-env' @@%} + {%@@set aws_db_host = 'super-duper.host' @@%} + {%@@set aws_db_port = 4521 @@%} +{%@@ elif _dotfile_key == 'server1-env' @@%} + {%@@set aws_db_host = 'cheaper.host' @@%} + {%@@set aws_db_host = 9632 @@%} +{%@@ endif @@%} + +export DB_HOST='{{@@ aws_db_host @@}}' +export DB_PORT='{{@@ aws_db_port @@}}' +``` + +Part of Dotdrop `config.yaml` file: +```yaml +# config.yaml + +dotfiles: + server0-env: + src: projects/env + dst: ~/projects/server0/.env + server1-env: + src: projects/env + dst: ~/projects/server1/.env +``` + +Installing the dotfile `server0-env` will create an environment file in +`~/projects/server0/.env` with the following content: + +```bash +# .env + +export DB_HOST='super-duper.host' +export DB_PORT='4521' +``` + +# Profile variables + +Albeit flexible, the previous method is a bit cumbersome for some use cases. +For example, when the dotfiles belong to different profiles, the cleanest +solution consists in using +[profile variables](config-variables#profile-variables). This is achieved by: + +1. Creating the merged dotfile with an arbitrary name somewhere in `dotpath`. +2. Adding some variables in the merged dotfile via templating. +3. Overriding them with different values in each profile via profile variables. +4. Typically, making the dotfile `dst` dynamic, as different profiles need + usually to deploy the dotfiles in different locations. + +**NOTE**: This technique does *not* require two different `dotfiles` entry in +`config.yaml`. + +An example: + +The merged dotfile (`dotpath/projects/env`) +```bash +# .env + +export DB_HOST='{{@@ aws_db_host @@}}' +export DB_PORT='{{@@ aws_db_port @@}}' +``` + +Part of Dotdrop `config.yaml` file: +```yaml +# config.yaml + +dotfiles: + env: + src: projects/env + dst: '{{@@ server_path @@}}/.env' + +profiles: + server0: + dotfiles: + - env + variables: + aws_db_host: super-duper.host + aws_db_port: 4521 + server_path: ~/projects/server0 + + server1: + dotfiles: + - env + variables: + aws_db_host: cheaper.host + aws_db_port: 9632 + server_path: ~/projects/server1 +``` + +With this setup, installing the `server1` profile will create an environment +file in `~/projects/server1/.env` with the following content: + +```bash +# .env + +export DB_HOST='cheaper.host' +export DB_PORT='9632' +``` + +# Jinja macros + +Even though it has cleaner dotfiles, the profile-variable-based procedure can't +be used in two scenarios: when the dotfiles belong to the same profile, and +when variable values require some complex computations. In both cases the brute +force templating approach can be used, but in the latter one it also makes the +dotfiles bloated with "bookkeeping" logic, thus hard to read. + +A solution for this relies in leveraging Jinja macros. This method is a +variation of the brute force templating one, where the merged dotfile is +included from many different dotfiles in `dotpath` via jinja macros, rather +than via many `dotfile` entries with the same `src` attribute. This way, the +merged original dotfiles stays clean as in the profile variables solution, +because computations are in other files. + +The steps to achieve this are: + +1. Creating the merged dotfile with an arbitrary name somewhere in `dotpath`. +2. Wrapping the whole content of the merged dotfile in a jinja macro, with the + necessary parameters. +3. Calling the macro in each original dotfiles, computing the parameters there. + +**NOTE**: The merged dotfile will be empty, as it only contains a jinja macro. + If it needs not to be deployed, the `ignoreempty` entry can be set to + `true` in `config.yaml`. + +As usual, an example: + +The merged dotfile in `dotpath` (`dotpath/projects/env`): +```bash +{%@@ macro env(db_host, db_port) @@%} +# .env + +export DB_HOST='{{@@ db_host @@}}' +export DB_PORT='{{@@ db_port @@}}' +{%@@ endmacro @@%} +``` + +Server0's environment file (`projects/server0/.env`) +```jinja2 +{%@@ from projects/env import env @@%} + +{%@@ set keyPieces = _dotfile_key.split('-') @@%} +{%@@ if keyPieces[-1] == 'dbg' @@%} + {%@@ set isLocal = keyPieces[-2] == 'local' @@%} + {%@@ set remote_host = 'super-duper-dbg.host' + if not isLocal + else 'localhost' @@%} + {%@@set aws_db_port = 3333 @@%} + +{%@@ elif keyPieces[-1] == 'dev' @@%} + {%@@set aws_db_host = 'localhost' @@%} + {%@@set aws_db_host = 4521 @@%} +{%@@ endif @@%} + +{{@@ env(db_host, db_port) @@}} +``` + +Server1's environment file (`projects/server1/.env`) +```jinja2 +{%@@ from projects/env import env @@%} + +{{@@ env('average-host.com', 9632) @@}} +``` + +Part of Dotdrop `config.yaml` file: +```yaml +# config.yaml + +dotfiles: + server0-env-remote-dbg: + src: projects/server0/.env + dst: ~/projects/server0/.env.remote.dbg + server0-env-local-dbg: + src: projects/server0/.env + dst: ~/projects/server0/.env.local.dbg + server1-env: + src: projects/server1/.env + dst: ~/projects/server1/.env + +``` + +With this configuration, installing the dotfile `server0-env-local-dbg` will +create an environment file in `~/projects/server0/.env.local.dbg` with the +following content: + +```bash +# .env + +export DB_HOST='localhost' +export DB_PORT='3333' +``` diff --git a/docs/howto/special-chars.md b/docs/howto/special-chars.md new file mode 100644 index 0000000..375ea20 --- /dev/null +++ b/docs/howto/special-chars.md @@ -0,0 +1,46 @@ +* [Detect encoding](#detect-encoding) +* [Special chars](#special-chars) +* [Re-encode](#re-encode) + +--- + +# Detect encoding + +Text file encoding can be identified using for example `file -b ` or in vim +with `:set fileencoding` + +Here's an example of encoding that will fully work with dotdrop: +```bash +$ file -b +UTF-8 Unicode text, with escape sequences +``` + +and another that will mislead the `compare` command and return false/inaccurate results: +```bash +$ file -b +ISO-8859 text, with escape sequences +``` + +# Special chars + +## CRLF + +The use of dotfiles with DOS/Windows line ending (CRLF, `\r\n`) will result in +the comparison (`compare`) returning a difference while there is none. +This is due to Jinja2 stripping CRLF. + +One solution is to use `dos2unix` to re-format the dotfiles before adding them to dotdrop. + +See https://github.com/deadc0de6/dotdrop/issues/42. + +## Non-unicode chars + +Jinja2 is not able to process non-unicode chars (http://jinja.pocoo.org/docs/2.10/api/). This means that dotfiles using non-unicode chars can still be fully managed by dotdrop however when comparing the local file with the one stored in dotdrop, `compare` will return a difference even if there is none. + +Either replace the non-unicode chars (see below [Re-encode](re-encode)) or accept the fact the comparison shows a difference while there's none. + +See https://github.com/deadc0de6/dotdrop/issues/42. + +# Re-encode + +To change an existing file's encoding, you can use `recode UTF-8 ` (see [recode](https://linux.die.net/man/1/recode)) or in vim `:set fileencoding=utf-8`. \ No newline at end of file diff --git a/docs/howto/store-compressed-directories.md b/docs/howto/store-compressed-directories.md new file mode 100644 index 0000000..f96b4ba --- /dev/null +++ b/docs/howto/store-compressed-directories.md @@ -0,0 +1,36 @@ +# Store compressed directories + +This is an example on how to use transformations (`trans_read` and `trans_write`) to store +compressed directories and deploy them with dotdrop. + +Config file: +```yaml +trans_read: + uncompress: "mkdir -p {1} && tar -xf {0} -C {1}" +trans_write: + compress: "tar -cf {1} -C {0} ." +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + d_somedir: + dst: ~/.somedir + src: somedir + trans_read: uncompress + trans_write: compress +profiles: + p1: + dotfiles: + - d_somedir +``` + +The *read* transformation `uncompress` is used to execute below command before deploying the dotfile (where `{0}` is the source and `{1}` the destination) +``` +mkdir -p {1} && tar -xf {0} -C {1} +``` + +And the *write* transformation `compress` is run when updating the dotfile directory by compressing it (where `{0}` is the source and `{1}` the destination) +``` +tar -cf {1} -C {0} . +``` \ No newline at end of file diff --git a/docs/howto/symlinked-dotfiles.md b/docs/howto/symlinked-dotfiles.md new file mode 100644 index 0000000..989e732 --- /dev/null +++ b/docs/howto/symlinked-dotfiles.md @@ -0,0 +1,102 @@ +# Symlink dotfiles + +Dotdrop offers two ways to symlink a dotfile through its +config entry `link` + +* setting `link: link` for a dotfile will symlink `dst` to `src` +* setting `link: link_children` will, for every direct children of `src`, symlink `dst/` to `src/` (see [Link children](#link-children)) + +Where `src` is considered as the file stored in your *dotpath* and +`dst` as the file located in your `$HOME`. + +Note that if the dotfile is using template directives, it will be symlinked into +`~/.config/dotdrop` instead of directly into your *dotpath* +(see [Templating symlinked dotfiles](#templating-symlinked-dotfiles)) + +* [Link children](#link-children) +* [Templating symlinked dotfiles](#templating-symlinked-dotfiles) + +--- + +# Link children + +This feature can be very useful for dotfiles when you don't want the entire +directory to be symlink but still want to keep a clean config files (with a +limited number of entries). + +*Make sure to do a backup of your dotfiles with something like `cp -r {,.bak}`* + +A good example of its use is when managing `~/.vim` with dotdrop. + +Here's what it looks like when using `link: link`. +```yaml +config: + dotpath: dotfiles +dotfiles: + vim: + dst: ~/.vim + src: vim + link: link +``` + +The top directory `~/.vim` is symlinked to the `/vim` location +```bash +$ readlink ~/.vim +~/.dotfiles/vim/ +$ ls ~/.dotfiles/vim/ +after autoload plugged plugin snippets spell swap vimrc +``` + +As a result, all files under `~/.vim` will be managed by +dotdrop (including unwanted directories like `spell`, `swap`, etc). + +A cleaner solution is to use `link_children` which allows to only symlink +files under the dotfile directory. Let's say only `after`, `plugin`, `snippets`, and `vimrc` +need to be managed in dotdrop. `~/.vim` is imported in dotdrop, cleaned off all unwanted +files/directories and then the `link` entry is set to `link_children` in the config file. +```yaml +config: + dotpath: dotfiles +dotfiles: + vim: + dst: ~/.vim/ + src: vim + link: link_children +``` + +Now all children of the `vim` dotfile's directory in the *dotpath* will be symlinked under `~/.vim/` +without affecting the rest of the local files, keeping the config file clean +and all unwanted files only on the local system. +```bash +$ readlink -f ~/.vim +~/.vim +$ tree -L 1 ~/.vim +~/.vim +├── after -> ~/.dotfiles/vim/after +├── autoload +├── plugged +├── plugin -> ~/.dotfiles/vim/plugin +├── snippets -> ~/.dotfiles/vim/snippets +├── spell +├── swap +└── vimrc -> ~/.dotfiles/vim/vimrc +``` + +# Templating symlinked dotfiles + +For dotfiles not using any templating directives, those are directly linked +to dotdrop's `dotpath` directory (see [Config](config)). + +When using templating directives however the dotfiles are first installed into +`workdir` (defaults to *~/.config/dotdrop*, see [Config](config)) +and then symlinked there. +This applies to both dotfiles with `link: link` and `link: link_children`. + +For example +```bash +# with template +/home/user/.xyz -> /home/user/.config/dotdrop/.xyz + +# without template +/home/user/.xyz -> /home/user/dotfiles/xyz +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..e3f6969 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,35 @@ +# Welcome to the dotdrop wiki! + +The idea of dotdrop is to have the ability to store each dotfile only once and deploy them with a different content on different hosts/setups. To achieve this, it uses [jinja2](http://jinja.pocoo.org/) which is a templating engine that allows to specify, during the dotfile installation with dotdrop, based on a selected profile, how (with what content) each dotfile will be installed. + +Most information on using dotdrop are described in this wiki and in the [readme](https://github.com/deadc0de6/dotdrop/blob/master/README.md). For more check + +* [a quick overview of dotdrop features](https://deadc0de.re/dotdrop/) +* [the blogpost on dotdrop](https://deadc0de.re/articles/dotfiles.html) +* [an example](https://github.com/deadc0de6/dotdrop#getting-started) +* [how people are using dotdrop](people-using-dotdrop) + +For more examples of config file, [search github](https://github.com/search?q=filename%3Aconfig.yaml+dotdrop&type=Code). + +# Wiki pages + +* Documentation + * [Installation](installation) + * [Usage](usage) + * [Config file format](config) + * [Templating](templating) +* How To + * [Use actions](usage-actions) + * [Use transformations](usage-transformations) + * [Store secrets](sensitive-dotfiles) + * [Symlink dotfiles](symlinked-dotfiles) + * [Store compressed directories](store-compressed-directories) + * [Merge files when installing](merge-files-when-installing) + * [Append to a dotfile](append) + * [Manage system/global config files](global-config-files) + * [Handle special chars](special-chars) + * [Share content across dotfiles](sharing-content) + * [Ignore patterns](ignore-pattern) + * [Create special files](create-special-files) +* [Related projects](related-projects) +* [Troubleshooting](troubleshooting) diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..3f13e5f --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,172 @@ +# Installation + +Installing dotdrop [as a submodule](#as-a-submodule) is the recommended way. + +If you want to keep your python environment clean, use the virtualenv installation instructions +(see [As a submodule in a virtualenv](#as-a-submodule-in-a-virtualenv) and +[With pypi in a virtualenv](#with-pypi-in-a-virtualenv)). +In that case, the virtualenv environment might need to be loaded before any attempt to use dotdrop. + +Installation instructions + +* Installation + * [Install as a submodule](#as-a-submodule) + * [Install as a submodule in a virtualenv](#as-a-submodule-in-a-virtualenv) + * [Install with pypi](#with-pypi) + * [Install with pypi in a virtualenv](#with-pypi-in-a-virtualenv) + * [Aur packages](#aur-packages) + * [Snap package](#snap-package) +* [Setup your repository](#setup-your-repository) +* [Shell completion](#shell-completion) +* [Dependencies](dependencies) + +# As a submodule + +The following will create a git repository for your dotfiles and +keep dotdrop as a submodule: +```bash +## create the repository +$ mkdir dotfiles; cd dotfiles +$ git init + +## install dotdrop as a submodule +$ git submodule add https://github.com/deadc0de6/dotdrop.git +$ pip3 install --user -r dotdrop/requirements.txt +$ ./dotdrop/bootstrap.sh + +## use dotdrop +$ ./dotdrop.sh --help +``` + +For MacOS users, make sure to install `realpath` through homebrew +(part of *coreutils*). + +Using this solution will need you to work with dotdrop by +using the generated script `dotdrop.sh` at the root +of your dotfiles repository. + +To ease the use of dotdrop, it is recommended to add an alias to it in your +shell with the config file path, for example +``` +alias dotdrop= --cfg=' +``` + +# As a submodule in a virtualenv + +To install in a [virtualenv](https://virtualenv.pypa.io): +```bash +## create the repository +$ mkdir dotfiles; cd dotfiles +$ git init + +## install dotdrop as a submodule +$ git submodule add https://github.com/deadc0de6/dotdrop.git +$ virtualenv -p python3 env +$ echo 'env' > .gitignore +$ source env/bin/activate +$ pip install -r dotdrop/requirements.txt +$ ./dotdrop/bootstrap.sh + +## use dotdrop +$ ./dotdrop.sh --help +``` + +When using a virtualenv, make sure to source the environment before using dotdrop +```bash +$ source env/bin/activate +$ ./dotdrop.sh --help +``` + +Then follow the instructions under [As a submodule](#as-a-submodule). + +# With pypi + +Install dotdrop +```bash +$ pip3 install --user dotdrop +``` + +and then [setup your repository](#setup-your-repository). + +# With pypi in a virtualenv + +Install dotdrop in a virtualenv from pypi +```bash +$ virtualenv -p python3 env +$ source env/bin/activate +$ pip install dotdrop +``` + +When using a virtualenv, make sure to source the environment +before using dotdrop: +```bash +$ source env/bin/activate +$ dotdrop --help +``` + +Then follow the instructions under [With pypi](#with-pypi). + +# Aur packages + +Dotdrop is available on aur: +* stable: https://aur.archlinux.org/packages/dotdrop/ +* git version: https://aur.archlinux.org/packages/dotdrop-git/ + +Then follow the [doc to setup your repository](#setup-your-repository). + +# Snap package + +Dotdrop is available as a snap package: + +Install it with +```bash +snap install dotdrop +``` + +Then follow the [doc to setup your repository](#setup-your-repository). + +# Setup your repository + +Either create a repository on your prefered platform and clone it or create one locally. +This repository will contain two main elements, dotdrop's config file (`config.yaml`) +and a directory containing all your dotfiles managed by dotdrop. +```bash +## clone your repository (my-dotfiles) +$ git clone /my-dotfiles +$ cd my-dotfiles + +## within the repository create a directory to store your dotfiles +## (refered by "dotpath" in the config, which defaults to "dotfiles") +$ mkdir dotfiles +``` + +Then add a config file. You can get a +[minimal config file](https://github.com/deadc0de6/dotdrop/blob/master/config.yaml) +from dotdrop's repository with +```bash +$ wget https://raw.githubusercontent.com/deadc0de6/dotdrop/master/config.yaml +``` +It is recommended to store your config file directly within your repository +(*my-dotfiles* in the example above) but you could save it in different places if you wish, +see [this doc](https://github.com/deadc0de6/dotdrop/wiki/config#location) for more. + +```bash +$ tree my-dotfiles +my-dotfiles +├── config.yaml +└── dotfiles +``` + +If your config file is in an exotic location, you can add an alias +in your preferred shell to call dotdrop with the config file path argument. +``` +alias dotdrop='dotdrop --cfg=' +``` + +For more info on the config file format, see [the config doc](https://github.com/deadc0de6/dotdrop/wiki/config) + +Finally start using dotdrop with `dotdrop --help`. See the [usage doc](https://github.com/deadc0de6/dotdrop/wiki/usage) and [the example](https://github.com/deadc0de6/dotdrop/blob/master/README.md#getting-started). + +# Shell completion + +Completion scripts exist for `bash`, `zsh` and `fish`, see [the related doc](completion/README.md). \ No newline at end of file diff --git a/docs/meta/dependencies.md b/docs/meta/dependencies.md new file mode 100644 index 0000000..c145306 --- /dev/null +++ b/docs/meta/dependencies.md @@ -0,0 +1,8 @@ +Beside the python dependencies defined in [requirements.txt](https://github.com/deadc0de6/dotdrop/blob/master/requirements.txt), dotdrop depends on following tools: +* `file` +* `diff` +* `mkdir` +* `git` (for the entry point script [dotdrop.sh](https://github.com/deadc0de6/dotdrop/blob/master/dotdrop.sh)) +* `readlink` or `realpath` (for the entry point script [dotdrop.sh](https://github.com/deadc0de6/dotdrop/blob/master/dotdrop.sh)) + +For MacOS users, make sure to install `realpath` (part of `coreutils`) through [homebrew](https://brew.sh/). \ No newline at end of file diff --git a/docs/meta/people-using-dotdrop.md b/docs/meta/people-using-dotdrop.md new file mode 100644 index 0000000..1cf378f --- /dev/null +++ b/docs/meta/people-using-dotdrop.md @@ -0,0 +1,12 @@ +For more examples, see how people are using dotdrop + +* [https://github.com/open-dynaMIX/dotfiles](https://github.com/open-dynaMIX/dotfiles) +* [https://github.com/moyiz/dotfiles](https://github.com/moyiz/dotfiles) +* [https://github.com/japorized/dotfiles](https://github.com/japorized/dotfiles) +* [https://gitlab.com/lyze237/dotfiles-public](https://gitlab.com/lyze237/dotfiles-public) +* [https://github.com/whitelynx/dotfiles](https://github.com/whitelynx/dotfiles) +* [https://github.com/Eluminae/dotfiles](https://github.com/Eluminae/dotfiles) +* [https://github.com/davla/dotfiles](https://github.com/davla/dotfiles) and [https://github.com/davla/setup](https://github.com/davla/setup) + +Or search directly on [github](https://github.com/search?q=filename%3Aconfig.yaml+dotdrop&type=Code) +for config examples. \ No newline at end of file diff --git a/docs/misc/migrate-from-submodule.md b/docs/misc/migrate-from-submodule.md new file mode 100644 index 0000000..382b246 --- /dev/null +++ b/docs/misc/migrate-from-submodule.md @@ -0,0 +1,70 @@ + +**WARNING** + +Only do the following if you are using dotdrop version `< 0.7.1` or if you encounter an issue when running dotdrop that redirects you here. + +--- + +Initially dotdrop was only available as a submodule directly in the +dotfiles git tree. When updated to work with pypi, some code changed +that brought some issues to older versions. + +If you want to keep it as a submodule (recommended), simply do the following +```bash +$ cd + +## get latest version of the submodule +$ git submodule foreach git pull origin master + +## and stage the changes +$ git add dotdrop +$ git commit -m 'update dotdrop' + +## update the bash script wrapper +$ ./dotdrop/bootstrap.sh + +## and stage the change to the dotdrop.sh script +$ git add dotdrop.sh +$ git commit -m 'update dotdrop.sh' + +## and finally push the changes upstream +$ git push +``` + +Otherwise, simply install it from pypi as shown below: + +* move to the dotfiles directory where dotdrop is used as a submodule +```bash +$ cd +``` +* remove the entire `submodule "dotdrop"` section in `.gitmodules` +* stage the changes +```bash +$ git add .gitmodules +``` +* remove the entire `submodule "dotdrop"` section in `.git/config` +* remove the submodule +```bash +$ git rm --cached dotdrop +``` +* remove the submodule from .git +```bash +$ rm -rf .git/modules/dotdrop +``` +* commit the changes +```bash +$ git commit -m 'removing dotdrop submodule' +``` +* remove any remaining files from the dotdrop submodule +```bash +$ rm -rf dotdrop +``` +* remove `dotdrop.sh` +```bash +$ git rm dotdrop.sh +$ git commit -m 'remove dotdrop.sh script' +``` +* push upstream +```bash +$ git push +``` \ No newline at end of file diff --git a/docs/template/templating.md b/docs/template/templating.md new file mode 100644 index 0000000..b932a6e --- /dev/null +++ b/docs/template/templating.md @@ -0,0 +1,242 @@ +# Templating + +Dotdrop leverage the power of [jinja2](http://jinja.pocoo.org/) to handle the +templating of dotfiles. See [jinja2 template doc](http://jinja.pocoo.org/docs/2.9/templates/) +or the below sections for more information on how to template your dotfiles. + +* [Delimiters](#delimiters) +* [Template variables](#template-variables) + * [Dotfile variables](#dotfile-variables) + * [Environment variables](#environment-variables) + * [Dotdrop header](#dotdrop-header) +* [Available methods](#available-methods) +* [Available filters](#available-filters) +* [Import macros](#import-macros) +* [Ignore empty template](#ignore-empty-template) +* [Include file or template in template](#include-file-or-template-in-template) +* [Debug templates](#debug-templates) + +--- + +# Delimiters + +Dotdrop uses different delimiters than +[jinja2](http://jinja.pocoo.org/)'s defaults: + +* block/statement start = `{%@@` +* block/statement end = `@@%}` +* variable/expression start = `{{@@` +* variable/expression end = `@@}}` +* comment start = `{#@@` +* comment end = `@@#}` + +More info in [jinja2 templating doc](https://jinja.palletsprojects.com/en/2.11.x/templates/?highlight=delimiter) + +# Template variables + +Following variables are available in templates: + +* `{{@@ profile @@}}` contains the profile provided to dotdrop. +* `{{@@ env['MY_VAR'] @@}}` contains environment variables (see [Environment variables](#environment-variables)). +* `{{@@ header() @@}}` contains dotdrop header (see [Dotdrop header](#dotdrop-header)). +* `{{@@ _dotdrop_dotpath @@}}` contains the [dotpath](https://github.com/deadc0de6/dotdrop/wiki/config) absolute path. +* `{{@@ _dotdrop_cfgpath @@}}` contains the absolute path to the [config file](https://github.com/deadc0de6/dotdrop/wiki/config). +* `{{@@ _dotdrop_workdir @@}}` contains the [workdir](https://github.com/deadc0de6/dotdrop/wiki/config) absolute path. +* dotfile specific variables (see [Dotfile variables](#dotfile-variables)) +* config variables (see [Variables](config-variables)). +* config interpreted variables (see [Interpreted variables](config-variables)). + +# Dotfile variables + +When a dotfile is handled by dotdrop, the following variables are added: + +* `{{@@ _dotfile_abs_src @@}}` contains the processed dotfile absolute source path. +* `{{@@ _dotfile_abs_dst @@}}` contains the processed dotfile absolute destination path. +* `{{@@ _dotfile_key @@}}` contains the processed dotfile key. +* `{{@@ _dotfile_link @@}}` contains the processed dotfile `link` string value. + +Additionally to the above, the following variables are set in each file processed by dotdrop. + +* `{{@@ _dotfile_sub_abs_src @@}}` contains the absolute source path of each file when handled by dotdrop. +* `{{@@ _dotfile_sub_abs_dst @@}}` contains the absolute destination path of each file when handled by dotdrop. + +For example a directory dotfile (like `~/.ssh`) would process several files +(`~/.ssh/config` and `~/.ssh/authorized_keys` for example). In `~/.ssh/config`: +* `_dotfile_abs_dst` would be `/home/user/.ssh` +* `_dotfile_sub_abs_dst` would be `/home/user/.ssh/config` + +# Environment variables + +It's possible to access environment variables inside the templates. +``` +{{@@ env['MY_VAR'] @@}} +``` + +This allows for storing host-specific properties and/or secrets in environment variables. +It is recommended to use `variables` (see [Config variables](#config-variables)) +instead of environment variables unless these contain sensitive information that +shouldn't be versioned in git. + +For example you can have a `.env` file in the directory where your `config.yaml` lies: +``` +## Some secrets +pass="verysecurepassword" +``` +If this file contains secrets that should not be tracked by git, +put it in your `.gitignore`. + +You can then invoke dotdrop with the help of an alias +```bash +# when dotdrop is installed as a submodule +alias dotdrop='eval $(grep -v "^#" ~/dotfiles/.env) ~/dotfiles/dotdrop.sh' + +# when dotdrop is installed from pypi or aur +alias dotdrop='eval $(grep -v "^#" ~/dotfiles/.env) /usr/bin/dotdrop --cfg=~/dotfiles/config.yaml' +``` + +The above aliases load all the variables from `~/dotfiles/.env` +(while omitting lines starting with `#`) before calling dotdrop. + +# Dotdrop header + +Dotdrop is able to insert a header in the generated dotfiles. This allows +to remind anyone opening the file for editing that this file is managed by dotdrop. + +Here's what it looks like: +``` +This dotfile is managed using dotdrop +``` + +The header can be automatically added with: +``` +{{@@ header() @@}} +``` + +Properly commenting the header in templates is the responsibility of the user +as [jinja2](http://jinja.pocoo.org/) has no way of knowing what is the proper char(s) used for comments. +Either prepend the directive with the commenting char(s) used in the dotfile +(for example `# {{@@ header() @@}}`) or provide it as an argument `{{@@ header('# ') @@}}`. +The result is equivalent. + +# Available methods + +Beside [jinja2 global functions](http://jinja.pocoo.org/docs/2.10/templates/#list-of-global-functions) +the following methods can be used within the templates: + +* `exists(path)`: return true when path exists +``` +{%@@ if exists('/dev/null') @@%} +it does exist +{%@@ endif @@%} +``` + +* `exists_in_path(name, path=None)`: return true when executable exists in `$PATH` +``` +{%@@ if exists_in_path('exa') @@%} +alias ls='exa --git --color=always' +{%@@ endif @@%} +``` + +* `basename(path)`: return the `basename` of the path argument +``` +{%@@ set dotfile_filename = basename( _dotfile_abs_dst ) @@%} +dotfile dst filename: {{@@ dotfile_filename @@}} +``` + +* `dirname(path)`: return the `dirname` of the path argument +``` +{%@@ set dotfile_dirname = dirname( _dotfile_abs_dst ) @@%} +dotfile dst dirname: {{@@ dotfile_dirname @@}} +``` + +Custom user-defined functions can be loaded with the help of the +config entry `func_file`. + +Example: + +```yaml +config: + func_file: + - /tmp/myfuncs_file.py +``` + +`/tmp/myfuncs_file.py` +```python +def myfunc(arg): + return not arg +``` + +dotfile content +``` +{%@@ if myfunc(False) @@%} +this should exist +{%@@ endif @@%} +``` + +# Available filters + +Beside [jinja2 builtin filters](https://jinja.palletsprojects.com/en/2.10.x/templates/#builtin-filters) +custom user-defined filter functions can be loaded using the config entry `filter_file`: + +Example: + +```yaml +config: + filter_file: + - /tmp/myfilter_file.py +``` + +`/tmp/myfilter_file.py` +```python +def myfilter(arg1): + return str(int(arg1) - 10) +``` + +dotfile content +``` +{{@@ "13" | myfilter() @@}} +``` + +For more information on how to create filters, +see [jinja2 official doc](https://jinja.palletsprojects.com/en/2.10.x/api/#writing-filters). + +# Import macros + +Macros must be imported `with context` in order to have access to the variables: +``` +{%@@ from 'macro_file' import macro with context @@%} +``` + +For more see the [dedicated jinja2 doc](https://jinja.palletsprojects.com/en/2.11.x/templates/#macros). + +# Ignore empty template + +It is possible to avoid having an empty rendered template being +deployed by setting the `ignoreempty` entry to *true*. This can be set +globally for all dotfiles or only for specific dotfiles. + +For more see the [Config](config). + +# Include file or template in template + +[Jinja2](http://jinja.pocoo.org/docs/2.10/templates/) provides the ability to include an external file/template from within a template with the directive `include`. See the [related doc](http://jinja.pocoo.org/docs/2.10/templates/#include) for more. The path must be relative to the `dotpath`. + +For example: +```yaml +{%@@ include 'colors/black.colors' @@%} +``` + +Of course, paths could be also dynamically generated using variables. +For example: +```yaml +{%@@ include colors_path + '/black.colors' @@%} +``` + +# Debug templates + +To debug the result of a template, one can install the dotfiles to a temporary +directory with the `install` command and the `-t` switch: +```bash +$ dotdrop install -t +Installed to tmp /tmp/dotdrop-6ajz7565 +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..051c69c --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,304 @@ +# Usage + +Run `dotdrop --help` to see all available options. + +* [Basic use](#basic-use) +* Commands: + * [Install dotfiles](#install-dotfiles) + * [Compare dotfiles](#compare-dotfiles) + * [Import dotfiles](#import-dotfiles) + * [List profiles](#list-profiles) + * [List dotfiles](#list-dotfiles) + * [Update dotfiles](#update-dotfiles) + * [Remove dotfiles](#remove-dotfiles) +* Uses + * [Use actions](usage-actions) + * [Use transformations](usage-transformations) +* [Update dotdrop](#update-dotdrop) +* [Environment variables](#environment-variables) +* [User tricks](#user-tricks) + +--- + +# Basic use + +The basic use of dotdrop is +* import a file/directory to manage (this will copy the files from the filesystem to your `dotpath`): `dotdrop import ` +* install the dotfiles (will *copy/link* those from your `dotpath` to the filesystem): `dotdrop install` + +Then if you happen to update the file/directory directly on the filesystem (add new file/dir, edit content, etc) you can use `update` to mirror back those changes in the `dotpath` of dotdrop. + +For more advanced uses: +* See [this wiki](https://github.com/deadc0de6/dotdrop/wiki) +* `dotdrop --help` for more options. +* [the example](https://github.com/deadc0de6/dotdrop#getting-started) + +# Install dotfiles + +Simply run +```bash +$ dotdrop install +``` + +options + +* `-t --temp`: install the dotfile(s) to a temporary directory for review (it helps to debug templating issues for example). Note that actions are not executed in that mode. +* `-a --force-actions`: force the execution of actions even if the dotfiles are not installed + +For more detail, see the usage with `dotdrop --help` + +To ignore specific pattern during installation see [the dedicated wiki page](ignore-pattern) + +# Compare dotfiles + +Compare local dotfiles with the ones stored in dotdrop: +```bash +$ dotdrop compare +``` + +The diffing is done by `diff` in the backend, one can provide its specific +diff command using the config option `diff_command`. + +To ignore specific pattern, +see [the dedicated wiki page](ignore-pattern) + +It is also possible to install all dotfiles for a specific profile +in a temporary directory in order to manually compare them with +the local version by using `install` and the `-t` switch. + +# Import dotfiles + +Dotdrop allows to import dotfiles directly from the +filesystem. It will copy the dotfile and update the +config file automatically. + +Note that dotdrop will dereference all symlinks +when importing a file or directory (see [issue #184](https://github.com/deadc0de6/dotdrop/issues/184) for more) + +For example to import `~/.xinitrc` +```bash +$ dotdrop import ~/.xinitrc +``` + +You can control how the dotfile key is generated in the config file +with the option `longkey` (per default to *false*). + +Two formats are available: + + * *short format* (default): take the shortest unique path + * *long format*: take the full path + +For example `~/.config/awesome/rc.lua` gives + + * `f_rc.lua` in the short format + * `f_config_awesome_rc.lua` in the long format + +Importing `~/.mutt/colors` and then `~/.vim/colors` will result in + + * `d_colors` and `d_vim_colors` in the short format + * `d_mutt_colors` and `d_vim_colors` in the long format + +Dotfile can be imported as a different file with the use +of the command line switch `--as`. It is however recommended +to use the [[templating]] to avoid duplicates and optimize +dotfiles management. +```bash +$ dotdrop import ~/.zshrc --as=~/.zshrc.test +``` + +# List profiles + +```bash +$ dotdrop profiles +``` + +Dotdrop allows to choose which profile to use +with the `--profile` switch if you use something +else than the default (the hostname). + +The default profile can also be changed by defining the +`DOTDROP_PROFILE` environment variable. + +# List dotfiles + +The following command lists the different dotfiles +configured for a specific profile: + +```bash +$ dotdrop files --profile= +``` + +For example: +``` +Dotfile(s) for profile "some-profile": +f_vimrc (file: "vimrc", link: nolink) + -> ~/.vimrc +f_dunstrc (file: "config/dunst/dunstrc", link: nolink) + -> ~/.config/dunst/dunstrc +``` + +By using the `-T --template` switch, only the dotfiles that +are using [jinja2](http://jinja.pocoo.org/) directives are listed. + +It is also possible to list all files related to each dotfile entries +by invoking the `detail` command, for example: +```bash +$ dotdrop detail +dotfiles details for profile "some-profile": +f_tmux.conf (dst: "~/.tmux.conf", link: nolink) + -> /home/user/dotfiles/tmux.conf (template:no) +f_vimrc (dst: "~/.vimrc", link: nolink) + -> /home/user/dotfiles/vimrc (template:no) +``` + +This is especially useful when the dotfile entry is a directory +and one wants to have information on the different files (is it +a templated file, etc). + +# Update dotfiles + +Dotfiles managed by dotdrop can be updated using the `update` command. When updating, only +dotfiles that have differences with the stored version are updated. +A confirmation is requested from the user before any overwrite/update unless the +`-f --force` switch is used. + +Either provide the path of the file containing the new version of the dotfile or +provide the dotfile key to update (as found in the config file) along with the `-k --key` switch. +When using the `-k --key` switch and no key is provided, all dotfiles for that profile are updated. +```bash +# update by path +$ dotdrop update ~/.vimrc + +# update by key with the --key switch +$ dotdrop update --key f_vimrc +``` + +If not argument is provided, all dotfiles for the selected profile are updated. + +To ignore specific pattern, +see [the dedicated wiki page](ignore-pattern) + +There are two cases when updating a dotfile: + +## The dotfile doesn't use [templating](templating) + +The new version of the dotfile is copied to the *dotpath* directory and overwrites +the old version. If git is used to version the dotfiles stored by dotdrop, the git command +`diff` can be used to view the changes. + +```bash +$ dotdrop update ~/.vimrc +$ git diff +``` + +## The dotfile uses [templating](templating) + +The dotfile must be manually updated, three solutions can be used to identify the +changes to apply to the template: + +* Use dotdrop's `compare` command +```bash +# use compare to identify change(s) +$ dotdrop compare --file=~/.vimrc +``` + +* Call `update` with the `-P --show-patch` switch that will provide with an ad-hoc solution + to manually patch the template file using a temporary generated version of the template + (this isn't a bullet proof solution and might need manual checking) +```bash +# get an ad-hoc solution to manually patch the template +$ dotdrop update --show-patch ~/.vimrc +[WARN] /home/user/dotfiles/vimrc uses template, update manually +[WARN] try patching with: "diff -u /tmp/dotdrop-sbx6hw0r /home/user/.vimrc | patch /home/user/dotfiles/vimrc" +``` + +* Install the dotfiles to a temporary directory (using the `install` command and the + `-t` switch) and compare the generated dotfile with the local one. +```bash +# use install to identify change(s) +$ dotdrop install -t +Installed to tmp /tmp/dotdrop-6ajz7565 +$ diff ~/.vimrc /tmp/dotdrop-6ajz7565/home/user/.vimrc +``` + +It is also possible to install only specific dotfiles by providing their keys +in the command line. For example for a dotfile having a key `f_zshrc` in the config file. +```bash +$ dotdrop install -t f_zshrc +``` + +# Remove dotfiles + +The command `remove` allows to stop managing a specific dotfile with +dotdrop. It will: + +* remove the entry in the config file (under `dotfiles` and `profile`) +* remove the file from the `dotpath` + +# Update dotdrop + +If using dotdrop as a submodule, one can control if dotdrop +is auto-updated through the [dotdrop.sh](https://github.com/deadc0de6/dotdrop/blob/master/dotdrop.sh) +script by defining the environment variable `DOTDROP_AUTOUPDATE=yes`. +If undefined, `DOTDROP_AUTOUPDATE` will take the value `yes`. + +If used as a submodule, update it with +```bash +$ git submodule update --init --recursive +$ git submodule update --remote dotdrop +``` + +You will then need to commit the changes with +```bash +$ git add dotdrop +$ git commit -m 'update dotdrop' +$ git push +``` + +Or if installed through pypi: +```bash +$ pip3 install --user dotdrop --upgrade +``` + +# Environment variables + +Following environment variables can be used to specify different CLI options. +Note that CLI switches take precedence over environment variables (except for `DOTDROP_FORCE_NODEBUG`) + +* `DOTDROP_PROFILE`: `-p --profile` +```bash +export DOTDROP_PROFILE="my-fancy-profile" +``` +* `DOTDROP_CONFIG`: `-c --cfg` +```bash +export DOTDROP_CONFIG="/home/user/dotdrop/config.yaml" +``` +* `DOTDROP_NOBANNER`: `-b --no-banner` +```bash +export DOTDROP_NOBANNER= +``` +* `DOTDROP_DEBUG`: `-V --verbose` +```bash +export DOTDROP_DEBUG= +``` +* `DOTDROP_FORCE_NODEBUG`: disable debug outputs even if `-V --verbose` is provided or `DOTDROP_DEBUG` is set +```bash +export DOTDROP_FORCE_NODEBUG= +``` + +# User tricks + +## Improve git integration + +The below aliases can help with the process of updating your dotfiles between multiple hosts. Add those to your `~/.zshrc` or `~/.bashrc`. You can then simply run `dotsync` to push or pull from your dotfile repository. + +``` +# Your dotdrop git repository location +export DOTREPO="/path/to/your/dotdrop/repo" + +alias dotdrop="$DOTREPO/dotdrop.sh" +alias dotgit="git -C $DOTREPO" +alias dotsync="dotgit pull && dotgit add -A && dotgit commit && dotgit push; dotdrop install" +``` + +Provided by [ReekyMarko](https://github.com/ReekyMarko) diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..ed341b9 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,18 @@ +site_name: dotdrop +site_url: https://github.com/deadc0de6/dotdrop +repo_url: https://github.com/deadc0de6/dotdrop +theme: + name: readthedocs + highlightjs: true +use_directory_urls: true +markdown_extensions: + - mdx_truly_sane_lists +nav: + - Home: 'index.md' + - Installation: 'installation.md' + - Usage: 'usage.md' + - Config: 'config/config.md' + - Template: 'template/templating.md' + - HowTo: 'howto/index.md' + - Dependencies: 'meta/dependencies.md' + - People using dotdrop: 'meta/people-using-dotdrop.md'