diff rust/hg-core/src/revlog/filelog.rs @ 48237:027ebad952ac

rhg: internally, return a structured representation from hg cat The purpose of this change is to make it possible to support limited templating in `hg cat`, so we could print separators between files etc. The templating itself is not implemented yet, so this functionality is unused in `rhg cat`. However, in our fork of hg we're implementing a slightly different command `hg jscat` which makes use of this. So accepting this change will let us minimize the size of the patch we're maintaining on our side. Differential Revision: https://phab.mercurial-scm.org/D11679
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Fri, 15 Oct 2021 14:05:20 +0100
parents 87e3f878e65f
children e9faae0f445c
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/filelog.rs	Thu Oct 14 19:02:08 2021 +0100
+++ b/rust/hg-core/src/revlog/filelog.rs	Fri Oct 15 14:05:20 2021 +0100
@@ -7,7 +7,6 @@
 use crate::utils::files::get_path_from_bytes;
 use crate::utils::hg_path::HgPath;
 use crate::utils::SliceExt;
-use std::borrow::Cow;
 use std::path::PathBuf;
 
 /// A specialized `Revlog` to work with file data logs.
@@ -40,7 +39,7 @@
         &self,
         file_rev: Revision,
     ) -> Result<FilelogEntry, RevlogError> {
-        let data = self.revlog.get_rev_data(file_rev)?;
+        let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?;
         Ok(FilelogEntry(data.into()))
     }
 }
@@ -51,22 +50,32 @@
     get_path_from_bytes(&encoded_bytes).into()
 }
 
-pub struct FilelogEntry<'filelog>(Cow<'filelog, [u8]>);
+pub struct FilelogEntry(Vec<u8>);
 
-impl<'filelog> FilelogEntry<'filelog> {
+impl FilelogEntry {
     /// Split into metadata and data
-    pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> {
+    /// Returns None if there is no metadata, so the entire entry is data.
+    fn split_metadata(&self) -> Result<Option<(&[u8], &[u8])>, HgError> {
         const DELIMITER: &[u8; 2] = &[b'\x01', b'\n'];
 
         if let Some(rest) = self.0.drop_prefix(DELIMITER) {
             if let Some((metadata, data)) = rest.split_2_by_slice(DELIMITER) {
-                Ok((Some(metadata), data))
+                Ok(Some((metadata, data)))
             } else {
                 Err(HgError::corrupted(
                     "Missing metadata end delimiter in filelog entry",
                 ))
             }
         } else {
+            Ok(None)
+        }
+    }
+
+    /// Split into metadata and data
+    pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> {
+        if let Some((metadata, data)) = self.split_metadata()? {
+            Ok((Some(metadata), data))
+        } else {
             Ok((None, &self.0))
         }
     }
@@ -76,4 +85,14 @@
         let (_metadata, data) = self.split()?;
         Ok(data)
     }
+
+    /// Consume the entry, and convert it into data, discarding any metadata,
+    /// if present.
+    pub fn into_data(self) -> Result<Vec<u8>, HgError> {
+        if let Some((_metadata, data)) = self.split_metadata()? {
+            Ok(data.to_owned())
+        } else {
+            Ok(self.0)
+        }
+    }
 }