equal
deleted
inserted
replaced
1 use cpython::exc::ValueError; |
1 use cpython::exc::{KeyboardInterrupt, ValueError}; |
2 use cpython::{ |
2 use cpython::{ |
3 ObjectProtocol, PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, |
3 ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, |
4 Python, ToPyObject, |
4 PyTuple, Python, ToPyObject, |
5 }; |
5 }; |
6 use hg::config::Config; |
6 use hg::config::Config; |
7 use hg::errors::HgError; |
7 use hg::errors::HgError; |
8 use hg::repo::{Repo, RepoError}; |
8 use hg::repo::{Repo, RepoError}; |
9 use hg::revlog::Node; |
9 use hg::revlog::Node; |
47 .unwrap(); |
47 .unwrap(); |
48 PyErr::from_instance( |
48 PyErr::from_instance( |
49 py, |
49 py, |
50 cls.call(py, (msg,), None).ok().into_py_object(py), |
50 cls.call(py, (msg,), None).ok().into_py_object(py), |
51 ) |
51 ) |
|
52 } |
|
53 HgError::InterruptReceived => { |
|
54 PyErr::new::<KeyboardInterrupt, _>(py, "") |
52 } |
55 } |
53 e => PyErr::new::<cpython::exc::RuntimeError, _>(py, e.to_string()), |
56 e => PyErr::new::<cpython::exc::RuntimeError, _>(py, e.to_string()), |
54 }) |
57 }) |
55 } |
58 } |
56 |
59 |
102 format!("{}-byte hash required", NODE_BYTES_LENGTH), |
105 format!("{}-byte hash required", NODE_BYTES_LENGTH), |
103 ) |
106 ) |
104 }) |
107 }) |
105 .map(Into::into) |
108 .map(Into::into) |
106 } |
109 } |
|
110 |
|
111 /// Wrap a call to `func` so that Python's `SIGINT` handler is first stored, |
|
112 /// then restored after the call to `func` and finally raised if |
|
113 /// `func` returns a [`HgError::InterruptReceived`] |
|
114 pub fn with_sigint_wrapper<R>( |
|
115 py: Python, |
|
116 func: impl Fn() -> Result<R, HgError>, |
|
117 ) -> PyResult<Result<R, HgError>> { |
|
118 let signal_py_mod = py.import("signal")?; |
|
119 let sigint_py_const = signal_py_mod.get(py, "SIGINT")?; |
|
120 let old_handler = signal_py_mod.call( |
|
121 py, |
|
122 "getsignal", |
|
123 PyTuple::new(py, &[sigint_py_const.clone_ref(py)]), |
|
124 None, |
|
125 )?; |
|
126 let res = func(); |
|
127 // Reset the old signal handler in Python because we've may have changed it |
|
128 signal_py_mod.call( |
|
129 py, |
|
130 "signal", |
|
131 PyTuple::new(py, &[sigint_py_const.clone_ref(py), old_handler]), |
|
132 None, |
|
133 )?; |
|
134 if let Err(HgError::InterruptReceived) = res { |
|
135 // Trigger the signal in Python |
|
136 signal_py_mod.call( |
|
137 py, |
|
138 "raise_signal", |
|
139 PyTuple::new(py, &[sigint_py_const]), |
|
140 None, |
|
141 )?; |
|
142 } |
|
143 Ok(res) |
|
144 } |