diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-validate/src | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-validate/src')
-rw-r--r-- | vendor/gix-validate/src/lib.rs | 11 | ||||
-rw-r--r-- | vendor/gix-validate/src/reference.rs | 75 | ||||
-rw-r--r-- | vendor/gix-validate/src/tag.rs | 61 |
3 files changed, 147 insertions, 0 deletions
diff --git a/vendor/gix-validate/src/lib.rs b/vendor/gix-validate/src/lib.rs new file mode 100644 index 000000000..fd603aeb8 --- /dev/null +++ b/vendor/gix-validate/src/lib.rs @@ -0,0 +1,11 @@ +//! Validation for various kinds of git related items. +#![deny(missing_docs, rust_2018_idioms)] +#![forbid(unsafe_code)] + +/// +pub mod reference; +pub use reference::name as refname; + +/// +pub mod tag; +pub use tag::name as tagname; diff --git a/vendor/gix-validate/src/reference.rs b/vendor/gix-validate/src/reference.rs new file mode 100644 index 000000000..eb1f25a81 --- /dev/null +++ b/vendor/gix-validate/src/reference.rs @@ -0,0 +1,75 @@ +/// +pub mod name { + use std::convert::Infallible; + + /// The error used in [name()][super::name()] and [name_partial()][super::name_partial()] + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error("A reference must be a valid tag name as well")] + Tag(#[from] crate::tag::name::Error), + #[error("Standalone references must be all uppercased, like 'HEAD'")] + SomeLowercase, + #[error("A reference name must not start with a slash '/'")] + StartsWithSlash, + #[error("Multiple slashes in a row are not allowed as they may change the reference's meaning")] + RepeatedSlash, + #[error("Names must not be a single '.', but may contain it.")] + SingleDot, + } + + impl From<Infallible> for Error { + fn from(_: Infallible) -> Self { + unreachable!("this impl is needed to allow passing a known valid partial path as parameter") + } + } +} + +use bstr::BStr; + +/// Validate a reference name running all the tests in the book. This disallows lower-case references, but allows +/// ones like `HEAD`. +pub fn name(path: &BStr) -> Result<&BStr, name::Error> { + validate(path, Mode::Complete) +} + +/// Validate a partial reference name. As it is assumed to be partial, names like `some-name` is allowed +/// even though these would be disallowed with when using [`name()`]. +pub fn name_partial(path: &BStr) -> Result<&BStr, name::Error> { + validate(path, Mode::Partial) +} + +enum Mode { + Complete, + Partial, +} + +fn validate(path: &BStr, mode: Mode) -> Result<&BStr, name::Error> { + crate::tagname(path)?; + if path[0] == b'/' { + return Err(name::Error::StartsWithSlash); + } + let mut previous = 0; + let mut one_before_previous = 0; + let mut saw_slash = false; + for byte in path.iter() { + match *byte { + b'/' if previous == b'.' && one_before_previous == b'/' => return Err(name::Error::SingleDot), + b'/' if previous == b'/' => return Err(name::Error::RepeatedSlash), + _ => {} + } + + if *byte == b'/' { + saw_slash = true; + } + one_before_previous = previous; + previous = *byte; + } + + if let Mode::Complete = mode { + if !saw_slash && !path.iter().all(|c| c.is_ascii_uppercase() || *c == b'_') { + return Err(name::Error::SomeLowercase); + } + } + Ok(path) +} diff --git a/vendor/gix-validate/src/tag.rs b/vendor/gix-validate/src/tag.rs new file mode 100644 index 000000000..91ceec185 --- /dev/null +++ b/vendor/gix-validate/src/tag.rs @@ -0,0 +1,61 @@ +use bstr::BStr; + +/// +pub mod name { + use bstr::BString; + + /// The error returned by [`name()`][super::name()]. + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error("A ref must not contain invalid bytes or ascii control characters: {byte:?}")] + InvalidByte { byte: BString }, + #[error("A ref must not contain '..' as it may be mistaken for a range")] + DoubleDot, + #[error("A ref must not end with '.lock'")] + LockFileSuffix, + #[error("A ref must not contain '@{{' which is a part of a ref-log")] + ReflogPortion, + #[error("A ref must not contain '*' character")] + Asterisk, + #[error("A ref must not start with a '.'")] + StartsWithDot, + #[error("A ref must not end with a '/'")] + EndsWithSlash, + #[error("A ref must not be empty")] + Empty, + } +} + +/// Assure the given `input` resemble a valid git tag name, which is returned unchanged on success. +pub fn name(input: &BStr) -> Result<&BStr, name::Error> { + if input.is_empty() { + return Err(name::Error::Empty); + } + if *input.last().expect("non-empty") == b'/' { + return Err(name::Error::EndsWithSlash); + } + + let mut previous = 0; + for byte in input.iter() { + match byte { + b'\\' | b'^' | b':' | b'[' | b'?' | b' ' | b'~' | b'\0'..=b'\x1F' | b'\x7F' => { + return Err(name::Error::InvalidByte { + byte: (&[*byte][..]).into(), + }) + } + b'*' => return Err(name::Error::Asterisk), + b'.' if previous == b'.' => return Err(name::Error::DoubleDot), + b'{' if previous == b'@' => return Err(name::Error::ReflogPortion), + _ => {} + } + previous = *byte; + } + if input[0] == b'.' { + return Err(name::Error::StartsWithDot); + } + if input.ends_with(b".lock") { + return Err(name::Error::LockFileSuffix); + } + Ok(input) +} |