#git #reference #ref #name #everything #macro #wanted

git-ref-format

Everything you never knew you wanted for handling git ref names

7 releases

0.3.1 Sep 2, 2024
0.3.0 Jun 2, 2023
0.2.3 May 5, 2023
0.2.0 Feb 8, 2023
0.1.0 Oct 14, 2022

#697 in Rust patterns

Download history 137/week @ 2024-06-10 183/week @ 2024-06-17 138/week @ 2024-06-24 95/week @ 2024-07-01 63/week @ 2024-07-08 130/week @ 2024-07-15 100/week @ 2024-07-22 82/week @ 2024-07-29 166/week @ 2024-08-05 112/week @ 2024-08-12 89/week @ 2024-08-19 145/week @ 2024-08-26 299/week @ 2024-09-02 235/week @ 2024-09-09 162/week @ 2024-09-16 113/week @ 2024-09-23

840 downloads per month
Used in 15 crates (2 directly)

GPL-3.0-or-later

9KB

Everything you never knew you wanted for handling git ref names.

Overview

This crate provides a number of types which allow to validate git ref names, create new ones which are valid by construction, make assertions about their structure, and deconstruct them into their components.

Basic Types

The basic types are:

They are wrappers around [str] and String respectively, with the additional guarantee that they are also valid ref names as per git-check-ref-format (which is also exposed directly as check_ref_format). Both types are referred to as "ref strings".

Note that this implies that ref names must be valid UTF-8, which git itself doesn't require.

Ref strings can be iterated over, either yielding &str or Component. A Component is guaranteed to not contain a '/' separator, and can thus also be used to conveniently construct known-valid ref strings. The [lit] module contains a number of types (and const values thereof) which can be coerced into Component, and thus can be used to construct known-valid ref strings.

The name module also provides a number of constant values of commonly used ref strings / components, which are useful for pattern matching.

The "macro" feature enables the refstring! and component! macros, which can be convenient to construct compile-time validated RefStrings respectively Components.

Refspec Patterns

The types

guarantee that their values are valid ref strings but additionally may contain at most one "*" character. It is thus possible to convert a ref string to a refspec pattern, but not the other way round. Refspec patterns are commonly used for mapping remote to local refs (cf. git-fetch).

The "macro" feature enables the refspec::pattern! macro, which constructs a compile-time validated refspec::PatternString.

Structured Ref Strings

Ref strings may be Qualified, which essentially means that they start with "refs/". Qualified ref string also require at least three components (eg. "refs/heads/main"), which makes it easier to deal with common naming conventions.

Qualified refs may be Namespaced, or can be given a namespace (namespaces can be nested). Namespaced refs are also Qualified, and can have their namespace(s) stripped.

On Git Ref Name Conventions

Git references are essentially path names pointing to their traditional storage location in a the repository ($GIT_DIR/refs). Unlike (UNIX) file paths, they are subject to a few restrictions, as described in git-check-ref-format.

On top of that, there are a number of conventions around the hierarchical naming, some of which are treated specially by tools such as the git CLI. For example:

  • refs/heads/.. are also called "branches".

    Omitting the "refs/heads/" prefix is typically accepted. Such a branch name is also referred to as a "shorthand" ref.

  • refs/tags/.. are assumed to contain tags.

    git treats tags specially, specifically it insists that they be globally unique across all copies of the repository.

  • refs/remotes/../.. is where "remote tracking branches" are stored.

    In git, the first element after "remotes" is considered the name of the remote (as it appears in the config file), while everything after that is considered a shorthand branch. Note, however, that the remote name may itself contain '/' separators, so it is not generally possible to extract the branch name without access to the config.

  • refs/namespaces/.. is hidden unless gitnamespaces are in effect.

    The structure of namespaces is recursive: they contain full refs, which can themselves be namespaces (eg. refs/namespaces/a/refs/namespaces/b/refs/heads/branch). Note that, unlike remote names, namespace names can not contain forward slashes but there is no tooling which would enforce that.

There are also other such ref hierachies git knows about, and this crate doesn't attempt to cover all of them. More importantly, git does not impose any restrictions on ref hierarchies: as long as they don't collide with convential ones, applications can introduce any hierchies they want.

This restricts the transformations between conventional refs which can be made without additional information besides the ref name: for example, it is not generally possible to turn a remote tracking branch into a branch (or a shorthand) without knowning about all possible remote names.

Therefore, this crate doesn't attempt to interpret all possible semantics associated with refs, and instead tries to make it easy for library consumers to do so.

Dependencies

~0.3–1MB
~22K SLoC