Commit aadede8d authored by Arseniy Alekseyev's avatar Arseniy Alekseyev
Browse files

rhg: do not fail when the repo is empty

Differential Revision: https://phab.mercurial-scm.org/D11651
parent 61ce70fd420e
Pipeline #27723 failed with stages
in 41 minutes and 4 seconds
......@@ -70,15 +70,21 @@ impl Revlog {
data_path: Option<&Path>,
) -> Result<Self, HgError> {
let index_path = index_path.as_ref();
let index_mmap = repo.store_vfs().mmap_open(&index_path)?;
let version = get_version(&index_mmap)?;
if version != 1 {
// A proper new version should have had a repo/store requirement.
return Err(HgError::corrupted("corrupted revlog"));
}
let index = Index::new(Box::new(index_mmap))?;
let index = {
match repo.store_vfs().mmap_open_opt(&index_path)? {
None => Index::new(Box::new(vec![])),
Some(index_mmap) => {
let version = get_version(&index_mmap)?;
if version != 1 {
// A proper new version should have had a repo/store requirement.
return Err(HgError::corrupted("corrupted revlog"));
}
let index = Index::new(Box::new(index_mmap))?;
Ok(index)
}
}
}?;
let default_data_path = index_path.with_extension("d");
......@@ -418,6 +424,6 @@ mod tests {
.with_version(1)
.build();
assert_eq!(get_version(&bytes), 1)
assert_eq!(get_version(&bytes).map_err(|_err|()), Ok(1))
}
}
......@@ -9,6 +9,8 @@ pub struct Vfs<'a> {
pub(crate) base: &'a Path,
}
struct FileNotFound(std::io::Error, PathBuf);
impl Vfs<'_> {
pub fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf {
self.base.join(relative_path)
......@@ -22,16 +24,41 @@ impl Vfs<'_> {
std::fs::read(&path).when_reading_file(&path)
}
pub fn mmap_open(
fn mmap_open_gen(
&self,
relative_path: impl AsRef<Path>,
) -> Result<Mmap, HgError> {
let path = self.base.join(relative_path);
let file = std::fs::File::open(&path).when_reading_file(&path)?;
) -> Result<Result<Mmap, FileNotFound>, HgError> {
let path = self.join(relative_path);
let file = match std::fs::File::open(&path) {
Err(err) => {
if let ErrorKind::NotFound = err.kind() {
return Ok(Err(FileNotFound(err, path)));
};
return (Err(err)).when_reading_file(&path);
}
Ok(file) => file,
};
// TODO: what are the safety requirements here?
let mmap = unsafe { MmapOptions::new().map(&file) }
.when_reading_file(&path)?;
Ok(mmap)
Ok(Ok(mmap))
}
pub fn mmap_open_opt(
&self,
relative_path: impl AsRef<Path>,
) -> Result<Option<Mmap>, HgError> {
self.mmap_open_gen(relative_path).map(|res| res.ok())
}
pub fn mmap_open(
&self,
relative_path: impl AsRef<Path>,
) -> Result<Mmap, HgError> {
match self.mmap_open_gen(relative_path)? {
Err(FileNotFound(err, path)) => Err(err).when_reading_file(&path),
Ok(res) => Ok(res),
}
}
pub fn rename(
......
Create a repo such that the changelog entry refers to a null manifest node:
Test null revisions (node 0000000000000000000000000000000000000000, aka rev -1)
in various circumstances.
Make an empty repo:
$ hg init a
$ cd a
$ hg log
$ touch x
$ hg add x
$ hg commit -m "init"
$ hg rm x
$ hg commit -q --amend
$ wc -c < .hg/store/00manifest.i
0
$ hg files -r 0000000000000000000000000000000000000000
[1]
$ hg files -r .
[1]
Add an empty commit (this makes the changelog refer to a null manifest node):
Make sure that the manifest can be read (and is empty):
$ hg commit -m "init" --config ui.allowemptycommit=true
$ hg --config rhg.on-unsupported=abort files -r .
$ hg files -r .
[1]
Test a null changelog rev, too:
Strip that empty commit (this makes the changelog file empty, as opposed to missing):
$ hg --config 'extensions.strip=' strip . > /dev/null
$ hg --config rhg.on-unsupported=abort files -r 0000000000000000000000000000000000000000
$ hg files -r .
[1]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment