feat: one store directory per checkout
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user