Compare commits
3
Commits
c3f6b500fc
...
3d504ee6b3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d504ee6b3 | ||
|
|
8407c99ba4 | ||
|
|
088b88b225 |
@@ -32,7 +32,7 @@ install-systemd:
|
||||
install-dashboard:
|
||||
cd dashboard && npm ci && npm run build
|
||||
install -dm755 $(INSTALL_STATIC)
|
||||
cp -r dashboard/dist/. $(INSTALL_STATIC)/
|
||||
cp -r claw-store/static/. $(INSTALL_STATIC)/
|
||||
@echo "Dashboard installed to $(INSTALL_STATIC)"
|
||||
|
||||
## Install node-specific config (NODE=architect|tank)
|
||||
|
||||
@@ -21,8 +21,14 @@ pub fn write_cargo_config(warm_path: &Path, hot_target_path: &Path) -> Result<()
|
||||
String::new()
|
||||
};
|
||||
|
||||
// Drop any leading copies of our own marker comment before stripping the
|
||||
// [build] section — it sits above the [build] header, outside the range
|
||||
// strip_section tracks, so without this it would survive every
|
||||
// regenerate cycle and duplicate one more time.
|
||||
let existing = strip_leading_marker(&existing);
|
||||
|
||||
// Remove old [build] block (from its header to the next section or EOF).
|
||||
let stripped = strip_section(&existing, "build");
|
||||
let stripped = strip_section(existing, "build");
|
||||
|
||||
let new_content = format!(
|
||||
"# claw-store managed — do not edit manually\n\
|
||||
@@ -37,6 +43,21 @@ pub fn write_cargo_config(warm_path: &Path, hot_target_path: &Path) -> Result<()
|
||||
.with_context(|| format!("writing {}", config_path.display()))
|
||||
}
|
||||
|
||||
const MANAGED_MARKER: &str = "# claw-store managed — do not edit manually";
|
||||
|
||||
/// Strip leading copies of `MANAGED_MARKER`, one per line, from the start of `src`.
|
||||
fn strip_leading_marker(src: &str) -> &str {
|
||||
let mut rest = src;
|
||||
while let Some(line_end) = rest.find('\n') {
|
||||
if rest[..line_end].trim() == MANAGED_MARKER {
|
||||
rest = &rest[line_end + 1..];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rest
|
||||
}
|
||||
|
||||
/// Remove a TOML section `[name]` and all its key=value lines from `src`,
|
||||
/// stopping at the next `[section]` header or EOF.
|
||||
fn strip_section(src: &str, name: &str) -> String {
|
||||
@@ -102,6 +123,46 @@ mod tests {
|
||||
assert!(verify_cargo_config(&warm, &hot).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_cargo_config_idempotent_no_duplicate_marker() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let warm = dir.path().join("proj");
|
||||
std::fs::create_dir_all(&warm).unwrap();
|
||||
let hot: std::path::PathBuf = "/hot/targets/proj".into();
|
||||
|
||||
write_cargo_config(&warm, &hot).unwrap();
|
||||
write_cargo_config(&warm, &hot).unwrap();
|
||||
write_cargo_config(&warm, &hot).unwrap();
|
||||
|
||||
let content = std::fs::read_to_string(warm.join(".cargo/config.toml")).unwrap();
|
||||
assert_eq!(content.matches("claw-store managed").count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_cargo_config_heals_existing_duplicate_marker() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let warm = dir.path().join("proj");
|
||||
let cargo_dir = warm.join(".cargo");
|
||||
std::fs::create_dir_all(&cargo_dir).unwrap();
|
||||
std::fs::write(
|
||||
cargo_dir.join("config.toml"),
|
||||
"# claw-store managed — do not edit manually\n\
|
||||
[build]\n\
|
||||
target-dir = \"/hot/targets/proj\"\n\
|
||||
# claw-store managed — do not edit manually\n\
|
||||
[env]\n\
|
||||
FOO = \"bar\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let hot: std::path::PathBuf = "/hot/targets/proj".into();
|
||||
write_cargo_config(&warm, &hot).unwrap();
|
||||
|
||||
let content = std::fs::read_to_string(cargo_dir.join("config.toml")).unwrap();
|
||||
assert_eq!(content.matches("claw-store managed").count(), 1);
|
||||
assert!(content.contains("FOO = \"bar\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_cargo_config_detects_missing() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
[node]
|
||||
name = "morpheus"
|
||||
role = "secondary"
|
||||
|
||||
[hot]
|
||||
path = "/hot/targets"
|
||||
max_gb = 80
|
||||
stale_hours = 48
|
||||
|
||||
[warm]
|
||||
projects_path = "/slab/projects"
|
||||
# No ZFS on morpheus — zfs_dataset is set so the config parses, but snapshot
|
||||
# timers are not enabled and snapshot commands will log errors and continue.
|
||||
zfs_dataset = "none"
|
||||
snapshot_retain_hours = 24
|
||||
snapshot_retain_days = 7
|
||||
snapshot_retain_weeks = 4
|
||||
|
||||
# No cold tier and no replication — morpheus is a standalone dev node.
|
||||
Reference in New Issue
Block a user