rhg: allow specifying a changeset ID prefix
authorSimon Sapin <simon-commits@exyr.org>
Mon, 30 Nov 2020 19:34:49 +0100
changeset 46032 8d6164098782
parent 46031 c701f616d852
child 46033 88e741bf2d93
rhg: allow specifying a changeset ID prefix Differential Revision: https://phab.mercurial-scm.org/D9479
rust/hg-core/src/operations/cat.rs
rust/hg-core/src/operations/debugdata.rs
rust/hg-core/src/operations/list_tracked_files.rs
rust/hg-core/src/revlog/revlog.rs
rust/rhg/src/commands/cat.rs
rust/rhg/src/commands/debugdata.rs
rust/rhg/src/commands/files.rs
tests/test-rhg.t
--- a/rust/hg-core/src/operations/cat.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/hg-core/src/operations/cat.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -26,6 +26,8 @@
     IoError(std::io::Error),
     /// The revision has not been found.
     InvalidRevision,
+    /// Found more than one revision whose ID match the requested prefix
+    AmbiguousPrefix,
     /// A `revlog` file is corrupted.
     CorruptedRevlog,
     /// The `revlog` format version is not supported.
@@ -55,6 +57,7 @@
                 CatRevErrorKind::UnsuportedRevlogVersion(version)
             }
             RevlogError::InvalidRevision => CatRevErrorKind::InvalidRevision,
+            RevlogError::AmbiguousPrefix => CatRevErrorKind::AmbiguousPrefix,
             RevlogError::Corrupted => CatRevErrorKind::CorruptedRevlog,
             RevlogError::UnknowDataFormat(format) => {
                 CatRevErrorKind::UnknowRevlogDataFormat(format)
--- a/rust/hg-core/src/operations/debugdata.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/hg-core/src/operations/debugdata.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -24,6 +24,8 @@
     IoError(std::io::Error),
     /// The revision has not been found.
     InvalidRevision,
+    /// Found more than one revision whose ID match the requested prefix
+    AmbiguousPrefix,
     /// A `revlog` file is corrupted.
     CorruptedRevlog,
     /// The `revlog` format version is not supported.
@@ -69,6 +71,9 @@
             RevlogError::InvalidRevision => {
                 DebugDataErrorKind::InvalidRevision
             }
+            RevlogError::AmbiguousPrefix => {
+                DebugDataErrorKind::AmbiguousPrefix
+            }
             RevlogError::Corrupted => DebugDataErrorKind::CorruptedRevlog,
             RevlogError::UnknowDataFormat(format) => {
                 DebugDataErrorKind::UnknowRevlogDataFormat(format)
--- a/rust/hg-core/src/operations/list_tracked_files.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/hg-core/src/operations/list_tracked_files.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -86,6 +86,8 @@
     IoError(std::io::Error),
     /// The revision has not been found.
     InvalidRevision,
+    /// Found more than one revision whose ID match the requested prefix
+    AmbiguousPrefix,
     /// A `revlog` file is corrupted.
     CorruptedRevlog,
     /// The `revlog` format version is not supported.
@@ -119,6 +121,9 @@
             RevlogError::InvalidRevision => {
                 ListRevTrackedFilesErrorKind::InvalidRevision
             }
+            RevlogError::AmbiguousPrefix => {
+                ListRevTrackedFilesErrorKind::AmbiguousPrefix
+            }
             RevlogError::Corrupted => {
                 ListRevTrackedFilesErrorKind::CorruptedRevlog
             }
--- a/rust/hg-core/src/revlog/revlog.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/hg-core/src/revlog/revlog.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -21,6 +21,8 @@
     IoError(std::io::Error),
     UnsuportedVersion(u16),
     InvalidRevision,
+    /// Found more than one entry whose ID match the requested prefix
+    AmbiguousPrefix,
     Corrupted,
     UnknowDataFormat(u8),
 }
@@ -93,14 +95,21 @@
     pub fn get_node_rev(&self, node: &[u8]) -> Result<Revision, RevlogError> {
         // This is brute force. But it is fast enough for now.
         // Optimization will come later.
+        let mut found_by_prefix = None;
         for rev in (0..self.len() as Revision).rev() {
             let index_entry =
                 self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
-            if node == index_entry.hash() {
+            if index_entry.hash() == node {
                 return Ok(rev);
             }
+            if index_entry.hash().starts_with(node) {
+                if found_by_prefix.is_some() {
+                    return Err(RevlogError::AmbiguousPrefix);
+                }
+                found_by_prefix = Some(rev)
+            }
         }
-        Err(RevlogError::InvalidRevision)
+        found_by_prefix.ok_or(RevlogError::InvalidRevision)
     }
 
     /// Return the full data associated to a revision.
--- a/rust/rhg/src/commands/cat.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/rhg/src/commands/cat.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -75,6 +75,13 @@
                 ))
                 .into(),
             )),
+            CatRevErrorKind::AmbiguousPrefix => CommandErrorKind::Abort(Some(
+                utf8_to_local(&format!(
+                    "abort: ambiguous revision identifier {}\n",
+                    rev
+                ))
+                .into(),
+            )),
             CatRevErrorKind::UnsuportedRevlogVersion(version) => {
                 CommandErrorKind::Abort(Some(
                     utf8_to_local(&format!(
--- a/rust/rhg/src/commands/debugdata.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/rhg/src/commands/debugdata.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -55,6 +55,15 @@
                 .into(),
             )),
         },
+        DebugDataErrorKind::AmbiguousPrefix => CommandError {
+            kind: CommandErrorKind::Abort(Some(
+                utf8_to_local(&format!(
+                    "abort: ambiguous revision identifier{}\n",
+                    rev
+                ))
+                .into(),
+            )),
+        },
         DebugDataErrorKind::UnsuportedRevlogVersion(version) => CommandError {
             kind: CommandErrorKind::Abort(Some(
                 utf8_to_local(&format!(
--- a/rust/rhg/src/commands/files.rs	Thu Dec 03 13:23:59 2020 -0800
+++ b/rust/rhg/src/commands/files.rs	Mon Nov 30 19:34:49 2020 +0100
@@ -91,6 +91,15 @@
                     .into(),
                 ))
             }
+            ListRevTrackedFilesErrorKind::AmbiguousPrefix => {
+                CommandErrorKind::Abort(Some(
+                    utf8_to_local(&format!(
+                        "abort: ambiguous revision identifier {}\n",
+                        rev
+                    ))
+                    .into(),
+                ))
+            }
             ListRevTrackedFilesErrorKind::UnsuportedRevlogVersion(version) => {
                 CommandErrorKind::Abort(Some(
                     utf8_to_local(&format!(
--- a/tests/test-rhg.t	Thu Dec 03 13:23:59 2020 -0800
+++ b/tests/test-rhg.t	Mon Nov 30 19:34:49 2020 +0100
@@ -74,31 +74,49 @@
   $ rm -rf repository
   $ hg init repository
   $ cd repository
-  $ for i in 1 2 3; do
-  >   echo $i >> file$i
-  >   hg add file$i
-  >   hg commit -m "commit $i" -q
+  $ for i in 1 2 3 4 5 6; do
+  >   echo $i >> file-$i
+  >   hg add file-$i
+  >   hg commit -m "Commit $i" -q
   > done
   $ rhg debugdata -c 2
-  e36fa63d37a576b27a69057598351db6ee5746bd
+  8d0267cb034247ebfa5ee58ce59e22e57a492297
   test
   0 0
-  file3
+  file-3
   
-  commit 3 (no-eol)
+  Commit 3 (no-eol)
   $ rhg debugdata -m 2
-  file1\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
-  file2\x005d9299349fc01ddd25d0070d149b124d8f10411e (esc)
-  file3\x002661d26c649684b482d10f91960cc3db683c38b4 (esc)
+  file-1\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc)
+  file-2\x005d9299349fc01ddd25d0070d149b124d8f10411e (esc)
+  file-3\x002661d26c649684b482d10f91960cc3db683c38b4 (esc)
 
 Debuging with full node id
   $ rhg debugdata -c `hg log -r 0 -T '{node}'`
-  c8e64718e1ca0312eeee0f59d37f8dc612793856
+  d1d1c679d3053e8926061b6f45ca52009f011e3f
   test
   0 0
-  file1
+  file-1
   
-  commit 1 (no-eol)
+  Commit 1 (no-eol)
+
+Specifying revisions by changeset ID
+  $ hg log -T '{node}\n'
+  c6ad58c44207b6ff8a4fbbca7045a5edaa7e908b
+  d654274993d0149eecc3cc03214f598320211900
+  f646af7e96481d3a5470b695cf30ad8e3ab6c575
+  cf8b83f14ead62b374b6e91a0e9303b85dfd9ed7
+  91c6f6e73e39318534dc415ea4e8a09c99cd74d6
+  6ae9681c6d30389694d8701faf24b583cf3ccafe
+  $ rhg files -r cf8b83
+  file-1
+  file-2
+  file-3
+  $ rhg cat -r cf8b83 file-2
+  2
+  $ rhg cat -r c file-2
+  abort: invalid revision identifier c
+  [255]
 
 Cat files
   $ cd $TESTTMP
@@ -116,26 +134,6 @@
   $ rhg cat -r 1 copy_of_original
   original content
 
-Specifying revisions by changeset ID
-  $ hg log
-  changeset:   1:41263439dc17
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add copy of original
-  
-  changeset:   0:1c9e69808da7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add original
-  
-  $ rhg files -r 41263439dc17
-  abort: invalid revision identifier 41263439dc17
-  [255]
-  $ rhg cat -r 41263439dc17 original
-  abort: invalid revision identifier 41263439dc17
-  [255]
-
 Requirements
   $ rhg debugrequirements
   dotencode