Skip to content

Commit 8826502

Browse files
committed
added support for share-safe requirement, options
1 parent f34c83c commit 8826502

File tree

7 files changed

+104
-46
lines changed

7 files changed

+104
-46
lines changed

Cargo.toml

+11-11
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = """
44
Mercurial repository changelog parser. It allows to get any revision
55
with creation date, user, parents, branch and files.
66
"""
7-
edition = "2018"
7+
edition = "2021"
88
homepage = "https://github.com/kilork/hg-parser"
99
keywords = ["hg", "mercurial", "parser"]
1010
license = "GPL-2.0-or-later"
@@ -14,14 +14,14 @@ version = "0.8.0"
1414
rust-version = "1.78"
1515

1616
[dependencies]
17-
bitflags = {version = "2.5", default-features = false}
18-
byteorder = {version = "1.3", default-features = false}
19-
chrono = {version = "0.4", features = ["clock"], default-features = false}
17+
bitflags = { version = "2.5", default-features = false }
18+
byteorder = { version = "1.3", default-features = false }
19+
chrono = { version = "0.4", features = ["clock"], default-features = false }
2020
flate2 = "1.0"
21-
lazy_static = {version = "1.4", default-features = false}
22-
lru-cache = {version = "0.1", default-features = false}
23-
nom = {version = "7.1", default-features = false, features = ["alloc"]}
24-
ordered-parallel-iterator = {version = "0.2", default-features = false}
25-
rayon = {version = "1.4", default-features = false}
26-
sha-1 = {version = "0.10", default-features = false}
27-
thiserror = "1"
21+
lazy_static = { version = "1.4", default-features = false }
22+
lru-cache = { version = "0.1", default-features = false }
23+
nom = { version = "7.1", default-features = false, features = ["alloc"] }
24+
ordered-parallel-iterator = { version = "0.2", default-features = false }
25+
rayon = { version = "1.4", default-features = false }
26+
sha-1 = { version = "0.10", default-features = false }
27+
thiserror = "1"

README.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ hg-parser = "0.8"
1313

1414
### Use case - Analyse revision log and export to ```git fast-import``` format
1515

16-
```rust#ignore
17-
use hg_parser::{file_content, FileType, ManifestEntryDetails, MercurialRepository, Revision};
16+
```rust, no_run
17+
use std::{
18+
env::args,
19+
io::Write,
20+
path::{Path, PathBuf},
21+
string::ParseError,
22+
time::Instant,
23+
};
1824
19-
use std::env::args;
20-
use std::io::Write;
21-
use std::path::{Path, PathBuf};
22-
use std::string::ParseError;
23-
use std::time::Instant;
25+
use hg_parser::{file_content, FileType, ManifestEntryDetails, MercurialRepository, Revision};
2426
2527
fn main() -> Result<(), Error> {
2628
let path: PathBuf = args().nth(1).expect("path not provided").parse()?;

examples/git-fast-import.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use hg_parser::{file_content, FileType, ManifestEntryDetails, MercurialRepository, Revision};
1+
use std::{
2+
env::args,
3+
io::Write,
4+
path::{Path, PathBuf},
5+
string::ParseError,
6+
time::Instant,
7+
};
28

3-
use std::env::args;
4-
use std::io::Write;
5-
use std::path::{Path, PathBuf};
6-
use std::string::ParseError;
7-
use std::time::Instant;
9+
use hg_parser::{file_content, FileType, ManifestEntryDetails, MercurialRepository, Revision};
810

911
fn main() -> Result<(), Error> {
1012
let path: PathBuf = args().nth(1).expect("path not provided").parse()?;

src/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::types::RepositoryRequire;
2+
13
#[derive(Debug, thiserror::Error)]
24
pub enum ErrorKind {
35
/// Parser failed.
@@ -20,7 +22,7 @@ pub enum ErrorKind {
2022
InvalidDateTime(String),
2123
/// Requirement in ``.hg/requires`` is not supported.
2224
#[error("unknown requirement {0}")]
23-
UnknownRequirement(String),
25+
UnknownRequirement(RepositoryRequire),
2426
/// Manifest issue.
2527
#[error("manifest issue {0}")]
2628
Manifest(String),

src/lib.rs

+33-8
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,23 @@ mod revisionlog;
2222
mod types;
2323

2424
use cache::{Cachable, Cache};
25-
pub use changeset::*;
26-
pub use error::ErrorKind;
2725
use manifest::Manifest;
2826
use path::{fncache_fsencode, simple_fsencode, MPath, MPathElement};
2927
use revisionlog::RevisionLog;
3028
use types::{MercurialTag, NodeHash, RepositoryRequire};
3129

30+
pub use changeset::*;
31+
pub use error::ErrorKind;
3232
pub use manifest::{FileType, ManifestEntry, ManifestEntryDetails};
3333
pub use types::{Revision, RevisionRange};
3434

35+
/// Options for mercurial repository.
36+
#[derive(Default)]
37+
pub struct MercurialRepositoryOptions {
38+
/// Threat unknown requirements as warnings.
39+
pub ignore_unknown_requirements: bool,
40+
}
41+
3542
#[derive(Debug)]
3643
/// Mercurial repository. Top-level structure for access to change sets and tags.
3744
pub struct MercurialRepository {
@@ -44,9 +51,17 @@ pub struct MercurialRepository {
4451
impl MercurialRepository {
4552
/// Opens `MercurialRepository` at `root_path`.
4653
pub fn open<P: AsRef<Path>>(root_path: P) -> Result<MercurialRepository, ErrorKind> {
54+
Self::open_with_options(root_path, Default::default())
55+
}
56+
57+
/// Opens `MercurialRepository` at `root_path` with options.
58+
pub fn open_with_options<P: AsRef<Path>>(
59+
root_path: P,
60+
options: MercurialRepositoryOptions,
61+
) -> Result<MercurialRepository, ErrorKind> {
4762
let base = root_path.as_ref().join(".hg");
4863

49-
let requires = MercurialRepository::load_requires(&base)?;
64+
let requires = MercurialRepository::load_requires(&base, &options)?;
5065

5166
let store = base.join("store");
5267

@@ -142,13 +157,23 @@ impl MercurialRepository {
142157

143158
fn load_requires<P: AsRef<Path>>(
144159
path: P,
145-
) -> Result<HashSet<RepositoryRequire>, std::io::Error> {
160+
options: &MercurialRepositoryOptions,
161+
) -> Result<HashSet<RepositoryRequire>, ErrorKind> {
146162
let requires_path = path.as_ref().join("requires");
147163
let file = File::open(requires_path)?;
148-
Ok(BufReader::new(file)
149-
.lines()
150-
.map(|x| x.unwrap().parse().expect("could not parse requirement"))
151-
.collect())
164+
let lines = BufReader::new(file).lines().map_while(Result::ok);
165+
if options.ignore_unknown_requirements {
166+
lines
167+
.map(|x| match x.parse() {
168+
Err(ErrorKind::UnknownRequirement(r)) => Ok(r),
169+
other => other,
170+
})
171+
.collect()
172+
} else {
173+
Ok(lines
174+
.map(|x| x.parse().expect("could not parse requirement"))
175+
.collect())
176+
}
152177
}
153178

154179
fn fsencode_path(&self, elements: &[MPathElement]) -> PathBuf {

src/types.rs

+39-12
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
use std::{
2-
fmt::{self, Debug, Display},
2+
fmt::{self, Display},
33
ops::{Add, Range, Sub},
44
rc::Rc,
55
str::FromStr,
66
sync::Arc,
77
};
88

9-
/// Repository requires flags.
10-
/// Repositories contain a file (``.hg/requires``) containing a list of
11-
/// features/capabilities that are *required* for clients to interface
12-
/// with the repository.
139
use super::error::ErrorKind;
1410
use bitflags::bitflags;
1511
use chrono::{
1612
DateTime as ChronoDateTime, FixedOffset, Local, LocalResult, NaiveDateTime, TimeZone,
1713
};
1814
use sha1::{Digest, Sha1};
19-
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
20-
pub(crate) enum RepositoryRequire {
15+
16+
/// Repository requires flags.
17+
/// Repositories contain a file (``.hg/requires``) containing a list of
18+
/// features/capabilities that are *required* for clients to interface
19+
/// with the repository.
20+
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
21+
pub enum RepositoryRequire {
2122
/// When present, revlogs are version 1 (**RevlogNG**).
2223
Revlogv1,
2324
/// The **store** repository layout is used.
@@ -45,6 +46,10 @@ pub(crate) enum RepositoryRequire {
4546
TreeManifest,
4647
/// The working directory is sparse (only contains a subset of files).
4748
ExpSparse,
49+
/// Safe behaviour for all shares that access a repository.
50+
ShareSafe,
51+
/// Unknown requirement.
52+
Unknown(String),
4853
}
4954

5055
impl FromStr for RepositoryRequire {
@@ -64,7 +69,29 @@ impl FromStr for RepositoryRequire {
6469
"manifestv2" => Ok(Manifestv2),
6570
"treemanifest" => Ok(TreeManifest),
6671
"exp-sparse" => Ok(ExpSparse),
67-
other => Err(ErrorKind::UnknownRequirement(other.into())),
72+
"share-safe" => Ok(ShareSafe),
73+
other => Err(ErrorKind::UnknownRequirement(Self::Unknown(other.into()))),
74+
}
75+
}
76+
}
77+
78+
impl std::fmt::Display for RepositoryRequire {
79+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80+
use RepositoryRequire::*;
81+
match self {
82+
Revlogv1 => "revlogv1".fmt(f),
83+
Store => "store".fmt(f),
84+
FnCache => "fncache".fmt(f),
85+
Shared => "shared".fmt(f),
86+
RelShared => "relshared".fmt(f),
87+
DotEncode => "dotencode".fmt(f),
88+
ParentDelta => "parentdelta".fmt(f),
89+
GeneralDelta => "generaldelta".fmt(f),
90+
Manifestv2 => "manifestv2".fmt(f),
91+
TreeManifest => "treemanifest".fmt(f),
92+
ExpSparse => "exp-sparse".fmt(f),
93+
ShareSafe => "share-safe".fmt(f),
94+
Unknown(s) => s.fmt(f),
6895
}
6996
}
7097
}
@@ -81,7 +108,7 @@ impl Revision {
81108

82109
/// Return an open ended iterator from index.
83110
pub fn range(self) -> RevisionRange {
84-
RevisionRange(self.0, std::u32::MAX)
111+
RevisionRange(self.0, u32::MAX)
85112
}
86113
}
87114

@@ -221,13 +248,13 @@ impl AsRef<[u8]> for NodeHash {
221248
}
222249
}
223250

224-
impl Display for NodeHash {
251+
impl std::fmt::Display for NodeHash {
225252
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
226253
Display::fmt(&self.to_hex(), fmt)
227254
}
228255
}
229256

230-
impl Debug for NodeHash {
257+
impl std::fmt::Debug for NodeHash {
231258
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
232259
write!(fmt, "NodeHash({})", self)
233260
}
@@ -303,7 +330,7 @@ impl Fragment {
303330
}
304331
}
305332

306-
impl Debug for Fragment {
333+
impl std::fmt::Debug for Fragment {
307334
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
308335
write!(
309336
fmt,

templates/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ hg-parser = "0.8"
1313

1414
### Use case - Analyse revision log and export to ```git fast-import``` format
1515

16-
{{ codeblock "rust#ignore" ( read_to_str "examples/git-fast-import.rs" ) }}
16+
{{ codeblock "rust, no_run" ( read_to_str "examples/git-fast-import.rs" ) }}
1717

1818
## Implementation details
1919

0 commit comments

Comments
 (0)