Skip to content

Commit

Permalink
refactor: simplify __MISE_WATCH variable to only contain the most rec…
Browse files Browse the repository at this point in the history
…ent timestamp
  • Loading branch information
jdx committed Nov 29, 2024
1 parent 87b11ef commit 47e73ca
Show file tree
Hide file tree
Showing 20 changed files with 30 additions and 154 deletions.
130 changes: 13 additions & 117 deletions src/hook_env.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeSet;
use std::io::prelude::*;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
use std::time::{SystemTime, UNIX_EPOCH};

use base64::prelude::*;
use eyre::Result;
Expand Down Expand Up @@ -75,29 +75,15 @@ pub fn dir_change() -> Option<(PathBuf, PathBuf)> {
}

fn have_files_been_modified(watches: &HookEnvWatches, watch_files: BTreeSet<PathBuf>) -> bool {
// make sure they have exactly the same config filenames
let watch_keys = watches.files.keys().cloned().collect::<BTreeSet<_>>();
if watch_keys != watch_files {
trace!(
"config files do not match {:?}",
watch_keys.symmetric_difference(&watch_files)
);
return true;
}

// check the files to see if they've been altered
let mut modified = false;
for (fp, prev_modtime) in &watches.files {
if let Ok(modtime) = fp
.metadata()
.expect("accessing config file modtime")
.modified()
{
for fp in &watch_files {
if let Ok(modtime) = fp.metadata().and_then(|m| m.modified()) {
let modtime = modtime
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
if modtime != *prev_modtime {
if modtime > watches.latest_update {
trace!("file modified: {:?}", fp);
modified = true;
watch_files::add_modified_file(fp.clone());
Expand All @@ -117,9 +103,9 @@ fn have_mise_env_vars_been_modified(watches: &HookEnvWatches) -> bool {
false
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct HookEnvWatches {
files: BTreeMap<PathBuf, u64>,
latest_update: u64,
env_var_hash: String,
}

Expand All @@ -141,20 +127,17 @@ pub fn deserialize_watches(raw: String) -> Result<HookEnvWatches> {
pub fn build_watches(
watch_files: impl IntoIterator<Item = WatchFilePattern>,
) -> Result<HookEnvWatches> {
let mut watches = BTreeMap::new();
let mut max_modtime = UNIX_EPOCH;
for cf in get_watch_files(watch_files) {
watches.insert(
cf.clone(),
cf.metadata()?
.modified()?
.duration_since(SystemTime::UNIX_EPOCH)?
.as_secs(),
);
max_modtime = std::cmp::max(cf.metadata()?.modified()?, max_modtime);
}

Ok(HookEnvWatches {
files: watches,
env_var_hash: get_mise_env_vars_hashed(),
latest_update: max_modtime
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
})
}

Expand Down Expand Up @@ -222,90 +205,3 @@ pub fn build_env_commands(shell: &dyn Shell, patches: &EnvDiffPatches) -> String

output
}

#[cfg(test)]
mod tests {
use std::time::UNIX_EPOCH;

use pretty_assertions::{assert_eq, assert_str_eq};
use test_log::test;

use super::*;

#[test]
fn test_have_config_files_been_modified() {
let files = BTreeSet::new();
let watches = HookEnvWatches {
files: BTreeMap::new(),
env_var_hash: "".into(),
};
assert!(!have_files_been_modified(&watches, files));

let fp = env::current_dir().unwrap().join(".test-tool-versions");
let watches = HookEnvWatches {
files: BTreeMap::from([(
fp.clone(),
UNIX_EPOCH
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
)]),
env_var_hash: "".into(),
};
let files = BTreeSet::from([fp.clone()]);
assert!(have_files_been_modified(&watches, files));

let modtime = fp.metadata().unwrap().modified().unwrap();
let watches = HookEnvWatches {
files: BTreeMap::from([(
fp.clone(),
modtime
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
)]),
env_var_hash: "".into(),
};
let files = BTreeSet::from([fp]);
assert!(!have_files_been_modified(&watches, files));
}

#[test]
fn test_serialize_watches_empty() {
let watches = HookEnvWatches {
files: BTreeMap::new(),
env_var_hash: "".into(),
};
let serialized = serialize_watches(&watches).unwrap();
let deserialized = deserialize_watches(serialized).unwrap();
assert_eq!(deserialized.files.len(), 0);
}

#[test]
fn test_serialize_watches() {
let serialized = serialize_watches(&HookEnvWatches {
files: BTreeMap::from([(
PathBuf::from("foo"),
UNIX_EPOCH
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
)]),
env_var_hash: "testing-123".into(),
})
.unwrap();
let deserialized = deserialize_watches(serialized).unwrap();
assert_eq!(deserialized.files.len(), 1);
assert_str_eq!(deserialized.env_var_hash, "testing-123");
assert_eq!(
*deserialized
.files
.get(PathBuf::from("foo").as_path())
.unwrap(),
UNIX_EPOCH
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs()
);
}
}
3 changes: 1 addition & 2 deletions src/shell/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ impl Shell for Bash {
let settings = Settings::get();
let exe = exe.to_string_lossy();
let mut out = formatdoc! {r#"
export MISE_SHELL=bash
export __MISE_ORIG_PATH="$PATH"
mise() {{
Expand Down Expand Up @@ -79,8 +78,8 @@ impl Shell for Bash {
PROMPT_COMMAND="${{PROMPT_COMMAND//_mise_hook/}}"
unset _mise_hook
unset mise
unset MISE_SHELL
unset __MISE_DIFF
unset __MISE_DIR
unset __MISE_WATCH
"#}
}
Expand Down
3 changes: 1 addition & 2 deletions src/shell/elvish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ impl Shell for Elvish {
set edit:before-readline = (conj $edit:before-readline $hook-env~)
fn activate {{
set-env MISE_SHELL elvish
set hook-enabled = $true
hook-env
}}
Expand Down Expand Up @@ -60,8 +59,8 @@ impl Shell for Elvish {

fn deactivate(&self) -> String {
formatdoc! {r#"
unset-env MISE_SHELL
unset-env __MISE_DIFF
unset-env __MISE_DIR
unset-env __MISE_WATCH
"#}
}
Expand Down
3 changes: 1 addition & 2 deletions src/shell/fish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ impl Shell for Fish {
// much of this is from direnv
// https://github.com/direnv/direnv/blob/cb5222442cb9804b1574954999f6073cc636eff0/internal/cmd/shell_fish.go#L14-L36
out.push_str(&formatdoc! {r#"
set -gx MISE_SHELL fish
set -gx __MISE_ORIG_PATH $PATH
function mise
Expand Down Expand Up @@ -101,8 +100,8 @@ impl Shell for Fish {
functions --erase __mise_env_eval_2
functions --erase __mise_cd_hook
functions --erase mise
set -e MISE_SHELL
set -e __MISE_DIFF
set -e __MISE_DIR
set -e __MISE_WATCH
"#}
}
Expand Down
2 changes: 1 addition & 1 deletion src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub enum ShellType {

impl ShellType {
pub fn load() -> Option<ShellType> {
let shell = env::var("MISE_SHELL").or(env::var("SHELL")).ok()?;
let shell = env::var("SHELL").ok()?;
if shell.ends_with("bash") {
Some(ShellType::Bash)
} else if shell.ends_with("elvish") {
Expand Down
8 changes: 3 additions & 5 deletions src/shell/nushell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ impl Shell for Nushell {

formatdoc! {r#"
export-env {{
$env.MISE_SHELL = "nu"
let mise_hook = {{
condition: {{ "MISE_SHELL" in $env }}
condition: {{ "__MISE_DIR" in $env }}
code: {{ mise_hook }}
}}
add-hook hooks.pre_prompt $mise_hook
Expand All @@ -63,7 +62,6 @@ impl Shell for Nushell {
if ($command == null) {{
^"{exe}"
}} else if ($command == "activate") {{
$env.MISE_SHELL = "nu"
}} else if ($command in $commands) {{
^"{exe}" $command ...$rest
| parse vars
Expand Down Expand Up @@ -94,9 +92,9 @@ impl Shell for Nushell {

fn deactivate(&self) -> String {
[
self.unset_env("MISE_SHELL"),
self.unset_env("__MISE_DIFF"),
self.unset_env("__MISE_DIFF"),
self.unset_env("__MISE_DIR"),
self.unset_env("__MISE_WATCH"),
]
.join("")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ source: src/shell/bash.rs
expression: "bash.activate(exe, \" --status\".into())"
snapshot_kind: text
---
export MISE_SHELL=bash
export __MISE_ORIG_PATH="$PATH"

mise() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ PROMPT_COMMAND="${PROMPT_COMMAND//_mise_hook;/}"
PROMPT_COMMAND="${PROMPT_COMMAND//_mise_hook/}"
unset _mise_hook
unset mise
unset MISE_SHELL
unset __MISE_DIFF
unset __MISE_DIR
unset __MISE_WATCH
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ source: src/shell/elvish.rs
expression: replace_path(&deactivate)
snapshot_kind: text
---
unset-env MISE_SHELL
unset-env __MISE_DIFF
unset-env __MISE_DIR
unset-env __MISE_WATCH
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ set after-chdir = (conj $after-chdir {|_| hook-env })
set edit:before-readline = (conj $edit:before-readline $hook-env~)

fn activate {
set-env MISE_SHELL elvish
set hook-enabled = $true
hook-env
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ source: src/shell/fish.rs
expression: "fish.activate(exe, \" --status\".into())"
snapshot_kind: text
---
set -gx MISE_SHELL fish
set -gx __MISE_ORIG_PATH $PATH

function mise
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ functions --erase __mise_env_eval
functions --erase __mise_env_eval_2
functions --erase __mise_cd_hook
functions --erase mise
set -e MISE_SHELL
set -e __MISE_DIFF
set -e __MISE_DIR
set -e __MISE_WATCH
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ source: src/shell/nushell.rs
expression: replace_path(&deactivate)
snapshot_kind: text
---
hide,MISE_SHELL,
hide,__MISE_DIFF,
hide,__MISE_DIFF,
hide,__MISE_DIR,
hide,__MISE_WATCH,
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ expression: "nushell.activate(exe, \" --status\".into())"
snapshot_kind: text
---
export-env {
$env.MISE_SHELL = "nu"
let mise_hook = {
condition: { "MISE_SHELL" in $env }
condition: { "__MISE_DIR" in $env }
code: { mise_hook }
}
add-hook hooks.pre_prompt $mise_hook
Expand All @@ -29,7 +28,6 @@ export def --env --wrapped main [command?: string, --help, ...rest: string] {
if ($command == null) {
^"/some/dir/mise"
} else if ($command == "activate") {
$env.MISE_SHELL = "nu"
} else if ($command in $commands) {
^"/some/dir/mise" $command ...$rest
| parse vars
Expand Down
2 changes: 0 additions & 2 deletions src/shell/snapshots/mise__shell__xonsh__tests__hook_init.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ def listen_prompt(): # Hook Events
execx($(/some/dir/mise hook-env --status -s xonsh))

envx = XSH.env
envx[ 'MISE_SHELL'] = 'xonsh'
environ['MISE_SHELL'] = envx.get_detyped('MISE_SHELL')
XSH.builtins.events.on_pre_prompt(listen_prompt) # Activate hook: before showing the prompt

def _mise(args):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ for hook_type in hooks:
break

del XSH.aliases['mise']
del XSH.env['MISE_SHELL']
del os.environ['MISE_SHELL']
del XSH.env['__MISE_DIFF']
del os.environ['__MISE_DIFF']
del XSH.env['__MISE_WATCH']
Expand Down
1 change: 0 additions & 1 deletion src/shell/snapshots/mise__shell__zsh__tests__activate.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ source: src/shell/zsh.rs
expression: "zsh.activate(exe, \" --status\".into())"
snapshot_kind: text
---
export MISE_SHELL=zsh
export __MISE_ORIG_PATH="$PATH"

mise() {
Expand Down
4 changes: 2 additions & 2 deletions src/shell/snapshots/mise__shell__zsh__tests__deactivate.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ precmd_functions=( ${precmd_functions:#_mise_hook} )
chpwd_functions=( ${chpwd_functions:#_mise_hook} )
unset -f _mise_hook
unset -f mise
unset MISE_SHELL
unset __MISE_WATCH
unset __MISE_DIFF
unset __MISE_DIR
unset __MISE_WATCH
4 changes: 0 additions & 4 deletions src/shell/xonsh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ impl Shell for Xonsh {
execx($({exe} hook-env{flags} -s xonsh))
envx = XSH.env
envx[ 'MISE_SHELL'] = 'xonsh'
environ['MISE_SHELL'] = envx.get_detyped('MISE_SHELL')
XSH.builtins.events.on_pre_prompt(listen_prompt) # Activate hook: before showing the prompt
def _mise(args):
Expand Down Expand Up @@ -86,8 +84,6 @@ impl Shell for Xonsh {
break
del XSH.aliases['mise']
del XSH.env['MISE_SHELL']
del os.environ['MISE_SHELL']
del XSH.env['__MISE_DIFF']
del os.environ['__MISE_DIFF']
del XSH.env['__MISE_WATCH']
Expand Down
Loading

0 comments on commit 47e73ca

Please sign in to comment.