Skip to content

Commit bad9a79

Browse files
ByronEliahKagan
andcommitted
Apply suggestions from code review
Co-authored-by: Eliah Kagan <[email protected]>
1 parent 4c684ca commit bad9a79

File tree

5 files changed

+35
-25
lines changed

5 files changed

+35
-25
lines changed

gix-fs/src/stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub trait Delegate {
2525
/// Called whenever we push a directory on top of the stack, and after the respective call to [`push()`](Self::push).
2626
///
2727
/// It is only called if the currently acted on path is a directory in itself, which is determined by knowing
28-
/// that it's not the last component fo the path.
28+
/// that it's not the last component of the path.
2929
/// Use [`Stack::current()`] to see the directory.
3030
fn push_directory(&mut self, stack: &Stack) -> std::io::Result<()>;
3131

gix-index/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub struct AccelerateLookup<'a> {
122122
/// This means that before using these paths to recreate files on disk, *they must be validated*.
123123
///
124124
/// It's notable that it's possible to manufacture tree objects which contain names like `.git/hooks/pre-commit`
125-
/// which then will look like `.git/hooiks/pre-commit` in the index, which doesn't care that the name came from a single
125+
/// which then will look like `.git/hooks/pre-commit` in the index, which doesn't care that the name came from a single
126126
/// tree instead of from trees named `.git`, `hooks` and a blob named `pre-commit`. The effect is still the same - an invalid
127127
/// path is presented in the index and its consumer must validate each path component before usage.
128128
///

gix-validate/src/path.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ pub mod component {
1111
Empty,
1212
#[error("Path separators like / or \\ are not allowed")]
1313
PathSeparator,
14-
#[error("Window path prefixes are not allowed")]
14+
#[error("Windows path prefixes are not allowed")]
1515
WindowsPathPrefix,
1616
#[error("Windows device-names may have side-effects and are not allowed")]
1717
WindowsReservedName,
18-
#[error("Trailing spaces or dots and the following characters are forbidden in Windows paths, along with non-printable ones: <>:\"|?*")]
18+
#[error("Trailing spaces or dots, and the following characters anywhere, are forbidden in Windows paths, along with non-printable ones: <>:\"|?*")]
1919
WindowsIllegalCharacter,
2020
#[error("The .git name may never be used")]
2121
DotGitDir,
@@ -37,7 +37,7 @@ pub mod component {
3737
/// This field is equivalent to `core.protectHFS`.
3838
pub protect_hfs: bool,
3939
/// If `true`, protections for Windows NTFS specific features will be active. This adds special handling
40-
/// for `8.3` filenames and alternate data streams, both of which could be used to mask th etrue name of
40+
/// for `8.3` filenames and alternate data streams, both of which could be used to mask the true name of
4141
/// what would be created on disk.
4242
///
4343
/// This field is equivalent to `core.protectNTFS`.
@@ -64,7 +64,7 @@ pub mod component {
6464

6565
/// Assure the given `input` resembles a valid name for a tree or blob, and in that sense, a path component.
6666
/// `mode` indicates the kind of `input` and it should be `Some` if `input` is the last component in the underlying
67-
/// path. Currently, this is only used to determine if `.gitmodules` is a symlink.
67+
/// path.
6868
///
6969
/// `input` must not make it possible to exit the repository, or to specify absolute paths.
7070
pub fn component(
@@ -148,7 +148,8 @@ fn check_win_devices_and_illegal_characters(input: &BStr) -> Option<component::E
148148
return Some(component::Error::WindowsReservedName);
149149
}
150150
if in3.eq_ignore_ascii_case(b"con")
151-
&& ((input.get(3..6).map_or(false, |n| n.eq_ignore_ascii_case(b"in$")) && is_done_windows(input.get(6..)))
151+
&& (is_done_windows(input.get(3..))
152+
|| (input.get(3..6).map_or(false, |n| n.eq_ignore_ascii_case(b"in$")) && is_done_windows(input.get(6..)))
152153
|| (input.get(3..7).map_or(false, |n| n.eq_ignore_ascii_case(b"out$")) && is_done_windows(input.get(7..))))
153154
{
154155
return Some(component::Error::WindowsReservedName);
@@ -168,22 +169,26 @@ fn is_symlink(mode: Option<component::Mode>) -> bool {
168169

169170
fn is_dot_hfs(input: &BStr, search_case_insensitive: &str) -> bool {
170171
let mut input = input.chars().filter(|c| match *c as u32 {
171-
0x200c | /* ZERO WIDTH NON-JOINER */
172-
0x200d | /* ZERO WIDTH JOINER */
173-
0x200e | /* LEFT-TO-RIGHT MARK */
174-
0x200f | /* RIGHT-TO-LEFT MARK */
175-
0x202a | /* LEFT-TO-RIGHT EMBEDDING */
176-
0x202b | /* RIGHT-TO-LEFT EMBEDDING */
177-
0x202c | /* POP DIRECTIONAL FORMATTING */
178-
0x202d | /* LEFT-TO-RIGHT OVERRIDE */
179-
0x202e | /* RIGHT-TO-LEFT OVERRIDE */
180-
0x206a | /* INHIBIT SYMMETRIC SWAPPING */
181-
0x206b | /* ACTIVATE SYMMETRIC SWAPPING */
182-
0x206c | /* INHIBIT ARABIC FORM SHAPING */
183-
0x206d | /* ACTIVATE ARABIC FORM SHAPING */
184-
0x206e | /* NATIONAL DIGIT SHAPES */
185-
0x206f | /* NOMINAL DIGIT SHAPES */
186-
0xfeff => false, /* ZERO WIDTH NO-BREAK SPACE */
172+
// Case-insensitive HFS+ skips these code points as "ignorable" when comparing filenames. See:
173+
// https://github.com/git/git/commit/6162a1d323d24fd8cbbb1a6145a91fb849b2568f
174+
// https://developer.apple.com/library/archive/technotes/tn/tn1150.html#StringComparisonAlgorithm
175+
// https://github.com/apple-oss-distributions/hfs/blob/main/core/UCStringCompareData.h
176+
0x200c | // ZERO WIDTH NON-JOINER
177+
0x200d | // ZERO WIDTH JOINER
178+
0x200e | // LEFT-TO-RIGHT MARK
179+
0x200f | // RIGHT-TO-LEFT MARK
180+
0x202a | // LEFT-TO-RIGHT EMBEDDING
181+
0x202b | // RIGHT-TO-LEFT EMBEDDING
182+
0x202c | // POP DIRECTIONAL FORMATTING
183+
0x202d | // LEFT-TO-RIGHT OVERRIDE
184+
0x202e | // RIGHT-TO-LEFT OVERRIDE
185+
0x206a | // INHIBIT SYMMETRIC SWAPPING
186+
0x206b | // ACTIVATE SYMMETRIC SWAPPING
187+
0x206c | // INHIBIT ARABIC FORM SHAPING
188+
0x206d | // ACTIVATE ARABIC FORM SHAPING
189+
0x206e | // NATIONAL DIGIT SHAPES
190+
0x206f | // NOMINAL DIGIT SHAPES
191+
0xfeff => false, // ZERO WIDTH NO-BREAK SPACE
187192
_ => true
188193
});
189194
if input.next() != Some('.') {
@@ -278,7 +283,9 @@ fn is_dot_ntfs(input: &BStr, search_case_insensitive: &str, ntfs_shortname_prefi
278283
}
279284
}
280285

286+
/// Check if trailing filename bytes leave a match to special files like `.git` unchanged in NTFS.
281287
fn is_done_ntfs(input: Option<&[u8]>) -> bool {
288+
// Skip spaces and dots. Then return true if we are at the end or a colon.
282289
let Some(input) = input else { return true };
283290
for b in input.bytes() {
284291
if b == b':' {
@@ -291,9 +298,11 @@ fn is_done_ntfs(input: Option<&[u8]>) -> bool {
291298
true
292299
}
293300

301+
/// Check if trailing filename bytes leave a match to Windows reserved device names unchanged.
294302
fn is_done_windows(input: Option<&[u8]>) -> bool {
303+
// Skip spaces. Then return true if we are at the end or a dot or colon.
295304
let Some(input) = input else { return true };
296305
let skip = input.bytes().take_while(|b| *b == b' ').count();
297306
let Some(next) = input.get(skip) else { return true };
298-
!(*next != b'.' && *next != b':')
307+
*next == b'.' || *next == b':'
299308
}

gix-validate/tests/path/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ mod component {
200200
mktest!(lpt_mixed_with_number, b"LPt8", Error::WindowsReservedName);
201201
mktest!(nul_mixed, b"NuL", Error::WindowsReservedName);
202202
mktest!(prn_mixed_with_extension, b"PrN.abc", Error::WindowsReservedName);
203+
mktest!(con, b"CON", Error::WindowsReservedName);
203204
mktest!(
204205
conout_mixed_with_extension,
205206
b"ConOut$ .xyz",

gix/src/attribute_stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl DerefMut for AttributeStack<'_> {
3434
/// Platform retrieval
3535
impl<'repo> AttributeStack<'repo> {
3636
/// Append the `relative` path to the root directory of the cache and load all attribute or ignore files on the way as needed.
37-
/// Use `mode` to specify what kind of item lives at `relative` - directories may match against rules specifically .
37+
/// Use `mode` to specify what kind of item lives at `relative` - directories may match against rules specifically.
3838
/// If `mode` is `None`, the item at `relative` is assumed to be a file.
3939
///
4040
/// The returned platform may be used to access the actual attribute or ignore information.

0 commit comments

Comments
 (0)