// Copyright 2021 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. #![expect(missing_docs)] use std::any::Any;use std::collections::HashMap;use std::collections::hash_map;use std::convert::Infallible;use std::fmt;use std::ops::ControlFlow;use std::ops::Range;use std::sync::Arc;use std::sync::LazyLock; use itertools::Itertools as _;use pollster::FutureExt as _;use thiserror::Error; use crate::backend::BackendError;use crate::backend::ChangeId;use crate::backend::CommitId;use crate::commit::Commit;use crate::dsl_util;use crate::dsl_util::collect_similar;use crate::fileset;use crate::fileset::FilesetAliasesMap;use crate::fileset::FilesetDiagnostics;use crate::fileset::FilesetExpression;use crate::fileset::FilesetParseContext;use crate::graph::GraphNode;use crate::id_prefix::IdPrefixContext;use crate::id_prefix::IdPrefixIndex;use crate::index::ResolvedChangeTargets;use crate::object_id::HexPrefix;use crate::object_id::PrefixResolution;use crate::op_store::LocalRemoteRefTarget;use crate::op_store::RefTarget;use crate::op_store::RemoteRefState;use crate::op_walk;use crate::ref_name::RefName;use crate::ref_name::RemoteName;use crate::ref_name::RemoteRefSymbol;use crate::ref_name::RemoteRefSymbolBuf;use crate::ref_name::WorkspaceName;use crate::ref_name::WorkspaceNameBuf;use crate::repo::ReadonlyRepo;use crate::repo::Repo;use crate::repo::RepoLoaderError;use crate::repo_path::RepoPathUiConverter;use crate::revset_parser;pub use crate::revset_parser::BinaryOp;pub use crate::revset_parser::ExpressionKind;pub use crate::revset_parser::ExpressionNode;pub use crate::revset_parser::FunctionCallNode;pub use crate::revset_parser::RevsetAliasesMap;pub use crate::revset_parser::RevsetDiagnostics;pub use crate::revset_parser::RevsetParseError;pub use crate::revset_parser::RevsetParseErrorKind;pub use crate::revset_parser::UnaryOp;pub use crate::revset_parser::expect_literal;pub use crate::revset_parser::parse_program;pub use crate::revset_parser::parse_symbol;use crate::store::Store;use crate::str_util::StringExpression;use crate::str_util::StringPattern;use crate::time_util::DatePattern;use crate::time_util::DatePatternContext; /// Error occurred during symbol resolution.#[derive(Debug, Error)]pub enum RevsetResolutionError { #[error("Revision `{name}` doesn't exist")] NoSuchRevision { name: String, candidates: Vec<String>, }, #[error("Workspace `{}` doesn't have a working-copy commit", name.as_symbol())] WorkspaceMissingWorkingCopy { name: WorkspaceNameBuf }, #[error("An empty string is not a valid revision")] EmptyString, #[error("Commit ID prefix `{0}` is ambiguous")] AmbiguousCommitIdPrefix(String), #[error("Change ID prefix `{0}` is ambiguous")] AmbiguousChangeIdPrefix(String), #[error("Change ID `{symbol}` is divergent")] DivergentChangeId { symbol: String, visible_targets: Vec<(usize, CommitId)>, }, #[error("Name `{symbol}` is conflicted")] ConflictedRef { kind: &'static str, symbol: String, targets: Vec<CommitId>, }, #[error("Unexpected error from commit backend")] Backend(#[source] BackendError), #[error(transparent)] Other(#[from] Box<dyn std::error::Error + Send + Sync>),} /// Error occurred during revset evaluation.#[derive(Debug, Error)]pub enum RevsetEvaluationError { #[error("Unexpected error from commit backend")] Backend(#[from] BackendError), #[error(transparent)] Other(Box<dyn std::error::Error + Send + Sync>),} impl RevsetEvaluationError { // TODO: Create a higher-level error instead of putting non-BackendErrors in a // BackendError pub fn into_backend_error(self) -> BackendError { match self { Self::Backend(err) => err, Self::Other(err) => BackendError::Other(err), } }} // assumes index has less than u64::MAX entries.pub const GENERATION_RANGE_FULL: Range<u64> = 0..u64::MAX;pub const GENERATION_RANGE_EMPTY: Range<u64> = 0..0; pub const PARENTS_RANGE_FULL: Range<u32> = 0..u32::MAX; /// Symbol or function to be resolved to `CommitId`s.#[derive(Clone, Debug)]pub enum RevsetCommitRef { WorkingCopy(WorkspaceNameBuf), WorkingCopies, Symbol(String), RemoteSymbol(RemoteRefSymbolBuf), ChangeId(HexPrefix), CommitId(HexPrefix), Bookmarks(StringExpression), RemoteBookmarks { symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, }, Tags(StringExpression), RemoteTags { symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, }, GitRefs, GitHead,} /// String expressions to match `name@remote` bookmarks/tags.#[derive(Clone, Debug)]pub struct RemoteRefSymbolExpression { /// Matches local name. pub name: StringExpression, /// Matches remote name. pub remote: StringExpression,} /// A custom revset filter expression, defined by an extension.pub trait RevsetFilterExtension: std::fmt::Debug + Any + Send + Sync { /// Returns true iff this filter matches the specified commit. fn matches_commit(&self, commit: &Commit) -> bool;} impl dyn RevsetFilterExtension { /// Returns reference of the implementation type. pub fn downcast_ref<T: RevsetFilterExtension>(&self) -> Option<&T> { (self as &dyn Any).downcast_ref() }} #[derive(Clone, Debug)]pub enum RevsetFilterPredicate { /// Commits with number of parents in the range. ParentCount(Range<u32>), /// Commits with description matching the pattern. Description(StringExpression), /// Commits with first line of the description matching the pattern. Subject(StringExpression), /// Commits with author name matching the pattern. AuthorName(StringExpression), /// Commits with author email matching the pattern. AuthorEmail(StringExpression), /// Commits with author dates matching the given date pattern. AuthorDate(DatePattern), /// Commits with committer name matching the pattern. CommitterName(StringExpression), /// Commits with committer email matching the pattern. CommitterEmail(StringExpression), /// Commits with committer dates matching the given date pattern. CommitterDate(DatePattern), /// Commits modifying the paths specified by the fileset. File(FilesetExpression), /// Commits containing diffs matching the `text` pattern within the `files`. DiffLines { text: StringExpression, files: FilesetExpression, }, /// Commits with conflicts HasConflict, /// Commits that are cryptographically signed. Signed, /// Custom predicates provided by extensions Extension(Arc<dyn RevsetFilterExtension>),} mod private { /// Defines [`RevsetExpression`] variants depending on resolution state. pub trait ExpressionState { type CommitRef: Clone; type Operation: Clone; } // Not constructible because these state types just define associated types. #[derive(Debug)] pub enum UserExpressionState {} #[derive(Debug)] pub enum ResolvedExpressionState {}} use private::ExpressionState;use private::ResolvedExpressionState;use private::UserExpressionState; impl ExpressionState for UserExpressionState { type CommitRef = RevsetCommitRef; type Operation = String;} impl ExpressionState for ResolvedExpressionState { type CommitRef = Infallible; type Operation = Infallible;} /// [`RevsetExpression`] that may contain unresolved commit refs.pub type UserRevsetExpression = RevsetExpression<UserExpressionState>;/// [`RevsetExpression`] that never contains unresolved commit refs.pub type ResolvedRevsetExpression = RevsetExpression<ResolvedExpressionState>; /// Tree of revset expressions describing DAG operations.////// Use [`UserRevsetExpression`] or [`ResolvedRevsetExpression`] to construct/// expression of that state.#[derive(Clone, Debug)]pub enum RevsetExpression<St: ExpressionState> { None, All, VisibleHeads, /// Visible heads and all referenced commits within the current expression /// scope. Used as the default of `Range`/`DagRange` heads. VisibleHeadsOrReferenced, Root, Commits(Vec<CommitId>), CommitRef(St::CommitRef), Ancestors { heads: Arc<Self>, generation: Range<u64>, parents_range: Range<u32>, }, Descendants { roots: Arc<Self>, generation: Range<u64>, }, // Commits that are ancestors of "heads" but not ancestors of "roots" Range { roots: Arc<Self>, heads: Arc<Self>, generation: Range<u64>, // Parents range is only used for traversing heads, not roots parents_range: Range<u32>, }, // Commits that are descendants of "roots" and ancestors of "heads" DagRange { roots: Arc<Self>, heads: Arc<Self>, // TODO: maybe add generation_from_roots/heads? }, // Commits reachable from "sources" within "domain" Reachable { sources: Arc<Self>, domain: Arc<Self>, }, Heads(Arc<Self>), /// Heads of the set of commits which are ancestors of `heads` but are not /// ancestors of `roots`, and which also are contained in `filter`. HeadsRange { roots: Arc<Self>, heads: Arc<Self>, parents_range: Range<u32>, filter: Arc<Self>, }, Roots(Arc<Self>), ForkPoint(Arc<Self>), Bisect(Arc<Self>), HasSize { candidates: Arc<Self>, count: usize, }, Latest { candidates: Arc<Self>, count: usize, }, Filter(RevsetFilterPredicate), /// Marker for subtree that should be intersected as filter. AsFilter(Arc<Self>), Divergent, /// Resolves symbols and visibility at the specified operation. AtOperation { operation: St::Operation, candidates: Arc<Self>, }, /// Makes `All` include the commits and their ancestors in addition to the /// visible heads. WithinReference { candidates: Arc<Self>, /// Commits explicitly referenced within the scope. commits: Vec<CommitId>, }, /// Resolves visibility within the specified repo state. WithinVisibility { candidates: Arc<Self>, /// Copy of `repo.view().heads()` at the operation. visible_heads: Vec<CommitId>, }, Coalesce(Arc<Self>, Arc<Self>), Present(Arc<Self>), NotIn(Arc<Self>), Union(Arc<Self>, Arc<Self>), Intersection(Arc<Self>, Arc<Self>), Difference(Arc<Self>, Arc<Self>),} // Leaf expression that never contains unresolved commit refs, which can be// either user or resolved expressionimpl<St: ExpressionState> RevsetExpression<St> { pub fn none() -> Arc<Self> { Arc::new(Self::None) } /// Ancestors of visible heads and all referenced commits within the current /// expression scope, which may include hidden commits. pub fn all() -> Arc<Self> { Arc::new(Self::All) } pub fn visible_heads() -> Arc<Self> { Arc::new(Self::VisibleHeads) } fn visible_heads_or_referenced() -> Arc<Self> { Arc::new(Self::VisibleHeadsOrReferenced) } pub fn root() -> Arc<Self> { Arc::new(Self::Root) } pub fn commit(commit_id: CommitId) -> Arc<Self> { Self::commits(vec![commit_id]) } pub fn commits(commit_ids: Vec<CommitId>) -> Arc<Self> { Arc::new(Self::Commits(commit_ids)) } pub fn filter(predicate: RevsetFilterPredicate) -> Arc<Self> { Arc::new(Self::Filter(predicate)) } pub fn divergent() -> Arc<Self> { Arc::new(Self::AsFilter(Arc::new(Self::Divergent))) } /// Find any empty commits. pub fn is_empty() -> Arc<Self> { Self::filter(RevsetFilterPredicate::File(FilesetExpression::all())).negated() }} // Leaf expression that represents unresolved commit refsimpl<St: ExpressionState<CommitRef = RevsetCommitRef>> RevsetExpression<St> { pub fn working_copy(name: WorkspaceNameBuf) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::WorkingCopy(name))) } pub fn working_copies() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::WorkingCopies)) } pub fn symbol(value: String) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Symbol(value))) } pub fn remote_symbol(value: RemoteRefSymbolBuf) -> Arc<Self> { let commit_ref = RevsetCommitRef::RemoteSymbol(value); Arc::new(Self::CommitRef(commit_ref)) } pub fn change_id_prefix(prefix: HexPrefix) -> Arc<Self> { let commit_ref = RevsetCommitRef::ChangeId(prefix); Arc::new(Self::CommitRef(commit_ref)) } pub fn commit_id_prefix(prefix: HexPrefix) -> Arc<Self> { let commit_ref = RevsetCommitRef::CommitId(prefix); Arc::new(Self::CommitRef(commit_ref)) } pub fn bookmarks(expression: StringExpression) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Bookmarks(expression))) } pub fn remote_bookmarks( symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, ) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::RemoteBookmarks { symbol, remote_ref_state, })) } pub fn tags(expression: StringExpression) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Tags(expression))) } pub fn remote_tags( symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, ) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::RemoteTags { symbol, remote_ref_state, })) } pub fn git_refs() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::GitRefs)) } pub fn git_head() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::GitHead)) }} // Compound expressionimpl<St: ExpressionState> RevsetExpression<St> { pub fn latest(self: &Arc<Self>, count: usize) -> Arc<Self> { Arc::new(Self::Latest { candidates: self.clone(), count, }) } /// Commits in `self` that don't have descendants in `self`. pub fn heads(self: &Arc<Self>) -> Arc<Self> { Arc::new(Self::Heads(self.clone())) } /// Commits in `self` that don't have ancestors in `self`. pub fn roots(self: &Arc<Self>) -> Arc<Self> { Arc::new(Self::Roots(self.clone())) } /// Parents of `self`. pub fn parents(self: &Arc<Self>) -> Arc<Self> { self.ancestors_at(1) } /// Ancestors of `self`, including `self`. pub fn ancestors(self: &Arc<Self>) -> Arc<Self> { self.ancestors_range(GENERATION_RANGE_FULL) } /// Ancestors of `self` at an offset of `generation` behind `self`. /// The `generation` offset is zero-based starting from `self`. pub fn ancestors_at(self: &Arc<Self>, generation: u64) -> Arc<Self> { self.ancestors_range(generation..generation.saturating_add(1)) } /// Ancestors of `self` in the given range. pub fn ancestors_range(self: &Arc<Self>, generation_range: Range<u64>) -> Arc<Self> { Arc::new(Self::Ancestors { heads: self.clone(), generation: generation_range, parents_range: PARENTS_RANGE_FULL, })Lines 1–500 of 6439. Load more
// Copyright 2021 The Jujutsu Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![expect(missing_docs)] use std::any::Any; use std::collections::HashMap; use std::collections::hash_map; use std::convert::Infallible; use std::fmt; use std::ops::ControlFlow; use std::ops::Range; use std::sync::Arc; use std::sync::LazyLock; use itertools::Itertools as _; use pollster::FutureExt as _; use thiserror::Error; use crate::backend::BackendError; use crate::backend::ChangeId; use crate::backend::CommitId; use crate::commit::Commit; use crate::dsl_util; use crate::dsl_util::collect_similar; use crate::fileset; use crate::fileset::FilesetAliasesMap; use crate::fileset::FilesetDiagnostics; use crate::fileset::FilesetExpression; use crate::fileset::FilesetParseContext; use crate::graph::GraphNode; use crate::id_prefix::IdPrefixContext; use crate::id_prefix::IdPrefixIndex; use crate::index::ResolvedChangeTargets; use crate::object_id::HexPrefix; use crate::object_id::PrefixResolution; use crate::op_store::LocalRemoteRefTarget; use crate::op_store::RefTarget; use crate::op_store::RemoteRefState; use crate::op_walk; use crate::ref_name::RefName; use crate::ref_name::RemoteName; use crate::ref_name::RemoteRefSymbol; use crate::ref_name::RemoteRefSymbolBuf; use crate::ref_name::WorkspaceName; use crate::ref_name::WorkspaceNameBuf; use crate::repo::ReadonlyRepo; use crate::repo::Repo; use crate::repo::RepoLoaderError; use crate::repo_path::RepoPathUiConverter; use crate::revset_parser; pub use crate::revset_parser::BinaryOp; pub use crate::revset_parser::ExpressionKind; pub use crate::revset_parser::ExpressionNode; pub use crate::revset_parser::FunctionCallNode; pub use crate::revset_parser::RevsetAliasesMap; pub use crate::revset_parser::RevsetDiagnostics; pub use crate::revset_parser::RevsetParseError; pub use crate::revset_parser::RevsetParseErrorKind; pub use crate::revset_parser::UnaryOp; pub use crate::revset_parser::expect_literal; pub use crate::revset_parser::parse_program; pub use crate::revset_parser::parse_symbol; use crate::store::Store; use crate::str_util::StringExpression; use crate::str_util::StringPattern; use crate::time_util::DatePattern; use crate::time_util::DatePatternContext; /// Error occurred during symbol resolution. #[derive(Debug, Error)] pub enum RevsetResolutionError { #[error("Revision `{name}` doesn't exist")] NoSuchRevision { name: String, candidates: Vec<String>, }, #[error("Workspace `{}` doesn't have a working-copy commit", name.as_symbol())] WorkspaceMissingWorkingCopy { name: WorkspaceNameBuf }, #[error("An empty string is not a valid revision")] EmptyString, #[error("Commit ID prefix `{0}` is ambiguous")] AmbiguousCommitIdPrefix(String), #[error("Change ID prefix `{0}` is ambiguous")] AmbiguousChangeIdPrefix(String), #[error("Change ID `{symbol}` is divergent")] DivergentChangeId { symbol: String, visible_targets: Vec<(usize, CommitId)>, }, #[error("Name `{symbol}` is conflicted")] ConflictedRef { kind: &'static str, symbol: String, targets: Vec<CommitId>, }, #[error("Unexpected error from commit backend")] Backend(#[source] BackendError), #[error(transparent)] Other(#[from] Box<dyn std::error::Error + Send + Sync>), } /// Error occurred during revset evaluation. #[derive(Debug, Error)] pub enum RevsetEvaluationError { #[error("Unexpected error from commit backend")] Backend(#[from] BackendError), #[error(transparent)] Other(Box<dyn std::error::Error + Send + Sync>), } impl RevsetEvaluationError { // TODO: Create a higher-level error instead of putting non-BackendErrors in a // BackendError pub fn into_backend_error(self) -> BackendError { match self { Self::Backend(err) => err, Self::Other(err) => BackendError::Other(err), } } } // assumes index has less than u64::MAX entries. pub const GENERATION_RANGE_FULL: Range<u64> = 0..u64::MAX; pub const GENERATION_RANGE_EMPTY: Range<u64> = 0..0; pub const PARENTS_RANGE_FULL: Range<u32> = 0..u32::MAX; /// Symbol or function to be resolved to `CommitId`s. #[derive(Clone, Debug)] pub enum RevsetCommitRef { WorkingCopy(WorkspaceNameBuf), WorkingCopies, Symbol(String), RemoteSymbol(RemoteRefSymbolBuf), ChangeId(HexPrefix), CommitId(HexPrefix), Bookmarks(StringExpression), RemoteBookmarks { symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, }, Tags(StringExpression), RemoteTags { symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, }, GitRefs, GitHead, } /// String expressions to match `name@remote` bookmarks/tags. #[derive(Clone, Debug)] pub struct RemoteRefSymbolExpression { /// Matches local name. pub name: StringExpression, /// Matches remote name. pub remote: StringExpression, } /// A custom revset filter expression, defined by an extension. pub trait RevsetFilterExtension: std::fmt::Debug + Any + Send + Sync { /// Returns true iff this filter matches the specified commit. fn matches_commit(&self, commit: &Commit) -> bool; } impl dyn RevsetFilterExtension { /// Returns reference of the implementation type. pub fn downcast_ref<T: RevsetFilterExtension>(&self) -> Option<&T> { (self as &dyn Any).downcast_ref() } } #[derive(Clone, Debug)] pub enum RevsetFilterPredicate { /// Commits with number of parents in the range. ParentCount(Range<u32>), /// Commits with description matching the pattern. Description(StringExpression), /// Commits with first line of the description matching the pattern. Subject(StringExpression), /// Commits with author name matching the pattern. AuthorName(StringExpression), /// Commits with author email matching the pattern. AuthorEmail(StringExpression), /// Commits with author dates matching the given date pattern. AuthorDate(DatePattern), /// Commits with committer name matching the pattern. CommitterName(StringExpression), /// Commits with committer email matching the pattern. CommitterEmail(StringExpression), /// Commits with committer dates matching the given date pattern. CommitterDate(DatePattern), /// Commits modifying the paths specified by the fileset. File(FilesetExpression), /// Commits containing diffs matching the `text` pattern within the `files`. DiffLines { text: StringExpression, files: FilesetExpression, }, /// Commits with conflicts HasConflict, /// Commits that are cryptographically signed. Signed, /// Custom predicates provided by extensions Extension(Arc<dyn RevsetFilterExtension>), } mod private { /// Defines [`RevsetExpression`] variants depending on resolution state. pub trait ExpressionState { type CommitRef: Clone; type Operation: Clone; } // Not constructible because these state types just define associated types. #[derive(Debug)] pub enum UserExpressionState {} #[derive(Debug)] pub enum ResolvedExpressionState {} } use private::ExpressionState; use private::ResolvedExpressionState; use private::UserExpressionState; impl ExpressionState for UserExpressionState { type CommitRef = RevsetCommitRef; type Operation = String; } impl ExpressionState for ResolvedExpressionState { type CommitRef = Infallible; type Operation = Infallible; } /// [`RevsetExpression`] that may contain unresolved commit refs. pub type UserRevsetExpression = RevsetExpression<UserExpressionState>; /// [`RevsetExpression`] that never contains unresolved commit refs. pub type ResolvedRevsetExpression = RevsetExpression<ResolvedExpressionState>; /// Tree of revset expressions describing DAG operations. /// /// Use [`UserRevsetExpression`] or [`ResolvedRevsetExpression`] to construct /// expression of that state. #[derive(Clone, Debug)] pub enum RevsetExpression<St: ExpressionState> { None, All, VisibleHeads, /// Visible heads and all referenced commits within the current expression /// scope. Used as the default of `Range`/`DagRange` heads. VisibleHeadsOrReferenced, Root, Commits(Vec<CommitId>), CommitRef(St::CommitRef), Ancestors { heads: Arc<Self>, generation: Range<u64>, parents_range: Range<u32>, }, Descendants { roots: Arc<Self>, generation: Range<u64>, }, // Commits that are ancestors of "heads" but not ancestors of "roots" Range { roots: Arc<Self>, heads: Arc<Self>, generation: Range<u64>, // Parents range is only used for traversing heads, not roots parents_range: Range<u32>, }, // Commits that are descendants of "roots" and ancestors of "heads" DagRange { roots: Arc<Self>, heads: Arc<Self>, // TODO: maybe add generation_from_roots/heads? }, // Commits reachable from "sources" within "domain" Reachable { sources: Arc<Self>, domain: Arc<Self>, }, Heads(Arc<Self>), /// Heads of the set of commits which are ancestors of `heads` but are not /// ancestors of `roots`, and which also are contained in `filter`. HeadsRange { roots: Arc<Self>, heads: Arc<Self>, parents_range: Range<u32>, filter: Arc<Self>, }, Roots(Arc<Self>), ForkPoint(Arc<Self>), Bisect(Arc<Self>), HasSize { candidates: Arc<Self>, count: usize, }, Latest { candidates: Arc<Self>, count: usize, }, Filter(RevsetFilterPredicate), /// Marker for subtree that should be intersected as filter. AsFilter(Arc<Self>), Divergent, /// Resolves symbols and visibility at the specified operation. AtOperation { operation: St::Operation, candidates: Arc<Self>, }, /// Makes `All` include the commits and their ancestors in addition to the /// visible heads. WithinReference { candidates: Arc<Self>, /// Commits explicitly referenced within the scope. commits: Vec<CommitId>, }, /// Resolves visibility within the specified repo state. WithinVisibility { candidates: Arc<Self>, /// Copy of `repo.view().heads()` at the operation. visible_heads: Vec<CommitId>, }, Coalesce(Arc<Self>, Arc<Self>), Present(Arc<Self>), NotIn(Arc<Self>), Union(Arc<Self>, Arc<Self>), Intersection(Arc<Self>, Arc<Self>), Difference(Arc<Self>, Arc<Self>), } // Leaf expression that never contains unresolved commit refs, which can be // either user or resolved expression impl<St: ExpressionState> RevsetExpression<St> { pub fn none() -> Arc<Self> { Arc::new(Self::None) } /// Ancestors of visible heads and all referenced commits within the current /// expression scope, which may include hidden commits. pub fn all() -> Arc<Self> { Arc::new(Self::All) } pub fn visible_heads() -> Arc<Self> { Arc::new(Self::VisibleHeads) } fn visible_heads_or_referenced() -> Arc<Self> { Arc::new(Self::VisibleHeadsOrReferenced) } pub fn root() -> Arc<Self> { Arc::new(Self::Root) } pub fn commit(commit_id: CommitId) -> Arc<Self> { Self::commits(vec![commit_id]) } pub fn commits(commit_ids: Vec<CommitId>) -> Arc<Self> { Arc::new(Self::Commits(commit_ids)) } pub fn filter(predicate: RevsetFilterPredicate) -> Arc<Self> { Arc::new(Self::Filter(predicate)) } pub fn divergent() -> Arc<Self> { Arc::new(Self::AsFilter(Arc::new(Self::Divergent))) } /// Find any empty commits. pub fn is_empty() -> Arc<Self> { Self::filter(RevsetFilterPredicate::File(FilesetExpression::all())).negated() } } // Leaf expression that represents unresolved commit refs impl<St: ExpressionState<CommitRef = RevsetCommitRef>> RevsetExpression<St> { pub fn working_copy(name: WorkspaceNameBuf) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::WorkingCopy(name))) } pub fn working_copies() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::WorkingCopies)) } pub fn symbol(value: String) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Symbol(value))) } pub fn remote_symbol(value: RemoteRefSymbolBuf) -> Arc<Self> { let commit_ref = RevsetCommitRef::RemoteSymbol(value); Arc::new(Self::CommitRef(commit_ref)) } pub fn change_id_prefix(prefix: HexPrefix) -> Arc<Self> { let commit_ref = RevsetCommitRef::ChangeId(prefix); Arc::new(Self::CommitRef(commit_ref)) } pub fn commit_id_prefix(prefix: HexPrefix) -> Arc<Self> { let commit_ref = RevsetCommitRef::CommitId(prefix); Arc::new(Self::CommitRef(commit_ref)) } pub fn bookmarks(expression: StringExpression) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Bookmarks(expression))) } pub fn remote_bookmarks( symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, ) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::RemoteBookmarks { symbol, remote_ref_state, })) } pub fn tags(expression: StringExpression) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::Tags(expression))) } pub fn remote_tags( symbol: RemoteRefSymbolExpression, remote_ref_state: Option<RemoteRefState>, ) -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::RemoteTags { symbol, remote_ref_state, })) } pub fn git_refs() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::GitRefs)) } pub fn git_head() -> Arc<Self> { Arc::new(Self::CommitRef(RevsetCommitRef::GitHead)) } } // Compound expression impl<St: ExpressionState> RevsetExpression<St> { pub fn latest(self: &Arc<Self>, count: usize) -> Arc<Self> { Arc::new(Self::Latest { candidates: self.clone(), count, }) } /// Commits in `self` that don't have descendants in `self`. pub fn heads(self: &Arc<Self>) -> Arc<Self> { Arc::new(Self::Heads(self.clone())) } /// Commits in `self` that don't have ancestors in `self`. pub fn roots(self: &Arc<Self>) -> Arc<Self> { Arc::new(Self::Roots(self.clone())) } /// Parents of `self`. pub fn parents(self: &Arc<Self>) -> Arc<Self> { self.ancestors_at(1) } /// Ancestors of `self`, including `self`. pub fn ancestors(self: &Arc<Self>) -> Arc<Self> { self.ancestors_range(GENERATION_RANGE_FULL) } /// Ancestors of `self` at an offset of `generation` behind `self`. /// The `generation` offset is zero-based starting from `self`. pub fn ancestors_at(self: &Arc<Self>, generation: u64) -> Arc<Self> { self.ancestors_range(generation..generation.saturating_add(1)) } /// Ancestors of `self` in the given range. pub fn ancestors_range(self: &Arc<Self>, generation_range: Range<u64>) -> Arc<Self> { Arc::new(Self::Ancestors { heads: self.clone(), generation: generation_range, parents_range: PARENTS_RANGE_FULL, })