Crate hm

Source
Expand description

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.

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'
platform = "linux::debian"
  1. hm ~/path/to/your/config.toml

built with spacemacs and neovim

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§

copy_item
Copy our {file|directory} to the destination. Generally we’ll be doing this in a tilde’d home subdirectory, so we need to be careful to get our Path right.
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. 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_item
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.