cargo_hakari/
helpers.rs

1// Copyright (c) The cargo-guppy Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use crate::{cargo_cli::CargoCli, output::OutputContext};
5use camino::{Utf8Path, Utf8PathBuf};
6use color_eyre::{
7    eyre::{bail, WrapErr},
8    Result,
9};
10
11/// Read the contents of the first file that matches and is present. Errors out.
12pub(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                // The path wasn't found -- continue to the next one.
23                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
38/// Regenerate the lockfile after dependency updates.
39pub(crate) fn regenerate_lockfile(output: OutputContext) -> Result<()> {
40    // This seems to be the cheapest way to update the lockfile.
41    // cargo update -p <hakari-package> can sometimes cause unnecessary index updates.
42    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}