Fix rules:exists directory lookup missing existing directories
What does this MR do and why?
Since 18.2, rules:exists treats a path ending in / as a directory check. That check
could return false for a directory that exists, depending on which unrelated files
happened to be in the repository.
The trailing-slash branch of exact_matches? used bsearch with a start_with?
predicate. bsearch requires a predicate that is false for a prefix of the sorted
array and true for the rest, but start_with?("docs/") is only true for the
contiguous block of paths inside docs/, with false on both sides. A probe landing
past that block tells the search to keep going right, so it can return nil without
ever looking at the directory.
This MR searches for the first path that is not less than the glob instead, which is a monotonic predicate, and then checks whether that path is inside the directory. This keeps the lookup O(log n), matching the existing exact-file branch, which already relies on the paths being sorted (git tree order is byte-sorted).
A regression spec reproduces the issue's file layout: docs/ is truthy, and the prefix
sibling doc/ is falsy. The spec fails on the previous code and passes with the fix.
References
- Resolves #630776 (closed)
Screenshots or screen recordings
Not applicable, backend-only change with no UI.
How to set up and validate locally
-
Create a project with these files:
.gitlab-ci.yml Cargo.toml README.md a.txt b.txt c.txt docs/guide.md src/main.rs z.txt -
Use this
.gitlab-ci.yml:docs-dir: script: echo docs/ exists rules: - exists: [docs/] always: script: echo always -
Run a pipeline. Before this change, only
alwaysis created. After this change, bothdocs-dirandalwaysare created. -
Alternatively, verify the predicate directly in a Rails console:
paths = %w[.gitlab-ci.yml Cargo.toml README.md a.txt b.txt c.txt docs/guide.md src/main.rs z.txt] paths.bsearch { |path| path.start_with?("docs/") } # => nil (old) paths.bsearch { |path| path >= "docs/" }&.start_with?("docs/") # => true (new)
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.