diff --git a/git-branchless/src/commands/hide.rs b/git-branchless/src/commands/hide.rs index 465ff346b..c8808f162 100644 --- a/git-branchless/src/commands/hide.rs +++ b/git-branchless/src/commands/hide.rs @@ -46,7 +46,8 @@ pub fn hide( &references_snapshot, )?; - let commit_sets = match resolve_commits(effects, &repo, &mut dag, revsets) { + let commit_sets = match resolve_commits(effects, &repo, &mut dag, &references_snapshot, revsets) + { Ok(commit_sets) => commit_sets, Err(err) => { err.describe(effects)?; @@ -198,7 +199,8 @@ pub fn unhide(effects: &Effects, revsets: Vec, recursive: bool) -> eyre: &references_snapshot, )?; - let commit_sets = match resolve_commits(effects, &repo, &mut dag, revsets) { + let commit_sets = match resolve_commits(effects, &repo, &mut dag, &references_snapshot, revsets) + { Ok(commit_sets) => commit_sets, Err(err) => { err.describe(effects)?; diff --git a/git-branchless/src/commands/move.rs b/git-branchless/src/commands/move.rs index b7c3e30c0..d44a03d57 100644 --- a/git-branchless/src/commands/move.rs +++ b/git-branchless/src/commands/move.rs @@ -100,21 +100,29 @@ pub fn r#move( &references_snapshot, )?; - let source_oids: CommitSet = match resolve_commits(effects, &repo, &mut dag, sources) { - Ok(commit_sets) => union_all(&commit_sets), - Err(err) => { - err.describe(effects)?; - return Ok(ExitCode(1)); - } - }; - let base_oids: CommitSet = match resolve_commits(effects, &repo, &mut dag, bases) { - Ok(commit_sets) => union_all(&commit_sets), - Err(err) => { - err.describe(effects)?; - return Ok(ExitCode(1)); - } - }; - let exact_components = match resolve_commits(effects, &repo, &mut dag, exacts) { + let source_oids: CommitSet = + match resolve_commits(effects, &repo, &mut dag, &references_snapshot, sources) { + Ok(commit_sets) => union_all(&commit_sets), + Err(err) => { + err.describe(effects)?; + return Ok(ExitCode(1)); + } + }; + let base_oids: CommitSet = + match resolve_commits(effects, &repo, &mut dag, &references_snapshot, bases) { + Ok(commit_sets) => union_all(&commit_sets), + Err(err) => { + err.describe(effects)?; + return Ok(ExitCode(1)); + } + }; + let exact_components = match resolve_commits( + effects, + &repo, + &mut dag, + &references_snapshot, + exacts, + ) { Ok(commit_sets) => { let exact_oids = union_all(&commit_sets); let mut components: HashMap = HashMap::new(); @@ -159,7 +167,13 @@ pub fn r#move( } }; - let dest_oid: NonZeroOid = match resolve_commits(effects, &repo, &mut dag, vec![dest.clone()]) { + let dest_oid: NonZeroOid = match resolve_commits( + effects, + &repo, + &mut dag, + &references_snapshot, + vec![dest.clone()], + ) { Ok(commit_sets) => match commit_set_to_vec_unsorted(&commit_sets[0])?.as_slice() { [only_commit_oid] => *only_commit_oid, other => { diff --git a/git-branchless/src/commands/query.rs b/git-branchless/src/commands/query.rs index 7f7203053..5a5dc39aa 100644 --- a/git-branchless/src/commands/query.rs +++ b/git-branchless/src/commands/query.rs @@ -34,13 +34,14 @@ pub fn query( &references_snapshot, )?; - let commit_set = match resolve_commits(effects, &repo, &mut dag, vec![query]) { - Ok(commit_sets) => commit_sets[0].clone(), - Err(err) => { - err.describe(effects)?; - return Ok(ExitCode(1)); - } - }; + let commit_set = + match resolve_commits(effects, &repo, &mut dag, &references_snapshot, vec![query]) { + Ok(commit_sets) => commit_sets[0].clone(), + Err(err) => { + err.describe(effects)?; + return Ok(ExitCode(1)); + } + }; if show_branches { let commit_oids = { diff --git a/git-branchless/src/commands/restack.rs b/git-branchless/src/commands/restack.rs index 0763d4530..064d9bc69 100644 --- a/git-branchless/src/commands/restack.rs +++ b/git-branchless/src/commands/restack.rs @@ -278,7 +278,8 @@ pub fn restack( &references_snapshot, )?; - let commit_sets = match resolve_commits(effects, &repo, &mut dag, revsets) { + let commit_sets = match resolve_commits(effects, &repo, &mut dag, &references_snapshot, revsets) + { Ok(commit_sets) => commit_sets, Err(err) => { err.describe(effects)?; diff --git a/git-branchless/src/commands/reword.rs b/git-branchless/src/commands/reword.rs index cf188c503..d6c52bc8c 100644 --- a/git-branchless/src/commands/reword.rs +++ b/git-branchless/src/commands/reword.rs @@ -289,7 +289,8 @@ fn resolve_commits_from_hashes<'repo>( revsets }; - let commit_sets = match resolve_commits(effects, repo, dag, hashes) { + let references_snapshot = repo.get_references_snapshot()?; + let commit_sets = match resolve_commits(effects, repo, dag, &references_snapshot, hashes) { Ok(commit_sets) => commit_sets, Err(err) => { err.describe(effects)?; diff --git a/git-branchless/src/commands/smartlog.rs b/git-branchless/src/commands/smartlog.rs index 145235538..758df2aff 100644 --- a/git-branchless/src/commands/smartlog.rs +++ b/git-branchless/src/commands/smartlog.rs @@ -618,8 +618,13 @@ pub fn smartlog( if *show_hidden_commits { swap(&mut dag.obsolete_commits, &mut old_obsolete_commits); } - let observed_commits = match resolve_commits(effects, &repo, &mut dag, vec![revset.clone()]) - { + let observed_commits = match resolve_commits( + effects, + &repo, + &mut dag, + &references_snapshot, + vec![revset.clone()], + ) { Ok(result) => match result.as_slice() { [commit_set] => commit_set.clone(), other => panic!( diff --git a/git-branchless/src/commands/sync.rs b/git-branchless/src/commands/sync.rs index 101632993..70e58d00f 100644 --- a/git-branchless/src/commands/sync.rs +++ b/git-branchless/src/commands/sync.rs @@ -75,7 +75,8 @@ pub fn sync( &references_snapshot, )?; - let commit_sets = match resolve_commits(effects, &repo, &mut dag, revsets) { + let commit_sets = match resolve_commits(effects, &repo, &mut dag, &references_snapshot, revsets) + { Ok(commit_sets) => commit_sets, Err(err) => { err.describe(effects)?; diff --git a/git-branchless/src/revset/eval.rs b/git-branchless/src/revset/eval.rs index 4706ad75d..5a12b8483 100644 --- a/git-branchless/src/revset/eval.rs +++ b/git-branchless/src/revset/eval.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::convert::TryFrom; +use std::ffi::OsString; use std::num::ParseIntError; use std::sync::Arc; @@ -8,11 +9,12 @@ use eyre::Context as EyreContext; use itertools::Itertools; use lazy_static::lazy_static; use lib::core::effects::{Effects, OperationType}; +use lib::core::repo_ext::RepoReferencesSnapshot; use once_cell::unsync::OnceCell; use thiserror::Error; use lib::core::dag::{CommitSet, Dag}; -use lib::git::{Repo, ResolvedReferenceInfo}; +use lib::git::Repo; use tracing::instrument; use super::Expr; @@ -22,6 +24,7 @@ struct Context<'a> { effects: &'a Effects, repo: &'a Repo, dag: &'a mut Dag, + references_snapshot: &'a RepoReferencesSnapshot, public_commits: OnceCell, active_heads: OnceCell, active_commits: OnceCell, @@ -127,7 +130,13 @@ pub type EvalResult = Result; /// Evaluate the provided revset expression. #[instrument] -pub fn eval(effects: &Effects, repo: &Repo, dag: &mut Dag, expr: &Expr) -> EvalResult { +pub fn eval( + effects: &Effects, + repo: &Repo, + dag: &mut Dag, + references_snapshot: &RepoReferencesSnapshot, + expr: &Expr, +) -> EvalResult { let (effects, _progress) = effects.start_operation(OperationType::EvaluateRevset(Arc::new(expr.to_string()))); @@ -135,6 +144,7 @@ pub fn eval(effects: &Effects, repo: &Repo, dag: &mut Dag, expr: &Expr) -> EvalR effects: &effects, repo, dag, + references_snapshot, public_commits: Default::default(), active_heads: Default::default(), active_commits: Default::default(), @@ -154,14 +164,25 @@ fn eval_inner(ctx: &mut Context, expr: &Expr) -> EvalResult { fn eval_name(ctx: &mut Context, name: &str) -> EvalResult { if name == "." || name == "@" { - let head_info = ctx.repo.get_head_info(); - if let Ok(ResolvedReferenceInfo { - oid: Some(oid), - reference_name: _, - }) = head_info - { - return Ok(oid.into()); - } + return Ok(CommitSet::from_iter( + ctx.references_snapshot.head_oid.map(|oid| Ok(oid.into())), + )); + } + + let branch_name = OsString::from(format!("refs/heads/{name}")); + if let Some(branch_oid) = + ctx.references_snapshot + .branch_oid_to_names + .iter() + .find_map(|(k, v)| { + if v.contains(&branch_name) { + Some(*k) + } else { + None + } + }) + { + return Ok(CommitSet::from(branch_oid)); } let commit = ctx.repo.revparse_single_commit(name); @@ -240,7 +261,13 @@ fn eval_fn(ctx: &mut Context, name: &str, args: &[Expr]) -> EvalResult { } fn fn_branches(ctx: &mut Context, name: &str, args: &[Expr]) -> EvalResult { eval0(ctx, name, args)?; - Ok(ctx.dag.branch_commits.clone()) + Ok(ctx + .references_snapshot + .branch_oid_to_names + .keys() + .copied() + .map(|oid| oid.into()) + .collect()) } fn fn_nthparent(ctx: &mut Context, name: &str, args: &[Expr]) -> EvalResult { let (lhs, n) = eval_number_rhs(ctx, name, args)?; @@ -444,7 +471,8 @@ mod tests { dag: &mut Dag, expr: &Expr, ) -> eyre::Result>> { - let result = eval(effects, repo, dag, expr)?; + let references_snapshot = repo.get_references_snapshot()?; + let result = eval(effects, repo, dag, &references_snapshot, expr)?; let mut commits: Vec = commit_set_to_vec_unsorted(&result)? .into_iter() .map(|oid| repo.find_commit_or_fail(oid)) diff --git a/git-branchless/src/revset/resolve.rs b/git-branchless/src/revset/resolve.rs index aad1e73f0..8b0819e49 100644 --- a/git-branchless/src/revset/resolve.rs +++ b/git-branchless/src/revset/resolve.rs @@ -2,6 +2,7 @@ use std::fmt::Write; use lib::core::dag::{CommitSet, Dag}; use lib::core::effects::Effects; +use lib::core::repo_ext::RepoReferencesSnapshot; use lib::git::Repo; use tracing::instrument; @@ -58,6 +59,7 @@ pub fn resolve_commits( effects: &Effects, repo: &Repo, dag: &mut Dag, + references_snapshot: &RepoReferencesSnapshot, revsets: Vec, ) -> Result, ResolveError> { let mut commit_sets = Vec::new(); @@ -66,9 +68,11 @@ pub fn resolve_commits( expr: revset.clone(), source: err, })?; - let commits = eval(effects, repo, dag, &expr).map_err(|err| ResolveError::EvalError { - expr: revset.clone(), - source: err, + let commits = eval(effects, repo, dag, references_snapshot, &expr).map_err(|err| { + ResolveError::EvalError { + expr: revset.clone(), + source: err, + } })?; commit_sets.push(commits); }