mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-11-29 05:19:03 -05:00
switch from ancient clap/structopt release to bpaf
Improves #70: this reduces binary size from 12.3 MiB to 11.9 MiB (3%) on macOS/arm64. The user experience is almost the same. (The help output's `Usage:` lines lack the e.g. `moonfire-nvr run` prefix of argv[0] and subcommand, which isn't ideal, but I guess it's pretty minor in the grand scheme of things.)
This commit is contained in:
@@ -4,45 +4,39 @@
|
||||
|
||||
//! Subcommand to check the database and sample file dir for errors.
|
||||
|
||||
use bpaf::Bpaf;
|
||||
use db::check;
|
||||
use failure::Error;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
/// Directory holding the SQLite3 index database.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
value_name = "path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(argument("PATH"), fallback_with(crate::default_db_dir))]
|
||||
db_dir: PathBuf,
|
||||
|
||||
/// Compare sample file lengths on disk to the database.
|
||||
#[structopt(long)]
|
||||
/// Compares sample file lengths on disk to the database.
|
||||
compare_lens: bool,
|
||||
|
||||
/// Trash sample files without matching recording rows in the database.
|
||||
/// This addresses "Missing ... row" errors.
|
||||
/// Trashes sample files without matching recording rows in the database.
|
||||
/// This addresses `Missing ... row` errors.
|
||||
///
|
||||
/// The ids are added to the "garbage" table to indicate the files need to
|
||||
/// The ids are added to the `garbage` table to indicate the files need to
|
||||
/// be deleted. Garbage is collected on normal startup.
|
||||
#[structopt(long)]
|
||||
trash_orphan_sample_files: bool,
|
||||
|
||||
/// Delete recording rows in the database without matching sample files.
|
||||
/// This addresses "Recording ... missing file" errors.
|
||||
#[structopt(long)]
|
||||
/// Deletes recording rows in the database without matching sample files.
|
||||
///
|
||||
/// This addresses `Recording ... missing file` errors.
|
||||
delete_orphan_rows: bool,
|
||||
|
||||
/// Trash recordings when their database rows appear corrupt.
|
||||
/// Trashes recordings when their database rows appear corrupt.
|
||||
/// This addresses "bad video_index" errors.
|
||||
///
|
||||
/// The ids are added to the "garbage" table to indicate their files need to
|
||||
/// The ids are added to the `garbage` table to indicate their files need to
|
||||
/// be deleted. Garbage is collected on normal startup.
|
||||
#[structopt(long)]
|
||||
trash_corrupt_rows: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -8,26 +8,23 @@
|
||||
//! configuration will likely be almost entirely done through a web-based UI.
|
||||
|
||||
use base::clock;
|
||||
use bpaf::Bpaf;
|
||||
use cursive::views;
|
||||
use cursive::Cursive;
|
||||
use failure::Error;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use structopt::StructOpt;
|
||||
|
||||
mod cameras;
|
||||
mod dirs;
|
||||
mod users;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
/// Directory holding the SQLite3 index database.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
value_name = "path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(argument("PATH"), fallback_with(crate::default_db_dir))]
|
||||
db_dir: PathBuf,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
// Copyright (C) 2020 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
use bpaf::Bpaf;
|
||||
use failure::Error;
|
||||
use log::info;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
/// Directory holding the SQLite3 index database.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
value_name = "path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(argument("PATH"), fallback_with(crate::default_db_dir))]
|
||||
db_dir: PathBuf,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,51 +5,58 @@
|
||||
//! Subcommand to login a user (without requiring a password).
|
||||
|
||||
use base::clock::{self, Clocks};
|
||||
use bpaf::Bpaf;
|
||||
use db::auth::SessionFlag;
|
||||
use failure::{format_err, Error};
|
||||
use std::io::Write as _;
|
||||
use std::os::unix::fs::OpenOptionsExt as _;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Default, StructOpt)]
|
||||
fn parse_perms(perms: String) -> Result<db::Permissions, protobuf::text_format::ParseError> {
|
||||
protobuf::text_format::parse_from_str(&perms)
|
||||
}
|
||||
|
||||
fn parse_flags(flags: String) -> Result<Vec<SessionFlag>, Error> {
|
||||
flags.split(',').map(SessionFlag::from_str).collect()
|
||||
}
|
||||
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
/// Directory holding the SQLite3 index database.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
value_name = "path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(argument("PATH"), fallback_with(crate::default_db_dir))]
|
||||
db_dir: PathBuf,
|
||||
|
||||
/// Create a session with the given permissions.
|
||||
/// Creates a session with the given permissions.
|
||||
///
|
||||
/// If unspecified, uses user's default permissions.
|
||||
#[structopt(long, value_name="perms",
|
||||
parse(try_from_str = protobuf::text_format::parse_from_str))]
|
||||
#[bpaf(argument::<String>("PERMS"), parse(parse_perms), optional)]
|
||||
permissions: Option<db::Permissions>,
|
||||
|
||||
/// Restrict this cookie to the given domain.
|
||||
#[structopt(long)]
|
||||
/// Restricts this cookie to the given domain.
|
||||
#[bpaf(argument("DOMAIN"))]
|
||||
domain: Option<String>,
|
||||
|
||||
/// Write the cookie to a new curl-compatible cookie-jar file.
|
||||
/// Writes the cookie to a new curl-compatible cookie-jar file.
|
||||
///
|
||||
/// ---domain must be specified. This file can be used later with curl's --cookie flag.
|
||||
#[structopt(long, requires("domain"), value_name = "path")]
|
||||
/// `--domain` must be specified. This file can be used later with curl's `--cookie` flag.
|
||||
#[bpaf(argument("PATH"))]
|
||||
curl_cookie_jar: Option<PathBuf>,
|
||||
|
||||
/// Set the given db::auth::SessionFlags.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "http-only,secure,same-site,same-site-strict",
|
||||
value_name = "flags",
|
||||
use_delimiter = true
|
||||
/// Sets the given db::auth::SessionFlags.
|
||||
///
|
||||
/// default: `http-only,secure,same-site,same-site-strict`.
|
||||
#[bpaf(
|
||||
argument::<String>("FLAGS"),
|
||||
fallback_with(|| Ok::<_, std::convert::Infallible>("http-only,secure,same-site,same-site-strict".to_owned())),
|
||||
parse(parse_flags),
|
||||
)]
|
||||
session_flags: Vec<SessionFlag>,
|
||||
|
||||
/// Create the session for this username.
|
||||
#[bpaf(argument("USERNAME"))]
|
||||
username: String,
|
||||
}
|
||||
|
||||
@@ -87,7 +94,7 @@ pub fn run(args: Args) -> Result<i32, Error> {
|
||||
let d = args
|
||||
.domain
|
||||
.as_ref()
|
||||
.ok_or_else(|| format_err!("--cookiejar requires --domain"))?;
|
||||
.ok_or_else(|| format_err!("--curl-cookie-jar requires --domain"))?;
|
||||
let mut f = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
|
||||
@@ -27,6 +27,9 @@ pub struct ConfigFile {
|
||||
pub binds: Vec<BindConfig>,
|
||||
|
||||
/// Directory holding the SQLite3 index database.
|
||||
///
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[serde(default = "default_db_dir")]
|
||||
pub db_dir: PathBuf,
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::streamer;
|
||||
use crate::web;
|
||||
use crate::web::accept::Listener;
|
||||
use base::clock;
|
||||
use bpaf::Bpaf;
|
||||
use db::{dir, writer};
|
||||
use failure::{bail, Error, ResultExt};
|
||||
use fnv::FnvHashMap;
|
||||
@@ -18,23 +19,24 @@ use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use structopt::StructOpt;
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
|
||||
use self::config::ConfigFile;
|
||||
|
||||
mod config;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
#[structopt(short, long, default_value = "/etc/moonfire-nvr.toml")]
|
||||
/// Path to configuration file.
|
||||
///
|
||||
/// default: `/etc/moonfire-nvr.toml`. See `ref/config.md` for config file documentation.
|
||||
#[bpaf(short, long, argument("PATH"), fallback_with(|| Ok::<_, Error>("/etc/moonfire-nvr.toml".into())))]
|
||||
config: PathBuf,
|
||||
|
||||
/// Open the database in read-only mode and disables recording.
|
||||
/// Opens the database in read-only mode and disables recording.
|
||||
///
|
||||
/// Note this is incompatible with session authentication; consider adding
|
||||
/// a bind with `allow_unauthenticated_permissions` to your config.
|
||||
#[structopt(long)]
|
||||
/// a bind with `allowUnauthenticatedPermissions` to your config.
|
||||
read_only: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,35 +5,31 @@
|
||||
//! Subcommand to run a SQLite shell.
|
||||
|
||||
use super::OpenMode;
|
||||
use bpaf::Bpaf;
|
||||
use failure::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug, PartialEq, Eq)]
|
||||
pub struct Args {
|
||||
/// Directory holding the SQLite3 index database.
|
||||
#[structopt(
|
||||
long,
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
value_name = "path",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(fallback_with(crate::default_db_dir))]
|
||||
db_dir: PathBuf,
|
||||
|
||||
/// Opens the database in read-only mode and locks it only for shared access.
|
||||
///
|
||||
/// This can be run simultaneously with "moonfire-nvr run --read-only".
|
||||
#[structopt(long)]
|
||||
/// This can be run simultaneously with `moonfire-nvr run --read-only`.
|
||||
read_only: bool,
|
||||
|
||||
/// Arguments to pass to sqlite3.
|
||||
///
|
||||
/// Use the -- separator to pass sqlite3 options, as in
|
||||
/// "moonfire-nvr sql -- -line 'select username from user'".
|
||||
#[structopt(parse(from_os_str))]
|
||||
/// Use the `--` separator to pass sqlite3 options, as in
|
||||
/// `moonfire-nvr sql -- -line 'select username from user'`.
|
||||
#[bpaf(positional)]
|
||||
arg: Vec<OsString>,
|
||||
}
|
||||
|
||||
@@ -58,3 +54,32 @@ pub fn run(args: Args) -> Result<i32, Error> {
|
||||
.exec()
|
||||
.into())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use bpaf::Parser;
|
||||
|
||||
#[test]
|
||||
fn parse_args() {
|
||||
let args = args()
|
||||
.to_options()
|
||||
.run_inner(bpaf::Args::from(&[
|
||||
"--db-dir",
|
||||
"/foo/bar",
|
||||
"--",
|
||||
"-line",
|
||||
"select username from user",
|
||||
]))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
Args {
|
||||
db_dir: "/foo/bar".into(),
|
||||
read_only: false, // default
|
||||
arg: vec!["-line".into(), "select username from user".into()],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
// Copyright (C) 2020 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
use bpaf::Bpaf;
|
||||
use failure::Error;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
/// Timestamp(s) to translate.
|
||||
///
|
||||
/// May be either an integer or an RFC-3339-like string:
|
||||
/// `YYYY-mm-dd[THH:MM[:SS[:FFFFF]]][{Z,{+,-,}HH:MM}]`.
|
||||
///
|
||||
/// Eg: `142913484000000`, `2020-04-26`, `2020-04-26T12:00:00:00000-07:00`.
|
||||
#[structopt(required = true)]
|
||||
/// E.g.: `142913484000000`, `2020-04-26`, `2020-04-26T12:00:00:00000-07:00`.
|
||||
#[bpaf(positional("TS"), some("must specify at least one timestamp"))]
|
||||
timestamps: Vec<String>,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,41 +2,36 @@
|
||||
// Copyright (C) 2020 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
use bpaf::Bpaf;
|
||||
/// Upgrades the database schema.
|
||||
///
|
||||
/// See `guide/schema.md` for more information.
|
||||
use failure::Error;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[derive(Bpaf, Debug)]
|
||||
pub struct Args {
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Directory holding the SQLite3 index database.",
|
||||
default_value = "/var/lib/moonfire-nvr/db",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
/// Directory holding the SQLite3 index database.
|
||||
///
|
||||
///
|
||||
/// default: `/var/lib/moonfire-nvr/db`.
|
||||
#[bpaf(argument("PATH"), fallback_with(crate::default_db_dir))]
|
||||
db_dir: std::path::PathBuf,
|
||||
|
||||
#[structopt(
|
||||
help = "When upgrading from schema version 1 to 2, the sample file directory.",
|
||||
long,
|
||||
parse(from_os_str)
|
||||
)]
|
||||
/// When upgrading from schema version 1 to 2, the sample file directory.
|
||||
#[bpaf(argument("PATH"))]
|
||||
sample_file_dir: Option<std::path::PathBuf>,
|
||||
|
||||
#[structopt(
|
||||
help = "Resets the SQLite journal_mode to the specified mode prior to \
|
||||
the upgrade. The default, delete, is recommended. off is very \
|
||||
dangerous but may be desirable in some circumstances. See \
|
||||
guide/schema.md for more information. The journal mode will be \
|
||||
reset to wal after the upgrade.",
|
||||
long,
|
||||
default_value = "delete"
|
||||
)]
|
||||
/// Resets the SQLite journal_mode to the specified mode prior to
|
||||
/// the upgrade.
|
||||
///
|
||||
///
|
||||
/// default: `delete` (recommended). `off` is very dangerous but may be
|
||||
/// desirable in some circumstances. See `guide/schema.md` for more
|
||||
/// information. The journal mode will be reset to `wal` after the upgrade.
|
||||
#[bpaf(argument("MODE"), fallback_with(|| Ok::<_, std::convert::Infallible>("delete".into())))]
|
||||
preset_journal: String,
|
||||
|
||||
#[structopt(help = "Skips the normal post-upgrade vacuum operation.", long)]
|
||||
/// Skips the normal post-upgrade vacuum operation.
|
||||
no_vacuum: bool,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user