changeset 42609:326fdce22fb2

rust: switch hg-core and hg-cpython to rust 2018 edition Many interesting changes have happened in Rust since the Oxidation Plan was introduced, like the 2018 edition and procedural macros: - Opting in to the 2018 edition is a clear benefit in terms of future proofing, new (nice to have) syntactical sugar notwithstanding. It also has a new non-lexical, non-AST based borrow checker that has fewer bugs(!) and allows us to write correct code that in some cases would have been rejected by the old one. - Procedural macros allow us to use the PyO3 crate which maintainers have expressed the clear goal of compiling on stable, which would help in code maintainability compared to rust-cpython. In this patch are the following changes: - Removing most `extern crate` uses - Updating `use` clauses (`crate` keyword, nested `use`) - Removing `mod.rs` in favor of an aptly named module file Like discussed in the mailing list ( https://www.mercurial-scm.org/pipermail/mercurial-devel/2019-July/132316.html ), until Rust integration in Mercurial is considered to be out of the experimental phase, the maximum version of Rust allowed is whatever the latest version Debian packages. Differential Revision: https://phab.mercurial-scm.org/D6597
author Raphaël Gomès <rgomes@octobus.net>
date Tue, 02 Jul 2019 17:15:03 +0200
parents 717686c5e461
children 5672bb73f61e
files rust/hg-core/Cargo.toml rust/hg-core/src/dirstate.rs rust/hg-core/src/dirstate/dirs_multiset.rs rust/hg-core/src/dirstate/mod.rs rust/hg-core/src/dirstate/parsers.rs rust/hg-core/src/filepatterns.rs rust/hg-core/src/lib.rs rust/hg-core/src/utils.rs rust/hg-core/src/utils/mod.rs rust/hg-core/tests/test_missing_ancestors.rs rust/hg-cpython/Cargo.toml rust/hg-cpython/src/ancestors.rs rust/hg-cpython/src/cindex.rs rust/hg-cpython/src/dagops.rs rust/hg-cpython/src/dirstate.rs rust/hg-cpython/src/discovery.rs rust/hg-cpython/src/exceptions.rs rust/hg-cpython/src/filepatterns.rs rust/hg-cpython/src/lib.rs
diffstat 19 files changed, 126 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-core/Cargo.toml	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/Cargo.toml	Tue Jul 02 17:15:03 2019 +0200
@@ -3,6 +3,7 @@
 version = "0.1.0"
 authors = ["Georges Racinet <gracinet@anybox.fr>"]
 description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)"
+edition = "2018"
 
 [lib]
 name = "hg"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-core/src/dirstate.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -0,0 +1,36 @@
+pub mod dirs_multiset;
+pub mod parsers;
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+pub struct DirstateParents<'a> {
+    pub p1: &'a [u8],
+    pub p2: &'a [u8],
+}
+
+/// The C implementation uses all signed types. This will be an issue
+/// either when 4GB+ source files are commonplace or in 2038, whichever
+/// comes first.
+#[derive(Debug, PartialEq)]
+pub struct DirstateEntry {
+    pub state: i8,
+    pub mode: i32,
+    pub mtime: i32,
+    pub size: i32,
+}
+
+pub type DirstateVec = Vec<(Vec<u8>, DirstateEntry)>;
+
+#[derive(Debug, PartialEq)]
+pub struct CopyVecEntry<'a> {
+    pub path: &'a [u8],
+    pub copy_path: &'a [u8],
+}
+
+pub type CopyVec<'a> = Vec<CopyVecEntry<'a>>;
+
+/// The Python implementation passes either a mapping (dirstate) or a flat
+/// iterable (manifest)
+pub enum DirsIterable {
+    Dirstate(DirstateVec),
+    Manifest(Vec<Vec<u8>>),
+}
--- a/rust/hg-core/src/dirstate/dirs_multiset.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/src/dirstate/dirs_multiset.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -8,10 +8,9 @@
 //! A multiset of directory names.
 //!
 //! Used to counts the references to directories in a manifest or dirstate.
+use crate::{utils::files, DirsIterable, DirstateEntry, DirstateMapError};
 use std::collections::hash_map::{Entry, Iter};
 use std::collections::HashMap;
-use {DirsIterable, DirstateEntry, DirstateMapError};
-use utils::files;
 
 #[derive(PartialEq, Debug)]
 pub struct DirsMultiset {
--- a/rust/hg-core/src/dirstate/mod.rs	Fri Jul 12 11:08:31 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-pub mod dirs_multiset;
-pub mod parsers;
-
-#[derive(Debug, PartialEq, Copy, Clone)]
-pub struct DirstateParents<'a> {
-    pub p1: &'a [u8],
-    pub p2: &'a [u8],
-}
-
-/// The C implementation uses all signed types. This will be an issue
-/// either when 4GB+ source files are commonplace or in 2038, whichever
-/// comes first.
-#[derive(Debug, PartialEq)]
-pub struct DirstateEntry {
-    pub state: i8,
-    pub mode: i32,
-    pub mtime: i32,
-    pub size: i32,
-}
-
-pub type DirstateVec = Vec<(Vec<u8>, DirstateEntry)>;
-
-#[derive(Debug, PartialEq)]
-pub struct CopyVecEntry<'a> {
-    pub path: &'a [u8],
-    pub copy_path: &'a [u8],
-}
-
-pub type CopyVec<'a> = Vec<CopyVecEntry<'a>>;
-
-/// The Python implementation passes either a mapping (dirstate) or a flat
-/// iterable (manifest)
-pub enum DirsIterable {
-    Dirstate(DirstateVec),
-    Manifest(Vec<Vec<u8>>),
-}
--- a/rust/hg-core/src/dirstate/parsers.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/src/dirstate/parsers.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -3,13 +3,13 @@
 // This software may be used and distributed according to the terms of the
 // GNU General Public License version 2 or any later version.
 
+use crate::{
+    CopyVec, CopyVecEntry, DirstateEntry, DirstatePackError, DirstateParents,
+    DirstateParseError, DirstateVec,
+};
 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
 use std::collections::HashMap;
 use std::io::Cursor;
-use {
-    CopyVec, CopyVecEntry, DirstateEntry, DirstatePackError, DirstateParents,
-    DirstateParseError, DirstateVec,
-};
 
 /// Parents are stored in the dirstate as byte hashes.
 const PARENT_SIZE: usize = 20;
--- a/rust/hg-core/src/filepatterns.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/src/filepatterns.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -1,11 +1,13 @@
-use crate::{LineNumber, PatternError, PatternFileError};
+use crate::{
+    utils::{files::get_path_from_bytes, replace_slice, SliceExt},
+    LineNumber, PatternError, PatternFileError,
+};
+use lazy_static::lazy_static;
 use regex::bytes::Regex;
 use std::collections::HashMap;
 use std::fs::File;
 use std::io::Read;
 use std::vec::Vec;
-use utils::files::get_path_from_bytes;
-use utils::{replace_slice, SliceExt};
 
 lazy_static! {
     static ref RE_ESCAPE: Vec<Vec<u8>> = {
--- a/rust/hg-core/src/lib.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/src/lib.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -2,12 +2,6 @@
 //
 // This software may be used and distributed according to the terms of the
 // GNU General Public License version 2 or any later version.
-extern crate byteorder;
-extern crate memchr;
-#[macro_use]
-extern crate lazy_static;
-extern crate regex;
-
 mod ancestors;
 pub mod dagops;
 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
@@ -50,7 +44,7 @@
     /// Return the two parents of the given `Revision`.
     ///
     /// Each of the parents can be independently `NULL_REVISION`
-    fn parents(&self, Revision) -> Result<[Revision; 2], GraphError>;
+    fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
 }
 
 pub type LineNumber = usize;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-core/src/utils.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -0,0 +1,45 @@
+pub mod files;
+
+pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
+where
+    T: Clone + PartialEq,
+{
+    if buf.len() < from.len() || from.len() != to.len() {
+        return;
+    }
+    for i in 0..=buf.len() - from.len() {
+        if buf[i..].starts_with(from) {
+            buf[i..(i + from.len())].clone_from_slice(to);
+        }
+    }
+}
+
+pub trait SliceExt {
+    fn trim(&self) -> &Self;
+    fn trim_end(&self) -> &Self;
+}
+
+fn is_not_whitespace(c: &u8) -> bool {
+    !(*c as char).is_whitespace()
+}
+
+impl SliceExt for [u8] {
+    fn trim(&self) -> &[u8] {
+        if let Some(first) = self.iter().position(is_not_whitespace) {
+            if let Some(last) = self.iter().rposition(is_not_whitespace) {
+                &self[first..last + 1]
+            } else {
+                unreachable!();
+            }
+        } else {
+            &[]
+        }
+    }
+    fn trim_end(&self) -> &[u8] {
+        if let Some(last) = self.iter().rposition(is_not_whitespace) {
+            &self[..last + 1]
+        } else {
+            &[]
+        }
+    }
+}
--- a/rust/hg-core/src/utils/mod.rs	Fri Jul 12 11:08:31 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-pub mod files;
-
-pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
-where
-    T: Clone + PartialEq,
-{
-    if buf.len() < from.len() || from.len() != to.len() {
-        return;
-    }
-    for i in 0..=buf.len() - from.len() {
-        if buf[i..].starts_with(from) {
-            buf[i..(i + from.len())].clone_from_slice(to);
-        }
-    }
-}
-
-pub trait SliceExt {
-    fn trim(&self) -> &Self;
-    fn trim_end(&self) -> &Self;
-}
-
-fn is_not_whitespace(c: &u8) -> bool {
-    !(*c as char).is_whitespace()
-}
-
-impl SliceExt for [u8] {
-    fn trim(&self) -> &[u8] {
-        if let Some(first) = self.iter().position(is_not_whitespace) {
-            if let Some(last) = self.iter().rposition(is_not_whitespace) {
-                &self[first..last + 1]
-            } else {
-                unreachable!();
-            }
-        } else {
-            &[]
-        }
-    }
-    fn trim_end(&self) -> &[u8] {
-        if let Some(last) = self.iter().rposition(is_not_whitespace) {
-            &self[..last + 1]
-        } else {
-            &[]
-        }
-    }
-}
--- a/rust/hg-core/tests/test_missing_ancestors.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-core/tests/test_missing_ancestors.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -1,7 +1,3 @@
-extern crate hg;
-extern crate rand;
-extern crate rand_pcg;
-
 use hg::testing::VecGraph;
 use hg::Revision;
 use hg::*;
--- a/rust/hg-cpython/Cargo.toml	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/Cargo.toml	Tue Jul 02 17:15:03 2019 +0200
@@ -2,6 +2,7 @@
 name = "hg-cpython"
 version = "0.1.0"
 authors = ["Georges Racinet <gracinet@anybox.fr>"]
+edition = "2018"
 
 [lib]
 name='rusthg'
--- a/rust/hg-cpython/src/ancestors.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/ancestors.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -34,13 +34,15 @@
 //! [`LazyAncestors`]: struct.LazyAncestors.html
 //! [`MissingAncestors`]: struct.MissingAncestors.html
 //! [`AncestorsIterator`]: struct.AncestorsIterator.html
-use crate::conversion::{py_set, rev_pyiter_collect};
-use cindex::Index;
+use crate::{
+    cindex::Index,
+    conversion::{py_set, rev_pyiter_collect},
+    exceptions::GraphError,
+};
 use cpython::{
     ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult,
     Python, PythonObject, ToPyObject,
 };
-use exceptions::GraphError;
 use hg::Revision;
 use hg::{
     AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy,
--- a/rust/hg-cpython/src/cindex.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/cindex.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -10,14 +10,14 @@
 //! Ideally, we should use an Index entirely implemented in Rust,
 //! but this will take some time to get there.
 #[cfg(feature = "python27")]
-extern crate python27_sys as python_sys;
+use python27_sys as python_sys;
 #[cfg(feature = "python3")]
-extern crate python3_sys as python_sys;
+use python3_sys as python_sys;
 
-use self::python_sys::PyCapsule_Import;
 use cpython::{PyClone, PyErr, PyObject, PyResult, Python};
 use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
 use libc::c_int;
+use python_sys::PyCapsule_Import;
 use std::ffi::CStr;
 use std::mem::transmute;
 
--- a/rust/hg-cpython/src/dagops.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/dagops.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -9,10 +9,12 @@
 //! `hg-core` package.
 //!
 //! From Python, this will be seen as `mercurial.rustext.dagop`
-use crate::conversion::{py_set, rev_pyiter_collect};
-use cindex::Index;
+use crate::{
+    cindex::Index,
+    conversion::{py_set, rev_pyiter_collect},
+    exceptions::GraphError,
+};
 use cpython::{PyDict, PyModule, PyObject, PyResult, Python};
-use exceptions::GraphError;
 use hg::dagops;
 use hg::Revision;
 use std::collections::HashSet;
--- a/rust/hg-cpython/src/dirstate.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/dirstate.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -19,17 +19,14 @@
     DirstateEntry, DirstateMapError, DirstatePackError, DirstateParents,
     DirstateParseError, DirstateVec,
 };
+use libc::{c_char, c_int};
+#[cfg(feature = "python27")]
+use python27_sys::PyCapsule_Import;
+#[cfg(feature = "python3")]
+use python3_sys::PyCapsule_Import;
+use std::cell::RefCell;
 use std::collections::HashMap;
 use std::ffi::CStr;
-
-#[cfg(feature = "python27")]
-extern crate python27_sys as python_sys;
-#[cfg(feature = "python3")]
-extern crate python3_sys as python_sys;
-
-use self::python_sys::PyCapsule_Import;
-use libc::{c_char, c_int};
-use std::cell::RefCell;
 use std::mem::transmute;
 
 /// C code uses a custom `dirstate_tuple` type, checks in multiple instances
--- a/rust/hg-cpython/src/discovery.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/discovery.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -12,13 +12,15 @@
 //! - [`PartialDiscover`] is the Rust implementation of
 //!   `mercurial.setdiscovery.partialdiscovery`.
 
-use crate::conversion::{py_set, rev_pyiter_collect};
-use cindex::Index;
+use crate::{
+    cindex::Index,
+    conversion::{py_set, rev_pyiter_collect},
+    exceptions::GraphError,
+};
 use cpython::{
     ObjectProtocol, PyDict, PyModule, PyObject, PyResult, Python,
     PythonObject, ToPyObject,
 };
-use exceptions::GraphError;
 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
 use hg::Revision;
 
--- a/rust/hg-cpython/src/exceptions.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/exceptions.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -12,8 +12,10 @@
 //! existing Python exceptions if appropriate.
 //!
 //! [`GraphError`]: struct.GraphError.html
-use cpython::exc::{RuntimeError, ValueError};
-use cpython::{exc, PyErr, Python};
+use cpython::{
+    exc::{IOError, RuntimeError, ValueError},
+    py_exception, PyErr, Python,
+};
 use hg;
 
 py_exception!(rustext, GraphError, ValueError);
@@ -55,7 +57,7 @@
         match inner {
             hg::PatternFileError::IO(e) => {
                 let value = (e.raw_os_error().unwrap_or(2), e.to_string());
-                PyErr::new::<exc::IOError, _>(py, value)
+                PyErr::new::<IOError, _>(py, value)
             }
             hg::PatternFileError::Pattern(e, l) => match e {
                 hg::PatternError::UnsupportedSyntax(m) => {
--- a/rust/hg-cpython/src/filepatterns.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/filepatterns.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -10,10 +10,10 @@
 //! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns`
 //! and can be used as replacement for the the pure `filepatterns` Python module.
 //!
+use crate::exceptions::{PatternError, PatternFileError};
 use cpython::{
     PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
 };
-use exceptions::{PatternError, PatternFileError};
 use hg::{build_single_regex, read_pattern_file, LineNumber, PatternTuple};
 
 /// Rust does not like functions with different return signatures.
--- a/rust/hg-cpython/src/lib.rs	Fri Jul 12 11:08:31 2019 +0200
+++ b/rust/hg-cpython/src/lib.rs	Tue Jul 02 17:15:03 2019 +0200
@@ -19,10 +19,10 @@
 //! 'Generic DAG ancestor algorithms - Rust implementation'
 //! ```
 
+/// This crate uses nested private macros, `extern crate` is still needed in
+/// 2018 edition.
 #[macro_use]
 extern crate cpython;
-extern crate hg;
-extern crate libc;
 
 pub mod ancestors;
 mod cindex;