##// END OF EJS Templates
dirstate: cleanup remaining of "now" during write...
dirstate: cleanup remaining of "now" during write Since the whole `need_delay` have been removed, we no longer need this. Differential Revision: https://phab.mercurial-scm.org/D11797

File last commit:

r49079:269ff897 default
r49222:1a8a70b4 default
Show More
parsers.rs
137 lines | 4.2 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
Simon Sapin
rust: Replace DirstatePackError with HgError...
r47168 use crate::errors::HgError;
Simon Sapin
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs...
r47894 use crate::utils::hg_path::HgPath;
Simon Sapin
dirstate: Remove the flat Rust DirstateMap implementation...
r48882 use crate::{dirstate::EntryState, DirstateEntry, DirstateParents};
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 use byteorder::{BigEndian, WriteBytesExt};
Simon Sapin
rust: Move DirstateEntry to its own module...
r48830 use bytes_cast::{unaligned, BytesCast};
Raphaël Gomès
hg-core: add function timing information...
r45028 use micro_timer::timed;
Simon Sapin
dirstate: Remove the flat Rust DirstateMap implementation...
r48882 use std::convert::TryFrom;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
/// Parents are stored in the dirstate as byte hashes.
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 pub const PARENT_SIZE: usize = 20;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 /// Dirstate entries have a static part of 8 + 32 + 32 + 32 + 32 bits.
const MIN_ENTRY_SIZE: usize = 17;
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 type ParseResult<'a> = (
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 &'a DirstateParents,
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 Vec<(&'a HgPath, DirstateEntry)>,
Vec<(&'a HgPath, &'a HgPath)>,
);
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993
Simon Sapin
rhg: Add support for the blackbox extension...
r47343 pub fn parse_dirstate_parents(
contents: &[u8],
) -> Result<&DirstateParents, HgError> {
let (parents, _rest) = DirstateParents::from_bytes(contents)
.map_err(|_| HgError::corrupted("Too little data for dirstate."))?;
Ok(parents)
}
Raphaël Gomès
hg-core: add function timing information...
r45028 #[timed]
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 pub fn parse_dirstate(contents: &[u8]) -> Result<ParseResult, HgError> {
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 let mut copies = Vec::new();
let mut entries = Vec::new();
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 let parents =
parse_dirstate_entries(contents, |path, entry, copy_source| {
if let Some(source) = copy_source {
copies.push((path, source));
}
entries.push((path, *entry));
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 Ok(())
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 })?;
Ok((parents, entries, copies))
}
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Simon Sapin
rust: Move DirstateEntry to its own module...
r48830 #[derive(BytesCast)]
#[repr(C)]
Simon Sapin
rust: Make the fields of DirstateEntry private...
r48834 struct RawEntry {
Simon Sapin
rust: Move DirstateEntry to its own module...
r48830 state: u8,
mode: unaligned::I32Be,
size: unaligned::I32Be,
mtime: unaligned::I32Be,
length: unaligned::I32Be,
}
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 pub fn parse_dirstate_entries<'a>(
mut contents: &'a [u8],
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 mut each_entry: impl FnMut(
&'a HgPath,
&DirstateEntry,
Option<&'a HgPath>,
) -> Result<(), HgError>,
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 ) -> Result<&'a DirstateParents, HgError> {
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 let (parents, rest) = DirstateParents::from_bytes(contents)
.map_err(|_| HgError::corrupted("Too little data for dirstate."))?;
contents = rest;
while !contents.is_empty() {
let (raw_entry, rest) = RawEntry::from_bytes(contents)
.map_err(|_| HgError::corrupted("Overflow in dirstate."))?;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Simon Sapin
rust: Make the fields of DirstateEntry private...
r48834 let entry = DirstateEntry::from_v1_data(
EntryState::try_from(raw_entry.state)?,
raw_entry.mode.get(),
raw_entry.size.get(),
raw_entry.mtime.get(),
);
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 let (paths, rest) =
u8::slice_from_bytes(rest, raw_entry.length.get() as usize)
.map_err(|_| HgError::corrupted("Overflow in dirstate."))?;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 // `paths` is either a single path, or two paths separated by a NULL
// byte
let mut iter = paths.splitn(2, |&byte| byte == b'\0');
let path = HgPath::new(
iter.next().expect("splitn always yields at least one item"),
);
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 let copy_source = iter.next().map(HgPath::new);
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 each_entry(path, &entry, copy_source)?;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Simon Sapin
rust: Rewrite dirstate parsing usin the `bytes-cast` crate...
r47336 contents = rest;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Simon Sapin
dirstate-tree: Implement DirstateMap::read...
r47867 Ok(parents)
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 fn packed_filename_and_copy_source_size(
Simon Sapin
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs...
r47894 filename: &HgPath,
copy_source: Option<&HgPath>,
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 ) -> usize {
filename.len()
+ if let Some(source) = copy_source {
b"\0".len() + source.len()
} else {
0
}
}
pub fn packed_entry_size(
Simon Sapin
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs...
r47894 filename: &HgPath,
copy_source: Option<&HgPath>,
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 ) -> usize {
MIN_ENTRY_SIZE
+ packed_filename_and_copy_source_size(filename, copy_source)
}
pub fn pack_entry(
Simon Sapin
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs...
r47894 filename: &HgPath,
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 entry: &DirstateEntry,
Simon Sapin
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs...
r47894 copy_source: Option<&HgPath>,
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 packed: &mut Vec<u8>,
) {
let length = packed_filename_and_copy_source_size(filename, copy_source);
Simon Sapin
rust: Make the fields of DirstateEntry private...
r48834 let (state, mode, size, mtime) = entry.v1_data();
Simon Sapin
dirstate-tree: Serialize to disk...
r47872
// Unwrapping because `impl std::io::Write for Vec<u8>` never errors
Simon Sapin
rust: Make the fields of DirstateEntry private...
r48834 packed.write_u8(state).unwrap();
packed.write_i32::<BigEndian>(mode).unwrap();
packed.write_i32::<BigEndian>(size).unwrap();
packed.write_i32::<BigEndian>(mtime).unwrap();
Simon Sapin
dirstate-tree: Serialize to disk...
r47872 packed.write_i32::<BigEndian>(length as i32).unwrap();
packed.extend(filename.as_bytes());
if let Some(source) = copy_source {
packed.push(b'\0');
packed.extend(source.as_bytes());
}
}