commit - 909f9a264cd944a07663229da8c7a3bcea3b8669
commit + 1d4fd61d620ea15c2ef27cf0d2b43393e67143bf
blob - 3052036d179adf94e91e509edee5c4300de5ebb2
blob + 19085ff7394171e68015bf889e644db55d39e9a8
--- marmita.rs
+++ marmita.rs
const VENDOR_DIR: &str = "vendor";
const VENDOR_FILE: &str = "vendor/VENDOR";
+const LINK_FILE: &str = "link.mk";
const TRAILER: &str =
"Managed by marmita(1). Use 'marmita update' to refresh.\n";
format!("{stem}.rs")
}
+fn link_name(file: &str) -> String {
+ let stem = Path::new(file)
+ .file_stem()
+ .and_then(|s| s.to_str())
+ .unwrap_or(file);
+ format!("{stem}.mk")
+}
+
fn looks_like_oid(s: &str) -> bool {
s.len() >= 7 && s.len() <= 40 && s.chars().all(|c| c.is_ascii_hexdigit())
}
url: &str,
spec: &str,
file: &str,
-) -> Result<(String, Vec<u8>), String> {
+) -> Result<(String, Vec<u8>, Option<Vec<u8>>), String> {
let tmp = make_tempdir()?;
let result = (|| {
let repo = clone(url, &tmp)?;
let commit = resolve_commit(&repo, spec)?;
let bytes = read_blob(&repo, &commit, file)?;
- Ok((commit, bytes))
+ let link = read_blob(&repo, &commit, LINK_FILE).ok();
+ Ok((commit, bytes, link))
})();
let _ = fs::remove_dir_all(&tmp);
result
let file = file_arg.unwrap_or_else(|| deduce_filename(&url));
let spec = reference.as_deref().unwrap_or("HEAD");
- let (commit, bytes) = fetch_file(&url, spec, &file)?;
+ let (commit, bytes, link) = fetch_file(&url, spec, &file)?;
fs::create_dir_all(VENDOR_DIR)
.map_err(|e| format!("mkdir {VENDOR_DIR}: {e}"))?;
let dest = Path::new(VENDOR_DIR).join(&file);
fs::write(&dest, &bytes)
.map_err(|e| format!("write {}: {e}", dest.display()))?;
+ let link_dest = Path::new(VENDOR_DIR).join(link_name(&file));
+ match link {
+ Some(b) => fs::write(&link_dest, b)
+ .map_err(|e| format!("write {}: {e}", link_dest.display()))?,
+ None => {
+ let _ = fs::remove_file(&link_dest);
+ }
+ }
let mut entries: Vec<Entry> = read_manifest()?
.into_iter()
continue;
}
};
- let (commit, bytes) = fetch_file(&e.origin, &spec, &e.file)?;
+ let (commit, bytes, link) = fetch_file(&e.origin, &spec, &e.file)?;
let dest = Path::new(VENDOR_DIR).join(&e.file);
fs::write(&dest, &bytes)
.map_err(|err| format!("write {}: {err}", dest.display()))?;
+ let link_dest = Path::new(VENDOR_DIR).join(link_name(&e.file));
+ match link {
+ Some(b) => fs::write(&link_dest, b).map_err(|err| {
+ format!("write {}: {err}", link_dest.display())
+ })?,
+ None => {
+ let _ = fs::remove_file(&link_dest);
+ }
+ }
let changed = e.commit != commit;
e.commit = commit.clone();
e.date = today_utc();
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
Err(e) => return Err(format!("remove {}: {e}", path.display())),
}
+ let link_path = Path::new(VENDOR_DIR).join(link_name(file));
+ let _ = fs::remove_file(&link_path);
write_manifest(&mut entries)?;
println!("removed {file}");
Ok(())