--- a/rust/hg-core/src/repo.rs Mon Jun 05 17:29:52 2023 +0200
+++ b/rust/hg-core/src/repo.rs Mon Jun 05 16:43:27 2023 +0200
@@ -238,9 +238,10 @@
/// a dirstate-v2 file will indeed be found, but in rare cases (like the
/// upgrade mechanism being cut short), the on-disk version will be a
/// v1 file.
- /// Semantically, having a requirement only means that a client should be
- /// able to understand the repo *if* it uses the requirement, but not that
- /// the requirement is actually used.
+ /// Semantically, having a requirement only means that a client cannot
+ /// properly understand or properly update the repo if it lacks the support
+ /// for the required feature, but not that that feature is actually used
+ /// in all occasions.
pub fn use_dirstate_v2(&self) -> bool {
self.requirements
.contains(requirements::DIRSTATE_V2_REQUIREMENT)
@@ -287,9 +288,20 @@
let parents = if dirstate.is_empty() {
DirstateParents::NULL
} else if self.use_dirstate_v2() {
- let docket =
- crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
- docket.parents()
+ let docket_res =
+ crate::dirstate_tree::on_disk::read_docket(&dirstate);
+ match docket_res {
+ Ok(docket) => docket.parents(),
+ Err(_) => {
+ log::info!(
+ "Parsing dirstate docket failed, \
+ falling back to dirstate-v1"
+ );
+ *crate::dirstate::parsers::parse_dirstate_parents(
+ &dirstate,
+ )?
+ }
+ }
} else {
*crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?
};
@@ -317,10 +329,30 @@
self.dirstate_parents.set(DirstateParents::NULL);
Ok((identity, None, 0))
} else {
- let docket =
- crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
- self.dirstate_parents.set(docket.parents());
- Ok((identity, Some(docket.uuid.to_owned()), docket.data_size()))
+ let docket_res =
+ crate::dirstate_tree::on_disk::read_docket(&dirstate);
+ match docket_res {
+ Ok(docket) => {
+ self.dirstate_parents.set(docket.parents());
+ Ok((
+ identity,
+ Some(docket.uuid.to_owned()),
+ docket.data_size(),
+ ))
+ }
+ Err(_) => {
+ log::info!(
+ "Parsing dirstate docket failed, \
+ falling back to dirstate-v1"
+ );
+ let parents =
+ *crate::dirstate::parsers::parse_dirstate_parents(
+ &dirstate,
+ )?;
+ self.dirstate_parents.set(parents);
+ Ok((identity, None, 0))
+ }
+ }
}
}
@@ -352,7 +384,13 @@
);
continue;
}
- _ => return Err(e),
+ _ => {
+ log::info!(
+ "Reading dirstate v2 failed, \
+ falling back to v1"
+ );
+ return self.new_dirstate_map_v1();
+ }
},
}
}
@@ -363,23 +401,22 @@
);
Err(DirstateError::Common(error))
} else {
- debug_wait_for_file_or_print(
- self.config(),
- "dirstate.pre-read-file",
- );
- let identity = self.dirstate_identity()?;
- let dirstate_file_contents = self.dirstate_file_contents()?;
- if dirstate_file_contents.is_empty() {
- self.dirstate_parents.set(DirstateParents::NULL);
- Ok(OwningDirstateMap::new_empty(Vec::new()))
- } else {
- let (map, parents) = OwningDirstateMap::new_v1(
- dirstate_file_contents,
- identity,
- )?;
- self.dirstate_parents.set(parents);
- Ok(map)
- }
+ self.new_dirstate_map_v1()
+ }
+ }
+
+ fn new_dirstate_map_v1(&self) -> Result<OwningDirstateMap, DirstateError> {
+ debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file");
+ let identity = self.dirstate_identity()?;
+ let dirstate_file_contents = self.dirstate_file_contents()?;
+ if dirstate_file_contents.is_empty() {
+ self.dirstate_parents.set(DirstateParents::NULL);
+ Ok(OwningDirstateMap::new_empty(Vec::new()))
+ } else {
+ let (map, parents) =
+ OwningDirstateMap::new_v1(dirstate_file_contents, identity)?;
+ self.dirstate_parents.set(parents);
+ Ok(map)
}
}