Skip to content

Commit 7523e5c

Browse files
committed
feat!: support for precompose_unicode, which is now an extra argument in the Store constructor.
1 parent 47e2fec commit 7523e5c

File tree

10 files changed

+84
-22
lines changed

10 files changed

+84
-22
lines changed

gix-ref/src/store/file/loose/iter.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ pub(in crate::store_impl::file) struct SortedLoosePaths {
1313
}
1414

1515
impl SortedLoosePaths {
16-
pub fn at(path: &Path, base: PathBuf, filename_prefix: Option<BString>) -> Self {
16+
pub fn at(path: &Path, base: PathBuf, filename_prefix: Option<BString>, precompose_unicode: bool) -> Self {
1717
SortedLoosePaths {
1818
base,
1919
filename_prefix,
2020
file_walk: path.is_dir().then(|| {
2121
// serial iteration as we expect most refs in packed-refs anyway.
22-
gix_features::fs::walkdir_sorted_new(path, gix_features::fs::walkdir::Parallelism::Serial).into_iter()
22+
gix_features::fs::walkdir_sorted_new(
23+
path,
24+
gix_features::fs::walkdir::Parallelism::Serial,
25+
precompose_unicode,
26+
)
27+
.into_iter()
2328
}),
2429
}
2530
}
@@ -32,10 +37,10 @@ impl Iterator for SortedLoosePaths {
3237
for entry in self.file_walk.as_mut()?.by_ref() {
3338
match entry {
3439
Ok(entry) => {
35-
if !entry.file_type().is_file() {
40+
if !entry.file_type().map_or(false, |ft| ft.is_file()) {
3641
continue;
3742
}
38-
let full_path = entry.path().to_owned();
43+
let full_path = entry.path().into_owned();
3944
if let Some((prefix, name)) = self
4045
.filename_prefix
4146
.as_deref()

gix-ref/src/store/file/loose/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ mod init {
3333
/// Create a new instance at the given `git_dir`, which commonly is a standard git repository with a
3434
/// `refs/` subdirectory.
3535
/// The `object_hash` defines which kind of hash we should recognize.
36-
pub fn at(git_dir: PathBuf, write_reflog: file::WriteReflog, object_hash: gix_hash::Kind) -> Self {
36+
/// `precompose_unicode` is used to set to the value of [`Self::precompose_unicode].
37+
pub fn at(
38+
git_dir: PathBuf,
39+
write_reflog: file::WriteReflog,
40+
object_hash: gix_hash::Kind,
41+
precompose_unicode: bool,
42+
) -> Self {
3743
file::Store {
3844
git_dir,
3945
packed_buffer_mmap_threshold: packed_refs_mmap_threshold(),
@@ -42,6 +48,7 @@ mod init {
4248
namespace: None,
4349
packed: gix_fs::SharedFileSnapshotMut::new().into(),
4450
object_hash,
51+
precompose_unicode,
4552
}
4653
}
4754

@@ -52,6 +59,7 @@ mod init {
5259
common_dir: PathBuf,
5360
write_reflog: file::WriteReflog,
5461
object_hash: gix_hash::Kind,
62+
precompose_unicode: bool,
5563
) -> Self {
5664
file::Store {
5765
git_dir,
@@ -61,6 +69,7 @@ mod init {
6169
namespace: None,
6270
packed: gix_fs::SharedFileSnapshotMut::new().into(),
6371
object_hash,
72+
precompose_unicode,
6473
}
6574
}
6675
}

gix-ref/src/store/file/loose/reflog/create_or_update/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn hex_to_id(hex: &str) -> gix_hash::ObjectId {
1717

1818
fn empty_store(writemode: WriteReflog) -> Result<(TempDir, file::Store)> {
1919
let dir = TempDir::new()?;
20-
let store = file::Store::at(dir.path().into(), writemode, gix_hash::Kind::Sha1);
20+
let store = file::Store::at(dir.path().into(), writemode, gix_hash::Kind::Sha1, false);
2121
Ok((dir, store))
2222
}
2323

gix-ref/src/store/file/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pub struct Store {
2727
pub write_reflog: WriteReflog,
2828
/// The namespace to use for edits and reads
2929
pub namespace: Option<Namespace>,
30+
/// If set, we will convert decomposed unicode like `a\u308` into precomposed unicode like `ä` when reading
31+
/// ref names from disk.
32+
pub precompose_unicode: bool,
3033
/// A packed buffer which can be mapped in one version and shared as such.
3134
/// It's updated only in one spot, which is prior to reading it based on file stamps.
3235
/// Doing it like this has the benefit of being able to hand snapshots out to people without blocking others from updating it.

gix-ref/src/store/file/overlay_iter.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,15 +220,18 @@ impl file::Store {
220220
pub(crate) enum IterInfo<'a> {
221221
Base {
222222
base: &'a Path,
223+
precompose_unicode: bool,
223224
},
224225
BaseAndIterRoot {
225226
base: &'a Path,
226227
iter_root: PathBuf,
227228
prefix: Cow<'a, Path>,
229+
precompose_unicode: bool,
228230
},
229231
PrefixAndBase {
230232
base: &'a Path,
231233
prefix: &'a Path,
234+
precompose_unicode: bool,
232235
},
233236
ComputedIterationRoot {
234237
/// The root to iterate over
@@ -239,6 +242,8 @@ pub(crate) enum IterInfo<'a> {
239242
prefix: Cow<'a, Path>,
240243
/// The remainder of the prefix that wasn't a valid path
241244
remainder: Option<BString>,
245+
/// If `true`, we will convert decomposed into precomposed unicode.
246+
precompose_unicode: bool,
242247
},
243248
}
244249

@@ -255,24 +260,33 @@ impl<'a> IterInfo<'a> {
255260

256261
fn into_iter(self) -> Peekable<SortedLoosePaths> {
257262
match self {
258-
IterInfo::Base { base } => SortedLoosePaths::at(&base.join("refs"), base.into(), None),
263+
IterInfo::Base {
264+
base,
265+
precompose_unicode,
266+
} => SortedLoosePaths::at(&base.join("refs"), base.into(), None, precompose_unicode),
259267
IterInfo::BaseAndIterRoot {
260268
base,
261269
iter_root,
262270
prefix: _,
263-
} => SortedLoosePaths::at(&iter_root, base.into(), None),
264-
IterInfo::PrefixAndBase { base, prefix } => SortedLoosePaths::at(&base.join(prefix), base.into(), None),
271+
precompose_unicode,
272+
} => SortedLoosePaths::at(&iter_root, base.into(), None, precompose_unicode),
273+
IterInfo::PrefixAndBase {
274+
base,
275+
prefix,
276+
precompose_unicode,
277+
} => SortedLoosePaths::at(&base.join(prefix), base.into(), None, precompose_unicode),
265278
IterInfo::ComputedIterationRoot {
266279
iter_root,
267280
base,
268281
prefix: _,
269282
remainder,
270-
} => SortedLoosePaths::at(&iter_root, base.into(), remainder),
283+
precompose_unicode,
284+
} => SortedLoosePaths::at(&iter_root, base.into(), remainder, precompose_unicode),
271285
}
272286
.peekable()
273287
}
274288

275-
fn from_prefix(base: &'a Path, prefix: Cow<'a, Path>) -> std::io::Result<Self> {
289+
fn from_prefix(base: &'a Path, prefix: Cow<'a, Path>, precompose_unicode: bool) -> std::io::Result<Self> {
276290
if prefix.is_absolute() {
277291
return Err(std::io::Error::new(
278292
std::io::ErrorKind::InvalidInput,
@@ -292,6 +306,7 @@ impl<'a> IterInfo<'a> {
292306
base,
293307
iter_root,
294308
prefix,
309+
precompose_unicode,
295310
})
296311
} else {
297312
let filename_prefix = iter_root
@@ -314,6 +329,7 @@ impl<'a> IterInfo<'a> {
314329
prefix,
315330
iter_root,
316331
remainder: filename_prefix,
332+
precompose_unicode,
317333
})
318334
}
319335
}
@@ -332,16 +348,24 @@ impl file::Store {
332348
IterInfo::PrefixAndBase {
333349
base: self.git_dir(),
334350
prefix: namespace.to_path(),
351+
precompose_unicode: self.precompose_unicode,
335352
},
336353
self.common_dir().map(|base| IterInfo::PrefixAndBase {
337354
base,
338355
prefix: namespace.to_path(),
356+
precompose_unicode: self.precompose_unicode,
339357
}),
340358
packed,
341359
),
342360
None => self.iter_from_info(
343-
IterInfo::Base { base: self.git_dir() },
344-
self.common_dir().map(|base| IterInfo::Base { base }),
361+
IterInfo::Base {
362+
base: self.git_dir(),
363+
precompose_unicode: self.precompose_unicode,
364+
},
365+
self.common_dir().map(|base| IterInfo::Base {
366+
base,
367+
precompose_unicode: self.precompose_unicode,
368+
}),
345369
packed,
346370
),
347371
}
@@ -357,19 +381,20 @@ impl file::Store {
357381
) -> std::io::Result<LooseThenPacked<'p, 's>> {
358382
match self.namespace.as_ref() {
359383
None => {
360-
let git_dir_info = IterInfo::from_prefix(self.git_dir(), prefix.into())?;
384+
let git_dir_info = IterInfo::from_prefix(self.git_dir(), prefix.into(), self.precompose_unicode)?;
361385
let common_dir_info = self
362386
.common_dir()
363-
.map(|base| IterInfo::from_prefix(base, prefix.into()))
387+
.map(|base| IterInfo::from_prefix(base, prefix.into(), self.precompose_unicode))
364388
.transpose()?;
365389
self.iter_from_info(git_dir_info, common_dir_info, packed)
366390
}
367391
Some(namespace) => {
368392
let prefix = namespace.to_owned().into_namespaced_prefix(prefix);
369-
let git_dir_info = IterInfo::from_prefix(self.git_dir(), prefix.clone().into())?;
393+
let git_dir_info =
394+
IterInfo::from_prefix(self.git_dir(), prefix.clone().into(), self.precompose_unicode)?;
370395
let common_dir_info = self
371396
.common_dir()
372-
.map(|base| IterInfo::from_prefix(base, prefix.into()))
397+
.map(|base| IterInfo::from_prefix(base, prefix.into(), self.precompose_unicode))
373398
.transpose()?;
374399
self.iter_from_info(git_dir_info, common_dir_info, packed)
375400
}

gix-ref/src/store/general/init.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,18 @@ impl crate::Store {
2121
/// Create a new store at the given location, typically the `.git/` directory.
2222
///
2323
/// `object_hash` defines the kind of hash to assume when dealing with refs.
24-
pub fn at(git_dir: PathBuf, reflog_mode: WriteReflog, object_hash: gix_hash::Kind) -> Result<Self, Error> {
24+
/// `precompose_unicode` is used to set to the value of [`crate::file::Store::precompose_unicode].
25+
pub fn at(
26+
git_dir: PathBuf,
27+
reflog_mode: WriteReflog,
28+
object_hash: gix_hash::Kind,
29+
precompose_unicode: bool,
30+
) -> Result<Self, Error> {
2531
// for now, just try to read the directory - later we will do that naturally as we have to figure out if it's a ref-table or not.
2632
std::fs::read_dir(&git_dir)?;
2733
Ok(crate::Store {
2834
inner: crate::store::State::Loose {
29-
store: file::Store::at(git_dir, reflog_mode, object_hash),
35+
store: file::Store::at(git_dir, reflog_mode, object_hash, precompose_unicode),
3036
},
3137
})
3238
}

gix-ref/tests/file/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn store_at(name: &str) -> crate::Result<Store> {
1919
path.join(".git"),
2020
gix_ref::store::WriteReflog::Normal,
2121
gix_hash::Kind::Sha1,
22+
false,
2223
))
2324
}
2425

@@ -27,7 +28,12 @@ fn store_writable(name: &str) -> crate::Result<(gix_testtools::tempfile::TempDir
2728
let git_dir = dir.path().join(".git");
2829
Ok((
2930
dir,
30-
Store::at(git_dir, gix_ref::store::WriteReflog::Normal, gix_hash::Kind::Sha1),
31+
Store::at(
32+
git_dir,
33+
gix_ref::store::WriteReflog::Normal,
34+
gix_hash::Kind::Sha1,
35+
false,
36+
),
3137
))
3238
}
3339

gix-ref/tests/file/store/reflog.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ fn store() -> crate::Result<crate::file::Store> {
33
gix_testtools::scripted_fixture_read_only_standalone("make_repo_for_reflog.sh")?.join(".git"),
44
gix_ref::store::WriteReflog::Disable,
55
gix_hash::Kind::Sha1,
6+
false,
67
))
78
}
89

gix-ref/tests/file/transaction/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub(crate) mod prepare_and_commit {
2828
dir.path().into(),
2929
gix_ref::store::WriteReflog::Normal,
3030
gix_hash::Kind::Sha1,
31+
false,
3132
);
3233
Ok((dir, store))
3334
}

gix-ref/tests/file/worktree.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn main_store(
2929
let (dir, tmp) = dir(packed, writable)?;
3030
let git_dir = dir.join("repo").join(".git");
3131
Ok((
32-
gix_ref::file::Store::at(git_dir.clone(), Default::default(), Default::default()),
32+
gix_ref::file::Store::at(git_dir.clone(), Default::default(), Default::default(), false),
3333
gix_odb::at(git_dir.join("objects"))?,
3434
tmp,
3535
))
@@ -50,7 +50,13 @@ fn worktree_store(
5050
.into_repository_and_work_tree_directories();
5151
let common_dir = git_dir.join("../..");
5252
Ok((
53-
gix_ref::file::Store::for_linked_worktree(git_dir, common_dir.clone(), Default::default(), Default::default()),
53+
gix_ref::file::Store::for_linked_worktree(
54+
git_dir,
55+
common_dir.clone(),
56+
Default::default(),
57+
Default::default(),
58+
false,
59+
),
5460
gix_odb::at(common_dir.join("objects"))?,
5561
tmp,
5662
))

0 commit comments

Comments
 (0)