diff --git a/src/commands/link.rs b/src/commands/link.rs
index 2e20f49..a20a518 100644
--- a/src/commands/link.rs
+++ b/src/commands/link.rs
@@ -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());
}
diff --git a/src/commands/link/check.rs b/src/commands/link/check.rs
index b0f36f9..2e8b58f 100644
--- a/src/commands/link/check.rs
+++ b/src/commands/link/check.rs
@@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
use anyhow::{Result, anyhow};
-use super::store::{Leads, Repo, leads, resolve, symlink_metadata_opt};
+use super::store::{Leads, Repo, held, leads, resolve, symlink_metadata_opt};
use crate::cli::link as cli;
use crate::cmd::{Cmd, LsFiles};
use crate::ctx::Ctx;
@@ -179,10 +179,10 @@ fn classify(repo: &Repo, rel: &Path, mark: char) -> Result