1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
//! # rfm
//!
//! **`rfm`** is a convenient and intuitive way to interact with files on OS.
//! Function naming is similar to Unix commands
//! _(`ls`, `mkdir`, `mv`, `rm`, `cp`, `touch` etc.)_,
//! so you can easily figure out how to use it.
mod utils;
use std::{
    fs::{copy, create_dir, read_dir, remove_dir_all, remove_file},
    io::{Error, ErrorKind, Result},
    path::PathBuf,
};

macro_rules! err {
    ($text:expr, $kind:expr) => {
        return Err(Error::new($kind, $text));
    };

    ($text:expr) => {
        err!($text, ErrorKind::Other)
    };
}

// ------------------------------------------------------------------------ //

/// Read the directory/directories and return the content.
/// `dir` - takes the path to the directory whose contents you want to
/// retrieve.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `dir` contains file or directory does not exist.
/// - Param `dir` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::ls;
///
///  let dir = std::path::Path::new("./dir1").to_path_buf();
///
///  let directory_contents = ls(&dir)?;
/// ```
pub fn ls(dir: &PathBuf) -> Result<Vec<PathBuf>> {
    let mut elements: Vec<PathBuf> = vec![];
    for entry in read_dir(dir)? {
        let dir = entry?;
        elements.push(dir.path())
    }
    Ok(elements)
}

/// Deletes files/directories (including nested files/directories).
/// `from` - takes a list of paths of what you want to delete.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `from` contains file or directory does not exist.
/// - Param `from` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::rm;
///
///  let dir = std::path::Path::new("./dir").to_path_buf();
///  let file = std::path::Path::new("./file.txt").to_path_buf();
///  let elements: Vec<&std::path::PathBuf> = vec![&dir, &file];
///
///  rm(&elements)?;
/// ```
pub fn rm(from: &Vec<&PathBuf>) -> Result<()> {
    if from.len() <= 0 {
        let err_msg = format!("from param is empty - {:?}", from);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    for i in from {
        if i.is_file() {
            remove_file(i)?;
        } else {
            remove_dir_all(i)?;
        }
    }

    Ok(())
}

/// Creates a file/files in the passed path.
/// `file_paths` - takes a list of paths of what you want to create.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `file_paths` contains file or directory does not exist.
/// - Param `file_paths` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::touch;
///
///  let file_1 = std::path::Path::new("./file-1.txt").to_path_buf();
///  let file_2 = std::path::Path::new("./file-2.txt").to_path_buf();
///  let files: Vec<&std::path::PathBuf> = vec![&file_1, &file_2];
///
///  touch(&files)?;
/// ```
pub fn touch(file_paths: &Vec<&PathBuf>) -> Result<()> {
    if file_paths.len() <= 0 {
        let err_msg = format!("file_paths param is empty - {:?}", file_paths);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    Ok(utils::create(file_paths, &utils::CreateType::File)?)
}

/// Creates a directory/directories on the passed path. **Note**, the function
/// creates all missing directories if they occur in the passed parameter.
/// `dir_paths` - takes a list of paths of what you want to create.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `dir_paths` contains file or directory does not exist.
/// - Param `dir_paths` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::mkdir;
///
///  let dir_1 = std::path::Path::new("./dir1").to_path_buf();
///  let dir_2 = std::path::Path::new("./dir2").to_path_buf();
///  let dirs: Vec<&std::path::PathBuf> = vec![&dir_1, &dir_2];
///
///  mkdir(&dirs)?;
/// ```
pub fn mkdir(dir_paths: &Vec<&PathBuf>) -> Result<()> {
    if dir_paths.len() <= 0 {
        let err_msg = format!("dir_paths param is empty - {:?}", dir_paths);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    Ok(utils::create(dir_paths, &utils::CreateType::Dir)?)
}

/// Copies files and directories, including nested files and directories.
/// `from` - takes a list of paths of what you want to copy.
/// `to` - destination path.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `from` contains file or directory does not exist.
/// - Param `from` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::cp;
///
///  let file = std::path::Path::new("./file.txt").to_path_buf();
///  let dir = std::path::Path::new("./dir").to_path_buf();
///  let elements: Vec<&std::path::PathBuf> = vec![&file, &dir];
///  let to = std::path::Path::new("./tests/expected_files").to_path_buf();
///
///  cp(&elements, &to)?;
/// ```
pub fn cp(from: &Vec<&PathBuf>, to: &PathBuf) -> Result<u64> {
    if from.len() <= 0 {
        let err_msg = format!("from param is empty - {:?}", from);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    if from.len() == 1 && from[0].is_file() {
        let file_name = &from[0].file_name().unwrap();
        let path_to = &to.join(file_name);

        Ok(copy(&from[0], &path_to)?)
    } else {
        for path in from {
            if path.is_file() {
                let from: Vec<&PathBuf> = vec![path];
                cp(&from, &to)?;
            } else {
                let dir_name = path.file_name().unwrap();
                let path_to = &to.join(dir_name);
                create_dir(&path_to)?;

                for i in ls(&path).unwrap() {
                    let from: Vec<&PathBuf> = vec![&i];
                    cp(&from, &path_to)?;
                }
            }
        }

        Ok(1)
    }
}

/// Moves files and directories, including nested files and directories.
/// `from` - takes a list of paths of what you want to copy.
/// `to` - destination path.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `from` contains file or directory does not exist.
/// - Param `from` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::mv;
///
///  let file = std::path::Path::new("./file.txt").to_path_buf();
///  let dir = std::path::Path::new("./dir").to_path_buf();
///  let elements: Vec<&std::path::PathBuf> = vec![&file, &dir];
///  let to = std::path::Path::new("./tests/expected_files").to_path_buf();
///
///  mv(&elements, &to)?;
/// ```
pub fn mv(from: &Vec<&PathBuf>, to: &PathBuf) -> Result<()> {
    if from.len() <= 0 {
        let err_msg = format!("from param is empty - {:?}", from);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    let copy = cp(&from, &to);
    Ok(match copy {
        Ok(_res) => rm(&from),
        Err(error) => panic!("Copying error: {:?}", error),
    }?)
}

/// Clears the directory/directories of all child files and directories on the
/// passed path.
/// `paths` - takes a list of paths of what you want to clean.
///
/// # Errors
///
/// This function will return an error in the following situations, but is not
/// limited to just these case:
///
/// - Param `paths` contains file or directory does not exist.
/// - Param `paths` contains file or directory with invalid name.
/// - The current process does not have the permission to access to input
/// params.
///
/// # Example
///
/// ```rust,ignore
///  extern crate rfm;
///  use rfm::clean;
///
///  let dir_1 = std::path::Path::new("./dir1").to_path_buf();
///  let dir_2 = std::path::Path::new("./dir2").to_path_buf();
///  let dirs: Vec<&std::path::PathBuf> = vec![&dir_1, &dir_2];
///
///  clean(&dirs)?;
/// ```
pub fn clean(paths: &Vec<&PathBuf>) -> Result<()> {
    if paths.len() <= 0 {
        let err_msg = format!("paths param is empty - {:?}", paths);
        err!(err_msg, ErrorKind::InvalidInput);
    }

    if paths.len() == 1 {
        rm(&paths)?;
        let vec_of_paths = vec![paths[0]];
        Ok(mkdir(&vec_of_paths)?)
    } else {
        for i in paths {
            let elements: Vec<&PathBuf> = vec![i];
            clean(&elements)?;
        }
        Ok(())
    }
}