Browse Source

Start working on automatic file history

timvisee 7 years ago
parent
commit
6da2e5ca2a
7 changed files with 151 additions and 2 deletions
  1. 12 0
      Cargo.lock
  2. 1 1
      api/src/file/remote_file.rs
  3. 3 0
      cli/Cargo.toml
  4. 15 0
      cli/history.toml
  5. 14 1
      cli/src/action/upload.rs
  6. 102 0
      cli/src/history.rs
  7. 4 0
      cli/src/main.rs

+ 12 - 0
Cargo.lock

@@ -370,6 +370,9 @@ dependencies = [
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1311,6 +1314,14 @@ dependencies = [
  "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 ]
 
 
+[[package]]
+name = "toml"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 [[package]]
 name = "typenum"
 name = "typenum"
 version = "1.10.0"
 version = "1.10.0"
@@ -1630,6 +1641,7 @@ dependencies = [
 "checksum tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29a89e4ad0c8f1e4c9860e605c38c69bfdad3cccd4ea446e58ff588c1c07a397"
 "checksum tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29a89e4ad0c8f1e4c9860e605c38c69bfdad3cccd4ea446e58ff588c1c07a397"
 "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913"
 "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913"
 "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a"
 "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a"
+"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9"
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
 "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"

+ 1 - 1
api/src/file/remote_file.rs

@@ -26,7 +26,7 @@ const SHARE_FRAGMENT_PATTERN: &'static str = r"^([a-zA-Z0-9-_+/]+)?\s*$";
 ///
 ///
 /// The struct contains the file ID, the file URL, the key that is required
 /// The struct contains the file ID, the file URL, the key that is required
 /// in combination with the file, and the owner key.
 /// in combination with the file, and the owner key.
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct RemoteFile {
 pub struct RemoteFile {
     /// The ID of the file on that server.
     /// The ID of the file on that server.
     id: String,
     id: String,

+ 3 - 0
cli/Cargo.toml

@@ -26,3 +26,6 @@ ffsend-api = { version = "*", path = "../api" }
 open = "1"
 open = "1"
 pbr = "1"
 pbr = "1"
 rpassword = "2.0"
 rpassword = "2.0"
+serde = "1.0"
+serde_derive = "1.0"
+toml = "0.4"

+ 15 - 0
cli/history.toml

@@ -0,0 +1,15 @@
+[[files]]
+id = "462aad1de5"
+time = "2018-04-18T22:45:01.121174527Z"
+host = "http://localhost:8081/"
+url = "http://localhost:8081/download/462aad1de5/"
+secret = [244, 53, 118, 229, 172, 83, 160, 232, 231, 244, 119, 59, 193, 11, 114, 78]
+owner_token = "07734e9bfc8fc7d59873"
+
+[[files]]
+id = "d0ef8edb0a"
+time = "2018-04-18T22:45:06.934834655Z"
+host = "http://localhost:8081/"
+url = "http://localhost:8081/download/d0ef8edb0a/"
+secret = [7, 190, 112, 142, 31, 59, 95, 158, 167, 57, 12, 120, 224, 150, 88, 94]
+owner_token = "3e17d911164114ff3973"

+ 14 - 1
cli/src/action/upload.rs

@@ -1,5 +1,5 @@
 use std::fs::File;
 use std::fs::File;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::sync::{Arc, Mutex};
 use std::sync::{Arc, Mutex};
 
 
 use clap::ArgMatches;
 use clap::ArgMatches;
@@ -11,6 +11,7 @@ use ffsend_api::reqwest::Client;
 
 
 use cmd::matcher::{Matcher, MainMatcher, UploadMatcher};
 use cmd::matcher::{Matcher, MainMatcher, UploadMatcher};
 use error::ActionError;
 use error::ActionError;
+use history::History;
 use progress::ProgressBar;
 use progress::ProgressBar;
 use util::{
 use util::{
     ErrorHintsBuilder,
     ErrorHintsBuilder,
@@ -124,6 +125,18 @@ impl<'a> Upload<'a> {
         println!("Download URL: {}", url);
         println!("Download URL: {}", url);
         println!("Owner token: {}", file.owner_token().unwrap());
         println!("Owner token: {}", file.owner_token().unwrap());
 
 
+        // Update the history manager, load it first
+        // TODO: complete this implementation
+        let history_path = PathBuf::from("./history.toml");
+        match History::load_or_new(history_path) {
+            Ok(mut history) => {
+                // Add the file, and save
+                history.add(file.clone());
+                history.save();
+            },
+            Err(err) => println!("TODO: PRINT LOAD ERROR HERE"),
+        }
+
         // Open the URL in the browser
         // Open the URL in the browser
         if matcher_upload.open() {
         if matcher_upload.open() {
             if let Err(err) = open_url(url.clone()) {
             if let Err(err) = open_url(url.clone()) {

+ 102 - 0
cli/src/history.rs

@@ -0,0 +1,102 @@
+extern crate toml;
+
+use std::fs;
+use std::io::Read;
+use std::path::PathBuf;
+
+use ffsend_api::file::remote_file::RemoteFile;
+
+#[derive(Serialize, Deserialize)]
+pub struct History {
+    /// The file history.
+    files: Vec<RemoteFile>,
+
+    /// Whether the list of files has changed.
+    #[serde(skip)]
+    changed: bool,
+
+    /// An optional path to automatically save the history to.
+    #[serde(skip)]
+    autosave: Option<PathBuf>,
+}
+
+impl History {
+    /// Construct a new history.
+    /// A path may be given to automatically save the history to once changed.
+    pub fn new(autosave: Option<PathBuf>) -> Self {
+        let mut history = History::default();
+        history.autosave = autosave;
+        history
+    }
+
+    /// Load the history from the given file.
+    /// If the file doesn't exist, create a new empty history instance.
+    ///
+    /// Autosaving will be enabled, and will save to the given file path.
+    pub fn load_or_new(file: PathBuf) -> Result<Self, ()> {
+        if file.is_file() {
+            Self::load(file)
+        } else {
+            Ok(Self::new(Some(file)))
+        }
+    }
+
+    /// Load the history from the given file.
+    pub fn load(path: PathBuf) -> Result<Self, ()> {
+        // Read the file to a string
+        // TODO: handle error
+        let data = fs::read_to_string(path.clone()).unwrap();
+
+        // Parse the data, set the autosave path
+        let mut history: Self = toml::from_str(&data).unwrap();
+        history.autosave = Some(path);
+
+        Ok(history)
+    }
+
+    /// Save the history to the internal autosave file.
+    pub fn save(&mut self) -> Result<(), ()> {
+        // Build the data
+        // TODO: handle error
+        let data = toml::to_string(self).unwrap();
+
+        // Write to a file
+        // TODO: handle error
+        fs::write(self.autosave.as_ref().unwrap(), data).unwrap();
+
+        // There are no new changes, set the flag
+        self.changed = false;
+
+        Ok(())
+    }
+
+    /// Add the given remote file to the history.
+    pub fn add(&mut self, file: RemoteFile) {
+        self.files.push(file);
+        self.changed = true;
+    }
+
+    /// Get all files.
+    pub fn files(&self) -> &Vec<RemoteFile> {
+        &self.files
+    }
+}
+
+impl Drop for History {
+    fn drop(&mut self) {
+        // Automatically save if enabled and something was changed
+        if self.autosave.is_some() && self.changed {
+            self.save();
+        }
+    }
+}
+
+impl Default for History {
+    fn default() -> Self {
+        Self {
+            files: Vec::new(),
+            changed: false,
+            autosave: None,
+        }
+    }
+}

+ 4 - 0
cli/src/main.rs

@@ -7,10 +7,14 @@ extern crate failure;
 extern crate failure_derive;
 extern crate failure_derive;
 extern crate ffsend_api;
 extern crate ffsend_api;
 extern crate rpassword;
 extern crate rpassword;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
 
 
 mod action;
 mod action;
 mod cmd;
 mod cmd;
 mod error;
 mod error;
+mod history;
 mod host;
 mod host;
 mod progress;
 mod progress;
 mod util;
 mod util;