##// END OF EJS Templates
tagcache: distinguish between invalid and missing entries...
tagcache: distinguish between invalid and missing entries The TortoiseHg repo has typically not had a newly applied tag accessible by name for recent releases, for unknown reasons. Deleting and rebuilding the tag cache doesn't fix it, though deleting the cache and running `hg log -r $new_tag` does. Eventually the situation does sort itself out for new clones from the server. In an effort to figure out what the issue is, Pierre-Yves David suggested listing these entries in the debug output more specifically. This isn't complete yet- the second test change that says "missing" is more like "invalid", since it was truncated. The problem there is the code that reads the raw array truncates any partial records and then fills it with 0xFF, which signifies that it is missing. As a side note, that means the check for the length when validating an existing entry never fails. Differential Revision: https://phab.mercurial-scm.org/D9811

File last commit:

r47169:776b9717 default
r47245:5aac1a1a default
Show More
parsers.rs
520 lines | 16.9 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;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 use crate::utils::hg_path::HgPath;
Raphaël Gomès
rust: switch hg-core and hg-cpython to rust 2018 edition...
r42828 use crate::{
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 dirstate::{CopyMap, EntryState, StateMap},
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 DirstateEntry, DirstateParents,
Raphaël Gomès
rust: switch hg-core and hg-cpython to rust 2018 edition...
r42828 };
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
Raphaël Gomès
hg-core: add function timing information...
r45028 use micro_timer::timed;
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 use std::convert::{TryFrom, TryInto};
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 use std::io::Cursor;
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 use std::time::Duration;
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> = (
DirstateParents,
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
Raphaël Gomès
hg-core: add function timing information...
r45028 #[timed]
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 pub fn parse_dirstate(contents: &[u8]) -> Result<ParseResult, HgError> {
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 if contents.len() < PARENT_SIZE * 2 {
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 return Err(HgError::corrupted("Too little data for dirstate."));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 let mut copies = vec![];
let mut entries = vec![];
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
let mut curr_pos = PARENT_SIZE * 2;
let parents = DirstateParents {
Yuya Nishihara
rust: simply use TryInto to convert slice to array...
r43067 p1: contents[..PARENT_SIZE].try_into().unwrap(),
p2: contents[PARENT_SIZE..curr_pos].try_into().unwrap(),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
while curr_pos < contents.len() {
if curr_pos + MIN_ENTRY_SIZE > contents.len() {
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 return Err(HgError::corrupted("Overflow in dirstate."));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
let entry_bytes = &contents[curr_pos..];
let mut cursor = Cursor::new(entry_bytes);
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 // Unwraping errors from `byteorder` as we’ve already checked
// `MIN_ENTRY_SIZE` so the input should never be too short.
let state = EntryState::try_from(cursor.read_u8().unwrap())?;
let mode = cursor.read_i32::<BigEndian>().unwrap();
let size = cursor.read_i32::<BigEndian>().unwrap();
let mtime = cursor.read_i32::<BigEndian>().unwrap();
let path_len = cursor.read_i32::<BigEndian>().unwrap() as usize;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
if path_len > contents.len() - curr_pos {
Simon Sapin
rust: Remove DirstateParseError and ListDirstateTrackedFilesError...
r47169 return Err(HgError::corrupted("Overflow in dirstate."));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
// Slice instead of allocating a Vec needed for `read_exact`
let path = &entry_bytes[MIN_ENTRY_SIZE..MIN_ENTRY_SIZE + (path_len)];
let (path, copy) = match memchr::memchr(0, path) {
None => (path, None),
Some(i) => (&path[..i], Some(&path[(i + 1)..])),
};
if let Some(copy_path) = copy {
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 copies.push((HgPath::new(path), HgPath::new(copy_path)));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 entries.push((
HgPath::new(path),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
state,
mode,
size,
mtime,
},
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 ));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 curr_pos = curr_pos + MIN_ENTRY_SIZE + (path_len);
}
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 Ok((parents, entries, copies))
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 /// `now` is the duration in seconds since the Unix epoch
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 #[cfg(not(feature = "dirstate-tree"))]
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 pub fn pack_dirstate(
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 state_map: &mut StateMap,
copy_map: &CopyMap,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 parents: DirstateParents,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 now: Duration,
Simon Sapin
rust: Replace DirstatePackError with HgError...
r47168 ) -> Result<Vec<u8>, HgError> {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 // TODO move away from i32 before 2038.
let now: i32 = now.as_secs().try_into().expect("time overflow");
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let expected_size: usize = state_map
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 .iter()
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 .map(|(filename, _)| {
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let mut length = MIN_ENTRY_SIZE + filename.len();
Yuya Nishihara
rust-dirstate: remove unneeded "ref"...
r43062 if let Some(copy) = copy_map.get(filename) {
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 length += copy.len() + 1;
}
length
})
.sum();
let expected_size = expected_size + PARENT_SIZE * 2;
let mut packed = Vec::with_capacity(expected_size);
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 packed.extend(&parents.p1);
packed.extend(&parents.p2);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Raphaël Gomès
rust-parsers: use in-place mutation instead of allocating a new `Vec`...
r46223 for (filename, entry) in state_map.iter_mut() {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let new_filename = filename.to_owned();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let mut new_mtime: i32 = entry.mtime;
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 if entry.state == EntryState::Normal && entry.mtime == now {
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 // The file was last modified "simultaneously" with the current
// write to dirstate (i.e. within the same second for file-
// systems with a granularity of 1 sec). This commonly happens
// for at least a couple of files on 'update'.
// The user could change the file without changing its size
// within the same second. Invalidate the file's mtime in
// dirstate, forcing future 'status' calls to compare the
// contents of the file if the size is the same. This prevents
// mistakenly treating such files as clean.
new_mtime = -1;
Raphaël Gomès
rust-parsers: use in-place mutation instead of allocating a new `Vec`...
r46223 *entry = DirstateEntry {
mtime: new_mtime,
..*entry
};
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let mut new_filename = new_filename.into_vec();
Yuya Nishihara
rust-dirstate: remove unneeded "ref"...
r43062 if let Some(copy) = copy_map.get(filename) {
Raphaël Gomès
rust: do a clippy pass...
r45500 new_filename.push(b'\0');
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 new_filename.extend(copy.bytes());
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Simon Sapin
rust: Replace DirstatePackError with HgError...
r47168 // Unwrapping because `impl std::io::Write for Vec<u8>` never errors
packed.write_u8(entry.state.into()).unwrap();
packed.write_i32::<BigEndian>(entry.mode).unwrap();
packed.write_i32::<BigEndian>(entry.size).unwrap();
packed.write_i32::<BigEndian>(new_mtime).unwrap();
packed
.write_i32::<BigEndian>(new_filename.len() as i32)
.unwrap();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 packed.extend(new_filename)
}
if packed.len() != expected_size {
Simon Sapin
rust: Replace DirstatePackError with HgError...
r47168 return Err(HgError::CorruptedRepository(format!(
"bad dirstate size: {} != {}",
expected_size,
packed.len()
)));
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 Ok(packed)
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 /// `now` is the duration in seconds since the Unix epoch
#[cfg(feature = "dirstate-tree")]
pub fn pack_dirstate(
state_map: &mut StateMap,
copy_map: &CopyMap,
parents: DirstateParents,
now: Duration,
) -> Result<Vec<u8>, DirstatePackError> {
// TODO move away from i32 before 2038.
let now: i32 = now.as_secs().try_into().expect("time overflow");
let expected_size: usize = state_map
.iter()
.map(|(filename, _)| {
let mut length = MIN_ENTRY_SIZE + filename.len();
if let Some(copy) = copy_map.get(&filename) {
length += copy.len() + 1;
}
length
})
.sum();
let expected_size = expected_size + PARENT_SIZE * 2;
let mut packed = Vec::with_capacity(expected_size);
let mut new_state_map = vec![];
packed.extend(&parents.p1);
packed.extend(&parents.p2);
for (filename, entry) in state_map.iter() {
let new_filename = filename.to_owned();
let mut new_mtime: i32 = entry.mtime;
if entry.state == EntryState::Normal && entry.mtime == now {
// The file was last modified "simultaneously" with the current
// write to dirstate (i.e. within the same second for file-
// systems with a granularity of 1 sec). This commonly happens
// for at least a couple of files on 'update'.
// The user could change the file without changing its size
// within the same second. Invalidate the file's mtime in
// dirstate, forcing future 'status' calls to compare the
// contents of the file if the size is the same. This prevents
// mistakenly treating such files as clean.
new_mtime = -1;
new_state_map.push((
filename.to_owned(),
DirstateEntry {
mtime: new_mtime,
..entry
},
));
}
let mut new_filename = new_filename.into_vec();
if let Some(copy) = copy_map.get(&filename) {
new_filename.push(b'\0');
new_filename.extend(copy.bytes());
}
packed.write_u8(entry.state.into())?;
packed.write_i32::<BigEndian>(entry.mode)?;
packed.write_i32::<BigEndian>(entry.size)?;
packed.write_i32::<BigEndian>(new_mtime)?;
packed.write_i32::<BigEndian>(new_filename.len() as i32)?;
packed.extend(new_filename)
}
if packed.len() != expected_size {
return Err(DirstatePackError::BadSize(expected_size, packed.len()));
}
state_map.extend(new_state_map);
Ok(packed)
}
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
#[cfg(test)]
mod tests {
use super::*;
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 use crate::{utils::hg_path::HgPathBuf, FastHashMap};
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 use pretty_assertions::assert_eq;
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
#[test]
fn test_pack_dirstate_empty() {
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 let mut state_map = StateMap::default();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let copymap = FastHashMap::default();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let parents = DirstateParents {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let now = Duration::new(15000000, 0);
let expected = b"1234567891011121314100000000000000000000".to_vec();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
assert_eq!(
expected,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 pack_dirstate(&mut state_map, &copymap, parents, now).unwrap()
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 );
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993
assert!(state_map.is_empty())
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 }
#[test]
fn test_pack_dirstate_one_entry() {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let expected_state_map: StateMap = [(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 0,
mtime: 791231220,
},
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 )]
.iter()
.cloned()
.collect();
let mut state_map = expected_state_map.clone();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let copymap = FastHashMap::default();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let parents = DirstateParents {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let now = Duration::new(15000000, 0);
let expected = [
49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49,
51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47,
41, 58, 244, 0, 0, 0, 2, 102, 49,
]
.to_vec();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
assert_eq!(
expected,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 pack_dirstate(&mut state_map, &copymap, parents, now).unwrap()
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 );
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 assert_eq!(expected_state_map, state_map);
}
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 #[test]
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 fn test_pack_dirstate_one_entry_with_copy() {
let expected_state_map: StateMap = [(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 0,
mtime: 791231220,
},
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 )]
.iter()
.cloned()
.collect();
let mut state_map = expected_state_map.clone();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let mut copymap = FastHashMap::default();
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 copymap.insert(
HgPathBuf::from_bytes(b"f1"),
HgPathBuf::from_bytes(b"copyname"),
);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let parents = DirstateParents {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let now = Duration::new(15000000, 0);
let expected = [
49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49,
51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47,
41, 58, 244, 0, 0, 0, 11, 102, 49, 0, 99, 111, 112, 121, 110, 97,
109, 101,
]
.to_vec();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
assert_eq!(
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 expected,
pack_dirstate(&mut state_map, &copymap, parents, now).unwrap()
);
assert_eq!(expected_state_map, state_map);
}
#[test]
fn test_parse_pack_one_entry_with_copy() {
let mut state_map: StateMap = [(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 mode: 0o644,
size: 0,
mtime: 791231220,
},
)]
.iter()
.cloned()
.collect();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let mut copymap = FastHashMap::default();
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 copymap.insert(
HgPathBuf::from_bytes(b"f1"),
HgPathBuf::from_bytes(b"copyname"),
);
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let parents = DirstateParents {
p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
};
let now = Duration::new(15000000, 0);
let result =
pack_dirstate(&mut state_map, &copymap, parents.clone(), now)
.unwrap();
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 let (new_parents, entries, copies) =
parse_dirstate(result.as_slice()).unwrap();
let new_state_map: StateMap = entries
.into_iter()
.map(|(path, entry)| (path.to_owned(), entry))
.collect();
let new_copy_map: CopyMap = copies
.into_iter()
.map(|(path, copy)| (path.to_owned(), copy.to_owned()))
.collect();
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 assert_eq!(
(parents, state_map, copymap),
(new_parents, new_state_map, new_copy_map)
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 )
}
#[test]
fn test_parse_pack_multiple_entries_with_copy() {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let mut state_map: StateMap = [
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 (
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 0,
mtime: 791231220,
},
),
(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f2"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Merged,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o777,
size: 1000,
mtime: 791231220,
},
),
(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f3"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Removed,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 234553,
mtime: 791231220,
},
),
(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f4\xF6"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Added,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: -1,
mtime: -1,
},
),
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 ]
.iter()
.cloned()
.collect();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let mut copymap = FastHashMap::default();
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 copymap.insert(
HgPathBuf::from_bytes(b"f1"),
HgPathBuf::from_bytes(b"copyname"),
);
copymap.insert(
HgPathBuf::from_bytes(b"f4\xF6"),
HgPathBuf::from_bytes(b"copyname2"),
);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let parents = DirstateParents {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let now = Duration::new(15000000, 0);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let result =
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 pack_dirstate(&mut state_map, &copymap, parents.clone(), now)
.unwrap();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 let (new_parents, entries, copies) =
parse_dirstate(result.as_slice()).unwrap();
let new_state_map: StateMap = entries
.into_iter()
.map(|(path, entry)| (path.to_owned(), entry))
.collect();
let new_copy_map: CopyMap = copies
.into_iter()
.map(|(path, copy)| (path.to_owned(), copy.to_owned()))
.collect();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 assert_eq!(
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 (parents, state_map, copymap),
(new_parents, new_state_map, new_copy_map)
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 )
}
#[test]
/// https://www.mercurial-scm.org/repo/hg/rev/af3f26b6bba4
fn test_parse_pack_one_entry_with_copy_and_time_conflict() {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let mut state_map: StateMap = [(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 0,
mtime: 15000000,
},
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 )]
.iter()
.cloned()
.collect();
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let mut copymap = FastHashMap::default();
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 copymap.insert(
HgPathBuf::from_bytes(b"f1"),
HgPathBuf::from_bytes(b"copyname"),
);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let parents = DirstateParents {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 p1: *b"12345678910111213141",
p2: *b"00000000000000000000",
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 };
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let now = Duration::new(15000000, 0);
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 let result =
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 pack_dirstate(&mut state_map, &copymap, parents.clone(), now)
.unwrap();
Antoine Cezar
hg-core: make parse_dirstate return references rather than update hashmaps...
r45916 let (new_parents, entries, copies) =
parse_dirstate(result.as_slice()).unwrap();
let new_state_map: StateMap = entries
.into_iter()
.map(|(path, entry)| (path.to_owned(), entry))
.collect();
let new_copy_map: CopyMap = copies
.into_iter()
.map(|(path, copy)| (path.to_owned(), copy.to_owned()))
.collect();
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617
assert_eq!(
(
parents,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 [(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(b"f1"),
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 DirstateEntry {
Raphaël Gomès
rust-dirstate: use EntryState enum instead of literals...
r42994 state: EntryState::Normal,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 mode: 0o644,
size: 0,
mtime: -1
}
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 )]
.iter()
.cloned()
.collect::<StateMap>(),
copymap,
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 ),
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 (new_parents, new_state_map, new_copy_map)
Raphaël Gomès
rust-dirstate: create dirstate submodule...
r42617 )
}
}