Crate gitrevset

Source
Expand description

A domain-specific-language to select commits in a git repo. Similar to Mercurial’s revset.

§Language Specification

Specifying a commit:

  • Reference names like master, release-foo, or origin/master.
  • Hex commit hashes or hash prefixes.
  • A dot ., or the at sign @ refers to HEAD.

Operators:

  • x + y, x | y, x or y, union(x, y): Union of x and y (1).
  • x & y, x and y, intersection(x, y): Intersection of x and y.
  • x - y, difference(x, y): Commits in x but not y.
  • !x, not x, negate(x): Commits not in x.
  • ::x, ancestors(x): Ancestors of x, including x.
  • x::, descendants(x): Descendants of x, including x.
  • x^, parents(x): Parents of x (2).
  • x % y, only(x, y): Reachable from x, not y, or ::x - ::y.
  • x:y, range(x, y): A DAG range, descendants of x and ancestors of y, or x:: & ::y (3).

Functions:

  • children(x): Commits with at least one parent in the x set.
  • heads(x): Heads of a set, x - parents(x).
  • roots(x): Roots of a set, x - children(x).
  • gca(x, y, ...), ancestor(x, y, ...): Heads of common ancestors (4).
  • first(x, ...): First item in x, or first(...) if x is empty.
  • last(x): Last item in x, or empty.
  • head(): Visible heads (references).
  • all(): Visible commits, aka. ::head().
  • publichead(): Heads referred by remotes, ref("remotes/**").
  • drafthead(): Heads not referred by remotes, head() - publichead().
  • public(): Commits reachable from publichead(), ::publichead().
  • draft(): Commits only reachable from draft heads, all() - public().
  • author(name): Filter by author name or email.
  • committer(name): Filter by committer name or email.
  • date(date): Filter by author date.
  • committerdate(date): Filter by committer date.
  • desc(text): Filter by commit message.
  • modifies(path): Filter by modified path.
  • predecessors(x): Previous versions of x, including x.
  • successors(x): Newer versions of x, including x.
  • obsolete(): Commits with at least one newer versions.
  • id(hexhash): Resolve a commit explicitly by a hex hash string.
  • ref(): All references.
  • ref(name): Resolve commits by a reference name or glob.
  • tag(): All tags.
  • tag(name): Resolve commits by a tag name or glob.
  • none(): Empty set.
  • present(set): Empty set on “unresolved name” error. Otherwise just set.
  • apply(expr, $1, $2, ...): Replace $1, $2 in expr with evaluated sets. Then evaluate expr. Useful to avoid evaluate same sets multiple times.

Differences from Mercurial:

  1. x + y does not make sure y comes after x. For example, first(x + y) might be first(x) or first(y). In Mercurial, first(x + y) would be first(x).
  2. x^ selects all parents, not just first parents.
  3. x:y selects DAG range x to y, not revision number range. x::y is invalid syntax, for easier parsing.
  4. ancestor(x, y) can return multiple commits for criss-cross merges.

§Quick Start

First, construct a gitrevset::Repo:

// Open from the current directory.
let repo = gitrevset::Repo::open_from_env()?;

// Open from a libgit2 repository.
let git_repo = git2::Repository::open(path)?;
let repo = gitrevset::Repo::open_from_repo(Box::new(git_repo))?;

Then, use revs or anyrevs to perform queries.

let set = repo.revs("(draft() & ::.)^ + .")?;

// With user-defined aliases considered.
// ex. git config revsetalias.foo "parents($1)"
let set = repo.anyrevs("foo(.)")?;

Finally, use to_oids to extract Git object IDs from the resulting set:

use gitrevset::SetExt;
for oid in set.to_oids()? {
    dbg!(oid?);
}

To parse the revset expression at compile time, to avoid issues about string escaping or injection, use the ast! macro.

§Note on Commit Graph Index

gitrevset takes advantage of the commit graph index from the EdenSCM project that is designed to support very large repositories. The index is built on demand under the .git/dag directory during the construction of the Repo struct.

The index is highly optimized for ancestors-related queries. For example, gca(x, y), x & ::y, x % y usually complete under 1 millisecond regardless of the distance between x and y.

The index is not optimized for many visible heads. Having too many references might have a visible performance penalty on Repo construction.

The index can be accessed by repo.dag() and the re-exported dag crate.

Re-exports§

Modules§

  • Extended methods on types defined in other crates.

Macros§

  • Construct an AST statically. This can be useful to avoid escaping issues parsing strings.

Structs§

  • Extra context for eval. It can define customized aliases.
  • Repo with extra states to support revset queries.

Enums§

  • Error type used by gitrevset.
  • A node in the parsed AST.

Type Aliases§

  • Result type used by gitrevset.