mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-10 14:16:24 +03:00
revsets: add syntax for a particular workspace's checkout (#13)
Because we record each workspace's checkout in the repo view, we can -- unlike other VCSs -- let the user refer to any workspace's checkout in revsets. This patch adds syntax for that, so you can show the contents of the checkout in workspace "foo" with `jj show foo@`. That won't automatically commit that workspace's working copy, however.
This commit is contained in:
parent
5b46fa3282
commit
012b4c4d8e
@ -27,6 +27,7 @@ use thiserror::Error;
|
|||||||
use crate::backend::{BackendError, BackendResult, CommitId};
|
use crate::backend::{BackendError, BackendResult, CommitId};
|
||||||
use crate::commit::Commit;
|
use crate::commit::Commit;
|
||||||
use crate::index::{HexPrefix, IndexEntry, IndexPosition, PrefixResolution, RevWalk};
|
use crate::index::{HexPrefix, IndexEntry, IndexPosition, PrefixResolution, RevWalk};
|
||||||
|
use crate::op_store::WorkspaceId;
|
||||||
use crate::repo::RepoRef;
|
use crate::repo::RepoRef;
|
||||||
use crate::revset_graph_iterator::RevsetGraphIterator;
|
use crate::revset_graph_iterator::RevsetGraphIterator;
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
@ -102,7 +103,7 @@ fn resolve_change_id(repo: RepoRef, change_id_prefix: &str) -> Result<Vec<Commit
|
|||||||
let mut found_change_id = None;
|
let mut found_change_id = None;
|
||||||
let mut commit_ids = vec![];
|
let mut commit_ids = vec![];
|
||||||
// TODO: Create a persistent lookup from change id to (visible?) commit ids.
|
// TODO: Create a persistent lookup from change id to (visible?) commit ids.
|
||||||
for index_entry in RevsetExpression::all().evaluate(repo).unwrap().iter() {
|
for index_entry in RevsetExpression::all().evaluate(repo, None).unwrap().iter() {
|
||||||
let change_id = index_entry.change_id();
|
let change_id = index_entry.change_id();
|
||||||
if change_id.hex().starts_with(hex_prefix.hex()) {
|
if change_id.hex().starts_with(hex_prefix.hex()) {
|
||||||
if let Some(previous_change_id) = found_change_id.replace(change_id.clone()) {
|
if let Some(previous_change_id) = found_change_id.replace(change_id.clone()) {
|
||||||
@ -124,9 +125,26 @@ fn resolve_change_id(repo: RepoRef, change_id_prefix: &str) -> Result<Vec<Commit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_symbol(repo: RepoRef, symbol: &str) -> Result<Vec<CommitId>, RevsetError> {
|
pub fn resolve_symbol(
|
||||||
if symbol == "@" {
|
repo: RepoRef,
|
||||||
Ok(vec![repo.view().checkout().clone()])
|
symbol: &str,
|
||||||
|
workspace_id: Option<&WorkspaceId>,
|
||||||
|
) -> Result<Vec<CommitId>, RevsetError> {
|
||||||
|
if symbol.ends_with('@') {
|
||||||
|
let target_workspace = if symbol == "@" {
|
||||||
|
if let Some(workspace_id) = workspace_id {
|
||||||
|
workspace_id.clone()
|
||||||
|
} else {
|
||||||
|
return Err(RevsetError::NoSuchRevision(symbol.to_owned()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WorkspaceId::new(symbol.strip_suffix('@').unwrap().to_string())
|
||||||
|
};
|
||||||
|
if let Some(commit_id) = repo.view().get_checkout(&target_workspace) {
|
||||||
|
Ok(vec![commit_id.clone()])
|
||||||
|
} else {
|
||||||
|
Err(RevsetError::NoSuchRevision(symbol.to_owned()))
|
||||||
|
}
|
||||||
} else if symbol == "root" {
|
} else if symbol == "root" {
|
||||||
Ok(vec![repo.store().root_commit_id().clone()])
|
Ok(vec![repo.store().root_commit_id().clone()])
|
||||||
} else {
|
} else {
|
||||||
@ -387,8 +405,9 @@ impl RevsetExpression {
|
|||||||
pub fn evaluate<'repo>(
|
pub fn evaluate<'repo>(
|
||||||
&self,
|
&self,
|
||||||
repo: RepoRef<'repo>,
|
repo: RepoRef<'repo>,
|
||||||
|
workspace_id: Option<&WorkspaceId>,
|
||||||
) -> Result<Box<dyn Revset<'repo> + 'repo>, RevsetError> {
|
) -> Result<Box<dyn Revset<'repo> + 'repo>, RevsetError> {
|
||||||
evaluate_expression(repo, self)
|
evaluate_expression(repo, self, workspace_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,6 +1088,7 @@ impl<'revset, 'repo> Iterator for DifferenceRevsetIterator<'revset, 'repo> {
|
|||||||
pub fn evaluate_expression<'repo>(
|
pub fn evaluate_expression<'repo>(
|
||||||
repo: RepoRef<'repo>,
|
repo: RepoRef<'repo>,
|
||||||
expression: &RevsetExpression,
|
expression: &RevsetExpression,
|
||||||
|
workspace_id: Option<&WorkspaceId>,
|
||||||
) -> Result<Box<dyn Revset<'repo> + 'repo>, RevsetError> {
|
) -> Result<Box<dyn Revset<'repo> + 'repo>, RevsetError> {
|
||||||
match expression {
|
match expression {
|
||||||
RevsetExpression::None => Ok(Box::new(EagerRevset {
|
RevsetExpression::None => Ok(Box::new(EagerRevset {
|
||||||
@ -1076,12 +1096,12 @@ pub fn evaluate_expression<'repo>(
|
|||||||
})),
|
})),
|
||||||
RevsetExpression::Commits(commit_ids) => Ok(revset_for_commit_ids(repo, commit_ids)),
|
RevsetExpression::Commits(commit_ids) => Ok(revset_for_commit_ids(repo, commit_ids)),
|
||||||
RevsetExpression::Symbol(symbol) => {
|
RevsetExpression::Symbol(symbol) => {
|
||||||
let commit_ids = resolve_symbol(repo, symbol)?;
|
let commit_ids = resolve_symbol(repo, symbol, workspace_id)?;
|
||||||
evaluate_expression(repo, &RevsetExpression::Commits(commit_ids))
|
evaluate_expression(repo, &RevsetExpression::Commits(commit_ids), workspace_id)
|
||||||
}
|
}
|
||||||
RevsetExpression::Parents(base_expression) => {
|
RevsetExpression::Parents(base_expression) => {
|
||||||
// TODO: Make this lazy
|
// TODO: Make this lazy
|
||||||
let base_set = base_expression.evaluate(repo)?;
|
let base_set = base_expression.evaluate(repo, workspace_id)?;
|
||||||
let mut parent_entries = base_set
|
let mut parent_entries = base_set
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|entry| entry.parents())
|
.flat_map(|entry| entry.parents())
|
||||||
@ -1093,9 +1113,9 @@ pub fn evaluate_expression<'repo>(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
RevsetExpression::Children(roots) => {
|
RevsetExpression::Children(roots) => {
|
||||||
let root_set = roots.evaluate(repo)?;
|
let root_set = roots.evaluate(repo, workspace_id)?;
|
||||||
let candidates_expression = roots.descendants();
|
let candidates_expression = roots.descendants();
|
||||||
let candidate_set = candidates_expression.evaluate(repo)?;
|
let candidate_set = candidates_expression.evaluate(repo, workspace_id)?;
|
||||||
Ok(Box::new(ChildrenRevset {
|
Ok(Box::new(ChildrenRevset {
|
||||||
root_set,
|
root_set,
|
||||||
candidate_set,
|
candidate_set,
|
||||||
@ -1103,11 +1123,11 @@ pub fn evaluate_expression<'repo>(
|
|||||||
}
|
}
|
||||||
RevsetExpression::Ancestors(base_expression) => RevsetExpression::none()
|
RevsetExpression::Ancestors(base_expression) => RevsetExpression::none()
|
||||||
.range(base_expression)
|
.range(base_expression)
|
||||||
.evaluate(repo),
|
.evaluate(repo, workspace_id),
|
||||||
RevsetExpression::Range { roots, heads } => {
|
RevsetExpression::Range { roots, heads } => {
|
||||||
let root_set = roots.evaluate(repo)?;
|
let root_set = roots.evaluate(repo, workspace_id)?;
|
||||||
let root_ids = root_set.iter().commit_ids().collect_vec();
|
let root_ids = root_set.iter().commit_ids().collect_vec();
|
||||||
let head_set = heads.evaluate(repo)?;
|
let head_set = heads.evaluate(repo, workspace_id)?;
|
||||||
let head_ids = head_set.iter().commit_ids().collect_vec();
|
let head_ids = head_set.iter().commit_ids().collect_vec();
|
||||||
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
||||||
Ok(Box::new(RevWalkRevset { walk }))
|
Ok(Box::new(RevWalkRevset { walk }))
|
||||||
@ -1116,8 +1136,8 @@ pub fn evaluate_expression<'repo>(
|
|||||||
// reverse
|
// reverse
|
||||||
#[allow(clippy::needless_collect)]
|
#[allow(clippy::needless_collect)]
|
||||||
RevsetExpression::DagRange { roots, heads } => {
|
RevsetExpression::DagRange { roots, heads } => {
|
||||||
let root_set = roots.evaluate(repo)?;
|
let root_set = roots.evaluate(repo, workspace_id)?;
|
||||||
let candidate_set = heads.ancestors().evaluate(repo)?;
|
let candidate_set = heads.ancestors().evaluate(repo, workspace_id)?;
|
||||||
let mut reachable: HashSet<_> = root_set.iter().map(|entry| entry.position()).collect();
|
let mut reachable: HashSet<_> = root_set.iter().map(|entry| entry.position()).collect();
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let candidates = candidate_set.iter().collect_vec();
|
let candidates = candidate_set.iter().collect_vec();
|
||||||
@ -1142,7 +1162,7 @@ pub fn evaluate_expression<'repo>(
|
|||||||
&repo.view().heads().iter().cloned().collect_vec(),
|
&repo.view().heads().iter().cloned().collect_vec(),
|
||||||
)),
|
)),
|
||||||
RevsetExpression::HeadsOf(candidates) => {
|
RevsetExpression::HeadsOf(candidates) => {
|
||||||
let candidate_set = candidates.evaluate(repo)?;
|
let candidate_set = candidates.evaluate(repo, workspace_id)?;
|
||||||
let candidate_ids = candidate_set.iter().commit_ids().collect_vec();
|
let candidate_ids = candidate_set.iter().commit_ids().collect_vec();
|
||||||
Ok(revset_for_commit_ids(
|
Ok(revset_for_commit_ids(
|
||||||
repo,
|
repo,
|
||||||
@ -1153,7 +1173,7 @@ pub fn evaluate_expression<'repo>(
|
|||||||
candidates,
|
candidates,
|
||||||
parent_count_range,
|
parent_count_range,
|
||||||
} => {
|
} => {
|
||||||
let candidates = candidates.evaluate(repo)?;
|
let candidates = candidates.evaluate(repo, workspace_id)?;
|
||||||
let parent_count_range = parent_count_range.clone();
|
let parent_count_range = parent_count_range.clone();
|
||||||
Ok(Box::new(FilterRevset {
|
Ok(Box::new(FilterRevset {
|
||||||
candidates,
|
candidates,
|
||||||
@ -1201,7 +1221,7 @@ pub fn evaluate_expression<'repo>(
|
|||||||
Ok(revset_for_commit_ids(repo, &commit_ids))
|
Ok(revset_for_commit_ids(repo, &commit_ids))
|
||||||
}
|
}
|
||||||
RevsetExpression::Description { needle, candidates } => {
|
RevsetExpression::Description { needle, candidates } => {
|
||||||
let candidates = candidates.evaluate(repo)?;
|
let candidates = candidates.evaluate(repo, workspace_id)?;
|
||||||
let repo = repo;
|
let repo = repo;
|
||||||
let needle = needle.clone();
|
let needle = needle.clone();
|
||||||
Ok(Box::new(FilterRevset {
|
Ok(Box::new(FilterRevset {
|
||||||
@ -1216,7 +1236,7 @@ pub fn evaluate_expression<'repo>(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
RevsetExpression::Author { needle, candidates } => {
|
RevsetExpression::Author { needle, candidates } => {
|
||||||
let candidates = candidates.evaluate(repo)?;
|
let candidates = candidates.evaluate(repo, workspace_id)?;
|
||||||
let repo = repo;
|
let repo = repo;
|
||||||
let needle = needle.clone();
|
let needle = needle.clone();
|
||||||
// TODO: Make these functions that take a needle to search for accept some
|
// TODO: Make these functions that take a needle to search for accept some
|
||||||
@ -1232,7 +1252,7 @@ pub fn evaluate_expression<'repo>(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
RevsetExpression::Committer { needle, candidates } => {
|
RevsetExpression::Committer { needle, candidates } => {
|
||||||
let candidates = candidates.evaluate(repo)?;
|
let candidates = candidates.evaluate(repo, workspace_id)?;
|
||||||
let repo = repo;
|
let repo = repo;
|
||||||
let needle = needle.clone();
|
let needle = needle.clone();
|
||||||
Ok(Box::new(FilterRevset {
|
Ok(Box::new(FilterRevset {
|
||||||
@ -1245,18 +1265,18 @@ pub fn evaluate_expression<'repo>(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
RevsetExpression::Union(expression1, expression2) => {
|
RevsetExpression::Union(expression1, expression2) => {
|
||||||
let set1 = expression1.evaluate(repo)?;
|
let set1 = expression1.evaluate(repo, workspace_id)?;
|
||||||
let set2 = expression2.evaluate(repo)?;
|
let set2 = expression2.evaluate(repo, workspace_id)?;
|
||||||
Ok(Box::new(UnionRevset { set1, set2 }))
|
Ok(Box::new(UnionRevset { set1, set2 }))
|
||||||
}
|
}
|
||||||
RevsetExpression::Intersection(expression1, expression2) => {
|
RevsetExpression::Intersection(expression1, expression2) => {
|
||||||
let set1 = expression1.evaluate(repo)?;
|
let set1 = expression1.evaluate(repo, workspace_id)?;
|
||||||
let set2 = expression2.evaluate(repo)?;
|
let set2 = expression2.evaluate(repo, workspace_id)?;
|
||||||
Ok(Box::new(IntersectionRevset { set1, set2 }))
|
Ok(Box::new(IntersectionRevset { set1, set2 }))
|
||||||
}
|
}
|
||||||
RevsetExpression::Difference(expression1, expression2) => {
|
RevsetExpression::Difference(expression1, expression2) => {
|
||||||
let set1 = expression1.evaluate(repo)?;
|
let set1 = expression1.evaluate(repo, workspace_id)?;
|
||||||
let set2 = expression2.evaluate(repo)?;
|
let set2 = expression2.evaluate(repo, workspace_id)?;
|
||||||
Ok(Box::new(DifferenceRevset { set1, set2 }))
|
Ok(Box::new(DifferenceRevset { set1, set2 }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> {
|
|||||||
.parents()
|
.parents()
|
||||||
.minus(&old_commits_expression);
|
.minus(&old_commits_expression);
|
||||||
let heads_to_add = heads_to_add_expression
|
let heads_to_add = heads_to_add_expression
|
||||||
.evaluate(mut_repo.as_repo_ref())
|
.evaluate(mut_repo.as_repo_ref(), None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.commit_ids()
|
.commit_ids()
|
||||||
@ -164,7 +164,7 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> {
|
|||||||
|
|
||||||
let to_visit_expression = old_commits_expression.descendants();
|
let to_visit_expression = old_commits_expression.descendants();
|
||||||
let to_visit_revset = to_visit_expression
|
let to_visit_revset = to_visit_expression
|
||||||
.evaluate(mut_repo.as_repo_ref())
|
.evaluate(mut_repo.as_repo_ref(), None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let to_visit_entries = to_visit_revset.iter().collect_vec();
|
let to_visit_entries = to_visit_revset.iter().collect_vec();
|
||||||
drop(to_visit_revset);
|
drop(to_visit_revset);
|
||||||
|
@ -29,7 +29,7 @@ fn test_resolve_symbol_root(use_git: bool) {
|
|||||||
let repo = &test_workspace.repo;
|
let repo = &test_workspace.repo;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo.as_repo_ref(), "root"),
|
resolve_symbol(repo.as_repo_ref(), "root", None),
|
||||||
Ok(vec![repo.store().root_commit_id().clone()])
|
Ok(vec![repo.store().root_commit_id().clone()])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -84,39 +84,39 @@ fn test_resolve_symbol_commit_id() {
|
|||||||
// Test lookup by full commit id
|
// Test lookup by full commit id
|
||||||
let repo_ref = repo.as_repo_ref();
|
let repo_ref = repo.as_repo_ref();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "0454de3cae04c46cda37ba2e8873b4c17ff51dcb"),
|
resolve_symbol(repo_ref, "0454de3cae04c46cda37ba2e8873b4c17ff51dcb", None),
|
||||||
Ok(vec![commits[0].id().clone()])
|
Ok(vec![commits[0].id().clone()])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "045f56cd1b17e8abde86771e2705395dcde6a957"),
|
resolve_symbol(repo_ref, "045f56cd1b17e8abde86771e2705395dcde6a957", None),
|
||||||
Ok(vec![commits[1].id().clone()])
|
Ok(vec![commits[1].id().clone()])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "0468f7da8de2ce442f512aacf83411d26cd2e0cf"),
|
resolve_symbol(repo_ref, "0468f7da8de2ce442f512aacf83411d26cd2e0cf", None),
|
||||||
Ok(vec![commits[2].id().clone()])
|
Ok(vec![commits[2].id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test commit id prefix
|
// Test commit id prefix
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "046"),
|
resolve_symbol(repo_ref, "046", None),
|
||||||
Ok(vec![commits[2].id().clone()])
|
Ok(vec![commits[2].id().clone()])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04"),
|
resolve_symbol(repo_ref, "04", None),
|
||||||
Err(RevsetError::AmbiguousCommitIdPrefix("04".to_string()))
|
Err(RevsetError::AmbiguousCommitIdPrefix("04".to_string()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, ""),
|
resolve_symbol(repo_ref, "", None),
|
||||||
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "040"),
|
resolve_symbol(repo_ref, "040", None),
|
||||||
Err(RevsetError::NoSuchRevision("040".to_string()))
|
Err(RevsetError::NoSuchRevision("040".to_string()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test non-hex string
|
// Test non-hex string
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "foo"),
|
resolve_symbol(repo_ref, "foo", None),
|
||||||
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -183,19 +183,19 @@ fn test_resolve_symbol_change_id() {
|
|||||||
// Test lookup by full change id
|
// Test lookup by full change id
|
||||||
let repo_ref = repo.as_repo_ref();
|
let repo_ref = repo.as_repo_ref();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e12a5467bba790efb88a9870894ec2"),
|
resolve_symbol(repo_ref, "04e12a5467bba790efb88a9870894ec2", None),
|
||||||
Ok(vec![CommitId::from_hex(
|
Ok(vec![CommitId::from_hex(
|
||||||
"8fd68d104372910e19511df709e5dde62a548720"
|
"8fd68d104372910e19511df709e5dde62a548720"
|
||||||
)])
|
)])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "040b3ba3a51d8edbc4c5855cbd09de71"),
|
resolve_symbol(repo_ref, "040b3ba3a51d8edbc4c5855cbd09de71", None),
|
||||||
Ok(vec![CommitId::from_hex(
|
Ok(vec![CommitId::from_hex(
|
||||||
"5339432b8e7b90bd3aa1a323db71b8a5c5dcd020"
|
"5339432b8e7b90bd3aa1a323db71b8a5c5dcd020"
|
||||||
)])
|
)])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e1c7082e4e34f3f371d8a1a46770b8"),
|
resolve_symbol(repo_ref, "04e1c7082e4e34f3f371d8a1a46770b8", None),
|
||||||
Ok(vec![CommitId::from_hex(
|
Ok(vec![CommitId::from_hex(
|
||||||
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
||||||
)])
|
)])
|
||||||
@ -203,34 +203,34 @@ fn test_resolve_symbol_change_id() {
|
|||||||
|
|
||||||
// Test change id prefix
|
// Test change id prefix
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e12"),
|
resolve_symbol(repo_ref, "04e12", None),
|
||||||
Ok(vec![CommitId::from_hex(
|
Ok(vec![CommitId::from_hex(
|
||||||
"8fd68d104372910e19511df709e5dde62a548720"
|
"8fd68d104372910e19511df709e5dde62a548720"
|
||||||
)])
|
)])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e1c"),
|
resolve_symbol(repo_ref, "04e1c", None),
|
||||||
Ok(vec![CommitId::from_hex(
|
Ok(vec![CommitId::from_hex(
|
||||||
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
||||||
)])
|
)])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e1"),
|
resolve_symbol(repo_ref, "04e1", None),
|
||||||
Err(RevsetError::AmbiguousChangeIdPrefix("04e1".to_string()))
|
Err(RevsetError::AmbiguousChangeIdPrefix("04e1".to_string()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, ""),
|
resolve_symbol(repo_ref, "", None),
|
||||||
// Commit id is checked first, so this is considered an ambiguous commit id
|
// Commit id is checked first, so this is considered an ambiguous commit id
|
||||||
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "04e13"),
|
resolve_symbol(repo_ref, "04e13", None),
|
||||||
Err(RevsetError::NoSuchRevision("04e13".to_string()))
|
Err(RevsetError::NoSuchRevision("04e13".to_string()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test non-hex string
|
// Test non-hex string
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(repo_ref, "foo"),
|
resolve_symbol(repo_ref, "foo", None),
|
||||||
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -248,14 +248,40 @@ fn test_resolve_symbol_checkout(use_git: bool) {
|
|||||||
let commit1 = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo);
|
let commit1 = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo);
|
||||||
let commit2 = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo);
|
let commit2 = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo);
|
||||||
|
|
||||||
mut_repo.set_checkout(WorkspaceId::default(), commit1.id().clone());
|
let ws1 = WorkspaceId::new("ws1".to_string());
|
||||||
|
let ws2 = WorkspaceId::new("ws2".to_string());
|
||||||
|
mut_repo.remove_checkout(&WorkspaceId::default());
|
||||||
|
|
||||||
|
// With no workspaces, no variation can be resolved
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
resolve_symbol(mut_repo.as_repo_ref(), "@", None),
|
||||||
|
Err(RevsetError::NoSuchRevision("@".to_string()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
resolve_symbol(mut_repo.as_repo_ref(), "@", Some(&ws1)),
|
||||||
|
Err(RevsetError::NoSuchRevision("@".to_string()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
resolve_symbol(mut_repo.as_repo_ref(), "ws1@", Some(&ws1)),
|
||||||
|
Err(RevsetError::NoSuchRevision("ws1@".to_string()))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add some workspaces
|
||||||
|
mut_repo.set_checkout(ws1.clone(), commit1.id().clone());
|
||||||
|
mut_repo.set_checkout(ws2, commit2.id().clone());
|
||||||
|
// @ cannot be resolved without a default workspace ID
|
||||||
|
assert_eq!(
|
||||||
|
resolve_symbol(mut_repo.as_repo_ref(), "@", None),
|
||||||
|
Err(RevsetError::NoSuchRevision("@".to_string()))
|
||||||
|
);
|
||||||
|
// Can resolve "@" shorthand with a default workspace ID
|
||||||
|
assert_eq!(
|
||||||
|
resolve_symbol(mut_repo.as_repo_ref(), "@", Some(&ws1)),
|
||||||
Ok(vec![commit1.id().clone()])
|
Ok(vec![commit1.id().clone()])
|
||||||
);
|
);
|
||||||
mut_repo.set_checkout(WorkspaceId::default(), commit2.id().clone());
|
// Can resolve an explicit checkout
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
resolve_symbol(mut_repo.as_repo_ref(), "ws2@", Some(&ws1)),
|
||||||
Ok(vec![commit2.id().clone()])
|
Ok(vec![commit2.id().clone()])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -301,7 +327,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
|
|
||||||
// Non-existent ref
|
// Non-existent ref
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "non-existent"),
|
resolve_symbol(mut_repo.as_repo_ref(), "non-existent", None),
|
||||||
Err(RevsetError::NoSuchRevision("non-existent".to_string()))
|
Err(RevsetError::NoSuchRevision("non-existent".to_string()))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -311,7 +337,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
RefTarget::Normal(commit4.id().clone()),
|
RefTarget::Normal(commit4.id().clone()),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/branch"),
|
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/branch", None),
|
||||||
Ok(vec![commit4.id().clone()])
|
Ok(vec![commit4.id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -325,7 +351,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
RefTarget::Normal(commit4.id().clone()),
|
RefTarget::Normal(commit4.id().clone()),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "heads/branch"),
|
resolve_symbol(mut_repo.as_repo_ref(), "heads/branch", None),
|
||||||
Ok(vec![commit5.id().clone()])
|
Ok(vec![commit5.id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -339,7 +365,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
RefTarget::Normal(commit4.id().clone()),
|
RefTarget::Normal(commit4.id().clone()),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "branch"),
|
resolve_symbol(mut_repo.as_repo_ref(), "branch", None),
|
||||||
Ok(vec![commit3.id().clone()])
|
Ok(vec![commit3.id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -349,7 +375,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
RefTarget::Normal(commit4.id().clone()),
|
RefTarget::Normal(commit4.id().clone()),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "tag"),
|
resolve_symbol(mut_repo.as_repo_ref(), "tag", None),
|
||||||
Ok(vec![commit4.id().clone()])
|
Ok(vec![commit4.id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -359,7 +385,7 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
RefTarget::Normal(commit2.id().clone()),
|
RefTarget::Normal(commit2.id().clone()),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "origin/remote-branch"),
|
resolve_symbol(mut_repo.as_repo_ref(), "origin/remote-branch", None),
|
||||||
Ok(vec![commit2.id().clone()])
|
Ok(vec![commit2.id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -367,17 +393,21 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
mut_repo.set_git_ref("@".to_string(), RefTarget::Normal(commit2.id().clone()));
|
mut_repo.set_git_ref("@".to_string(), RefTarget::Normal(commit2.id().clone()));
|
||||||
mut_repo.set_git_ref("root".to_string(), RefTarget::Normal(commit3.id().clone()));
|
mut_repo.set_git_ref("root".to_string(), RefTarget::Normal(commit3.id().clone()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
resolve_symbol(mut_repo.as_repo_ref(), "@", Some(&WorkspaceId::default())),
|
||||||
Ok(vec![mut_repo.view().checkout().clone()])
|
Ok(vec![mut_repo
|
||||||
|
.view()
|
||||||
|
.get_checkout(&WorkspaceId::default())
|
||||||
|
.unwrap()
|
||||||
|
.clone()])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "root"),
|
resolve_symbol(mut_repo.as_repo_ref(), "root", None),
|
||||||
Ok(vec![mut_repo.store().root_commit().id().clone()])
|
Ok(vec![mut_repo.store().root_commit().id().clone()])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Conflicted ref resolves to its "adds"
|
// Conflicted ref resolves to its "adds"
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/conflicted"),
|
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/conflicted", None),
|
||||||
Ok(vec![commit1.id().clone(), commit3.id().clone()])
|
Ok(vec![commit1.id().clone(), commit3.id().clone()])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -385,7 +415,21 @@ fn test_resolve_symbol_git_refs() {
|
|||||||
fn resolve_commit_ids(repo: RepoRef, revset_str: &str) -> Vec<CommitId> {
|
fn resolve_commit_ids(repo: RepoRef, revset_str: &str) -> Vec<CommitId> {
|
||||||
let expression = parse(revset_str).unwrap();
|
let expression = parse(revset_str).unwrap();
|
||||||
expression
|
expression
|
||||||
.evaluate(repo)
|
.evaluate(repo, None)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.commit_ids()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_commit_ids_in_workspace(
|
||||||
|
repo: RepoRef,
|
||||||
|
revset_str: &str,
|
||||||
|
workspace_id: &WorkspaceId,
|
||||||
|
) -> Vec<CommitId> {
|
||||||
|
let expression = parse(revset_str).unwrap();
|
||||||
|
expression
|
||||||
|
.evaluate(repo, Some(workspace_id))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.commit_ids()
|
.commit_ids()
|
||||||
@ -414,7 +458,7 @@ fn test_evaluate_expression_root_and_checkout(use_git: bool) {
|
|||||||
// Can find the current checkout
|
// Can find the current checkout
|
||||||
mut_repo.set_checkout(WorkspaceId::default(), commit1.id().clone());
|
mut_repo.set_checkout(WorkspaceId::default(), commit1.id().clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_commit_ids(mut_repo.as_repo_ref(), "@"),
|
resolve_commit_ids_in_workspace(mut_repo.as_repo_ref(), "@", &WorkspaceId::default()),
|
||||||
vec![commit1.id().clone()]
|
vec![commit1.id().clone()]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -504,7 +548,7 @@ fn test_evaluate_expression_parents(use_git: bool) {
|
|||||||
// Can find parents of the current checkout
|
// Can find parents of the current checkout
|
||||||
mut_repo.set_checkout(WorkspaceId::default(), commit2.id().clone());
|
mut_repo.set_checkout(WorkspaceId::default(), commit2.id().clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_commit_ids(mut_repo.as_repo_ref(), "@-"),
|
resolve_commit_ids_in_workspace(mut_repo.as_repo_ref(), "@-", &WorkspaceId::default()),
|
||||||
vec![commit1.id().clone()]
|
vec![commit1.id().clone()]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -386,7 +386,8 @@ impl WorkspaceCommandHelper {
|
|||||||
revision_str: &str,
|
revision_str: &str,
|
||||||
) -> Result<Commit, CommandError> {
|
) -> Result<Commit, CommandError> {
|
||||||
let revset_expression = self.parse_revset(ui, revision_str)?;
|
let revset_expression = self.parse_revset(ui, revision_str)?;
|
||||||
let revset = revset_expression.evaluate(self.repo.as_repo_ref())?;
|
let revset =
|
||||||
|
revset_expression.evaluate(self.repo.as_repo_ref(), Some(&self.workspace_id()))?;
|
||||||
let mut iter = revset.iter().commits(self.repo.store());
|
let mut iter = revset.iter().commits(self.repo.store());
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
None => Err(CommandError::UserError(format!(
|
None => Err(CommandError::UserError(format!(
|
||||||
@ -412,7 +413,8 @@ impl WorkspaceCommandHelper {
|
|||||||
revision_str: &str,
|
revision_str: &str,
|
||||||
) -> Result<Vec<Commit>, CommandError> {
|
) -> Result<Vec<Commit>, CommandError> {
|
||||||
let revset_expression = self.parse_revset(ui, revision_str)?;
|
let revset_expression = self.parse_revset(ui, revision_str)?;
|
||||||
let revset = revset_expression.evaluate(self.repo.as_repo_ref())?;
|
let revset =
|
||||||
|
revset_expression.evaluate(self.repo.as_repo_ref(), Some(&self.workspace_id()))?;
|
||||||
Ok(revset
|
Ok(revset
|
||||||
.iter()
|
.iter()
|
||||||
.commits(self.repo.store())
|
.commits(self.repo.store())
|
||||||
@ -2541,7 +2543,8 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &ArgMatches) -> Result<()
|
|||||||
workspace_command.parse_revset(ui, args.value_of("revisions").unwrap())?;
|
workspace_command.parse_revset(ui, args.value_of("revisions").unwrap())?;
|
||||||
let repo = workspace_command.repo();
|
let repo = workspace_command.repo();
|
||||||
let checkout_id = repo.view().checkout().clone();
|
let checkout_id = repo.view().checkout().clone();
|
||||||
let revset = revset_expression.evaluate(repo.as_repo_ref())?;
|
let revset =
|
||||||
|
revset_expression.evaluate(repo.as_repo_ref(), Some(&workspace_command.workspace_id()))?;
|
||||||
let store = repo.store();
|
let store = repo.store();
|
||||||
|
|
||||||
let template_string = match args.value_of("template") {
|
let template_string = match args.value_of("template") {
|
||||||
@ -3344,7 +3347,10 @@ fn cmd_rebase(ui: &mut Ui, command: &CommandHelper, args: &ArgMatches) -> Result
|
|||||||
let mut num_rebased_descendants = 0;
|
let mut num_rebased_descendants = 0;
|
||||||
let store = workspace_command.repo.store();
|
let store = workspace_command.repo.store();
|
||||||
for child_commit in children_expression
|
for child_commit in children_expression
|
||||||
.evaluate(workspace_command.repo().as_repo_ref())
|
.evaluate(
|
||||||
|
workspace_command.repo().as_repo_ref(),
|
||||||
|
Some(&workspace_command.workspace_id()),
|
||||||
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.commits(store)
|
.commits(store)
|
||||||
|
@ -312,7 +312,7 @@ impl DivergentProperty {
|
|||||||
pub fn new(repo: RepoRef) -> Self {
|
pub fn new(repo: RepoRef) -> Self {
|
||||||
// TODO: Create a persistent index from change id to commit ids.
|
// TODO: Create a persistent index from change id to commit ids.
|
||||||
let mut commit_count_by_change: HashMap<ChangeId, i32> = HashMap::new();
|
let mut commit_count_by_change: HashMap<ChangeId, i32> = HashMap::new();
|
||||||
for index_entry in RevsetExpression::all().evaluate(repo).unwrap().iter() {
|
for index_entry in RevsetExpression::all().evaluate(repo, None).unwrap().iter() {
|
||||||
let change_id = index_entry.change_id();
|
let change_id = index_entry.change_id();
|
||||||
commit_count_by_change
|
commit_count_by_change
|
||||||
.entry(change_id)
|
.entry(change_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user