Repository: astral-sh/uv
File: crates/uv-cache-info/src/glob.rs (Rust)

Code before:
use std::{
    collections::BTreeMap,
    path::{Component, Components, Path, PathBuf},
};

fn is_glob_like(part: Component) -> bool {
    matches!(part, Component::Normal(_))
        && part
            .as_os_str()
            .to_str()
            .is_some_and(|part| ["*", "{", "}", "?"].into_iter().any(|c| part.contains(c)))
}

#[derive(Debug, Default, Clone, PartialEq, Eq)]
struct GlobParts {
    base: PathBuf,
    pattern: PathBuf,
}

/// Split a glob into longest possible base + shortest possible glob pattern.
fn split_glob(pattern: impl AsRef<str>) -> GlobParts {
    let pattern: &Path = pattern.as_ref().as_ref();

    let mut glob = GlobParts::default();
    let mut current = PathBuf::new();
    let mut globbing = false;
    let mut last = None;

    for part in pattern.components() {
        if let Some(last) = last {
            if last != Component::CurDir {
                current.push(last);
                if globbing {
                    glob.pattern.push(last);
                } else {
                    glob.base.push(last);
                }
            }
        }

Review comment (suggestion):
Can you document the contract for this function? In particular, I think it is necessary that this always return true if the given part returns something different if it's interpreted as a glob versus if it was interpreted as a literal. But that it can also return true in cases even when the result is identical. That is, this routine allows false positives but not false negatives.

I think this is how it's used too. That is, if you interpret a path component as a glob when it isn't, then I think the worst thing that happens is that you traverse more of the directory tree? (i.e., You lose on perf but not correctness.)

I'm thinking about components like `foo{bar` or `foo[bar`.

Code after:
use std::{
    collections::BTreeMap,
    path::{Component, Components, Path, PathBuf},
};

/// Check if a component of the path looks like it may be a glob pattern.
///
/// Note: this function is being used when splitting a glob pattern into a long possible
/// base and the glob remainder (scanning through components until we hit the first component
/// for which this function returns true). It is acceptable for this function to return
/// false positives (e.g. patterns like 'foo[bar' or 'foo{bar') in which case correctness
/// will not be affected but efficiency might be (because we'll traverse more than we should),
/// however it should not return false negatives.
fn is_glob_like(part: Component) -> bool {
    matches!(part, Component::Normal(_))
        && part.as_os_str().to_str().is_some_and(|part| {
            ["*", "{", "}", "?", "[", "]"]
                .into_iter()
                .any(|c| part.contains(c))
        })
}

#[derive(Debug, Default, Clone, PartialEq, Eq)]
struct GlobParts {
    base: PathBuf,
    pattern: PathBuf,
}

/// Split a glob into longest possible base + shortest possible glob pattern.
fn split_glob(pattern: impl AsRef<str>) -> GlobParts {
    let pattern: &Path = pattern.as_ref().as_ref();

    let mut glob = GlobParts::default();
    let mut globbing = false;
    let mut last = None;

    for part in pattern.components() {
        if let Some(last) = last {
            if last != Component::CurDir {