Commit Graph

37 Commits

Author SHA1 Message Date
Meyer Jacobs
b9f3c9c692 taggederror: Introduce taggederror-util for more ergonomic error tagging for eden error types.
Summary:
Introduce taggederror-util, which provides a new trait `AnyhowEdenExt`, which provides a method `eden_metadata` for anyhow errors and results. This method works much like `AnyhowExt::common_metadata`, but additionally supports extracting default error metadata from known `Tagged` types which are listed explicitly in the method implementation.

Extend `FilteredAnyhow` to support a configuration "metadata function", which allows swapping out `eden_metadata` for the standard `common_metadata`.

Modify Rust dispatch and Python bindings to use `AnyhowEdenExt` for metadata extraction and printing.

Modify `intentional_error` to rely on `AnyhowEdenExt` for tagging (removes `.tagged` call, no tags will be visible if `AnyhowEdenExt` is not used).

Reviewed By: DurhamG

Differential Revision: D22927203

fbshipit-source-id: 04b36fdfaa24af591118acb9e418d1ed7ae33f91
2020-08-06 19:37:25 -07:00
Jun Wu
78c05bb5e6 cpython-ext: extract io::Error translation to a function
Summary: This will be used later.

Reviewed By: sfilipco

Differential Revision: D22883863

fbshipit-source-id: 4f7ed4eb51d403f96e9d1aa1792062b4c55e3398
2020-08-06 12:31:57 -07:00
Meyer Jacobs
e3b86cf77d debug: introduce binding layer for propagating error metadata to Python
Summary:
Implements based Rust-Python binding layer for error metadata propagation.

We introduce a new type, `TaggedExceptionData`, which carries CommonMetadata and the original (without metadata) error message for a Rust Anyhow error. This class is passed to RustError and can be accessed in Python (somewhat awkwardly) via indexing:
```
except error.RustError as e:
    fault = e.args[0].fault()
    typename = e.args[0].typename()
    message = e.args[0].message()
```
As far as I can tell, due to limitations in cpython-rs, this can't be made more ergonomic without introducing a Python shim around the Rust binding layer, which could adapt the cpython-rs classes to use whatever API we'd like.

Currently, anyhow errors that are not otherwise special-cased will be converted into RustError, with both the original error message and any attached metadata printed as shown below
```
  abort: intentional error for debugging with message 'intentional_error'
  error has type name taggederror::IntentionalError and fault None
```
We can of course re-raise the error if desired to maintain the previous behavior for handling a RustError.

If we'd like other, specialized Rust Python Exception types to carry metadata (such as `IndexedLogError`), we'll need to modify them to accept a `TaggedExceptionData` like `RustError`.

Renamed the "cause an error in pure rust command" function to `debugcauserusterror`, and instead used the name `debugthrowrustexception` for a command which causes an error in rust which is converted to a Python exception across the binding layer.

Introduced a simple integration test which exercises `debugthrowrustexception`.

Added a basic handler for RustError to scmutil.py

Reviewed By: DurhamG

Differential Revision: D22517796

fbshipit-source-id: 0409489243fe739a26958aad48f608890eb93aa0
2020-07-16 19:30:00 -07:00
Arun Kulshreshtha
14a7fe636f cpython-ext: Add ExtractInnerRef trait
Summary: Per comments on D22429347, add a new `ExtractInnerRef` trait that is similar to `ExtractInner`, but returns a reference to the underlying value. A default implementation is provided for types whose inner value is `Clone + 'static`, so in practice most types will only need to implement `ExtractInnerRef`, whereas the callsite may choose whether it needs a reference or an owned value.

Reviewed By: quark-zju

Differential Revision: D22464158

fbshipit-source-id: 7b97329aedcddb0e51fd242b519e79eba2eed350
2020-07-09 19:05:55 -07:00
Arun Kulshreshtha
7ae097e8da cpython-ext: add ExtractInner trait
Summary:
A common pattern in Mercurial's data storage layer Python bindings is to have a Python object that wraps a Rust object. These Python objects are often passed across the FFI boundary to Rust code, which then may need to access the underlying Rust value.

Previously, the objects that used this pattern did so in an ad-hoc manner, typically by providing an `into_inner` or `to_inner` inherent method. This diff introduces a new `ExtractInner` trait that standardizes this pattern into a single interface, which in turn allows this pattern to be used with generics.

Reviewed By: quark-zju

Differential Revision: D22429347

fbshipit-source-id: cab4c24b8b98c6ef8307f72a9b4726aabdc829cc
2020-07-09 19:05:55 -07:00
Carolyn Busch
89f238b8dd Replace whitelist/blacklist term
Summary: Replaces usages of whitelist/blacklist with include/exclude/allow. These terms are more descriptive and less likely to contribute to racial stereotyping. More context: https://fb.workplace.com/groups/sourcecontrolteam/permalink/2926049127516414/

Reviewed By: farnz

Differential Revision: D22039299

fbshipit-source-id: d5b4cdeca681e1f4c992f7ef0b9f772b2ae1abd3
2020-06-15 15:01:19 -07:00
Carolyn Busch
4eeab3b81b Update cpython to 0.5
Summary:
D21270958 updated the cpython, python27-sys, and python3-sys crates to 0.5. Update
the Mercurial cargo dependencies to match.

Reviewed By: xavierd

Differential Revision: D21281875

fbshipit-source-id: ccad68749a25d11240351b5faeef27cb9c693456
2020-04-28 11:47:41 -07:00
Jun Wu
0b5a4ae2c3 cpython-ext: infer errno from io::ErrorKind
Summary:
Sometimes the Rust io::Error is generated without an errno (ex. pipe
0.2 would generate BrokenPipe error without an errno). The Python
land uses errno to check error type (Python does not have io::ErrorKind).

Therefore attempt to translate ErrorKind to Python errno. Without this
exiting the rust pager early would crash like:

  StdioError: [Errno None] pipe reader has been dropped
  abort: pipe reader has been dropped

Reviewed By: markbt

Differential Revision: D20898559

fbshipit-source-id: ef863617e0e500d878ea0f9aeac06b4d87ffbcf2
2020-04-08 13:13:08 -07:00
Xavier Deguillard
767134797c pyerror: stringify Rust errors with "{:?}"
Summary:
According to the anyhow documentation[0], the behavior of `.to_string()` is to
only stringify the top-level errors, hiding all the context of the error.
Instead, the debug format allows all the context to be displayed, and, if
available the backtrace.

This should significantly help debug Rust errors when context is available,
which we should strive to have everywhere!

[0]: https://docs.rs/anyhow/1.0.27/anyhow/struct.Error.html#display-representations

Reviewed By: sfilipco

Differential Revision: D20575944

fbshipit-source-id: 2968d7fb755edec7f7e5151138e8049ded181c1b
2020-03-20 20:22:14 -07:00
Jun Wu
ad8190713b cpython-ext: serialize Rust str into Python str type
Summary:
Previously Rust str was serialized into bytes. To be Python 3 friendly, let's
serialize it into `str`.

Reviewed By: markbt

Differential Revision: D19797706

fbshipit-source-id: 388eb044dc7e25cdc438f0c3d6fa5a5740f22e3d
2020-03-12 12:19:38 -07:00
Jun Wu
7316c4cc22 cpython-ext: add a way to wrap Rust Write object into a Python object
Summary:
The library already has a way to wrap a Python object into a Rust object that
exposes the Rust Read/Write interface. This is the reverse direction for
the Write interface.

The initial intention is to expose Rust stdout as described in D19702533.
However, I found Python's `sys.stdout.buffer` also enforces utf-8 encoding
on Windows (unless PYTHONLEGACYWINDOWSSTDIO is set). So Python's
stdout actually behaves similarly with Rust's stdout on Windows and is okay
to use. That said, it's still useful to have this abstraction, for streampager [1]
integration.

[1]: https://github.com/markbt/streampager/

Reviewed By: sfilipco

Differential Revision: D19716127

fbshipit-source-id: ba39898122561d9a49b7080ee95d7c940540eb40
2020-02-04 18:41:13 -08:00
Mark Thomas
914607cac7 cpython-ext: add PyPath for references to paths
Summary: `PyPath` is to `PyPathBuf` as `Path` is to `PathBuf` and `str` is to `String`.

Reviewed By: quark-zju

Differential Revision: D19647995

fbshipit-source-id: 841a5f6fea295bc72b00da028ae256ca38578504
2020-01-30 17:33:35 -08:00
Mark Thomas
13b7a759a2 cpython-ext: add PyNone, a marker struct for functions that can only return None
Summary: Add `PyNone`.  This is a marker struct that indicates that a python function can only return `PyNone`.

Reviewed By: xavierd

Differential Revision: D19644338

fbshipit-source-id: f846b146237ebf7de996177494934fec662cde0f
2020-01-30 12:28:38 -08:00
Mark Thomas
6b8042662a cpython_ext: rename PyPath to PyPathBuf
Summary:
`PyPath` is the type that owns the data.  Rename it to `PyPathBuf` for analogy
with `PathBuf` and `RepoPathBuf`, and to allow us to introduce a reference type
named `PyPath`.

Reviewed By: xavierd

Differential Revision: D19643797

fbshipit-source-id: 56d80fea5677f7223e967b0723039d1763b26f68
2020-01-30 11:06:24 -08:00
Jun Wu
c5dd6829c7 cpython-ext: add more utilities for PyPath
Summary:
Make the type easier to use. Namely, the treestate bindings want PyPath <->
bytes since treestate internally uses bytes.

Reviewed By: xavierd

Differential Revision: D19635357

fbshipit-source-id: 37d1889b5da1d7f3869bb7820de0219b87b71a8b
2020-01-30 08:27:33 -08:00
Mark Thomas
1e63f205f4 rust-cpython: allow compilation for both py2 and py3
Summary:
Set up the `cpython-ext` and `hgcommands` libraries so that they can compile
against py2 and py3 versions of rust-cpython.  Make py2 the default so
that cargo test still works.

Reviewed By: singhsrb

Differential Revision: D19615656

fbshipit-source-id: 3403e7077deb3c0a9dfe0e3b7d4f4ad1da73bba3
2020-01-28 20:17:20 -08:00
Jun Wu
ed3a2b2247 cpython-ext: add missed types dep
Summary: This is incorrectly removed due to a bad rebase / merge.

Reviewed By: DurhamG

Differential Revision: D19607801

fbshipit-source-id: a6ee7a3f184ff1882eb1f1513f7fed74a7108727
2020-01-28 13:50:14 -08:00
Jun Wu
8703970cea py3: update Cargo.toml to make py3 buildable
Summary:
This makes `make hg3` work. It requires cleaning up the `build` directory when
switching between py2 and py3 build, which will be fixed later.

Reviewed By: DurhamG

Differential Revision: D19604824

fbshipit-source-id: 060ff313420126a5dba935c4451b45dc9af45f13
2020-01-28 13:39:38 -08:00
Xavier Deguillard
d087e39a34 pypathmatcher: use PyPath instead of PyByte
Reviewed By: DurhamG

Differential Revision: D19592136

fbshipit-source-id: 5db6ca629cd920d52ffbf7f10963c44c8f7b203d
2020-01-28 12:40:48 -08:00
Adam Simpkins
beff6fdea7 py3: add additional from() conversion methods for Str
Summary: Add methods to convert to a `Str` object from `String` and from `Vec[u8]`

Reviewed By: xavierd

Differential Revision: D19596743

fbshipit-source-id: 6499f7f1b8329f4d14ce8179a41ed46982a85c8e
2020-01-28 12:25:39 -08:00
Mark Thomas
4fe02f3607 bindings: update to rust-cpython 0.4
Summary: Update to the new version of rust-cpython.  This supports `list.append`, so make use of it.

Reviewed By: xavierd

Differential Revision: D19590905

fbshipit-source-id: 03609d4f698ae8e4380e82b8144caaa205b4c2d4
2020-01-28 10:46:33 -08:00
Stefan Filip
5720b9a2a1 py3/pymanifest: convert path types from PyBytes to PyPath
Reviewed By: xavierd

Differential Revision: D19594134

fbshipit-source-id: e8532a125aa2ed4b7740e669ad572fcbb327692f
2020-01-28 10:29:11 -08:00
Jun Wu
373073df47 py3/rust: cpython-ext: optionally show Python error traceback
Summary:
This is optional, but it helps investigating Python errors chained with other
Rust errors.

For example:

  error.RustError: failed fetching from store (, cc38739855a7f356b4a2aaac0a0a858fd646e6bf)
  Caused by:
    TypeError()
    Traceback (most recent call last):
      File "scm3/edenscm/hgext/remotefilelog/contentstore.py", line 53, in get
        chain = self.getdeltachain(name, node)
      File "scm3/edenscm/hgext/remotefilelog/contentstore.py", line 91, in getdeltachain
        chain = self._getpartialchain(name, node)
      File "scm3/edenscm/hgext/remotefilelog/contentstore.py", line 125, in _getpartialchain
        return store.getdeltachain(name, node)
    TypeError

Without this diff there is only "TypeError()" without the traceback.
This can be turned off by unsetting RUST_BACKTRACE.

Reviewed By: markbt

Differential Revision: D19581173

fbshipit-source-id: 74605b78146b6b1c9ddd5ad720dcd19ff73908a8
2020-01-27 18:56:10 -08:00
Xavier Deguillard
24ae9f9592 cpython-ext: fix python3 compile error
Summary: The format_err is used in shared code too, we need to import it.

Reviewed By: quark-zju

Differential Revision: D19592591

fbshipit-source-id: bd344bf3c295473f4647235a98432d11c9678bf9
2020-01-27 16:58:42 -08:00
Xavier Deguillard
33ea1763ce cpython-ext: add a PyPath type
Summary:
This will be used as an argument to the Rust bindings when using paths. This
type is either a PyBytes in Python2 and uses the various encoding function to
convert into a String, or a PyUnicode in Python3 with no encoding change.

Reviewed By: farnz

Differential Revision: D19587890

fbshipit-source-id: 58903426585693193754691fe3c756b9097b35f6
2020-01-27 16:50:14 -08:00
Xavier Deguillard
e512c370fd py3/rust: cpython-ext: set ob_size on raw PyObject
Summary:
Without this, Rust code using the feature (ex. lz4, used by lz4revlog) will
panic.

Reviewed By: sfilipco

Differential Revision: D19581188

fbshipit-source-id: b499449df4fede27fe66cf8e5af57e8347a0dd48
2020-01-27 16:50:14 -08:00
Xavier Deguillard
f16bb04977 py3/rust: cpython-ext: support memoryview as PySimpleBuf
Summary: Otherwise we got RustPanic when clindex or dagindex reads mmapped changelog.i.

Reviewed By: sfilipco

Differential Revision: D19581189

fbshipit-source-id: 3ee74a1bd000d58272551ae404dcfe7f957bb2c0
2020-01-27 16:50:13 -08:00
Xavier Deguillard
1c697dbc49 py3/rust: cpython-ext: add Str type
Summary: This converts to bytes on Python 2, but unicode on Python 3.

Reviewed By: markbt

Differential Revision: D19581180

fbshipit-source-id: 0de9056a01ae30810a72352387de5a940b37d7ab
2020-01-27 16:50:13 -08:00
Jun Wu
c624847c84 hgtime: limit year in 1900 to 9999
Summary:
The Python `datatime` stdlib has limitations:

- `datetime.datetime` can only express year 1 to 9999.
- `strptime` requires year >= 1900.

Limit the `HgTime` to 1900 ..= 9999 range to be consistent.

Note: Mercurial has an `i32` range limit, which seems to problematic
since `i32::MAX` is Jan 19, 2038. So I kept using `i64`.

This addressed some XXX comments about not returning errors.

The code change is mostly because added error handling.

Reviewed By: sfilipco

Differential Revision: D18946333

fbshipit-source-id: 0e4756457b0f13451dc5008ef19d4670a7aaa7fb
2019-12-22 11:27:32 -08:00
Jun Wu
fbdecc96bb cpython-ext: move foreign error handling to pyerror
Summary:
Make cpython-ext free from business logic. This adds a bit overhead.
But it should be fine given the error cases are considered rare.

Reviewed By: markbt

Differential Revision: D19186692

fbshipit-source-id: daaffc1369a36c781d1badea822bf62a144eb54e
2019-12-22 11:27:29 -08:00
Jun Wu
d4a19306ed cpython-ext: rename fallible to anyhow_result
Summary: We no longer use the `failure` crate. Rename related methods and traits.

Reviewed By: markbt

Differential Revision: D19186694

fbshipit-source-id: 1c83a90ee12db431b7d8e09a9c2cf1d43a4c0f93
2019-12-22 11:27:29 -08:00
Jun Wu
ef3f9b932d cpython-ext: rename mod failure to error
Summary:
We no longer use the `failure` crate. Rename the module.

`cpython-failure` is dropped since it was merged into `cpython-ext`.

Reviewed By: markbt

Differential Revision: D19186693

fbshipit-source-id: 410d1491bcadd8d3272c7e2df08ecbe66fc0fef2
2019-12-22 11:27:29 -08:00
Jun Wu
2824ac99f7 cpython-ext: drop PE type parameter from map_pyerr<PE>
Summary:
The `map_pyerr<PE>` API is kind of hard to use correctly since the
code that calls `map_pyerr` does not really know the best suitable error type.

The existing code also "encourage"s the use of stdlib error types like
RuntimeError, ValueError, etc since the code is shorter, which is not great.
Error types from `mercurial.error` are better choices.

With previous diffs in this stack, we now decide the Python error type based
on the Rust error type. It's no longer necessary to specify an error type
with `map_pyerr<PE>`. So let's just drop the type parameter.

A `RustError` was added for error types that `cpython-ext` does not know how
to convert. We should avoid leaking it to the Python land by just implementing
how to convert `anyhow::Error` to `PyErr` in `cpython-ext`.

Reviewed By: markbt

Differential Revision: D19169527

fbshipit-source-id: f4563c36174cd51201b526bbc92a3f1c8a3da864
2019-12-22 11:27:28 -08:00
Jun Wu
d6b2eb80a7 cpython-ext: convert known error types to dedicated errors directly
Summary:
Convert indexedlog error and IOError to dedicated Python types so the Python
world can match them meaningfully by type and handle them accordingly.

Reviewed By: markbt

Differential Revision: D19169210

fbshipit-source-id: 1e7bfdf7cbaf917098efdcd63d600483a9427d33
2019-12-22 11:27:27 -08:00
David Tolnay
d1d8fb939a Switch from failure::Fail trait to std::error::Error for errors
Summary:
This diff replaces eden's dependencies on failure::Error with anyhow::Error.

Failure's error type requires all errors to have an implementation of failure's own failure::Fail trait in order for cause chains and backtraces to work. The necessary methods for this functionality have made their way into the standard library error trait, so modern error libraries build directly on std::error::Error rather than something like failure::Fail. Once we are no longer tied to failure 0.1's Fail trait, different parts of the codebase will be free to use any std::error::Error-based libraries they like while still working nicely together.

Reviewed By: xavierd

Differential Revision: D18576093

fbshipit-source-id: e2d862b659450f2969520d9b74877913fabb2e5d
2019-11-22 08:53:31 -08:00
David Tolnay
b1793a4416 rust: Rename Fallible<T> to Result<T>
Summary:
This diff is preparation for migrating off of failure::Fail / failure::Error for errors in favor of errors that implement std::error::Error. The Fallible terminology is unique to failure and in non-failure code we should be using Result<T>. To minimize the size of the eventual diff that removes failure, this codemod replaces all use of Fallible with Result by:

- In modules that do not use Result<T, E>, we import `failure::Fallible as Result`;
- In modules that use a mix of Result<T, E> and Fallible<T> (only 5) we define `type Result<T, E = failure::Error> = std::result::Result<T, E>` to allow both Result<T> and Result<T, E> to work simultaneously.

Reviewed By: Imxset21

Differential Revision: D18499758

fbshipit-source-id: 9f5a54c47f81fdeedbc6003cef42a1194eee55bf
2019-11-14 14:11:01 -08:00
Adam Simpkins
ab3a7cb21f Move fb-mercurial sources into an eden/scm subdirectory.
Summary:
In preparation for merging fb-mercurial sources to the Eden repository,
move everything from the top-level directory into an `eden/scm`
subdirectory.
2019-11-13 16:04:48 -08:00