Skip to content

Commit

Permalink
feat(rsjudge-utils): ✨ add generic error logging support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jisu-Woniu committed Apr 4, 2024
1 parent 7ff8399 commit 27c6d80
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 14 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"rsjudge-judger",
"rsjudge-rest",
"rsjudge-runner",
"rsjudge-utils",
"xtask"
],
"editor.defaultFormatter": "dprint.dprint",
Expand Down
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions crates/rsjudge-runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{os::unix::process::CommandExt as _, process::Command};

use caps::Capability;
use nix::unistd::{setgroups, Gid};
use rsjudge_utils::log_if_error;
use uzers::User;

pub use crate::{
Expand All @@ -26,11 +27,11 @@ pub trait RunAs {
impl RunAs for Command {
type Error = Error;
fn run_as(&mut self, user: &User) -> Result<&mut Self> {
require_caps([
log_if_error!(require_caps([
Capability::CAP_SETUID,
Capability::CAP_SETGID,
Capability::CAP_DAC_READ_SEARCH,
])?;
]))?;

let uid = user.uid();
let gid = user.primary_group_id();
Expand All @@ -49,12 +50,11 @@ impl RunAs for Command {
.into_iter()
.map(|g| Gid::from_raw(g.gid()))
.collect();
unsafe {
self.pre_exec(move || {
setgroups(&groups)?;
Ok(())
})
let set_groups = move || {
log_if_error!(setgroups(&groups))?;
Ok(())
};
unsafe { self.pre_exec(set_groups) };
}

#[cfg(setgroups)]
Expand Down
2 changes: 2 additions & 0 deletions crates/rsjudge-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ rust-version.workspace = true

[dependencies]
anyhow = "1.0.81"
log.workspace = true
shell-words = "1.1.0"
35 changes: 29 additions & 6 deletions crates/rsjudge-utils/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
use std::{
io::ErrorKind,
iter,
process::{Command, Output},
};

use anyhow::{bail, ensure};

/// Display a command in a human-readable format, suitable for error messages.
///
/// # Examples
///
/// ```
/// use std::process::Command;
/// use rsjudge_utils::command::display_cmd;
///
/// let mut cmd = Command::new("echo");
/// cmd.arg("Hello, world!");
/// assert_eq!(display_cmd(&cmd), "\"echo\" \"Hello, world!\"");
/// ```
pub fn display_cmd(cmd: &Command) -> String {
let mut s = format!("{:?}", cmd.get_program().to_string_lossy());
s.extend(
cmd.get_args()
.map(|arg| format!(" {:?}", arg.to_string_lossy())),
);
s
let args = iter::once(cmd.get_program())
.chain(cmd.get_args())
.map(|arg| arg.to_string_lossy());

shell_words::join(args)
}

/// Run a command, returning the output if succeeded, with some error handling.
///
/// # Examples
///
/// ```no_run
/// use std::process::Command;
/// use rsjudge_utils::command::check_output;
///
/// let mut cmd = Command::new("echo");
/// cmd.arg("Hello, world!");
/// let output = check_output(&mut cmd).unwrap();
/// assert_eq!(output.stdout, b"Hello, world!\n");
/// ```
pub fn check_output(cmd: &mut Command) -> anyhow::Result<Output> {
let output = match cmd.output() {
Ok(o) => o,
Expand Down
25 changes: 25 additions & 0 deletions crates/rsjudge-utils/src/error_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Macro for logging when error occurs.
/// Log an error message and return an `Err` variant of `Result`.
///
/// This macro is transparent and does not affect the return value.
/// You may still want to use `?` to propagate the error to the caller.
///
/// # Examples
///
/// ```
/// use anyhow::{anyhow, Result};
/// use rsjudge_utils::log_if_error;
///
/// let result: Result<()> = Err(anyhow!("An error"));
/// log_if_error!(result);
/// ```
#[macro_export]
macro_rules! log_if_error {
($expr: expr) => {
$expr.map_err(|err| {
::log::error!("{}", err);
err
})
};
}
4 changes: 3 additions & 1 deletion crates/rsjudge-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#![warn(missing_docs)]

/// Functions for trimming ASCII whitespace from `[u8]` and `str`.
#[macro_use]
mod error_macros;

pub mod trim;

/// Functions for working with `std::process::Command`.
Expand Down
2 changes: 2 additions & 0 deletions crates/rsjudge-utils/src/trim.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Functions for trimming ASCII whitespace from `[u8]` and `str`.
/// Returns a byte slice with leading ASCII whitespace bytes removed.
///
/// 'Whitespace' refers to the definition used by
Expand Down

0 comments on commit 27c6d80

Please sign in to comment.