From 8cd2d2f80f5e8a3b3bec1cebb488f79bfbe1a2d7 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 29 Oct 2026 22:36:17 -0600 Subject: [PATCH] fix(settings): a repository on this computer may be a Windows drive path or a rooted Unix path on any system The portable Windows job (P11c run 6) failed ledger-core's `where_backups_go_is_checked`: `/srv/books.git` is not an absolute path to Windows, and `C:\books` was read as the host `C` of a networked address. `backup.git_remote` now reads a drive path (one letter, a colon, a slash or backslash) as a path on this computer, as git does, and a path from `/` as rooted on every system git runs on; the test holds the three forms on every OS. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp --- crates/ledger-core/src/settings.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/ledger-core/src/settings.rs b/crates/ledger-core/src/settings.rs index 1f20afb..8477eac 100644 --- a/crates/ledger-core/src/settings.rs +++ b/crates/ledger-core/src/settings.rs @@ -1198,13 +1198,22 @@ pub fn check(key: &Key, v: &Value) -> Result { } // A path on this computer is named from the root of its disk: // the server's working folder is no place to name one from. - let networked = match s.split_once("://") { - Some((scheme, _)) => scheme != "file", - None => s - .split_once(':') - .is_some_and(|(host, _)| !host.contains('/')), - }; - if !networked && !s.starts_with("file://") && !std::path::Path::new(&s).is_absolute() { + // `C:\books` is a Windows drive path, not the host `C` (git + // reads it the same way), and `/srv/books` is rooted on every + // system git runs on (on Windows through its own shell). + let drive_path = s.len() > 2 + && s.as_bytes()[0].is_ascii_alphabetic() + && &s[1..2] == ":" + && matches!(&s[2..3], "\\" | "/"); + let networked = !drive_path + && match s.split_once("://") { + Some((scheme, _)) => scheme != "file", + None => s + .split_once(':') + .is_some_and(|(host, _)| !host.contains('/')), + }; + let rooted = drive_path || s.starts_with('/') || std::path::Path::new(&s).is_absolute(); + if !networked && !s.starts_with("file://") && !rooted { return Err(format!( "{name} {s:?}: a repository on this computer is named from the root of its disk (such as /srv/books)" )); @@ -1854,6 +1863,8 @@ mod tests { "git@host:owner/books.git", "https://host/owner/books", "/srv/books.git", + "C:\\books\\acme.git", + "D:/books/acme.git", ] { assert_eq!(check(remote, &json!(ok)).unwrap(), json!(ok), "{ok}"); }