Browse Source

Implement history feature compiler USE flag

timvisee 7 years ago
parent
commit
29e44e9c9e

+ 0 - 2
ROADMAP.md

@@ -1,5 +1,4 @@
 # Release 0.1
 # Release 0.1
-- Switch to `directories` instead of `app_dirs2`?
 - Allow file/directory archiving on upload
 - Allow file/directory archiving on upload
 - Allow unarchiving on download 
 - Allow unarchiving on download 
 - Use clipboard through `xclip` on Linux if available for persistence
 - Use clipboard through `xclip` on Linux if available for persistence
@@ -23,7 +22,6 @@
 - Allow hiding the progress bar, and/or showing simple progress (with `-q`)
 - Allow hiding the progress bar, and/or showing simple progress (with `-q`)
 - Implement a quiet `-q` mode
 - Implement a quiet `-q` mode
 - Host configuration file for host tags, to easily upload to other hosts
 - Host configuration file for host tags, to easily upload to other hosts
-- History use flag
 
 
 # Other ideas
 # Other ideas
 - Rework encrypted reader/writer
 - Rework encrypted reader/writer

+ 4 - 1
cli/Cargo.toml

@@ -13,7 +13,10 @@ path = "src/main.rs"
 name = "ffsend"
 name = "ffsend"
 
 
 [features]
 [features]
-default = ["clipboard"]
+default = ["clipboard", "history"]
+
+# Compile with file history support
+history = []
 
 
 # Compile without colored output support
 # Compile without colored output support
 no-color = ["colored/no-color"]
 no-color = ["colored/no-color"]

+ 4 - 0
cli/src/action/delete.rs

@@ -15,6 +15,7 @@ use cmd::matcher::{
     main::MainMatcher,
     main::MainMatcher,
 };
 };
 use error::ActionError;
 use error::ActionError;
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use util::{ensure_owner_token, print_success};
 use util::{ensure_owner_token, print_success};
 
 
@@ -46,6 +47,7 @@ impl<'a> Delete<'a> {
 
 
         // Parse the remote file based on the share URL, derive the owner token from history
         // Parse the remote file based on the share URL, derive the owner token from history
         let mut file = RemoteFile::parse_url(url, matcher_delete.owner())?;
         let mut file = RemoteFile::parse_url(url, matcher_delete.owner())?;
+        #[cfg(feature = "history")]
         history_tool::derive_file_properties(&matcher_main, &mut file);
         history_tool::derive_file_properties(&matcher_main, &mut file);
 
 
         // Ensure the owner token is set
         // Ensure the owner token is set
@@ -55,11 +57,13 @@ impl<'a> Delete<'a> {
         let result = ApiDelete::new(&file, None).invoke(&client);
         let result = ApiDelete::new(&file, None).invoke(&client);
         if let Err(DeleteError::Expired) = result {
         if let Err(DeleteError::Expired) = result {
             // Remove the file from the history manager if it does not exist
             // Remove the file from the history manager if it does not exist
+            #[cfg(feature = "history")]
             history_tool::remove(&matcher_main, &file);
             history_tool::remove(&matcher_main, &file);
         }
         }
         result?;
         result?;
 
 
         // Remove the file from the history manager
         // Remove the file from the history manager
+        #[cfg(feature = "history")]
         history_tool::remove(&matcher_main, &file);
         history_tool::remove(&matcher_main, &file);
 
 
         // Print a success message
         // Print a success message

+ 3 - 0
cli/src/action/download.rs

@@ -25,6 +25,7 @@ use cmd::matcher::{
     download::DownloadMatcher,
     download::DownloadMatcher,
     main::MainMatcher,
     main::MainMatcher,
 };
 };
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use progress::ProgressBar;
 use progress::ProgressBar;
 use util::{
 use util::{
@@ -74,6 +75,7 @@ impl<'a> Download<'a> {
         let exists = ApiExists::new(&file).invoke(&client)?;
         let exists = ApiExists::new(&file).invoke(&client)?;
         if !exists.exists() {
         if !exists.exists() {
             // Remove the file from the history manager if it does not exist
             // Remove the file from the history manager if it does not exist
+            #[cfg(feature = "history")]
             history_tool::remove(&matcher_main, &file);
             history_tool::remove(&matcher_main, &file);
 
 
             return Err(Error::Expired);
             return Err(Error::Expired);
@@ -114,6 +116,7 @@ impl<'a> Download<'a> {
         ).invoke(&client, bar)?;
         ).invoke(&client, bar)?;
 
 
         // Add the file to the history
         // Add the file to the history
+        #[cfg(feature = "history")]
         history_tool::add(&matcher_main, file, true);
         history_tool::add(&matcher_main, file, true);
 
 
         // TODO: open the file, or it's location
         // TODO: open the file, or it's location

+ 13 - 13
cli/src/action/exists.rs

@@ -3,18 +3,14 @@ use ffsend_api::action::exists::{
     Error as ExistsError,
     Error as ExistsError,
     Exists as ApiExists,
     Exists as ApiExists,
 };
 };
-use ffsend_api::file::remote_file::{
-    FileParseError,
-    RemoteFile,
-};
+use ffsend_api::file::remote_file::{FileParseError, RemoteFile};
 use ffsend_api::reqwest::Client;
 use ffsend_api::reqwest::Client;
 
 
-use cmd::matcher::{
-    Matcher,
-    exists::ExistsMatcher,
-    main::MainMatcher,
-};
+use cmd::matcher::{Matcher, exists::ExistsMatcher};
+#[cfg(feature = "history")]
+use cmd::matcher::main::MainMatcher;
 use error::ActionError;
 use error::ActionError;
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 
 
 /// A file exists action.
 /// A file exists action.
@@ -35,6 +31,7 @@ impl<'a> Exists<'a> {
     pub fn invoke(&self) -> Result<(), ActionError> {
     pub fn invoke(&self) -> Result<(), ActionError> {
         // Create the command matchers
         // Create the command matchers
         let matcher_exists = ExistsMatcher::with(self.cmd_matches).unwrap();
         let matcher_exists = ExistsMatcher::with(self.cmd_matches).unwrap();
+        #[cfg(feature = "history")]
         let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
         let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
 
 
         // Get the share URL
         // Get the share URL
@@ -58,10 +55,13 @@ impl<'a> Exists<'a> {
         }
         }
 
 
         // Add or remove the file from the history
         // Add or remove the file from the history
-        if exists {
-            history_tool::add(&matcher_main, file, false);
-        } else {
-            history_tool::remove(&matcher_main, &file);
+        #[cfg(feature = "history")]
+        {
+            if exists {
+                history_tool::add(&matcher_main, file, false);
+            } else {
+                history_tool::remove(&matcher_main, &file);
+            }
         }
         }
 
 
         Ok(())
         Ok(())

+ 0 - 2
cli/src/action/history.rs

@@ -10,7 +10,6 @@ use self::prettytable::{
 
 
 use cmd::matcher::{
 use cmd::matcher::{
     Matcher,
     Matcher,
-    history::HistoryMatcher,
     main::MainMatcher,
     main::MainMatcher,
 };
 };
 use error::ActionError;
 use error::ActionError;
@@ -38,7 +37,6 @@ impl<'a> History<'a> {
     pub fn invoke(&self) -> Result<(), ActionError> {
     pub fn invoke(&self) -> Result<(), ActionError> {
         // Create the command matchers
         // Create the command matchers
         let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
         let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
-        let _matcher_history = HistoryMatcher::with(self.cmd_matches).unwrap();
 
 
         // Get the history path, make sure it exists
         // Get the history path, make sure it exists
         let history_path = matcher_main.history();
         let history_path = matcher_main.history();

+ 4 - 0
cli/src/action/info.rs

@@ -21,6 +21,7 @@ use cmd::matcher::{
     info::InfoMatcher,
     info::InfoMatcher,
     main::MainMatcher,
     main::MainMatcher,
 };
 };
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use util::{
 use util::{
     ensure_owner_token,
     ensure_owner_token,
@@ -58,6 +59,7 @@ impl<'a> Info<'a> {
 
 
         // Parse the remote file based on the share URL, derive the owner token from history
         // Parse the remote file based on the share URL, derive the owner token from history
         let mut file = RemoteFile::parse_url(url, matcher_info.owner())?;
         let mut file = RemoteFile::parse_url(url, matcher_info.owner())?;
+        #[cfg(feature = "history")]
         history_tool::derive_file_properties(&matcher_main, &mut file);
         history_tool::derive_file_properties(&matcher_main, &mut file);
 
 
         // Ensure the owner token is set
         // Ensure the owner token is set
@@ -67,6 +69,7 @@ impl<'a> Info<'a> {
         let exists = ApiExists::new(&file).invoke(&client)?;
         let exists = ApiExists::new(&file).invoke(&client)?;
         if !exists.exists() {
         if !exists.exists() {
             // Remove the file from the history manager if it doesn't exist
             // Remove the file from the history manager if it doesn't exist
+            #[cfg(feature = "history")]
             history_tool::remove(&matcher_main, &file);
             history_tool::remove(&matcher_main, &file);
 
 
             return Err(Error::Expired);
             return Err(Error::Expired);
@@ -95,6 +98,7 @@ impl<'a> Info<'a> {
         file.set_expire_duration(ttl);
         file.set_expire_duration(ttl);
 
 
         // Add the file to the history
         // Add the file to the history
+        #[cfg(feature = "history")]
         history_tool::add(&matcher_main, file.clone(), true);
         history_tool::add(&matcher_main, file.clone(), true);
 
 
         // Print all file details
         // Print all file details

+ 1 - 0
cli/src/action/mod.rs

@@ -1,6 +1,7 @@
 pub mod delete;
 pub mod delete;
 pub mod download;
 pub mod download;
 pub mod exists;
 pub mod exists;
+#[cfg(feature = "history")]
 pub mod history;
 pub mod history;
 pub mod info;
 pub mod info;
 pub mod params;
 pub mod params;

+ 4 - 0
cli/src/action/params.rs

@@ -13,6 +13,7 @@ use cmd::matcher::{
     params::ParamsMatcher,
     params::ParamsMatcher,
 };
 };
 use error::ActionError;
 use error::ActionError;
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use util::{ensure_owner_token, print_success};
 use util::{ensure_owner_token, print_success};
 
 
@@ -44,6 +45,7 @@ impl<'a> Params<'a> {
 
 
         // Parse the remote file based on the share URL, derive the owner token from history
         // Parse the remote file based on the share URL, derive the owner token from history
         let mut file = RemoteFile::parse_url(url, matcher_params.owner())?;
         let mut file = RemoteFile::parse_url(url, matcher_params.owner())?;
+        #[cfg(feature = "history")]
         history_tool::derive_file_properties(&matcher_main, &mut file);
         history_tool::derive_file_properties(&matcher_main, &mut file);
 
 
         // Ensure the owner token is set
         // Ensure the owner token is set
@@ -61,11 +63,13 @@ impl<'a> Params<'a> {
         let result = ApiParams::new(&file, data, None).invoke(&client);
         let result = ApiParams::new(&file, data, None).invoke(&client);
         if let Err(ParamsError::Expired) = result {
         if let Err(ParamsError::Expired) = result {
             // Remove the file from the history if expired
             // Remove the file from the history if expired
+            #[cfg(feature = "history")]
             history_tool::remove(&matcher_main, &file);
             history_tool::remove(&matcher_main, &file);
         }
         }
         result?;
         result?;
 
 
         // Update the history
         // Update the history
+        #[cfg(feature = "history")]
         history_tool::add(&matcher_main, file, true);
         history_tool::add(&matcher_main, file, true);
 
 
         // Print a success message
         // Print a success message

+ 4 - 0
cli/src/action/password.rs

@@ -12,6 +12,7 @@ use cmd::matcher::{
     password::PasswordMatcher,
     password::PasswordMatcher,
 };
 };
 use error::ActionError;
 use error::ActionError;
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use util::{ensure_owner_token, print_success};
 use util::{ensure_owner_token, print_success};
 
 
@@ -43,6 +44,7 @@ impl<'a> Password<'a> {
 
 
         // Parse the remote file based on the share URL, derive the owner token from history
         // Parse the remote file based on the share URL, derive the owner token from history
         let mut file = RemoteFile::parse_url(url, matcher_password.owner())?;
         let mut file = RemoteFile::parse_url(url, matcher_password.owner())?;
+        #[cfg(feature = "history")]
         history_tool::derive_file_properties(&matcher_main, &mut file);
         history_tool::derive_file_properties(&matcher_main, &mut file);
 
 
         // Ensure the owner token is set
         // Ensure the owner token is set
@@ -56,11 +58,13 @@ impl<'a> Password<'a> {
         ).invoke(&client);
         ).invoke(&client);
         if let Err(PasswordError::Expired) = result {
         if let Err(PasswordError::Expired) = result {
             // Remove the file from the history if expired
             // Remove the file from the history if expired
+            #[cfg(feature = "history")]
             history_tool::remove(&matcher_main, &file);
             history_tool::remove(&matcher_main, &file);
         }
         }
         result?;
         result?;
 
 
         // Add the file to the history
         // Add the file to the history
+        #[cfg(feature = "history")]
         history_tool::add(&matcher_main, file, true);
         history_tool::add(&matcher_main, file, true);
 
 
         // Print a success message
         // Print a success message

+ 4 - 5
cli/src/action/upload.rs

@@ -3,7 +3,7 @@ use std::path::Path;
 use std::sync::{Arc, Mutex};
 use std::sync::{Arc, Mutex};
 
 
 use clap::ArgMatches;
 use clap::ArgMatches;
-use failure::{err_msg, Fail};
+use failure::Fail;
 use ffsend_api::action::params::ParamsDataBuilder;
 use ffsend_api::action::params::ParamsDataBuilder;
 use ffsend_api::action::upload::Upload as ApiUpload;
 use ffsend_api::action::upload::Upload as ApiUpload;
 use ffsend_api::config::{UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_RECOMMENDED};
 use ffsend_api::config::{UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_RECOMMENDED};
@@ -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;
+#[cfg(feature = "history")]
 use history_tool;
 use history_tool;
 use progress::ProgressBar;
 use progress::ProgressBar;
 use util::{
 use util::{
@@ -126,6 +127,7 @@ impl<'a> Upload<'a> {
         println!("Owner token: {}", file.owner_token().unwrap());
         println!("Owner token: {}", file.owner_token().unwrap());
 
 
         // Add the file to the history manager
         // Add the file to the history manager
+        #[cfg(feature = "history")]
         history_tool::add(&matcher_main, file.clone(), false);
         history_tool::add(&matcher_main, file.clone(), false);
 
 
         // Open the URL in the browser
         // Open the URL in the browser
@@ -142,10 +144,7 @@ impl<'a> Upload<'a> {
         {
         {
             if matcher_upload.copy() {
             if matcher_upload.copy() {
                 if set_clipboard(url.as_str().to_owned()).is_err() {
                 if set_clipboard(url.as_str().to_owned()).is_err() {
-                    print_error(
-                        err_msg("failed to copy the URL to the clipboard")
-                            .compat()
-                    );
+                    print_error_msg("failed to copy the URL to the clipboard");
                 }
                 }
             }
             }
         }
         }

+ 2 - 0
cli/src/cmd/cmd/mod.rs

@@ -1,6 +1,7 @@
 pub mod delete;
 pub mod delete;
 pub mod download;
 pub mod download;
 pub mod exists;
 pub mod exists;
+#[cfg(feature = "history")]
 pub mod history;
 pub mod history;
 pub mod info;
 pub mod info;
 pub mod params;
 pub mod params;
@@ -11,6 +12,7 @@ pub mod upload;
 pub use self::delete::CmdDelete;
 pub use self::delete::CmdDelete;
 pub use self::download::CmdDownload;
 pub use self::download::CmdDownload;
 pub use self::exists::CmdExists;
 pub use self::exists::CmdExists;
+#[cfg(feature = "history")]
 pub use self::history::CmdHistory;
 pub use self::history::CmdHistory;
 pub use self::info::CmdInfo;
 pub use self::info::CmdInfo;
 pub use self::params::CmdParams;
 pub use self::params::CmdParams;

+ 19 - 11
cli/src/cmd/handler.rs

@@ -6,25 +6,29 @@ use super::matcher::{
     DeleteMatcher,
     DeleteMatcher,
     DownloadMatcher,
     DownloadMatcher,
     ExistsMatcher,
     ExistsMatcher,
-    HistoryMatcher,
     InfoMatcher,
     InfoMatcher,
     Matcher,
     Matcher,
     ParamsMatcher,
     ParamsMatcher,
     PasswordMatcher,
     PasswordMatcher,
     UploadMatcher,
     UploadMatcher,
 };
 };
+#[cfg(feature = "history")]
+use super::matcher::HistoryMatcher;
 use super::cmd::{
 use super::cmd::{
     CmdDelete,
     CmdDelete,
     CmdDownload,
     CmdDownload,
     CmdExists,
     CmdExists,
-    CmdHistory,
     CmdInfo,
     CmdInfo,
     CmdParams,
     CmdParams,
     CmdPassword,
     CmdPassword,
     CmdUpload,
     CmdUpload,
 };
 };
+#[cfg(feature = "history")]
+use super::cmd::CmdHistory;
+#[cfg(feature = "history")]
 use util::app_history_file_path_string;
 use util::app_history_file_path_string;
 
 
+#[cfg(feature = "history")]
 lazy_static! {
 lazy_static! {
     /// The default history file
     /// The default history file
     static ref DEFAULT_HISTORY_FILE: String = app_history_file_path_string();
     static ref DEFAULT_HISTORY_FILE: String = app_history_file_path_string();
@@ -64,7 +68,17 @@ impl<'a: 'b, 'b> Handler<'a> {
                 .alias("assume-yes")
                 .alias("assume-yes")
                 .global(true)
                 .global(true)
                 .help("Assume yes for prompts"))
                 .help("Assume yes for prompts"))
-            .arg(Arg::with_name("history")
+            .subcommand(CmdDelete::build())
+            .subcommand(CmdDownload::build().display_order(2))
+            .subcommand(CmdExists::build())
+            .subcommand(CmdInfo::build())
+            .subcommand(CmdParams::build())
+            .subcommand(CmdPassword::build())
+            .subcommand(CmdUpload::build().display_order(1));
+
+        // With history support, a flag for the history file and incognito mode
+        #[cfg(feature = "history")]
+        let app = app.arg(Arg::with_name("history")
                 .long("history")
                 .long("history")
                 .short("H")
                 .short("H")
                 .value_name("FILE")
                 .value_name("FILE")
@@ -79,14 +93,7 @@ impl<'a: 'b, 'b> Handler<'a> {
                 .alias("priv")
                 .alias("priv")
                 .global(true)
                 .global(true)
                 .help("Don't update local history for actions"))
                 .help("Don't update local history for actions"))
-            .subcommand(CmdDelete::build())
-            .subcommand(CmdDownload::build().display_order(2))
-            .subcommand(CmdExists::build())
-            .subcommand(CmdHistory::build())
-            .subcommand(CmdInfo::build())
-            .subcommand(CmdParams::build())
-            .subcommand(CmdPassword::build())
-            .subcommand(CmdUpload::build().display_order(1));
+            .subcommand(CmdHistory::build());
 
 
         // Disable color usage if compiled without color support
         // Disable color usage if compiled without color support
         #[cfg(feature = "no-color")]
         #[cfg(feature = "no-color")]
@@ -124,6 +131,7 @@ impl<'a: 'b, 'b> Handler<'a> {
     }
     }
 
 
     /// Get the history sub command, if matched.
     /// Get the history sub command, if matched.
+    #[cfg(feature = "history")]
     pub fn history(&'a self) -> Option<HistoryMatcher> {
     pub fn history(&'a self) -> Option<HistoryMatcher> {
         HistoryMatcher::with(&self.matches)
         HistoryMatcher::with(&self.matches)
     }
     }

+ 4 - 0
cli/src/cmd/matcher/main.rs

@@ -1,8 +1,10 @@
+#[cfg(feature = "history")]
 use std::path::PathBuf;
 use std::path::PathBuf;
 
 
 use clap::ArgMatches;
 use clap::ArgMatches;
 
 
 use super::Matcher;
 use super::Matcher;
+#[cfg(feature = "history")]
 use util::{ErrorHintsBuilder, quit_error_msg};
 use util::{ErrorHintsBuilder, quit_error_msg};
 
 
 /// The main command matcher.
 /// The main command matcher.
@@ -27,6 +29,7 @@ impl<'a: 'b, 'b> MainMatcher<'a> {
     }
     }
 
 
     /// Get the history file to use.
     /// Get the history file to use.
+    #[cfg(feature = "history")]
     pub fn history(&self) -> PathBuf {
     pub fn history(&self) -> PathBuf {
         // Get the path
         // Get the path
         let path = self.matches.value_of("history")
         let path = self.matches.value_of("history")
@@ -47,6 +50,7 @@ impl<'a: 'b, 'b> MainMatcher<'a> {
     }
     }
 
 
     /// Check whether we are incognito from the file history.
     /// Check whether we are incognito from the file history.
+    #[cfg(feature = "history")]
     pub fn incognito(&self) -> bool {
     pub fn incognito(&self) -> bool {
         self.matches.is_present("incognito")
         self.matches.is_present("incognito")
     }
     }

+ 2 - 0
cli/src/cmd/matcher/mod.rs

@@ -1,6 +1,7 @@
 pub mod delete;
 pub mod delete;
 pub mod download;
 pub mod download;
 pub mod exists;
 pub mod exists;
+#[cfg(feature = "history")]
 pub mod history;
 pub mod history;
 pub mod info;
 pub mod info;
 pub mod main;
 pub mod main;
@@ -12,6 +13,7 @@ pub mod upload;
 pub use self::delete::DeleteMatcher;
 pub use self::delete::DeleteMatcher;
 pub use self::download::DownloadMatcher;
 pub use self::download::DownloadMatcher;
 pub use self::exists::ExistsMatcher;
 pub use self::exists::ExistsMatcher;
+#[cfg(feature = "history")]
 pub use self::history::HistoryMatcher;
 pub use self::history::HistoryMatcher;
 pub use self::info::InfoMatcher;
 pub use self::info::InfoMatcher;
 pub use self::main::MainMatcher;
 pub use self::main::MainMatcher;

+ 3 - 0
cli/src/error.rs

@@ -6,6 +6,7 @@ use ffsend_api::action::upload::Error as UploadError;
 use ffsend_api::file::remote_file::FileParseError;
 use ffsend_api::file::remote_file::FileParseError;
 
 
 use action::download::Error as CliDownloadError;
 use action::download::Error as CliDownloadError;
+#[cfg(feature = "history")]
 use action::history::Error as CliHistoryError;
 use action::history::Error as CliHistoryError;
 use action::info::Error as CliInfoError;
 use action::info::Error as CliInfoError;
 
 
@@ -49,6 +50,7 @@ pub enum ActionError {
     Exists(#[cause] ExistsError),
     Exists(#[cause] ExistsError),
 
 
     /// An error occurred while processing the file history.
     /// An error occurred while processing the file history.
+    #[cfg(feature = "history")]
     #[fail(display = "failed to process the history")]
     #[fail(display = "failed to process the history")]
     History(#[cause] CliHistoryError),
     History(#[cause] CliHistoryError),
 
 
@@ -87,6 +89,7 @@ impl From<ExistsError> for ActionError {
     }
     }
 }
 }
 
 
+#[cfg(feature = "history")]
 impl From<CliHistoryError> for ActionError {
 impl From<CliHistoryError> for ActionError {
     fn from(err: CliHistoryError) -> ActionError {
     fn from(err: CliHistoryError) -> ActionError {
         ActionError::History(err)
         ActionError::History(err)

+ 11 - 3
cli/src/main.rs

@@ -7,17 +7,21 @@ extern crate failure;
 #[macro_use]
 #[macro_use]
 extern crate failure_derive;
 extern crate failure_derive;
 extern crate ffsend_api;
 extern crate ffsend_api;
+#[cfg(feature = "history")]
 #[macro_use]
 #[macro_use]
 extern crate lazy_static;
 extern crate lazy_static;
 extern crate rpassword;
 extern crate rpassword;
 extern crate serde;
 extern crate serde;
+#[cfg(feature = "history")]
 #[macro_use]
 #[macro_use]
 extern crate serde_derive;
 extern crate serde_derive;
 
 
 mod action;
 mod action;
 mod cmd;
 mod cmd;
 mod error;
 mod error;
+#[cfg(feature = "history")]
 mod history;
 mod history;
+#[cfg(feature = "history")]
 mod history_tool;
 mod history_tool;
 mod host;
 mod host;
 mod progress;
 mod progress;
@@ -26,6 +30,7 @@ mod util;
 use action::delete::Delete;
 use action::delete::Delete;
 use action::download::Download;
 use action::download::Download;
 use action::exists::Exists;
 use action::exists::Exists;
+#[cfg(feature = "history")]
 use action::history::History;
 use action::history::History;
 use action::info::Info;
 use action::info::Info;
 use action::params::Params;
 use action::params::Params;
@@ -70,9 +75,12 @@ fn invoke_action(handler: &Handler) -> Result<(), Error> {
     }
     }
 
 
     // Match the history command
     // Match the history command
-    if handler.history().is_some() {
-        return History::new(handler.matches()).invoke()
-            .map_err(|err| err.into());
+    #[cfg(feature = "history")]
+    {
+        if handler.history().is_some() {
+            return History::new(handler.matches()).invoke()
+                .map_err(|err| err.into());
+        }
     }
     }
 
 
     // Match the info command
     // Match the info command

+ 29 - 7
cli/src/util.rs

@@ -15,16 +15,19 @@ use std::io::{
     stderr,
     stderr,
     Write,
     Write,
 };
 };
-use std::path::{Path, PathBuf};
+use std::path::Path;
+#[cfg(feature = "history")]
+use std::path::PathBuf;
 use std::process::{exit, ExitStatus};
 use std::process::{exit, ExitStatus};
 
 
 use chrono::Duration;
 use chrono::Duration;
-#[cfg(feature = "clipboard")]
 use failure::{err_msg, Fail};
 use failure::{err_msg, Fail};
 use ffsend_api::url::Url;
 use ffsend_api::url::Url;
 use rpassword::prompt_password_stderr;
 use rpassword::prompt_password_stderr;
+#[cfg(feature = "clipboard")]
 use self::clipboard::{ClipboardContext, ClipboardProvider};
 use self::clipboard::{ClipboardContext, ClipboardProvider};
 use self::colored::*;
 use self::colored::*;
+#[cfg(feature = "history")]
 use self::directories::ProjectDirs;
 use self::directories::ProjectDirs;
 use self::fs2::available_space;
 use self::fs2::available_space;
 
 
@@ -65,6 +68,7 @@ pub fn print_error_msg<S>(err: S)
 }
 }
 
 
 /// Print a warning.
 /// Print a warning.
+#[cfg(feature = "history")]
 pub fn print_warning<S>(err: S)
 pub fn print_warning<S>(err: S)
     where
     where
         S: AsRef<str> + Display + Debug + Sync + Send + 'static
         S: AsRef<str> + Display + Debug + Sync + Send + 'static
@@ -113,6 +117,7 @@ pub struct ErrorHints {
     owner: bool,
     owner: bool,
 
 
     /// Show about the history flag.
     /// Show about the history flag.
+    #[cfg(feature = "history")]
     history: bool,
     history: bool,
 
 
     /// Show about the force flag.
     /// Show about the force flag.
@@ -128,12 +133,21 @@ pub struct ErrorHints {
 impl ErrorHints {
 impl ErrorHints {
     /// Check whether any hint should be printed.
     /// Check whether any hint should be printed.
     pub fn any(&self) -> bool {
     pub fn any(&self) -> bool {
-        self.password
+        // Determine the result
+        #[allow(unused_mut)]
+        let mut result = self.password
             || self.owner
             || self.owner
-            || self.history
             || self.force
             || self.force
             || self.verbose
             || self.verbose
-            || self.help
+            || self.help;
+
+        // Factor in the history hint when enabled
+        #[cfg(feature = "history")]
+        {
+            result = result || self.history;
+        }
+
+        result
     }
     }
 
 
     /// Print the error hints.
     /// Print the error hints.
@@ -157,8 +171,11 @@ impl ErrorHints {
         if self.owner {
         if self.owner {
             eprintln!("Use '{}' to specify an owner token", highlight("--owner <TOKEN>"));
             eprintln!("Use '{}' to specify an owner token", highlight("--owner <TOKEN>"));
         }
         }
-        if self.history {
-            eprintln!("Use '{}' to specify a history file", highlight("--history <FILE>"));
+        #[cfg(feature = "history")]
+        {
+            if self.history {
+                eprintln!("Use '{}' to specify a history file", highlight("--history <FILE>"));
+            }
         }
         }
         if self.force {
         if self.force {
             eprintln!("Use '{}' to force", highlight("--force"));
             eprintln!("Use '{}' to force", highlight("--force"));
@@ -181,6 +198,7 @@ impl Default for ErrorHints {
             info: Vec::new(),
             info: Vec::new(),
             password: false,
             password: false,
             owner: false,
             owner: false,
+            #[cfg(feature = "history")]
             history: false,
             history: false,
             force: false,
             force: false,
             verbose: true,
             verbose: true,
@@ -217,6 +235,7 @@ pub fn highlight_error(msg: &str) -> ColoredString {
 }
 }
 
 
 /// Highlight the given text with an warning color.
 /// Highlight the given text with an warning color.
+#[cfg(feature = "history")]
 pub fn highlight_warning(msg: &str) -> ColoredString {
 pub fn highlight_warning(msg: &str) -> ColoredString {
     highlight(msg).bold()
     highlight(msg).bold()
 }
 }
@@ -594,16 +613,19 @@ pub fn ensure_enough_space<P: AsRef<Path>>(path: P, size: u64) {
 /// Get the project directories instance for this application.
 /// Get the project directories instance for this application.
 /// This may be used to determine the project, cache, configuration, data and
 /// This may be used to determine the project, cache, configuration, data and
 /// some other directory paths.
 /// some other directory paths.
+#[cfg(feature = "history")]
 pub fn app_project_dirs() -> ProjectDirs {
 pub fn app_project_dirs() -> ProjectDirs {
     ProjectDirs::from("", "", crate_name!())
     ProjectDirs::from("", "", crate_name!())
 }
 }
 
 
 /// Get the default path to use for the history file.
 /// Get the default path to use for the history file.
+#[cfg(feature = "history")]
 pub fn app_history_file_path<'a>() -> PathBuf {
 pub fn app_history_file_path<'a>() -> PathBuf {
     app_project_dirs().cache_dir().join("history.toml")
     app_project_dirs().cache_dir().join("history.toml")
 }
 }
 
 
 /// Get the default path to use for the history file, as a string.
 /// Get the default path to use for the history file, as a string.
+#[cfg(feature = "history")]
 pub fn app_history_file_path_string() -> String {
 pub fn app_history_file_path_string() -> String {
     app_history_file_path().to_str()
     app_history_file_path().to_str()
         .unwrap()
         .unwrap()