1use crate::{cargo_cli::CargoCli, output::OutputContext};
5use camino::{Utf8Path, Utf8PathBuf};
6use color_eyre::{
7 eyre::{bail, WrapErr},
8 Result,
9};
10
11pub(crate) fn read_contents(
13 root: &Utf8Path,
14 rel_paths: impl IntoIterator<Item = impl AsRef<Utf8Path>>,
15) -> Result<(Utf8PathBuf, String)> {
16 let mut paths_tried_str = String::new();
17 for path in rel_paths {
18 let abs_path = root.join(path);
19 match std::fs::read_to_string(&abs_path) {
20 Ok(contents) => return Ok((abs_path, contents)),
21 Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
22 paths_tried_str.push_str(" - ");
24 paths_tried_str.push_str(abs_path.as_str());
25 paths_tried_str.push('\n');
26 continue;
27 }
28 Err(err) => {
29 return Err(err)
30 .wrap_err_with(|| format!("error reading contents at {}", abs_path));
31 }
32 }
33 }
34
35 bail!("none of these paths were found:\n{}", paths_tried_str)
36}
37
38pub(crate) fn regenerate_lockfile(output: OutputContext) -> Result<()> {
40 let cargo_cli = CargoCli::new("tree", output);
43 cargo_cli
44 .to_expression()
45 .stdout_null()
46 .run()
47 .wrap_err("updating Cargo.lock failed")?;
48 Ok(())
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use std::convert::TryInto;
55 use tempfile::TempDir;
56
57 #[test]
58 fn test_read_contents() -> Result<()> {
59 let dir = TempDir::new()?;
60 let root: &Utf8Path = dir.path().try_into().expect("path is UTF-8");
61 std::fs::write(dir.path().join("foo"), "foo-contents")?;
62 std::fs::write(dir.path().join("bar"), "bar-contents")?;
63
64 assert_eq!(
65 read_contents(root, ["foo", "bar"]).unwrap().1,
66 "foo-contents"
67 );
68 assert_eq!(
69 read_contents(root, ["bar", "foo"]).unwrap().1,
70 "bar-contents"
71 );
72 assert_eq!(
73 read_contents(root, ["missing", "foo"]).unwrap().1,
74 "foo-contents"
75 );
76 println!(
77 "{}",
78 read_contents(root, ["missing", "missing-2"]).unwrap_err(),
79 );
80
81 Ok(())
82 }
83}