UPDATE
This article is an early idea of what the tool could be. Since I wrote it, it has evolved and changed a lot. Stay tuned for more infos about the current version of the tool. The tool has since been renamed to ins
Idea
I want to unify lots of instantOS things into an instantCLI
the base command will just be instant
Dotfiles
I wrote about ideas for dotfile management a while back. I thought about it some more. I am abandoning the “home dir as git worktree” approach. It’s just not flexible enough.
What follows is incomprehensible pseudocode for the new solution
Overlaying repos
Dotfiles can come from multiple repos. Those repos have an order. If a dotfile exists in multiple repos, the version from the one with higher priority gets used. This allows for easy application of themes. It is not specified, which applications a theme can theme, and multiple themes can be used and removed very easily
Repos are structured like in yadm, the main difference being that dotfiles are kept in a subdirectory, corresponding to their place in the home directory
~/.local/share/instantdots/dots/.bashrc
installs to
~/.bashrc
~/.local/share/instantdots/dots/.config/kitty/kitty.conf
installs to
~/.config/kitty/kitty.conf
Leaving the user alone
instantOS should remain hackable without bothering users who do not want to learn its tools. This means user configurations should not be overridden, ever. The tool will keep a list of valid hashes for a file, and if a file doesn’t match any of them, it is assumed to be modified by the user or another program and will be left alone.
resetting files
If a modified file is marked as valid, it will automatically be reset. to the latest official version on the next update.
applying
struct dotfile {
repo_path // absolute path to source git repo
target_path
hash: Option<hash>
target_hash: Option<hash>
}
impl dotfile {
fn is_outdated(self) -> bool {
if not self.target_path.exists()
return true
if self.source is newer than the target
return true
current_hash = self.get
}
fn is_modified(self) -> bool {
if not self.target_path.exists()
modified = false
else if newest_hash is newer than file modification date
modified = false
else if self.get_target_hash in get_valid_hashes(self.path)
modified = false
else
modified = true
}
fn get_target_hash() -> Option<Hash> {
if !target_path.exists()
return none
if hashes.contains(self.path) and self.path is older {
return newest hashes[self.path]
} else {
newhash compute_hash(target_path)
if hashes.get(newhash) is not None
return hashes[newhash]
else
savehash(newhash)
return newhash
}
}
fn get_source_hash() {
// similar to target_hash, but hash should be inserted into
valid_hashes. Slightly less lazy
}
fn apply {
if self.is_modified()
return
if not self.is_outdated()
return
cp self.source_file self.target_path
compute_and_save_target_hash()
}
fn fetch {
if self.modified or self.current_hash != self.targethash
cp self.target_path self.source_file
}
}
filemap = HashMap<FilePath, Dotfile>
for repo in repos
for file in repo.update_file_tree
//this should override things when same path
filemap.insert(path, file)
for file on filemap.values
file.applyfile
tech
Rust clap CLI validhashes in sqlite DB repo sources in toml config commands to add and remove repos command to edit the config file libgit2 or simple git wrapper to clone things probably anyhow for errors
TODO
look for good sql lib should support schema updates look for good terminal output lib
interface
instant dot
apply
update
reset
clone
status //which repos are currently applied etc
init // initialize new dotfile repo
fetch // fetch modified files from disk to repo
// to allow for yadm style workflow
DB schema
table hashes
DATE Created
String Hash
String Path
Bool valid
primary key Hash, Path
dotfile repo
git repo with public source url (should be) instantdots.toml
name = "catppuccin"
author = person_xyz
dots_dir = ./dots
Cleanup
old invalid hashes should be cleaned newest invalid hash should be kept all valid hashes should be kept