Updating documentation
This commit is contained in:
parent
a1f10ebfb0
commit
ef5f8cba8d
19
LICENSE.txt
Normal file
19
LICENSE.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2015 Alex Yatskov <alex@foosoft.net>
|
||||||
|
Author: Alex Yatskov <alex@foosoft.net>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
249
README.md
Normal file
249
README.md
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
# Homemaker #
|
||||||
|
|
||||||
|
Homemaker is a tool for straightforward and efficient management of *nix configuration files found in the user's home
|
||||||
|
directory, commonly known as [dot-files](https://en.wikipedia.org/wiki/Dot-file). It is written in
|
||||||
|
[Golang](https://golang.org/), requires no installation, has no dependencies and makes use of simple configuration file
|
||||||
|
format inspired by [make](https://en.wikipedia.org/wiki/Make_%28software%29) to generate symlinks and execute system
|
||||||
|
commands to aid in configuring a new system for use.
|
||||||
|
|
||||||
|
## Motivation ##
|
||||||
|
|
||||||
|
Ever since switching to using Linux as my daily driver operating system, I have been searching for a way to effectively
|
||||||
|
manage settings between different computers (and system reinstalls on the same machine) while avoiding the accumulation
|
||||||
|
of cruft that plagues our home directories.
|
||||||
|
|
||||||
|
Specifically, I required a solution that had the following characteristics:
|
||||||
|
|
||||||
|
* **Do not require software installation**
|
||||||
|
|
||||||
|
The user may not have root privileges on all the computers that she accesses, making it difficult to make use
|
||||||
|
software that has additional dependencies. Even if the user has root on the machine in question, it is sub-optimal
|
||||||
|
to require her to install software packages just to bootstrap the system.
|
||||||
|
|
||||||
|
* **Support configuration variants**
|
||||||
|
|
||||||
|
The user should be able to use cherry-pick which settings they wish to use. Different system installs have different
|
||||||
|
configuration requirements; it must be possible to share common settings while keeping the unique bits unique to
|
||||||
|
each machine. Furthermore, it should be possible to store all configuration settings in one location.
|
||||||
|
|
||||||
|
* **Make no assumptions about synchronization**
|
||||||
|
|
||||||
|
While Git often works well for managing dot-files, it is not ideal for every situation. I've seen some applications
|
||||||
|
add and remove seemingly randomly-named files within their configuration directories, while others store their
|
||||||
|
settings in large, opaque binary blobs. Managing configuration settings for such poorly-behaved applications may be
|
||||||
|
easier through, [Dropbox](https://www.dropbox.com/), [rsync](https://en.wikipedia.org/wiki/Rsync), or some other
|
||||||
|
utility outside of version control.
|
||||||
|
|
||||||
|
* **Be easy to read and modify the source**
|
||||||
|
|
||||||
|
As a programmer, I always consider the underlying technology of a tool when deciding whether or not to use it. The
|
||||||
|
user should feel empowered to change and test the application without having to deal with the archaic incantations
|
||||||
|
otherwise known as shell scripts. Scripting languages can work well but are closely tied to the environment in which
|
||||||
|
they are executed.
|
||||||
|
|
||||||
|
It became apparent to me that utility which I was looking for did not exist. After making due with a simple Python
|
||||||
|
script that I hacked together, I decided that this problem deserved a clean, formal solution. I decided to create this
|
||||||
|
new utility in Go; in addition to the language itself being clear and easy to understand, executables built with the Go
|
||||||
|
compiler are statically linked, making them highly portable. The result of my work is Homemaker; I hope that you find it
|
||||||
|
suitable for your needs.
|
||||||
|
|
||||||
|
## Installation ##
|
||||||
|
|
||||||
|
If you already have the Go environment and toolchain set up, you can get the latest version by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/FooSoft/homemaker
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise, you can use the pre-built binaries for the architectures below:
|
||||||
|
|
||||||
|
* [amd64](http://foosoft.net/dl/homemaker/homemaker_amd64.tar.gz)
|
||||||
|
* 386 (build not available yet)
|
||||||
|
|
||||||
|
## Configuration ##
|
||||||
|
|
||||||
|
Configuration files for Homemaker can be authored in your choice of [TOML](https://github.com/toml-lang/toml),
|
||||||
|
[YAML](http://yaml.org/) or [JSON](http://json.org/) markup languages. Being the easiest to read out of the three, TOML
|
||||||
|
will be used for the example configuration files. Worry not if you are unfamiliar with this format; everything you need
|
||||||
|
to know about it will be shown below.
|
||||||
|
|
||||||
|
Let's start by looking at a basic example configuration file, `example.toml`. Notice that Homemaker determines which
|
||||||
|
markdown language processor to use based on the extension of your configuration file. Use `.toml` for TOML, `.yaml` for
|
||||||
|
YAML, and `.json` for JSON. Having a wrong file extension will prevent your configuration file from being parsed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
```
|
||||||
|
[tasks.default]
|
||||||
|
links = [
|
||||||
|
[".config/fish"],
|
||||||
|
[".config/keepassx"],
|
||||||
|
[".config/terminal"],
|
||||||
|
[".config/vlc"],
|
||||||
|
[".gitconfig"],
|
||||||
|
[".xinputrc"],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
We could have just as easily written this configuration in JSON (or YAML for that matter), but it's subjectively uglier:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"tasks": {
|
||||||
|
"default": {
|
||||||
|
"links": [
|
||||||
|
[".config/fish"],
|
||||||
|
[".config/keepassx"],
|
||||||
|
[".config/terminal"],
|
||||||
|
[".config/vlc"],
|
||||||
|
[".gitconfig"],
|
||||||
|
[".xinputrc"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To create symlinks based on this configuration we invoke the `homemaker` utility:
|
||||||
|
|
||||||
|
```
|
||||||
|
homemaker example.json /mnt/data/config
|
||||||
|
```
|
||||||
|
|
||||||
|
To get a better idea of what `/mnt/data/config` is, let's look at the in-program documentation:
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: homemaker [options] conf [src]
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
-clobber=false: delete files and directories at target
|
||||||
|
-dest="/home/alex": target directory for tasks
|
||||||
|
-force=true: create parent directories to target
|
||||||
|
-task="default": name of task to execute
|
||||||
|
-verbose=false: verbose output
|
||||||
|
```
|
||||||
|
|
||||||
|
For the purpose of our illustration, `src` is defined on the command line to be `/mnt/data/config`; namely the source
|
||||||
|
directory where your dot-files live (this will be your Git repository, Dropbox folder, rsync root, etc.). The symlinks
|
||||||
|
that Homemaker creates will point to the configuration files in this directory. You may have noticed that you can also
|
||||||
|
provide a destination directory via the `-dest` command line argument; this is where the symlinks should be created (and
|
||||||
|
it defaults to your home directory).
|
||||||
|
|
||||||
|
Another useful parameter is `task`; it will be initialized to the value `default` unless you override it on the command
|
||||||
|
line. In practice, this means that Homemaker will try to find a task called `default` and execute it. You can create as
|
||||||
|
many unique tasks as necessary to correspond to your configuration requirements, and then choose which one will execute
|
||||||
|
by specifying it on the command line in the format `-task=taskname`. Good candidates for tasks are computer names, as
|
||||||
|
shown in the configuration file below:
|
||||||
|
|
||||||
|
```
|
||||||
|
[tasks.flatline]
|
||||||
|
links = [
|
||||||
|
[".config/syncthing", ".config/syncthing_flatline"],
|
||||||
|
[".s3cfg"],
|
||||||
|
[".sabnzbd"],
|
||||||
|
[".ssh", ".ssh_flatline"],
|
||||||
|
]
|
||||||
|
|
||||||
|
[tasks.wintermute]
|
||||||
|
links = [
|
||||||
|
[".config/syncthing", ".config/syncthing_wintermute"],
|
||||||
|
[".ssh", ".ssh_wintermute"],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we see two tasks, named after the computers that will be using them, `flatline` and `wintermute`. Certain
|
||||||
|
configuration data like key pairs and other per-machine settings should only be linked on the computer that is using
|
||||||
|
them. That is to say if `flatline` and `wintermute` both try to manage the `.ssh` directory, a conflict will occur at
|
||||||
|
both the source and destination directories. We can easily resolve the source directory conflict by giving the `.ssh`
|
||||||
|
directories unique names, such as `.ssh_flatline` and `.ssh_wintermute`. The conflict at the destination directory can
|
||||||
|
be fixed as shown above; we will create per-machine tasks that will symlink only the needed directory.
|
||||||
|
|
||||||
|
You may have noticed that each entry in the `links` collection is an array, which up until now has contained only one
|
||||||
|
item. A second item can be added if the source file or directory name is different from that in the destination. If the
|
||||||
|
paths provided are relative they will be assumed to be relative to the destination and source directories respectively.
|
||||||
|
|
||||||
|
Now that we have machine specific tasks defined in our configuration file, it would be nice to still be able to share
|
||||||
|
configuration settings that are common to the two computers. We can do this by adding a `dep` array to our tasks as
|
||||||
|
shown below:
|
||||||
|
|
||||||
|
```
|
||||||
|
[tasks.common]
|
||||||
|
links = [
|
||||||
|
[".config/fish"],
|
||||||
|
[".config/keepassx"],
|
||||||
|
[".config/terminal"],
|
||||||
|
[".config/vlc"],
|
||||||
|
[".gitconfig"],
|
||||||
|
[".xinputrc"],
|
||||||
|
]
|
||||||
|
|
||||||
|
[tasks.flatline]
|
||||||
|
deps = ["common"]
|
||||||
|
links = [
|
||||||
|
[".config/syncthing", ".config/syncthing_flatline"],
|
||||||
|
[".s3cfg"],
|
||||||
|
[".sabnzbd"],
|
||||||
|
[".ssh", ".ssh_flatline"],
|
||||||
|
]
|
||||||
|
|
||||||
|
[tasks.wintermute]
|
||||||
|
deps = ["common"]
|
||||||
|
links = [
|
||||||
|
[".config/syncthing", ".config/syncthing_wintermute"],
|
||||||
|
[".ssh", ".ssh_wintermute"],
|
||||||
|
]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Homemaker will process the dependency tasks before processing the task itself.
|
||||||
|
|
||||||
|
In addition to creating links, Homemaker is capable of executing commands on a per-task basis. Commands should be
|
||||||
|
defined in an array called `cmds`, split into an item per each command line argument. All of the commands are executed
|
||||||
|
with `dest` as the working directory (as mentioned previously, this defaults to your home directory). If any command
|
||||||
|
returns a nonzero exit code, Homemaker will display an error message and stop.
|
||||||
|
|
||||||
|
The example task below will clone and install configuration files for [Vim](http://www.vim.org/) into the `.config`
|
||||||
|
directory, and create links to it from the home directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
[tasks.vim]
|
||||||
|
cmds = [
|
||||||
|
["rm", "-rf", ".config/vim"],
|
||||||
|
["git", "clone", "https://github.com/FooSoft/dotvim", ".config/vim"],
|
||||||
|
["ln", "-sf", ".config/vim/.vimrc"],
|
||||||
|
["ln", "-sf", ".config/vim/.vim"],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parameters ##
|
||||||
|
|
||||||
|
Executing Homemaker with the `-help` command line argument will trigger online help to be displayed. The list below
|
||||||
|
provides a more detailed description of what the parameters do.
|
||||||
|
|
||||||
|
* `clobber`
|
||||||
|
|
||||||
|
By default, Homemaker will only remove identically-named symlinks at the destination directory. Using this parameter
|
||||||
|
will cause Homemaker to be more aggressive and delete clashing files and entire directories as well. This can be
|
||||||
|
useful for getting rid of the default configuration settings some applications write when you run them for the first
|
||||||
|
time, but should obviously be used with caution.
|
||||||
|
|
||||||
|
* `dest`
|
||||||
|
|
||||||
|
This parameter specifies destination where Homemaker is to create symlinks. This will default to the home directory
|
||||||
|
for the current user, and as long as you are just using this application to manage dot-files, will probably never
|
||||||
|
need to be changed.
|
||||||
|
|
||||||
|
* `force`
|
||||||
|
|
||||||
|
Sometimes dot-files for an application are nested within parent directories that must exist in order to allow the
|
||||||
|
symlink to be successfully created (for example the `.config` directory in `.config/vlc`). As this is the expected
|
||||||
|
behavior, this parameter defaults to `true`; however you can explicitly disable it if required.
|
||||||
|
|
||||||
|
* `task`
|
||||||
|
|
||||||
|
This parameter is used to specify which task Homemaker will process when executed. It defaults to the `default`
|
||||||
|
task, which should be used when creating a configuration file that does not have system-specific tasks specified.
|
||||||
|
|
||||||
|
* `verbose`
|
||||||
|
|
||||||
|
When something isn't going the way you expect, you can use this parameter to make Homemaker to log everything it is
|
||||||
|
doing to console.
|
@ -70,7 +70,8 @@ func parse(filename string) (*config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
fmt.Printf("Usage: %s [options] conf [src]\n\n", os.Args[0])
|
fmt.Printf("Usage: %s [options] conf [src]\n", os.Args[0])
|
||||||
|
fmt.Print("http://foosoft.net/projects/homemaker/\n\n")
|
||||||
fmt.Print("Parameters:\n")
|
fmt.Print("Parameters:\n")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user