[][src]Crate hm

hm is a commandline program to help with dotfile (and more) management.

It can handle putting configuration files where they should go, but its real strength lies in the solutions it'll execute - shell scripts, usually - to pull a git repository, compile something from source, etc.

hm exists because I bring along a few utilities to all Linux boxes I regularly use, and those are often built from source. So rather than manually install all dependency libraries, then build each dependent piece, then finally the top-level dependent program, I built hm. It also provides functionality to thread off heavier operations into task threads, which regularly report back their status with Worker objects over a std::sync::mpsc.

hm can also perform dependency resolution, thanks to the solvent crate. You can provide a big ol' list of tasks to complete, each with their own dependencies, and as long as you have a solveable dependency graph, you can get workable batches from get_task_batches(). They will be in some order that will resolve your dependencies, but that order is non-deterministic - if there's multiple ways to solve a graph, you'll probably get all those different ways back if you run it multiple times.

The crate provides this library, which is in turn used by the bin hm (in src/bin/main.rs). hm is a commandline program to help with dotfile (and more) management.

It can handle putting configuration files where they should go, but its real strength lies in the solutions it'll execute - shell scripts, usually - to pull a git repository, compile something from source, etc.

hm exists because I bring along a few utilities to all Linux boxes I regularly use, and those are often built from source. So rather than manually install all dependency libraries, then build each dependent piece, then finally the top-level dependent program, I built hm.

gfycat of it in action

  1. create a config.toml file either anywhere or in ~/.config/homemaker/.
  2. enter things to do things to in the file. example:
## config.toml

[[obj]]
file = 'tmux.conf'
source = '~/dotfiles/.tmux.conf'
destination = '~/.tmux.conf'
method = 'symlink'

[[obj]]
task = 'zt'
solution = 'cd ~/dotfiles/zt && git pull'
dependencies = 'maim, slop'

[[obj]]
task = 'slop'
source = '~/dotfiles/zt/slop'
solution = 'cd ~/dotfiles/zt/slop; make clean; cmake -DCMAKE_INSTALL_PREFIX="/usr" ./ && make && sudo make install'
method = 'execute'
  1. hm ~/path/to/your/config.toml

built with spacemacs

thanks to actual good code: serde toml symlink solvent indicatif console

Modules

config

Define our Config and Worker. Implement how to take the config.toml and turn it into a Config { files: Vec<ManagedObject> }. Describes the Worker object, which is how we communicate back to our main() thread about how our task is going.

hmerror

Custom Error implementation to allow for our own kind, along with run-of-the-mill std::io::Errors.

Macros

function

equivalent of func for stacktrace/debugging see https://stackoverflow.com/questions/38088067/equivalent-of-func-or-function-in-rust

Functions

do_tasks

Take our list of ManagedObjects to do stuff to, and determine if they're simple or complex (simple is symlink or copy, complex maybe compilation or pulling a git repo). We just do the simple ones, as they won't be computationally expensive.

get_task_batches

Create a non-cyclical dependency graph and give it back as a Vec<Vec<ManagedObject>>. Will return a CyclicalDependencyError if the graph is unsolveable. Intended to be used with either mgmt::execute_solution or mgmt::send_tasks_off_to_college.

perform_operation_on

Pretty simple. We currently support only symlinking, but copying would be trivial. Hand off to the actual function that does the work.

send_tasks_off_to_college

Take a ManagedObject task, an mpsc tx, and a Progressbar. Execute task and regularly inform the rx (all the way over back in main())about our status using config::Worker.

symlink_file

Either create a symlink to a file or directory. Generally we'll be doing this in a tilde'd home subdirectory, so we need to be careful to get our Path right.