cli/
io.rs

1//! # io
2//!
3//! IO helper functions
4//!
5
6#[cfg(test)]
7#[path = "io_test.rs"]
8mod io_test;
9
10use crate::error::CargoMakeError;
11use fsio::file::modify_file;
12use fsio::path as fsio_path;
13use fsio::path::from_path::FromPath;
14use glob::glob;
15use ignore::WalkBuilder;
16use std::collections::HashSet;
17use std::fs::File;
18use std::io;
19use std::path::PathBuf;
20
21pub(crate) fn create_text_file(text: &str, extension: &str) -> Result<String, CargoMakeError> {
22    let file_path = fsio_path::get_temporary_file_path(extension);
23
24    match fsio::file::write_text_file(&file_path, text) {
25        Ok(_) => Ok(file_path),
26        Err(error) => {
27            error!("Unable to create file: {} {:#?}", &file_path, &error);
28            Err(error.into())
29        }
30    }
31}
32
33pub(crate) fn create_file(
34    write_content: &dyn Fn(&mut File) -> io::Result<()>,
35    extension: &str,
36) -> Result<String, CargoMakeError> {
37    let file_path = fsio_path::get_temporary_file_path(extension);
38
39    match modify_file(&file_path, write_content, false) {
40        Ok(_) => Ok(file_path),
41        Err(error) => {
42            error!("Unable to write to file: {} {:#?}", &file_path, &error);
43            Err(error.into())
44        }
45    }
46}
47
48pub(crate) fn delete_file(file: &str) {
49    match fsio::file::delete(file) {
50        Ok(_) => debug!("File deleted: {}", &file),
51        Err(error) => debug!("Unable to delete file: {} {:#?}", &file, error),
52    }
53}
54
55pub(crate) fn write_text_file(file_path: &str, text: &str) -> bool {
56    match fsio::file::write_text_file(file_path, text) {
57        Ok(_) => true,
58        Err(_) => false,
59    }
60}
61
62pub(crate) fn read_text_file(file_path: &PathBuf) -> Result<String, CargoMakeError> {
63    debug!("Opening file: {:#?}", &file_path);
64
65    Ok(fsio::file::read_text_file(file_path)?)
66}
67
68pub(crate) fn get_path_list(
69    glob_pattern: &str,
70    include_files: bool,
71    include_dirs: bool,
72    ignore_type: Option<String>,
73) -> Vec<String> {
74    let mut path_list = vec![];
75    match glob(glob_pattern) {
76        Ok(paths) => {
77            for entry in paths {
78                match entry {
79                    Ok(path) => {
80                        if (include_dirs && path.is_dir()) || (include_files && path.is_file()) {
81                            let mut value_string: String = FromPath::from_path(&path);
82                            value_string = value_string.replace("\\", "/");
83                            if !value_string.starts_with("./") {
84                                value_string.insert_str(0, "./");
85                            }
86
87                            path_list.push(value_string);
88                        }
89                    }
90                    Err(error) => {
91                        error!(
92                            "Error while iterating over path entries of glob: {}, error: {:#?}",
93                            glob_pattern, error
94                        );
95                        return vec![];
96                    }
97                }
98            }
99        }
100        Err(error) => {
101            error!(
102                "Error while running glob: {}, error: {:#?}",
103                glob_pattern, error
104            );
105            return vec![];
106        }
107    }
108
109    if !path_list.is_empty() {
110        if let Some(ignore_type_value) = ignore_type {
111            let mut included_paths = HashSet::new();
112
113            match ignore_type_value.as_str() {
114                "git" => {
115                    for entry in WalkBuilder::new("./")
116                        .hidden(true)
117                        .parents(true)
118                        .git_ignore(true)
119                        .git_exclude(true)
120                        .build()
121                    {
122                        match entry {
123                            Ok(path) => {
124                                let mut value_string: String = FromPath::from_path(&path.path());
125                                value_string = value_string.replace("\\", "/");
126                                included_paths.insert(value_string);
127                            }
128                            Err(error) => error!(
129                                "Error while running git ignore path checks, error: {:#?}",
130                                error
131                            ),
132                        }
133                    }
134                }
135                _ => error!("Unsupported ignore type: {}", &ignore_type_value),
136            };
137
138            if included_paths.is_empty() {
139                path_list.clear();
140            } else {
141                let org_path_list = path_list;
142                path_list = vec![];
143                for path in org_path_list {
144                    if included_paths.contains(&path) {
145                        path_list.push(path);
146                    }
147                }
148            }
149        }
150    }
151
152    path_list
153}
154
155pub(crate) fn canonicalize_to_string(path_string: &str) -> String {
156    fsio_path::canonicalize_or(path_string, path_string)
157}