Skip to content

Commit

Permalink
feat: Add clear command to clear the wallpaper cache
Browse files Browse the repository at this point in the history
  • Loading branch information
bcyran committed Jan 21, 2024
1 parent 10976ab commit 355bd75
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ pub fn preview<P: AsRef<Path>>(path: P, delay: u64, repeat: bool) -> Result<()>
Ok(())
}

pub fn clear(all: bool) -> Result<()> {
let mut loader = WallpaperLoader::new();
let last_wallpaper = (!all).then(|| LastWallpaper::find().get()).flatten();
loader.clear_cache(last_wallpaper);
if all {
LastWallpaper::find().clear();
}
Ok(())
}

fn validate_wallpaper_file<P: AsRef<Path>>(path: P) -> Result<()> {
let path = path.as_ref();
if !path.exists() {
Expand Down
61 changes: 60 additions & 1 deletion src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::constants::{APP_NAME, APP_QUALIFIER};
#[derive(Debug)]
pub struct Cache {
base_dir: PathBuf,
entries: HashSet<String>,
pub entries: HashSet<String>,
}

impl Cache {
Expand Down Expand Up @@ -63,6 +63,15 @@ impl Cache {
}
}

/// Remove the cache dir for a given key.
pub fn remove_entry(&mut self, key: &str) {
let entry_path = self.get_entry(key);
if entry_path.is_dir() {
fs::remove_dir_all(entry_path).expect("couldn't remove cache entry directory");
}
self.entries.remove(key);
}

/// Create cache dir for a given key. Panics if the dir already exists.
fn add_entry(&mut self, key: &str) -> PathBuf {
let entry_path = self.base_dir.join(key);
Expand Down Expand Up @@ -127,6 +136,13 @@ impl LastWallpaper {
None
}
}

/// Remove the link to the last used wallpaper.
pub fn clear(&self) {
if fs::read_link(&self.link_path).is_ok() {
fs::remove_file(&self.link_path).ok();
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -185,6 +201,34 @@ mod tests {

assert_eq!(cache.entry(&entry_name), expected_dir.path());
expected_dir.assert(predicate::path::is_dir());

cache.remove_entry(&entry_name);
expected_dir.assert(predicate::path::missing());
}

#[rstest]
fn test_cache_entry_remove_exists(tmp_dir: TempDir) {
let entry_name = String::from("some_entry");
let expected_dir = tmp_dir.child(&entry_name);
expected_dir.create_dir_all().unwrap();

let mut cache = Cache::in_dir(&tmp_dir);

expected_dir.assert(predicate::path::is_dir());
cache.remove_entry(&entry_name);
expected_dir.assert(predicate::path::missing());
}

#[rstest]
fn test_cache_entry_remove_not_exists(tmp_dir: TempDir) {
let entry_name = String::from("some_entry");
let expected_dir = tmp_dir.child(&entry_name);

let mut cache = Cache::in_dir(&tmp_dir);

expected_dir.assert(predicate::path::missing());
cache.remove_entry(&entry_name);
expected_dir.assert(predicate::path::missing());
}

#[rstest]
Expand Down Expand Up @@ -225,4 +269,19 @@ mod tests {
last_wall.save(&target_path_2);
assert_eq!(last_wall.get(), Some(target_path_2.to_path_buf()));
}

#[rstest]
fn test_last_wallpaper_save_clear(tmp_dir: TempDir) {
let target_path = tmp_dir.child("target.heic");
let link_path = tmp_dir.child("test_link");
target_path.touch().unwrap();

let last_wall = LastWallpaper::load(&link_path);

last_wall.save(&target_path);
link_path.assert(predicate::path::exists());

last_wall.clear();
link_path.assert(predicate::path::missing());
}
}
6 changes: 6 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ pub enum Action {
#[arg(short, long, value_enum)]
appearance: Option<Appearance>,
},
/// Clear the wallpaper cache
Clear {
/// Clear all - do not skip the currently set wallpaper
#[arg(short, long, action)]
all: bool,
},
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
Expand Down
14 changes: 14 additions & 0 deletions src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ impl WallpaperLoader {
}
Wallpaper::load(&cache_dir).expect("malformed wallpaper cache")
}

/// Clear the wallpaper loader cache. Optionally skips one wallpaper with a given pahth.
pub fn clear_cache<P: AsRef<Path>>(&mut self, skip_wall_path: Option<P>) {
let mut entries_to_clear = self.cache.entries.clone();

if let Some(skip_wall_path) = skip_wall_path {
let skip_wall_hash = hash_file(&skip_wall_path).expect("wallpaper hashing failed");
entries_to_clear.remove(&skip_wall_hash);
}

for hash in entries_to_clear {
self.cache.remove_entry(&hash);
}
}
}

fn hash_file<P: AsRef<Path>>(path: P) -> Result<String> {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ fn main() -> Result<()> {
daemon,
appearance,
} => actions::set(file, daemon, appearance),
cli::Action::Clear { all } => actions::clear(all),
}
}
28 changes: 28 additions & 0 deletions tests/clear.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
mod common;

use common::{cached_wallpaper_dir, testenv, TestEnv, EXAMPLE_SUN, EXAMPLE_TIME};
use predicates::prelude::*;
use rstest::rstest;

#[rstest]
fn test_clear(testenv: TestEnv) {
let expected_first_wall_cache_dir = cached_wallpaper_dir(&testenv.cache_dir, &EXAMPLE_SUN);
let expected_second_wall_cache_dir = cached_wallpaper_dir(&testenv.cache_dir, &EXAMPLE_TIME);

testenv
.run(&["set", EXAMPLE_SUN.to_str().unwrap()])
.success();
testenv
.run(&["set", EXAMPLE_TIME.to_str().unwrap()])
.success();
assert!(predicates::path::is_dir().eval(&expected_first_wall_cache_dir));
assert!(predicates::path::is_dir().eval(&expected_second_wall_cache_dir));

testenv.run(&["clear"]).success();
assert!(predicates::path::missing().eval(&expected_first_wall_cache_dir));
assert!(predicates::path::is_dir().eval(&expected_second_wall_cache_dir));

testenv.run(&["clear", "--all"]).success();
assert!(predicates::path::missing().eval(&expected_first_wall_cache_dir));
assert!(predicates::path::missing().eval(&expected_second_wall_cache_dir));
}
13 changes: 9 additions & 4 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ pub const IMAGE_SET_MESSAGE: &str = "Set: ";
/// Message printed to stdout in dry-run mode to indicate that command is being run.
pub const COMMAND_RUN_MESSAGE: &str = "Run: ";

/// Get full path to cached wallpaper directory.
pub fn cached_wallpaper_dir<CP: AsRef<Path>>(cache_dir: CP, wallpaper: &PathBuf) -> PathBuf {
cache_dir
.as_ref()
.join("wallpapers")
.join(WALLPAPER_HASHES.get(wallpaper).unwrap())
}

/// Get full path to cached wallpaper image as a string.
/// Path is determined based on root cache directory, used wallpaper and name of the image in this
/// wallpaper.
Expand All @@ -64,10 +72,7 @@ pub fn cached_image_path_str<CP: AsRef<Path>>(
wallpaper: &PathBuf,
image: &str,
) -> String {
cache_dir
.as_ref()
.join("wallpapers")
.join(WALLPAPER_HASHES.get(wallpaper).unwrap())
cached_wallpaper_dir(cache_dir, wallpaper)
.join(image)
.to_str()
.unwrap()
Expand Down

0 comments on commit 355bd75

Please sign in to comment.