annotate rust/chg/src/procutil.rs @ 48981:f3aafd785e65

filemerge: add support for partial conflict resolution by external tool A common class of merge conflicts is in imports/#includes/etc. It's relatively easy to write a tool that can resolve these conflicts, perhaps by naively just unioning the statements and leaving any cleanup to other tools to do later [1]. Such specialized tools cannot generally resolve all conflicts in a file, of course. Let's therefore call them "partial merge tools". Note that the internal simplemerge algorithm is such a partial merge tool - one that only resolves trivial "conflicts" where one side is unchanged or both sides change in the same way. One can also imagine having smarter language-aware partial tools that merge the AST. It may be useful for such tools to interactively let the user resolve any conflicts it can't resolve itself. However, having the option of implementing it as a partial merge tool means that the developer doesn't *need* to create a UI for it. Instead, the user can resolve any remaining conflicts with their regular merge tool (e.g. `:merge3` or `meld). We don't currently have a way to let the user define such partial merge tools. That's what this patch addresses. It lets the user configure partial merge tools to run. Each tool can be configured to run only on files matching certain patterns (e.g. "*.py"). The tool takes three inputs (local, base, other) and resolves conflicts by updating these in place. For example, let's say the inputs are these: base: ``` import sys def main(): print('Hello') ``` local: ``` import os import sys def main(): print('Hi') ``` other: ``` import re import sys def main(): print('Howdy') ``` A partial merge tool could now resolve the conflicting imports by replacing the import statements in *all* files by the following snippet, while leaving the remainder of the files unchanged. ``` import os import re import sys ``` As a result, simplemerge and any regular merge tool that runs after the partial merge tool(s) will consider the imports to be non-conflicting and will only present the conflict in `main()` to the user. Differential Revision: https://phab.mercurial-scm.org/D12356
author Martin von Zweigbergk <martinvonz@google.com>
date Tue, 18 Jan 2022 13:05:21 -0800
parents 426294d06ddc
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
39970
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
2 //
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
3 // This software may be used and distributed according to the terms of the
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
4 // GNU General Public License version 2 or any later version.
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
5
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
6 //! Low-level utility for signal and process handling.
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
7
40120
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
8 use libc::{self, c_int, pid_t, size_t, ssize_t};
39970
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
9 use std::io;
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
10 use std::os::unix::io::RawFd;
40120
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
11 use std::sync;
39970
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
12
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
13 #[link(name = "procutil", kind = "static")]
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
14 extern "C" {
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
15 // sendfds.c
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
16 fn sendfds(sockfd: c_int, fds: *const c_int, fdlen: size_t) -> ssize_t;
40120
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
17
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
18 // sighandlers.c
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
19 fn setupsignalhandler(pid: pid_t, pgid: pid_t) -> c_int;
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
20 fn restoresignalhandler() -> c_int;
39970
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
21 }
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
22
39976
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents: 39973
diff changeset
23 /// Returns the effective uid of the current process.
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents: 39973
diff changeset
24 pub fn get_effective_uid() -> u32 {
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents: 39973
diff changeset
25 unsafe { libc::geteuid() }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents: 39973
diff changeset
26 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents: 39973
diff changeset
27
44683
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
28 /// Returns the umask of the current process.
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
29 ///
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
30 /// # Safety
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
31 ///
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
32 /// This is unsafe because the umask value is temporarily changed, and
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
33 /// the change can be observed from the other threads. Don't call this in
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
34 /// multi-threaded context.
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
35 pub unsafe fn get_umask() -> u32 {
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
36 let mask = libc::umask(0);
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
37 libc::umask(mask);
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
38 mask
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
39 }
065048e66f32 rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents: 43818
diff changeset
40
39973
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
41 /// Changes the given fd to blocking mode.
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
42 pub fn set_blocking_fd(fd: RawFd) -> io::Result<()> {
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
43 let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
44 if flags < 0 {
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
45 return Err(io::Error::last_os_error());
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
46 }
45620
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
47 let r =
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
48 unsafe { libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK) };
39973
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
49 if r < 0 {
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40120
diff changeset
50 return Err(io::Error::last_os_error());
39973
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
51 }
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
52 Ok(())
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
53 }
ba447b83cd56 rust-chg: add low-level function to set pager fd blocking
Yuya Nishihara <yuya@tcha.org>
parents: 39970
diff changeset
54
39970
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
55 /// Sends file descriptors via the given socket.
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
56 pub fn send_raw_fds(sock_fd: RawFd, fds: &[RawFd]) -> io::Result<()> {
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
57 let r = unsafe { sendfds(sock_fd, fds.as_ptr(), fds.len() as size_t) };
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
58 if r < 0 {
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
59 return Err(io::Error::last_os_error());
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
60 }
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
61 Ok(())
a8be2cff613f rust-chg: add wrapper around C function
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
62 }
40120
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
63
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
64 static SETUP_SIGNAL_HANDLER: sync::Once = sync::Once::new();
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
65 static RESTORE_SIGNAL_HANDLER: sync::Once = sync::Once::new();
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
66
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
67 /// Installs signal handlers to forward signals to the server.
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
68 ///
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
69 /// # Safety
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
70 ///
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
71 /// This touches global states, and thus synchronized as a one-time
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
72 /// initialization function.
45620
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
73 pub fn setup_signal_handler_once(
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
74 pid: u32,
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
75 pgid: Option<u32>,
426294d06ddc rust: move rustfmt.toml to repo root so it can be used by `hg fix`
Martin von Zweigbergk <martinvonz@google.com>
parents: 44683
diff changeset
76 ) -> io::Result<()> {
40120
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
77 let pid_signed = pid as i32;
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
78 let pgid_signed = pgid.map(|n| n as i32).unwrap_or(0);
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
79 let mut r = 0;
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
80 SETUP_SIGNAL_HANDLER.call_once(|| {
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
81 r = unsafe { setupsignalhandler(pid_signed, pgid_signed) };
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
82 });
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
83 if r < 0 {
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
84 return Err(io::Error::last_os_error());
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
85 }
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
86 Ok(())
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
87 }
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
88
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
89 /// Restores the original signal handlers.
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
90 ///
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
91 /// # Safety
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
92 ///
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
93 /// This touches global states, and thus synchronized as a one-time
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
94 /// initialization function.
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
95 pub fn restore_signal_handler_once() -> io::Result<()> {
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
96 let mut r = 0;
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
97 RESTORE_SIGNAL_HANDLER.call_once(|| {
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
98 r = unsafe { restoresignalhandler() };
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
99 });
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
100 if r < 0 {
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
101 return Err(io::Error::last_os_error());
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
102 }
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
103 Ok(())
89742f1fa6cb rust-chg: install signal handlers to forward signals to server
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
104 }