feat: one store directory per checkout

This commit is contained in:
2026-09-21 13:02:26 +00:00
parent 9adcfed28e
commit c96211a28b
3 changed files with 99 additions and 18 deletions

View File

@@ -109,7 +109,24 @@ fn git_root(ctx: &Ctx) -> Result<PathBuf> {
)))?)
}
// the remote names the project and the checkout names its clone, so two clones
// never share a directory
fn repo_components(ctx: &Ctx, root: &Path) -> Result<PathBuf> {
Ok(project_components(ctx, root)?.join(checkout_name(root)))
}
// `<dir>-<hash>`: the directory for a human, the hash of the canonical path
// for two checkouts in directories of one name
fn checkout_name(root: &Path) -> String {
let hash = fingerprint(root.as_os_str().as_bytes());
match root.file_name() {
Some(dir) => format!("{}-{hash}", cleaned(&dir.to_string_lossy())),
None => hash,
}
}
fn project_components(ctx: &Ctx, root: &Path) -> Result<PathBuf> {
if let Some(url) = git_origin_url(ctx) {
if let Some(components) = components_from_remote(&url) {
return Ok(components);
@@ -302,11 +319,13 @@ pub(super) fn leads(path: &Path, root: &Path) -> Leads {
#[cfg(test)]
mod tests {
use super::{components_from_remote, fingerprint, normalized, sanitize, sanitize_name};
use super::{
checkout_name, components_from_remote, fingerprint, normalized, sanitize, sanitize_name,
};
use std::collections::HashSet;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
#[test]
fn parses_every_spelling_of_a_remote() {
@@ -407,6 +426,17 @@ mod tests {
assert_eq!(sanitize_name(OsStr::new("afurnik")), "afurnik");
}
#[test]
fn a_checkout_is_named_by_its_directory_and_its_path() {
let one = checkout_name(Path::new("/home/a/afurnik"));
let two = checkout_name(Path::new("/home/b/afurnik"));
assert!(one.starts_with("afurnik-"), "{one}");
assert_ne!(one, two);
// the root itself has no directory to be named after
assert_eq!(checkout_name(Path::new("/")), fingerprint(b"/"));
}
#[test]
fn a_store_root_is_absolute_with_the_dots_folded_out() {
// it is written into every symlink add creates, and compared against the