two-way file system sync
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

file_tree.rs 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. use std::ffi::{OsStr, OsString};
  2. use std::fs;
  3. use std::path::Path;
  4. use std::sync::Arc;
  5. use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
  6. use tokio::sync::Mutex;
  7. use super::{Database, Error};
  8. pub struct FileTree {
  9. db: Arc<Mutex<Database>>,
  10. new_version_notifiers: Vec<UnboundedSender<NewVersionEvent>>,
  11. next_version_source: u64,
  12. root_path: OsString,
  13. }
  14. impl FileTree {
  15. pub fn open(db: Arc<Mutex<Database>>, directory: &OsStr) -> Result<FileTree, Error> {
  16. // Check whether the database entry for this file tree exists and fetch the root
  17. // file ID.
  18. // TODO
  19. // Create a lock file to make sure that the directory is only synchronized once.
  20. // TODO
  21. // Clear up any temporary files which were left over.
  22. // TODO
  23. // Enqueue the root directory to be rechecked against the database.
  24. // TODO
  25. Ok(FileTree {
  26. db,
  27. new_version_notifiers: Vec::new(),
  28. next_version_source: 0,
  29. root_path: directory.to_owned(),
  30. })
  31. }
  32. pub fn root_path(&self) -> &OsStr {
  33. &self.root_path
  34. }
  35. pub fn new_notifier(&mut self) -> NewVersionNotifier {
  36. let (send, receive) = unbounded_channel();
  37. self.new_version_notifiers.push(send);
  38. NewVersionNotifier { receive }
  39. }
  40. pub fn new_version_source(&mut self) -> NewVersionSource {
  41. let source = NewVersionSource {
  42. id: self.next_version_source,
  43. };
  44. self.next_version_source += 1;
  45. source
  46. }
  47. // TODO: Limit on size of all temporary files, make this function return a
  48. // future which yields a temporary file once enough space is available?
  49. pub fn create_temporary_file(&self, _target_path: &OsStr) -> Result<TemporaryFile, Error> {
  50. // TODO
  51. panic!("Not yet implemented.");
  52. }
  53. pub async fn lock_path<P>(&mut self, path: P) -> Option<LockedPath>
  54. where
  55. P: AsRef<Path>,
  56. {
  57. let _path = path.as_ref();
  58. // TODO
  59. panic!("Not yet implemented.");
  60. }
  61. pub async fn lock_two_paths<P1, P2>(&mut self, path1: P1, path2: P2) -> Option<LockedPath>
  62. where
  63. P1: AsRef<Path>,
  64. P2: AsRef<Path>,
  65. {
  66. let _path1 = path1.as_ref();
  67. let _path2 = path2.as_ref();
  68. // TODO
  69. panic!("Not yet implemented.");
  70. }
  71. }
  72. pub struct LockedPath {
  73. // TODO
  74. }
  75. impl LockedPath {
  76. pub fn get_file_info<P>(&self, path: P) -> Option<FileInfo>
  77. where
  78. P: AsRef<Path>,
  79. {
  80. let _path = path.as_ref();
  81. // TODO
  82. panic!("Not yet implemented.");
  83. }
  84. pub fn get_directory_listing(&self, _path: &OsStr) -> Option<Vec<FileInfo>> {
  85. // TODO
  86. panic!("Not yet implemented.");
  87. }
  88. pub fn local_file_changed(&self, _source: NewVersionSource, _path: &OsStr, _info: FileInfo) {
  89. // TODO
  90. panic!("Not yet implemented.");
  91. }
  92. pub fn local_file_removed<P>(&self, _source: NewVersionSource, _path: P)
  93. where
  94. P: AsRef<Path>,
  95. {
  96. // TODO
  97. panic!("Not yet implemented.");
  98. }
  99. pub fn update_file(
  100. &self,
  101. _source: NewVersionSource,
  102. _path: &OsStr,
  103. _info: FileInfo,
  104. _contents: TemporaryFile,
  105. _origin: OriginInfo,
  106. ) -> Result<NewVersionEvent, Error> {
  107. // TODO
  108. panic!("Not yet implemented.");
  109. }
  110. pub fn create_directory<P>(
  111. &self,
  112. _source: NewVersionSource,
  113. _path: P,
  114. _origin: OriginInfo,
  115. ) -> Result<NewVersionEvent, Error>
  116. where
  117. P: AsRef<Path>,
  118. {
  119. // TODO
  120. panic!("Not yet implemented.");
  121. }
  122. }
  123. impl Drop for LockedPath {
  124. fn drop(&mut self) {
  125. // Release the lock again.
  126. // TODO
  127. }
  128. }
  129. pub struct NewVersionNotifier {
  130. // TODO: Probably should not be public.
  131. pub receive: UnboundedReceiver<NewVersionEvent>,
  132. }
  133. pub struct NewVersionEvent {
  134. pub source: NewVersionSource,
  135. // TODO
  136. }
  137. #[derive(Clone, Copy, PartialEq, Eq)]
  138. pub struct NewVersionSource {
  139. id: u64,
  140. }
  141. pub struct FileInfo {
  142. pub file_name: OsString,
  143. pub file_type: FileType,
  144. /// Local modification time in seconds since the Unix epoch. Only valid for files and symlinks,
  145. /// not for directories.
  146. pub local_modification_time: Option<u64>,
  147. /// Local size of the file in bytes. Only valid for files and symlinks, not for directories.
  148. pub local_size: Option<u64>,
  149. // TODO
  150. }
  151. #[derive(PartialEq)]
  152. pub enum FileType {
  153. File,
  154. Directory,
  155. Symlink,
  156. }
  157. impl FileType {
  158. pub fn from(ft: fs::FileType) -> Option<FileType> {
  159. if ft.is_file() {
  160. Some(FileType::File)
  161. } else if ft.is_dir() {
  162. Some(FileType::Directory)
  163. } else if ft.is_symlink() {
  164. Some(FileType::Symlink)
  165. } else {
  166. None
  167. }
  168. }
  169. }
  170. pub struct TemporaryFile {
  171. // TODO
  172. }
  173. pub enum OriginInfo {
  174. Local,
  175. // TODO: For remote sources, include the previous version to detect conflicts?
  176. Remote,
  177. }