Mercurial > hg
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 |
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 } |