git_copyright/
file_ops.rs1use crate::CError;
4use futures::join;
5use futures::Future;
6use regex::Regex;
7use std::io::{BufRead, BufReader};
8use std::sync::Arc;
9use std::{path::Path, path::PathBuf};
10use tokio::io::{AsyncReadExt, AsyncWriteExt};
11
12pub async fn read_write_copyright(
13 filepath: PathBuf,
14 regex: Arc<Regex>,
15 years_fut: impl Future<Output = String>,
16 copyright_line: impl Future<Output = String>,
17) -> Result<(), CError> {
18 let (years, copyright_line) = join!(years_fut, copyright_line);
19
20 let file = std::fs::File::open(&filepath)
23 .map_err(|_| CError::ReadError(filepath.display().to_string()))?;
24 let file_header = BufReader::new(file).lines().take(3);
25
26 for (line_nr, line_) in file_header.enumerate() {
27 if let Ok(line_) = line_ {
28 if let Some(cap) = regex.captures_iter(&line_).take(1).next() {
29 if years == &cap[1] {
30 log::debug!(
31 "File {} has correct copyright with years {}",
32 filepath.display(),
33 years
34 );
35 return Ok(());
36 } else {
37 println!(
38 "File {} has copyright with year(s) {} on line {} but should have {}",
39 filepath.display(),
40 &cap[1],
41 line_nr,
42 years
43 );
44 return write_copyright(&filepath, ©right_line, Some(line_nr)).await;
45 }
46 }
47 }
48 }
49
50 println!(
51 "File {} has no copyright but should have {}",
52 filepath.display(),
53 years
54 );
55 write_copyright(&filepath, ©right_line, None).await
56}
57
58async fn write_copyright(
59 filepath: &Path,
60 copyright_line: &str,
61 line_nr: Option<usize>,
62) -> Result<(), CError> {
63 let mut file = tokio::fs::File::open(filepath)
64 .await
65 .map_err(|_| CError::ReadError(filepath.display().to_string()))?;
66 let mut data = Vec::new();
67 file.read_to_end(&mut data).await?;
68 let mut data: Vec<&str> = std::str::from_utf8(&data)?.split("\n").collect();
69
70 match line_nr {
71 Some(line_nr) => {
72 data[line_nr] = ©right_line;
73 }
74 None => {
75 if data.len() >= 1 && data[0].starts_with("#!") {
76 data.insert(1, copyright_line);
79 } else {
80 data.insert(0, copyright_line);
81 }
82 }
83 }
84
85 let mut file = tokio::fs::File::create(filepath)
86 .await
87 .map_err(|_| CError::WriteError(filepath.display().to_string()))?;
88 file.write_all(data.join("\n").as_bytes())
89 .await
90 .map_err(|_| CError::WriteError(filepath.display().to_string()))?;
91
92 Ok(())
93}