.. _tutorial:
Beginner Tutorial
=================
This tutorial will walk you through setting up a git repository for your
dotfiles and creating a ``HOMELY.py`` script to automate their installation on
any of your computers.
1. Create an Online Repository
------------------------------
Since **homely** relies on a Version Control System to keep your dotfiles
syncronised across computers, the first step is to create a repository for your
dotfiles. If you already have a repository containing your dotfiles hosted
online, proceed to `2. Add a Repository`_.
If you are happy to publish your dotfiles publicly, you are may wish to host
wish to use one of the following VCS hosting providers:
GitHub
`Create a Repository `_.
Requires signing up for a free account.
BitBucket
`Create a Repository `_.
Requires signing up for a free account.
2. Add a Repository
-------------------
Once you have created your online repository, you will need to tell **homely**
to create a local clone of it. Use ``homely add ``, where ```` is the
same URL you would use to ``git clone`` the repository yourself.
**Note**: It is easier to get started cloning via HTTPS, but setting up SSH key
access can reduce the number of password prompts encountered.
**GitHub** (assuming a username of ``john.smith`` and a repository named ``dotfiles``)::
# HTTPS
$ homely add https://github.com/john.smith/dotfiles.git
# SSH
$ homely add git@github.com:phodge/dotfiles.git
**BitBucket** (assuming a username of ``john.smith`` and a repository named ``dotfiles``)::
# HTTPS
$ homely add https://john.smith@bitbucket.org/john.smith/dotfiles.git
# SSH
$ homely add git@bitbucket.org:john.smith/dotfiles.git
**homely** will create a local clone of your repository and put it in your home
directory. If you wish you may tell ``homely add`` where to create the local
clone by giving it a path as a 2nd parameter. If you don't provide an explicit
path, the repo's local path will be similar to what ``git clone`` would use.
(For the purposes of this tutorial, we will assume your dotfiles repo was
cloned to ``~/dotfiles``.). Check the CLI Reference for :any:`homely-add` for
more information.
3. Write and Run a HOMELY.py script
-----------------------------------
**homely** will look for a python script named ``HOMELY.py`` in your dotfiles
repo and execute it (import it) to install your config files locally. The
simplest things you can do in your ``HOMELY.py`` script is creating directories
and symlinks to things stored in the dotfiles repo.
For example, if you wanted to make sure that the ``~/.config/nvim`` and
``~/.config/pip`` directories are always created on all of your machines, you
could create a ``HOMELY.py`` script that looks like this::
# ~/dotfiles/HOMELY.py
# NOTE that we use homely's mkdir() not os.mkdir()
from homely.files import mkdir
# create ~/.config first - mkdir() is not recursive
mkdir('~/.coonfig')
mkdir('~/.coonfig/nvim')
mkdir('~/.coonfig/pip')
Now you can use :any:`homely-update` to execute your ``HOMELY.py``::
$ homely update
Now, assuming you already have a ``pip.conf`` and an ``init.vim`` in your
``~/.config`` directory, you might want to move these files into your dotfiles
repo and create symlinks to them on each machine.
First, move the real files into your dotfiles repo::
$ mv ~/.config/nvim/init.vim ~/dotfiles/
$ mv ~/.config/pip/pip.conf ~/dotfiles/
Now you can modify your ``HOMELY.py`` script to also install symlinks to those
files::
# ~/dotfiles/HOMELY.py
# NOTE that we use homely's mkdir() not os.mkdir()
from homely.files import mkdir
# create ~/.config first - mkdir() is not recursive
mkdir('~/.coonfig')
mkdir('~/.coonfig/nvim')
mkdir('~/.coonfig/pip')
# NOTE that we use homely's symlink() not os.symlink()
from homely.files import symlink
symlink('init.vim', '~/.coonfig/nvim')
symlink('pip.conf', '~/.coonfig/pip')
**homely**'s functions are idempotent, so it is safe to run them again and
again. Run :any:`homely-update` again now to install your symlinks::
$ homely update
Oh no! We misspelled ``~/.config`` everywhere! This is actually OK, because
**homely**'s :any:`automatic-cleanup` can remove all these unwanted
``~/.coonfig`` directories and symlinks for you, and all you need to do is
correct the typo and run :any:`homely-update` again. We can tidy up the code
while we're at it::
# ~/dotfiles/HOMELY.py
from homely.files import mkdir, symlink
mkdir('~/.config')
mkdir('~/.config/nvim')
mkdir('~/.config/pip')
symlink('init.vim', '~/.config/nvim/')
symlink('pip.conf', '~/.config/pip/')
Now re-run update::
$ homely update
So what exactly did :any:`homely-update` do here?
* First, :any:`homely-update` re-ran the corrected ``HOMELY.py`` script which
created the symlinks in ``~/.config`` instead of ``~/.coonfig``.
* After finishing with the ``HOMELY.py`` script, :any:`homely-update` noticed
that the calls to ``mkdir('~/.coonfig...')`` and ``symlink(..., '~/.coonfig...')``
weren't executed, so it performed :any:`automatic-cleanup` of each of the
things under ``~/.coonfig`` that it had created previously.
Automatic cleanup is one of the best features of **homely**. Generally speaking
it means you can just delete something from your ``HOMELY.py`` script and
:any:`homely-update` will make sure it gets removed anywhere it has already
been installed. There are some edge cases and limitations so there is a
:any:`dedicated page for how automatic cleanup works ` which
you may wish to read after finishing the tutorials.
4. Installing Packages
----------------------
If you were writing a plain shell script to install your dotfiles, you might
also include a few calls to e.g. ``brew install`` to install your favourite
software packages. **homely** includes a dedicated function for this which
offers the following advantages:
* Automaticaly chooses between ``brew``, ``yum``, ``pacman`` or ``apt`` depending which on
what's available on your operating system.
* Won't hang on a ``sudo`` password prompt when there's no TTY available.
* :any:`automatic_cleanup`!
You could get your ``HOMELY.py`` script to install
`ack `_ and
`ag `_ like this::
#~/dotfiles/HOMELY.py
[...snip...]
from homely.install import installpkg
# use the name "ack-grep" when installing using apt
installpkg('ack', apt='ack-grep')
# ag uses different names for yum, pacman and apt-get
installpkg('ag', yum='the_silver_searcher', apt='silversearcher-ag', pacman = 'the_silver_searcher')
and then::
$ homely update
Check the reference for :any:`homely-install-installpkg` for more information.