fix: follow a link anywhere under the store base

This commit is contained in:
2026-09-21 13:04:36 +00:00
parent c96211a28b
commit 22d735d52c
4 changed files with 46 additions and 8 deletions

View File

@@ -9,7 +9,7 @@ use std::path::{Path, PathBuf};
use anyhow::{Context, Result, anyhow, bail};
use self::store::{Leads, Repo, ignored, leads, resolve, symlink_metadata_opt, tracked};
use self::store::{Leads, Repo, held, ignored, leads, resolve, symlink_metadata_opt, tracked};
use crate::cli::link as cli;
use crate::ctx::Ctx;
use crate::fsops::suffixed;
@@ -104,7 +104,6 @@ pub fn restore(ctx: &Ctx, args: &cli::Restore) -> Result<()> {
fn restore_one(ctx: &Ctx, repo: &Repo, path: &Path, report: &Report) -> Result<()> {
let src = resolve(path)?;
let rel = repo.relative(&src)?;
let stored = repo.store.join(&rel);
let Some(meta) = symlink_metadata_opt(&src)? else {
bail!("{} does not exist", rel.display());
@@ -116,14 +115,16 @@ fn restore_one(ctx: &Ctx, repo: &Repo, path: &Path, report: &Report) -> Result<(
);
}
// followed to wherever under the base it points, so a checkout that moved
// or a store laid out by an older ahab can still take its files back
let dest = read_link(&src)?;
if dest != stored {
let Some(stored) = held(repo, &src, &dest) else {
bail!(
"{} points at {}, which is not where the store keeps it",
"{} points at {}, which is not in the store",
rel.display(),
dest.display()
);
}
};
if symlink_metadata_opt(&stored)?.is_none() {
bail!("{} is missing from the store", rel.display());
}