dir.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. mod utils;
  2. use ignore::Walk;
  3. use serde::Serialize;
  4. use tempfile::{self, tempdir};
  5. use utils::get_dir_name_from_path;
  6. use std::fs::{self, metadata};
  7. #[derive(Debug, Serialize)]
  8. pub struct DiskEntry {
  9. pub path: String,
  10. pub is_dir: bool,
  11. pub name: String,
  12. }
  13. fn is_dir(file_name: String) -> crate::Result<bool> {
  14. match metadata(file_name) {
  15. Ok(md) => Result::Ok(md.is_dir()),
  16. Err(err) => Result::Err(err.to_string().into()),
  17. }
  18. }
  19. pub fn walk_dir(path_copy: String) -> crate::Result<Vec<DiskEntry>> {
  20. println!("Trying to walk: {}", path_copy.as_str());
  21. let mut files_and_dirs: Vec<DiskEntry> = vec![];
  22. for result in Walk::new(path_copy) {
  23. if let Ok(entry) = result {
  24. let display_value = entry.path().display();
  25. let _dir_name = display_value.to_string();
  26. if let Ok(flag) = is_dir(display_value.to_string()) {
  27. files_and_dirs.push(DiskEntry {
  28. path: display_value.to_string(),
  29. is_dir: flag,
  30. name: display_value.to_string(),
  31. });
  32. }
  33. }
  34. }
  35. Result::Ok(files_and_dirs)
  36. }
  37. pub fn list_dir_contents(dir_path: String) -> crate::Result<Vec<DiskEntry>> {
  38. fs::read_dir(dir_path)
  39. .map_err(|err| crate::Error::with_chain(err, "read string failed"))
  40. .and_then(|paths| {
  41. let mut dirs: Vec<DiskEntry> = vec![];
  42. for path in paths {
  43. let dir_path = path.expect("dirpath error").path();
  44. let _dir_name = dir_path.display();
  45. dirs.push(DiskEntry {
  46. path: format!("{}", _dir_name),
  47. is_dir: true,
  48. name: get_dir_name_from_path(_dir_name.to_string()),
  49. });
  50. }
  51. Ok(dirs)
  52. })
  53. }
  54. pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir) -> ()>(callback: F) -> crate::Result<()> {
  55. let dir = tempdir()?;
  56. callback(&dir);
  57. dir.close()?;
  58. Ok(())
  59. }
  60. #[cfg(test)]
  61. mod test {
  62. use super::*;
  63. use quickcheck_macros::quickcheck;
  64. use totems::assert_ok;
  65. // check is dir function by passing in arbitrary strings
  66. #[quickcheck]
  67. fn qc_is_dir(f: String) -> bool {
  68. // is the string runs through is_dir and comes out as an OK result then it must be a DIR.
  69. if let Ok(_) = is_dir(f.clone()) {
  70. std::path::PathBuf::from(f).exists()
  71. } else {
  72. true
  73. }
  74. }
  75. #[test]
  76. // check the walk_dir function
  77. fn check_walk_dir() {
  78. // define a relative directory string test/
  79. let dir = String::from("test/");
  80. // add the files to this directory
  81. let file_one = format!("{}test.txt", &dir).to_string();
  82. let file_two = format!("{}test_binary", &dir).to_string();
  83. // call walk_dir on the directory
  84. let res = walk_dir(dir.clone());
  85. // assert that the result is Ok()
  86. assert_ok!(&res);
  87. // destruct the OK into a vector of DiskEntry Structs
  88. if let Ok(vec) = res {
  89. // assert that the vector length is only 3
  90. assert_eq!(vec.len(), 3);
  91. // get the first DiskEntry
  92. let first = &vec[0];
  93. // get the second DiskEntry
  94. let second = &vec[1];
  95. // get the third DiskEntry
  96. let third = &vec[2];
  97. // check the fields for the first DiskEntry
  98. assert_eq!(first.path, dir);
  99. assert_eq!(first.is_dir, true);
  100. assert_eq!(first.name, dir);
  101. if second.path.contains(".txt") {
  102. // check the fields for the second DiskEntry
  103. assert_eq!(second.path, file_one);
  104. assert_eq!(second.is_dir, false);
  105. assert_eq!(second.name, file_one);
  106. // check the fields for the third DiskEntry
  107. assert_eq!(third.path, file_two);
  108. assert_eq!(third.is_dir, false);
  109. assert_eq!(third.name, file_two);
  110. } else {
  111. // check the fields for the second DiskEntry
  112. assert_eq!(second.path, file_two);
  113. assert_eq!(second.is_dir, false);
  114. assert_eq!(second.name, file_two);
  115. // check the fields for the third DiskEntry
  116. assert_eq!(third.path, file_one);
  117. assert_eq!(third.is_dir, false);
  118. assert_eq!(third.name, file_one);
  119. }
  120. }
  121. }
  122. #[test]
  123. // check the list_dir_contents function
  124. fn check_list_dir_contents() {
  125. // define a relative directory string test/
  126. let dir = String::from("test/");
  127. // call list_dir_contents on the dir string
  128. let res = list_dir_contents(dir);
  129. // assert that the result is Ok()
  130. assert_ok!(&res);
  131. // destruct the vector from the Ok()
  132. if let Ok(vec) = res {
  133. // assert the length of the vector is 2
  134. assert_eq!(vec.len(), 2);
  135. // get the two DiskEntry structs in this vector
  136. let first = &vec[0];
  137. let second = &vec[1];
  138. if first.path.contains(".txt") {
  139. // check the fields for the first DiskEntry
  140. assert_eq!(first.path, "test/test.txt".to_string());
  141. assert_eq!(first.is_dir, true);
  142. assert_eq!(first.name, "test.txt".to_string());
  143. // check the fields for the second DiskEntry
  144. assert_eq!(second.path, "test/test_binary".to_string());
  145. assert_eq!(second.is_dir, true);
  146. assert_eq!(second.name, "test_binary".to_string());
  147. } else {
  148. // check the fields for the first DiskEntry
  149. assert_eq!(second.path, "test/test.txt".to_string());
  150. assert_eq!(second.is_dir, true);
  151. assert_eq!(second.name, "test.txt".to_string());
  152. // check the fields for the second DiskEntry
  153. assert_eq!(first.path, "test/test_binary".to_string());
  154. assert_eq!(first.is_dir, true);
  155. assert_eq!(first.name, "test_binary".to_string());
  156. }
  157. }
  158. }
  159. #[test]
  160. // test the with_temp_dir function
  161. fn check_test_dir() {
  162. // create a callback closure that takes in a TempDir type and prints it.
  163. let callback = |td: &tempfile::TempDir| {
  164. println!("{:?}", td);
  165. };
  166. // execute the with_temp_dir function on the callback
  167. let res = with_temp_dir(callback);
  168. // assert that the result is an OK type.
  169. assert_ok!(res);
  170. }
  171. }