feat: take the store root as an option
This commit is contained in:
@@ -13,11 +13,11 @@ build = "build.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.6.6", features = ["derive"] }
|
||||
clap = { version = "4.6.6", features = ["derive", "env"] }
|
||||
clap_complete = "4.6.9"
|
||||
anyhow = "1.0.104"
|
||||
serde_json = "1.0.145"
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "4.6.6", features = ["derive"] }
|
||||
clap = { version = "4.6.6", features = ["derive", "env"] }
|
||||
clap_complete = "4.6.9"
|
||||
|
||||
@@ -134,4 +134,5 @@ from the git `origin` remote.
|
||||
|
||||
Currently `ahab` respects the following environment variables.
|
||||
|
||||
- `AHAB_LINK_ROOT`: root of the out-of-repo store `ahab link` moves paths into - defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`
|
||||
- `AHAB_LINK_ROOT`: where `ahab link` keeps its store - the same as `--store`,
|
||||
which takes precedence, and defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Subcommand;
|
||||
use clap::{Args, Subcommand};
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Link {
|
||||
@@ -13,6 +13,9 @@ pub enum Link {
|
||||
/// Link to a store path that already exists
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
|
||||
#[command(flatten)]
|
||||
store: Store,
|
||||
},
|
||||
|
||||
/// Move paths in the store back into the repository
|
||||
@@ -22,6 +25,9 @@ pub enum Link {
|
||||
/// Restore every path this repository has in the store
|
||||
#[arg(long)]
|
||||
all: bool,
|
||||
|
||||
#[command(flatten)]
|
||||
store: Store,
|
||||
},
|
||||
|
||||
/// List untracked paths a sandbox would still see
|
||||
@@ -40,5 +46,17 @@ pub enum Link {
|
||||
/// Terminate porcelain entries with NUL
|
||||
#[arg(short = 'z')]
|
||||
null: bool,
|
||||
|
||||
#[command(flatten)]
|
||||
store: Store,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct Store {
|
||||
/// Where the out-of-repo store lives
|
||||
///
|
||||
/// Defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`.
|
||||
#[arg(long = "store", env = "AHAB_LINK_ROOT", value_name = "DIR")]
|
||||
pub root: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ mod postgres;
|
||||
|
||||
pub use ahab::{Ahab, Commands};
|
||||
pub use django::Django;
|
||||
pub use link::Link;
|
||||
pub use link::{Link, Store};
|
||||
pub use postgres::{Format, Postgres};
|
||||
|
||||
13
src/main.rs
13
src/main.rs
@@ -53,15 +53,22 @@ fn run(command: cli::Commands) -> Result<ExitCode> {
|
||||
Ok(done)
|
||||
}
|
||||
cli::Commands::Link { command } => match command {
|
||||
cli::Link::Add { paths, force } => scripts::link::add(&paths, force).map(|()| done),
|
||||
cli::Link::Restore { paths, all } => scripts::link::restore(&paths, all).map(|()| done),
|
||||
cli::Link::Add {
|
||||
paths,
|
||||
force,
|
||||
store,
|
||||
} => scripts::link::add(&paths, force, store.root.as_deref()).map(|()| done),
|
||||
cli::Link::Restore { paths, all, store } => {
|
||||
scripts::link::restore(&paths, all, store.root.as_deref()).map(|()| done)
|
||||
}
|
||||
// the one command with something to say through its exit code
|
||||
cli::Link::Check {
|
||||
paths,
|
||||
porcelain,
|
||||
null,
|
||||
exit_code,
|
||||
} => scripts::link::check(&paths, porcelain, null, exit_code),
|
||||
store,
|
||||
} => scripts::link::check(&paths, porcelain, null, exit_code, store.root.as_deref()),
|
||||
},
|
||||
cli::Commands::Completions { shell } => {
|
||||
scripts::completions::completions(shell)?;
|
||||
|
||||
@@ -13,8 +13,8 @@ const BACKUP_SUFFIX: &str = ".ahab-bak";
|
||||
const LOCAL_NAMESPACE: &str = "_local";
|
||||
|
||||
// move untracked paths out of the repo and symlink them back
|
||||
pub fn add(paths: &[PathBuf], force: bool) -> Result<()> {
|
||||
let repo = Repo::discover()?;
|
||||
pub fn add(paths: &[PathBuf], force: bool, store: Option<&Path>) -> Result<()> {
|
||||
let repo = Repo::discover(store)?;
|
||||
let report = Report::new(&repo);
|
||||
|
||||
if let [path] = paths {
|
||||
@@ -36,8 +36,8 @@ pub fn add(paths: &[PathBuf], force: bool) -> Result<()> {
|
||||
}
|
||||
|
||||
// move paths in the store back into the repo, the inverse of add
|
||||
pub fn restore(paths: &[PathBuf], all: bool) -> Result<()> {
|
||||
let repo = Repo::discover()?;
|
||||
pub fn restore(paths: &[PathBuf], all: bool, store: Option<&Path>) -> Result<()> {
|
||||
let repo = Repo::discover(store)?;
|
||||
let report = Report::new(&repo);
|
||||
|
||||
let paths = match (all, paths) {
|
||||
@@ -178,8 +178,14 @@ fn warn(msg: impl std::fmt::Display) {
|
||||
}
|
||||
|
||||
// list untracked paths not in the store, i.e. what a sandbox can still read
|
||||
pub fn check(paths: &[PathBuf], porcelain: bool, null: bool, exit_code: bool) -> Result<ExitCode> {
|
||||
let repo = Repo::discover()?;
|
||||
pub fn check(
|
||||
paths: &[PathBuf],
|
||||
porcelain: bool,
|
||||
null: bool,
|
||||
exit_code: bool,
|
||||
store: Option<&Path>,
|
||||
) -> Result<ExitCode> {
|
||||
let repo = Repo::discover(store)?;
|
||||
let pathspecs = relative_pathspecs(&repo, paths)?;
|
||||
|
||||
let mut exposed = Vec::new();
|
||||
@@ -422,10 +428,17 @@ struct Repo {
|
||||
}
|
||||
|
||||
impl Repo {
|
||||
fn discover() -> Result<Self> {
|
||||
fn discover(store: Option<&Path>) -> Result<Self> {
|
||||
let root = git_root()?;
|
||||
let store = store_root()?.join(repo_components(&root)?);
|
||||
Ok(Self { root, store })
|
||||
let store = match store {
|
||||
Some(store) => store.to_path_buf(),
|
||||
None => store_root()?,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
root: root.clone(),
|
||||
store: store.join(repo_components(&root)?),
|
||||
})
|
||||
}
|
||||
|
||||
fn relative(&self, src: &Path) -> Result<PathBuf> {
|
||||
@@ -677,18 +690,16 @@ fn sanitize(s: &str) -> String {
|
||||
}
|
||||
|
||||
fn store_root() -> Result<PathBuf> {
|
||||
if let Some(root) = non_empty_var("AHAB_LINK_ROOT") {
|
||||
return Ok(PathBuf::from(root));
|
||||
}
|
||||
if let Some(xdg) = non_empty_var("XDG_DATA_HOME") {
|
||||
return Ok(PathBuf::from(xdg).join("ahab"));
|
||||
}
|
||||
|
||||
let home = non_empty_var("HOME")
|
||||
.ok_or_else(|| anyhow!("none of AHAB_LINK_ROOT, XDG_DATA_HOME or HOME is set"))?;
|
||||
.filter(|v| !v.is_empty())
|
||||
.ok_or_else(|| anyhow!("neither XDG_DATA_HOME nor HOME is set"))?;
|
||||
|
||||
Ok(PathBuf::from(home).join(".local/share/ahab"))
|
||||
}
|
||||
|
||||
fn non_empty_var(name: &str) -> Option<OsString> {
|
||||
env::var_os(name).filter(|v| !v.is_empty())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user