aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/populate/src/check.rs
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/populate/src/check.rs')
-rw-r--r--pkgs/populate/src/check.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/pkgs/populate/src/check.rs b/pkgs/populate/src/check.rs
index cb67865..ebe5dbf 100644
--- a/pkgs/populate/src/check.rs
+++ b/pkgs/populate/src/check.rs
@@ -1,13 +1,16 @@
-//! Checks of the spec, the same as checks.nix makes during evaluation, so a
-//! spec from anywhere else gets checked as well. Messages are the same.
+//! Checks of the sources and the target, the same as checks.nix makes during
+//! evaluation, so sources from anywhere else get checked as well. Messages
+//! are the same.
use crate::spec::{Source, Spec};
use serde_json::{Map, Value};
use std::collections::BTreeMap;
-/// The spec's checks in the order checks.nix makes them, the first failing
-/// one's message.
+/// The checks in the order checks.nix makes them, the first failing one's
+/// message. The target's host and user, which a command line gives, come
+/// first.
pub fn spec(spec: &Spec) -> Result<(), String> {
+ target_host(&spec.target.host, spec.target.user.as_deref())?;
target_path(&spec.target.path)?;
for (name, source) in &spec.source {
source_name(name)?;
@@ -16,6 +19,24 @@ pub fn spec(spec: &Spec) -> Result<(), String> {
inputs(&spec.source)
}
+/// The target's host and user, which ssh gets as arguments, mustn't be
+/// taken for its options, and the host can't be empty.
+fn target_host(host: &str, user: Option<&str>) -> Result<(), String> {
+ if host.is_empty() || host.starts_with('-') {
+ return Err(format!(
+ "krops: target host {} can't be used: it must not be empty or start with -",
+ quote(host)
+ ));
+ }
+ if user.is_some_and(|u| u.starts_with('-')) {
+ return Err(format!(
+ "krops: target user {} can't be used: it must not start with -",
+ quote(user.unwrap_or_default())
+ ));
+ }
+ Ok(())
+}
+
/// What a setting holds.
#[derive(Clone, Copy)]
enum Kind {
@@ -365,14 +386,37 @@ mod tests {
}
#[test]
+ fn target_hosts() {
+ assert!(target_host("host", Some("root")).is_ok());
+ assert!(target_host("2001:db8::1", None).is_ok());
+ assert_eq!(
+ target_host("-oProxyCommand=x", None).unwrap_err(),
+ r#"krops: target host "-oProxyCommand=x" can't be used: it must not be empty or start with -"#
+ );
+ assert!(target_host("", None).is_err());
+ assert!(target_host("host", Some("-x")).is_err());
+ }
+
+ #[test]
fn settings() {
let spec = |file: &str| -> Spec {
- serde_json::from_str(&format!(
- r#"{{"version": 1, "target": {{"host": "h", "path": "/a"}},
- "source": {{"x": {{"type": "file", "file": {}}}}}}}"#,
- file
- ))
- .unwrap()
+ Spec {
+ backup: false,
+ force: false,
+ prune: false,
+ source: serde_json::from_str(&format!(
+ r#"{{"x": {{"type": "file", "file": {file}}}}}"#
+ ))
+ .unwrap(),
+ target: crate::spec::Target {
+ user: None,
+ host: "h".to_string(),
+ port: None,
+ path: "/a".to_string(),
+ sudo: false,
+ extra_options: vec![],
+ },
+ }
};
assert!(super::spec(&spec(r#"{"path": "/src"}"#)).is_ok());
assert!(super::spec(&spec(r#"{"path": "--rsync-path=x"}"#)).is_err());