Compare commits
2 Commits
e2cb36d2a8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 8379ae2136 | |||
| 12de215527 |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -9,17 +9,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- New `filter_grep` feature to optionally include the grep filter plugin (regex-based line filtering). Disabling this feature removes the `regex` crate and its ~800 KiB dependency stack from the binary.
|
||||||
|
- New `meta_all_musl` feature for all MUSL-compatible meta plugins (excludes `meta_magic` which requires libmagic)
|
||||||
|
- New `filter_all_musl` feature for all MUSL-compatible filter plugins
|
||||||
- Database index on `items(ts)` column for faster ORDER BY sorting
|
- Database index on `items(ts)` column for faster ORDER BY sorting
|
||||||
- Server API `ItemInfo` now includes `file_size` — actual filesystem-reported size of the item data file
|
- Server API `ItemInfo` now includes `file_size` — actual filesystem-reported size of the item data file
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- CLI args now feature-gated: `--server` and related options hidden when built without `server` feature; `--client-*` options hidden when built without `client` feature. Run `--help` only shows relevant options.
|
||||||
|
- `server` Cargo feature now includes TLS support by default (`axum-server`); `tls` feature removed
|
||||||
|
- Clap `conflicts_with_all` removed from all mode args — exclusivity now handled by implicit `group("mode")`
|
||||||
- Filter plugins check size before loading content into memory (prevents OOM on large inputs)
|
- Filter plugins check size before loading content into memory (prevents OOM on large inputs)
|
||||||
- Status page pre-allocates collections with known capacities (meta plugins, compression info)
|
- Status page pre-allocates collections with known capacities (meta plugins, compression info)
|
||||||
- `#[inline]` on HTML escape helper functions (`esc`, `esc_attr`) for hot path performance
|
- `#[inline]` on HTML escape helper functions (`esc`, `esc_attr`) for hot path performance
|
||||||
- Removed `once_cell` crate (replaced with `std::sync::LazyLock` from Rust 1.80)
|
- Removed `once_cell` crate (replaced with `std::sync::LazyLock` from Rust 1.80)
|
||||||
- Removed `lazy_static` crate (replaced with `std::sync::LazyLock`)
|
- Removed `lazy_static` crate (replaced with `std::sync::LazyLock`)
|
||||||
|
|
||||||
|
### Breaking
|
||||||
|
|
||||||
|
- Plugin feature flags renamed with type prefix for consistency:
|
||||||
|
- `magic` → `meta_magic`
|
||||||
|
- `infer` → `meta_infer`
|
||||||
|
- `tree_magic_mini` → `meta_tree_magic_mini`
|
||||||
|
- `tokens` → `meta_tokens`
|
||||||
|
- `grep` → `filter_grep`
|
||||||
|
- `all-meta-plugins` → `meta_all`
|
||||||
|
- `all-filter-plugins` → `filter_all`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- CLI help text typo: "metatdata" → "metadata" in `--get` and `--info` descriptions
|
- CLI help text typo: "metatdata" → "metadata" in `--get` and `--info` descriptions
|
||||||
|
|||||||
39
Cargo.toml
39
Cargo.toml
@@ -46,7 +46,7 @@ tree_magic_mini = { version = "3.2", optional = true }
|
|||||||
nix = { version = "0.30", features = ["fs", "process"] }
|
nix = { version = "0.30", features = ["fs", "process"] }
|
||||||
comfy-table = "7.2"
|
comfy-table = "7.2"
|
||||||
pwhash = "1.0"
|
pwhash = "1.0"
|
||||||
regex = "1.10"
|
regex = { version = "1.10", optional = true }
|
||||||
ringbuf = "0.4"
|
ringbuf = "0.4"
|
||||||
rusqlite = { version = "0.37", features = ["bundled", "array", "chrono"] }
|
rusqlite = { version = "0.37", features = ["bundled", "array", "chrono"] }
|
||||||
rusqlite_migration = "2.3"
|
rusqlite_migration = "2.3"
|
||||||
@@ -85,19 +85,20 @@ tiktoken-rs = { version = "0.9", optional = true }
|
|||||||
tempfile = "3.3"
|
tempfile = "3.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Default features include core compression engines and swagger UI
|
# Default features include core compression engines plugins that support MUSL
|
||||||
default = [
|
default = [
|
||||||
"client",
|
"client",
|
||||||
"gzip",
|
"gzip",
|
||||||
"infer",
|
"filter_grep",
|
||||||
|
"meta_infer",
|
||||||
"lz4",
|
"lz4",
|
||||||
"tokens",
|
"meta_tokens",
|
||||||
"tree_magic_mini",
|
"meta_tree_magic_mini",
|
||||||
"zstd"
|
"zstd"
|
||||||
]
|
]
|
||||||
|
|
||||||
# Server feature (includes axum and related dependencies)
|
# Server feature (includes axum and TLS/HTTPS via axum-server; rustls already available via client/ureq)
|
||||||
server = ["dep:axum", "dep:tower", "dep:tower-http", "dep:utoipa", "dep:jsonwebtoken"]
|
server = ["dep:axum", "dep:tower", "dep:tower-http", "dep:utoipa", "dep:jsonwebtoken", "dep:axum-server"]
|
||||||
|
|
||||||
# Compression features
|
# Compression features
|
||||||
gzip = ["flate2"]
|
gzip = ["flate2"]
|
||||||
@@ -106,14 +107,18 @@ bzip2 = []
|
|||||||
xz = []
|
xz = []
|
||||||
zstd = ["dep:zstd"]
|
zstd = ["dep:zstd"]
|
||||||
|
|
||||||
# Plugin features (meta and filter)
|
# Meta plugin features
|
||||||
all-meta-plugins = ["dep:magic", "dep:infer", "dep:tree_magic_mini"]
|
meta_magic = ["dep:magic"]
|
||||||
all-filter-plugins = []
|
meta_infer = ["dep:infer"]
|
||||||
|
meta_tree_magic_mini = ["dep:tree_magic_mini"]
|
||||||
|
meta_tokens = ["dep:tiktoken-rs"]
|
||||||
|
meta_all = ["meta_magic", "meta_infer", "meta_tree_magic_mini", "meta_tokens"]
|
||||||
|
meta_all_musl = ["meta_infer", "meta_tree_magic_mini", "meta_tokens"]
|
||||||
|
|
||||||
# Individual plugin features
|
# Filter plugin features
|
||||||
magic = ["dep:magic"]
|
filter_grep = ["dep:regex"]
|
||||||
infer = ["dep:infer"]
|
filter_all = ["filter_grep"]
|
||||||
tree_magic_mini = ["dep:tree_magic_mini"]
|
filter_all_musl = ["filter_grep"]
|
||||||
|
|
||||||
# Swagger UI feature
|
# Swagger UI feature
|
||||||
swagger = ["dep:utoipa-swagger-ui"]
|
swagger = ["dep:utoipa-swagger-ui"]
|
||||||
@@ -121,11 +126,5 @@ swagger = ["dep:utoipa-swagger-ui"]
|
|||||||
# Client feature (HTTP client for remote server)
|
# Client feature (HTTP client for remote server)
|
||||||
client = ["dep:ureq", "dep:os_pipe"]
|
client = ["dep:ureq", "dep:os_pipe"]
|
||||||
|
|
||||||
# TLS feature (HTTPS server support)
|
|
||||||
tls = ["dep:axum-server"]
|
|
||||||
|
|
||||||
# Token counting feature (LLM token support via tiktoken)
|
|
||||||
tokens = ["dep:tiktoken-rs"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.9"
|
rand = "0.9"
|
||||||
|
|||||||
41
src/args.rs
41
src/args.rs
@@ -24,77 +24,80 @@ pub struct Args {
|
|||||||
/// Struct for mode-specific arguments, defining CLI flags for different operations.
|
/// Struct for mode-specific arguments, defining CLI flags for different operations.
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
pub struct ModeArgs {
|
pub struct ModeArgs {
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "diff", "list", "delete", "info", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long)]
|
||||||
#[arg(help("Save an item using any tags or metadata provided"))]
|
#[arg(help("Save an item using any tags or metadata provided"))]
|
||||||
pub save: bool,
|
pub save: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "diff", "list", "delete", "info", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long)]
|
||||||
#[arg(help("Get an item either by its ID or by a combination of matching tags and metadata"))]
|
#[arg(help("Get an item either by its ID or by a combination of matching tags and metadata"))]
|
||||||
pub get: bool,
|
pub get: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "list", "delete", "info", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Show a diff between two items by ID"))]
|
#[arg(help("Show a diff between two items by ID"))]
|
||||||
pub diff: bool,
|
pub diff: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "delete", "info", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long)]
|
||||||
#[arg(help("List items, filtering on tags or metadata if given"))]
|
#[arg(help("List items, filtering on tags or metadata if given"))]
|
||||||
pub list: bool,
|
pub list: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "info", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long)]
|
||||||
#[arg(help("Delete items either by ID or by matching tags"))]
|
#[arg(help("Delete items either by ID or by matching tags"))]
|
||||||
#[arg(requires = "ids_or_tags")]
|
#[arg(requires = "ids_or_tags")]
|
||||||
pub delete: bool,
|
pub delete: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "delete", "update", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long)]
|
||||||
#[arg(help("Get an item either by its ID or by a combination of matching tags and metadata"))]
|
#[arg(help("Get an item either by its ID or by a combination of matching tags and metadata"))]
|
||||||
pub info: bool,
|
pub info: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short('u'), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "status", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short('u'), long)]
|
||||||
#[arg(help("Update an item's tags and metadata by ID"))]
|
#[arg(help("Update an item's tags and metadata by ID"))]
|
||||||
pub update: bool,
|
pub update: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "server", "status_plugins", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long)]
|
||||||
#[arg(help("Show status of directories and supported compression algorithms"))]
|
#[arg(help("Show status of directories and supported compression algorithms"))]
|
||||||
pub status: bool,
|
pub status: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status", "server", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Show available plugins and their configurations"))]
|
#[arg(help("Show available plugins and their configurations"))]
|
||||||
pub status_plugins: bool,
|
pub status_plugins: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Export items to a .keep.tar archive (requires IDs or tags)"))]
|
#[arg(help("Export items to a .keep.tar archive (requires IDs or tags)"))]
|
||||||
pub export: bool,
|
pub export: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, value_name("FILE"), conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status", "export"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), long, value_name("FILE"))]
|
||||||
#[arg(help("Import items from a .keep.tar archive or legacy .meta.yml file"))]
|
#[arg(help("Import items from a .keep.tar archive or legacy .meta.yml file"))]
|
||||||
pub import: Option<String>,
|
pub import: Option<String>,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status"]))]
|
#[cfg(feature = "server")]
|
||||||
|
#[arg(group("mode"), help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Start REST HTTP server"))]
|
#[arg(help("Start REST HTTP server"))]
|
||||||
pub server: bool,
|
pub server: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status", "server", "export", "import"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Generate default configuration and output to stdout"))]
|
#[arg(help("Generate default configuration and output to stdout"))]
|
||||||
pub generate_config: bool,
|
pub generate_config: bool,
|
||||||
|
|
||||||
#[arg(help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "update", "status", "server", "generate_config", "export", "import"]))]
|
#[arg(help_heading("Mode Options"), long)]
|
||||||
#[arg(help("Generate shell completion script"))]
|
#[arg(help("Generate shell completion script"))]
|
||||||
pub generate_completion: Option<Shell>,
|
pub generate_completion: Option<Shell>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_ADDRESS"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_ADDRESS"))]
|
||||||
#[arg(help("Server address to bind to"))]
|
#[arg(help("Server address to bind to"))]
|
||||||
pub server_address: Option<String>,
|
pub server_address: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PORT"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PORT"))]
|
||||||
#[arg(help("Server port to bind to"))]
|
#[arg(help("Server port to bind to"))]
|
||||||
pub server_port: Option<u16>,
|
pub server_port: Option<u16>,
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_CERT"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_CERT"))]
|
||||||
#[arg(help("Path to TLS certificate file (PEM) for HTTPS"))]
|
#[arg(help("Path to TLS certificate file (PEM) for HTTPS"))]
|
||||||
pub server_cert: Option<PathBuf>,
|
pub server_cert: Option<PathBuf>,
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_KEY"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_KEY"))]
|
||||||
#[arg(help("Path to TLS private key file (PEM) for HTTPS"))]
|
#[arg(help("Path to TLS private key file (PEM) for HTTPS"))]
|
||||||
pub server_key: Option<PathBuf>,
|
pub server_key: Option<PathBuf>,
|
||||||
@@ -249,24 +252,29 @@ pub struct OptionsArgs {
|
|||||||
#[arg(help("Output format (only works with --info, --status, --list)"))]
|
#[arg(help("Output format (only works with --info, --status, --list)"))]
|
||||||
pub output_format: Option<String>,
|
pub output_format: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PASSWORD"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PASSWORD"))]
|
||||||
#[arg(help("Password for server authentication (requires --server)"))]
|
#[arg(help("Password for server authentication (requires --server)"))]
|
||||||
pub server_password: Option<String>,
|
pub server_password: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PASSWORD_HASH"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_PASSWORD_HASH"))]
|
||||||
#[arg(help("Password hash for server authentication (requires --server)"))]
|
#[arg(help("Password hash for server authentication (requires --server)"))]
|
||||||
pub server_password_hash: Option<String>,
|
pub server_password_hash: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_USERNAME"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_USERNAME"))]
|
||||||
#[arg(help(
|
#[arg(help(
|
||||||
"Username for server Basic authentication (requires --server, defaults to 'keep')"
|
"Username for server Basic authentication (requires --server, defaults to 'keep')"
|
||||||
))]
|
))]
|
||||||
pub server_username: Option<String>,
|
pub server_username: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_JWT_SECRET"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_JWT_SECRET"))]
|
||||||
#[arg(help("JWT secret for token-based authentication (requires --server)"))]
|
#[arg(help("JWT secret for token-based authentication (requires --server)"))]
|
||||||
pub server_jwt_secret: Option<String>,
|
pub server_jwt_secret: Option<String>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(
|
#[arg(
|
||||||
help_heading("Server Options"),
|
help_heading("Server Options"),
|
||||||
long,
|
long,
|
||||||
@@ -275,6 +283,7 @@ pub struct OptionsArgs {
|
|||||||
#[arg(help("Path to file containing JWT secret (requires --server)"))]
|
#[arg(help("Path to file containing JWT secret (requires --server)"))]
|
||||||
pub server_jwt_secret_file: Option<PathBuf>,
|
pub server_jwt_secret_file: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_MAX_BODY_SIZE"))]
|
#[arg(help_heading("Server Options"), long, env("KEEP_SERVER_MAX_BODY_SIZE"))]
|
||||||
#[arg(help("Maximum request body size in bytes (requires --server, default: unlimited)"))]
|
#[arg(help("Maximum request body size in bytes (requires --server, default: unlimited)"))]
|
||||||
pub server_max_body_size: Option<u64>,
|
pub server_max_body_size: Option<u64>,
|
||||||
|
|||||||
@@ -301,42 +301,48 @@ impl Settings {
|
|||||||
config_builder = config_builder.set_override("force", true)?;
|
config_builder = config_builder.set_override("force", true)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_password) = &args.options.server_password {
|
if let Some(server_password) = &args.options.server_password {
|
||||||
config_builder =
|
config_builder =
|
||||||
config_builder.set_override("server.password", server_password.as_str())?;
|
config_builder.set_override("server.password", server_password.as_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_password_hash) = &args.options.server_password_hash {
|
if let Some(server_password_hash) = &args.options.server_password_hash {
|
||||||
config_builder = config_builder
|
config_builder = config_builder
|
||||||
.set_override("server.password_hash", server_password_hash.as_str())?;
|
.set_override("server.password_hash", server_password_hash.as_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_username) = &args.options.server_username {
|
if let Some(server_username) = &args.options.server_username {
|
||||||
config_builder =
|
config_builder =
|
||||||
config_builder.set_override("server.username", server_username.as_str())?;
|
config_builder.set_override("server.username", server_username.as_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_address) = &args.mode.server_address {
|
if let Some(server_address) = &args.mode.server_address {
|
||||||
config_builder =
|
config_builder =
|
||||||
config_builder.set_override("server.address", server_address.as_str())?;
|
config_builder.set_override("server.address", server_address.as_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_port) = args.mode.server_port {
|
if let Some(server_port) = args.mode.server_port {
|
||||||
config_builder = config_builder.set_override("server.port", server_port)?;
|
config_builder = config_builder.set_override("server.port", server_port)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_cert) = &args.mode.server_cert {
|
if let Some(server_cert) = &args.mode.server_cert {
|
||||||
config_builder = config_builder
|
config_builder = config_builder
|
||||||
.set_override("server.cert_file", server_cert.to_string_lossy().as_ref())?;
|
.set_override("server.cert_file", server_cert.to_string_lossy().as_ref())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "server")]
|
||||||
if let Some(server_key) = &args.mode.server_key {
|
if let Some(server_key) = &args.mode.server_key {
|
||||||
config_builder = config_builder
|
config_builder = config_builder
|
||||||
.set_override("server.key_file", server_key.to_string_lossy().as_ref())?;
|
.set_override("server.key_file", server_key.to_string_lossy().as_ref())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if let Some(max_body_size) = args.options.server_max_body_size {
|
if let Some(max_body_size) = args.options.server_max_body_size {
|
||||||
config_builder = config_builder.set_override("server.max_body_size", max_body_size)?;
|
config_builder = config_builder.set_override("server.max_body_size", max_body_size)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::io::{Read, Result, Write};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use strum::EnumString;
|
use strum::EnumString;
|
||||||
|
|
||||||
|
#[cfg(feature = "filter_grep")]
|
||||||
pub mod grep;
|
pub mod grep;
|
||||||
/// Filter plugin module for processing input streams.
|
/// Filter plugin module for processing input streams.
|
||||||
///
|
///
|
||||||
@@ -16,7 +17,7 @@ pub mod grep;
|
|||||||
/// ```
|
/// ```
|
||||||
/// # use std::io::{Read, Write};
|
/// # use std::io::{Read, Write};
|
||||||
/// # use keep::filter_plugin::parse_filter_string;
|
/// # use keep::filter_plugin::parse_filter_string;
|
||||||
/// let mut chain = parse_filter_string("head_lines(10)|grep(pattern=error)")?;
|
/// let mut chain = parse_filter_string("head_lines(10)|tail_lines(5)")?;
|
||||||
/// # let mut reader: &mut dyn Read = &mut std::io::empty();
|
/// # let mut reader: &mut dyn Read = &mut std::io::empty();
|
||||||
/// # let mut writer: Vec<u8> = Vec::new();
|
/// # let mut writer: Vec<u8> = Vec::new();
|
||||||
/// # chain.filter(&mut reader, &mut writer)?;
|
/// # chain.filter(&mut reader, &mut writer)?;
|
||||||
@@ -26,12 +27,13 @@ pub mod head;
|
|||||||
pub mod skip;
|
pub mod skip;
|
||||||
pub mod strip_ansi;
|
pub mod strip_ansi;
|
||||||
pub mod tail;
|
pub mod tail;
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[cfg(feature = "filter_grep")]
|
||||||
pub use grep::GrepFilter;
|
pub use grep::GrepFilter;
|
||||||
pub use head::{HeadBytesFilter, HeadLinesFilter};
|
pub use head::{HeadBytesFilter, HeadLinesFilter};
|
||||||
pub use skip::{SkipBytesFilter, SkipLinesFilter};
|
pub use skip::{SkipBytesFilter, SkipLinesFilter};
|
||||||
@@ -199,13 +201,14 @@ pub enum FilterType {
|
|||||||
TailLines,
|
TailLines,
|
||||||
SkipBytes,
|
SkipBytes,
|
||||||
SkipLines,
|
SkipLines,
|
||||||
|
#[cfg(feature = "filter_grep")]
|
||||||
Grep,
|
Grep,
|
||||||
StripAnsi,
|
StripAnsi,
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
HeadTokens,
|
HeadTokens,
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
SkipTokens,
|
SkipTokens,
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
TailTokens,
|
TailTokens,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,9 +359,8 @@ impl FilterChain {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use keep::filter_plugin::{FilterChain, GrepFilter};
|
/// # use keep::filter_plugin::FilterChain;
|
||||||
/// let mut chain = FilterChain::new();
|
/// let mut chain = FilterChain::new();
|
||||||
/// chain.add_plugin(Box::new(GrepFilter::new("error".to_string()).unwrap()));
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_plugin(&mut self, plugin: Box<dyn FilterPlugin>) {
|
pub fn add_plugin(&mut self, plugin: Box<dyn FilterPlugin>) {
|
||||||
self.plugins.push(plugin);
|
self.plugins.push(plugin);
|
||||||
@@ -535,6 +537,7 @@ fn create_filter_with_options(
|
|||||||
// Get the default options for this filter type by creating a temporary instance
|
// Get the default options for this filter type by creating a temporary instance
|
||||||
// To do this, we need to create a default instance of the appropriate filter
|
// To do this, we need to create a default instance of the appropriate filter
|
||||||
let option_defs = match filter_type {
|
let option_defs = match filter_type {
|
||||||
|
#[cfg(feature = "filter_grep")]
|
||||||
FilterType::Grep => grep::GrepFilter::new("".to_string())?.options(),
|
FilterType::Grep => grep::GrepFilter::new("".to_string())?.options(),
|
||||||
FilterType::HeadBytes => head::HeadBytesFilter::new(0).options(),
|
FilterType::HeadBytes => head::HeadBytesFilter::new(0).options(),
|
||||||
FilterType::HeadLines => head::HeadLinesFilter::new(0).options(),
|
FilterType::HeadLines => head::HeadLinesFilter::new(0).options(),
|
||||||
@@ -543,11 +546,11 @@ fn create_filter_with_options(
|
|||||||
FilterType::SkipBytes => skip::SkipBytesFilter::new(0).options(),
|
FilterType::SkipBytes => skip::SkipBytesFilter::new(0).options(),
|
||||||
FilterType::SkipLines => skip::SkipLinesFilter::new(0).options(),
|
FilterType::SkipLines => skip::SkipLinesFilter::new(0).options(),
|
||||||
FilterType::StripAnsi => strip_ansi::StripAnsiFilter::new().options(),
|
FilterType::StripAnsi => strip_ansi::StripAnsiFilter::new().options(),
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::HeadTokens => tokens::HeadTokensFilter::new(0).options(),
|
FilterType::HeadTokens => tokens::HeadTokensFilter::new(0).options(),
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::SkipTokens => tokens::SkipTokensFilter::new(0).options(),
|
FilterType::SkipTokens => tokens::SkipTokensFilter::new(0).options(),
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::TailTokens => tokens::TailTokensFilter::new(0).options(),
|
FilterType::TailTokens => tokens::TailTokensFilter::new(0).options(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -617,6 +620,7 @@ fn create_specific_filter(
|
|||||||
options: &HashMap<String, serde_json::Value>,
|
options: &HashMap<String, serde_json::Value>,
|
||||||
) -> Result<Box<dyn FilterPlugin>> {
|
) -> Result<Box<dyn FilterPlugin>> {
|
||||||
match filter_type {
|
match filter_type {
|
||||||
|
#[cfg(feature = "filter_grep")]
|
||||||
FilterType::Grep => {
|
FilterType::Grep => {
|
||||||
let pattern = options
|
let pattern = options
|
||||||
.get("pattern")
|
.get("pattern")
|
||||||
@@ -717,7 +721,7 @@ fn create_specific_filter(
|
|||||||
}
|
}
|
||||||
Ok(Box::new(strip_ansi::StripAnsiFilter::new()))
|
Ok(Box::new(strip_ansi::StripAnsiFilter::new()))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::HeadTokens => {
|
FilterType::HeadTokens => {
|
||||||
let count = options
|
let count = options
|
||||||
.get("count")
|
.get("count")
|
||||||
@@ -735,7 +739,7 @@ fn create_specific_filter(
|
|||||||
f.encoding = encoding;
|
f.encoding = encoding;
|
||||||
Ok(Box::new(f))
|
Ok(Box::new(f))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::SkipTokens => {
|
FilterType::SkipTokens => {
|
||||||
let count = options
|
let count = options
|
||||||
.get("count")
|
.get("count")
|
||||||
@@ -753,7 +757,7 @@ fn create_specific_filter(
|
|||||||
f.encoding = encoding;
|
f.encoding = encoding;
|
||||||
Ok(Box::new(f))
|
Ok(Box::new(f))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
FilterType::TailTokens => {
|
FilterType::TailTokens => {
|
||||||
let count = options
|
let count = options
|
||||||
.get("count")
|
.get("count")
|
||||||
@@ -774,7 +778,7 @@ fn create_specific_filter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
fn parse_encoding_option(
|
fn parse_encoding_option(
|
||||||
options: &std::collections::HashMap<String, serde_json::Value>,
|
options: &std::collections::HashMap<String, serde_json::Value>,
|
||||||
) -> (crate::tokenizer::TokenEncoding, crate::tokenizer::Tokenizer) {
|
) -> (crate::tokenizer::TokenEncoding, crate::tokenizer::Tokenizer) {
|
||||||
|
|||||||
17
src/lib.rs
17
src/lib.rs
@@ -45,7 +45,7 @@ pub mod services;
|
|||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
pub mod tokenizer;
|
pub mod tokenizer;
|
||||||
|
|
||||||
// Re-export Args struct for library usage
|
// Re-export Args struct for library usage
|
||||||
@@ -56,9 +56,12 @@ pub use services::CoreError;
|
|||||||
|
|
||||||
// Import all filter plugins to ensure they register themselves
|
// Import all filter plugins to ensure they register themselves
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use filter_plugin::{grep, head, skip, strip_ansi, tail};
|
#[cfg(feature = "filter_grep")]
|
||||||
|
use filter_plugin::grep;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use filter_plugin::{head, skip, strip_ansi, tail};
|
||||||
|
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use filter_plugin::tokens as token_filters;
|
use filter_plugin::tokens as token_filters;
|
||||||
|
|
||||||
@@ -66,19 +69,19 @@ use crate::meta_plugin::{
|
|||||||
cwd, digest, env, exec, hostname, keep_pid, read_rate, read_time, shell, shell_pid, user,
|
cwd, digest, env, exec, hostname, keep_pid, read_rate, read_time, shell, shell_pid, user,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::meta_plugin::magic_file;
|
use crate::meta_plugin::magic_file;
|
||||||
|
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::meta_plugin::tokens;
|
use crate::meta_plugin::tokens;
|
||||||
|
|
||||||
#[cfg(feature = "infer")]
|
#[cfg(feature = "meta_infer")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::meta_plugin::infer_plugin;
|
use crate::meta_plugin::infer_plugin;
|
||||||
|
|
||||||
#[cfg(feature = "tree_magic_mini")]
|
#[cfg(feature = "meta_tree_magic_mini")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::meta_plugin::tree_magic_mini;
|
use crate::meta_plugin::tree_magic_mini;
|
||||||
|
|
||||||
|
|||||||
24
src/main.rs
24
src/main.rs
@@ -122,6 +122,7 @@ fn main() -> Result<(), Error> {
|
|||||||
Import,
|
Import,
|
||||||
Status,
|
Status,
|
||||||
StatusPlugins,
|
StatusPlugins,
|
||||||
|
#[cfg(feature = "server")]
|
||||||
Server,
|
Server,
|
||||||
GenerateConfig,
|
GenerateConfig,
|
||||||
}
|
}
|
||||||
@@ -150,9 +151,14 @@ fn main() -> Result<(), Error> {
|
|||||||
mode = KeepModes::Status;
|
mode = KeepModes::Status;
|
||||||
} else if args.mode.status_plugins {
|
} else if args.mode.status_plugins {
|
||||||
mode = KeepModes::StatusPlugins;
|
mode = KeepModes::StatusPlugins;
|
||||||
} else if args.mode.server {
|
}
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
{
|
||||||
|
if args.mode.server {
|
||||||
mode = KeepModes::Server;
|
mode = KeepModes::Server;
|
||||||
} else if args.mode.generate_config {
|
}
|
||||||
|
}
|
||||||
|
if args.mode.generate_config {
|
||||||
mode = KeepModes::GenerateConfig;
|
mode = KeepModes::GenerateConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +194,7 @@ fn main() -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate server password usage
|
// Validate server password usage
|
||||||
|
#[cfg(feature = "server")]
|
||||||
if settings.server_password().is_some() && mode != KeepModes::Server {
|
if settings.server_password().is_some() && mode != KeepModes::Server {
|
||||||
cmd.error(
|
cmd.error(
|
||||||
ErrorKind::InvalidValue,
|
ErrorKind::InvalidValue,
|
||||||
@@ -355,19 +362,8 @@ fn main() -> Result<(), Error> {
|
|||||||
KeepModes::StatusPlugins => {
|
KeepModes::StatusPlugins => {
|
||||||
modes::status_plugins::mode_status_plugins(&mut cmd, &settings, data_path, db_path)
|
modes::status_plugins::mode_status_plugins(&mut cmd, &settings, data_path, db_path)
|
||||||
}
|
}
|
||||||
KeepModes::Server => {
|
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
{
|
KeepModes::Server => modes::server::mode_server(&mut cmd, &settings, &mut conn, data_path),
|
||||||
modes::server::mode_server(&mut cmd, &settings, &mut conn, data_path)
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "server"))]
|
|
||||||
{
|
|
||||||
cmd.error(
|
|
||||||
ErrorKind::MissingRequiredArgument,
|
|
||||||
"This binary was not compiled with server support. Recompile with --features server"
|
|
||||||
).exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KeepModes::GenerateConfig => {
|
KeepModes::GenerateConfig => {
|
||||||
modes::generate_config::mode_generate_config(&mut cmd, &settings)
|
modes::generate_config::mode_generate_config(&mut cmd, &settings)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
use magic::{Cookie, CookieFlags};
|
use magic::{Cookie, CookieFlags};
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
@@ -16,12 +16,12 @@ use crate::meta_plugin::{
|
|||||||
// separate cookies can be used from different threads concurrently without
|
// separate cookies can be used from different threads concurrently without
|
||||||
// synchronization. Using thread_local! avoids unsafe impl Send since the
|
// synchronization. Using thread_local! avoids unsafe impl Send since the
|
||||||
// storage is inherently !Send.
|
// storage is inherently !Send.
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static MAGIC_COOKIE: std::cell::RefCell<Option<Cookie>> = const { std::cell::RefCell::new(None) };
|
static MAGIC_COOKIE: std::cell::RefCell<Option<Cookie>> = const { std::cell::RefCell::new(None) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MagicFileMetaPluginImpl {
|
pub struct MagicFileMetaPluginImpl {
|
||||||
buffer: Vec<u8>,
|
buffer: Vec<u8>,
|
||||||
@@ -30,7 +30,7 @@ pub struct MagicFileMetaPluginImpl {
|
|||||||
base: BaseMetaPlugin,
|
base: BaseMetaPlugin,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
impl MagicFileMetaPluginImpl {
|
impl MagicFileMetaPluginImpl {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
options: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
options: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
||||||
@@ -113,7 +113,7 @@ impl MagicFileMetaPluginImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
impl MetaPlugin for MagicFileMetaPluginImpl {
|
impl MetaPlugin for MagicFileMetaPluginImpl {
|
||||||
fn is_finalized(&self) -> bool {
|
fn is_finalized(&self) -> bool {
|
||||||
self.is_finalized
|
self.is_finalized
|
||||||
@@ -222,10 +222,10 @@ impl MetaPlugin for MagicFileMetaPluginImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
pub use MagicFileMetaPluginImpl as MagicFileMetaPlugin;
|
pub use MagicFileMetaPluginImpl as MagicFileMetaPlugin;
|
||||||
|
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FallbackMagicFileMetaPlugin {
|
pub struct FallbackMagicFileMetaPlugin {
|
||||||
buffer: Vec<u8>,
|
buffer: Vec<u8>,
|
||||||
@@ -234,7 +234,7 @@ pub struct FallbackMagicFileMetaPlugin {
|
|||||||
base: BaseMetaPlugin,
|
base: BaseMetaPlugin,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
impl FallbackMagicFileMetaPlugin {
|
impl FallbackMagicFileMetaPlugin {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
options: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
options: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
||||||
@@ -336,7 +336,7 @@ impl FallbackMagicFileMetaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
impl MetaPlugin for FallbackMagicFileMetaPlugin {
|
impl MetaPlugin for FallbackMagicFileMetaPlugin {
|
||||||
fn is_finalized(&self) -> bool {
|
fn is_finalized(&self) -> bool {
|
||||||
self.is_finalized
|
self.is_finalized
|
||||||
@@ -441,7 +441,7 @@ impl MetaPlugin for FallbackMagicFileMetaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
pub use FallbackMagicFileMetaPlugin as MagicFileMetaPlugin;
|
pub use FallbackMagicFileMetaPlugin as MagicFileMetaPlugin;
|
||||||
|
|
||||||
use crate::meta_plugin::register_meta_plugin;
|
use crate::meta_plugin::register_meta_plugin;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub mod digest;
|
|||||||
pub mod env;
|
pub mod env;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
pub mod hostname;
|
pub mod hostname;
|
||||||
#[cfg(feature = "infer")]
|
#[cfg(feature = "meta_infer")]
|
||||||
pub mod infer_plugin;
|
pub mod infer_plugin;
|
||||||
pub mod keep_pid;
|
pub mod keep_pid;
|
||||||
pub mod magic_file;
|
pub mod magic_file;
|
||||||
@@ -17,32 +17,32 @@ pub mod read_time;
|
|||||||
pub mod shell;
|
pub mod shell;
|
||||||
pub mod shell_pid;
|
pub mod shell_pid;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
#[cfg(feature = "tokens")]
|
#[cfg(feature = "meta_tokens")]
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
#[cfg(feature = "tree_magic_mini")]
|
#[cfg(feature = "meta_tree_magic_mini")]
|
||||||
pub mod tree_magic_mini;
|
pub mod tree_magic_mini;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
pub use digest::DigestMetaPlugin;
|
pub use digest::DigestMetaPlugin;
|
||||||
pub use exec::MetaPluginExec;
|
pub use exec::MetaPluginExec;
|
||||||
#[cfg(feature = "magic")]
|
#[cfg(feature = "meta_magic")]
|
||||||
pub use magic_file::MagicFileMetaPlugin;
|
pub use magic_file::MagicFileMetaPlugin;
|
||||||
// pub use text::TextMetaPlugin; // Removed duplicate
|
// pub use text::TextMetaPlugin; // Removed duplicate
|
||||||
pub use cwd::CwdMetaPlugin;
|
pub use cwd::CwdMetaPlugin;
|
||||||
pub use env::EnvMetaPlugin;
|
pub use env::EnvMetaPlugin;
|
||||||
pub use hostname::HostnameMetaPlugin;
|
pub use hostname::HostnameMetaPlugin;
|
||||||
#[cfg(feature = "infer")]
|
#[cfg(feature = "meta_infer")]
|
||||||
pub use infer_plugin::InferMetaPlugin;
|
pub use infer_plugin::InferMetaPlugin;
|
||||||
pub use keep_pid::KeepPidMetaPlugin;
|
pub use keep_pid::KeepPidMetaPlugin;
|
||||||
pub use read_rate::ReadRateMetaPlugin;
|
pub use read_rate::ReadRateMetaPlugin;
|
||||||
pub use read_time::ReadTimeMetaPlugin;
|
pub use read_time::ReadTimeMetaPlugin;
|
||||||
pub use shell::ShellMetaPlugin;
|
pub use shell::ShellMetaPlugin;
|
||||||
pub use shell_pid::ShellPidMetaPlugin;
|
pub use shell_pid::ShellPidMetaPlugin;
|
||||||
#[cfg(feature = "tree_magic_mini")]
|
#[cfg(feature = "meta_tree_magic_mini")]
|
||||||
pub use tree_magic_mini::TreeMagicMiniMetaPlugin;
|
pub use tree_magic_mini::TreeMagicMiniMetaPlugin;
|
||||||
pub use user::UserMetaPlugin;
|
pub use user::UserMetaPlugin;
|
||||||
|
|
||||||
#[cfg(not(feature = "magic"))]
|
#[cfg(not(feature = "meta_magic"))]
|
||||||
pub use magic_file::FallbackMagicFileMetaPlugin as MagicFileMetaPlugin;
|
pub use magic_file::FallbackMagicFileMetaPlugin as MagicFileMetaPlugin;
|
||||||
|
|
||||||
type PluginConstructor = fn(
|
type PluginConstructor = fn(
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use clap::Command;
|
|||||||
use clap::error::ErrorKind;
|
use clap::error::ErrorKind;
|
||||||
use comfy_table::{Attribute, Cell, ContentArrangement, Table};
|
use comfy_table::{Attribute, Cell, ContentArrangement, Table};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use regex::Regex;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
@@ -56,23 +55,18 @@ pub enum OutputFormat {
|
|||||||
Yaml,
|
Yaml,
|
||||||
}
|
}
|
||||||
|
|
||||||
static KEEP_META_RE: std::sync::LazyLock<Regex> =
|
|
||||||
std::sync::LazyLock::new(|| Regex::new(r"^KEEP_META_(.+)$").unwrap());
|
|
||||||
|
|
||||||
pub const IMPORT_FORMAT_ERROR: &str =
|
pub const IMPORT_FORMAT_ERROR: &str =
|
||||||
"Unsupported import format: {} (expected .keep.tar or .meta.yml)";
|
"Unsupported import format: {} (expected .keep.tar or .meta.yml)";
|
||||||
|
|
||||||
pub fn get_meta_from_env() -> HashMap<String, String> {
|
pub fn get_meta_from_env() -> HashMap<String, String> {
|
||||||
debug!("COMMON: Getting meta from KEEP_META_*");
|
debug!("COMMON: Getting meta from KEEP_META_*");
|
||||||
let mut meta_env: HashMap<String, String> = HashMap::new();
|
let mut meta_env: HashMap<String, String> = HashMap::new();
|
||||||
|
const PREFIX: &str = "KEEP_META_";
|
||||||
for (key, value) in env::vars() {
|
for (key, value) in env::vars() {
|
||||||
if let Some(meta_name_caps) = KEEP_META_RE.captures(key.as_str()) {
|
if let Some(name) = key.strip_prefix(PREFIX) {
|
||||||
let name = meta_name_caps.get(1).map(|m| m.as_str().to_string());
|
if !name.is_empty() && name != "PLUGINS" {
|
||||||
if let Some(name) = name {
|
|
||||||
if name != "PLUGINS" {
|
|
||||||
debug!("COMMON: Found meta: {}={}", name, value);
|
debug!("COMMON: Found meta: {}={}", name, value);
|
||||||
meta_env.insert(name, value);
|
meta_env.insert(name.to_string(), value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,6 +635,7 @@ pub struct ImportMeta {
|
|||||||
///
|
///
|
||||||
/// Returns the first ID if provided, the newest item matching tags,
|
/// Returns the first ID if provided, the newest item matching tags,
|
||||||
/// or the newest item overall if neither is specified.
|
/// or the newest item overall if neither is specified.
|
||||||
|
#[cfg(feature = "client")]
|
||||||
pub fn resolve_item_id(
|
pub fn resolve_item_id(
|
||||||
client: &crate::client::KeepClient,
|
client: &crate::client::KeepClient,
|
||||||
ids: &[i64],
|
ids: &[i64],
|
||||||
@@ -664,6 +659,7 @@ pub fn resolve_item_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve item IDs from explicit IDs or tags (multi-item variant).
|
/// Resolve item IDs from explicit IDs or tags (multi-item variant).
|
||||||
|
#[cfg(feature = "client")]
|
||||||
pub fn resolve_item_ids(
|
pub fn resolve_item_ids(
|
||||||
client: &crate::client::KeepClient,
|
client: &crate::client::KeepClient,
|
||||||
ids: &[i64],
|
ids: &[i64],
|
||||||
|
|||||||
@@ -532,6 +532,7 @@ pub struct TagsQuery {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// use keep::modes::server::common::ListItemsQuery;
|
/// use keep::modes::server::common::ListItemsQuery;
|
||||||
/// let query = ListItemsQuery {
|
/// let query = ListItemsQuery {
|
||||||
|
/// ids: None,
|
||||||
/// tags: Some("important".to_string()),
|
/// tags: Some("important".to_string()),
|
||||||
/// order: Some("newest".to_string()),
|
/// order: Some("newest".to_string()),
|
||||||
/// start: Some(0),
|
/// start: Some(0),
|
||||||
|
|||||||
@@ -179,24 +179,18 @@ async fn run_server(
|
|||||||
let addr: SocketAddr = bind_address.parse()?;
|
let addr: SocketAddr = bind_address.parse()?;
|
||||||
|
|
||||||
// Warn if authentication is enabled without TLS
|
// Warn if authentication is enabled without TLS
|
||||||
if config.password.is_some() || config.password_hash.is_some() || config.jwt_secret.is_some() {
|
if (config.password.is_some() || config.password_hash.is_some() || config.jwt_secret.is_some())
|
||||||
#[cfg(not(feature = "tls"))]
|
&& (config.cert_file.is_none() || config.key_file.is_none())
|
||||||
log::warn!(
|
{
|
||||||
"SECURITY: Authentication enabled but TLS support is not compiled in. Credentials will be transmitted in plain text!"
|
|
||||||
);
|
|
||||||
#[cfg(feature = "tls")]
|
|
||||||
if config.cert_file.is_none() || config.key_file.is_none() {
|
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"SECURITY: Authentication enabled but TLS is not configured. Credentials will be transmitted in plain text!"
|
"SECURITY: Authentication enabled but TLS is not configured. Credentials will be transmitted in plain text!"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Build the app into a service
|
// Build the app into a service
|
||||||
let service = app.into_make_service_with_connect_info::<SocketAddr>();
|
let service = app.into_make_service_with_connect_info::<SocketAddr>();
|
||||||
|
|
||||||
// Use TLS if both cert and key files are provided
|
// Use TLS if both cert and key files are provided
|
||||||
#[cfg(feature = "tls")]
|
|
||||||
if let (Some(cert_file), Some(key_file)) = (&config.cert_file, &config.key_file) {
|
if let (Some(cert_file), Some(key_file)) = (&config.cert_file, &config.key_file) {
|
||||||
info!("SERVER: HTTPS server listening on {addr}");
|
info!("SERVER: HTTPS server listening on {addr}");
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod digest_tests;
|
pub mod digest_tests;
|
||||||
|
|
||||||
#[cfg(feature = "infer")]
|
#[cfg(feature = "meta_infer")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod infer_tests;
|
pub mod infer_tests;
|
||||||
|
|
||||||
#[cfg(feature = "tree_magic_mini")]
|
#[cfg(feature = "meta_tree_magic_mini")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tree_magic_mini_tests;
|
pub mod tree_magic_mini_tests;
|
||||||
|
|||||||
Reference in New Issue
Block a user