LCOV - code coverage report
Current view: top level - internal/src - packaging.rs (source / functions) Hit Total Coverage
Test: unnamed Lines: 97 98 99.0 %
Date: 2024-10-23 19:20:50 Functions: 17 30 56.7 %

          Line data    Source code
       1             : // smoelius: Since the update to `rust_embed` 8.3.0, `unnecessary_conversion_for_trait` started
       2             : // firing on `struct Template`. Requiring `!expr.span.from_expansion()` in
       3             : // `unnecessary_conversion_for_trait` causes one of its tests to fail. So allow the lint for now.
       4             : // smoelius: `abs_home_path` now fires as well.
       5             : #![cfg_attr(dylint_lib = "general", allow(abs_home_path))]
       6             : #![cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
       7             : #![cfg_attr(dylint_lib = "supplementary", allow(unnecessary_conversion_for_trait))]
       8             : 
       9             : use crate::cargo::{current_metadata, package};
      10             : use anyhow::{anyhow, Context, Result};
      11             : use rust_embed::RustEmbed;
      12             : use std::{
      13             :     fs::{create_dir_all, OpenOptions},
      14             :     io::Write,
      15             :     path::Path,
      16             : };
      17             : 
      18         164 : #[derive(RustEmbed)]
      19             : #[folder = "template"]
      20             : #[exclude = "Cargo.lock"]
      21             : #[exclude = "target/*"]
      22             : struct Template;
      23             : 
      24           9 : pub fn new_template(to: &Path) -> Result<()> {
      25          81 :     for path in Template::iter() {
      26          72 :         let embedded_file = Template::get(&path)
      27          72 :             .ok_or_else(|| anyhow!("Could not get embedded file `{}`", path))?;
      28          72 :         let to_path = to.join(path.trim_end_matches('~'));
      29          72 :         let parent = to_path
      30          72 :             .parent()
      31          72 :             .ok_or_else(|| anyhow!("Could not get parent directory"))?;
      32          72 :         create_dir_all(parent).with_context(|| {
      33           0 :             format!("`create_dir_all` failed for `{}`", parent.to_string_lossy())
      34          72 :         })?;
      35          72 :         let mut file = OpenOptions::new()
      36          72 :             .create(true)
      37          72 :             .truncate(true)
      38          72 :             .write(true)
      39          72 :             .open(&to_path)
      40          72 :             .with_context(|| format!("Could not open `{}`", to_path.to_string_lossy()))?;
      41          72 :         file.write_all(&embedded_file.data)
      42          72 :             .with_context(|| format!("Could not write to {to_path:?}"))?;
      43             :     }
      44             : 
      45           9 :     Ok(())
      46           9 : }
      47             : 
      48             : // smoelius: If a package is checked out in the current directory, this must be dealt with:
      49             : // error: current package believes it's in a workspace when it's not
      50          13 : pub fn isolate(path: &Path) -> Result<()> {
      51          13 :     let manifest = path.join("Cargo.toml");
      52          13 :     let mut file = OpenOptions::new()
      53          13 :         .append(true)
      54          13 :         .open(&manifest)
      55          13 :         .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?;
      56             : 
      57          13 :     writeln!(file)
      58          13 :         .and_then(|()| writeln!(file, "[workspace]"))
      59          13 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
      60             : 
      61          13 :     Ok(())
      62          13 : }
      63             : 
      64             : // smoelius: If you clone, say, `dylint-template` and run `cargo test` on it, it will obtain Dylint
      65             : // packages from `crates.io`. But for the tests in this repository, you often want it to use the
      66             : // packages in this repository. The function `use_local_packages` patches a workspace's `Cargo.toml`
      67             : // file to do so.
      68           9 : pub fn use_local_packages(path: &Path) -> Result<()> {
      69           9 :     let metadata = current_metadata()?;
      70             : 
      71           9 :     let manifest = path.join("Cargo.toml");
      72             : 
      73           9 :     let mut file = OpenOptions::new()
      74           9 :         .append(true)
      75           9 :         .open(&manifest)
      76           9 :         .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?;
      77             : 
      78             :     // smoelius: `use_local_packages` broke when `dylint_linting` was removed from the workspace.
      79             :     // For now, add `dylint_linting` manually.
      80           9 :     writeln!(file)
      81           9 :         .and_then(|()| writeln!(file, "[patch.crates-io]"))
      82           9 :         .and_then(|()| {
      83           9 :             writeln!(
      84           9 :                 file,
      85           9 :                 r#"dylint_linting = {{ path = "{}" }}"#,
      86           9 :                 metadata
      87           9 :                     .workspace_root
      88           9 :                     .join("utils/linting")
      89           9 :                     .to_string()
      90           9 :                     .replace('\\', "\\\\")
      91           9 :             )
      92           9 :         })
      93           9 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
      94             : 
      95          72 :     for package_id in &metadata.workspace_members {
      96          63 :         let package = package(&metadata, package_id)?;
      97          63 :         if package.publish == Some(vec![])
      98          45 :             || package
      99          45 :                 .targets
     100          45 :                 .iter()
     101          72 :                 .all(|target| target.kind.iter().all(|kind| kind != "lib"))
     102             :         {
     103          36 :             continue;
     104          27 :         }
     105          27 :         let path = package
     106          27 :             .manifest_path
     107          27 :             .parent()
     108          27 :             .ok_or_else(|| anyhow!("Could not get parent directory"))?;
     109          27 :         writeln!(
     110          27 :             file,
     111          27 :             r#"{} = {{ path = "{}" }}"#,
     112          27 :             package.name,
     113          27 :             path.to_string().replace('\\', "\\\\")
     114          27 :         )
     115          27 :         .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?;
     116             :     }
     117             : 
     118           9 :     Ok(())
     119           9 : }
     120             : 
     121             : #[cfg(test)]
     122             : mod test {
     123             :     use super::*;
     124             :     use std::fs::read_to_string;
     125             :     use toml_edit::{DocumentMut, Item};
     126             : 
     127             :     #[cfg_attr(
     128             :         dylint_lib = "assert_eq_arg_misordering",
     129             :         allow(assert_eq_arg_misordering)
     130             :     )]
     131             :     #[test]
     132           1 :     fn template_includes_only_whitelisted_paths() {
     133             :         const PATHS: [&str; 8] = [
     134             :             ".cargo/config.toml",
     135             :             ".gitignore",
     136             :             "Cargo.toml~",
     137             :             "README.md",
     138             :             "rust-toolchain",
     139             :             "src/lib.rs",
     140             :             "ui/main.rs",
     141             :             "ui/main.stderr",
     142             :         ];
     143             : 
     144           1 :         let mut paths_sorted = PATHS.to_vec();
     145           1 :         paths_sorted.sort_unstable();
     146           1 :         assert_eq!(paths_sorted, PATHS);
     147             : 
     148           1 :         let paths = Template::iter()
     149           8 :             .filter(|path| PATHS.binary_search(&&**path).is_err())
     150           1 :             .collect::<Vec<_>>();
     151           1 : 
     152           1 :         assert!(paths.is_empty(), "found {paths:#?}");
     153           1 :     }
     154             : 
     155             :     #[test]
     156           1 :     fn template_has_initial_version() {
     157           1 :         let contents = read_to_string("template/Cargo.toml~").unwrap();
     158           1 :         let document = contents.parse::<DocumentMut>().unwrap();
     159           1 :         let version = document
     160           1 :             .as_table()
     161           1 :             .get("package")
     162           1 :             .and_then(Item::as_table)
     163           1 :             .and_then(|table| table.get("version"))
     164           1 :             .and_then(Item::as_str)
     165           1 :             .unwrap();
     166           1 :         assert_eq!("0.1.0", version);
     167           1 :     }
     168             : }

Generated by: LCOV version 1.14