Skip to content

Commit

Permalink
Set calling process directly because delta started it
Browse files Browse the repository at this point in the history
This info then takes precedence over whatever
start_determining_calling_process_in_thread() finds or rather
doesn't find.
(The simple yet generous SeqCst is used on purpose for the atomic operations.)
  • Loading branch information
th1000s committed Nov 27, 2024
1 parent 45001d6 commit c23d8e8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
11 changes: 10 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mod subcommands;

mod tests;

use std::ffi::OsString;
use std::ffi::{OsStr, OsString};
use std::io::{self, BufRead, Cursor, ErrorKind, IsTerminal, Write};
use std::process::{self, Command, Stdio};

Expand Down Expand Up @@ -91,6 +91,15 @@ pub fn run_app(
} else if let Call::Help(msg) = call {
OutputType::oneshot_write(msg)?;
return Ok(0);
} else if let Call::SubCommand(_, cmd) = &call {
// Set before creating the Config, which already asks for the calling process
// (not required for Call::DeltaDiff)
utils::process::set_calling_process(
&cmd.args
.iter()
.map(|arg| OsStr::to_string_lossy(arg).to_string())
.collect::<Vec<_>>(),
);
}
let opt = opt.unwrap_or_else(|| delta_unreachable("Opt is set"));

Expand Down
4 changes: 4 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ pub mod round_char_boundary;
pub mod syntect;
pub mod tabs;
pub mod workarounds;

// Use the most (even overly) strict ordering. Atomics are not used in hot loops so
// a one-size-fits-all approach which is never incorrect is okay.
pub const DELTA_ATOMIC_ORDERING: std::sync::atomic::Ordering = std::sync::atomic::Ordering::SeqCst;
31 changes: 29 additions & 2 deletions src/utils/process.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::collections::{HashMap, HashSet};
use std::path::Path;
use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, Condvar, Mutex, MutexGuard};

use lazy_static::lazy_static;
use sysinfo::{Pid, PidExt, Process, ProcessExt, ProcessRefreshKind, SystemExt};

use crate::utils::DELTA_ATOMIC_ORDERING;

pub type DeltaPid = u32;

#[derive(Clone, Debug, PartialEq, Eq)]
Expand All @@ -19,7 +22,13 @@ pub enum CallingProcess {
None, // no matching process could be found
Pending, // calling process is currently being determined
}
// TODO: Git blame is currently handled differently

// The information where the calling process info comes from *should* be inside
// `CallingProcess`, but that is handed out (within a MutexGuard) to callers.
// To keep the interface simple, store it here:
static CALLER_INFO_SOURCE: AtomicUsize = AtomicUsize::new(CALLER_GUESSED);
const CALLER_GUESSED: usize = 1;
const CALLER_KNOWN: usize = 2;

impl CallingProcess {
pub fn paths_in_input_are_relative_to_cwd(&self) -> bool {
Expand Down Expand Up @@ -47,6 +56,8 @@ lazy_static! {
Arc::new((Mutex::new(CallingProcess::Pending), Condvar::new()));
}

// delta was called by this process (or called by something which called delta and it),
// try looking up this information in the process tree.
pub fn start_determining_calling_process_in_thread() {
// The handle is neither kept nor returned nor joined but dropped, so the main
// thread can exit early if it does not need to know its parent process.
Expand All @@ -58,12 +69,28 @@ pub fn start_determining_calling_process_in_thread() {
let (caller_mutex, determine_done) = &**CALLER;

let mut caller = caller_mutex.lock().unwrap();
*caller = calling_process;

if CALLER_INFO_SOURCE.load(DELTA_ATOMIC_ORDERING) <= CALLER_GUESSED {
*caller = calling_process;
}

determine_done.notify_all();
})
.unwrap();
}

// delta starts the process, so it is known.
pub fn set_calling_process(args: &[String]) {
if let ProcessArgs::Args(result) = describe_calling_process(args) {
let (caller_mutex, determine_done) = &**CALLER;

let mut caller = caller_mutex.lock().unwrap();
*caller = result;
CALLER_INFO_SOURCE.store(CALLER_KNOWN, DELTA_ATOMIC_ORDERING);
determine_done.notify_all();
}
}

#[cfg(not(test))]
pub fn calling_process() -> MutexGuard<'static, CallingProcess> {
let (caller_mutex, determine_done) = &**CALLER;
Expand Down

0 comments on commit c23d8e8

Please sign in to comment.