Giter VIP home page Giter VIP logo

dotfiler's Introduction

Dotfiler — the ultimate solution for managing dotfiles!

changelog

This was inspired by Zach Holman's dotfiles and homesick, but was made according the KISS priciple.

There are very few commands in dotfiler, only: update, add and status:

  • update will pull from all version controlled envs (env is a subdirectory inside the ~/.dotfiles dir, where different configs and scripts could be placed). After that, update will make all that mumbo-jumbo, symlinking, and removing old broken symlinks. If you want to see what will it do without but afraid to loose some files, just fire dot update --dry --verbose.
  • add allows you to clone one or more repositories with configs. For example, this will clone my emacs's configs: dot add svetlyak40wt/dot-emacs. Of course you could use a full url, like this: https://github.com/svetlyak40wt/dot-emacs or <[email protected]:svetlyak40wt/dot-emacs.git>.
  • status will show you if there are any uncommited changes in the envs and warn you if some of them aren't version controlled.

Installation

  1. Clone this project somewhere like $HOME/.dotfiles and add $HOME/.dotfiles/bin into your PATH.
  2. Clone some config files into the $HOME/.dotfiles.
  3. Run dot update to make all necessary symlinks.
  4. Have a profit!

Overview

From user's point of view — very simply. You just create a separate subdirectory called "environments", put configs there and then run dot update. Dotfiler will make all necessary symlinks automagickally. What makes dotfiler better, than other solutions? It's ability to merge files from different environments into one target dir. Here's an example:

Suppose, you have a ~/.zshrc which sources all configs from ~/.zsh/. And you want to separate default configs from the configs only needed on work machines. In most config managers you will end up with two separate repositories, each sharing part of zsh config. But dotfiler allows you to do a much more clever thing — separate zsh (actually any other configs too, if they understand include) into the different environments.

In this example:

  • The first environment, let's call it base, will contain the file base/.zsh/generic.
  • The second environment, called atwork, will have atwork/.zsh/secret-settings.

Both of them, of course, could include other files, not only zsh configs. Most importantly, these environment now can be stored separately and installed on each machine separately. Now, you can share you default configs on the GitHub, but keep work configs in a separate, private repository.

You can also add new environments using dot add <url> <url>.... (Probably the process of adding environments on a fresh machine will be even more improved, when I introduce a 'meta-environments', which will allow you to make one env depend on other envs and pull them automatically when adding)

Get involved

Don't hesitate to try dotfiler. Just install it and make your configs more structured. Extract useful ones and share them on GitHub, as I did. Then send me a link with a short description (or make a pull request), and I'll add you repositories to the end of this page.

Dotfiler's core functionality is fully tested, but that doesn't mean there aren't bugs. If you find one, file the issue on Github, or even better, try to write a test and/or fix for that use case and send it as a pull request. To run all tests, install nose and run nosetests bin/lib/dot.

How it works

First dotfiler, walks through all files and all environments collecting dirs and files mentioned in more than one environment as a tree. If a file with same filename exits in more than one environment this is an error and dot will tell you they are conflicting.

Then, using this tree, it generates source—target pairs, where source is a file inside the environment dir and target is where it should be in your home dir.

Finally, dot generates actions for each pair. Actions could be rm, mkdir, link, already-linked and error. Action are generated based on the current file system's state and previously generated actions. Here is a simple example:

This is a structure of the ~/.dotfiles with two separate enviroments zsh and emacs:

.
├── emacs
│   └── .emacs.d
│       ├── .gitignore
│       ├── COPYING
│       ├── README.markdown
│       ├── art
│       │   ├── debian-changelog-mode.el
│       │   ├── lisp.el
│       │   ├── multiple.el
│       │   ├── my-org.el
│       │   ├── my-python.el
│       │   └── pymacs.el
│       ├── art.el
│       ├── changelog.md
│       ├── customizations.el
│       ├── init.el
│       ├── modules
│       │   ├── starter-kit-bindings.el
│       │   ├── starter-kit-eshell.el
│       │   ├── starter-kit-js.el
│       │   ├── starter-kit-lisp.el
│       │   ├── starter-kit-perl.el
│       │   └── starter-kit-ruby.el
│       ├── snippets
│       │   └── python-mode
│       │       └── pdb.yasnippet
│       ├── starter-kit-defuns.el
│       ├── starter-kit-misc.el
│       ├── starter-kit-pkg.el
│       ├── starter-kit.el
│       ├── tar.sh
│       ├── ubuntu -> art
│       ├── ubuntu.el -> art.el
│       ├── vagrant -> art
│       └── vagrant.el -> art.el
└── zsh
    ├── .bash_profile
    ├── .zsh
    │   ├── 00-options
    │   ├── 01-prompt-functions
    │   ├── 02-prompt-colors
    │   ├── 03-prompt
    │   ├── aliases
    │   ├── ash
    │   ├── dotfiler
    │   └── ssh-agent
    └── .zshrc

And here is result of dot update:

[art@art-osx:~/.dotfiles]% dot update
LINK    Symlink from /home/art/.bash_profile to /home/art/.dotfiles/zsh/.bash_profile was created
LINK    Symlink from /home/art/.emacs.d to /home/art/.dotfiles/emacs/.emacs.d was created
LINK    Symlink from /home/art/.zsh to /home/art/.dotfiles/zsh/.zsh was created
LINK    Symlink from /home/art/.zshrc to /home/art/.dotfiles/zsh/.zshrc was created

As you can see, dotfiler creates four symlinks, two to files, and two to directories. But this was simple situation with no overlapping subdirectories.

Here is another example, showing how config merging works:

.
├── git
│   ├── .gitconfig
│   └── .zsh
│       ├── git-aliases
│       └── git-prompt
└── zsh
    ├── .bash_profile
    ├── .zsh
    │   ├── 00-options
    │   ├── 01-prompt-functions
    │   ├── 02-prompt-colors
    │   ├── 03-prompt
    │   ├── aliases
    │   ├── ash
    │   ├── dotfiler
    │   └── ssh-agent
    └── .zshrc

In this case, we have two environments and both of them have configs for zsh. For this situation, dotfiler will try to create a directory ~/.zsh and will make symlinks there:

[art@art-osx:~/.dotfiles]% dot update
LINK    Symlink from /home/art/.bash_profile to /home/art/.dotfiles/zsh/.bash_profile was created
LINK    Symlink from /home/art/.gitconfig to /home/art/.dotfiles/git/.gitconfig was created
MKDIR   Directory /home/art/.zsh was created.
LINK    Symlink from /home/art/.zsh/00-options to /home/art/.dotfiles/zsh/.zsh/00-options was created
LINK    Symlink from /home/art/.zsh/01-prompt-functions to /home/art/.dotfiles/zsh/.zsh/01-prompt-functions was created
LINK    Symlink from /home/art/.zsh/02-prompt-colors to /home/art/.dotfiles/zsh/.zsh/02-prompt-colors was created
LINK    Symlink from /home/art/.zsh/03-prompt to /home/art/.dotfiles/zsh/.zsh/03-prompt was created
LINK    Symlink from /home/art/.zsh/aliases to /home/art/.dotfiles/zsh/.zsh/aliases was created
LINK    Symlink from /home/art/.zsh/ash to /home/art/.dotfiles/zsh/.zsh/ash was created
LINK    Symlink from /home/art/.zsh/dotfiler to /home/art/.dotfiles/zsh/.zsh/dotfiler was created
LINK    Symlink from /home/art/.zsh/git-aliases to /home/art/.dotfiles/git/.zsh/git-aliases was created
LINK    Symlink from /home/art/.zsh/git-prompt to /home/art/.dotfiles/git/.zsh/git-prompt was created
LINK    Symlink from /home/art/.zsh/ssh-agent to /home/art/.dotfiles/zsh/.zsh/ssh-agent was created
LINK    Symlink from /home/art/.zshrc to /home/art/.dotfiles/zsh/.zshrc was created

How to ignore some files

Edit a config file ~/.dotfiles/.dotignore and add any regex patterns you need.

Environments

Another solutions

  • skeswa/dotfiler – another utility with the same name but completely different approach.

dotfiler's People

Contributors

alamaison avatar bitdeli-chef avatar chasebro avatar cybtachyon avatar dhleong avatar dpremy avatar drzel avatar svetlyak40wt avatar timothyearley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dotfiler's Issues

Dotfiler not portable across Ubuntu Bash on Windows

When running dot update, it does not properly recognize and handle existing symlinks when inside a symlinked home directory on Ubuntu Bash on Windows.

testuser@pc:~$ dot update
CANT LINK: /home/testuser/.bash_profile -> /mnt/c/Users/testuser/.dotfiles/base/.bash_profile
Traceback (most recent call last):
  File "/home/testuser/.dotfiles/bin/dot", line 43, in <module>
    arguments)
  File "/mnt/f/Users/testuser/.dotfiles/bin/lib/dot/core.py", line 441, in update
    created_links = processor(remove_actions + actions, created_links, fs)
  File "/mnt/f/Users/testuser/.dotfiles/bin/lib/dot/core.py", line 77, in processor_real
    mapping[action[0].replace('-', '_')](*action[1:])
  File "/mnt/f/Users/testuser/.dotfiles/bin/lib/dot/core.py", line 63, in link
    fs.symlink(source, target)
  File "/mnt/f/Users/testuser/.dotfiles/bin/lib/dot/real_filesystem.py", line 28, in symlink
    os_symlink(source, link_name)
OSError: [Errno 17] File exists

Not Python3 compatible

  File "bin/dot", line 31, in <module>
    from dot import COMMANDS
  File "/home/alee/.dotfiles/bin/lib/dot/__init__.py", line 2, in <module>
    from .core import COMMANDS
  File "/home/alee/.dotfiles/bin/lib/dot/core.py", line 486
    print env
            ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(env)?

I see you just changed the shebang from python2 to python, so I won't propose changing that back. Maybe you could import print_function from __future__; or simply move to Py3 as Py2 will be EOL soon anyway?

Common dotfiles plugins

I was wondering what if we could develop some common dotfiler plugins. They can be same dotfiler-oriented repositories, but they will have scripts for common tasks and dotfiler users can reuse it.
For example, when i start creating dotfiles repos, i found myself wanting to have some commands for bootstrapping my environment on some machines. For example, i made simple stupid [script](https://github.com/l0kix2/dot-homebrew/blob/master/.scripts/brew-install-packages.sh script) for installing my homebrew packages. It installs in ~/.scripts directory and assumes, that i have brew package names in ~/.brew/* text files.
As downside this common scripts must be shell-agnostic, but in simple cases, i think it will not be so hard.

At bottom line we will have some common scripts, gently forcing some directories naming conventions, but it sure will be user choice and plugins are simple dotfiler repos, so we don't have to invent anything new (maybe some syntax sugar for dot executable). So user can benefit from already invented and community-developed ways of doing common environment-bootstrap-related tasks.

Any thoughts on this? I can explain better in russian, if it is not clear because of my loosy english.

Symlinks not created when target directory exists

I just tried out your tool and noticed that sometimes not all links are created correctly:

Assume I have a repository in ~/.dotfiles/emacs with the following contents

~/.dotfiles/emacs/.emacs.d/init.el
~/.dotfiles/emacs/.emacs.d/config/base.el

Now, if in my home directory the directory ~/.emacs.d doesn't exists, everything runs nicely and 'dot update' creates a symlink from ~/.dotfiles/emacs/.emacs.d to ~/.emacs.d, here is the output from 'dot update --dry --verbose':

INFO Making pull in "emacs":
INFO Already up-to-date.
LINK Symlink from /home/simon/.emacs.d to /home/simon/.dotfiles/emacs/.emacs.d will be created

However, if the directory ~/.emacs.d already exists (I have some other files in it which should not be administered by dotfiler), it only creates a symlink for the config directory, not for init.el. Again, here is the output of "dot update --dry --verbose':

INFO Making pull in "emacs":
INFO Already up-to-date.
LINK Symlink from /home/simon/.emacs.d/config to /home/simon/.dotfiles/emacs/.emacs.d/config will be created

As you can see, the link for init.el is not created. I guess that there's some mistake in how dotfiler traverses the filesystem.

Best,

Simon

Update command exists with error if there is git repository without upstream

This is a traceback:

fatal: No remote repository specified.  Please, specify either a URL or a
remote name from which new revisions should be fetched.
Traceback (most recent call last):
  File "/Users/art/.dotfiles/bin/dot", line 43, in <module>
    arguments)
  File "/Users/art/.dotfiles/bin/lib/dot/core.py", line 364, in update
    make_pull(base_dir, env)
  File "/Users/art/.dotfiles/bin/lib/dot/core.py", line 352, in make_pull
    subprocess.check_call('git pull > /dev/null', shell=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 511, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'git pull > /dev/null' returned non-zero exit status 1

😞

Dotfiler confused when moving directories between environments

I recently moved some files across environments. In my "default" environment, I used to have .vim/ftplugin/. I moved this directory (and a few other sudirectories in my .vim/ directory) to my "personal" environment and ran dot update (note: I use a custom base_dir).

It appears dotfiler was confused by this move. It successfully removed the original symlinks to my default environment, but then did not create new symlinks to my personal environment. When I ran it again it created the new symlinks successfully.

Here's its log from the first run (with a few irrelevant updates omitted):

RM	Symlink /home/karepker/.vim/ftdetect was removed.
RM	Symlink /home/karepker/.vim/ftplugin was removed.
RM	Symlink /home/karepker/.vim/syntax was removed.
RM	Symlink /home/karepker/.bash.d/alias_personal.bash was removed.
RM	Symlink /home/karepker/.bash.d/command_personal.bash was removed.
RM	Symlink /home/karepker/.vim/indent was removed.
Traceback (most recent call last):
  File "/home/karepker/links/third_party/dotfiler/bin/dot", line 43, in <module>
    arguments)
  File "/home/karepker/links/third_party/dotfiler/bin/lib/dot/core.py", line 441, in update
    created_links = processor(remove_actions + actions, created_links, fs)
  File "/home/karepker/links/third_party/dotfiler/bin/lib/dot/core.py", line 77, in processor_real
    mapping[action[0].replace('-', '_')](*action[1:])
  File "/home/karepker/links/third_party/dotfiler/bin/lib/dot/core.py", line 58, in rm
    fs.rm(dir)
  File "/home/karepker/links/third_party/dotfiler/bin/lib/dot/real_filesystem.py", line 18, in rm
    os.unlink(path)
OSError: [Errno 2] No such file or directory: '/home/karepker/.vim/ftdetect'

And here's what happened on the second run:

LINK	Symlink from /home/karepker/.vim/ftdetect to /home/karepker/links/personal/settings/personal/.vim/ftdetect was created
LINK	Symlink from /home/karepker/.vim/ftplugin to /home/karepker/links/personal/settings/personal/.vim/ftplugin was created
LINK	Symlink from /home/karepker/.vim/indent to /home/karepker/links/settings/personal/.vim/indent was created
LINK	Symlink from /home/karepker/.vim/syntax to /home/karepker/links/personal/settings/personal/.vim/syntax was created

Make `update -v` moderately verbose

When running dot update -v, in addition to:

INFO    Making pull in "...":
INFO        Already up to date.
INFO    Making pull in "...":
INFO        Already up to date.
INFO    Making pull in "...":
INFO        Already up to date.
[...]

we get a lot of lines such as:

INFO Symlink from ... to ... already exists

Would it be possible to make the -v option less verbose by dropping these INFO Symlink [...] lines and, possibly, display them with a -vv more verbose option?

Crash which I don't understand

Dear @svetlyak40wt ,

I'm trying out dotfiler on both Windows (with Cygwin) and Windows (with WSL) for a couple of days. So far, so good, better than my in-house solution -- thanks a lot!

Today, got this, after having renamed one "castle" in the ~/.dotfiler directory.

image

Maybe not the best thing to do?

Best regards,
Fabrice

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.