merge with stable
authorYuya Nishihara <yuya@tcha.org>
Fri, 25 Jan 2019 18:55:23 +0900
changeset 41351 0ae3ddb4fbed
parent 41347 40787a96fda7 (current diff)
parent 41350 ab0d762d89ef (diff)
child 41352 73ccba60aaa1
merge with stable
--- a/mercurial/revlog.py	Thu Jan 24 15:03:00 2019 -0500
+++ b/mercurial/revlog.py	Fri Jan 25 18:55:23 2019 +0900
@@ -396,6 +396,11 @@
             newversionflags = REVLOGV1 | FLAG_INLINE_DATA
             if 'generaldelta' in opts:
                 newversionflags |= FLAG_GENERALDELTA
+        elif getattr(self.opener, 'options', None) is not None:
+            # If options provided but no 'revlog*' found, the repository
+            # would have no 'requires' file in it, which means we have to
+            # stick to the old format.
+            newversionflags = REVLOGV0
         else:
             newversionflags = REVLOG_DEFAULT_VERSION
 
@@ -896,8 +901,6 @@
             common = [nullrev]
 
         if rustext is not None:
-            # TODO: WdirUnsupported should be raised instead of GraphError
-            # if common includes wdirrev
             return rustext.ancestor.MissingAncestors(self.index, common)
         return ancestor.incrementalmissingancestors(self.parentrevs, common)
 
--- a/mercurial/setdiscovery.py	Thu Jan 24 15:03:00 2019 -0500
+++ b/mercurial/setdiscovery.py	Fri Jan 25 18:55:23 2019 +0900
@@ -183,7 +183,8 @@
     def addcommons(self, commons):
         """registrer nodes known as common"""
         self._common.addbases(commons)
-        self._common.removeancestorsfrom(self.undecided)
+        if self._undecided is not None:
+            self._common.removeancestorsfrom(self._undecided)
 
     def addmissings(self, missings):
         """registrer some nodes as missing"""
--- a/mercurial/ui.py	Thu Jan 24 15:03:00 2019 -0500
+++ b/mercurial/ui.py	Fri Jan 25 18:55:23 2019 +0900
@@ -999,15 +999,47 @@
         "cmdname.type" is recommended. For example, status issues
         a label of "status.modified" for modified files.
         '''
-        self._write(self._fout, *args, **opts)
+        dest = self._fout
+
+        # inlined _write() for speed
+        if self._buffers:
+            label = opts.get(r'label', '')
+            if label and self._bufferapplylabels:
+                self._buffers[-1].extend(self.label(a, label) for a in args)
+            else:
+                self._buffers[-1].extend(args)
+            return
+
+        # inliend _writenobuf() for speed
+        self._progclear()
+        msg = b''.join(args)
+
+        # opencode timeblockedsection because this is a critical path
+        starttime = util.timer()
+        try:
+            if self._colormode == 'win32':
+                # windows color printing is its own can of crab, defer to
+                # the color module and that is it.
+                color.win32print(self, dest.write, msg, **opts)
+            else:
+                if self._colormode is not None:
+                    label = opts.get(r'label', '')
+                    msg = self.label(msg, label)
+                dest.write(msg)
+        except IOError as err:
+            raise error.StdioError(err)
+        finally:
+            self._blockedtimes['stdio_blocked'] += \
+                (util.timer() - starttime) * 1000
 
     def write_err(self, *args, **opts):
         self._write(self._ferr, *args, **opts)
 
     def _write(self, dest, *args, **opts):
+        # update write() as well if you touch this code
         if self._isbuffered(dest):
-            if self._bufferapplylabels:
-                label = opts.get(r'label', '')
+            label = opts.get(r'label', '')
+            if label and self._bufferapplylabels:
                 self._buffers[-1].extend(self.label(a, label) for a in args)
             else:
                 self._buffers[-1].extend(args)
@@ -1015,6 +1047,7 @@
             self._writenobuf(dest, *args, **opts)
 
     def _writenobuf(self, dest, *args, **opts):
+        # update write() as well if you touch this code
         self._progclear()
         msg = b''.join(args)
 
--- a/rust/hg-core/src/lib.rs	Thu Jan 24 15:03:00 2019 -0500
+++ b/rust/hg-core/src/lib.rs	Fri Jan 25 18:55:23 2019 +0900
@@ -16,6 +16,12 @@
 
 pub const NULL_REVISION: Revision = -1;
 
+/// Same as `mercurial.node.wdirrev`
+///
+/// This is also equal to `i32::max_value()`, but it's better to spell
+/// it out explicitely, same as in `mercurial.node`
+pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
+
 /// The simplest expression of what we need of Mercurial DAGs.
 pub trait Graph {
     /// Return the two parents of the given `Revision`.
@@ -27,4 +33,5 @@
 #[derive(Clone, Debug, PartialEq)]
 pub enum GraphError {
     ParentOutOfRange(Revision),
+    WorkingDirectoryUnsupported,
 }
--- a/rust/hg-cpython/src/cindex.rs	Thu Jan 24 15:03:00 2019 -0500
+++ b/rust/hg-cpython/src/cindex.rs	Fri Jan 25 18:55:23 2019 +0900
@@ -16,7 +16,7 @@
 
 use self::python_sys::PyCapsule_Import;
 use cpython::{PyClone, PyErr, PyObject, PyResult, Python};
-use hg::{Graph, GraphError, Revision};
+use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
 use libc::c_int;
 use std::ffi::CStr;
 use std::mem::transmute;
@@ -86,6 +86,9 @@
 impl Graph for Index {
     /// wrap a call to the C extern parents function
     fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
+        if rev == WORKING_DIRECTORY_REVISION {
+            return Err(GraphError::WorkingDirectoryUnsupported);
+        }
         let mut res: [c_int; 2] = [0; 2];
         let code = unsafe {
             (self.parents)(
--- a/rust/hg-cpython/src/exceptions.rs	Thu Jan 24 15:03:00 2019 -0500
+++ b/rust/hg-cpython/src/exceptions.rs	Fri Jan 25 18:55:23 2019 +0900
@@ -8,6 +8,8 @@
 //! Bindings for Rust errors
 //!
 //! [`GraphError`] exposes `hg::GraphError` as a subclass of `ValueError`
+//! but some variants of `hg::GraphError` can be converted directly to other
+//! existing Python exceptions if appropriate.
 //!
 //! [`GraphError`]: struct.GraphError.html
 use cpython::exc::ValueError;
@@ -22,6 +24,15 @@
             hg::GraphError::ParentOutOfRange(r) => {
                 GraphError::new(py, ("ParentOutOfRange", r))
             }
+            hg::GraphError::WorkingDirectoryUnsupported => {
+                match py
+                    .import("mercurial.error")
+                    .and_then(|m| m.get(py, "WdirUnsupported"))
+                {
+                    Err(e) => e,
+                    Ok(cls) => PyErr::from_instance(py, cls),
+                }
+            }
         }
     }
 }
--- a/tests/test-clone.t	Thu Jan 24 15:03:00 2019 -0500
+++ b/tests/test-clone.t	Fri Jan 25 18:55:23 2019 +0900
@@ -717,6 +717,9 @@
   $ hg -R src commit -m '#0'
   $ hg -R src log -q
   0:e1bab28bca43
+  $ hg -R src debugrevlog -c | egrep 'format|flags'
+  format : 0
+  flags  : (none)
   $ hg clone -U -q src dst
   $ hg -R dst log -q
   0:e1bab28bca43
--- a/tests/test-rust-ancestor.py	Thu Jan 24 15:03:00 2019 -0500
+++ b/tests/test-rust-ancestor.py	Fri Jan 25 18:55:23 2019 +0900
@@ -2,6 +2,11 @@
 import sys
 import unittest
 
+from mercurial import (
+    error,
+    node,
+)
+
 try:
     from mercurial import rustext
     rustext.__name__  # trigger immediate actual import
@@ -153,6 +158,12 @@
         # rust-cpython issues appropriate str instances for Python 2 and 3
         self.assertEqual(exc.args, ('ParentOutOfRange', 1))
 
+    def testwdirunsupported(self):
+        # trying to access ancestors of the working directory raises
+        # WdirUnsupported directly
+        idx = self.parseindex()
+        with self.assertRaises(error.WdirUnsupported):
+            list(AncestorsIterator(idx, [node.wdirrev], -1, False))
 
 if __name__ == '__main__':
     import silenttestrunner