The dotfiles manager.
refactor: rename project to dothub
3 files changed, +28 -28
+1-1Cargo.lock
| @@ -241,7 +241,7 @@ dependencies = [ | ||
| 241 | 241 | ] |
| 242 | 242 | |
| 243 | 243 | [[package]] |
| 244 | -name = "dotman" | |
| 244 | +name = "dothub" | |
| 245 | 245 | version = "0.1.0" |
| 246 | 246 | dependencies = [ |
| 247 | 247 | "anyhow", |
+1-1Cargo.toml
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | [package] |
| 2 | -name = "dotman" | |
| 2 | +name = "dothub" | |
| 3 | 3 | version = "0.1.0" |
| 4 | 4 | edition = "2021" |
| 5 | 5 |
+26-26src/main.rs
| @@ -13,13 +13,13 @@ use std::io::Write; | ||
| 13 | 13 | use std::path::Path; |
| 14 | 14 | use std::process::Command; |
| 15 | 15 | |
| 16 | -const DOTMAN_DIR: &str = "/usr/local/share/dotman"; | |
| 16 | +const DOTHUB_DIR: &str = "/usr/local/share/dothub"; | |
| 17 | 17 | const DEFAULT_FLEX_URL: &str = |
| 18 | - "https://raw.githubusercontent.com/huncholane/dotman/refs/heads/main/flex.yml"; | |
| 18 | + "https://raw.githubusercontent.com/huncholane/dothub/refs/heads/main/flex.yml"; | |
| 19 | 19 | const GH_TOKEN_HELP_URL: &str = "https://github.com/settings/personal-access-tokens"; |
| 20 | 20 | |
| 21 | 21 | #[derive(Parser)] |
| 22 | -#[command(name = "dotman", about = "Manage dotfile repos and links", version)] | |
| 22 | +#[command(name = "dothub", about = "Manage dotfile repos and links", version)] | |
| 23 | 23 | #[command(arg_required_else_help = true)] |
| 24 | 24 | struct Cli { |
| 25 | 25 | #[command(subcommand)] |
| @@ -28,15 +28,15 @@ struct Cli { | ||
| 28 | 28 | |
| 29 | 29 | #[derive(Subcommand)] |
| 30 | 30 | enum Commands { |
| 31 | - /// Clone a git repository into the dotman store | |
| 31 | + /// Clone a git repository into the dothub store | |
| 32 | 32 | Install(InstallArgs), |
| 33 | 33 | /// Replace ~/.config/<target> with a symlink to a stored repo |
| 34 | 34 | Link(LinkArgs), |
| 35 | 35 | /// Pull latest changes for all stored repos |
| 36 | 36 | Update, |
| 37 | - /// List active links in ~/.config that point into dotman | |
| 37 | + /// List active links in ~/.config that point into dothub | |
| 38 | 38 | Active, |
| 39 | - /// List repositories installed in the dotman store | |
| 39 | + /// List repositories installed in the dothub store | |
| 40 | 40 | List, |
| 41 | 41 | /// Fetch and list repos from flex.yml (remote), sorted by GitHub stars |
| 42 | 42 | Flex(FlexArgs), |
| @@ -62,7 +62,7 @@ struct InstallArgs { | ||
| 62 | 62 | |
| 63 | 63 | #[derive(Args)] |
| 64 | 64 | struct LinkArgs { |
| 65 | - /// Repository name stored under dotman (e.g. hygo-nvim) | |
| 65 | + /// Repository name stored under dothub (e.g. hygo-nvim) | |
| 66 | 66 | name: String, |
| 67 | 67 | /// Target directory name under ~/.config (e.g. nvim, alacritty, fish) |
| 68 | 68 | target: String, |
| @@ -91,11 +91,11 @@ fn main() -> Result<()> { | ||
| 91 | 91 | } |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | -fn ensure_dotman_dir() -> Result<()> { | |
| 95 | - let path = Path::new(DOTMAN_DIR); | |
| 94 | +fn ensure_store_dir() -> Result<()> { | |
| 95 | + let path = Path::new(DOTHUB_DIR); | |
| 96 | 96 | if !path.exists() { |
| 97 | 97 | fs::create_dir_all(path) |
| 98 | - .with_context(|| format!("Failed creating {} (need sudo?)", DOTMAN_DIR))?; | |
| 98 | + .with_context(|| format!("Failed creating {} (need sudo?)", DOTHUB_DIR))?; | |
| 99 | 99 | } |
| 100 | 100 | Ok(()) |
| 101 | 101 | } |
| @@ -106,7 +106,7 @@ fn derive_repo_name(repo_url: &str) -> String { | ||
| 106 | 106 | } |
| 107 | 107 | |
| 108 | 108 | fn cmd_install(repo: &str) -> Result<()> { |
| 109 | - ensure_dotman_dir()?; | |
| 109 | + ensure_store_dir()?; | |
| 110 | 110 | |
| 111 | 111 | // Determine repo name |
| 112 | 112 | let name = derive_repo_name(repo); |
| @@ -114,7 +114,7 @@ fn cmd_install(repo: &str) -> Result<()> { | ||
| 114 | 114 | bail!("Could not infer repository name from URL: {}", repo); |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | - let dest = Path::new(DOTMAN_DIR).join(&name); | |
| 117 | + let dest = Path::new(DOTHUB_DIR).join(&name); | |
| 118 | 118 | if dest.exists() { |
| 119 | 119 | println!("Repo already exists: {}", dest.display()); |
| 120 | 120 | return Ok(()); |
| @@ -140,7 +140,7 @@ fn cmd_install(repo: &str) -> Result<()> { | ||
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | fn cmd_link(name: &str, target_name: &str) -> Result<()> { |
| 143 | - let source = Path::new(DOTMAN_DIR).join(name); | |
| 143 | + let source = Path::new(DOTHUB_DIR).join(name); | |
| 144 | 144 | if !source.exists() { |
| 145 | 145 | bail!("Source repo not found: {}", source.display()); |
| 146 | 146 | } |
| @@ -197,16 +197,16 @@ fn cmd_link(name: &str, target_name: &str) -> Result<()> { | ||
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | fn cmd_update() -> Result<()> { |
| 200 | - ensure_dotman_dir()?; | |
| 200 | + ensure_store_dir()?; | |
| 201 | 201 | if which::which("git").is_err() { |
| 202 | 202 | bail!("git is not installed or not found in PATH"); |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | - let root = Path::new(DOTMAN_DIR); | |
| 205 | + let root = Path::new(DOTHUB_DIR); | |
| 206 | 206 | let mut updated = 0usize; |
| 207 | 207 | let mut skipped = 0usize; |
| 208 | 208 | |
| 209 | - for entry in fs::read_dir(root).with_context(|| format!("Reading {}", DOTMAN_DIR))? { | |
| 209 | + for entry in fs::read_dir(root).with_context(|| format!("Reading {}", DOTHUB_DIR))? { | |
| 210 | 210 | let entry = entry?; |
| 211 | 211 | let path = entry.path(); |
| 212 | 212 | if !path.is_dir() { |
| @@ -310,7 +310,7 @@ fn cmd_active() -> Result<()> { | ||
| 310 | 310 | |
| 311 | 311 | let resolved = abs_target.canonicalize().unwrap_or(abs_target.clone()); |
| 312 | 312 | |
| 313 | - if resolved.starts_with(DOTMAN_DIR) { | |
| 313 | + if resolved.starts_with(DOTHUB_DIR) { | |
| 314 | 314 | let name = path |
| 315 | 315 | .file_name() |
| 316 | 316 | .and_then(|s| s.to_str()) |
| @@ -321,7 +321,7 @@ fn cmd_active() -> Result<()> { | ||
| 321 | 321 | } |
| 322 | 322 | |
| 323 | 323 | if found.is_empty() { |
| 324 | - println!("No active dotman links in ~/.config."); | |
| 324 | + println!("No active dothub links in ~/.config."); | |
| 325 | 325 | } else { |
| 326 | 326 | for (name, target) in found { |
| 327 | 327 | println!("{} -> {}", name, target.display()); |
| @@ -331,10 +331,10 @@ fn cmd_active() -> Result<()> { | ||
| 331 | 331 | } |
| 332 | 332 | |
| 333 | 333 | fn cmd_list() -> Result<()> { |
| 334 | - ensure_dotman_dir()?; | |
| 335 | - let root = Path::new(DOTMAN_DIR); | |
| 334 | + ensure_store_dir()?; | |
| 335 | + let root = Path::new(DOTHUB_DIR); | |
| 336 | 336 | let mut repos: Vec<String> = Vec::new(); |
| 337 | - for entry in fs::read_dir(root).with_context(|| format!("Reading {}", DOTMAN_DIR))? { | |
| 337 | + for entry in fs::read_dir(root).with_context(|| format!("Reading {}", DOTHUB_DIR))? { | |
| 338 | 338 | let entry = entry?; |
| 339 | 339 | let path = entry.path(); |
| 340 | 340 | if !path.is_dir() { |
| @@ -348,7 +348,7 @@ fn cmd_list() -> Result<()> { | ||
| 348 | 348 | } |
| 349 | 349 | repos.sort(); |
| 350 | 350 | if repos.is_empty() { |
| 351 | - println!("No repositories installed in {}.", DOTMAN_DIR); | |
| 351 | + println!("No repositories installed in {}.", DOTHUB_DIR); | |
| 352 | 352 | } else { |
| 353 | 353 | for r in repos { |
| 354 | 354 | println!("{}", r); |
| @@ -440,7 +440,7 @@ fn cmd_flex(args: FlexArgs) -> Result<()> { | ||
| 440 | 440 | for (idx, (_ty, link, stars)) in detailed.into_iter().enumerate() { |
| 441 | 441 | let rank = (idx + 1).to_string(); |
| 442 | 442 | let name = derive_repo_name(&link); |
| 443 | - let installed = Path::new(DOTMAN_DIR).join(&name).exists(); | |
| 443 | + let installed = Path::new(DOTHUB_DIR).join(&name).exists(); | |
| 444 | 444 | let installed_str = if installed { "y" } else { "n" }; |
| 445 | 445 | table.add_row(vec![rank, stars.to_string(), installed_str.to_string(), link]); |
| 446 | 446 | } |
| @@ -482,7 +482,7 @@ fn start_spinner(message: &str) -> Arc<AtomicBool> { | ||
| 482 | 482 | |
| 483 | 483 | fn fetch_text(url: &str) -> Result<String> { |
| 484 | 484 | let client = reqwest::blocking::Client::builder() |
| 485 | - .user_agent("dotman/0.1") | |
| 485 | + .user_agent("dothub/0.1") | |
| 486 | 486 | .build() |
| 487 | 487 | .context("building http client")?; |
| 488 | 488 | let resp = client |
| @@ -543,7 +543,7 @@ fn github_stars(link: &str) -> Result<u64> { | ||
| 543 | 543 | |
| 544 | 544 | let api = format!("https://api.github.com/repos/{}/{}", owner, repo); |
| 545 | 545 | let client = reqwest::blocking::Client::builder() |
| 546 | - .user_agent("dotman/0.1") | |
| 546 | + .user_agent("dothub/0.1") | |
| 547 | 547 | .build() |
| 548 | 548 | .context("building http client")?; |
| 549 | 549 | let resp = client |
| @@ -608,7 +608,7 @@ fn github_stars_batch(links: &[String], token: Option<&str>) -> Result<HashMap<S | ||
| 608 | 608 | } |
| 609 | 609 | |
| 610 | 610 | let client = reqwest::blocking::Client::builder() |
| 611 | - .user_agent("dotman/0.1") | |
| 611 | + .user_agent("dothub/0.1") | |
| 612 | 612 | .build() |
| 613 | 613 | .context("building http client")?; |
| 614 | 614 |