git_ref_format/lib.rs
1//! Everything you never knew you wanted for handling git ref names.
2//!
3//! # Overview
4//!
5//! This crate provides a number of types which allow to validate git ref names,
6//! create new ones which are valid by construction, make assertions about their
7//! structure, and deconstruct them into their components.
8//!
9//! ## Basic Types
10//!
11//! The basic types are:
12//!
13//! * [`RefStr`]
14//! * [`RefString`]
15//!
16//! They are wrappers around [`str`] and [`String`] respectively, with the
17//! additional guarantee that they are also valid ref names as per
18//! [`git-check-ref-format`] (which is also exposed directly as
19//! [`check_ref_format`]). Both types are referred to as "ref strings".
20//!
21//! Note that this implies that ref names must be valid UTF-8, which git itself
22//! doesn't require.
23//!
24//! Ref strings can be iterated over, either yielding `&str` or [`Component`]. A
25//! [`Component`] is guaranteed to not contain a '/' separator, and can thus
26//! also be used to conveniently construct known-valid ref strings. The [`lit`]
27//! module contains a number of types (and `const` values thereof) which can be
28//! coerced into [`Component`], and thus can be used to construct known-valid
29//! ref strings.
30//!
31//! The [`name`] module also provides a number of constant values of commonly
32//! used ref strings / components, which are useful for pattern matching.
33//!
34//! The `"macro"` feature enables the `refstring!` and `component!` macros,
35//! which can be convenient to construct compile-time validated [`RefString`]s
36//! respectively [`Component`]s.
37//!
38//! ## Refspec Patterns
39//!
40//! The types
41//!
42//! * [`refspec::PatternStr`]
43//! * [`refspec::PatternString`]
44//!
45//! guarantee that their values are valid ref strings but additionally _may_
46//! contain at most one "*" character. It is thus possible to convert a ref
47//! string to a refspec pattern, but not the other way round. Refspec patterns
48//! are commonly used for mapping remote to local refs (cf. [`git-fetch`]).
49//!
50//! The `"macro"` feature enables the `refspec::pattern!` macro, which
51//! constructs a compile-time validated [`refspec::PatternString`].
52//!
53//! ## Structured Ref Strings
54//!
55//! Ref strings may be [`Qualified`], which essentially means that they start
56//! with "refs/". [`Qualified`] ref string also require at least three
57//! components (eg. "refs/heads/main"), which makes it easier to deal with
58//! common naming conventions.
59//!
60//! [`Qualified`] refs may be [`Namespaced`], or can be given a namespace
61//! (namespaces can be nested). [`Namespaced`] refs are also [`Qualified`], and
62//! can have their namespace(s) stripped.
63//!
64//! # On Git Ref Name Conventions
65//!
66//! Git references are essentially path names pointing to their traditional
67//! storage location in a the repository (`$GIT_DIR/refs`). Unlike (UNIX) file
68//! paths, they are subject to a few restrictions, as described in
69//! [`git-check-ref-format`].
70//!
71//! On top of that, there are a number of conventions around the hierarchical
72//! naming, _some_ of which are treated specially by tools such as the `git`
73//! CLI. For example:
74//!
75//! * `refs/heads/..` are also called "branches".
76//!
77//! Omitting the "refs/heads/" prefix is typically accepted. Such a branch
78//! name is also referred to as a "shorthand" ref.
79//!
80//! * `refs/tags/..` are assumed to contain tags.
81//!
82//! `git` treats tags specially, specifically it insists that they be globally
83//! unique across all copies of the repository.
84//!
85//! * `refs/remotes/../..` is where "remote tracking branches" are stored.
86//!
87//! In `git`, the first element after "remotes" is considered the name of the
88//! [remote][git-remote] (as it appears in the config file), while everything
89//! after that is considered a shorthand branch. Note, however, that the
90//! remote name may itself contain '/' separators, so it is not generally
91//! possible to extract the branch name without access to the config.
92//!
93//! * `refs/namespaces/..` is hidden unless [`gitnamespaces`] are in effect.
94//!
95//! The structure of namespaces is recursive: they contain full refs, which
96//! can themselves be namespaces (eg.
97//! `refs/namespaces/a/refs/namespaces/b/refs/heads/branch`). Note that,
98//! unlike remote names, namespace names can **not** contain forward slashes
99//! but there is no tooling which would enforce that.
100//!
101//! There are also other such ref hierachies `git` knows about, and this crate
102//! doesn't attempt to cover all of them. More importantly, `git` does not
103//! impose any restrictions on ref hierarchies: as long as they don't collide
104//! with convential ones, applications can introduce any hierchies they want.
105//!
106//! This restricts the transformations between conventional refs which can be
107//! made without additional information besides the ref name: for example, it is
108//! not generally possible to turn a remote tracking branch into a branch (or a
109//! shorthand) without knowning about all possible remote names.
110//!
111//! Therefore, this crate doesn't attempt to interpret all possible semantics
112//! associated with refs, and instead tries to make it easy for library
113//! consumers to do so.
114//!
115//! [`git-check-ref-format`]: https://git-scm.com/docs/git-check-ref-format
116//! [`git-fetch`]: https://git-scm.com/docs/git-fetch
117//! [git-remote]: https://git-scm.com/docs/git-remote
118//! [`gitnamespaces`]: https://git-scm.com/docs/gitnamespaces
119#[cfg(feature = "percent-encoding")]
120pub use git_ref_format_core::PercentEncode;
121pub use git_ref_format_core::{
122 check_ref_format, lit, name::component, Component, DuplicateGlob, Error, Namespaced, Options,
123 Qualified, RefStr, RefString,
124};
125
126pub mod name {
127 pub use git_ref_format_core::name::*;
128
129 #[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
130 pub use git_ref_format_macro::component;
131}
132
133#[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
134pub use git_ref_format_macro::qualified;
135#[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
136pub use git_ref_format_macro::refname;
137
138pub mod refspec {
139 pub use git_ref_format_core::refspec::*;
140
141 #[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
142 pub use git_ref_format_macro::pattern;
143
144 #[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
145 pub use git_ref_format_macro::qualified_pattern;
146}