xtask/extendrtests/
with_absolute_path.rs

1use std::error::Error;
2use std::path::Path;
3
4use toml_edit::{DocumentMut, InlineTable, Value};
5use xshell::Shell;
6
7use crate::extendrtests::path_helper::RCompatiblePath;
8
9pub(crate) const R_FOLDER_PATH: &str = "tests/extendrtests";
10
11const RUST_FOLDER_PATH: &str = "tests/extendrtests/src/rust";
12const CARGO_TOML: &str = "Cargo.toml";
13
14#[derive(Debug)]
15pub(crate) struct DocumentMutHandle<'a> {
16    document: Vec<u8>,
17    shell: &'a Shell,
18}
19
20impl Drop for DocumentMutHandle<'_> {
21    fn drop(&mut self) {
22        let _rust_folder = self.shell.push_dir(RUST_FOLDER_PATH);
23        self.shell
24            .write_file(CARGO_TOML, &self.document)
25            .expect("Failed to restore Cargo.toml");
26    }
27}
28
29pub(crate) fn swap_extendr_api_path(shell: &Shell) -> Result<DocumentMutHandle, Box<dyn Error>> {
30    let current_path = shell.current_dir();
31    let _rust_folder = shell.push_dir(RUST_FOLDER_PATH);
32
33    let original_cargo_toml_bytes = read_file_with_line_ending(shell, CARGO_TOML)?;
34
35    let original_cargo_toml: DocumentMut =
36        std::str::from_utf8(&original_cargo_toml_bytes)?.parse()?;
37
38    let mut cargo_toml = original_cargo_toml.clone();
39
40    let extendr_api_entry =
41        get_extendr_api_entry(&mut cargo_toml).ok_or("`extendr-api` not found in Cargo.toml")?;
42
43    let mut replacement = InlineTable::new();
44
45    let item = Value::from(get_replacement_path_extendr_api(&current_path));
46    replacement.entry("path").or_insert(item);
47    *extendr_api_entry = Value::InlineTable(replacement);
48
49    // save altered paths
50    shell.write_file(CARGO_TOML, cargo_toml.to_string())?;
51    Ok(DocumentMutHandle {
52        document: original_cargo_toml_bytes,
53        shell,
54    })
55}
56
57fn get_replacement_path_extendr_api(path: &Path) -> String {
58    let path = path.adjust_for_r();
59
60    format!("{path}/extendr-api")
61}
62
63fn get_extendr_api_entry(document: &mut DocumentMut) -> Option<&mut Value> {
64    document
65        .get_mut("patch")?
66        .get_mut("crates-io")?
67        .get_mut("extendr-api")?
68        .as_value_mut()
69}
70
71fn read_file_with_line_ending<P: AsRef<Path>>(
72    shell: &Shell,
73    path: P,
74) -> Result<Vec<u8>, Box<dyn Error>> {
75    let file_contents = shell.read_binary_file(path)?;
76    Ok(file_contents)
77}