diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index 2acb4d2..db18833 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - project: [ myceli, controller, hyphae ] + project: [ myceli, controller, hyphae, watcher ] target: [ armv7-unknown-linux-gnueabihf, @@ -60,6 +60,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: + project: [ myceli, watcher ] target: [ armv7-unknown-linux-gnueabihf, @@ -73,14 +74,14 @@ jobs: - name: clean cargo run: cargo clean - name: cargo/cross build - run: CROSS_CONFIG=Cross.toml cross build --bin myceli --target ${{ matrix.target }} --profile small --features small --no-default-features + run: CROSS_CONFIG=Cross.toml cross build --bin ${{ matrix.project }} --target ${{ matrix.target }} --profile small --features small --no-default-features - name: Compress binary run: | - tar -cvf myceli-small-${{ github.ref_name }}-${{ matrix.target }}.tar -C ./target/${{ matrix.target }}/small myceli - xz -9 --keep --extreme myceli-small-${{ github.ref_name }}-${{ matrix.target }}.tar - gzip --best myceli-small-${{ github.ref_name }}-${{ matrix.target }}.tar + tar -cvf ${{ matrix.project }}-small-${{ github.ref_name }}-${{ matrix.target }}.tar -C ./target/${{ matrix.target }}/small ${{ matrix.project }} + xz -9 --keep --extreme ${{ matrix.project }}-small-${{ github.ref_name }}-${{ matrix.target }}.tar + gzip --best ${{ matrix.project }}-small-${{ github.ref_name }}-${{ matrix.target }}.tar - name: upload binary - run: gh release upload "$GITHUB_REF" myceli-small-${{ github.ref_name }}-${{ matrix.target }}.tar.?z + run: gh release upload "$GITHUB_REF" *-small-${{ github.ref_name }}-${{ matrix.target }}.tar.?z env: GITHUB_TOKEN: ${{ github.token }} shell: bash diff --git a/.idea/space.iml b/.idea/space.iml index 0f6a024..34493f2 100644 --- a/.idea/space.iml +++ b/.idea/space.iml @@ -13,7 +13,9 @@ + + @@ -21,4 +23,4 @@ - \ No newline at end of file + diff --git a/Cargo.lock b/Cargo.lock index 4b3bc49..cb62981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,7 +124,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -134,7 +134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -460,6 +460,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "config" +version = "0.1.0" +dependencies = [ + "anyhow", + "dirs", + "figment", + "log", + "serde", + "transports", +] + [[package]] name = "constant_time_eq" version = "0.2.6" @@ -600,6 +612,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -642,7 +675,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -703,6 +736,18 @@ dependencies = [ "walkdir", ] +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -724,6 +769,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "funty" version = "2.0.0" @@ -1091,6 +1145,26 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -1108,7 +1182,7 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1148,7 +1222,7 @@ dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1184,6 +1258,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1406,7 +1500,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1496,6 +1590,7 @@ dependencies = [ "assert_fs", "blake2", "cid", + "config", "env_logger", "figment", "file-hashing", @@ -1525,6 +1620,24 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "notify" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1581,6 +1694,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "parity-scale-codec" version = "3.6.1" @@ -1884,6 +2003,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1893,6 +2021,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" version = "1.8.4" @@ -1993,7 +2132,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2218,9 +2357,9 @@ dependencies = [ "autocfg", "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2308,7 +2447,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2639,6 +2778,20 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "watcher" +version = "0.1.0" +dependencies = [ + "anyhow", + "config", + "env_logger", + "log", + "messages", + "notify", + "smalog", + "transports", +] + [[package]] name = "web-sys" version = "0.3.64" @@ -2697,7 +2850,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -2706,7 +2868,22 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -2715,51 +2892,93 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 2f7cd6f..daac604 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "config", "controller", "hyphae", "ipfs-unixfs", @@ -8,7 +9,8 @@ members = [ "messages", "myceli", "smalog", - "transports" + "transports", + "watcher" ] [workspace.package] @@ -55,6 +57,7 @@ tokio-util = "0.7.8" toml = { version = "0.7.3", default-features = false } # Internal deps +config = { path = "config" } ipfs-unixfs = { path = "ipfs-unixfs" } local-storage = { path = "local-storage" } messages = { path = "messages" } diff --git a/config/Cargo.toml b/config/Cargo.toml new file mode 100644 index 0000000..926fb8c --- /dev/null +++ b/config/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "config" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow.workspace = true +dirs = "5.0.1" +figment.workspace = true +log.workspace = true +serde.workspace = true +transports.workspace = true \ No newline at end of file diff --git a/myceli/src/config.rs b/config/src/config.rs similarity index 75% rename from myceli/src/config.rs rename to config/src/config.rs index cac00ee..7e79f4e 100644 --- a/myceli/src/config.rs +++ b/config/src/config.rs @@ -1,12 +1,13 @@ use anyhow::{bail, Result}; use figment::{ providers::{Format, Serialized, Toml}, - Figment, + Figment, Provider, }; +use log::debug; use serde::{Deserialize, Serialize}; use transports::MAX_MTU; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct Config { // The network address myceli will listen on for incoming messages. pub listen_address: String, @@ -25,6 +26,9 @@ pub struct Config { // The network address of the radio that myceli should respond to by default, if not set then // myceli will respond to the sending address (or address set in relevant request). pub radio_address: Option, + // A path to a directory which where files that appear should be auto-imported. + // Absence implies no such directory exists + pub watched_directory: Option, } impl Default for Config { @@ -47,18 +51,29 @@ impl Default for Config { chunk_transmit_throttle: None, // Default to no set radio address radio_address: None, + watched_directory: None, } } } +fn default_path() -> Option { + if let Some(d) = dirs::config_dir() { + let f = d.join("myceli").join("myceli.toml"); + if f.is_file() { + return f.into_os_string().into_string().ok(); + } + } + None +} impl Config { pub fn parse(path: Option) -> Result { let mut config = Figment::from(Serialized::defaults(Config::default())); - if let Some(path) = path { - config = config.merge(Toml::file(path)); + if let Some(path) = path.or(default_path()) { + let toml_values = Toml::file(&path); + debug!("Config values in file {}: {:?}", &path, toml_values.data()); + config = config.merge(toml_values); } let config: Self = config.extract()?; - if config.mtu > MAX_MTU { bail!("Configured MTU is too large, cannot exceed {MAX_MTU}",); } diff --git a/config/src/lib.rs b/config/src/lib.rs new file mode 100644 index 0000000..05f5367 --- /dev/null +++ b/config/src/lib.rs @@ -0,0 +1,3 @@ +mod config; + +pub type Config = config::Config; diff --git a/local-storage/src/storage.rs b/local-storage/src/storage.rs index 31e65d6..74850ee 100644 --- a/local-storage/src/storage.rs +++ b/local-storage/src/storage.rs @@ -12,7 +12,7 @@ use std::fs::File as FsFile; use std::io::Write; use std::path::Path; -use log::{error, info}; +use log::{debug, error, info}; pub struct Storage { pub provider: Box, @@ -28,6 +28,7 @@ impl Storage { } pub fn import_path(&self, path: &Path) -> Result { + debug!("import_path({:?})", &path); let rt = tokio::runtime::Runtime::new()?; let blocks: Result> = rt.block_on(async { let file: File = FileBuilder::new() diff --git a/myceli/Cargo.toml b/myceli/Cargo.toml index 684fb5c..fc7bab6 100644 --- a/myceli/Cargo.toml +++ b/myceli/Cargo.toml @@ -9,6 +9,7 @@ rust-version.workspace = true [dependencies] anyhow.workspace = true cid = { workspace = true, features = ["scale-codec"] } +config.workspace = true env_logger = { workspace = true, optional = true } figment.workspace = true local-storage = { path = "../local-storage", default-features = false } @@ -21,7 +22,7 @@ transports.workspace = true [features] big = ["local-storage/big", "good_log"] -small = ["local-storage/small"] +small = ["local-storage/small", "small_log"] good_log = ["dep:env_logger"] small_log = ["dep:smalog"] diff --git a/myceli/src/lib.rs b/myceli/src/lib.rs index c39e8c8..bea1517 100644 --- a/myceli/src/lib.rs +++ b/myceli/src/lib.rs @@ -1,4 +1,3 @@ -pub mod config; mod handlers; pub mod listener; pub mod shipper; diff --git a/myceli/src/listener.rs b/myceli/src/listener.rs index 68270af..a59a8c1 100644 --- a/myceli/src/listener.rs +++ b/myceli/src/listener.rs @@ -11,7 +11,7 @@ use std::sync::{Arc, Mutex}; use std::thread::spawn; use transports::Transport; -use log::{debug, error, info}; +use log::{error, info}; pub struct Listener { storage_path: String, @@ -100,7 +100,7 @@ impl Listener { } } Err(_e) => { - debug!("Receive message failed: {_e}"); + println!("Receive message failed: {_e}"); } } } @@ -112,7 +112,7 @@ impl Listener { sender_addr: &str, shipper_sender: Sender<(DataProtocol, String)>, ) -> Result> { - info!("Handling {message:?}"); + println!("Handling {message:?}"); let resp = match message { Message::ApplicationAPI(ApplicationAPI::TransmitDag { cid, diff --git a/myceli/src/main.rs b/myceli/src/main.rs index a4617de..a7b057f 100644 --- a/myceli/src/main.rs +++ b/myceli/src/main.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use myceli::config::Config; +use config::Config; use myceli::listener::Listener; use std::net::ToSocketAddrs; use std::sync::Arc; diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml new file mode 100644 index 0000000..87a9bff --- /dev/null +++ b/watcher/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "watcher" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow.workspace = true +config.workspace = true +env_logger = { workspace = true, optional = true } +log.workspace = true +messages.workspace = true +notify = "6.0.1" +smalog = { workspace = true, optional = true } +transports.workspace = true + +[features] +big = ["good_log"] +small = ["small_log"] +good_log = ["dep:env_logger"] +small_log = ["dep:smalog"] diff --git a/watcher/src/handler.rs b/watcher/src/handler.rs new file mode 100644 index 0000000..99d7546 --- /dev/null +++ b/watcher/src/handler.rs @@ -0,0 +1,52 @@ +use log::{debug, error, info, trace}; +use messages::{ApplicationAPI, Message}; +use notify::{event::ModifyKind, Event, EventKind}; +use std::path::Path; +use std::time::Duration; +use transports::{Transport, UdpTransport}; + +pub(crate) struct Handler { + trx: UdpTransport, + target_addr: String, +} + +impl Handler { + pub fn new(cfg: &config::Config) -> Result { + let trx = UdpTransport::new("0.0.0.0:0", cfg.mtu, cfg.chunk_transmit_throttle)?; + let target_addr = cfg.listen_address.clone(); + Ok(Self { trx, target_addr }) + } + + pub fn handle_event(&self, event: notify::Result) { + trace!("handle_event({:?})", &event); + match event { + Err(err) => { + error!("FileSystem error: {:?}", err); + } + Ok(ev) => match ev.kind { + EventKind::Modify(ModifyKind::Data(_)) => { + //Some of these events can occur while the file is still being modified + std::thread::sleep(Duration::from_millis(100)); + info!("File modified, import: {:?}", &ev); + for p in ev.paths { + self.send(&p); + } + } + _ => debug!("Ignoring FileSystem event: {:?}", &ev), + }, + } + } + pub fn send(&self, path: &Path) { + let path = if let Some(p) = path.as_os_str().to_str() { + p.to_owned() + } else { + error!("Path {:?} can't be turned into string?!", &path); + return; + }; + let m = ApplicationAPI::ImportFile { path }; + let m = Message::ApplicationAPI(m); + if let Err(e) = self.trx.send(m, &self.target_addr) { + error!("Error sending: {:?}", &e); + } + } +} diff --git a/watcher/src/main.rs b/watcher/src/main.rs new file mode 100644 index 0000000..7fd8618 --- /dev/null +++ b/watcher/src/main.rs @@ -0,0 +1,52 @@ +use notify::Watcher; +use std::{fs, path::PathBuf, time::Duration}; + +mod handler; + +#[cfg(all(not(feature = "small"), not(feature = "big")))] +compile_error! {"Select either big or small feature"} + +fn watched_dir(cfg: &config::Config) -> PathBuf { + let mut result = PathBuf::new(); + result.push( + cfg.clone() + .watched_directory + .clone() + .expect("Must configure watched_directory before running watcher."), + ); + result +} + +fn main() { + #[cfg(feature = "good_log")] + env_logger::init(); + + #[cfg(feature = "small_log")] + smalog::init(); + + let config_path = std::env::args().nth(1); + let cfg = config::Config::parse(config_path).expect("Failed to parse config"); + let hndr = handler::Handler::new(&cfg).expect("Failed to configure transport & event handler"); + let dir = watched_dir(&cfg); + let mut watcher = notify::recommended_watcher(move |e| hndr.handle_event(e)) + .expect("Unable to create directory watcher."); + watcher + .watch(&dir, notify::RecursiveMode::NonRecursive) + .expect("Unable to watch directory."); + let hndr = + handler::Handler::new(&cfg).expect("Failed to configure second transport & event handler"); + let mut preexisting = + fs::read_dir(&dir).expect("Can't list watched_directory - does it exist?"); + let mut t = 2; + while dir.is_dir() { + std::thread::sleep(Duration::from_secs(t)); + if let Some(Ok(f)) = preexisting.next() { + if f.metadata().map(|d| d.is_file()).unwrap_or(false) { + hndr.send(&f.path()); + } + } else if let Ok(rd) = fs::read_dir(&dir) { + preexisting = rd; + t *= 2; + } + } +}