Update change fields, make single path

pull/196/head
Chip Senkbeil 12 months ago
parent 01f03413ab
commit d68eb4a364
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -1547,29 +1547,17 @@ mod tests {
}
/// Validates a response as being a series of changes that include the provided paths
fn validate_changed_paths(
data: &Response,
expected_paths: &[PathBuf],
should_panic: bool,
) -> bool {
fn validate_changed_path(data: &Response, expected_path: &Path, should_panic: bool) -> bool {
match data {
Response::Changed(change) if should_panic => {
let paths: Vec<PathBuf> = change
.paths
.iter()
.map(|x| x.canonicalize().unwrap())
.collect();
assert_eq!(paths, expected_paths, "Wrong paths reported: {:?}", change);
let path = change.path.canonicalize().unwrap();
assert_eq!(path, expected_path, "Wrong path reported: {:?}", change);
true
}
Response::Changed(change) => {
let paths: Vec<PathBuf> = change
.paths
.iter()
.map(|x| x.canonicalize().unwrap())
.collect();
paths == expected_paths
let path = change.path.canonicalize().unwrap();
path == expected_path
}
x if should_panic => panic!("Unexpected response: {:?}", x),
_ => false,
@ -1602,9 +1590,9 @@ mod tests {
.recv()
.await
.expect("Channel closed before we got change");
validate_changed_paths(
validate_changed_path(
&data,
&[file.path().to_path_buf().canonicalize().unwrap()],
&file.path().to_path_buf().canonicalize().unwrap(),
/* should_panic */ true,
);
}
@ -1657,9 +1645,9 @@ mod tests {
let path = file.path().to_path_buf();
assert!(
responses.iter().any(|res| validate_changed_paths(
responses.iter().any(|res| validate_changed_path(
res,
&[file.path().to_path_buf().canonicalize().unwrap()],
&file.path().to_path_buf().canonicalize().unwrap(),
/* should_panic */ false,
)),
"Missing {:?} in {:?}",
@ -1672,9 +1660,9 @@ mod tests {
let path = nested_file.path().to_path_buf();
assert!(
responses.iter().any(|res| validate_changed_paths(
responses.iter().any(|res| validate_changed_path(
res,
&[file.path().to_path_buf().canonicalize().unwrap()],
&file.path().to_path_buf().canonicalize().unwrap(),
/* should_panic */ false,
)),
"Missing {:?} in {:?}",
@ -1740,9 +1728,9 @@ mod tests {
.recv()
.await
.expect("Channel closed before we got change");
validate_changed_paths(
validate_changed_path(
&data,
&[file_1.path().to_path_buf().canonicalize().unwrap()],
&file_1.path().to_path_buf().canonicalize().unwrap(),
/* should_panic */ true,
);
@ -1752,9 +1740,9 @@ mod tests {
.recv()
.await
.expect("Channel closed before we got change");
validate_changed_paths(
validate_changed_path(
&data,
&[file_2.path().to_path_buf().canonicalize().unwrap()],
&file_2.path().to_path_buf().canonicalize().unwrap(),
/* should_panic */ true,
);
}

@ -7,7 +7,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use distant_core::net::common::ConnectionId;
use distant_core::protocol::{Change, ChangeDetails, ChangeDetailsAttribute, ChangeKind};
use log::*;
use notify::event::{AccessKind, AccessMode, MetadataKind, ModifyKind};
use notify::event::{AccessKind, AccessMode, MetadataKind, ModifyKind, RenameMode};
use notify::{
Config as WatcherConfig, Error as WatcherError, ErrorKind as WatcherErrorKind,
Event as WatcherEvent, EventKind, PollWatcher, RecommendedWatcher, RecursiveMode, Watcher,
@ -338,7 +338,21 @@ async fn watcher_task<W>(
};
for registered_path in registered_paths.iter() {
for path in ev.paths {
// For rename both, we assume the paths is a pair that represents before and
// after, so we want to grab the before and use it!
let (paths, renamed): (&[PathBuf], Option<PathBuf>) = match ev.kind {
EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => (
&ev.paths[0..1],
if ev.paths.len() > 1 {
ev.paths.last().cloned()
} else {
None
},
),
_ => (&ev.paths, None),
};
for path in paths {
let attribute = match ev.kind {
EventKind::Modify(ModifyKind::Metadata(MetadataKind::Ownership)) => {
Some(ChangeDetailsAttribute::Ownership)
@ -372,21 +386,22 @@ async fn watcher_task<W>(
let change = Change {
timestamp,
kind,
path,
path: path.to_path_buf(),
details: ChangeDetails {
attribute,
renamed: renamed.clone(),
timestamp: details_timestamp,
extra: ev.info().map(ToString::to_string),
},
};
}
match registered_path.filter_and_send(change).await {
Ok(_) => (),
Err(x) => error!(
"[Conn {}] Failed to forward changes to paths: {}",
registered_path.id(),
x
),
match registered_path.filter_and_send(change).await {
Ok(_) => (),
Err(x) => error!(
"[Conn {}] Failed to forward changes to paths: {}",
registered_path.id(),
x
),
}
}
}
}

@ -119,18 +119,16 @@ impl RegisteredPath {
}
/// Sends a reply for a change tied to this registered path, filtering
/// out any paths that are not applicable
/// out any changes that are not applicable.
///
/// Returns true if message was sent, and false if not
pub async fn filter_and_send(&self, mut change: Change) -> io::Result<bool> {
/// Returns true if message was sent, and false if not.
pub async fn filter_and_send(&self, change: Change) -> io::Result<bool> {
if !self.allowed().contains(&change.kind) {
return Ok(false);
}
// filter the paths that are not applicable
change.paths.retain(|p| self.applies_to_path(p.as_path()));
if !change.paths.is_empty() {
// Only send if this registered path applies to the changed path
if self.applies_to_path(&change.path) {
self.reply
.send(Response::Changed(change))
.await
@ -141,9 +139,9 @@ impl RegisteredPath {
}
/// Sends an error message and includes paths if provided, skipping sending the message if
/// no paths match and `skip_if_no_paths` is true
/// no paths match and `skip_if_no_paths` is true.
///
/// Returns true if message was sent, and false if not
/// Returns true if message was sent, and false if not.
pub async fn filter_and_send_error<T>(
&self,
msg: &str,

@ -38,6 +38,11 @@ pub struct ChangeDetails {
#[serde(skip_serializing_if = "Option::is_none")]
pub attribute: Option<ChangeDetailsAttribute>,
/// When event is renaming, this will be populated with the resulting name
/// when we know both the old and new names (for kind == rename)
#[serde(skip_serializing_if = "Option::is_none")]
pub renamed: Option<PathBuf>,
/// Unix timestamps (in seconds) related to the change. For other platforms, their timestamps
/// are converted into a Unix timestamp format.
///

@ -646,6 +646,7 @@ mod tests {
path: PathBuf::from("path"),
details: ChangeDetails {
attribute: Some(ChangeDetailsAttribute::Permissions),
renamed: Some(PathBuf::from("renamed")),
timestamp: Some(u64::MAX),
extra: Some(String::from("info")),
},
@ -661,6 +662,7 @@ mod tests {
"paths": ["path"],
"details": {
"attribute": "permissions",
"renamed": "renamed",
"ts": u64::MAX,
"extra": "info",
},
@ -698,6 +700,7 @@ mod tests {
"path": "path",
"details": {
"attribute": "permissions",
"renamed": "renamed",
"ts": u64::MAX,
"extra": "info",
},
@ -712,6 +715,7 @@ mod tests {
path: PathBuf::from("path"),
details: ChangeDetails {
attribute: Some(ChangeDetailsAttribute::Permissions),
renamed: Some(PathBuf::from("renamed")),
timestamp: Some(u64::MAX),
extra: Some(String::from("info")),
},
@ -743,6 +747,7 @@ mod tests {
path: PathBuf::from("path"),
details: ChangeDetails {
attribute: Some(ChangeDetailsAttribute::Permissions),
renamed: Some(PathBuf::from("renamed")),
timestamp: Some(u64::MAX),
extra: Some(String::from("info")),
},
@ -793,6 +798,7 @@ mod tests {
path: PathBuf::from("path"),
details: ChangeDetails {
attribute: Some(ChangeDetailsAttribute::Permissions),
renamed: Some(PathBuf::from("renamed")),
timestamp: Some(u64::MAX),
extra: Some(String::from("info")),
},
@ -808,6 +814,7 @@ mod tests {
path: PathBuf::from("path"),
details: ChangeDetails {
attribute: Some(ChangeDetailsAttribute::Permissions),
renamed: Some(PathBuf::from("renamed")),
timestamp: Some(u64::MAX),
extra: Some(String::from("info")),
},

@ -154,21 +154,16 @@ fn format_shell(state: &mut FormatterState, data: protocol::Response) -> Output
}
protocol::Response::Changed(change) => Output::StdoutLine(
format!(
"{}{}",
"{} {:?}",
match change.kind {
ChangeKind::Create => "Following paths were created:\n",
ChangeKind::Delete => "Following paths were removed:\n",
x if x.is_access() => "Following paths were accessed:\n",
x if x.is_modify() => "Following paths were modified:\n",
x if x.is_rename() => "Following paths were renamed:\n",
_ => "Following paths were affected:\n",
ChangeKind::Create => "(Created)",
ChangeKind::Delete => "(Removed)",
x if x.is_access() => "(Accessed)",
x if x.is_modify() => "(Modified)",
x if x.is_rename() => "(Renamed)",
_ => "(Affected)",
},
change
.paths
.into_iter()
.map(|p| format!("* {}", p.to_string_lossy()))
.collect::<Vec<String>>()
.join("\n")
change.path
)
.into_bytes(),
),

@ -63,8 +63,8 @@ async fn should_support_json_watching_single_file(mut api_process: CtxCommand<Ap
assert_eq!(res["origin_id"], id, "JSON: {res}");
assert_eq!(res["payload"]["type"], "changed", "JSON: {res}");
assert_eq!(
res["payload"]["paths"],
json!([file.to_path_buf().canonicalize().unwrap()]),
res["payload"]["path"],
json!(file.to_path_buf().canonicalize().unwrap()),
"JSON: {res}"
);
}
@ -121,8 +121,8 @@ async fn should_support_json_watching_directory_recursively(
assert_eq!(res["origin_id"], id, "JSON: {res}");
assert_eq!(res["payload"]["type"], "changed", "JSON: {res}");
assert_eq!(
res["payload"]["paths"],
json!([dir.to_path_buf().canonicalize().unwrap()]),
res["payload"]["path"],
json!(dir.to_path_buf().canonicalize().unwrap()),
"JSON: {res}"
);
}
@ -137,8 +137,8 @@ async fn should_support_json_watching_directory_recursively(
assert_eq!(res["origin_id"], id, "JSON: {res}");
assert_eq!(res["payload"]["type"], "changed", "JSON: {res}");
assert_eq!(
res["payload"]["paths"],
json!([file.to_path_buf().canonicalize().unwrap()]),
res["payload"]["path"],
json!(file.to_path_buf().canonicalize().unwrap()),
"JSON: {res}"
);
}
@ -213,8 +213,8 @@ async fn should_support_json_reporting_changes_using_correct_request_id(
assert_eq!(res["origin_id"], id_1, "JSON: {res}");
assert_eq!(res["payload"]["type"], "changed", "JSON: {res}");
assert_eq!(
res["payload"]["paths"],
json!([file1.to_path_buf().canonicalize().unwrap()]),
res["payload"]["path"],
json!(file1.to_path_buf().canonicalize().unwrap()),
"JSON: {res}"
);
@ -245,8 +245,8 @@ async fn should_support_json_reporting_changes_using_correct_request_id(
assert_eq!(res["origin_id"], id_2, "JSON: {res}");
assert_eq!(res["payload"]["type"], "changed", "JSON: {res}");
assert_eq!(
res["payload"]["paths"],
json!([file2.to_path_buf().canonicalize().unwrap()]),
res["payload"]["path"],
json!(file2.to_path_buf().canonicalize().unwrap()),
"JSON: {res}"
);
}

Loading…
Cancel
Save