Expand description
Parse GitHub CODEOWNERS files and answer the only question that matters:
who owns this file?
use codeowner::{CodeOwners, Owner};
let owners = CodeOwners::parse("\
* @org/everyone
/src/parser/ @alice
*.md docs@example.com
");
assert_eq!(owners.of("src/parser/lexer.rs"), Some(&[Owner::user("alice")][..]));
assert_eq!(owners.of("README.md"), Some(&[Owner::email("docs@example.com")][..]));
assert_eq!(owners.of("build.sh"), Some(&[Owner::team("org", "everyone")][..]));§Three things implementations usually get wrong
1. Unowned is not the same as unmatched. A rule with no owners deliberately clears ownership. GitHub documents this. Collapsing the two cases into one silently reassigns files to the wrong team.
use codeowner::CodeOwners;
let owners = CodeOwners::parse("/apps/ @octocat\n/apps/github\n");
assert!(owners.of("apps/main/index.js").is_some()); // owned by @octocat
assert_eq!(owners.of("apps/github/index.js").map(<[_]>::len), Some(0)); // matched, no owner
assert_eq!(owners.of("README.md"), None); // no rule matched at all2. CODEOWNERS is not gitignore. GitHub documents three gitignore
features as non-functional here: ! negation, [ ] character ranges, and
\ escaping of a leading #. Lines using them are invalid and skipped —
this crate reports them rather than silently mis-parsing.
3. docs/* does not match nested files. Under gitignore rules it would,
by matching the intermediate directory. GitHub says it does not.
use codeowner::CodeOwners;
let owners = CodeOwners::parse("docs/* docs@example.com\n");
assert!(owners.of("docs/getting-started.md").is_some());
assert!(owners.of("docs/build-app/troubleshooting.md").is_none());§Errors are data, not failures
GitHub skips invalid lines rather than rejecting the file, so
CodeOwners::parse never fails. Bad lines land in
errors with line numbers, which is what you want if
you are writing a linter.
use codeowner::CodeOwners;
let owners = CodeOwners::parse("*.rs @alice\n![!]bad @bob\n");
assert_eq!(owners.rules().len(), 1);
assert_eq!(owners.errors().len(), 1);
assert_eq!(owners.errors()[0].line, 2);§Scope
GitHub CODEOWNERS syntax, zero dependencies, no_std (needs alloc).
GitLab’s section headers ([Backend][2]) are not supported yet.
Structs§
- Code
Owners - A parsed CODEOWNERS file.
- Parse
Error - A skipped line, with enough context to point at it in an editor.
- Pattern
- A compiled CODEOWNERS path pattern.
- Rule
- One
pattern owners...line.
Enums§
- Error
Kind - What was wrong with a line.
- Owner
- A single code owner.
- Pattern
Error - Why a pattern could not be compiled.
Constants§
- MAX_
FILE_ SIZE - GitHub refuses to load a CODEOWNERS file above this size.
- SEARCH_
PATHS - The paths GitHub searches, in priority order.