Metadata-Version: 2.0
Name: dotdrop
Version: 0.7.2
Summary: Save your dotfiles once, deploy them everywhere
Home-page: https://github.com/deadc0de6/dotdrop
Author: deadc0de6
Author-email: deadc0de6@foo.bar
License: GPLv3
Download-URL: https://github.com/deadc0de6/dotdrop/archive/v0.7.2.tar.gz
Description-Content-Type: UNKNOWN
Keywords: dotfiles jinja2
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Requires-Dist: docopt
Requires-Dist: Jinja2
Requires-Dist: PyYAML
Provides-Extra: dev
Requires-Dist: check-manifest; extra == 'dev'
Provides-Extra: test
Requires-Dist: coverage; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'

DOTDROP
=======

|Build Status| |License: GPL v3| |Coverage Status| |PyPI version|
|Python|

*Save your dotfiles once, deploy them everywhere*

Dotdrop makes the management of dotfiles between different hosts easy.
It allows to store your dotfiles on git and automagically deploy
different versions on different setups.

For example you can have a set of dotfiles for your home laptop and a
different set for your office desktop. Those sets may overlap and
different versions of the same dotfile can be deployed on different
predefined *profiles*. Another use case is when you have a main set of
dotfiles for your everyday’s host and a sub-set you only need to deploy
to temporary hosts (cloud VM, etc) that may be using a slightly
different version of some of the dotfiles.

Features:

-  Sync once every dotfile on git for different usages
-  Allow dotfiles templating by leveraging
   `jinja2 <http://jinja.pocoo.org/>`__
-  Comparison between local and stored dotfiles
-  Handling multiple profiles with different sets of dotfiles
-  Easy import dotfiles
-  Handle files and directories
-  Associate an action to the deployment of specific dotfiles

Check the `blog post <https://deadc0de.re/articles/dotfiles.html>`__ and
and the `example <#example>`__ for more.

Quick start:

.. code:: bash

    mkdir dotfiles && cd dotfiles
    git init
    git submodule add https://github.com/deadc0de6/dotdrop.git
    ./dotdrop/bootstrap.sh
    ./dotdrop.sh --help

Why dotdrop ?
-------------

There exist many tools to manage dotfiles however not many allow to
deploy different versions of the same dotfile on different hosts.
Moreover dotdrop allows to specify the set of dotfiles that need to be
deployed on a specific profile.

See the `example <#example>`__ for a concrete example on why dotdrop
rocks.

--------------

**Table of Contents**

-  `Installation <#installation>`__
-  `Usage <#usage>`__

   -  `Installing dotfiles <#installing-dotfiles>`__
   -  `Diffing your local dotfiles with
      dotdrop <#diffing-your-local-dotfiles-with-dotdrop>`__
   -  `Import new dotfiles <#import-new-dotfiles>`__
   -  `List the available profiles <#list-the-available-profiles>`__
   -  `List configured dotfiles <#list-configured-dotfiles>`__
   -  `Execute an action when deploying a
      dotfile <#execute-an-action-when-deploying-a-dotfile>`__
   -  `All dotfiles for a profile <#all-dotfiles-for-a-profile>`__
   -  `Include dotfiles from another
      profile <#include-dotfiles-from-another-profile>`__
   -  `Update dotdrop <#update-dotdrop>`__

-  `Template <#template>`__
-  `Example <#example>`__
-  `People using dotdrop <#people-using-dotdrop>`__

Installation
============

There’s two ways of installing and using dotdrop, either `as a
submodule <#as-a-submodule>`__ to your dotfiles git tree or system-wide
`through pypi <#with-pypi>`__.

Having dotdrop as a submodule guarantees that anywhere your are cloning
your dotfiles git tree from you’ll have dotdrop shipped with it. It is
the recommended way.

As a submodule
--------------

The following will create a repository for your dotfiles and keep
dotdrop as a submodules:

.. code:: bash

    $ mkdir dotfiles; cd dotfiles
    $ git init
    $ git submodule add https://github.com/deadc0de6/dotdrop.git
    $ ./dotdrop/bootstrap.sh
    $ ./dotdrop.sh --help

Then install the requirements:

.. code:: bash

    $ sudo pip3 install -r dotdrop/requirements.txt

For MacOS users, make sure to install ``realpath`` through homebrew
(part of *coreutils*).

Using this solution will need you to work with dotdrop by using the
generated script ``dotdrop.sh`` at the root of your dotfiles repository.

Finally import your dotfiles as described `below <#usage>`__.

With pypi
---------

Start by installing dotdrop

.. code:: bash

    $ sudo pip3 install dotdrop

And then create a repository for your dotfiles

.. code:: bash

    $ mkdir dotfiles; cd dotfiles
    $ git init

To avoid the need to provide the config file path to dotdrop each time
it is call, you can create an alias:

::

    alias dotdrop='dotdrop --cfg=<path-to-your-config.yaml>'

Replace any call to ``dotdrop.sh`` in the documentation below by
``dotdrop`` if using the pypi solution.

Finally import your dotfiles as described `below <#usage>`__.

Usage
=====

If starting fresh, the ``import`` command of dotdrop allows to easily
and quickly get a running setup.

Install dotdrop on one of your host and then import any dotfiles you
want dotdrop to manage (be it a file or a directory):

.. code:: bash

    $ dotdrop.sh import ~/.vimrc ~/.xinitrc

Dotdrop does two things:

-  Copy the dotfiles in the *dotfiles* directory
-  Create the entries in the *config.yaml* file

Commit and push your changes.

Then go to another host where your dotfiles need to be managed as well,
clone the previously setup git tree and compare local dotfiles with the
ones stored by dotdrop:

.. code:: bash

    $ dotdrop.sh list
    $ dotdrop.sh compare --profile=<other-host-profile>

Then adapt any dotfile using the `template <#template>`__ feature and
set a new profile for the current host by simply adding lines in the
config files, for example:

.. code:: yaml

    ...
    profiles:
      host1:
        dotfiles:
        - f_vimrc
        - f_xinitrc
      host2:
        dotfiles:
        - f_vimrc
    ...

When done, you can install your dotfiles using

.. code:: bash

    $ dotdrop.sh install

That’s it, a single repository with all your dotfiles for your different
hosts.

For additional usage see the help:

::

    $ dotdrop.sh --help
         _       _      _
      __| | ___ | |_ __| |_ __ ___  _ __
     / _` |/ _ \| __/ _` | '__/ _ \| '_ |
     \__,_|\___/ \__\__,_|_|  \___/| .__/
                                   |_|

    Usage:
      dotdrop install   [-fndV] [-c <path>] [-p <profile>]
      dotdrop compare   [-V]    [-c <path>] [-p <profile>] [--files=<files>]
      dotdrop import    [-ldV]  [-c <path>] [-p <profile>] <paths>...
      dotdrop listfiles [-V]    [-c <path>] [-p <profile>]
      dotdrop list      [-V]    [-c <path>]
      dotdrop --help
      dotdrop --version

    Options:
      -p --profile=<profile>  Specify the profile to use [default: thor].
      -c --cfg=<path>         Path to the config [default: config.yaml].
      --files=<files>         Comma separated list of files to compare.
      -n --nodiff             Do not diff when installing.
      -l --link               Import and link.
      -f --force              Do not warn if exists.
      -V --verbose            Be verbose.
      -d --dry                Dry run.
      -v --version            Show version.
      -h --help               Show this screen.

For easy deployment the default profile used by dotdrop reflects the
hostname of the host on which it runs.

Config file details
-------------------

The config file (defaults to *config.yaml*) is a yaml file containing
the following entries:

-  **config** entry: contains settings for the deployment

   -  ``backup``: create a backup of the dotfile in case it differs from
      the one that will be installed by dotdrop
   -  ``create``: create directory hierarchy when installing dotfiles if
      it doesn’t exist
   -  ``dotpath``: path to the directory containing the dotfiles to be
      managed by dotdrop (absolute path or relative to the config file
      location)

-  **dotfiles** entry: a list of dotfiles

   -  When ``link`` is true, dotdrop will create a symlink instead of
      copying. Template generation (as in `template <#template>`__) is
      not supported when ``link`` is true.
   -  ``actions`` contains a list of action keys that need to be defined
      in the **actions** entry below.

   ::

       <dotfile-key-name>:
         dst: <where-this-file-is-deployed>
         src: <filename-within-the-dotpath>
         # Optional
         link: <true|false>
         actions:
           - <action-key>

-  **profiles** entry: a list of profiles with the different dotfiles
   that need to be managed

   -  ``dotfiles``: the dotfiles associated to this profile
   -  ``include``: include all dotfiles from another profile (optional)

::

      <some-name-usually-the-hostname>:
        dotfiles:
        - <some-dotfile-key-name-defined-above>
        - <some-other-dotfile-key-name>
        - ...
        # Optional
        include:
        - <some-other-profile>
        - ...

-  **actions** entry: a list of action

::

      <action-key>: <command-to-execute>

Installing dotfiles
-------------------

Simply run

.. code:: bash

    $ dotdrop.sh install

Use the ``--profile`` switch to specify a profile if not using the
host’s hostname.

Diffing your local dotfiles with dotdrop
----------------------------------------

Compare local dotfiles with dotdrop’s defined ones:

.. code:: bash

    $ dotdrop.sh compare

Import new dotfiles
-------------------

Dotdrop allows to import dotfiles directly from the filesystem. It will
copy the dotfile and update the config file automatically.

For example to import ``~/.xinitrc``

.. code:: bash

    $ dotdrop.sh import ~/.xinitrc

List the available profiles
---------------------------

.. code:: bash

    $ dotdrop.sh list

Dotdrop allows to choose which profile to use with the *–profile* switch
if you use something else than the default (the hostname).

List configured dotfiles
------------------------

The following command lists the different dotfiles configured for a
specific profile:

.. code:: bash

    $ dotdrop.sh listfiles --profile=<some-profile>

For example:

::

    Dotfile(s) for profile "some-profile":

    f_vimrc (file: "vimrc", link: False)
        -> ~/.vimrc
    f_dunstrc (file: "config/dunst/dunstrc", link: False)
        -> ~/.config/dunst/dunstrc

Execute an action when deploying a dotfile
------------------------------------------

It is sometimes useful to execute some kind of action when deploying a
dotfile. For example let’s consider
`Vundle <https://github.com/VundleVim/Vundle.vim>`__ is used to manage
vim’s plugins, the following action could be set to update and install
the plugins when ``vimrc`` is deployed:

.. code:: yaml

    actions:
      vundle: vim +VundleClean! +VundleInstall +VundleInstall! +qall
    config:
      backup: true
      create: true
      dotpath: dotfiles
    dotfiles:
      f_vimrc:
        dst: ~/.vimrc
        src: vimrc
        actions:
          - vundle
    profiles:
      home:
        dotfiles:
        - f_vimrc

Thus when ``f_vimrc`` is installed, the command
``vim +VundleClean! +VundleInstall +VundleInstall! +qall`` will be
executed.

Update dotdrop
--------------

If used as a submodule, update it with

.. code:: bash

    $ git submodule foreach git pull origin master
    $ git add dotdrop
    $ git commit -m 'update dotdrop'
    $ git push

Through pypi:

.. code:: bash

    $ sudo pip3 install dotdrop --upgrade

All dotfiles for a profile
--------------------------

To use all defined dotfiles for a profile, simply use the keyword
``ALL``.

For example:

.. code:: yaml

    dotfiles:
      f_xinitrc:
        dst: ~/.xinitrc
        src: xinitrc
      f_vimrc:
        dst: ~/.vimrc
        src: vimrc
    profiles:
      host1:
        dotfiles:
        - ALL
      host2:
        dotfiles:
        - f_vimrc

Include dotfiles from another profile
-------------------------------------

If one profile is using the entire set of another profile, one can use
the ``include`` entry to avoid redundancy.

For example:

.. code:: yaml

    profiles:
      host1:
          dotfiles:
            - f_xinitrc
          include:
            - host2
      host2:
          dotfiles:
            - f_vimrc

Here profile *host1* contains all the dotfiles defined for *host2* plus
``f_xinitrc``.

Template
========

Dotdrop leverage the power of `jinja2 <http://jinja.pocoo.org/>`__ to
handle the templating of dotfiles. See `jinja2 template
doc <http://jinja.pocoo.org/docs/2.9/templates/>`__ or the `example
section <#example>`__ for more information on how to template your
dotfiles.

Note that dotdrop uses different delimiters than
`jinja2 <http://jinja.pocoo.org/>`__\ ’s defaults:

-  block start = ``{%@@``
-  block end = ``@@%}``
-  variable start = ``{{@@``
-  variable end = ``@@}}``
-  comment start = ``{#@@``
-  comment end = ``@@#}``

Available variables
-------------------

Profile
~~~~~~~

``{{@@ profile @@}}`` contains the profile provided to dotdrop. Below
example shows how it is used.

Environment variables
~~~~~~~~~~~~~~~~~~~~~

It’s possible to access environment variables inside the templates. This
feature can be used like this:

::

    {{@@ env['MY_VAR'] @@}}

This allows for storing host-specific properties and/or secrets in
environment variables.

You can have an ``.env`` file in the directory where your
``config.yaml`` lies:

::

    ## My variables for this host
    var1="some value"
    var2="some other value"

    ## Some secrets
    pass="verysecurepassword"

Of course, this file should not be tracked by git (put it in your
``.gitignore``).

Then you can invoke dotdrop with the help of an alias like that:

::

    ## when using dotdrop as a submodule
    alias dotdrop='eval $(grep -v "^#" ~/dotfiles/.env) ~/dotfiles/dotdrop.sh'

    ## when using dotdrop from pypi
    alias dotdrop='eval $(grep -v "^#" ~/dotfiles/.env) dotdrop --cfg=~/dotfiles/config.yaml'

This loads all the variables from ``.env`` (while omitting lines
starting with ``#``) before calling dotdrop.

Example
=======

Let’s consider two hosts:

-  **home**: home computer with hostname *home*
-  **office**: office computer with hostname *office*

The home computer is running `awesomeWM <https://awesomewm.org/>`__ and
the office computer `bspwm <https://github.com/baskerville/bspwm>`__.
The *.xinitrc* file will therefore be different while still sharing some
lines. Dotdrop allows to store only one single *.xinitrc* but to deploy
different versions depending on where it is run from.

The following file is the dotfile stored in dotdrop containing jinja2
directives for the deployment based on the profile used.

Dotfile ``<dotpath>/xinitrc``:

.. code:: bash

    #!/bin/bash

    # load Xresources
    userresources=$HOME/.Xresources
    if [ -f "$userresources" ]; then
          xrdb -merge "$userresources" &
    fi

    # launch the wm
    {%@@ if profile == "home" @@%}
    exec awesome
    {%@@ elif profile == "office" @@%}
    exec bspwm
    {%@@ endif @@%}

The *if branch* will define which part is deployed based on the hostname
of the host on which dotdrop is run from.

And here’s how the config file looks like with this setup. Of course any
combination of the dotfiles (different sets) can be done if more
dotfiles have to be deployed.

``config.yaml`` file:

.. code:: yaml

    config:
      backup: true
      create: true
      dotpath: dotfiles
    dotfiles:
      f_xinitrc:
        dst: ~/.xinitrc
        src: xinitrc
    profiles:
      home:
        dotfiles:
        - f_xinitrc
      office:
        dotfiles:
        - f_xinitrc

Installing the dotfiles (the ``--profile`` switch is not needed if the
hostname matches the entry in the config file):

.. code:: bash

    # on home computer
    $ dotdrop.sh install --profile=home

    # on office computer
    $ dotdrop.sh install --profile=office

Comparing the dotfiles:

.. code:: bash

    # on home computer
    $ dotdrop.sh compare

    # on office computer
    $ dotdrop.sh compare

People using dotdrop
====================

For more examples, see how people are using dotdrop:

-  https://github.com/open-dynaMIX/dotfiles
-  https://github.com/moyiz/dotfiles
-  https://github.com/japorized/dotfiles

Related projects
================

These are some dotfiles related projects that have inspired me for
dotdrop:

-  https://github.com/EvanPurkhiser/dots
-  https://github.com/jaagr/dots
-  https://github.com/anishathalye/dotbot
-  https://github.com/tomjnixon/Dotfiles

See also `github does dotfiles <https://dotfiles.github.io/>`__

Migrate from submodule
======================

Initially dotdrop was used as a submodule directly in the dotfiles git
tree. That solution allows your dotfiles to be shipped along with the
tool able to handle those. Dotdrop is however also directly available on
pypi.

If you want to keep it as a submodule, simply do the following

.. code:: bash

    $ cd <dotfiles-directory>

    ## get latest version of the submodule
    $ git submodule foreach git pull origin master

    ## and stage the changes
    $ git add dotdrop
    $ git commit -m 'update dotdrop'

    ## update the bash script wrapper
    $ ./dotdrop/bootstrap.sh

    ## and stage the change to the dotdrop.sh script
    $ git add dotdrop.sh
    $ git commit -m 'update dotdrop.sh'

    ## and finally push the changes upstream
    $ git push

Otherwise, simply install it from pypi as explained
`above <#with-pypi>`__ and get rid of the submodule:

-  move to the dotfiles directory where dotdrop is used as a submodule

.. code:: bash

    $ cd <dotfiles-repository>

-  remove the entire ``submodule "dotdrop"`` section in ``.gitmodules``
-  stage the changes

.. code:: bash

    $ git add .gitmodules

-  remove the entire ``submodule "dotdrop"`` section in ``.git/config``
-  remove the submodule

.. code:: bash

    $ git rm --cached dotdrop

-  remove the submodule from .git

.. code:: bash

    $ rm -rf .git/modules/dotdrop

-  commit the changes

.. code:: bash

    $ git commit -m 'removing dotdrop submodule'

-  remove any remaining files from the dotdrop submodule

.. code:: bash

    $ rm -rf dotdrop

-  remove ``dotdrop.sh``

.. code:: bash

    $ git rm dotdrop.sh
    $ git commit -m 'remove dotdrop.sh script'

-  push upstream

.. code:: bash

    $ git push

Contribution
============

If you are having trouble installing or using dotdrop, open an issue.

If you want to contribute, feel free to do a PR (please follow PEP8).

License
=======

This project is licensed under the terms of the GPLv3 license.

.. |Build Status| image:: https://travis-ci.org/deadc0de6/dotdrop.svg?branch=master
   :target: https://travis-ci.org/deadc0de6/dotdrop
.. |License: GPL v3| image:: https://img.shields.io/badge/License-GPL%20v3-blue.svg
   :target: http://www.gnu.org/licenses/gpl-3.0
.. |Coverage Status| image:: https://coveralls.io/repos/github/deadc0de6/dotdrop/badge.svg?branch=master
   :target: https://coveralls.io/github/deadc0de6/dotdrop?branch=master
.. |PyPI version| image:: https://badge.fury.io/py/dotdrop.svg
   :target: https://badge.fury.io/py/dotdrop
.. |Python| image:: https://img.shields.io/pypi/pyversions/dotdrop.svg
   :target: https://pypi.python.org/pypi/dotdrop


