mirror of
https://github.com/tealdeer-rs/tealdeer.git
synced 2026-08-24 00:54:17 +02:00
Merge pull request #115 from ilai-deutel/automatic-updates
Implement automatic cache updates
This commit is contained in:
commit
d446e50813
7 changed files with 209 additions and 99 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -194,7 +194,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.8"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -996,7 +996,7 @@ name = "tar"
|
|||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -1012,6 +1012,7 @@ dependencies = [
|
|||
"docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"escargot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pager 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -1022,7 +1023,6 @@ dependencies = [
|
|||
"tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
@ -1180,16 +1180,6 @@ dependencies = [
|
|||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utime"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
|
|
@ -1420,7 +1410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
|
||||
"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
|
||||
"checksum escargot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19db1f7e74438642a5018cdf263bb1325b2e792f02dd0a3ca6d6c0f0d7b1d5a5"
|
||||
"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d"
|
||||
"checksum filetime 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695"
|
||||
"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f"
|
||||
"checksum float-cmp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da62c4f1b81918835a8c6a484a397775fff5953fe83529afd51b05f5c6a6617d"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
|
|
@ -1533,7 +1523,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
||||
"checksum utime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "055058552ca15c566082fc61da433ae678f78986a6f16957e33162d1b218792a"
|
||||
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ assert_cmd = "0.10"
|
|||
escargot = "0.3"
|
||||
predicates = "1.0"
|
||||
tempdir = "^0.3"
|
||||
utime = "0.2.0"
|
||||
filetime = "0.2.10"
|
||||
|
||||
[features]
|
||||
logging = ["env_logger"]
|
||||
|
|
|
|||
25
README.md
25
README.md
|
|
@ -208,6 +208,31 @@ Set this to enforce more compact output, where empty lines are stripped out
|
|||
compact = true
|
||||
|
||||
|
||||
### Automatic updates
|
||||
|
||||
tealdeer can refresh the cache automatically when it is outdated. This
|
||||
behavior can be configured in the `updates` section and is disabled by
|
||||
default.
|
||||
|
||||
#### `auto_update`
|
||||
|
||||
Specifies whether the auto-update feature should be enabled (defaults to
|
||||
`false`).
|
||||
|
||||
[updates]
|
||||
auto_update = true
|
||||
|
||||
#### `auto_update_interval_hours`
|
||||
|
||||
Duration, since the last cache update, after which the cache will be
|
||||
refreshed (defaults to 720 hours). This parameter is ignored if `auto_update`
|
||||
is set to `false`.
|
||||
|
||||
[updates]
|
||||
auto_update = true
|
||||
auto_update_interval_hours = 24
|
||||
|
||||
|
||||
## Autocompletion
|
||||
|
||||
- *Bash*: copy `bash_tealdeer` to `/usr/share/bash-completion/completions/tldr`
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::env;
|
|||
use std::fs;
|
||||
use std::io::{Error as IoError, Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use ansi_term::{Color, Style};
|
||||
use app_dirs::{get_app_root, AppDataType};
|
||||
|
|
@ -12,6 +13,8 @@ use toml;
|
|||
use crate::error::TealdeerError::{self, ConfigError};
|
||||
|
||||
pub const CONFIG_FILE_NAME: &str = "config.toml";
|
||||
pub const MAX_CACHE_AGE: Duration = Duration::from_secs(2_592_000); // 30 days
|
||||
const DEFAULT_UPDATE_INTERVAL_HOURS: u64 = MAX_CACHE_AGE.as_secs() / 3600; // 30 days
|
||||
|
||||
fn default_underline() -> bool {
|
||||
false
|
||||
|
|
@ -116,12 +119,38 @@ struct RawDisplayConfig {
|
|||
pub use_pager: bool,
|
||||
}
|
||||
|
||||
/// Serde doesn't support default values yet (tracking issue:
|
||||
/// https://github.com/serde-rs/serde/issues/368), so we need to wrap DEFAULT_UPDATE_INTERVAL_HOURS
|
||||
/// in a function to be able to use #[serde(default = ...)]
|
||||
const fn default_auto_update_interval_hours() -> u64 {
|
||||
DEFAULT_UPDATE_INTERVAL_HOURS
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
struct RawUpdatesConfig {
|
||||
#[serde(default)]
|
||||
pub auto_update: bool,
|
||||
#[serde(default = "default_auto_update_interval_hours")]
|
||||
pub auto_update_interval_hours: u64,
|
||||
}
|
||||
|
||||
impl Default for RawUpdatesConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
auto_update: false,
|
||||
auto_update_interval_hours: DEFAULT_UPDATE_INTERVAL_HOURS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
struct RawConfig {
|
||||
#[serde(default)]
|
||||
style: RawStyleConfig,
|
||||
#[serde(default)]
|
||||
display: RawDisplayConfig,
|
||||
#[serde(default)]
|
||||
updates: RawUpdatesConfig,
|
||||
}
|
||||
|
||||
impl RawConfig {
|
||||
|
|
@ -134,7 +163,6 @@ impl RawConfig {
|
|||
raw_config.style.example_code.foreground = Some(RawColor::Cyan);
|
||||
raw_config.style.example_variable.foreground = Some(RawColor::Cyan);
|
||||
raw_config.style.example_variable.underline = true;
|
||||
raw_config.display.use_pager = false;
|
||||
|
||||
raw_config
|
||||
}
|
||||
|
|
@ -155,10 +183,17 @@ pub struct DisplayConfig {
|
|||
pub use_pager: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct UpdatesConfig {
|
||||
pub auto_update: bool,
|
||||
pub auto_update_interval: Duration,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Config {
|
||||
pub style: StyleConfig,
|
||||
pub display: DisplayConfig,
|
||||
pub updates: UpdatesConfig,
|
||||
}
|
||||
|
||||
impl From<RawConfig> for Config {
|
||||
|
|
@ -175,6 +210,12 @@ impl From<RawConfig> for Config {
|
|||
compact: raw_config.display.compact,
|
||||
use_pager: raw_config.display.use_pager,
|
||||
},
|
||||
updates: UpdatesConfig {
|
||||
auto_update: raw_config.updates.auto_update,
|
||||
auto_update_interval: Duration::from_secs(
|
||||
raw_config.updates.auto_update_interval_hours * 3600,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
150
src/main.rs
150
src/main.rs
|
|
@ -21,7 +21,6 @@ use std::io::BufReader;
|
|||
use std::io::BufRead;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::time::Duration;
|
||||
|
||||
use ansi_term::Color;
|
||||
use app_dirs::AppInfo;
|
||||
|
|
@ -38,7 +37,7 @@ mod tokenizer;
|
|||
mod types;
|
||||
|
||||
use crate::cache::Cache;
|
||||
use crate::config::{get_config_path, make_default_config, Config};
|
||||
use crate::config::{get_config_path, make_default_config, Config, MAX_CACHE_AGE};
|
||||
use crate::error::TealdeerError::{CacheError, ConfigError, UpdateError};
|
||||
use crate::formatter::print_lines;
|
||||
use crate::tokenizer::Tokenizer;
|
||||
|
|
@ -86,7 +85,6 @@ To render a local file (for testing):
|
|||
$ tldr --render /path/to/file.md
|
||||
";
|
||||
const ARCHIVE_URL: &str = "https://github.com/tldr-pages/tldr/archive/master.tar.gz";
|
||||
const MAX_CACHE_AGE: Duration = Duration::from_secs(2_592_000); // 30 days
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const PAGER_COMMAND: &str = "less -R";
|
||||
|
||||
|
|
@ -108,24 +106,11 @@ struct Args {
|
|||
}
|
||||
|
||||
/// Print page by path
|
||||
fn print_page(path: &Path, enable_markdown: bool, enable_styles: bool) -> Result<(), String> {
|
||||
fn print_page(path: &Path, enable_markdown: bool, config: &Config) -> Result<(), String> {
|
||||
// Open file
|
||||
let file = File::open(path).map_err(|msg| format!("Could not open file: {}", msg))?;
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
// Look up config file, if none is found fall back to default config.
|
||||
let config = match Config::load(enable_styles) {
|
||||
Ok(config) => config,
|
||||
Err(ConfigError(msg)) => {
|
||||
eprintln!("Could not load config: {}", msg);
|
||||
process::exit(1);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Could not load config: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if enable_markdown {
|
||||
// Print the raw markdown of the file.
|
||||
for line in reader.lines() {
|
||||
|
|
@ -142,59 +127,42 @@ fn print_page(path: &Path, enable_markdown: bool, enable_styles: bool) -> Result
|
|||
|
||||
/// Set up display pager
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn configure_pager(args: &Args, enable_styles: bool) {
|
||||
// Flags have precedence
|
||||
if args.flag_pager {
|
||||
Pager::with_default_pager(PAGER_COMMAND).setup();
|
||||
return;
|
||||
}
|
||||
|
||||
// Then check config
|
||||
let config = match Config::load(enable_styles) {
|
||||
Ok(config) => config,
|
||||
Err(ConfigError(msg)) => {
|
||||
eprintln!("Could not load config: {}", msg);
|
||||
process::exit(1);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Could not load config: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if config.display.use_pager {
|
||||
Pager::with_default_pager(PAGER_COMMAND).setup();
|
||||
}
|
||||
fn configure_pager() {
|
||||
Pager::with_default_pager(PAGER_COMMAND).setup();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn configure_pager(_args: &Args, _enable_styles: bool) {
|
||||
fn configure_pager() {
|
||||
eprintln!("Warning: -p / --pager flag not available on Windows!");
|
||||
}
|
||||
|
||||
fn should_update_cache(args: &Args, config: &Config) -> bool {
|
||||
args.flag_update
|
||||
|| (config.updates.auto_update
|
||||
&& Cache::last_update().map_or(true, |ago| ago >= config.updates.auto_update_interval))
|
||||
}
|
||||
|
||||
/// Check the cache for freshness
|
||||
fn check_cache(args: &Args) {
|
||||
if !args.flag_update {
|
||||
match Cache::last_update() {
|
||||
Some(ago) if ago > MAX_CACHE_AGE => {
|
||||
if args.flag_quiet {
|
||||
return;
|
||||
}
|
||||
eprintln!(
|
||||
"{}",
|
||||
Color::Yellow.paint(format!(
|
||||
"The cache hasn't been updated for more than {} days.\n\
|
||||
match Cache::last_update() {
|
||||
Some(ago) if ago > MAX_CACHE_AGE => {
|
||||
if args.flag_quiet {
|
||||
return;
|
||||
}
|
||||
eprintln!(
|
||||
"{}",
|
||||
Color::Yellow.paint(format!(
|
||||
"The cache hasn't been updated for more than {} days.\n\
|
||||
You should probably run `tldr --update` soon.",
|
||||
MAX_CACHE_AGE.as_secs() / 24 / 3600
|
||||
))
|
||||
);
|
||||
}
|
||||
None => {
|
||||
eprintln!("Cache not found. Please run `tldr --update`.");
|
||||
process::exit(1);
|
||||
}
|
||||
_ => {}
|
||||
MAX_CACHE_AGE.as_secs() / 24 / 3600
|
||||
))
|
||||
);
|
||||
}
|
||||
None => {
|
||||
eprintln!("Cache not found. Please run `tldr --update`.");
|
||||
process::exit(1);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -320,14 +288,38 @@ fn main() {
|
|||
process::exit(0);
|
||||
}
|
||||
|
||||
// Show config file and path, pass through
|
||||
if args.flag_config_path {
|
||||
show_config_path();
|
||||
}
|
||||
|
||||
// Create a basic config and exit
|
||||
if args.flag_seed_config {
|
||||
create_config_and_exit();
|
||||
}
|
||||
|
||||
// Determine the usage of styles
|
||||
#[cfg(target_os = "windows")]
|
||||
let enable_styles = ansi_term::enable_ansi_support().is_ok();
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let enable_styles = true;
|
||||
|
||||
// Configure pager
|
||||
configure_pager(&args, enable_styles);
|
||||
// Look up config file, if none is found fall back to default config.
|
||||
let config = match Config::load(enable_styles) {
|
||||
Ok(config) => config,
|
||||
Err(ConfigError(msg)) => {
|
||||
eprintln!("Could not load config: {}", msg);
|
||||
process::exit(1);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Could not load config: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if args.flag_pager || config.display.use_pager {
|
||||
configure_pager();
|
||||
}
|
||||
|
||||
// Specify target OS
|
||||
let os: OsType = match args.flag_os {
|
||||
|
|
@ -344,24 +336,17 @@ fn main() {
|
|||
}
|
||||
|
||||
// Update cache, pass through
|
||||
if args.flag_update {
|
||||
let cache_updated = if should_update_cache(&args, &config) {
|
||||
update_cache(&cache, args.flag_quiet);
|
||||
}
|
||||
|
||||
// Show config file and path, pass through
|
||||
if args.flag_config_path {
|
||||
show_config_path();
|
||||
}
|
||||
|
||||
// Create a basic config and exit
|
||||
if args.flag_seed_config {
|
||||
create_config_and_exit();
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Render local file and exit
|
||||
if let Some(ref file) = args.flag_render {
|
||||
let path = PathBuf::from(file);
|
||||
if let Err(msg) = print_page(&path, args.flag_markdown, enable_styles) {
|
||||
if let Err(msg) = print_page(&path, args.flag_markdown, &config) {
|
||||
eprintln!("{}", msg);
|
||||
process::exit(1);
|
||||
} else {
|
||||
|
|
@ -371,8 +356,10 @@ fn main() {
|
|||
|
||||
// List cached commands and exit
|
||||
if args.flag_list {
|
||||
// Check cache for freshness
|
||||
check_cache(&args);
|
||||
if !cache_updated {
|
||||
// Check cache for freshness
|
||||
check_cache(&args);
|
||||
}
|
||||
|
||||
// Get list of pages
|
||||
let pages = cache.list_pages().unwrap_or_else(|e| {
|
||||
|
|
@ -392,12 +379,15 @@ fn main() {
|
|||
// Show command from cache
|
||||
if let Some(ref command) = args.arg_command {
|
||||
let command = command.join("-");
|
||||
// Check cache for freshness
|
||||
check_cache(&args);
|
||||
|
||||
if !cache_updated {
|
||||
// Check cache for freshness
|
||||
check_cache(&args);
|
||||
}
|
||||
|
||||
// Search for command in cache
|
||||
if let Some(path) = cache.find_page(&command) {
|
||||
if let Err(msg) = print_page(&path, args.flag_markdown, enable_styles) {
|
||||
if let Err(msg) = print_page(&path, args.flag_markdown, &config) {
|
||||
eprintln!("{}", msg);
|
||||
process::exit(1);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,3 +19,7 @@ bold = false
|
|||
[display]
|
||||
use_pager = false
|
||||
compact = false
|
||||
|
||||
[updates]
|
||||
auto_update = false
|
||||
auto_update_interval_hours = 720
|
||||
|
|
|
|||
65
tests/lib.rs
65
tests/lib.rs
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
extern crate assert_cmd;
|
||||
extern crate escargot;
|
||||
extern crate filetime;
|
||||
extern crate predicates;
|
||||
extern crate tempdir;
|
||||
extern crate utime;
|
||||
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::Write;
|
||||
use std::process::Command;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use assert_cmd::prelude::*;
|
||||
use tempdir::TempDir;
|
||||
|
|
@ -160,7 +161,11 @@ fn test_quiet_old_cache() {
|
|||
.success()
|
||||
.stdout(is_empty());
|
||||
|
||||
let _ = utime::set_file_times(testenv.cache_dir.path().join("tldr-master"), 1, 1).unwrap();
|
||||
filetime::set_file_mtime(
|
||||
testenv.cache_dir.path().join("tldr-master"),
|
||||
filetime::FileTime::from_unix_time(1, 0),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
testenv
|
||||
.command()
|
||||
|
|
@ -354,3 +359,59 @@ fn test_list_flag_rendering() {
|
|||
.success()
|
||||
.stdout("bar\nbaz\nfoo\nqux\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_autoupdate_cache() {
|
||||
let testenv = TestEnv::new();
|
||||
|
||||
// The first time, if automatic updates are disabled, the cache should not be found
|
||||
testenv
|
||||
.command()
|
||||
.args(&["--list"])
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(contains("Cache not found. Please run `tldr --update`."));
|
||||
|
||||
let config_file_path = testenv.config_dir.path().join("config.toml");
|
||||
let cache_file_path = testenv.cache_dir.path().join("tldr-master");
|
||||
|
||||
// Activate automatic updates, set the auto-update interval to 24 hours
|
||||
let mut config_file = File::create(&config_file_path).unwrap();
|
||||
config_file
|
||||
.write("[updates]\nauto_update = true\nauto_update_interval_hours = 24".as_bytes())
|
||||
.unwrap();
|
||||
config_file.flush().unwrap();
|
||||
|
||||
// Helper function that runs `tldr --list` and asserts that the cache is automatically updated
|
||||
// or not, depending on the value of `expected`.
|
||||
let check_cache_updated = |expected| {
|
||||
let assert = testenv.command().args(&["--list"]).assert().success();
|
||||
let pred = contains("Successfully updated cache");
|
||||
if expected {
|
||||
assert.stdout(pred)
|
||||
} else {
|
||||
assert.stdout(pred.not())
|
||||
};
|
||||
};
|
||||
|
||||
// The cache is updated the first time we run `tldr --list`
|
||||
check_cache_updated(true);
|
||||
|
||||
// The cache is not updated with a subsequent call
|
||||
check_cache_updated(false);
|
||||
|
||||
// We update the modification and access times such that they are about 23 hours from now.
|
||||
// auto-update interval is 24 hours, the cache should not be updated
|
||||
let new_mtime = SystemTime::now() - Duration::from_secs(82_800);
|
||||
filetime::set_file_mtime(&cache_file_path, new_mtime.into()).unwrap();
|
||||
check_cache_updated(false);
|
||||
|
||||
// We update the modification and access times such that they are about 25 hours from now.
|
||||
// auto-update interval is 24 hours, the cache should be updated
|
||||
let new_mtime = SystemTime::now() - Duration::from_secs(90_000);
|
||||
filetime::set_file_mtime(&cache_file_path, new_mtime.into()).unwrap();
|
||||
check_cache_updated(true);
|
||||
|
||||
// The cache is not updated with a subsequent call
|
||||
check_cache_updated(false);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue