├── tests ├── __init__.py └── dummy.py ├── .coveragerc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── need-help.md │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── homebrew-release.yml │ ├── snapcraft-release.yml │ ├── pypi-release.yml │ ├── aur-release.yml │ ├── testing.yml │ └── codeql-analysis.yml ├── MANIFEST.in ├── .gitattributes ├── dotdrop ├── version.py ├── __init__.py ├── exceptions.py ├── jhelpers.py ├── linktypes.py ├── dictparser.py └── profile.py ├── highlighters ├── README.md └── kakoune │ └── dotdrop.kak ├── config.toml ├── config.yaml ├── docs ├── template │ ├── template-debug.md │ ├── template-filters.md │ ├── template-methods.md │ └── templating.md ├── howto │ ├── improve-git-integration.md │ ├── include-in-template.md │ ├── prompt-user-for-variables.md │ ├── store-compressed-directories.md │ ├── howto.md │ ├── append.md │ ├── system-config-files.md │ ├── create-special-files.md │ ├── special-chars.md │ ├── group-hosts.md │ └── merge-files-when-installing.md ├── misc │ ├── people-using-dotdrop.md │ └── migrate-from-submodule.md ├── config │ ├── config-dynvars.md │ ├── config-variables.md │ ├── config-uservars.md │ └── config-actions.md ├── README.md ├── css │ └── extra.css └── getting-started.md ├── tests-requirements.txt ├── requirements.txt ├── tests-ng ├── README.md ├── dir-import-update.sh ├── bad-diff-cmd.sh ├── install-empty.sh ├── dotfile-no-src.sh ├── dyndotfilepaths.sh ├── import-subfile.sh ├── header.sh ├── dotfiles-dyn-paths.sh ├── dotdrop-variables.sh ├── dotfile-variables.sh ├── link-templates.sh ├── helpers ├── macro-with-globals.sh ├── install-to-temp.sh ├── link-import-default.sh ├── include-variables.sh ├── import-ignore.sh ├── toml.sh ├── imported-variables-from-config.sh ├── update-ignore-relative.sh ├── duplicate-key.sh ├── tests-launcher.py ├── global-update-ignore.sh ├── update-ignore.sh ├── double-config-import.sh ├── profile-import-dotfiles.sh ├── dyninclude.sh ├── link-templates-dir.sh ├── recvariables.sh ├── update-rights.sh ├── corner-case.sh ├── dotfiles-all.sh ├── link-templates-dir-home.sh ├── template-dotpath.sh ├── variables.sh ├── import-with-empty.sh ├── variables-include.sh ├── global-compare-ignore.sh ├── update-templates.sh ├── globs.sh ├── import-configs2.sh ├── dotfile-sub-variables.sh ├── install-link-children.sh ├── update-with-key.sh ├── ignore-empty.sh ├── ext-actions.sh ├── minversion.sh ├── chmod-more.sh └── dynvariables.sh ├── .gitignore ├── bootstrap.sh ├── test-doc.sh ├── completion ├── README.md └── generate.sh ├── packages ├── arch-dotdrop │ └── PKGBUILD ├── genpkg.sh ├── arch-dotdrop-git │ └── PKGBUILD └── snap │ └── snapcraft.yaml ├── dotdrop.sh ├── scripts ├── change-link.py └── yaml-to-toml.py ├── setup.py ├── test-syntax.sh ├── tests.sh └── mkdocs.yml /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] parallel=True 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: deadc0de6 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE requirements.txt 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-vendored 2 | *.py linguist-vendored=false 3 | -------------------------------------------------------------------------------- /dotdrop/version.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2018, deadc0de6 4 | """ 5 | 6 | __version__ = '1.12.1' 7 | -------------------------------------------------------------------------------- /highlighters/README.md: -------------------------------------------------------------------------------- 1 | Highlighters for dotdrop templates 2 | 3 | * [kakoune](https://kakoune.org/) -> [dotdrop.kak](/highlighters/kakoune/dotdrop.kak) (see #305) 4 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | [config] 2 | backup = true 3 | banner = true 4 | create = true 5 | dotpath = "dotfiles" 6 | keepdot = false 7 | link_dotfile_default = "nolink" 8 | link_on_import = "nolink" 9 | longkey = false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/need-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Need help 3 | about: Get help 4 | title: "[help]" 5 | labels: help 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What I am trying to achieve** 11 | 12 | **What I have tried so far** 13 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | backup: true 3 | banner: true 4 | create: true 5 | dotpath: dotfiles 6 | keepdot: false 7 | link_dotfile_default: nolink 8 | link_on_import: nolink 9 | longkey: false 10 | dotfiles: 11 | profiles: 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[feature]" 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | A clear and concise description of what you want to happen. 11 | -------------------------------------------------------------------------------- /docs/template/template-debug.md: -------------------------------------------------------------------------------- 1 | ## Debugging templates 2 | 3 | To debug the result of a template, one can install the dotfiles to a temporary 4 | directory with the `install` command and the `-t` switch: 5 | ```bash 6 | $ dotdrop install -t 7 | Installed to tmp /tmp/dotdrop-6ajz7565 8 | ``` -------------------------------------------------------------------------------- /tests-requirements.txt: -------------------------------------------------------------------------------- 1 | pycodestyle; python_version > '3.5' 2 | nose2; python_version > '3.5' 3 | coverage; python_version > '3.5' 4 | coveralls; python_version > '3.5' 5 | pyflakes; python_version > '3.5' 6 | pylint; python_version > '3.5' 7 | halo; python_version > '3.5' 8 | distro; python_version > '3.5' -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2; python_version > '3.5' 2 | docopt; python_version > '3.5' 3 | ruamel.yaml; python_version > '3.5' 4 | python-magic; python_version > '3.5' 5 | packaging; python_version > '3.5' 6 | requests; python_version > '3.5' 7 | toml; python_version > '3.5' 8 | distro; python_version > '3.5' 9 | -------------------------------------------------------------------------------- /dotdrop/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2017, deadc0de6 4 | """ 5 | 6 | # pylint: disable=C0415 7 | import sys 8 | 9 | 10 | def main(): 11 | """entry point""" 12 | import dotdrop.dotdrop 13 | if dotdrop.dotdrop.main(): 14 | sys.exit(0) 15 | sys.exit(1) 16 | -------------------------------------------------------------------------------- /tests-ng/README.md: -------------------------------------------------------------------------------- 1 | These are tests for testing entire behavior through shell scripts more easily than 2 | the overly complicated Python tests. 3 | 4 | For adding your own test, create a new script, copy the beginning of an 5 | existing test script (before the *this is the test*), and complete it 6 | with your test. 7 | 8 | Helper functions are available in `helpers`. 9 | -------------------------------------------------------------------------------- /.github/workflows/homebrew-release.yml: -------------------------------------------------------------------------------- 1 | name: Release to Homebrew 2 | on: 3 | release: 4 | types: [created] 5 | workflow_dispatch: 6 | jobs: 7 | homebrew-core: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: dawidd6/action-homebrew-bump-formula@v3 11 | with: 12 | token: ${{secrets.HOMEBREW_FORMULA_GH_TOKEN}} 13 | formula: dotdrop 14 | -------------------------------------------------------------------------------- /tests/dummy.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2017, deadc0de6 4 | basic unittest for the import function 5 | """ 6 | 7 | 8 | import unittest 9 | import dotdrop 10 | 11 | 12 | class TestDummy(unittest.TestCase): 13 | 14 | dotdrop.main() 15 | 16 | 17 | def main(): 18 | unittest.main() 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /dotdrop/exceptions.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2019, deadc0de6 4 | 5 | diverse exceptions 6 | """ 7 | 8 | 9 | class YamlException(Exception): 10 | """exception in CfgYaml""" 11 | 12 | 13 | class UndefinedException(Exception): 14 | """exception in templating""" 15 | 16 | 17 | class UnmetDependency(Exception): 18 | """unmet dependency""" 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .coverage 3 | .idea/ 4 | .vscode/ 5 | .atom/ 6 | .coverage* 7 | 8 | dist/ 9 | build/ 10 | *.egg-info/ 11 | tags 12 | env 13 | htmlcov 14 | 15 | # Snap packages 16 | parts/ 17 | prime/ 18 | stage/ 19 | *.snap 20 | 21 | /packages/snap/.snapcraft/ 22 | 23 | # Source archive packed by `snapcraft cleanbuild` before pushing to the LXD container 24 | /packages/*_source.tar.bz2 25 | 26 | venv 27 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | 5 | fold="dotfiles" 6 | conf="config.yaml" 7 | 8 | # copy dotdrop entry point 9 | cp dotdrop/dotdrop.sh dotdrop.sh 10 | chmod +x dotdrop.sh 11 | mkdir -p $fold 12 | 13 | if [ ! -e ${conf} ]; then 14 | # init config file 15 | cat << EOF > ${conf} 16 | config: 17 | backup: true 18 | create: true 19 | dotpath: $fold 20 | dotfiles: 21 | profiles: 22 | EOF 23 | fi 24 | -------------------------------------------------------------------------------- /.github/workflows/snapcraft-release.yml: -------------------------------------------------------------------------------- 1 | name: Release to Snapcraft 2 | on: 3 | release: 4 | types: [created] 5 | workflow_dispatch: 6 | jobs: 7 | build: 8 | runs-on: ubuntu-20.04 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: snapcore/action-build@v1 12 | id: build-snap 13 | with: 14 | path: ./packages/snap 15 | - uses: snapcore/action-publish@v1 16 | env: 17 | SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_LOGIN }} 18 | with: 19 | snap: ${{needs.build.outputs.snap}} 20 | release: stable 21 | -------------------------------------------------------------------------------- /docs/howto/improve-git-integration.md: -------------------------------------------------------------------------------- 1 | # Improve Git integration 2 | 3 | The below aliases can help with the process of updating your dotfiles between multiple hosts. Add them to your `~/.zshrc` or `~/.bashrc`. You can then simply run `dotsync` to push or pull from your dotfile repository. 4 | 5 | ``` 6 | # Your dotdrop git repository location 7 | export DOTREPO="/path/to/your/dotdrop/repo" 8 | 9 | alias dotdrop="$DOTREPO/dotdrop.sh" 10 | alias dotgit="git -C $DOTREPO" 11 | alias dotsync="dotgit pull && dotgit add -A && dotgit commit && dotgit push; dotdrop install" 12 | ``` 13 | 14 | Provided by [ReekyMarko](https://github.com/ReekyMarko). 15 | -------------------------------------------------------------------------------- /docs/howto/include-in-template.md: -------------------------------------------------------------------------------- 1 | # Include files or templates in templates 2 | 3 | [Jinja2](https://jinja.palletsprojects.com/en/2.11.x/templates/) provides the ability to include an external file/template from within a template with the directive `include`. See the [related docs](https://jinja.palletsprojects.com/en/2.11.x/templates/#include) for more. The path must be relative to the `dotpath`. 4 | 5 | For example: 6 | ```yaml 7 | {%@@ include 'colors/black.colors' @@%} 8 | ``` 9 | 10 | Of course, paths could be also dynamically generated using variables. 11 | For example: 12 | ```yaml 13 | {%@@ include colors_path + '/black.colors' @@%} 14 | ``` 15 | -------------------------------------------------------------------------------- /dotdrop/jhelpers.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2018, deadc0de6 4 | 5 | jinja2 helper methods 6 | """ 7 | 8 | import os 9 | import shutil 10 | 11 | 12 | def exists(path): 13 | """return true when path exists""" 14 | return os.path.exists(os.path.expandvars(path)) 15 | 16 | 17 | def exists_in_path(name, path=None): 18 | """return true when executable exists in os path""" 19 | return shutil.which(name, os.F_OK | os.X_OK, path) is not None 20 | 21 | 22 | def basename(path): 23 | """return basename""" 24 | return os.path.basename(path) 25 | 26 | 27 | def dirname(path): 28 | """return dirname""" 29 | return os.path.dirname(path) 30 | -------------------------------------------------------------------------------- /docs/template/template-filters.md: -------------------------------------------------------------------------------- 1 | # Template filters 2 | 3 | Besides [Jinja2 builtin filters](https://jinja.palletsprojects.com/en/2.11.x/templates/#builtin-filters), 4 | custom user-defined filter functions can be loaded using the config entry `filter_file`: 5 | 6 | Example: 7 | 8 | The config file: 9 | ```yaml 10 | config: 11 | filter_file: 12 | - /tmp/myfilter_file.py 13 | ``` 14 | 15 | The python filter under `/tmp/myfilter_file.py`: 16 | ```python 17 | def myfilter(arg1): 18 | return str(int(arg1) - 10) 19 | ``` 20 | 21 | The dotfile content: 22 | ``` 23 | {{@@ "13" | myfilter() @@}} 24 | ``` 25 | 26 | For more information on how to create filters, 27 | see [the Jinja2 official docs](https://jinja.palletsprojects.com/en/2.11.x/api/#writing-filters). -------------------------------------------------------------------------------- /.github/workflows/pypi-release.yml: -------------------------------------------------------------------------------- 1 | name: Release to PyPI 2 | on: 3 | release: 4 | types: [created] 5 | workflow_dispatch: 6 | jobs: 7 | pypi_publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Set up Python 3.8 12 | uses: actions/setup-python@v2 13 | with: 14 | python-version: 3.8 15 | - name: Install Tools 16 | run: | 17 | python -m pip install --upgrade pip 18 | pip install setuptools wheel twine 19 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 20 | - name: Build and Publish 21 | env: 22 | TWINE_USERNAME: __token__ 23 | TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} 24 | run: | 25 | python setup.py sdist bdist_wheel 26 | twine upload dist/* 27 | -------------------------------------------------------------------------------- /test-doc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | 5 | ## test the doc with remark 6 | ## https://github.com/remarkjs/remark-validate-links 7 | set +e 8 | which remark >/dev/null 2>&1 9 | r="$?" 10 | set -e 11 | if [ "$r" != "0" ]; then 12 | echo "[WARNING] install \"remark\" to test the doc" 13 | else 14 | remark -f -u validate-links docs/ 15 | remark -f -u validate-links *.md 16 | fi 17 | 18 | ### test the doc with markdown-link-check 19 | ### https://github.com/tcort/markdown-link-check 20 | #set +e 21 | #which markdown-link-check >/dev/null 2>&1 22 | #r="$?" 23 | #set -e 24 | #if [ "$r" != "0" ]; then 25 | # echo "[WARNING] install \"markdown-link-check\" to test the doc" 26 | #else 27 | # for i in `find docs -iname '*.md'`; do markdown-link-check $i; done 28 | # markdown-link-check README.md 29 | #fi 30 | 31 | echo "documentation OK" -------------------------------------------------------------------------------- /highlighters/kakoune/dotdrop.kak: -------------------------------------------------------------------------------- 1 | hook global WinCreate .* %{ 2 | require-module python 3 | add-highlighter window/dotdrop regions 4 | 5 | add-highlighter window/dotdrop/expression region '\{\{@[@]' '[@]@\}\}' group 6 | add-highlighter window/dotdrop/statement region '\{%@[@]' '[@]@%\}' group 7 | add-highlighter window/dotdrop/comment region '\{#@[@]' '[@]@#\}' fill comment 8 | 9 | add-highlighter window/dotdrop/expression/ fill variable 10 | add-highlighter window/dotdrop/statement/ fill variable 11 | 12 | add-highlighter window/dotdrop/expression/ ref python 13 | add-highlighter window/dotdrop/statement/ ref python 14 | 15 | add-highlighter window/dotdrop/expression/ regex '\{\{@[@]|[@]@\}\}' 0:block 16 | add-highlighter window/dotdrop/statement/ regex '\{%@[@]|[@]@%\}' 0:block 17 | add-highlighter window/dotdrop/statement/ regex 'endfor|endif' 0:keyword 18 | } 19 | -------------------------------------------------------------------------------- /docs/misc/people-using-dotdrop.md: -------------------------------------------------------------------------------- 1 | For more examples, see how people are using dotdrop: 2 | 3 | * [https://github.com/open-dynaMIX/dotfiles](https://github.com/open-dynaMIX/dotfiles) 4 | * [https://github.com/moyiz/dotfiles](https://github.com/moyiz/dotfiles) 5 | * [https://github.com/japorized/dotfiles](https://github.com/japorized/dotfiles) 6 | * [https://github.com/whitelynx/dotfiles](https://github.com/whitelynx/dotfiles) 7 | * [https://github.com/Eluminae/dotfiles](https://github.com/Eluminae/dotfiles) 8 | * [https://github.com/davla/dotfiles](https://github.com/davla/dotfiles) and [https://github.com/davla/setup](https://github.com/davla/setup) 9 | 10 | Dotfiles repositories using dotdrop on [GitHub](https://github.com/topics/dotdrop?o=desc&s=updated) and [GitLab](https://gitlab.com/search?search=dotdrop). 11 | 12 | Or search directly on [GitHub](https://github.com/search?q=filename%3Aconfig.yaml+dotdrop&type=Code) for config examples. 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: report bug 4 | title: "[bug] " 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | Dotdrop version (and git commit if run from source): v0.xxx 11 | Using dotdrop: as a submodule, from pypi, '...' 12 | 13 | **Describe the bug** 14 | 15 | A clear and concise description of what the bug is. 16 | 17 | **Steps to Reproduce** 18 | 19 | Steps to reproduce the behavior: 20 | 1. Create a dotfile with content '...' 21 | 2. '...' 22 | 4. See error 23 | 24 | **Expected behavior** 25 | 26 | A clear and concise description of what you expected to happen. 27 | 28 | **Additional information** 29 | 30 | The relevant part of the config file 31 | ```yaml 32 | config file content 33 | ``` 34 | 35 | Dotdrop's execution with the debug logs (`--verbose`) 36 | ```bash 37 | $ dotdrop --verbose ... 38 | ... 39 | ``` 40 | 41 | Any additional information that would help reproduce the bug. 42 | -------------------------------------------------------------------------------- /.github/workflows/aur-release.yml: -------------------------------------------------------------------------------- 1 | name: Release to aur 2 | on: 3 | release: 4 | types: [created] 5 | workflow_dispatch: 6 | jobs: 7 | aur_publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Prepare AUR package 12 | env: 13 | RELEASE_TAG: ${{ github.ref }} 14 | run: | 15 | version=$(echo ${RELEASE_TAG} | sed 's#^.*v##g') 16 | sed -i "s/^pkgver=.*$/pkgver=${version}/g" packages/arch-dotdrop/PKGBUILD 17 | cat packages/arch-dotdrop/PKGBUILD 18 | - name: Publish to aur 19 | uses: KSXGitHub/github-actions-deploy-aur@v2.2.4 20 | with: 21 | pkgname: dotdrop 22 | pkgbuild: ./packages/arch-dotdrop/PKGBUILD 23 | commit_username: ${{ secrets.AUR_USERNAME }} 24 | commit_email: ${{ secrets.AUR_EMAIL }} 25 | ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} 26 | commit_message: "bump version" 27 | -------------------------------------------------------------------------------- /dotdrop/linktypes.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2020, deadc0de6 4 | 5 | represents a type of link in dotdrop 6 | """ 7 | 8 | # https://github.com/PyCQA/pylint/issues/2062 9 | # pylint: disable=E1101 10 | 11 | from enum import IntEnum 12 | 13 | 14 | class LinkTypes(IntEnum): 15 | """a type of link""" 16 | NOLINK = 0 17 | LINK = 1 18 | LINK_CHILDREN = 2 19 | ABSOLUTE = 3 20 | RELATIVE = 4 21 | 22 | @classmethod 23 | def get(cls, key, default=None): 24 | """get the linktype""" 25 | try: 26 | return key if isinstance(key, cls) else cls[key.upper()] 27 | except KeyError as exc: 28 | if default: 29 | return default 30 | err = f'bad {cls.__name__} value: "{key}"' 31 | raise ValueError(err) from exc 32 | 33 | def __str__(self): 34 | """linktype to string""" 35 | return self.name.lower() 36 | -------------------------------------------------------------------------------- /docs/config/config-dynvars.md: -------------------------------------------------------------------------------- 1 | # Dynvariables entry 2 | 3 | The **dynvariables** entry (optional) contains an interpreted variables mapping. 4 | 5 | ```yaml 6 | dynvariables: 7 | : 8 | ``` 9 | 10 | You can also use multi-line (see [yaml related doc](https://yaml-multiline.info/)). 11 | For example: 12 | ```yaml 13 | dynvariables: 14 | : >- 15 | 16 | 17 | 18 | ``` 19 | 20 | For example: 21 | ```yaml 22 | dynvariables: 23 | dvar1: head -1 /proc/meminfo 24 | dvar2: "echo 'this is some test' | rev | tr ' ' ','" 25 | dvar3: /tmp/my_shell_script.sh 26 | user: "echo $USER" 27 | config_file: >- 28 | test -f "{{@@ base_config @@}}" && 29 | echo "{{@@ base_config @@}}" || 30 | echo "{{@@ dfl_config @@}}" 31 | variables: 32 | base_config: "profile_base.yaml" 33 | dfl_config: "profile_default.yaml" 34 | ``` 35 | 36 | They have the same properties as [Variables](config-variables.md). -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Dotdrop 2 | 3 | [Dotdrop](https://deadc0de.re/dotdrop/) is a dotfiles manager that provides efficient 4 | ways to manage your dotfiles. 5 | It is especially powerful when it comes to managing those across different hosts. 6 | 7 | The idea of dotdrop is to have the ability to store each dotfile only once and deploy 8 | them with different content on different hosts/setups. 9 | 10 | Most information on using dotdrop is described in this documentation 11 | and in the [readme](https://github.com/deadc0de6/dotdrop/blob/master/README.md). 12 | 13 | For more, check: 14 | 15 | * [A quick overview of dotdrop features](https://deadc0de.re/dotdrop/) 16 | * [The walkthrough example](https://github.com/deadc0de6/dotdrop#getting-started) 17 | * [The blogpost on dotdrop](https://deadc0de.re/articles/dotfiles.html) 18 | * [How people are using dotdrop](misc/people-using-dotdrop.md) 19 | 20 | For more config files examples, [search GitHub](https://github.com/search?q=filename%3Aconfig.yaml+dotdrop&type=Code). 21 | -------------------------------------------------------------------------------- /completion/README.md: -------------------------------------------------------------------------------- 1 | Here are completion files for `bash`, `zsh` and `fish` 2 | for the use of dotdrop through the bash script `dotdrop.sh` 3 | or through the Python script `dotdrop` (PyPI, snap, setup.py, etc.). 4 | 5 | `bash` and `zsh` scripts are generated using 6 | [infi.docopt_completion](https://github.com/Infinidat/infi.docopt_completion). 7 | 8 | # bash 9 | 10 | Source the file 11 | 12 | * if using `dotdrop.sh`: [dotdrop.sh-completion.bash](dotdrop.sh-completion.bash) 13 | * If using `dotdrop`: [dotdrop-completion.bash](dotdrop-completion.bash) 14 | 15 | # zsh 16 | 17 | Copy the file to a path within `${fpath}` 18 | 19 | * If using `dotdrop.sh`: [_dotdrop.sh-completion.zsh](_dotdrop.sh-completion.zsh) 20 | * If using `dotdrop`: [_dotdrop-completion.zsh](_dotdrop-completion.zsh) 21 | 22 | # fish 23 | 24 | Install for your user: 25 | ```bash 26 | mkdir -p ~/.config/fish/completions 27 | cp dotdrop.fish ~/.config/fish/completions/ 28 | ``` 29 | 30 | Install system-wide: 31 | ```bash 32 | cp dotdrop.fish /usr/share/fish/completions/ 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/howto/prompt-user-for-variables.md: -------------------------------------------------------------------------------- 1 | # Prompt user for variables 2 | 3 | With the use of [uservariables](../config/config-uservars.md), 4 | one can define specific variables that need to be initially filled in manually 5 | by the user on first run. 6 | 7 | The provided values are then automatically saved by dotdrop to `uservariables.yaml`, 8 | which can be included in the main config as a file from which variables are imported 9 | using [import_variables](../config/config-config.md). 10 | 11 | Let's say, for example, that you want to manually provide the email value 12 | on new hosts you deploy your dotfiles to. 13 | 14 | You'd add the following elements to your config: 15 | ```yaml 16 | uservariables: 17 | emailvar: "email" 18 | config: 19 | import_variables: 20 | - uservariables.yaml:optional 21 | ``` 22 | 23 | On first run, the `emailvar` is prompted to the user and then saved 24 | to `uservariables.yaml`. Since this file is imported, the value for 25 | `emailvar` will automatically be filled in without prompting the 26 | user on subsequent calls. 27 | -------------------------------------------------------------------------------- /dotdrop/dictparser.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2019, deadc0de6 4 | 5 | dictionary parser abstract class 6 | """ 7 | 8 | from dotdrop.logger import Logger 9 | 10 | 11 | class DictParser: 12 | """a dict parser""" 13 | 14 | log = Logger() 15 | 16 | @classmethod 17 | def _adjust_yaml_keys(cls, value): 18 | """adjust value for object 'cls'""" 19 | return value 20 | 21 | @classmethod 22 | def parse(cls, key, value): 23 | """parse (key,value) and construct object 'cls'""" 24 | tmp = value 25 | try: 26 | tmp = value.copy() 27 | except AttributeError: 28 | pass 29 | newv = cls._adjust_yaml_keys(tmp) 30 | if not key: 31 | return cls(**newv) 32 | return cls(key=key, **newv) 33 | 34 | @classmethod 35 | def parse_dict(cls, items): 36 | """parse a dictionary and construct object 'cls'""" 37 | if not items: 38 | return [] 39 | return [cls.parse(k, v) for k, v in items.items()] 40 | -------------------------------------------------------------------------------- /docs/howto/store-compressed-directories.md: -------------------------------------------------------------------------------- 1 | # Handle compressed directories 2 | 3 | This is an example of how to use transformations (`trans_read` and `trans_write`) to store 4 | compressed directories and deploy them with dotdrop. 5 | 6 | Start by defining the transformations: 7 | ```yaml 8 | trans_read: 9 | uncompress: "mkdir -p {1} && tar -xf {0} -C {1}" 10 | trans_write: 11 | compress: "tar -cf {1} -C {0} ." 12 | ``` 13 | 14 | Then import the directory by specifying which transformations to apply/associate: 15 | ```bash 16 | dotdrop import --transw=compress --transr=uncompress ~/.somedir 17 | ``` 18 | 19 | The *read* transformation `uncompress` is used to execute the below command before installing/comparing the dotfile (where `{0}` is the source and `{1}` the destination): 20 | ```bash 21 | mkdir -p {1} && tar -xf {0} -C {1} 22 | ``` 23 | 24 | And the *write* transformation `compress` is run when updating the dotfile directory by compressing it (where `{0}` is the source and `{1}` the destination): 25 | ```bash 26 | tar -cf {1} -C {0} . 27 | ``` 28 | 29 | See [transformations](../config/config-transformations.md). -------------------------------------------------------------------------------- /docs/config/config-variables.md: -------------------------------------------------------------------------------- 1 | # Variables entry 2 | 3 | The **variables** entry (optional) contains a variables mapping (See [variables](config-file.md#variables)). 4 | 5 | ```yaml 6 | variables: 7 | : 8 | ``` 9 | 10 | Variables defined in the `variables` entry are made available within the config file. 11 | 12 | For example 13 | ```yaml 14 | variables: 15 | myvar: "some value" 16 | home: "{{@@ env['HOME'] @@}}" 17 | email: "user@domain.com" 18 | ``` 19 | 20 | Config variables are recursively evaluated, which means that 21 | a config like the below: 22 | ```yaml 23 | variables: 24 | var1: "var1" 25 | var2: "{{@@ var1 @@}} var2" 26 | var3: "{{@@ var2 @@}} var3" 27 | var4: "{{@@ dvar4 @@}}" 28 | dynvariables: 29 | dvar1: "echo dvar1" 30 | dvar2: "{{@@ dvar1 @@}} dvar2" 31 | dvar3: "{{@@ dvar2 @@}} dvar3" 32 | dvar4: "echo {{@@ var3 @@}}" 33 | ``` 34 | 35 | will result in the following available variables: 36 | 37 | * var1: `var1` 38 | * var2: `var1 var2` 39 | * var3: `var1 var2 var3` 40 | * var4: `echo var1 var2 var3` 41 | * dvar1: `dvar1` 42 | * dvar2: `dvar1 dvar2` 43 | * dvar3: `dvar1 dvar2 dvar3` 44 | * dvar4: `var1 var2 var3` -------------------------------------------------------------------------------- /packages/arch-dotdrop/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: deadc0de6 2 | 3 | pkgname=dotdrop 4 | pkgver=1.5.4 5 | pkgrel=1 6 | pkgdesc="Save your dotfiles once, deploy them everywhere " 7 | arch=('any') 8 | url="https://github.com/deadc0de6/dotdrop" 9 | license=('GPL') 10 | groups=() 11 | depends=('python' 'python-setuptools' 'python-jinja' 'python-docopt' 'python-ruamel-yaml' 'python-magic' 'python-requests' 'python-packaging' 'python-toml' 'python-distro') 12 | makedepends=('git') 13 | source=("git+https://github.com/deadc0de6/dotdrop.git#tag=v${pkgver}") 14 | md5sums=('SKIP') 15 | 16 | pkgver() { 17 | cd "${pkgname}" 18 | git describe --abbrev=0 --tags | sed 's/^v//g' 19 | } 20 | 21 | package() { 22 | cd "${pkgname}" 23 | python setup.py install --root="${pkgdir}/" --optimize=1 24 | install -Dm644 ${srcdir}/${pkgname}/completion/dotdrop-completion.bash "${pkgdir}/usr/share/bash-completion/completions/${pkgname}" 25 | install -Dm644 ${srcdir}/${pkgname}/completion/_dotdrop-completion.zsh "${pkgdir}/usr/share/zsh/site-functions/_${pkgname}" 26 | install -Dm644 ${srcdir}/${pkgname}/completion/dotdrop.fish "${pkgdir}/usr/share/fish/completions/${pkgname}.fish" 27 | } 28 | 29 | -------------------------------------------------------------------------------- /docs/howto/howto.md: -------------------------------------------------------------------------------- 1 | # How To 2 | 3 | ## Append text to a dotfile on install 4 | 5 | [Append text to a dotfile on install](append.md) 6 | 7 | ## Create files on install 8 | 9 | [Create files on install](create-special-files.md) 10 | 11 | ## Handle compressed directories 12 | 13 | [Store compressed directories](store-compressed-directories.md) 14 | 15 | ## Handle secrets 16 | 17 | [Handle secrets](sensitive-dotfiles.md) 18 | 19 | ## Handle special chars 20 | 21 | [Handle special chars](special-chars.md) 22 | 23 | ## Improve Git integration 24 | 25 | [Improve Git integration](improve-git-integration.md) 26 | 27 | ## Include files or templates in templates 28 | 29 | [Include files or templates in templates](include-in-template.md) 30 | 31 | ## Manage system dotfiles 32 | 33 | [Manage system dotfiles](system-config-files.md) 34 | 35 | ## Merge files on install 36 | 37 | [Merge files on install](merge-files-when-installing.md) 38 | 39 | ## Prompt user for variables 40 | 41 | [Prompt user for variables](prompt-user-for-variables.md) 42 | 43 | ## Share content across dotfiles 44 | 45 | [Share content across dotfiles](sharing-content.md) 46 | 47 | ## Symlink dotfiles 48 | 49 | [Symlink dotfiles](symlink-dotfiles.md) 50 | -------------------------------------------------------------------------------- /docs/css/extra.css: -------------------------------------------------------------------------------- 1 | /* 2 | * from https://github.com/AaltoSciComp/scicomp-docs/blob/master/_static/theme_overrides.css 3 | */ 4 | 5 | /* override table width restrictions: 6 | https://github.com/rtfd/sphinx_rtd_theme/issues/117 */ 7 | .wy-table-responsive table td, .wy-table-responsive table th { 8 | white-space: normal !important; 9 | } 10 | 11 | @media screen and (min-width: 767px) { 12 | .wy-table-responsive { 13 | max-width: 100% !important; 14 | overflow: visible !important; 15 | } 16 | } 17 | 18 | /* RST has an extra space after sub-lists in unordered lists. This */ 19 | /* fixes that annoying problem. */ 20 | .rst-content .section ul p { 21 | margin-bottom: 0px; 22 | } 23 | .rst-content .section li ol { 24 | margin-bottom: 0px; 25 | } 26 | 27 | /* Strikethrough */ 28 | /* https://stackoverflow.com/questions/6518788/rest-strikethrough */ 29 | .strike { 30 | text-decoration: line-through; 31 | } 32 | 33 | /* */ 34 | .wy-side-nav-search > a img.logo, .wy-side-nav-search .wy-dropdown > a img.logo { 35 | max-width: 70%; 36 | } 37 | 38 | details summary { 39 | font-size: large; 40 | font-weight: bold; 41 | margin-bottom:12px 42 | } 43 | 44 | details { 45 | margin-bottom:20px 46 | } 47 | -------------------------------------------------------------------------------- /packages/genpkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # author: deadc0de6 3 | # 4 | # update packages 5 | # 6 | 7 | # $1: version 8 | up() 9 | { 10 | # update pkgver 11 | [ "${1}" != "" ] && sed -i "s/^pkgver=.*$/pkgver=${1}/g" ${pkgfile} 12 | # create srcinfo 13 | rm -f .SRCINFO 14 | makepkg --printsrcinfo > .SRCINFO 15 | } 16 | 17 | # pivot 18 | rl="readlink -f" 19 | if ! ${rl} "${0}" >/dev/null 2>&1; then 20 | rl="realpath" 21 | 22 | if ! hash ${rl}; then 23 | echo "\"${rl}\" not found!" && exit 1 24 | fi 25 | fi 26 | # cur 27 | cur=`dirname $(${rl} "${0}")` 28 | opwd=`pwd` 29 | pkgfile="PKGBUILD" 30 | cd ${cur} 31 | 32 | ######################## 33 | # update arch package 34 | # tag release 35 | ######################## 36 | dir="arch-dotdrop" 37 | echo "doing ${dir} ..." 38 | cd ${dir} 39 | version="`git describe --abbrev=0 --tags | sed 's/^v//g'`" 40 | up ${version} 41 | cd ${OLDPWD} 42 | 43 | ######################### 44 | ## update arch package 45 | ## git release 46 | ######################### 47 | #dir="arch-dotdrop-git" 48 | #echo "doing ${dir} ..." 49 | #cd ${dir} 50 | ## replace pkgver 51 | ##version="`git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/^v//g'`" 52 | #up 53 | #cd ${OLDPWD} 54 | 55 | # pivot back 56 | cd ${opwd} 57 | -------------------------------------------------------------------------------- /docs/howto/append.md: -------------------------------------------------------------------------------- 1 | # Append text on install 2 | 3 | Sometimes it might be useful to be able to append some text to a 4 | file. Dotdrop is able to do that with the help of 5 | [actions](../config/config-actions.md) and a temporary file. 6 | 7 | Below is a config example to append to a file: 8 | ```yaml 9 | dynvariables: 10 | tmpfile: mktemp 11 | variables: 12 | somefile_final: ~/.somefile 13 | dotfiles: 14 | f_somefile: 15 | dst: "{{@@ tmpfile @@}}" 16 | src: somefile 17 | actions: 18 | - strip "{{@@ somefile_final @@}}" 19 | - append "{{@@ tmpfile @@}}" "{{@@ somefile_final @@}}" 20 | actions: 21 | pre: 22 | strip: "sed -i '/^# my pattern$/,$d' {0}" 23 | post: 24 | append: "cat {0} >> {1}; rm -f {0}" 25 | ``` 26 | During installation, the `strip` action is executed before the installation, and it 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 contents of the `tmpfile` to the final dotfile pointed to by `somefile_final`. 27 | 28 | Obviously, the dotfile in the dotpath should start with a unique pattern (here `# my pattern`): 29 | ``` 30 | # my pattern 31 | this is the end 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/arch-dotdrop-git/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: deadc0de6 2 | 3 | _pkgname=dotdrop 4 | pkgname="${_pkgname}-git" 5 | pkgver=1.3.7.r13.g18b156e 6 | pkgrel=5 7 | pkgdesc="Save your dotfiles once, deploy them everywhere " 8 | arch=('any') 9 | url="https://github.com/deadc0de6/dotdrop" 10 | license=('GPL') 11 | groups=() 12 | depends=('python' 'python-setuptools' 'python-jinja' 'python-docopt' 'python-ruamel-yaml' 'python-magic' 'python-requests' 'python-packaging' 'python-toml' 'python-distro') 13 | makedepends=('git') 14 | provides=(dotdrop) 15 | conflicts=(dotdrop) 16 | source=("git+https://github.com/deadc0de6/dotdrop.git") 17 | md5sums=('SKIP') 18 | 19 | pkgver() { 20 | cd "${_pkgname}" 21 | git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/^v//g' 22 | } 23 | 24 | package() { 25 | cd "${_pkgname}" 26 | python setup.py install --root="${pkgdir}/" --optimize=1 27 | install -Dm644 ${srcdir}/${_pkgname}/completion/dotdrop-completion.bash "${pkgdir}/usr/share/bash-completion/completions/${_pkgname}" 28 | install -Dm644 ${srcdir}/${_pkgname}/completion/_dotdrop-completion.zsh "${pkgdir}/usr/share/zsh/site-functions/_${_pkgname}" 29 | install -Dm644 ${srcdir}/${_pkgname}/completion/dotdrop.fish "${pkgdir}/usr/share/fish/completions/${_pkgname}.fish" 30 | } 31 | 32 | -------------------------------------------------------------------------------- /dotdrop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | 5 | # check for readlink/realpath presence 6 | # https://github.com/deadc0de6/dotdrop/issues/6 7 | rl="readlink -f" 8 | 9 | if ! ${rl} "${0}" >/dev/null 2>&1; then 10 | rl="realpath" 11 | 12 | if ! hash ${rl}; then 13 | echo "\"${rl}\" not found!" && exit 1 14 | fi 15 | fi 16 | 17 | # setup variables 18 | args=("$@") 19 | cur=$(dirname "$(${rl} "${0}")") 20 | opwd=$(pwd) 21 | cfg="${cur}/config.yaml" 22 | sub="dotdrop" 23 | 24 | # pivot 25 | cd "${cur}" || { echo "Directory \"${cur}\" doesn't exist, aborting." && exit 1; } 26 | 27 | # init/update the submodule 28 | if [ "${DOTDROP_AUTOUPDATE-yes}" = yes ] ; then 29 | git submodule update --init --recursive 30 | git submodule update --remote dotdrop 31 | fi 32 | 33 | # check python executable 34 | pybin="python3" 35 | hash ${pybin} 2>/dev/null || pybin="python" 36 | [[ "`${pybin} -V 2>&1`" =~ "Python 3" ]] || { echo "install Python 3" && exit 1; } 37 | 38 | # launch dotdrop 39 | PYTHONPATH=dotdrop:${PYTHONPATH} ${pybin} -m dotdrop.dotdrop "${args[@]}" 40 | ret="$?" 41 | 42 | # pivot back 43 | cd "${opwd}" || { echo "Directory \"${opwd}\" doesn't exist, aborting." && exit 1; } 44 | 45 | # exit with dotdrop exit code 46 | exit ${ret} 47 | -------------------------------------------------------------------------------- /docs/config/config-uservars.md: -------------------------------------------------------------------------------- 1 | # Uservariables entry 2 | 3 | The **uservariables** entry (optional) contains a collection of variables 4 | whose values are queried from the user 5 | (See [User variables](config-variables.md)). 6 | 7 | ```yaml 8 | uservariables: 9 | : 10 | ``` 11 | 12 | If you want to manually enter variables' values, you can use the 13 | `uservariables` entry. Each variable will be prompted to the user. 14 | 15 | For example: 16 | ```yaml 17 | uservariables: 18 | emailvar: "email" 19 | ``` 20 | 21 | will prompt the user to enter a value for the variable `emailvar`: 22 | ``` 23 | Please provide the value for "email": 24 | ``` 25 | 26 | And store the entered text as the value for the variable `email`. 27 | The variable can then be used as any other [variable](config-file.md#variables). 28 | 29 | `uservariables` are eventually saved to `uservariables.yaml` (relatively to the 30 | config file). 31 | This allows to use the following construct to prompt once for some specific variables and 32 | then store them in a file. You might also want to add `uservariables.yaml` to your `.gitignore`. 33 | ```yaml 34 | uservariables: 35 | emailvar: "email" 36 | config: 37 | import_variables: 38 | - uservariables.yaml:optional 39 | ``` 40 | 41 | For an example, see [prompt user for variables](../howto/prompt-user-for-variables.md). 42 | -------------------------------------------------------------------------------- /docs/howto/system-config-files.md: -------------------------------------------------------------------------------- 1 | # Manage system dotfiles 2 | 3 | Dotdrop doesn't allow to handle file owernership (at least not directly). Every file operation (create/copy file/directory, create symlinks, etc.) is executed with the rights of the user calling dotdrop. 4 | 5 | Using dotdrop with `sudo` to manage unprivileged and privileged files in the same *session* is a bad idea as the resulting files will all have messed-up owners. 6 | 7 | It is therefore recommended to have two different config files (and thus two different *dotpath*s) 8 | for handling these two uses cases: 9 | 10 | For example: 11 | 12 | * One `config-user.yaml` for the local/user dotfiles (with its dedicated *dotpath*, for example `dotfiles-user`) 13 | * One `config-root.yaml` for the system/root dotfiles (with its dedicated *dotpath*, for example `dotfiles-root`) 14 | 15 | `config-user.yaml` is used when managing the user's dotfiles: 16 | ```bash 17 | ## user config file is config-user.yaml 18 | $ dotdrop import --cfg config-user.yaml 19 | $ dotdrop install --cfg config-user.yaml 20 | ... 21 | ``` 22 | 23 | `config-root.yaml` is used when managing the system's dotfiles and is to be used with `sudo` or directly by the root user: 24 | ```bash 25 | ## root config file is config-root.yaml 26 | $ sudo dotdrop import --cfg=config-root.yaml 27 | $ sudo dotdrop install --cfg=config-root.yaml 28 | ... 29 | ``` 30 | -------------------------------------------------------------------------------- /scripts/change-link.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | author: deadc0de6 (https://github.com/deadc0de6) 4 | Copyright (c) 2018, deadc0de6 5 | 6 | change the `link` key in all dotfiles 7 | to a specific value 8 | 9 | usage example: 10 | ./change-link.py --true ../config.yaml --ignore f_vimrc --ignore f_xinitrc 11 | """ 12 | 13 | import os 14 | import io 15 | from docopt import docopt 16 | from ruamel.yaml import YAML as yaml 17 | 18 | USAGE = """ 19 | change-link.py 20 | 21 | Usage: 22 | change-link.py --value= [--ignore=...] 23 | change-link.py --help 24 | 25 | Options: 26 | -h --help Show this screen. 27 | 28 | """ 29 | 30 | KEY = 'dotfiles' 31 | ENTRY = 'link' 32 | 33 | 34 | def main(): 35 | """entry point""" 36 | args = docopt(USAGE) 37 | path = os.path.expanduser(args['']) 38 | value = args['--value'] 39 | ignores = args['--ignore'] 40 | 41 | with open(path, 'r') as file: 42 | content = yaml(typ='safe').load(file) 43 | for k, val in content[KEY].items(): 44 | if k in ignores: 45 | continue 46 | val[ENTRY] = value 47 | 48 | output = io.StringIO() 49 | data = yaml() 50 | data.default_flow_style = False 51 | data.indent = 2 52 | data.typ = 'rt' 53 | data.dump(content, output) 54 | print(output) 55 | 56 | 57 | if __name__ == '__main__': 58 | main() 59 | -------------------------------------------------------------------------------- /.github/workflows/testing.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | on: [push, pull_request, workflow_dispatch] 3 | jobs: 4 | test: 5 | runs-on: ubuntu-20.04 6 | strategy: 7 | matrix: 8 | python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Set up Python ${{ matrix.python-version }} 12 | uses: actions/setup-python@v4 13 | with: 14 | python-version: ${{ matrix.python-version }} 15 | - name: Setup Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '16' 19 | - name: Install dependencies 20 | run: | 21 | python -m pip install --upgrade pip 22 | pip install -r tests-requirements.txt 23 | pip install -r requirements.txt 24 | npm install -g remark-cli remark-validate-links 25 | npm install -g markdown-link-check 26 | - name: Run sequential tests 27 | run: | 28 | ./tests.sh 29 | env: 30 | DOTDROP_FORCE_NODEBUG: yes 31 | DOTDROP_NOBANNER: yes 32 | DOTDROP_WORKERS: 1 33 | - name: Run parallel tests 34 | run: | 35 | ./tests.sh 36 | env: 37 | DOTDROP_FORCE_NODEBUG: yes 38 | DOTDROP_NOBANNER: yes 39 | DOTDROP_WORKERS: 4 40 | - name: Coveralls 41 | run: | 42 | pip install coveralls 43 | coveralls --service=github 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | -------------------------------------------------------------------------------- /docs/template/template-methods.md: -------------------------------------------------------------------------------- 1 | # Template methods 2 | 3 | Besides [Jinja2 global functions](https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-global-functions), 4 | the following methods can be used within templates: 5 | 6 | * `exists(path)`: returns true when path exists 7 | ``` 8 | {%@@ if exists('/dev/null') @@%} 9 | it does exist 10 | {%@@ endif @@%} 11 | ``` 12 | 13 | * `exists_in_path(name, path=None)`: returns true when executable exists in `$PATH` 14 | ``` 15 | {%@@ if exists_in_path('exa') @@%} 16 | alias ls='exa --git --color=always' 17 | {%@@ endif @@%} 18 | ``` 19 | 20 | * `basename(path)`: returns the `basename` of the path argument 21 | ``` 22 | {%@@ set dotfile_filename = basename( _dotfile_abs_dst ) @@%} 23 | dotfile dst filename: {{@@ dotfile_filename @@}} 24 | ``` 25 | 26 | * `dirname(path)`: returns the `dirname` of the path argument 27 | ``` 28 | {%@@ set dotfile_dirname = dirname( _dotfile_abs_dst ) @@%} 29 | dotfile dst dirname: {{@@ dotfile_dirname @@}} 30 | ``` 31 | 32 | Custom user-defined functions can be loaded with the help of the 33 | config entry `func_file`. 34 | 35 | Example: 36 | 37 | The config file: 38 | ```yaml 39 | config: 40 | func_file: 41 | - /tmp/myfuncs_file.py 42 | ``` 43 | 44 | The python function under `/tmp/myfuncs_file.py`: 45 | ```python 46 | def myfunc(arg): 47 | return not arg 48 | ``` 49 | 50 | The dotfile content: 51 | ``` 52 | {%@@ if myfunc(False) @@%} 53 | this should exist 54 | {%@@ endif @@%} 55 | ``` -------------------------------------------------------------------------------- /scripts/yaml-to-toml.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | author: deadc0de6 (https://github.com/deadc0de6) 5 | Copyright (c) 2022, deadc0de6 6 | 7 | convert yaml config file to toml 8 | """ 9 | 10 | import sys 11 | # pip3 install ruamel.yaml 12 | from ruamel.yaml import YAML as yaml 13 | # pip3 install toml 14 | import toml 15 | 16 | 17 | def yaml_load(path): 18 | """load from yaml""" 19 | with open(path, 'r', encoding='utf8') as file: 20 | data = yaml() 21 | data.typ = 'rt' 22 | content = data.load(file) 23 | return content 24 | 25 | 26 | def replace_None(content): 27 | """replace any occurence of None with empty string""" 28 | n = {} 29 | for k in content: 30 | if content[k] is None: 31 | if k == 'dotfiles': 32 | continue 33 | if k == 'profiles': 34 | continue 35 | n[k] = "" 36 | continue 37 | if isinstance(content[k], dict): 38 | n[k] = replace_None(content[k]) 39 | continue 40 | n[k] = content[k] 41 | return n 42 | 43 | 44 | def toml_dump(content): 45 | """dump toml to stdout""" 46 | return toml.dumps(content) 47 | 48 | 49 | if __name__ == '__main__': 50 | if len(sys.argv) < 2: 51 | print("usage: {} ".format(sys.argv[0])) 52 | sys.exit(1) 53 | 54 | path = sys.argv[1] 55 | content = yaml_load(path) 56 | content = replace_None(content) 57 | out = toml_dump(content) 58 | print(out) 59 | -------------------------------------------------------------------------------- /completion/generate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # pip3 install --user infi.docopt_completion 6 | # 7 | 8 | set -e 9 | 10 | bin="docopt-completion" 11 | if ! hash ${bin}; then 12 | echo "\"${bin}\" not found!" 13 | exit 1 14 | fi 15 | 16 | rl="readlink -f" 17 | if ! ${rl} "${0}" >/dev/null 2>&1; then 18 | rl="realpath" 19 | 20 | if ! hash ${rl}; then 21 | echo "\"${rl}\" not found!" 22 | exit 1 23 | fi 24 | fi 25 | 26 | cur=$(dirname "$(${rl} "${0}")") 27 | opwd=$(pwd) 28 | 29 | # output files 30 | compl="${cur}" 31 | dtsh_zsh="${compl}/_dotdrop.sh-completion.zsh" 32 | dtsh_bash="${compl}/dotdrop.sh-completion.bash" 33 | dt_zsh="${compl}/_dotdrop-completion.zsh" 34 | dt_bash="${compl}/dotdrop-completion.bash" 35 | 36 | # generate for dotdrop.sh 37 | cd ${cur}/.. 38 | docopt-completion ./dotdrop.sh --manual-zsh 39 | mv ./_dotdrop.sh ${dtsh_zsh} 40 | docopt-completion ./dotdrop.sh --manual-bash 41 | mv ./dotdrop.sh.sh ${dtsh_bash} 42 | 43 | # generate for dotdrop 44 | vbin="virtualenv" 45 | if ! hash ${vbin}; then 46 | echo "\"${vbin}\" not found!" 47 | exit 1 48 | fi 49 | cd ${cur}/.. 50 | venv="/tmp/dotdrop-venv" 51 | ${vbin} -p python3 ${venv} 52 | source ${venv}/bin/activate 53 | python setup.py install 54 | cd /tmp 55 | docopt-completion dotdrop --manual-zsh 56 | mv ./_dotdrop ${dt_zsh} 57 | docopt-completion dotdrop --manual-bash 58 | mv ./dotdrop.sh ${dt_bash} 59 | deactivate 60 | rm -rf ${venv} 61 | 62 | # pivot back 63 | cd ${opwd} 64 | -------------------------------------------------------------------------------- /packages/snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: dotdrop 2 | base: core18 3 | adopt-info: version 4 | summary: Save your dotfiles once, deploy them everywhere 5 | description: | 6 | Dotdrop makes the management of dotfiles between different hosts easy. 7 | It allows to store your dotfiles on git and automagically deploy different versions 8 | of the same file on different setups. 9 | 10 | It also allows to manage different sets of dotfiles. 11 | For example you can have a set of dotfiles for your home laptop and a different 12 | set for your office desktop. Those sets may overlap and different versions of 13 | the same dotfiles can be deployed on different predefined profiles. 14 | Or you may have a main set of dotfiles for your everyday's host and a sub-set you 15 | only need to deploy to temporary hosts (cloud VM, etc) that may be using a slightly 16 | different version of some of the dotfiles. 17 | It allows to store your dotfiles on git and automagically deploy 18 | different versions of the same file on different setups. 19 | 20 | Project page: https://github.com/deadc0de6/dotdrop 21 | 22 | confinement: strict 23 | grade: stable 24 | 25 | apps: 26 | dotdrop: 27 | command: dotdrop 28 | plugs: 29 | - home 30 | 31 | parts: 32 | dotdrop: 33 | plugin: python 34 | python-version: python3 35 | source: ../../ 36 | stage-packages: 37 | - file 38 | version: 39 | source: . 40 | plugin: nil 41 | override-build: | 42 | VERSION=$(git describe --abbrev=0 --tags | sed 's/^v//g') 43 | snapcraftctl set-version "${VERSION}" 44 | -------------------------------------------------------------------------------- /docs/howto/create-special-files.md: -------------------------------------------------------------------------------- 1 | # Create files on install 2 | 3 | One way to create symlinks (or any other special file) is to use a combination of 4 | [actions](../config/config-actions.md) and a *fake* dotfile. 5 | 6 | Let's say, for example, you have a list of directories you want to link 7 | from under `~/.original` to `~/symlinks`. 8 | ```bash 9 | $ tree ~/.original 10 | /home/user/.original 11 | ├── dir1 12 | ├── dir2 13 | └── dir3 14 | ``` 15 | 16 | First you would store these directory names in a text file in your `/links.txt`: 17 | ``` 18 | dir1 19 | dir2 20 | dir3 21 | ``` 22 | 23 | The config file would contain different elements: 24 | 25 | * A `dynvariables` that will read the above text file 26 | * A few `variables` for the source and destination 27 | * An action that will create the destination directory and symlink those directories 28 | * A *fake* dotfile (with no `src` and no `dst` values) that will be always installed with the above action 29 | 30 | ```yaml 31 | dynvariables: 32 | links_list: "cat {{@@ _dotdrop_dotpath @@}}/links.txt | xargs" 33 | ... 34 | variables: 35 | links_dst: "{{@@ env['HOME'] @@}}/.symlinks" 36 | links_src: "{{@@ env['HOME'] @@}}/.original" 37 | ... 38 | actions: 39 | symlink_them: 'mkdir -p "{1}" && for lnk in {0}; do ln -s "{{@@ links_src @@}}/$lnk" "{1}/$lnk"; done' 40 | ... 41 | fake: 42 | src: 43 | dst: 44 | actions: 45 | - symlink_them '{{@@ links_list @@}}' '{{@@ links_dst @@}}' 46 | ``` 47 | 48 | The result would be: 49 | ```bash 50 | $ tree ~/.symlinks 51 | /home/user/.symlinks 52 | ├── dir1 -> /home/user/.original/dir1 53 | ├── dir2 -> /home/user/.original/dir2 54 | └── dir3 -> /home/user/.original/dir3 55 | ``` 56 | 57 | For reference, see [issue 243](https://github.com/deadc0de6/dotdrop/issues/243). 58 | -------------------------------------------------------------------------------- /docs/howto/special-chars.md: -------------------------------------------------------------------------------- 1 | # Handle special chars 2 | 3 | * [Detect encoding](#detect-encoding) 4 | * [Special chars](#special-chars) 5 | * [Re-encode](#re-encode) 6 | 7 | --- 8 | 9 | ## Detect encoding 10 | 11 | Text file encoding can be identified using, for example, `file -b ` or in vim 12 | with `:set fileencoding`. 13 | 14 | Here's an example of encoding that will fully work with dotdrop: 15 | ```bash 16 | $ file -b 17 | UTF-8 Unicode text, with escape sequences 18 | ``` 19 | 20 | and another that will mislead the `compare` command and return false/inaccurate results: 21 | ```bash 22 | $ file -b 23 | ISO-8859 text, with escape sequences 24 | ``` 25 | 26 | ## Special chars 27 | 28 | ### CRLF 29 | 30 | The use of dotfiles with DOS/Windows line endings (CRLF, `\r\n`) will result in 31 | the comparison (`compare`) returning a difference where there is none. 32 | This is due to Jinja2 stripping CRLF. 33 | 34 | One solution is to use `dos2unix` to re-format the dotfiles before adding them 35 | to dotdrop. 36 | 37 | See . 38 | 39 | ### Non-Unicode chars 40 | 41 | Jinja2 is not able to process non-Unicode chars (). 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. 42 | 43 | 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. 44 | 45 | See . 46 | 47 | ## Re-encode 48 | 49 | 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`. 50 | -------------------------------------------------------------------------------- /dotdrop/profile.py: -------------------------------------------------------------------------------- 1 | """ 2 | author: deadc0de6 (https://github.com/deadc0de6) 3 | Copyright (c) 2019, deadc0de6 4 | 5 | represent a profile in dotdrop 6 | """ 7 | 8 | from dotdrop.dictparser import DictParser 9 | from dotdrop.action import Action 10 | 11 | 12 | class Profile(DictParser): 13 | """dotdrop profile""" 14 | 15 | # profile keys 16 | key_include = 'include' 17 | key_import = 'import' 18 | 19 | def __init__(self, key, actions=None, dotfiles=None, 20 | variables=None, dynvariables=None): 21 | """ 22 | constructor 23 | @key: profile key 24 | @actions: list of action keys 25 | @dotfiles: list of dotfile keys 26 | @variables: list of variable keys 27 | @dynvariables: list of interpreted variable keys 28 | """ 29 | self.key = key 30 | self.actions = actions or [] 31 | self.dotfiles = dotfiles or [] 32 | self.variables = variables or [] 33 | self.dynvariables = dynvariables or [] 34 | 35 | def get_pre_actions(self): 36 | """return all 'pre' actions""" 37 | return [a for a in self.actions if a.kind == Action.pre] 38 | 39 | def get_post_actions(self): 40 | """return all 'post' actions""" 41 | return [a for a in self.actions if a.kind == Action.post] 42 | 43 | @classmethod 44 | def _adjust_yaml_keys(cls, value): 45 | """patch dict""" 46 | value.pop(cls.key_import, None) 47 | value.pop(cls.key_include, None) 48 | return value 49 | 50 | def __eq__(self, other): 51 | return self.__dict__ == other.__dict__ 52 | 53 | def __hash__(self): 54 | return (hash(self.key) ^ 55 | hash(tuple(self.dotfiles))) 56 | 57 | def __str__(self): 58 | return f'key:"{self.key}"' 59 | 60 | def __repr__(self): 61 | return f'profile({self})' 62 | -------------------------------------------------------------------------------- /docs/misc/migrate-from-submodule.md: -------------------------------------------------------------------------------- 1 | **WARNING** 2 | 3 | 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. 4 | 5 | --- 6 | 7 | Initially dotdrop was only available as a submodule directly in the 8 | dotfiles git tree. When updated to work with PyPI, some code changed 9 | that brought some issues to older versions. 10 | 11 | If you want to keep it as a submodule (recommended), simply do the following: 12 | ```bash 13 | $ cd 14 | 15 | ## get latest version of the submodule 16 | $ git submodule foreach git pull origin master 17 | 18 | ## and stage the changes 19 | $ git add dotdrop 20 | $ git commit -m 'update dotdrop' 21 | 22 | ## update the bash script wrapper 23 | $ ./dotdrop/bootstrap.sh 24 | 25 | ## and stage the change to the dotdrop.sh script 26 | $ git add dotdrop.sh 27 | $ git commit -m 'update dotdrop.sh' 28 | 29 | ## and finally push the changes upstream 30 | $ git push 31 | ``` 32 | 33 | Otherwise, simply install it from PyPI as shown below: 34 | 35 | * Move to the dotfiles directory where dotdrop is used as a submodule 36 | ```bash 37 | $ cd 38 | ``` 39 | * Remove the entire `submodule "dotdrop"` section in `.gitmodules` 40 | * Stage the changes 41 | ```bash 42 | $ git add .gitmodules 43 | ``` 44 | * Remove the entire `submodule "dotdrop"` section in `.git/config` 45 | * Remove the submodule 46 | ```bash 47 | $ git rm --cached dotdrop 48 | ``` 49 | * Remove the submodule from .git 50 | ```bash 51 | $ rm -rf .git/modules/dotdrop 52 | ``` 53 | * Commit the changes 54 | ```bash 55 | $ git commit -m 'removing dotdrop submodule' 56 | ``` 57 | * Remove any remaining files from the dotdrop submodule 58 | ```bash 59 | $ rm -rf dotdrop 60 | ``` 61 | * Remove `dotdrop.sh` 62 | ```bash 63 | $ git rm dotdrop.sh 64 | $ git commit -m 'remove dotdrop.sh script' 65 | ``` 66 | * Push upstream 67 | ```bash 68 | $ git push 69 | ``` 70 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | from os import path 3 | from dotdrop.version import __version__ as VERSION 4 | 5 | readme = 'README.md' 6 | here = path.abspath(path.dirname(__file__)) 7 | 8 | def read_readme(f): 9 | with open(f, encoding="utf-8") as fp: 10 | return fp.read() 11 | 12 | REQUIRES_PYTHON = '>=3' 13 | 14 | setup( 15 | name='dotdrop', 16 | version=VERSION, 17 | 18 | description='Save your dotfiles once, deploy them everywhere', 19 | long_description=read_readme(readme), 20 | long_description_content_type="text/markdown; variant=GFM", 21 | url='https://github.com/deadc0de6/dotdrop', 22 | download_url = 'https://github.com/deadc0de6/dotdrop/archive/v'+VERSION+'.tar.gz', 23 | options={"bdist_wheel": {"python_tag": "py3"}}, 24 | # include anything from MANIFEST.in 25 | include_package_data=True, 26 | 27 | author='deadc0de6', 28 | author_email='deadc0de6@foo.bar', 29 | 30 | license='GPLv3', 31 | python_requires=REQUIRES_PYTHON, 32 | classifiers=[ 33 | 'Development Status :: 5 - Production/Stable', 34 | 'Programming Language :: Python :: 3.6', 35 | 'Programming Language :: Python :: 3.7', 36 | 'Programming Language :: Python :: 3.8', 37 | 'Programming Language :: Python :: 3.9', 38 | 'Programming Language :: Python :: 3.10', 39 | 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 40 | ], 41 | 42 | keywords='dotfiles jinja2', 43 | packages=find_packages(exclude=['tests*']), 44 | install_requires=['docopt', 'Jinja2', 'ruamel.yaml', 'python-magic', 'packaging', 'requests', 'toml', 'distro'], 45 | 46 | extras_require={ 47 | 'dev': ['check-manifest'], 48 | 'test': ['coverage', 'pytest', 'pytest-cov'], 49 | }, 50 | 51 | entry_points={ 52 | 'console_scripts': [ 53 | 'dotdrop=dotdrop:main', 54 | ], 55 | }, 56 | ) 57 | -------------------------------------------------------------------------------- /test-syntax.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | 5 | # stop on first error 6 | #set -ev 7 | set -e 8 | 9 | # versions 10 | echo "pylint version:" 11 | pylint --version 12 | echo "pycodestyle version:" 13 | pycodestyle --version 14 | echo "pyflakes version:" 15 | pyflakes --version 16 | 17 | # PEP8 tests 18 | which pycodestyle >/dev/null 2>&1 19 | [ "$?" != "0" ] && echo "Install pycodestyle" && exit 1 20 | echo "testing with pycodestyle" 21 | # W503: Line break occurred before a binary operator 22 | # W504: Line break occurred after a binary operator 23 | pycodestyle --ignore=W503,W504 dotdrop/ 24 | pycodestyle tests/ 25 | pycodestyle scripts/ 26 | 27 | # pyflakes tests 28 | echo "testing with pyflakes" 29 | pyflakes dotdrop/ 30 | pyflakes tests/ 31 | 32 | # pylint 33 | echo "testing with pylint" 34 | # https://pylint.pycqa.org/en/latest/user_guide/checkers/features.html 35 | # R0902: too-many-instance-attributes 36 | # R0913: too-many-arguments 37 | # R0903: too-few-public-methods 38 | # R0914: too-many-locals 39 | # R0915: too-many-statements 40 | # R0912: too-many-branches 41 | # R0911: too-many-return-statements 42 | # R0904: too-many-public-methods 43 | pylint \ 44 | --disable=R0902 \ 45 | --disable=R0913 \ 46 | --disable=R0903 \ 47 | --disable=R0914 \ 48 | --disable=R0915 \ 49 | --disable=R0912 \ 50 | --disable=R0911 \ 51 | --disable=R0904 \ 52 | dotdrop/ 53 | 54 | set +e 55 | exceptions="save_uservariables_name\|@@\|diff_cmd\|original,\|modified," 56 | # f-string errors and missing f literal 57 | find dotdrop/ -iname '*.py' -exec grep --with-filename -n -v "f'" {} \; | grep -v "{'" | grep -v "${exceptions}" | grep "'.*}" && echo "bad string format (1): ${errs}" && exit 1 58 | find dotdrop/ -iname '*.py' -exec grep --with-filename -n -v 'f"' {} \; | grep -v "f'" | grep -v '{"' | grep -v "${exceptions}" | grep '".*}' && echo "bad string format (2): ${errs}" && exit 1 59 | set -e 60 | 61 | echo "syntax OK" -------------------------------------------------------------------------------- /tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | 5 | # stop on first error 6 | #set -ev 7 | set -e 8 | 9 | rl="readlink -f" 10 | if ! ${rl} "${0}" >/dev/null 2>&1; then 11 | rl="realpath" 12 | 13 | if ! hash ${rl}; then 14 | echo "\"${rl}\" not found!" && exit 1 15 | fi 16 | fi 17 | cur=`dirname $(${rl} "${0}")` 18 | 19 | # test syntax 20 | ${cur}/test-syntax.sh 21 | 22 | # test doc 23 | ${cur}/test-doc.sh 24 | 25 | workers=${DOTDROP_WORKERS} 26 | if [ ! -z ${workers} ]; then 27 | unset DOTDROP_WORKERS 28 | echo "DISABLE workers" 29 | fi 30 | 31 | # execute tests with coverage 32 | if [ -z ${GITHUB_WORKFLOW} ]; then 33 | ## local 34 | export COVERAGE_FILE= 35 | # do not print debugs when running tests (faster) 36 | unset DOTDROP_DEBUG 37 | export DOTDROP_FORCE_NODEBUG=yes 38 | # tests 39 | PYTHONPATH="dotdrop" nose2 --with-coverage --coverage dotdrop --plugin=nose2.plugins.mp -N0 40 | else 41 | ## CI/CD 42 | export COVERAGE_FILE="${cur}/.coverage" 43 | # tests 44 | PYTHONPATH="dotdrop" nose2 --with-coverage --coverage dotdrop 45 | fi 46 | #PYTHONPATH="dotdrop" python3 -m pytest tests 47 | 48 | tmpworkdir="/tmp/dotdrop-tests-workdir" 49 | export DOTDROP_WORKDIR="${tmpworkdir}" 50 | 51 | if [ ! -z ${workers} ]; then 52 | DOTDROP_WORKERS=${workers} 53 | echo "ENABLE workers: ${workers}" 54 | fi 55 | 56 | # run bash tests 57 | export DOTDROP_DEBUG="yes" 58 | unset DOTDROP_FORCE_NODEBUG 59 | workdir_tmp_exists="no" 60 | [ -d "~/.config/dotdrop/tmp" ] && workdir_tmp_exists="yes" 61 | if [ -z ${GITHUB_WORKFLOW} ]; then 62 | ## local 63 | export COVERAGE_FILE= 64 | tests-ng/tests-launcher.py 65 | else 66 | ## CI/CD 67 | export COVERAGE_FILE="${cur}/.coverage" 68 | tests-ng/tests-launcher.py 1 69 | fi 70 | 71 | # clear workdir 72 | [ "${workdir_tmp_exists}" = "no" ] && rm -rf ~/.config/dotdrop/tmp 73 | # clear temp workdir 74 | rm -rf "${tmpworkdir}" 75 | 76 | ## done 77 | echo "All test finished successfully" 78 | -------------------------------------------------------------------------------- /docs/howto/group-hosts.md: -------------------------------------------------------------------------------- 1 | # Group hosts in config and meta profiles 2 | 3 | Let's consider the situation where you have multiple hosts from different distros and you 4 | want an easy way to structure your config file nicely but also simplify the use 5 | of templates (since multiple hosts in the same distro would share the same configs parts - 6 | or if branch in templates). 7 | 8 | You define two types of profiles: 9 | 10 | * **Meta profiles**: for example for distros it would be something like `os_arch`, `os_debian` and so on. 11 | These are never directly used for installing dotfiles but instead included by other profiles. 12 | * **Host profiles** (defaults to hostnames): the usual `home`, `office`, etc 13 | 14 | Each *Host profile* would include a *meta profile* and inherit all its dotfiles as well as 15 | it variables. For example in the *meta profile* you would define variables like `distro: debian` 16 | that you could use in your templates with `{%@@ if distro == "debian" @@%}` to target all 17 | profiles that inherit from the same *meta profile*. 18 | 19 | ```yaml 20 | profiles: 21 | meta_base: 22 | dotfiles: 23 | - f_zshrc 24 | - f_zshrc 25 | os_arch: 26 | variables: 27 | distro: arch 28 | include: 29 | - meta-base 30 | os_debian: 31 | variables: 32 | distro: debian 33 | include: 34 | - meta-base 35 | home: 36 | include: 37 | - os_arch 38 | dotfiles: 39 | - f_vimrc 40 | office: 41 | include: 42 | - os_debian 43 | dotfiles: 44 | - f_something 45 | ``` 46 | 47 | You then have the opportunity in your templates to do the following 48 | that would select the if branch for all profiles inheriting from 49 | a specific *meta profile*. 50 | ``` 51 | # zsh-syntax-highlighting 52 | # https://github.com/zsh-users/zsh-syntax-highlighting 53 | {%@@ if distro == "arch" @@%} 54 | source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 55 | {%@@ elif distro == "debian" @@%} 56 | source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 57 | {%@@ endif @@%} 58 | ``` -------------------------------------------------------------------------------- /tests-ng/dir-import-update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test importing and updating entire directories 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | dotfiles="${basedir}/dotfiles" 52 | echo "dotdrop dir: ${basedir}" 53 | # the dotfile 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | create_dir ${tmpd} 56 | 57 | clear_on_exit "${basedir}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${basedir}/config.yaml" 62 | create_conf ${cfg} # sets token 63 | 64 | # import the dir 65 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd} 66 | 67 | # change token 68 | echo "changed" > ${token} 69 | 70 | # update 71 | cd ${ddpath} | ${bin} update -f -c ${cfg} ${tmpd} --verbose 72 | 73 | grep 'changed' ${token} >/dev/null 2>&1 74 | 75 | echo "OK" 76 | exit 0 77 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ## Repository setup 4 | 5 | Either create a Git repository on your prefered platform and clone it or create one locally. 6 | This repository will contain two main elements, dotdrop's config file (`config.yaml`) 7 | and a directory containing all your dotfiles managed by dotdrop. 8 | ```bash 9 | ## clone your repository (my-dotfiles) 10 | $ git clone /my-dotfiles 11 | $ cd my-dotfiles 12 | 13 | ## within the repository create a directory to store your dotfiles 14 | ## (refered by "dotpath" in the config, which defaults to "dotfiles") 15 | $ mkdir dotfiles 16 | ``` 17 | 18 | Then add a config file. You can get a 19 | [minimal config file](https://github.com/deadc0de6/dotdrop/blob/master/config.yaml) 20 | from dotdrop's repository with: 21 | ```bash 22 | $ wget https://raw.githubusercontent.com/deadc0de6/dotdrop/master/config.yaml 23 | ``` 24 | It is recommended to store your config file directly within your repository 25 | (*my-dotfiles* in the example above), but you could save it in different places if you wish; 26 | see [config location](config/config-file.md#location) for more. 27 | 28 | ```bash 29 | $ tree my-dotfiles 30 | my-dotfiles 31 | ├── config.yaml 32 | └── dotfiles 33 | ``` 34 | 35 | If your config file is in an exotic location, you can add an alias 36 | in your preferred shell to call dotdrop with the config file path argument. 37 | ``` 38 | alias dotdrop='dotdrop --cfg=' 39 | ``` 40 | 41 | For more info on the config file format, see [the config file doc](config/config-file.md). 42 | 43 | ## Basic usage 44 | 45 | The basic use of dotdrop is: 46 | 47 | * Import a file/directory to manage (this will copy the files from the filesystem to your `dotpath`): `dotdrop import ` 48 | * Install the dotfiles (this will *copy/link* them from your `dotpath` to the filesystem): `dotdrop install` 49 | 50 | Then if you happen to update the file/directory directly on the filesystem (add a new file/dir, edit content, etc.) you can use the `update` command to mirror back those changes in dotdrop. 51 | 52 | For more advanced uses: 53 | 54 | * `dotdrop --help` for the CLI usage. 55 | * [The usage doc](usage.md) 56 | * [The example](https://github.com/deadc0de6/dotdrop#getting-started) 57 | * [The howto](howto/howto.md) -------------------------------------------------------------------------------- /docs/howto/merge-files-when-installing.md: -------------------------------------------------------------------------------- 1 | # Merge files on install 2 | 3 | Dotdrop allows to merge multiple files into one using Jinja2's `include` directive. 4 | 5 | For example, let's assume you want to keep your `.vimrc` split into multiple parts in dotdrop: 6 | * `/vimrc.d/top`: top part of the file 7 | * `/vimrc.d/bottom`: bottom part of the file 8 | 9 | And you want dotdrop to merge all those files into `~/.vimrc` whenever you process your .vimrc with dotdrop. 10 | 11 | First make sure `~/.vimrc` is present in your config file: 12 | ```yaml 13 | ... 14 | dotfiles: 15 | f_vimrc: 16 | dst: ~/.vimrc 17 | src: vimrc 18 | profiles: 19 | hostname: 20 | dotfiles: 21 | - f_vimrc 22 | ... 23 | ``` 24 | 25 | Note that the subfiles (`vimrc.d/top` and `vimrc.d/bottom`) 26 | are not known to the config and do not need to be. 27 | 28 | Edit the stored vimrc file to include the other files, for example: 29 | ```bash 30 | $ cat /vimrc 31 | {%@@ include 'vimrc.d/top' @@%} 32 | filetype on 33 | set t_Co=256 34 | set tw=0 35 | set tabstop=2 36 | set shiftwidth=2 37 | set expandtab 38 | set nocompatible 39 | set nomodeline 40 | syntax on 41 | {%@@ include 'vimrc.d/bottom' @@%} 42 | ``` 43 | 44 | The `include` path parameter needs to be relative to your `dotpath`. 45 | 46 | Dotdrop will then automagically include the files into your vimrc when handling `f_vimrc`. 47 | 48 | ## Merge all files in a directory 49 | 50 | To include all files in a directory, a combination of 51 | [dynvariables](../config/config-dynvars.md) 52 | and [Jinja2 directives](https://jinja.palletsprojects.com/en/2.11.x/) have to be used. 53 | 54 | Let's say all files in `/toinclude` need to be included into a dotfile. 55 | 56 | First define a [dynvariables](../config/config-dynvars.md) 57 | in the config file which will look for files to include in the above directory: 58 | ```yaml 59 | dynvariables: 60 | allfiles: "cd {{@@ _dotdrop_dotpath @@}}; find toinclude/ -type f | xargs" 61 | ``` 62 | 63 | Note that `_dotdrop_dotpath` is part of the built-in variables 64 | (For more, see [template variables](../template/template-variables.md#template-variables)). 65 | 66 | Then use the generated list in the dotfile template: 67 | ``` 68 | {%@@ for f in allfiles.split() @@%} 69 | {%@@ include f @@%} 70 | {%@@ endfor @@%} 71 | ``` 72 | -------------------------------------------------------------------------------- /tests-ng/bad-diff-cmd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | # 5 | # test bad diff cmd 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 49 | echo "[+] dotdrop dir: ${basedir}" 50 | 51 | clear_on_exit "${basedir}" 52 | 53 | # create the config file 54 | cfg="${basedir}/config.yaml" 55 | cat > ${cfg} << _EOF 56 | config: 57 | backup: true 58 | create: true 59 | dotpath: dotfiles 60 | diff_command: xxxxxxxxx {0} {1} 61 | dotfiles: 62 | profiles: 63 | _EOF 64 | 65 | set +e 66 | cd ${ddpath} | ${bin} compare -c ${cfg} 67 | [ "$?" = "0" ] && exit 1 68 | 69 | out=$(cd ${ddpath} | ${bin} compare -c ${cfg}) 70 | echo "${out}" | grep -i 'traceback' && exit 1 71 | 72 | cat > ${cfg} << _EOF 73 | config: 74 | backup: true 75 | create: true 76 | dotpath: dotfiles 77 | diff_command: 78 | dotfiles: 79 | profiles: 80 | _EOF 81 | 82 | set +e 83 | cd ${ddpath} | ${bin} compare -c ${cfg} 84 | [ "$?" = "0" ] && exit 1 85 | 86 | out=$(cd ${ddpath} | ${bin} compare -c ${cfg}) 87 | echo "${out}" | grep -i 'traceback' && exit 1 88 | 89 | echo "OK" 90 | exit 0 91 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: dotdrop 2 | site_url: https://github.com/deadc0de6/dotdrop 3 | repo_url: https://github.com/deadc0de6/dotdrop 4 | theme: 5 | name: readthedocs 6 | highlightjs: true 7 | hljs_languages: 8 | - yaml 9 | #collapse_navigation: false 10 | use_directory_urls: true 11 | nav: 12 | - 'Dotdrop': 'README.md' 13 | - 'Installation': 'installation.md' 14 | - 'Getting started': 'getting-started.md' 15 | - 'Usage': 'usage.md' 16 | - 'Config': 17 | - 'Config file': 'config/config-file.md' 18 | - 'Config block': 'config/config-config.md' 19 | - 'Dotfiles block': 'config/config-dotfiles.md' 20 | - 'Profiles block': 'config/config-profiles.md' 21 | - 'Actions block': 'config/config-actions.md' 22 | - 'Transformations block': 'config/config-transformations.md' 23 | - 'Variables block': 'config/config-variables.md' 24 | - 'Dynvariables block': 'config/config-dynvars.md' 25 | - 'Uservariables block': 'config/config-uservars.md' 26 | - 'Templating': 27 | - 'Templating': 'template/templating.md' 28 | - 'Template variables': 'template/template-variables.md' 29 | - 'Template methods': 'template/template-methods.md' 30 | - 'Template filters': 'template/template-filters.md' 31 | - 'Debugging templates': 'template/template-debug.md' 32 | - 'HowTo': 33 | - 'Append text to a dotfile on install': 'howto/append.md' 34 | - 'Create files on install': 'howto/create-special-files.md' 35 | - 'Group hosts and meta profiles': 'howto/group-hosts.md' 36 | - 'Handle compressed directories': 'howto/store-compressed-directories.md' 37 | - 'Handle secrets': 'howto/sensitive-dotfiles.md' 38 | - 'Handle special chars': 'howto/special-chars.md' 39 | - 'Improve Git integration': 'howto/improve-git-integration.md' 40 | - 'Include files or templates in templates': 'howto/include-in-template.md' 41 | - 'Manage system dotfiles': 'howto/system-config-files.md' 42 | - 'Merge files on install': 'howto/merge-files-when-installing.md' 43 | - 'Prompt user for variables': 'howto/prompt-user-for-variables.md' 44 | - 'Share content across dotfiles': 'howto/sharing-content.md' 45 | - 'Symlink dotfiles': 'howto/symlink-dotfiles.md' 46 | - '': '' 47 | - '': '' 48 | markdown_extensions: 49 | - meta 50 | - tables 51 | - fenced_code 52 | - toc: 53 | permalink: True 54 | extra_css: 55 | - css/extra.css 56 | 57 | -------------------------------------------------------------------------------- /tests-ng/install-empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test install empty dst or empty src 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | echo "[+] dotdrop dir: ${basedir}" 52 | echo "[+] dotpath dir: ${basedir}/dotfiles" 53 | 54 | clear_on_exit "${basedir}" 55 | 56 | # create the config file 57 | cfg="${basedir}/config.yaml" 58 | cat > ${cfg} << _EOF 59 | config: 60 | backup: true 61 | create: true 62 | dotpath: dotfiles 63 | dotfiles: 64 | f_x: 65 | src: /tmp/x 66 | dst: 67 | f_y: 68 | src: 69 | dst: /tmp/y 70 | f_z: 71 | src: 72 | dst: 73 | f_l: 74 | src: 75 | dst: 76 | link: link 77 | f_lc: 78 | src: 79 | dst: 80 | link: link_children 81 | profiles: 82 | p1: 83 | dotfiles: 84 | - f_x 85 | - f_y 86 | - f_z 87 | - f_l 88 | - f_lc 89 | _EOF 90 | 91 | echo "[+] install" 92 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 --verbose | grep '^5 dotfile(s) installed.$' 93 | [ "$?" != "0" ] && exit 1 94 | 95 | echo "OK" 96 | exit 0 97 | -------------------------------------------------------------------------------- /tests-ng/dotfile-no-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test dotfiles with no 'src' 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | #set -v 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # the dotfile source 51 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | mkdir -p ${tmps}/dotfiles 53 | echo "dotfiles source (dotpath): ${tmps}" 54 | # the dotfile destination 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | echo "dotfiles destination: ${tmpd}" 57 | 58 | clear_on_exit "${tmps}" 59 | clear_on_exit "${tmpd}" 60 | 61 | # create the config file 62 | cfg="${tmps}/config.yaml" 63 | 64 | cat > ${cfg} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: dotfiles 69 | dotfiles: 70 | abc: 71 | dst: ${tmpd}/abc 72 | profiles: 73 | p1: 74 | dotfiles: 75 | - ALL 76 | _EOF 77 | #cat ${cfg} 78 | 79 | # create the dotfiles 80 | echo "abc" > ${tmps}/dotfiles/abc 81 | 82 | ########################### 83 | # test install and compare 84 | ########################### 85 | 86 | # install 87 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 88 | [ "$?" != "0" ] && exit 1 89 | 90 | # checks 91 | [ ! -e ${tmpd}/abc ] && exit 1 92 | grep 'abc' ${tmpd}/abc 93 | 94 | echo "OK" 95 | exit 0 96 | -------------------------------------------------------------------------------- /tests-ng/dyndotfilepaths.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test dynamic variables in dotfile src/dst 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | dst=`echo ${tmpd} | rev` 62 | 63 | cat > ${cfg} << _EOF 64 | config: 65 | backup: true 66 | create: true 67 | dotpath: dotfiles 68 | dynvariables: 69 | dpath: echo ${dst} | rev 70 | dotfiles: 71 | f_abc: 72 | dst: "{{@@ dpath @@}}/abc" 73 | src: abc 74 | profiles: 75 | p1: 76 | dotfiles: 77 | - f_abc 78 | _EOF 79 | #cat ${cfg} 80 | 81 | # create the dotfile 82 | echo "{{@@ dpath @@}}" > ${tmps}/dotfiles/abc 83 | 84 | # install 85 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 86 | 87 | #cat ${tmpd}/abc 88 | 89 | [ ! -e ${tmpd}/abc ] && echo "abc not installed dynamically" && exit 1 90 | grep "^${tmpd}" ${tmpd}/abc >/dev/null 91 | 92 | #cat ${tmpd}/abc 93 | 94 | echo "OK" 95 | exit 0 96 | -------------------------------------------------------------------------------- /tests-ng/import-subfile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test import file in directory 6 | # after having imported directory 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | #echo "dotfile destination: ${tmpd}" 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the dotfile 60 | mkdir -p ${tmpd}/adir 61 | echo "first" > ${tmpd}/adir/file1 62 | 63 | # create the config file 64 | cfg="${tmps}/config.yaml" 65 | 66 | cat > ${cfg} << _EOF 67 | config: 68 | backup: true 69 | create: true 70 | dotpath: dotfiles 71 | dotfiles: 72 | profiles: 73 | _EOF 74 | #cat ${cfg} 75 | 76 | # import dir 77 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 -V ${tmpd}/adir 78 | 79 | # change the file 80 | echo "second" >> ${tmpd}/adir/file1 81 | 82 | # import file 83 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 -V ${tmpd}/adir/file1 84 | 85 | # test 86 | #cat ${tmps}/dotfiles/${tmpd}/adir/file1 87 | [ ! -e ${tmps}/dotfiles/${tmpd}/adir/file1 ] && echo "not exist" && exit 1 88 | grep 'second' ${tmps}/dotfiles/${tmpd}/adir/file1 >/dev/null 89 | 90 | echo "OK" 91 | exit 0 92 | -------------------------------------------------------------------------------- /docs/template/templating.md: -------------------------------------------------------------------------------- 1 | # Templating 2 | 3 | Dotdrop leverages the power of [Jinja2](https://palletsprojects.com/p/jinja/) to handle the 4 | templating of dotfiles. See [the Jinja2 templates docs](https://jinja.palletsprojects.com/en/2.11.x/templates/) 5 | or the below sections for more information on how to template your dotfiles. 6 | 7 | ## Templating or not templating 8 | 9 | The dotfile config entry [template](../config/config-dotfiles.md#dotfiles-block) 10 | and the global config entry [template_dotfile_default](../config/config-config.md) 11 | allow to control whether a dotfile is processed by the templating engine. 12 | 13 | Obviously, if the dotfile uses template directives, it needs to be templated. However, if it 14 | is not, disabling templating will speed up its installation (since it won't have to be 15 | processed by the engine). 16 | 17 | For dotfiles being symlinked (`absolute`, `relative` or `link_children`), see 18 | [the dedicated doc](../howto/symlink-dotfiles.md#templating-symlinked-dotfiles). 19 | 20 | ## Delimiters 21 | 22 | Dotdrop uses different delimiters than 23 | [Jinja2](https://palletsprojects.com/p/jinja/)'s defaults: 24 | 25 | * Block/statement start = `{%@@` 26 | * Block/statement end = `@@%}` 27 | * Variable/expression start = `{{@@` 28 | * Variable/expression end = `@@}}` 29 | * Comment start = `{#@@` 30 | * Comment end = `@@#}` 31 | 32 | More info in [Jinja2 templating docs](https://jinja.palletsprojects.com/en/2.11.x/templates/?highlight=delimiter) 33 | 34 | ## Importing macros 35 | 36 | Macros must be imported `with context` in order to have access to the variables: 37 | ``` 38 | {%@@ from 'macro_file' import macro with context @@%} 39 | ``` 40 | 41 | For more information, see the [dedicated Jinja2 docs](https://jinja.palletsprojects.com/en/2.11.x/templates/#macros). 42 | 43 | ## Dotdrop header 44 | 45 | Dotdrop is able to insert a header in the generated dotfiles. This allows 46 | to remind anyone opening the file for editing that this file is managed by dotdrop. 47 | 48 | Here's what it looks like: 49 | ```none 50 | This dotfile is managed using dotdrop 51 | ``` 52 | 53 | The header can be automatically added with: 54 | ```none 55 | {{@@ header() @@}} 56 | ``` 57 | 58 | Properly commenting the header in templates is the responsibility of the user, 59 | as [Jinja2](https://palletsprojects.com/p/jinja/) has no way of knowing what is the proper char(s) used for comments. 60 | Either prepend the directive with the commenting char(s) used in the dotfile 61 | (for example `# {{@@ header() @@}}`) or provide it as an argument `{{@@ header('# ') @@}}`. 62 | The results are equivalent. -------------------------------------------------------------------------------- /tests-ng/header.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test header 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | #echo "dotfile source: ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | #echo "dotfile destination: ${tmpd}" 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${tmps}/config.yaml" 62 | 63 | cat > ${cfg} << _EOF 64 | config: 65 | backup: true 66 | create: true 67 | dotpath: dotfiles 68 | dotfiles: 69 | f_abc: 70 | dst: ${tmpd}/abc 71 | src: abc 72 | profiles: 73 | p1: 74 | dotfiles: 75 | - f_abc 76 | _EOF 77 | #cat ${cfg} 78 | 79 | # create the dotfile 80 | echo "{{@@ header() @@}}" > ${tmps}/dotfiles/abc 81 | echo "{{@@ header('# ') @@}}" >> ${tmps}/dotfiles/abc 82 | echo "{{@@ header('// ') @@}}" >> ${tmps}/dotfiles/abc 83 | echo "test" >> ${tmps}/dotfiles/abc 84 | 85 | # install 86 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 87 | 88 | grep '^This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null 89 | grep '^# This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null 90 | grep '^// This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null 91 | 92 | #cat ${tmpd}/abc 93 | 94 | echo "OK" 95 | exit 0 96 | -------------------------------------------------------------------------------- /tests-ng/dotfiles-dyn-paths.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test dotfile dynamic paths 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | #set -v 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # the dotfile source 51 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | mkdir -p ${tmps}/dotfiles 53 | echo "dotfiles source (dotpath): ${tmps}" 54 | # the dotfile destination 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | echo "dotfiles destination: ${tmpd}" 57 | 58 | clear_on_exit "${tmps}" 59 | clear_on_exit "${tmpd}" 60 | 61 | # create the config file 62 | cfg="${tmps}/config.yaml" 63 | 64 | cat > ${cfg} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: dotfiles 69 | variables: 70 | dst: "${tmpd}/abc" 71 | dynvariables: 72 | src: "echo abc" 73 | dotfiles: 74 | f_abc: 75 | dst: "{{@@ dst @@}}" 76 | src: "{{@@ src @@}}" 77 | profiles: 78 | p1: 79 | dotfiles: 80 | - f_abc 81 | _EOF 82 | #cat ${cfg} 83 | 84 | # create the dotfiles 85 | echo "abc" > ${tmps}/dotfiles/abc 86 | 87 | ########################### 88 | # test install and compare 89 | ########################### 90 | 91 | # install 92 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 93 | [ "$?" != "0" ] && exit 1 94 | 95 | # checks 96 | [ ! -e ${tmpd}/abc ] && exit 1 97 | 98 | echo "OK" 99 | exit 0 100 | -------------------------------------------------------------------------------- /tests-ng/dotdrop-variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test dotdrop auto-added variables 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | #echo "dotfile source: ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | #echo "dotfile destination: ${tmpd}" 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${tmps}/config.yaml" 62 | 63 | cat > ${cfg} << _EOF 64 | config: 65 | backup: true 66 | create: true 67 | dotpath: dotfiles 68 | workdir: /tmp/xxx 69 | dotfiles: 70 | f_abc: 71 | dst: ${tmpd}/abc 72 | src: abc 73 | profiles: 74 | p1: 75 | dotfiles: 76 | - f_abc 77 | _EOF 78 | #cat ${cfg} 79 | 80 | # create the dotfile 81 | echo "dotpath: {{@@ _dotdrop_dotpath @@}}" > ${tmps}/dotfiles/abc 82 | echo "cfgpath: {{@@ _dotdrop_cfgpath @@}}" >> ${tmps}/dotfiles/abc 83 | echo "workdir: {{@@ _dotdrop_workdir @@}}" >> ${tmps}/dotfiles/abc 84 | 85 | # install 86 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 87 | 88 | cat ${tmpd}/abc 89 | 90 | grep "^dotpath: ${tmps}/dotfiles$" ${tmpd}/abc >/dev/null 91 | grep "^cfgpath: ${tmps}/config.yaml$" ${tmpd}/abc >/dev/null 92 | grep "^workdir: /tmp/xxx$" ${tmpd}/abc >/dev/null 93 | 94 | echo "OK" 95 | exit 0 96 | -------------------------------------------------------------------------------- /tests-ng/dotfile-variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test dotfile specific variables 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | cat > ${cfg} << _EOF 62 | config: 63 | backup: true 64 | create: true 65 | dotpath: dotfiles 66 | dotfiles: 67 | f_abc: 68 | dst: ${tmpd}/abc 69 | src: abc 70 | profiles: 71 | p1: 72 | dotfiles: 73 | - f_abc 74 | _EOF 75 | #cat ${cfg} 76 | 77 | # create the dotfile 78 | echo 'src:{{@@ _dotfile_abs_src @@}}' > ${tmps}/dotfiles/abc 79 | echo 'dst:{{@@ _dotfile_abs_dst @@}}' >> ${tmps}/dotfiles/abc 80 | echo 'key:{{@@ _dotfile_key @@}}' >> ${tmps}/dotfiles/abc 81 | echo 'link:{{@@ _dotfile_link @@}}' >> ${tmps}/dotfiles/abc 82 | 83 | # install 84 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 85 | 86 | # checks 87 | [ ! -e ${tmpd}/abc ] && echo 'dotfile not installed' && exit 1 88 | cat ${tmpd}/abc 89 | grep "src:${tmps}/dotfiles/abc" ${tmpd}/abc >/dev/null 90 | grep "dst:${tmpd}/abc" ${tmpd}/abc >/dev/null 91 | grep "key:f_abc" ${tmpd}/abc >/dev/null 92 | grep "link:nolink" ${tmpd}/abc >/dev/null 93 | 94 | echo "OK" 95 | exit 0 96 | -------------------------------------------------------------------------------- /tests-ng/link-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test link of templates 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | echo "dotfiles source (dotpath): ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | echo "dotfiles destination: ${tmpd}" 56 | # the workdir 57 | tmpw=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 58 | export DOTDROP_WORKDIR="${tmpw}" 59 | echo "workdir: ${tmpw}" 60 | 61 | clear_on_exit "${tmps}" 62 | clear_on_exit "${tmpd}" 63 | clear_on_exit "${tmpw}" 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | 68 | cat > ${cfg} << _EOF 69 | config: 70 | backup: true 71 | create: true 72 | dotpath: dotfiles 73 | workdir: ${tmpw} 74 | dotfiles: 75 | f_abc: 76 | dst: ${tmpd}/abc 77 | src: abc 78 | link: true 79 | profiles: 80 | p1: 81 | dotfiles: 82 | - f_abc 83 | _EOF 84 | #cat ${cfg} 85 | 86 | # create the dotfile 87 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/abc 88 | echo "blabla" >> ${tmps}/dotfiles/abc 89 | 90 | # install 91 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 92 | 93 | # checks 94 | [ ! -e ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1 95 | [ ! -h ${tmpd}/abc ] && echo "[ERROR] dotfile is not a symlink" && exit 1 96 | 97 | echo "OK" 98 | exit 0 99 | -------------------------------------------------------------------------------- /tests-ng/helpers: -------------------------------------------------------------------------------- 1 | # author: deadc0de6 (https://github.com/deadc0de6) 2 | # Copyright (c) 2017, deadc0de6 3 | # 4 | # file to be sourced from test scripts 5 | # 6 | # for i in *.sh; do ./$i >/dev/null 2>&1; find /tmp/ -maxdepth 1 -type f -iname 'tmp*' >> /tmp/$i.log; find /tmp/ -maxdepth 1 -type d -iname 'tmp.*-dotdrop-tests' >> /tmp/$i.log; find /tmp/ -maxdepth 1 -type d -iname 'dotdrop-*' >> /tmp/$i.log; wc -l /tmp/$i.log; [ "`wc -l /tmp/$i.log | awk '{print $1}'`" -gt "0" ] && break; done 7 | 8 | declare -a to_be_cleared 9 | 10 | # add a file/directory to be cleared 11 | # on exit 12 | # 13 | # $1: file path to clear 14 | clear_on_exit() 15 | { 16 | local len="${#to_be_cleared[*]}" 17 | to_be_cleared[${len}]="$1" 18 | if [ "${len}" = "0" ]; then 19 | # set trap 20 | trap on_exit EXIT 21 | fi 22 | } 23 | 24 | # clear files 25 | on_exit() 26 | { 27 | for i in "${to_be_cleared[@]}"; do 28 | rm -rf "${i}" 29 | done 30 | } 31 | 32 | # create a directory with sub-dirs and file 33 | # for tests 34 | # 35 | # $1: path of the parent directory to create 36 | # ret: set the variable token that allows to check 37 | create_dir() 38 | { 39 | dirs="a/aa a/ab a/ac b/ba c" 40 | mkdir -p ${1} 41 | for d in ${dirs}; do 42 | # create some dirs 43 | mkdir -p ${1}/${d} 44 | # create some files 45 | fn=`echo ${d} | sed 's#/#-#g'` 46 | f="${1}/${d}/${fn}" 47 | echo "${d}" > ${f} 48 | token=${f} 49 | done 50 | } 51 | 52 | # create a clean config file 53 | # 54 | # $1: path to save to 55 | create_conf() 56 | { 57 | cat > ${1} << _EOF 58 | config: 59 | backup: true 60 | create: true 61 | dotpath: dotfiles 62 | dotfiles: 63 | profiles: 64 | _EOF 65 | } 66 | 67 | # osx tricks 68 | # brew install coreutils gnu-sed 69 | if [[ $OSTYPE == 'darwin'* ]]; then 70 | mktemp() { 71 | gmktemp "$@" 72 | } 73 | stat() { 74 | gstat "$@" 75 | } 76 | sed() { 77 | gsed "$@" 78 | } 79 | wc() { 80 | gwc "$@" 81 | } 82 | date() { 83 | gdate "$@" 84 | } 85 | chmod() { 86 | gchmod "$@" 87 | } 88 | readlink() { 89 | greadlink "$@" 90 | } 91 | realpath() { 92 | grealpath "$@" 93 | } 94 | 95 | export -f mktemp 96 | export -f stat 97 | export -f sed 98 | export -f wc 99 | export -f date 100 | export -f chmod 101 | export -f readlink 102 | export -f realpath 103 | fi 104 | 105 | # workdir tricks 106 | # when tests are called without using the 107 | # top level tests.sh script which sets the workdir 108 | if [ -z "${DOTDROP_WORKDIR}" ]; then 109 | _workdir="/tmp/dotdrop-test-workdir" 110 | export DOTDROP_WORKDIR="${_workdir}" 111 | clear_on_exit "${_workdir}" 112 | fi -------------------------------------------------------------------------------- /tests-ng/macro-with-globals.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # import variables from file 6 | # 7 | 8 | # exit on first error 9 | set -e 10 | 11 | # all this crap to get current path 12 | rl="readlink -f" 13 | if ! ${rl} "${0}" >/dev/null 2>&1; then 14 | rl="realpath" 15 | 16 | if ! hash ${rl}; then 17 | echo "\"${rl}\" not found !" && exit 1 18 | fi 19 | fi 20 | cur=$(dirname "$(${rl} "${0}")") 21 | 22 | #hash dotdrop >/dev/null 2>&1 23 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 24 | 25 | #echo "called with ${1}" 26 | 27 | # dotdrop path can be pass as argument 28 | ddpath="${cur}/../" 29 | [ "${1}" != "" ] && ddpath="${1}" 30 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 31 | 32 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 33 | bin="python3 -m dotdrop.dotdrop" 34 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 35 | 36 | echo "dotdrop path: ${ddpath}" 37 | echo "pythonpath: ${PYTHONPATH}" 38 | 39 | # get the helpers 40 | source ${cur}/helpers 41 | 42 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 43 | 44 | ################################################################ 45 | # this is the test 46 | ################################################################ 47 | 48 | # the dotfile source 49 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 50 | mkdir -p ${tmps}/dotfiles 51 | # the dotfile destination 52 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 53 | 54 | clear_on_exit "${tmps}" 55 | clear_on_exit "${tmpd}" 56 | 57 | # create the config file 58 | cfg="${tmps}/config.yaml" 59 | 60 | cat > ${cfg} << _EOF 61 | config: 62 | backup: true 63 | create: true 64 | dotpath: dotfiles 65 | dotfiles: 66 | f_abc: 67 | dst: ${tmpd}/abc 68 | src: abc 69 | profiles: 70 | p0: 71 | dotfiles: 72 | - f_abc 73 | variables: 74 | global: global_var 75 | local: local_var 76 | _EOF 77 | 78 | # create the source 79 | mkdir -p ${tmps}/dotfiles/ 80 | 81 | cat > ${tmps}/dotfiles/macro_file << _EOF 82 | {%@@ macro macro(var) @@%} 83 | {{@@ global @@}} 84 | {{@@ var @@}} 85 | {%@@ endmacro @@%} 86 | _EOF 87 | 88 | cat > ${tmps}/dotfiles/abc << _EOF 89 | {%@@ from 'macro_file' import macro with context @@%} 90 | {{@@ macro(local) @@}} 91 | _EOF 92 | 93 | # install 94 | cd ${ddpath} | ${bin} install -c ${cfg} -p p0 -V -f 95 | 96 | # test file content 97 | cat ${tmpd}/abc 98 | grep 'global_var' ${tmpd}/abc >/dev/null 2>&1 99 | grep 'local_var' ${tmpd}/abc >/dev/null 2>&1 100 | 101 | echo "OK" 102 | exit 0 103 | -------------------------------------------------------------------------------- /tests-ng/install-to-temp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test install to temp 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${basedir}/dotfiles 52 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 53 | echo "[+] dotdrop dir: ${basedir}" 54 | echo "[+] dotpath dir: ${basedir}/dotfiles" 55 | 56 | clear_on_exit "${basedir}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the config file 60 | cfg="${basedir}/config.yaml" 61 | cat > ${cfg} << _EOF 62 | config: 63 | backup: true 64 | create: true 65 | dotpath: dotfiles 66 | dotfiles: 67 | f_x: 68 | src: x 69 | dst: ${tmpd}/x 70 | f_y: 71 | src: y 72 | dst: ${tmpd}/y 73 | link: link 74 | f_z: 75 | src: z 76 | dst: ${tmpd}/z 77 | profiles: 78 | p1: 79 | dotfiles: 80 | - f_x 81 | - f_y 82 | - f_z 83 | _EOF 84 | 85 | echo 'test_x' > ${basedir}/dotfiles/x 86 | echo 'test_y' > ${basedir}/dotfiles/y 87 | echo "00000000 01 02 03 04 05" | xxd -r - ${basedir}/dotfiles/z 88 | 89 | echo "[+] install" 90 | log="${basedir}/log" 91 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 --showdiff --verbose --temp > ${log} 92 | 93 | tmpfile=`cat ${basedir}/log | grep 'installed to tmp ' | sed 's/^.*to tmp "\(.*\)"./\1/'` 94 | echo "tmpfile: ${tmpfile}" 95 | clear_on_exit "${tmpfile}" 96 | 97 | cat ${log} | grep '^3 dotfile(s) installed.$' 98 | [ "$?" != "0" ] && exit 1 99 | 100 | echo "OK" 101 | exit 0 102 | -------------------------------------------------------------------------------- /tests-ng/link-import-default.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test the use of the keyword "link_on_import" 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | # create the source 62 | echo "abc" > ${tmpd}/abc 63 | 64 | # import with nolink by default 65 | cat > ${cfg} << _EOF 66 | config: 67 | backup: true 68 | create: true 69 | dotpath: dotfiles 70 | link_on_import: nolink 71 | dotfiles: 72 | profiles: 73 | _EOF 74 | 75 | # import 76 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 -V ${tmpd}/abc 77 | 78 | # checks 79 | inside="${tmps}/dotfiles/${tmpd}/abc" 80 | [ ! -e ${inside} ] && exit 1 81 | 82 | set +e 83 | cat ${cfg} | grep 'link:' && exit 1 84 | set -e 85 | 86 | # import with parent by default 87 | cat > ${cfg} << _EOF 88 | config: 89 | backup: true 90 | create: true 91 | dotpath: dotfiles 92 | link_on_import: link 93 | dotfiles: 94 | profiles: 95 | _EOF 96 | 97 | # import 98 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 -V ${tmpd}/abc 99 | 100 | # checks 101 | inside="${tmps}/dotfiles/${tmpd}/abc" 102 | [ ! -e ${inside} ] && exit 1 103 | 104 | cat ${cfg} 105 | cat ${cfg} | grep 'link: absolute' >/dev/null 106 | 107 | echo "OK" 108 | exit 0 109 | -------------------------------------------------------------------------------- /tests-ng/include-variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test the use of the keyword "include" 6 | # and (dyn)variables precedence 7 | # returns 1 in case of error 8 | # 9 | 10 | # exit on first error 11 | set -e 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # the dotfile source 51 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | mkdir -p ${tmps}/dotfiles 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the config file 60 | cfg="${tmps}/config.yaml" 61 | 62 | cat > ${cfg} << _EOF 63 | config: 64 | backup: true 65 | create: true 66 | dotpath: dotfiles 67 | variables: 68 | var: nopv 69 | dynvariables: 70 | dvar: "echo nopdv" 71 | dotfiles: 72 | f_abc: 73 | dst: ${tmpd}/abc 74 | src: abc 75 | profiles: 76 | p0: 77 | variables: 78 | var: p0v 79 | dynvariables: 80 | dvar: "echo p0dv" 81 | include: 82 | - p1 83 | p1: 84 | dotfiles: 85 | - f_abc 86 | variables: 87 | var: p1v 88 | dynvariables: 89 | dvar: "echo p1dv" 90 | _EOF 91 | #cat ${cfg} 92 | 93 | # create the source 94 | mkdir -p ${tmps}/dotfiles/ 95 | echo "head" > ${tmps}/dotfiles/abc 96 | echo "{{@@ var @@}}" >> ${tmps}/dotfiles/abc 97 | echo "{{@@ dvar @@}}" >> ${tmps}/dotfiles/abc 98 | echo "tail" >> ${tmps}/dotfiles/abc 99 | 100 | # install 101 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p0 --verbose 102 | 103 | #cat ${tmpd}/abc 104 | grep 'p0v' ${tmpd}/abc 105 | grep 'p0dv' ${tmpd}/abc 106 | 107 | echo "OK" 108 | exit 0 109 | -------------------------------------------------------------------------------- /tests-ng/import-ignore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2020, deadc0de6 4 | # 5 | # test ignore import 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # $1 pattern 50 | # $2 path 51 | grep_or_fail() 52 | { 53 | grep "${1}" "${2}" >/dev/null 2>&1 || (echo "pattern not found in ${2}" && exit 1) 54 | } 55 | 56 | # the dotfile source 57 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 58 | mkdir -p ${tmps}/dotfiles 59 | # the dotfile destination 60 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 61 | mkdir -p ${tmpd} 62 | #echo "dotfile destination: ${tmpd}" 63 | 64 | clear_on_exit "${tmps}" 65 | clear_on_exit "${tmpd}" 66 | 67 | # dotdrop directory 68 | mkdir -p ${tmpd}/a/{b,c} 69 | echo 'a' > ${tmpd}/a/b/abfile 70 | echo 'a' > ${tmpd}/a/c/acfile 71 | echo 'a' > ${tmpd}/a/b/newfile 72 | mkdir -p ${tmpd}/a/newdir 73 | echo 'a' > ${tmpd}/a/newdir/newfile 74 | 75 | # create the config file 76 | cfg="${tmps}/config.yaml" 77 | cat > ${cfg} << _EOF 78 | config: 79 | backup: false 80 | create: true 81 | dotpath: dotfiles 82 | impignore: 83 | - "*/cfile" 84 | - "*/newfile" 85 | - "newdir" 86 | dotfiles: 87 | profiles: 88 | _EOF 89 | #cat ${cfg} 90 | 91 | # import 92 | echo "[+] import" 93 | cd ${ddpath} | ${bin} import -c ${cfg} -f --verbose --profile=p1 ${tmpd}/a 94 | 95 | [ -d ${tmps}/dotfiles/newdir ] && echo "newdir not ignored" && exit 1 96 | [ -e ${tmps}/dotfiles/newdir/newfile ] && echo "newfile not ignored" && exit 1 97 | [ -e ${tmps}/dotfiles/a/b/newfile ] && echo "newfile not ignored" && exit 1 98 | 99 | echo "OK" 100 | exit 0 101 | -------------------------------------------------------------------------------- /tests-ng/toml.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | # 5 | # test toml config 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmp=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | tmpf="${tmp}/dotfiles" 52 | mkdir -p ${tmpf} 53 | echo "dotfiles source (dotpath): ${tmpf}" 54 | 55 | # create the config file 56 | cfg="${tmp}/config.toml" 57 | echo "config file: ${cfg}" 58 | 59 | # the dotfile destination 60 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 61 | echo "dotfiles destination: ${tmpd}" 62 | 63 | clear_on_exit "${tmp}" 64 | clear_on_exit "${tmpd}" 65 | 66 | ## RELATIVE 67 | cat > ${cfg} << _EOF 68 | [config] 69 | backup = true 70 | create = true 71 | dotpath = "dotfiles" 72 | 73 | [dotfiles.f_abc] 74 | dst = "${tmpd}/abc" 75 | src = "abc" 76 | link = true 77 | 78 | [profiles.p1] 79 | dotfiles = [ "f_abc",] 80 | _EOF 81 | #cat ${cfg} 82 | 83 | # create the dotfile 84 | echo "{{@@ profile @@}}" > ${tmpf}/abc 85 | echo "{{@@ profile @@}}" > ${tmpd}/def 86 | 87 | # install 88 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 89 | [ ! -e ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1 90 | 91 | # import 92 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 -b -V ${tmpd}/def 93 | [ ! -e ${tmpf}${tmpd}/def ] && echo "[ERROR] dotfile not imported" && exit 1 94 | 95 | # checks 96 | cnt=$(cd ${ddpath} | ${bin} files -G -c ${cfg} -p p1 -V | grep '^f_' | wc -l) 97 | [ "${cnt}" != "2" ] && echo "[ERROR]" && exit 1 98 | 99 | ## CLEANING 100 | rm -rf ${tmp} ${tmpd} 101 | 102 | echo "OK" 103 | exit 0 104 | -------------------------------------------------------------------------------- /tests-ng/imported-variables-from-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: davla (https://github.com/davls) 3 | # Copyright (c) 2020, davla 4 | # 5 | # test variables imported from config and used in the importing yaml config 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | subcfg="${tmps}/subconfig.yaml" 61 | 62 | cat > ${cfg} << _EOF 63 | config: 64 | backup: true 65 | create: true 66 | dotpath: dotfiles 67 | import_configs: 68 | - ${subcfg} 69 | dotfiles: 70 | f_abc: 71 | dst: ${tmpd}/abc 72 | src: '{{@@ abc_dyn_src @@}}{{@@ abc_src @@}}' 73 | profiles: 74 | p1: 75 | dotfiles: 76 | - f_abc 77 | _EOF 78 | cat ${cfg} 79 | 80 | # create the subconfig file 81 | cat > ${subcfg} << _EOF 82 | config: 83 | backup: true 84 | create: true 85 | dotpath: dotfiles 86 | variables: 87 | abc_src: c 88 | dynvariables: 89 | abc_dyn_src: 'echo ab' 90 | dotfiles: [] 91 | profiles: [] 92 | _EOF 93 | 94 | # create the dotfile 95 | dirname ${tmps}/dotfiles/abc | xargs mkdir -p 96 | cat > ${tmps}/dotfiles/abc << _EOF 97 | Hell yeah 98 | _EOF 99 | 100 | # install 101 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 102 | 103 | # test file existence and content 104 | [ -f "${tmpd}/abc" ] || { 105 | echo 'Dotfile not installed' 106 | exit 1 107 | } 108 | 109 | echo "OK" 110 | exit 0 111 | -------------------------------------------------------------------------------- /tests-ng/update-ignore-relative.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test ignore update relative pattern 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | dt="${tmps}/dotfiles" 52 | mkdir -p ${dt} 53 | mkdir -p ${dt}/a/{b,c} 54 | echo 'a' > ${dt}/a/b/abfile 55 | echo 'a' > ${dt}/a/c/acfile 56 | 57 | # fs dotfiles 58 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 59 | 60 | clear_on_exit "${tmps}" 61 | clear_on_exit "${tmpd}" 62 | 63 | cp -r ${dt}/a ${tmpd}/ 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | cat > ${cfg} << _EOF 68 | config: 69 | backup: false 70 | create: true 71 | dotpath: dotfiles 72 | dotfiles: 73 | f_abc: 74 | dst: ${tmpd}/a 75 | src: a 76 | upignore: 77 | - "cfile" 78 | - "newfile" 79 | - "newdir" 80 | profiles: 81 | p1: 82 | dotfiles: 83 | - f_abc 84 | _EOF 85 | #cat ${cfg} 86 | 87 | #tree ${dt} 88 | 89 | # edit/add files 90 | echo "[+] edit/add files" 91 | touch ${tmpd}/a/newfile 92 | echo 'b' > ${tmpd}/a/c/acfile 93 | mkdir -p ${tmpd}/a/newdir/b 94 | touch ${tmpd}/a/newdir/b/c 95 | 96 | #tree ${tmpd}/a 97 | 98 | # update 99 | echo "[+] update" 100 | cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=p1 --key f_abc 101 | 102 | #tree ${dt} 103 | 104 | # check files haven't been updated 105 | grep 'b' ${dt}/a/c/acfile >/dev/null || (echo "b not found" && exit 1) 106 | [ -e ${dt}/a/newfile ] && echo "new file does not exist" && exit 1 107 | 108 | echo "OK" 109 | exit 0 110 | -------------------------------------------------------------------------------- /tests-ng/duplicate-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test duplicate keys 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | cat > ${cfg} << _EOF 62 | config: 63 | backup: true 64 | create: true 65 | dotpath: dotfiles 66 | dotfiles: 67 | f_abc: 68 | dst: ${tmpd}/abc 69 | src: abc 70 | profiles: 71 | p1: 72 | dotfiles: 73 | - f_abc 74 | _EOF 75 | #cat ${cfg} 76 | 77 | # create the imported one 78 | mkdir -p ${tmps}/dotfiles/${tmpd} 79 | echo "test" > ${tmps}/dotfiles/${tmpd}/abc 80 | echo "test" > ${tmpd}/abc 81 | 82 | # create the to-be-imported 83 | mkdir -p ${tmpd}/sub 84 | echo "test2" > ${tmpd}/sub/abc 85 | 86 | mkdir -p ${tmpd}/sub/sub2 87 | echo "test2" > ${tmpd}/sub/sub2/abc 88 | 89 | mkdir -p ${tmpd}/sub/sub 90 | echo "test2" > ${tmpd}/sub/sub/abc 91 | 92 | # import 93 | cd ${ddpath} | ${bin} import -f --verbose -c ${cfg} -p p2 \ 94 | ${tmpd}/abc \ 95 | ${tmpd}/sub/abc \ 96 | ${tmpd}/sub/abc \ 97 | ${tmpd}/sub/sub/abc \ 98 | ${tmpd}/sub/sub2/abc 99 | 100 | # count dotfiles for p2 101 | cnt=`cd ${ddpath} | ${bin} files --verbose -c ${cfg} -p p2 -b | grep '^f_' | wc -l` 102 | [ "${cnt}" != "4" ] && echo "bad count for p2: ${cnt} != 4" && exit 1 103 | 104 | echo "OK" 105 | exit 0 106 | -------------------------------------------------------------------------------- /tests-ng/tests-launcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2020, deadc0de6 4 | # 5 | # tests launcher 6 | # 7 | 8 | 9 | import os 10 | import sys 11 | import subprocess 12 | from concurrent import futures 13 | from halo import Halo 14 | 15 | 16 | MAX_JOBS = 10 17 | LOG_FILE = '/tmp/dotdrop-tests-launcher.log' 18 | 19 | 20 | def run_test(logfd, path): 21 | cur = os.path.dirname(sys.argv[0]) 22 | name = os.path.basename(path) 23 | path = os.path.join(cur, name) 24 | 25 | if logfd: 26 | logfd.write('starting test {}\n'.format(path)) 27 | p = subprocess.Popen(path, shell=False, 28 | stdout=subprocess.PIPE, 29 | stderr=subprocess.STDOUT) 30 | out, _ = p.communicate() 31 | out = out.decode() 32 | r = p.returncode == 0 33 | if logfd: 34 | logfd.write('done test {}\n'.format(path)) 35 | reason = 'returncode' 36 | if 'Traceback' in out: 37 | r = False 38 | reason = 'traceback' 39 | return r, reason, path, out 40 | 41 | 42 | def get_tests(): 43 | tests = [] 44 | cur = os.path.dirname(sys.argv[0]) 45 | for (_, _, filenames) in os.walk(cur): 46 | for path in filenames: 47 | if not path.endswith('.sh'): 48 | continue 49 | tests.append(path) 50 | break 51 | return tests 52 | 53 | 54 | def main(): 55 | global MAX_JOBS 56 | if len(sys.argv) > 1: 57 | MAX_JOBS = int(sys.argv[1]) 58 | 59 | tests = get_tests() 60 | 61 | fd = open(LOG_FILE, 'w') 62 | fd.write('start with {} jobs\n'.format(MAX_JOBS)) 63 | fd.flush() 64 | 65 | print() 66 | spinner = Halo(text='Testing', spinner='bouncingBall') 67 | spinner.start() 68 | with futures.ThreadPoolExecutor(max_workers=MAX_JOBS) as ex: 69 | wait_for = [] 70 | for test in tests: 71 | j = ex.submit(run_test, fd, test) 72 | wait_for.append(j) 73 | fd.flush() 74 | 75 | for f in futures.as_completed(wait_for): 76 | r, reason, p, log = f.result() 77 | fd.flush() 78 | if not r: 79 | ex.shutdown(wait=False) 80 | for x in wait_for: 81 | x.cancel() 82 | print() 83 | print(log) 84 | print('test {} failed ({})'.format(p, reason)) 85 | fd.close() 86 | return False 87 | #else: 88 | # sys.stdout.write('.') 89 | # sys.stdout.flush() 90 | sys.stdout.write('\n') 91 | spinner.stop() 92 | print() 93 | fd.write('done with {} jobs\n'.format(MAX_JOBS)) 94 | fd.close() 95 | return True 96 | 97 | 98 | if __name__ == '__main__': 99 | if not main(): 100 | sys.exit(1) 101 | sys.exit(0) 102 | -------------------------------------------------------------------------------- /tests-ng/global-update-ignore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test global ignore update 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | dt="${tmps}/dotfiles" 52 | mkdir -p ${dt} 53 | mkdir -p ${dt}/a/{b,c} 54 | echo 'a' > ${dt}/a/b/abfile 55 | echo 'a' > ${dt}/a/c/acfile 56 | 57 | # fs dotfiles 58 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 59 | cp -r ${dt}/a ${tmpd}/ 60 | 61 | clear_on_exit "${tmps}" 62 | clear_on_exit "${tmpd}" 63 | 64 | # create the config file 65 | cfg="${tmps}/config.yaml" 66 | cat > ${cfg} << _EOF 67 | config: 68 | backup: false 69 | create: true 70 | dotpath: dotfiles 71 | upignore: 72 | - "*/cfile" 73 | - "*/newfile" 74 | - "*/newdir" 75 | dotfiles: 76 | f_abc: 77 | dst: ${tmpd}/a 78 | src: a 79 | profiles: 80 | p1: 81 | dotfiles: 82 | - f_abc 83 | _EOF 84 | #cat ${cfg} 85 | 86 | #tree ${dt} 87 | 88 | # edit/add files 89 | echo "[+] edit/add files" 90 | touch ${tmpd}/a/newfile 91 | echo 'b' > ${tmpd}/a/c/acfile 92 | mkdir -p ${tmpd}/a/newdir/b 93 | touch ${tmpd}/a/newdir/b/c 94 | 95 | #tree ${tmpd}/a 96 | 97 | # update 98 | echo "[+] update" 99 | cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=p1 --key f_abc 100 | 101 | #tree ${dt} 102 | 103 | # check files haven't been updated 104 | [ ! -e ${dt}/a/c/acfile ] && echo "acfile not found" && exit 1 105 | set +e 106 | grep 'b' ${dt}/a/c/acfile || (echo "acfile not updated" && exit 1) 107 | set -e 108 | [ -e ${dt}/a/newfile ] && echo "newfile found" && exit 1 109 | 110 | echo "OK" 111 | exit 0 112 | -------------------------------------------------------------------------------- /tests-ng/update-ignore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test ignore update 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # $1 pattern 50 | # $2 path 51 | grep_or_fail() 52 | { 53 | grep "${1}" "${2}" >/dev/null 2>&1 || (echo "pattern not found in ${2}" && exit 1) 54 | } 55 | 56 | # dotdrop directory 57 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 58 | dt="${tmps}/dotfiles" 59 | mkdir -p ${dt} 60 | mkdir -p ${dt}/a/{b,c} 61 | echo 'a' > ${dt}/a/b/abfile 62 | echo 'a' > ${dt}/a/c/acfile 63 | 64 | # fs dotfiles 65 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 66 | 67 | clear_on_exit "${tmps}" 68 | clear_on_exit "${tmpd}" 69 | 70 | cp -r ${dt}/a ${tmpd}/ 71 | 72 | # create the config file 73 | cfg="${tmps}/config.yaml" 74 | cat > ${cfg} << _EOF 75 | config: 76 | backup: false 77 | create: true 78 | dotpath: dotfiles 79 | dotfiles: 80 | f_abc: 81 | dst: ${tmpd}/a 82 | src: a 83 | upignore: 84 | - "*/cfile" 85 | - "*/newfile" 86 | - "*/newdir" 87 | profiles: 88 | p1: 89 | dotfiles: 90 | - f_abc 91 | _EOF 92 | #cat ${cfg} 93 | 94 | #tree ${dt} 95 | 96 | # edit/add files 97 | echo "[+] edit/add files" 98 | touch ${tmpd}/a/newfile 99 | echo 'b' > ${tmpd}/a/c/acfile 100 | mkdir -p ${tmpd}/a/newdir/b 101 | touch ${tmpd}/a/newdir/b/c 102 | 103 | # update 104 | echo "[+] update" 105 | cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=p1 --key f_abc 106 | 107 | # check files haven't been updated 108 | grep_or_fail 'b' "${dt}/a/c/acfile" 109 | [ -e ${dt}/a/newfile ] && echo "should not have been updated" && exit 1 110 | 111 | echo "OK" 112 | exit 0 113 | -------------------------------------------------------------------------------- /tests-ng/double-config-import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: davla (https://github.com/davla) 3 | # Copyright (c) 2022, deadc0de6 4 | # 5 | # test error report on importing the same sub-config file more than once 6 | # 7 | 8 | # exit on first error 9 | set -e 10 | 11 | # all this crap to get current path 12 | rl="readlink -f" 13 | if ! ${rl} "${0}" >/dev/null 2>&1; then 14 | rl="realpath" 15 | 16 | if ! hash ${rl}; then 17 | echo "\"${rl}\" not found !" && exit 1 18 | fi 19 | fi 20 | cur=$(dirname "$(${rl} "${0}")") 21 | 22 | #hash dotdrop >/dev/null 2>&1 23 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 24 | 25 | #echo "called with ${1}" 26 | 27 | # dotdrop path can be pass as argument 28 | ddpath="${cur}/../" 29 | [ "${1}" != "" ] && ddpath="${1}" 30 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 31 | 32 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 33 | bin="python3 -m dotdrop.dotdrop" 34 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 35 | 36 | echo "dotdrop path: ${ddpath}" 37 | echo "pythonpath: ${PYTHONPATH}" 38 | 39 | # get the helpers 40 | source ${cur}/helpers 41 | 42 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 43 | 44 | ################################################################ 45 | # this is the test 46 | ################################################################ 47 | 48 | # dotfile source path 49 | src="$(mktemp -d --suffix='-dotdrop-tests' || mktemp -d)" 50 | mkdir -p "${src}/dotfiles" 51 | clear_on_exit "${src}" 52 | 53 | # dotfile destination 54 | dst="$(mktemp -d --suffix='-dotdrop-tests' || mktemp -d)" 55 | clear_on_exit "${dst}" 56 | error_log="${dst}/error.log" 57 | 58 | # bottom-level 59 | bottom_level_cfg="${src}/bottom-level.yaml" 60 | cat > ${bottom_level_cfg} << _EOF 61 | config: 62 | backup: true 63 | create: true 64 | dotpath: ${src}/dotfiles 65 | 66 | dotfiles: [] 67 | profiles: [] 68 | _EOF 69 | touch "${src}/dotfiles/bottom" 70 | 71 | # mid-level 72 | mid_level_cfg="${src}/mid-level.yaml" 73 | cat > ${mid_level_cfg} << _EOF 74 | config: 75 | backup: true 76 | create: true 77 | dotpath: ${src}/dotfiles 78 | import_configs: 79 | - ${bottom_level_cfg} 80 | 81 | dotfiles: [] 82 | 83 | profiles: [] 84 | _EOF 85 | 86 | # top-level 87 | top_level_cfg="${src}/top-level.yaml" 88 | cat > ${top_level_cfg} << _EOF 89 | config: 90 | backup: true 91 | create: true 92 | dotpath: ${src}/dotfiles 93 | import_configs: 94 | - ${mid_level_cfg} 95 | - ${bottom_level_cfg} 96 | 97 | dotfiles: [] 98 | 99 | profiles: [] 100 | _EOF 101 | 102 | # install 103 | set +e 104 | cd ${ddpath} | ${bin} install -f -c ${top_level_cfg} -p top-level 2> "${error_log}" 105 | set -e 106 | 107 | # checks 108 | grep "${bottom_level_cfg} imported more than once in ${top_level_cfg}" "${error_log}" > /dev/null 2>&1 109 | 110 | echo "OK" 111 | exit 0 112 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '27 3 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /docs/config/config-actions.md: -------------------------------------------------------------------------------- 1 | # Actions entry 2 | 3 | The **actions** entry (optional) contains an actions mapping. 4 | 5 | ```yaml 6 | actions: 7 | : 8 | ``` 9 | 10 | *pre* actions: 11 | ```yaml 12 | actions: 13 | pre: 14 | : 15 | ``` 16 | 17 | *post* actions: 18 | ```yaml 19 | actions: 20 | post: 21 | : 22 | ``` 23 | 24 | Actions can be either `post` or `pre`. 25 | 26 | * `post` action will be executed after the dotfile deployment. 27 | * `pre` action will be executed before the dotfile deployment. 28 | 29 | If you don't specify either `post` or `pre`, the action will be executed 30 | after the dotfile deployment (which is equivalent to `post`). 31 | Actions cannot obviously be named `pre` or `post`. 32 | 33 | Four types of actions can be defined: 34 | 35 | * [Dotfiles actions](config-dotfiles.md#dotfile-actions) 36 | * [Default actions](config-config.md#default_actions-entry) 37 | * [Profile actions](config-profiles.md#profile-actions-entry) 38 | * [Fake dotfiles and actions](config-actions.md#fake-dotfile-and-actions) 39 | 40 | **Notes**: 41 | 42 | * 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. 43 | * Make sure to quote your actions to avoid bad surprises 44 | * Actions are executed using the default shell (`$SHELL`) 45 | * To use shell variables in your actions, you need to escape the curly brackets (`${HOME}` becomes `${{HOME}}`) 46 | 47 | ## Fake dotfile and actions 48 | 49 | *Fake* dotfile can be created by specifying no `dst` and no `src` (see [Fake dotfiles and actions](config-actions.md#fake-dotfile-and-actions)). 50 | By binding an action to such a *fake* dotfile, you make sure the action is always executed since 51 | *fake* dotfile are always considered installed. 52 | 53 | ```yaml 54 | actions: 55 | always_action: 'date > ~/.dotdrop.log' 56 | dotfiles: 57 | fake: 58 | src: 59 | dst: 60 | actions: 61 | - always_action 62 | ``` 63 | 64 | ## Dynamic actions 65 | 66 | Variables ([config variables and dynvariables](config-file.md#variables) 67 | and [template variables](../template/template-variables.md)) can be used 68 | in actions for more advanced use-cases. 69 | 70 | ```yaml 71 | dotfiles: 72 | f_test: 73 | dst: ~/.test 74 | src: test 75 | actions: 76 | - cookie_mv_somewhere "/tmp/moved-cookie" 77 | variables: 78 | cookie_dir_available: (test -d /tmp/cookiedir || mkdir -p /tmp/cookiedir) 79 | cookie_header: "{{@@ cookie_dir_available @@}} && echo 'header' > /tmp/cookiedir/cookie" 80 | cookie_mv: "{{@@ cookie_header @@}} && mv /tmp/cookiedir/cookie" 81 | actions: 82 | cookie_mv_somewhere: "{{@@ cookie_mv @@}} {0}" 83 | ``` 84 | 85 | or even something like this: 86 | ```yaml 87 | actions: 88 | log: "echo {0} >> {1}" 89 | config: 90 | default_actions: 91 | - preaction '{{@@ _dotfile_key @@}} installed' "/tmp/log" 92 | ... 93 | ``` 94 | 95 | Make sure to quote the actions using variables. -------------------------------------------------------------------------------- /tests-ng/profile-import-dotfiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | # 5 | # test dotfiles imported in profile 6 | # and importing 7 | # returns 1 in case of error 8 | # 9 | 10 | # exit on first error 11 | set -e 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # the dotfile source 51 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | mkdir -p ${tmps}/dotfiles 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the config file 60 | cfg="${tmps}/config.yaml" 61 | cfg2="${tmps}/dotfiles.yaml" 62 | 63 | src="dotdrop-test" 64 | dst=".dotdrop-test" 65 | clear_on_exit "${HOME}/${dst}" 66 | 67 | cat > ${cfg} << _EOF 68 | config: 69 | dotpath: dotfiles 70 | dotfiles: 71 | f_abc: 72 | dst: ${tmpd}/abc 73 | src: abc 74 | f_def: 75 | dst: ~/${dst} 76 | src: ${src} 77 | profiles: 78 | p1: 79 | import: 80 | - dotfiles.yaml 81 | dotfiles: 82 | - f_abc 83 | _EOF 84 | cat ${cfg} 85 | 86 | cat > ${cfg2} << _EOF 87 | dotfiles: 88 | - f_def 89 | _EOF 90 | #cat ${cfg2} 91 | 92 | # create the dotfile 93 | echo "abc" > ${tmps}/dotfiles/abc 94 | echo "abc" > ${tmpd}/abc 95 | echo "def" > ${tmps}/dotfiles/${src} 96 | echo "def" > ${HOME}/${dst} 97 | 98 | # import 99 | ## this is a special case since the dotfile must 100 | ## be in home (because it is strip) 101 | echo ${ddpath} 102 | echo ${bin} 103 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 --verbose ~/${dst} 104 | 105 | cat ${cfg} 106 | echo '----------' 107 | cat ${cfg2} 108 | 109 | cnt=$(cd ${ddpath} | ${bin} files -G -c ${cfg} -p p1 | grep '^f_def' | wc -l) 110 | [ "${cnt}" != "1" ] && echo "imported twice! (${cnt})" && exit 1 111 | 112 | echo "OK" 113 | exit 0 114 | -------------------------------------------------------------------------------- /tests-ng/dyninclude.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test dynamic includes 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | cat > ${cfg} << _EOF 62 | variables: 63 | var1: "_1" 64 | dynvariables: 65 | dvar1: "echo _2" 66 | config: 67 | backup: true 68 | create: true 69 | dotpath: dotfiles 70 | dotfiles: 71 | f_abc: 72 | dst: ${tmpd}/abc 73 | src: abc 74 | f_def: 75 | dst: ${tmpd}/def 76 | src: def 77 | profiles: 78 | profile_1: 79 | dotfiles: 80 | - f_abc 81 | profile_2: 82 | dotfiles: 83 | - f_def 84 | profile_3: 85 | include: 86 | - profile{{@@ var1 @@}} 87 | profile_4: 88 | include: 89 | - profile{{@@ dvar1 @@}} 90 | _EOF 91 | #cat ${cfg} 92 | 93 | # create the dotfile 94 | c1="content:abc" 95 | echo "${c1}" > ${tmps}/dotfiles/abc 96 | c2="content:def" 97 | echo "${c2}" > ${tmps}/dotfiles/def 98 | 99 | # install 100 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p profile_3 --verbose 101 | 102 | # check dotfile exists 103 | [ ! -e ${tmpd}/abc ] && exit 1 104 | #cat ${tmpd}/abc 105 | grep ${c1} ${tmpd}/abc >/dev/null || exit 1 106 | 107 | # install 108 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p profile_4 --verbose 109 | 110 | # check dotfile exists 111 | [ ! -e ${tmpd}/def ] && exit 1 112 | #cat ${tmpd}/def 113 | grep ${c2} ${tmpd}/def >/dev/null || exit 1 114 | 115 | echo "OK" 116 | exit 0 117 | -------------------------------------------------------------------------------- /tests-ng/link-templates-dir.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test link of directory containing templates 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | echo "dotfiles source (dotpath): ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | echo "dotfiles destination: ${tmpd}" 56 | # the workdir 57 | tmpw=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 58 | export DOTDROP_WORKDIR="${tmpw}" 59 | echo "workdir: ${tmpw}" 60 | 61 | clear_on_exit "${tmps}" 62 | clear_on_exit "${tmpd}" 63 | clear_on_exit "${tmpw}" 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | 68 | cat > ${cfg} << _EOF 69 | config: 70 | backup: true 71 | create: true 72 | dotpath: dotfiles 73 | workdir: ${tmpw} 74 | dotfiles: 75 | f_abc: 76 | dst: ${tmpd}/abc 77 | src: abc 78 | link: true 79 | profiles: 80 | p1: 81 | dotfiles: 82 | - f_abc 83 | _EOF 84 | #cat ${cfg} 85 | 86 | # create the dotfile 87 | mkdir -p ${tmps}/dotfiles/abc 88 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/abc/template 89 | echo "blabla" >> ${tmps}/dotfiles/abc/template 90 | echo "blabla" > ${tmps}/dotfiles/abc/nottemplate 91 | 92 | # install 93 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 94 | 95 | # checks 96 | [ ! -d ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1 97 | [ ! -h ${tmpd}/abc ] && echo "[ERROR] dotfile is not a symlink" && exit 1 98 | #cat ${tmpd}/abc/template 99 | #tree -a ${tmpd}/abc/ 100 | set +e 101 | grep '{{@@' ${tmpd}/abc/template >/dev/null 2>&1 && echo "[ERROR] template in dir not replace" && exit 1 102 | set -e 103 | 104 | echo "OK" 105 | exit 0 106 | -------------------------------------------------------------------------------- /tests-ng/recvariables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test recursive variables 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | #echo "dotfile destination: ${tmpd}" 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the config file 60 | cfg="${tmps}/config.yaml" 61 | 62 | cat > ${cfg} << _EOF 63 | config: 64 | backup: true 65 | create: true 66 | dotpath: dotfiles 67 | variables: 68 | var1: "var1" 69 | var2: "{{@@ var1 @@}} var2" 70 | var3: "{{@@ var2 @@}} var3" 71 | var4: "{{@@ dvar4 @@}}" 72 | dynvariables: 73 | dvar1: "echo dvar1" 74 | dvar2: "{{@@ dvar1 @@}} dvar2" 75 | dvar3: "{{@@ dvar2 @@}} dvar3" 76 | dvar4: "echo {{@@ var3 @@}}" 77 | dotfiles: 78 | f_abc: 79 | dst: ${tmpd}/abc 80 | src: abc 81 | profiles: 82 | p1: 83 | dotfiles: 84 | - f_abc 85 | _EOF 86 | #cat ${cfg} 87 | 88 | # create the dotfile 89 | echo "var3: {{@@ var3 @@}}" > ${tmps}/dotfiles/abc 90 | echo "dvar3: {{@@ dvar3 @@}}" >> ${tmps}/dotfiles/abc 91 | echo "var4: {{@@ var4 @@}}" >> ${tmps}/dotfiles/abc 92 | echo "dvar4: {{@@ dvar4 @@}}" >> ${tmps}/dotfiles/abc 93 | 94 | #cat ${tmps}/dotfiles/abc 95 | 96 | # install 97 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 98 | 99 | #cat ${tmpd}/abc 100 | 101 | grep '^var3: var1 var2 var3' ${tmpd}/abc >/dev/null 102 | grep '^dvar3: dvar1 dvar2 dvar3' ${tmpd}/abc >/dev/null 103 | grep '^var4: echo var1 var2 var3' ${tmpd}/abc >/dev/null 104 | grep '^dvar4: var1 var2 var3' ${tmpd}/abc >/dev/null 105 | 106 | #cat ${tmpd}/abc 107 | 108 | echo "OK" 109 | exit 0 110 | -------------------------------------------------------------------------------- /tests-ng/update-rights.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test updates and rights 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | echo "[+] dotdrop dir: ${basedir}" 52 | echo "[+] dotpath dir: ${basedir}/dotfiles" 53 | 54 | # the dotfile directory to be imported 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | # the dotfile file to be imported 57 | tmpf=`mktemp` 58 | 59 | clear_on_exit "${basedir}" 60 | clear_on_exit "${tmpd}" 61 | 62 | # single file 63 | echo 'file' > ${tmpf} 64 | 65 | mkdir ${tmpd}/dir1 66 | echo 'dir1file1' > ${tmpd}/dir1/file1 67 | echo 'dir1file2' > ${tmpd}/dir1/file2 68 | 69 | # create the config file 70 | cfg="${basedir}/config.yaml" 71 | create_conf ${cfg} # sets token 72 | 73 | # import dir1 74 | echo "[+] import" 75 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd} 76 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpf} 77 | 78 | # change file 79 | chmod +x ${tmpf} 80 | 81 | # update 82 | echo "[+] updating" 83 | cd ${ddpath} | ${bin} update -c ${cfg} -f --verbose ${tmpf} 84 | 85 | # test change applied 86 | [ "`stat -c '%a' ${tmpf}`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpf}`" ] && exit 1 87 | 88 | # change file 89 | chmod +x ${tmpd}/dir1/file2 90 | echo 'test' > ${tmpd}/dir1/newfile 91 | chmod +x ${tmpd}/dir1/newfile 92 | 93 | # update 94 | echo "[+] updating" 95 | cd ${ddpath} | ${bin} update -c ${cfg} -f --verbose ${tmpd} 96 | 97 | # test change applied 98 | [ "`stat -c '%a' ${tmpd}/dir1/newfile`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpd}/dir1/newfile`" ] && exit 1 99 | [ "`stat -c '%a' ${tmpd}/dir1/file2`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpd}/dir1/file2`" ] && exit 1 100 | 101 | echo "OK" 102 | exit 0 103 | -------------------------------------------------------------------------------- /tests-ng/corner-case.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # the only purpose is to test corner-cases 6 | # not covered by other tests like 7 | # dry 8 | # diff before write 9 | # etc 10 | # 11 | # returns 1 in case of error 12 | # 13 | 14 | # exit on first error 15 | set -e 16 | 17 | # all this crap to get current path 18 | rl="readlink -f" 19 | if ! ${rl} "${0}" >/dev/null 2>&1; then 20 | rl="realpath" 21 | 22 | if ! hash ${rl}; then 23 | echo "\"${rl}\" not found !" && exit 1 24 | fi 25 | fi 26 | cur=$(dirname "$(${rl} "${0}")") 27 | 28 | #hash dotdrop >/dev/null 2>&1 29 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 30 | 31 | #echo "called with ${1}" 32 | 33 | # dotdrop path can be pass as argument 34 | ddpath="${cur}/../" 35 | [ "${1}" != "" ] && ddpath="${1}" 36 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 37 | 38 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 39 | bin="python3 -m dotdrop.dotdrop" 40 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 41 | 42 | echo "dotdrop path: ${ddpath}" 43 | echo "pythonpath: ${PYTHONPATH}" 44 | 45 | # get the helpers 46 | source ${cur}/helpers 47 | 48 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 49 | 50 | ################################################################ 51 | # this is the test 52 | ################################################################ 53 | 54 | # dotdrop directory 55 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | echo "[+] dotdrop dir: ${basedir}" 57 | echo "[+] dotpath dir: ${basedir}/dotfiles" 58 | 59 | clear_on_exit "${basedir}" 60 | 61 | export DOTDROP_WORKERS=1 62 | 63 | # create the config file 64 | cfg="${basedir}/config.yaml" 65 | cat > ${cfg} << _EOF 66 | config: 67 | backup: true 68 | create: true 69 | dotpath: dotfiles 70 | dotfiles: 71 | f_x: 72 | src: /tmp/x 73 | dst: 74 | f_y: 75 | src: /tmp/.i-do-not-exist-dotdrop 76 | dst: /tmp/y 77 | profiles: 78 | p1: 79 | dotfiles: 80 | - f_x 81 | - f_y 82 | 83 | _EOF 84 | 85 | echo "[+] test install dry" 86 | cd ${ddpath} | ${bin} install -c ${cfg} --dry -p p1 --verbose f_x 87 | [ "$?" != "0" ] && exit 1 88 | 89 | echo "[+] test install show-diff" 90 | cd ${ddpath} | ${bin} install -c ${cfg} -p p1 --verbose f_x 91 | [ "$?" != "0" ] && exit 1 92 | cd ${ddpath} | ${bin} install -D -c ${cfg} -p p1 --verbose f_x 93 | [ "$?" != "0" ] && exit 1 94 | 95 | echo "[+] test install not existing src" 96 | cd ${ddpath} | ${bin} install -c ${cfg} -f --dry -p p1 --verbose f_y 97 | 98 | echo "[+] test install to temp" 99 | cd ${ddpath} | ${bin} install -t -c ${cfg} -p p1 --verbose f_x > ${basedir}/log 2>&1 100 | [ "$?" != "0" ] && echo "install to tmp failed" && exit 1 101 | 102 | # cleaning 103 | tmpfile=`cat ${basedir}/log | grep 'installed to tmp ' | sed 's/^.*to tmp "\(.*\)"./\1/'` 104 | echo "tmpfile: ${tmpfile}" 105 | rm -rf "${tmpfile}" 106 | 107 | echo "OK" 108 | exit 0 109 | -------------------------------------------------------------------------------- /tests-ng/dotfiles-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test ALL dotfiles 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | #set -v 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # the dotfile source 51 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | mkdir -p ${tmps}/dotfiles 53 | echo "dotfiles source (dotpath): ${tmps}" 54 | # the dotfile destination 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | echo "dotfiles destination: ${tmpd}" 57 | 58 | clear_on_exit "${tmps}" 59 | clear_on_exit "${tmpd}" 60 | 61 | # create the config file 62 | cfg="${tmps}/config.yaml" 63 | 64 | cat > ${cfg} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: dotfiles 69 | dotfiles: 70 | f_abc: 71 | dst: ${tmpd}/abc 72 | src: abc 73 | f_def: 74 | dst: ${tmpd}/def 75 | src: def 76 | d_ghi: 77 | dst: ${tmpd}/ghi 78 | src: ghi 79 | profiles: 80 | p1: 81 | dotfiles: 82 | - ALL 83 | _EOF 84 | #cat ${cfg} 85 | 86 | # create the dotfiles 87 | echo "abc" > ${tmps}/dotfiles/abc 88 | echo "def" > ${tmps}/dotfiles/def 89 | echo "ghi" > ${tmps}/dotfiles/ghi 90 | 91 | ########################### 92 | # test install and compare 93 | ########################### 94 | 95 | # install 96 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 97 | [ "$?" != "0" ] && exit 1 98 | 99 | # checks 100 | [ ! -e ${tmpd}/abc ] && exit 1 101 | [ ! -e ${tmpd}/def ] && exit 1 102 | [ ! -e ${tmpd}/ghi ] && exit 1 103 | 104 | # modify the dotfiles 105 | echo "abc-modified" > ${tmps}/dotfiles/abc 106 | echo "def-modified" > ${tmps}/dotfiles/def 107 | echo "ghi-modified" > ${tmps}/dotfiles/ghi 108 | 109 | # compare 110 | set +e 111 | cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -b -V 112 | ret="$?" 113 | set -e 114 | [ "$ret" = "0" ] && exit 1 115 | 116 | echo "OK" 117 | exit 0 118 | -------------------------------------------------------------------------------- /tests-ng/link-templates-dir-home.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test link of directory containing templates on home 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | echo "dotfiles source (dotpath): ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d -p ${HOME} --suffix='-dotdrop-tests' || mktemp -d` 55 | echo "dotfiles destination: ${tmpd}" 56 | # the workdir 57 | tmpw=`mktemp -d -p ${HOME} --suffix='-dotdrop-tests' || mktemp -d` 58 | export DOTDROP_WORKDIR="${tmpw}" 59 | echo "workdir: ${tmpw}" 60 | 61 | clear_on_exit "${tmps}" 62 | clear_on_exit "${tmpd}" 63 | clear_on_exit "${tmpw}" 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | 68 | cat > ${cfg} << _EOF 69 | config: 70 | backup: true 71 | create: true 72 | dotpath: dotfiles 73 | workdir: ${tmpw} 74 | dotfiles: 75 | f_abc: 76 | dst: ${tmpd}/abc 77 | src: abc 78 | link: true 79 | profiles: 80 | p1: 81 | dotfiles: 82 | - f_abc 83 | _EOF 84 | #cat ${cfg} 85 | 86 | # create the dotfile 87 | mkdir -p ${tmps}/dotfiles/abc 88 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/abc/template 89 | echo "blabla" >> ${tmps}/dotfiles/abc/template 90 | echo "blabla" > ${tmps}/dotfiles/abc/nottemplate 91 | 92 | # install 93 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V 94 | 95 | # checks 96 | [ ! -d ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1 97 | [ ! -h ${tmpd}/abc ] && echo "[ERROR] dotfile is not a symlink" && exit 1 98 | #cat ${tmpd}/abc/template 99 | #tree -a ${tmpd}/abc/ 100 | set +e 101 | grep '{{@@' ${tmpd}/abc/template >/dev/null 2>&1 && echo "[ERROR] template in dir not replace" && exit 1 102 | set -e 103 | 104 | echo "OK" 105 | exit 0 106 | -------------------------------------------------------------------------------- /tests-ng/template-dotpath.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2022, deadc0de6 4 | # 5 | # test dotpath templated 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | dotpath="xyz" 50 | 51 | # dotdrop directory 52 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 53 | mkdir -p ${tmps}/${dotpath} 54 | echo "[+] dotdrop dir: ${tmps}" 55 | echo "[+] dotpath dir: ${tmps}/${dotpath}" 56 | 57 | # dotfile destination 58 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 59 | 60 | clear_on_exit "${tmps}" 61 | clear_on_exit "${tmpd}" 62 | 63 | echo "content" > ${tmps}/${dotpath}/abc 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | cat > ${cfg} << _EOF 68 | config: 69 | backup: true 70 | create: true 71 | dotpath: "{{@@ env['DOTDROP_DOTPATH'] @@}}" 72 | dotfiles: 73 | f_abc: 74 | src: abc 75 | dst: ${tmpd}/abc 76 | profiles: 77 | p1: 78 | dotfiles: 79 | - f_abc 80 | _EOF 81 | 82 | echo "[+] install" 83 | export DOTDROP_DOTPATH=${dotpath} 84 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 --verbose | grep '^1 dotfile(s) installed.$' 85 | [ "$?" != "0" ] && exit 1 86 | 87 | [ ! -e ${tmpd}/abc ] && echo "f_abc not installed" && exit 1 88 | 89 | # clean 90 | rm ${tmpd}/abc 91 | 92 | # create the config file 93 | cat > ${cfg} << _EOF 94 | config: 95 | backup: true 96 | create: true 97 | dotpath: "{{@@ var1 @@}}" 98 | variables: 99 | var1: "${dotpath}" 100 | dotfiles: 101 | f_abc: 102 | src: abc 103 | dst: ${tmpd}/abc 104 | profiles: 105 | p1: 106 | dotfiles: 107 | - f_abc 108 | _EOF 109 | 110 | echo "[+] install" 111 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 --verbose | grep '^1 dotfile(s) installed.$' 112 | [ "$?" != "0" ] && exit 1 113 | 114 | [ ! -e ${tmpd}/abc ] && echo "f_abc not installed" && exit 1 115 | 116 | echo "OK" 117 | exit 0 118 | -------------------------------------------------------------------------------- /tests-ng/variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test variables from yaml file 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | #echo "dotfile source: ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | #echo "dotfile destination: ${tmpd}" 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${tmps}/config.yaml" 62 | export dotdrop_test_dst="${tmpd}/def" 63 | 64 | cat > ${cfg} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: dotfiles 69 | variables: 70 | var1: "this is some test" 71 | var2: 12 72 | var3: another test 73 | vardst: "{{@@ env['dotdrop_test_dst'] @@}}" 74 | dotfiles: 75 | f_abc: 76 | dst: ${tmpd}/abc 77 | src: abc 78 | f_def: 79 | dst: "{{@@ vardst @@}}" 80 | src: def 81 | profiles: 82 | p1: 83 | dotfiles: 84 | - f_abc 85 | - f_def 86 | _EOF 87 | #cat ${cfg} 88 | 89 | # create the dotfile 90 | echo "{{@@ var1 @@}}" > ${tmps}/dotfiles/abc 91 | echo "{{@@ var2 @@}}" >> ${tmps}/dotfiles/abc 92 | echo "{{@@ var3 @@}}" >> ${tmps}/dotfiles/abc 93 | echo "test" >> ${tmps}/dotfiles/abc 94 | 95 | echo "test_def" > ${tmps}/dotfiles/def 96 | 97 | # install 98 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 --verbose 99 | 100 | [ ! -e ${tmpd}/abc ] && echo "abc not installed" && exit 1 101 | grep '^this is some test' ${tmpd}/abc >/dev/null 102 | grep '^12' ${tmpd}/abc >/dev/null 103 | grep '^another test' ${tmpd}/abc >/dev/null 104 | 105 | [ ! -e ${tmpd}/def ] && echo "def not installed" && exit 1 106 | grep '^test_def' ${tmpd}/def >/dev/null 107 | 108 | #cat ${tmpd}/abc 109 | 110 | echo "OK" 111 | exit 0 112 | -------------------------------------------------------------------------------- /tests-ng/import-with-empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test import new dotfiles with empty dst/src on existing dotfiles 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | echo "[+] dotdrop dir: ${basedir}" 52 | echo "[+] dotpath dir: ${basedir}/dotfiles" 53 | # the temp directory 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | 56 | clear_on_exit "${basedir}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create a dotfile 60 | dftoimport="${tmpd}/a_dotfile" 61 | echo 'some content' > ${dftoimport} 62 | 63 | # create the config file 64 | cfg="${basedir}/config.yaml" 65 | cat > ${cfg} << _EOF 66 | config: 67 | backup: true 68 | create: true 69 | dotpath: dotfiles 70 | dotfiles: 71 | f_x: 72 | src: /tmp/x 73 | dst: 74 | f_y: 75 | src: 76 | dst: /tmp/y 77 | f_z: 78 | src: 79 | dst: 80 | f_l: 81 | src: 82 | dst: 83 | link: link 84 | f_lc: 85 | src: 86 | dst: 87 | link: link_children 88 | profiles: 89 | p1: 90 | dotfiles: 91 | - f_x 92 | - f_y 93 | - f_z 94 | - f_l 95 | - f_lc 96 | _EOF 97 | 98 | echo "[+] import" 99 | cd ${ddpath} | ${bin} import -f -c ${cfg} -p p1 --verbose ${dftoimport} 100 | [ "$?" != "0" ] && exit 1 101 | 102 | echo "[+] install" 103 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 --verbose | grep '^5 dotfile(s) installed.$' 104 | rm -f ${dftoimport} 105 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 --verbose | grep '^6 dotfile(s) installed.$' 106 | 107 | nb=`cd ${ddpath} | ${bin} files -c ${cfg} -p p1 --verbose | grep '^[a-zA-Z]' | grep -v '^Dotfile(s)' | wc -l` 108 | [ "${nb}" != "6" ] && echo "error in dotfile list (${nb} VS 6)" && exit 1 109 | 110 | #cat ${cfg} 111 | 112 | echo "OK" 113 | exit 0 114 | -------------------------------------------------------------------------------- /tests-ng/variables-include.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test variables from yaml file 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | #echo "dotfile source: ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | #echo "dotfile destination: ${tmpd}" 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${tmps}/config.yaml" 62 | 63 | cat > ${cfg} << _EOF 64 | config: 65 | backup: true 66 | create: true 67 | dotpath: dotfiles 68 | variables: 69 | var1: "this is some test" 70 | var2: 12 71 | var3: another test 72 | dotfiles: 73 | f_abc: 74 | dst: ${tmpd}/abc 75 | src: abc 76 | profiles: 77 | p1: 78 | dotfiles: 79 | - f_abc 80 | variables: 81 | var1: "this is some sub-test" 82 | p2: 83 | include: 84 | - p1 85 | variables: 86 | var2: 42 87 | _EOF 88 | #cat ${cfg} 89 | 90 | # create the dotfile 91 | echo "{{@@ var1 @@}}" > ${tmps}/dotfiles/abc 92 | echo "{{@@ var2 @@}}" >> ${tmps}/dotfiles/abc 93 | echo "{{@@ var3 @@}}" >> ${tmps}/dotfiles/abc 94 | echo "test" >> ${tmps}/dotfiles/abc 95 | 96 | # install 97 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 98 | 99 | cat ${tmpd}/abc 100 | grep '^this is some sub-test' ${tmpd}/abc >/dev/null 101 | grep '^12' ${tmpd}/abc >/dev/null 102 | grep '^another test' ${tmpd}/abc >/dev/null 103 | 104 | # install 105 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p2 106 | 107 | cat ${tmpd}/abc 108 | grep '^this is some sub-test' ${tmpd}/abc >/dev/null 109 | grep '^42' ${tmpd}/abc >/dev/null 110 | grep '^another test' ${tmpd}/abc >/dev/null 111 | 112 | #cat ${tmpd}/abc 113 | 114 | echo "OK" 115 | exit 0 116 | -------------------------------------------------------------------------------- /tests-ng/global-compare-ignore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test cmpignore 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | echo "[+] dotdrop dir: ${basedir}" 52 | echo "[+] dotpath dir: ${basedir}/dotfiles" 53 | 54 | # the dotfile to be imported 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | 57 | clear_on_exit "${basedir}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # some files 61 | mkdir -p ${tmpd}/{program,config} 62 | touch ${tmpd}/program/a 63 | touch ${tmpd}/config/a 64 | 65 | # create the config file 66 | cfg="${basedir}/config.yaml" 67 | cat > ${cfg} << _EOF 68 | config: 69 | backup: true 70 | create: true 71 | dotpath: dotfiles 72 | dotfiles: 73 | profiles: 74 | _EOF 75 | 76 | # import 77 | echo "[+] import" 78 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd}/program 79 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd}/config 80 | 81 | # add files 82 | echo "[+] add files" 83 | touch ${tmpd}/program/b 84 | touch ${tmpd}/config/b 85 | 86 | # adding ignore in dotfile 87 | cfg2="${basedir}/config2.yaml" 88 | sed '/dotpath: dotfiles/a \ \ cmpignore:\n\ \ \ \ - "*/config/b"' ${cfg} > ${cfg2} 89 | cat ${cfg2} 90 | 91 | # expects one diff 92 | echo "[+] comparing with ignore in dotfile - 1 diff" 93 | set +e 94 | cd ${ddpath} | ${bin} compare -c ${cfg2} --verbose 95 | [ "$?" = "0" ] && exit 1 96 | set -e 97 | 98 | # adding ignore in dotfile 99 | cfg2="${basedir}/config2.yaml" 100 | sed '/dotpath: dotfiles/a \ \ cmpignore:\n\ \ \ \ - "*b"' ${cfg} > ${cfg2} 101 | cat ${cfg2} 102 | 103 | # expects no diff 104 | patt="*b" 105 | echo "[+] comparing with ignore in dotfile - 0 diff" 106 | set +e 107 | cd ${ddpath} | ${bin} compare -c ${cfg2} --verbose 108 | [ "$?" != "0" ] && exit 1 109 | set -e 110 | 111 | echo "OK" 112 | exit 0 113 | -------------------------------------------------------------------------------- /tests-ng/update-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test update of templates 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | echo "dotfiles source (dotpath): ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | echo "dotfiles destination: ${tmpd}" 56 | # the workdir 57 | tmpw=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 58 | export DOTDROP_WORKDIR="${tmpw}" 59 | echo "workdir: ${tmpw}" 60 | 61 | clear_on_exit "${tmps}" 62 | clear_on_exit "${tmpd}" 63 | clear_on_exit "${tmpw}" 64 | 65 | # create the config file 66 | cfg="${tmps}/config.yaml" 67 | 68 | cat > ${cfg} << _EOF 69 | config: 70 | backup: true 71 | create: true 72 | dotpath: dotfiles 73 | workdir: ${tmpw} 74 | dotfiles: 75 | f_abc: 76 | dst: ${tmpd}/abc 77 | src: abc 78 | profiles: 79 | p1: 80 | dotfiles: 81 | - f_abc 82 | _EOF 83 | #cat ${cfg} 84 | 85 | # create the dotfile 86 | echo "head" > ${tmps}/dotfiles/abc 87 | echo '{%@@ if profile == "p1" @@%}' >> ${tmps}/dotfiles/abc 88 | echo "is p1" >> ${tmps}/dotfiles/abc 89 | echo '{%@@ else @@%}' >> ${tmps}/dotfiles/abc 90 | echo "is not p1" >> ${tmps}/dotfiles/abc 91 | echo '{%@@ endif @@%}' >> ${tmps}/dotfiles/abc 92 | echo "tail" >> ${tmps}/dotfiles/abc 93 | 94 | # create the installed dotfile 95 | echo "head" > ${tmpd}/abc 96 | echo "is p1" >> ${tmpd}/abc 97 | echo "tail" >> ${tmpd}/abc 98 | 99 | # update 100 | #cat ${tmps}/dotfiles/abc 101 | set +e 102 | patch=`cd ${ddpath} | ${bin} update -P -p p1 -k f_abc --cfg ${cfg} 2>&1 | grep 'try patching with' | sed 's/"//g'` 103 | set -e 104 | patch=`echo ${patch} | sed 's/^.*: //g'` 105 | echo "patching with: ${patch}" 106 | eval ${patch} 107 | #cat ${tmps}/dotfiles/abc 108 | 109 | echo "OK" 110 | exit 0 111 | -------------------------------------------------------------------------------- /tests-ng/globs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # ensure imports allow globs 6 | # - import_actions 7 | # - import_configs 8 | # - import_variables 9 | # - profile import 10 | # 11 | 12 | # exit on first error 13 | set -e 14 | 15 | # all this crap to get current path 16 | rl="readlink -f" 17 | if ! ${rl} "${0}" >/dev/null 2>&1; then 18 | rl="realpath" 19 | 20 | if ! hash ${rl}; then 21 | echo "\"${rl}\" not found !" && exit 1 22 | fi 23 | fi 24 | cur=$(dirname "$(${rl} "${0}")") 25 | 26 | #hash dotdrop >/dev/null 2>&1 27 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 28 | 29 | #echo "called with ${1}" 30 | 31 | # dotdrop path can be pass as argument 32 | ddpath="${cur}/../" 33 | [ "${1}" != "" ] && ddpath="${1}" 34 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 35 | 36 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 37 | bin="python3 -m dotdrop.dotdrop" 38 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 39 | 40 | echo "dotdrop path: ${ddpath}" 41 | echo "pythonpath: ${PYTHONPATH}" 42 | 43 | # get the helpers 44 | source ${cur}/helpers 45 | 46 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 47 | 48 | ################################################################ 49 | # this is the test 50 | ################################################################ 51 | 52 | # the dotfile source 53 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | mkdir -p ${tmps}/dotfiles 55 | # the dotfile destination 56 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 57 | # temporary 58 | tmpa=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 59 | 60 | clear_on_exit "${tmps}" 61 | clear_on_exit "${tmpd}" 62 | clear_on_exit "${tmpa}" 63 | 64 | ########### 65 | # test globs in import_actions 66 | ########### 67 | # create the action files 68 | actionsd="${tmps}/actions" 69 | mkdir -p ${actionsd} 70 | cat > ${actionsd}/action1.yaml << _EOF 71 | actions: 72 | fromaction1: echo "fromaction1" > ${tmpa}/fromaction1 73 | _EOF 74 | cat > ${actionsd}/action2.yaml << _EOF 75 | actions: 76 | fromaction2: echo "fromaction2" > ${tmpa}/fromaction2 77 | _EOF 78 | 79 | cfg="${tmps}/config.yaml" 80 | cat > ${cfg} << _EOF 81 | config: 82 | backup: true 83 | create: true 84 | dotpath: dotfiles 85 | import_actions: 86 | - ${actionsd}/* 87 | dotfiles: 88 | f_abc: 89 | dst: ${tmpd}/abc 90 | src: abc 91 | actions: 92 | - fromaction1 93 | - fromaction2 94 | profiles: 95 | p1: 96 | dotfiles: 97 | - f_abc 98 | _EOF 99 | 100 | # create the source 101 | mkdir -p ${tmps}/dotfiles/ 102 | echo "abc" > ${tmps}/dotfiles/abc 103 | 104 | # install 105 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 -V 106 | 107 | # checks 108 | [ ! -e ${tmpd}/abc ] && echo "dotfile not installed" && exit 1 109 | [ ! -e ${tmpa}/fromaction1 ] && echo "action1 not executed" && exit 1 110 | grep fromaction1 ${tmpa}/fromaction1 111 | [ ! -e ${tmpa}/fromaction2 ] && echo "action2 not executed" && exit 1 112 | grep fromaction2 ${tmpa}/fromaction2 113 | 114 | echo "OK" 115 | exit 0 116 | -------------------------------------------------------------------------------- /tests-ng/import-configs2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2021, deadc0de6 4 | # 5 | # import config testing 6 | # 7 | 8 | # exit on first error 9 | set -e 10 | 11 | # all this crap to get current path 12 | rl="readlink -f" 13 | if ! ${rl} "${0}" >/dev/null 2>&1; then 14 | rl="realpath" 15 | 16 | if ! hash ${rl}; then 17 | echo "\"${rl}\" not found !" && exit 1 18 | fi 19 | fi 20 | cur=$(dirname "$(${rl} "${0}")") 21 | 22 | #hash dotdrop >/dev/null 2>&1 23 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 24 | 25 | #echo "called with ${1}" 26 | 27 | # dotdrop path can be pass as argument 28 | ddpath="${cur}/../" 29 | [ "${1}" != "" ] && ddpath="${1}" 30 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 31 | 32 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 33 | bin="python3 -m dotdrop.dotdrop" 34 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 35 | 36 | echo "dotdrop path: ${ddpath}" 37 | echo "pythonpath: ${PYTHONPATH}" 38 | 39 | # get the helpers 40 | source ${cur}/helpers 41 | 42 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 43 | 44 | ################################################################ 45 | # this is the test 46 | ################################################################ 47 | 48 | # the dotfile sources 49 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 50 | # the dotfile destination 51 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | 53 | clear_on_exit "${tmps}" 54 | clear_on_exit "${tmpd}" 55 | 56 | first="${tmps}/first" 57 | second="${tmps}/second" 58 | mkdir -p ${first} ${second} 59 | 60 | # create the config file 61 | cfg1="${first}/config.yaml" 62 | cfg2="${second}/config.yaml" 63 | 64 | cat > ${cfg1} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: . 69 | import_configs: 70 | - ../second/config.yaml 71 | dotfiles: 72 | f_abc: 73 | dst: ${tmpd}/abc 74 | src: abc 75 | profiles: 76 | p0: 77 | include: 78 | - p1 79 | dotfiles: 80 | - f_abc 81 | _EOF 82 | 83 | cat > ${cfg2} << _EOF 84 | config: 85 | backup: true 86 | create: true 87 | dotpath: . 88 | dotfiles: 89 | f_def: 90 | dst: ${tmpd}/def 91 | src: def 92 | profiles: 93 | p1: 94 | dotfiles: 95 | - f_def 96 | _EOF 97 | 98 | # create the source 99 | echo "abc" > ${first}/abc 100 | echo "{{@@ _dotfile_abs_dst @@}}" >> ${first}/abc 101 | 102 | echo "def" > ${second}/def 103 | echo "{{@@ _dotfile_abs_dst @@}}" >> ${second}/def 104 | 105 | # files comparison 106 | cd ${ddpath} | ${bin} files -c ${cfg1} -G -p p0 | grep '^f_abc' 107 | cd ${ddpath} | ${bin} files -c ${cfg1} -G -p p0 | grep '^f_def' 108 | cd ${ddpath} | ${bin} files -c ${cfg1} -G -p p1 | grep '^f_def' 109 | cd ${ddpath} | ${bin} files -c ${cfg2} -G -p p1 | grep '^f_def' 110 | 111 | # test compare too 112 | cd ${ddpath} | ${bin} install -c ${cfg1} -p p0 -V -f 113 | cd ${ddpath} | ${bin} compare -c ${cfg1} -p p0 -V 114 | 115 | [ ! -s ${tmpd}/abc ] && echo "abc not installed" && exit 1 116 | [ ! -s ${tmpd}/def ] && echo "def not installed" && exit 1 117 | 118 | echo "OK" 119 | exit 0 120 | -------------------------------------------------------------------------------- /tests-ng/dotfile-sub-variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test dotfile sub file specific variables 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | 55 | clear_on_exit "${tmps}" 56 | clear_on_exit "${tmpd}" 57 | 58 | # create the config file 59 | cfg="${tmps}/config.yaml" 60 | 61 | cat > ${cfg} << _EOF 62 | config: 63 | backup: true 64 | create: true 65 | dotpath: dotfiles 66 | dotfiles: 67 | d_abc: 68 | dst: ${tmpd}/abc 69 | src: abc 70 | profiles: 71 | p1: 72 | dotfiles: 73 | - d_abc 74 | _EOF 75 | #cat ${cfg} 76 | 77 | # create the dotfile 78 | mkdir -p ${tmps}/dotfiles/abc 79 | # file1 80 | echo 'src:{{@@ _dotfile_sub_abs_src @@}}' > ${tmps}/dotfiles/abc/file1 81 | echo 'dst:{{@@ _dotfile_sub_abs_dst @@}}' >> ${tmps}/dotfiles/abc/file1 82 | 83 | # file2 84 | mkdir -p ${tmps}/dotfiles/abc/subdir 85 | echo 'src:{{@@ _dotfile_sub_abs_src @@}}' > ${tmps}/dotfiles/abc/subdir/file2 86 | echo 'dst:{{@@ _dotfile_sub_abs_dst @@}}' >> ${tmps}/dotfiles/abc/subdir/file2 87 | 88 | # install 89 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 90 | 91 | # checks 92 | [ ! -d ${tmpd}/abc ] && echo 'dotfile not installed' && exit 1 93 | [ ! -e ${tmpd}/abc/file1 ] && echo 'dotfile sub src not installed' && exit 1 94 | [ ! -e ${tmpd}/abc/subdir/file2 ] && echo 'dotfile sub dst not installed' && exit 1 95 | 96 | cat ${tmpd}/abc/file1 97 | cat ${tmpd}/abc/subdir/file2 98 | 99 | grep "src:${tmps}/dotfiles/abc/file1" ${tmpd}/abc/file1 >/dev/null 100 | grep "dst:${tmpd}/abc/file1" ${tmpd}/abc/file1>/dev/null 101 | 102 | grep "src:${tmps}/dotfiles/abc/subdir/file2" ${tmpd}/abc/subdir/file2 >/dev/null 103 | grep "dst:${tmpd}/abc/subdir/file2" ${tmpd}/abc/subdir/file2 >/dev/null 104 | 105 | echo "OK" 106 | exit 0 107 | -------------------------------------------------------------------------------- /tests-ng/install-link-children.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test link_dotfile_default 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | #echo "dotfile destination: ${tmpd}" 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create the config file 60 | cfg="${tmps}/config.yaml" 61 | 62 | cat > ${cfg} << _EOF 63 | config: 64 | backup: true 65 | create: true 66 | dotpath: dotfiles 67 | link_dotfile_default: nolink 68 | dotfiles: 69 | d_dir1: 70 | dst: ${tmpd}/dir1 71 | src: dir1 72 | link: link_children 73 | instignore: 74 | - '*ignore' 75 | profiles: 76 | p1: 77 | dotfiles: 78 | - d_dir1 79 | _EOF 80 | #cat ${cfg} 81 | 82 | # create the dotfile 83 | mkdir ${tmps}/dotfiles/dir1 84 | mkdir ${tmps}/dotfiles/dir1/empty 85 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/dir1/empty/this.ignore 86 | mkdir ${tmps}/dotfiles/dir1/not-empty 87 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/dir1/not-empty/file 88 | mkdir ${tmps}/dotfiles/dir1/sub 89 | mkdir ${tmps}/dotfiles/dir1/sub/empty 90 | echo "{{@@ profile @@}}" > ${tmps}/dotfiles/dir1/sub/empty/that.ignore 91 | 92 | # install 93 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 94 | #cat ${cfg} 95 | 96 | # check normal 97 | [ ! -d ${tmpd}/dir1 ] && exit 1 98 | [ -d ${tmpd}/dir1/empty ] && exit 1 99 | [ -d ${tmpd}/dir1/sub ] && exit 1 100 | [ -d ${tmpd}/dir1/sub/empty ] && exit 1 101 | [ ! -d ${tmpd}/dir1/not-empty ] && exit 1 102 | 103 | [ ! -e ${tmpd}/dir1/not-empty/file ] && exit 1 104 | 105 | # ignored files 106 | [ -e ${tmpd}/dir1/empty/this.ignore ] && exit 1 107 | [ -e ${tmpd}/dir1/sub/empty/that.ignore ] && exit 1 108 | 109 | cat ${tmpd}/dir1/not-empty/file 110 | grep "p1" ${tmpd}/dir1/not-empty/file 111 | 112 | echo "OK" 113 | exit 0 114 | -------------------------------------------------------------------------------- /tests-ng/update-with-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test updates with key 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # dotdrop directory 50 | basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | echo "[+] dotdrop dir: ${basedir}" 52 | echo "[+] dotpath dir: ${basedir}/dotfiles" 53 | 54 | # the dotfile to be imported 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | 57 | clear_on_exit "${basedir}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # originally imported directory 61 | echo 'unique' > ${tmpd}/uniquefile 62 | uniquefile_key="f_uniquefile" 63 | echo 'unique2' > ${tmpd}/uniquefile2 64 | uniquefile2_key="f_uniquefile2" 65 | mkdir ${tmpd}/dir1 66 | touch ${tmpd}/dir1/dir1f1 67 | mkdir ${tmpd}/dir1/dir1dir1 68 | dir1_key="d_dir1" 69 | 70 | # create the config file 71 | cfg="${basedir}/config.yaml" 72 | create_conf ${cfg} # sets token 73 | 74 | # import dir1 75 | echo "[+] import" 76 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd}/dir1 77 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd}/uniquefile 78 | cd ${ddpath} | ${bin} import -f -c ${cfg} ${tmpd}/uniquefile2 79 | 80 | # make some modification 81 | echo "[+] modify" 82 | echo 'changed' > ${tmpd}/uniquefile 83 | echo 'changed' > ${tmpd}/uniquefile2 84 | echo 'new' > ${tmpd}/dir1/dir1dir1/new 85 | 86 | # update by key 87 | echo "[+] updating single key" 88 | cd ${ddpath} | ${bin} update -c ${cfg} -k -f --verbose ${uniquefile_key} 89 | 90 | # ensure changes applied correctly (only to uniquefile) 91 | diff ${tmpd}/uniquefile ${basedir}/dotfiles/${tmpd}/uniquefile # should be same 92 | set +e 93 | diff ${tmpd}/uniquefile2 ${basedir}/dotfiles/${tmpd}/uniquefile2 # should be different 94 | [ "${?}" != "1" ] && exit 1 95 | set -e 96 | 97 | # update all keys 98 | echo "[+] updating all keys" 99 | cd ${ddpath} | ${bin} update -c ${cfg} -k -f --verbose 100 | 101 | # ensure all changes applied 102 | diff ${tmpd} ${basedir}/dotfiles/${tmpd} 103 | 104 | echo "OK" 105 | exit 0 106 | -------------------------------------------------------------------------------- /tests-ng/ignore-empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test empty template generation 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | #echo "dotfile source: ${tmps}" 53 | # the dotfile destination 54 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 55 | #echo "dotfile destination: ${tmpd}" 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | 60 | # create the config file 61 | cfg="${tmps}/config.yaml" 62 | 63 | # globally 64 | cat > ${cfg} << _EOF 65 | config: 66 | backup: true 67 | create: true 68 | dotpath: dotfiles 69 | ignoreempty: true 70 | dotfiles: 71 | d_d1: 72 | dst: ${tmpd}/d1 73 | src: d1 74 | profiles: 75 | p1: 76 | dotfiles: 77 | - d_d1 78 | _EOF 79 | #cat ${cfg} 80 | 81 | # create the dotfile 82 | mkdir -p ${tmps}/dotfiles/d1 83 | echo "{#@@ should be stripped @@#}" > ${tmps}/dotfiles/d1/empty 84 | echo "not empty" > ${tmps}/dotfiles/d1/notempty 85 | 86 | # install 87 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 88 | 89 | # test existence 90 | [ -e ${tmpd}/d1/empty ] && echo 'empty should not exist' && exit 1 91 | [ ! -e ${tmpd}/d1/notempty ] && echo 'not empty should exist' && exit 1 92 | 93 | # through the dotfile 94 | cat > ${cfg} << _EOF 95 | config: 96 | backup: true 97 | create: true 98 | dotpath: dotfiles 99 | ignoreempty: false 100 | dotfiles: 101 | d_d1: 102 | dst: ${tmpd}/d1 103 | src: d1 104 | ignoreempty: true 105 | profiles: 106 | p1: 107 | dotfiles: 108 | - d_d1 109 | _EOF 110 | #cat ${cfg} 111 | 112 | # clean destination 113 | rm -rf ${tmpd}/* 114 | 115 | # install 116 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 117 | 118 | # test existence 119 | [ -e ${tmpd}/d1/empty ] && echo 'empty should not exist' && exit 1 120 | [ ! -e ${tmpd}/d1/notempty ] && echo 'not empty should exist' && exit 1 121 | 122 | echo "OK" 123 | exit 0 124 | -------------------------------------------------------------------------------- /tests-ng/ext-actions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test external actions 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the action temp 50 | tmpa=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | # the dotfile source 52 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 53 | mkdir -p ${tmps}/dotfiles 54 | # the dotfile destination 55 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 56 | 57 | clear_on_exit "${tmps}" 58 | clear_on_exit "${tmpd}" 59 | clear_on_exit "${tmpa}" 60 | 61 | act="${tmps}/actions.yaml" 62 | cat > ${act} << _EOF 63 | actions: 64 | pre: 65 | preaction: echo 'pre' > ${tmpa}/pre 66 | post: 67 | postaction: echo 'post' > ${tmpa}/post 68 | nakedaction: echo 'naked' > ${tmpa}/naked 69 | overwrite: echo 'over' > ${tmpa}/write 70 | _EOF 71 | 72 | # create the config file 73 | cfg="${tmps}/config.yaml" 74 | 75 | cat > ${cfg} << _EOF 76 | config: 77 | backup: true 78 | create: true 79 | dotpath: dotfiles 80 | import_actions: 81 | - ${tmps}/actions.yaml 82 | actions: 83 | overwrite: echo 'write' > ${tmpa}/write 84 | dotfiles: 85 | f_abc: 86 | dst: ${tmpd}/abc 87 | src: abc 88 | actions: 89 | - preaction 90 | - postaction 91 | - nakedaction 92 | - overwrite 93 | profiles: 94 | p1: 95 | dotfiles: 96 | - f_abc 97 | _EOF 98 | #cat ${cfg} 99 | 100 | # create the dotfile 101 | echo "test" > ${tmps}/dotfiles/abc 102 | 103 | # install 104 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 105 | 106 | # checks 107 | [ ! -e ${tmpa}/pre ] && exit 1 108 | grep pre ${tmpa}/pre >/dev/null 109 | echo "pre is ok" 110 | 111 | [ ! -e ${tmpa}/post ] && exit 1 112 | grep post ${tmpa}/post >/dev/null 113 | echo "post is ok" 114 | 115 | [ ! -e ${tmpa}/naked ] && exit 1 116 | grep naked ${tmpa}/naked >/dev/null 117 | echo "naked is ok" 118 | 119 | [ ! -e ${tmpa}/write ] && exit 1 120 | grep over ${tmpa}/write >/dev/null 121 | echo "write is ok" 122 | 123 | echo "OK" 124 | exit 0 125 | -------------------------------------------------------------------------------- /tests-ng/minversion.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2019, deadc0de6 4 | # 5 | # test minversion 6 | 7 | # exit on first error 8 | set -e 9 | 10 | # all this crap to get current path 11 | rl="readlink -f" 12 | if ! ${rl} "${0}" >/dev/null 2>&1; then 13 | rl="realpath" 14 | 15 | if ! hash ${rl}; then 16 | echo "\"${rl}\" not found !" && exit 1 17 | fi 18 | fi 19 | cur=$(dirname "$(${rl} "${0}")") 20 | 21 | #hash dotdrop >/dev/null 2>&1 22 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 23 | 24 | #echo "called with ${1}" 25 | 26 | # dotdrop path can be pass as argument 27 | ddpath="${cur}/../" 28 | [ "${1}" != "" ] && ddpath="${1}" 29 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 30 | 31 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 32 | bin="python3 -m dotdrop.dotdrop" 33 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 34 | 35 | echo "dotdrop path: ${ddpath}" 36 | echo "pythonpath: ${PYTHONPATH}" 37 | 38 | # get the helpers 39 | source ${cur}/helpers 40 | 41 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 42 | 43 | ################################################################ 44 | # this is the test 45 | ################################################################ 46 | 47 | # the dotfile source 48 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 49 | mkdir -p ${tmps}/dotfiles 50 | # the dotfile destination 51 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 52 | 53 | clear_on_exit "${tmps}" 54 | clear_on_exit "${tmpd}" 55 | 56 | cfg="${tmps}/config.yaml" 57 | cat > ${cfg} << _EOF 58 | config: 59 | backup: true 60 | create: true 61 | dotpath: dotfiles 62 | dotfiles: 63 | f_abc: 64 | dst: ${tmpd}/abc 65 | src: abc 66 | link: true 67 | profiles: 68 | p1: 69 | dotfiles: 70 | - f_abc 71 | _EOF 72 | 73 | # create the source 74 | mkdir -p ${tmps}/dotfiles/ 75 | echo "abc" > ${tmps}/dotfiles/abc 76 | ln -s ${tmps}/dotfiles/abc ${tmpd}/abc 77 | 78 | # compare 79 | cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -V 80 | 81 | # ensure minversion is present 82 | cat ${cfg} 83 | grep 'link: absolute' ${cfg} 84 | grep 'minversion' ${cfg} 85 | 86 | # fake a higher version 87 | cat > ${cfg} << _EOF 88 | config: 89 | backup: true 90 | create: true 91 | dotpath: dotfiles 92 | minversion: 100.1.2 93 | dotfiles: 94 | f_abc: 95 | dst: ${tmpd}/abc 96 | src: abc 97 | link: true 98 | profiles: 99 | p1: 100 | dotfiles: 101 | - f_abc 102 | _EOF 103 | 104 | # compare 105 | set +e 106 | cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -V 107 | [ "$?" != "1" ] && echo "minversion not working" && exit 1 108 | set -e 109 | 110 | # all clean 111 | cat > ${cfg} << _EOF 112 | config: 113 | backup: true 114 | create: true 115 | dotpath: dotfiles 116 | dotfiles: 117 | f_abc: 118 | dst: ${tmpd}/abc 119 | src: abc 120 | profiles: 121 | p1: 122 | dotfiles: 123 | - f_abc 124 | _EOF 125 | 126 | # compare 127 | cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -V 128 | 129 | # test 130 | cat ${cfg} 131 | grep 'minversion' ${cfg} && echo "minversion added, not needed" && exit 1 132 | 133 | echo "OK" 134 | exit 0 135 | -------------------------------------------------------------------------------- /tests-ng/chmod-more.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2020, deadc0de6 4 | # 5 | # test chmod on import 6 | # with files and directories 7 | # with different link 8 | # 9 | 10 | # exit on first error 11 | set -e 12 | 13 | # all this crap to get current path 14 | rl="readlink -f" 15 | if ! ${rl} "${0}" >/dev/null 2>&1; then 16 | rl="realpath" 17 | 18 | if ! hash ${rl}; then 19 | echo "\"${rl}\" not found !" && exit 1 20 | fi 21 | fi 22 | cur=$(dirname "$(${rl} "${0}")") 23 | 24 | #hash dotdrop >/dev/null 2>&1 25 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 26 | 27 | #echo "called with ${1}" 28 | 29 | # dotdrop path can be pass as argument 30 | ddpath="${cur}/../" 31 | [ "${1}" != "" ] && ddpath="${1}" 32 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 33 | 34 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 35 | bin="python3 -m dotdrop.dotdrop" 36 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 37 | 38 | echo "dotdrop path: ${ddpath}" 39 | echo "pythonpath: ${PYTHONPATH}" 40 | 41 | # get the helpers 42 | source ${cur}/helpers 43 | 44 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 45 | 46 | ################################################################ 47 | # this is the test 48 | ################################################################ 49 | 50 | # $1 path 51 | # $2 rights 52 | has_rights() 53 | { 54 | echo "testing ${1} is ${2}" 55 | [ ! -e "$1" ] && echo "`basename $1` does not exist" && exit 1 56 | local mode=`stat -L -c '%a' "$1"` 57 | [ "${mode}" != "$2" ] && echo "bad mode for `basename $1` (${mode} instead of ${2})" && exit 1 58 | true 59 | } 60 | 61 | # $1 file 62 | chmod_to_umask() 63 | { 64 | u=`umask` 65 | u=`echo ${u} | sed 's/^0*//'` 66 | if [ -d ${1} ]; then 67 | v=$((777 - u)) 68 | else 69 | v=$((666 - u)) 70 | fi 71 | chmod ${v} ${1} 72 | } 73 | 74 | # the dotfile source 75 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 76 | mkdir -p ${tmps}/dotfiles 77 | # the dotfile destination 78 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 79 | #echo "dotfile destination: ${tmpd}" 80 | 81 | clear_on_exit "${tmps}" 82 | clear_on_exit "${tmpd}" 83 | 84 | # create the dotfiles 85 | f1="${tmpd}/f1" 86 | touch ${f1} 87 | chmod 777 ${f1} 88 | stat -c '%a' ${f1} 89 | 90 | f2="${tmpd}/f2" 91 | touch ${f2} 92 | chmod 644 ${f2} 93 | stat -c '%a' ${f2} 94 | 95 | toimport="${f1} ${f2}" 96 | 97 | # create the config file 98 | cfg="${tmps}/config.yaml" 99 | 100 | cat > ${cfg} << _EOF 101 | config: 102 | backup: true 103 | create: true 104 | dotpath: dotfiles 105 | dotfiles: 106 | profiles: 107 | _EOF 108 | #cat ${cfg} 109 | 110 | # import without --preserve-mode 111 | for i in ${toimport}; do 112 | stat -c '%a' ${i} 113 | cd ${ddpath} | ${bin} import -c ${cfg} -f -p p1 -V ${i} 114 | done 115 | 116 | cat ${cfg} 117 | 118 | has_rights "${tmpd}/f1" "777" 119 | has_rights "${tmps}/dotfiles/${tmpd}/f1" "777" 120 | has_rights "${tmpd}/f2" "644" 121 | has_rights "${tmps}/dotfiles/${tmpd}/f2" "644" 122 | 123 | # install 124 | cd ${ddpath} | ${bin} install -c ${cfg} -f -p p1 -V | grep '0 dotfile(s) installed' || (echo "should not install" && exit 1) 125 | 126 | echo "OK" 127 | exit 0 128 | -------------------------------------------------------------------------------- /tests-ng/dynvariables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # author: deadc0de6 (https://github.com/deadc0de6) 3 | # Copyright (c) 2017, deadc0de6 4 | # 5 | # test dynamic variables from yaml file 6 | # returns 1 in case of error 7 | # 8 | 9 | # exit on first error 10 | set -e 11 | 12 | # all this crap to get current path 13 | rl="readlink -f" 14 | if ! ${rl} "${0}" >/dev/null 2>&1; then 15 | rl="realpath" 16 | 17 | if ! hash ${rl}; then 18 | echo "\"${rl}\" not found !" && exit 1 19 | fi 20 | fi 21 | cur=$(dirname "$(${rl} "${0}")") 22 | 23 | #hash dotdrop >/dev/null 2>&1 24 | #[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 25 | 26 | #echo "called with ${1}" 27 | 28 | # dotdrop path can be pass as argument 29 | ddpath="${cur}/../" 30 | [ "${1}" != "" ] && ddpath="${1}" 31 | [ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 32 | 33 | export PYTHONPATH="${ddpath}:${PYTHONPATH}" 34 | bin="python3 -m dotdrop.dotdrop" 35 | hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true 36 | 37 | echo "dotdrop path: ${ddpath}" 38 | echo "pythonpath: ${PYTHONPATH}" 39 | 40 | # get the helpers 41 | source ${cur}/helpers 42 | 43 | echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" 44 | 45 | ################################################################ 46 | # this is the test 47 | ################################################################ 48 | 49 | # the dotfile source 50 | tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 51 | mkdir -p ${tmps}/dotfiles 52 | # the dotfile destination 53 | tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` 54 | #echo "dotfile destination: ${tmpd}" 55 | 56 | clear_on_exit "${tmps}" 57 | clear_on_exit "${tmpd}" 58 | 59 | # create a shell script 60 | export TESTENV="this is my testenv" 61 | scr=`mktemp --suffix='-dotdrop-tests' || mktemp -d` 62 | chmod +x ${scr} 63 | echo -e "#!/bin/bash\necho $TESTENV\n" >> ${scr} 64 | clear_on_exit "${scr}" 65 | 66 | # create the config file 67 | cfg="${tmps}/config.yaml" 68 | 69 | cat > ${cfg} << _EOF 70 | config: 71 | backup: true 72 | create: true 73 | dotpath: dotfiles 74 | variables: 75 | var1: "this is some test" 76 | var2: "the_dvar4" 77 | dynvariables: 78 | dvar1: head -1 ${cur}/helpers 79 | dvar2: "echo 'this is some test' | rev | tr ' ' ','" 80 | dvar3: ${scr} 81 | dvar4: "echo {{@@ var2 @@}} | rev" 82 | dotfiles: 83 | f_abc: 84 | dst: ${tmpd}/abc 85 | src: abc 86 | profiles: 87 | p1: 88 | dotfiles: 89 | - f_abc 90 | _EOF 91 | #cat ${cfg} 92 | 93 | # create the dotfile 94 | echo "{{@@ var1 @@}}" > ${tmps}/dotfiles/abc 95 | echo "{{@@ dvar1 @@}}" >> ${tmps}/dotfiles/abc 96 | echo "{{@@ dvar2 @@}}" >> ${tmps}/dotfiles/abc 97 | echo "{{@@ dvar3 @@}}" >> ${tmps}/dotfiles/abc 98 | echo "{{@@ dvar4 @@}}" >> ${tmps}/dotfiles/abc 99 | echo "test" >> ${tmps}/dotfiles/abc 100 | 101 | # install 102 | cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V 103 | 104 | echo "-----" 105 | cat ${tmpd}/abc 106 | echo "-----" 107 | 108 | grep '^this is some test' ${tmpd}/abc >/dev/null 109 | grep '^# author: deadc0de6' ${tmpd}/abc >/dev/null 110 | grep '^tset,emos,si,siht' ${tmpd}/abc >/dev/null 111 | grep "^${TESTENV}" ${tmpd}/abc > /dev/null 112 | grep '^4ravd_eht' ${tmpd}/abc >/dev/null 113 | 114 | #cat ${tmpd}/abc 115 | 116 | echo "OK" 117 | exit 0 118 | --------------------------------------------------------------------------------