revsets: refactor symbol lookup to prepare for trying to look up change id
@@ -38,26 +38,18 @@ pub enum RevsetError {
StoreError(#[from] StoreError),
}
-// TODO: Decide if we should allow a single symbol to resolve to multiple
-// revisions. For example, we may want to resolve a change id to all the
-// matching commits. Depending on how we decide to handle divergent git refs and
-// similar, we may also want those to resolve to multiple commits.
-pub fn resolve_symbol(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError> {
- // TODO: Support change ids.
- if symbol == "@" {
- Ok(repo.store().get_commit(repo.view().checkout())?)
- } else if symbol == "root" {
- Ok(repo.store().root_commit())
- } else {
- // Try to resolve as a git ref
+fn resolve_git_ref(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError> {
let view = repo.view();
for git_ref_prefix in &["", "refs/", "refs/heads/", "refs/tags/", "refs/remotes/"] {
if let Some(commit_id) = view.git_refs().get(&(git_ref_prefix.to_string() + symbol)) {
return Ok(repo.store().get_commit(&commit_id)?);
}
}
+ Err(RevsetError::NoSuchRevision(symbol.to_owned()))
+}
- // Try to resolve as a commit id. First check if it's a full commit id.
+fn resolve_commit_id(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError> {
+ // First check if it's a full commit id.
if let Ok(binary_commit_id) = hex::decode(symbol) {
let commit_id = CommitId(binary_commit_id);
match repo.store().get_commit(&commit_id) {
@@ -67,7 +59,7 @@ pub fn resolve_symbol(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError
}
}
- if let Some(prefix) = HexPrefix::new(symbol.to_string()) {
+ if let Some(prefix) = HexPrefix::new(symbol.to_owned()) {
match repo.index().resolve_prefix(&prefix) {
PrefixResolution::NoMatch => {
return Err(RevsetError::NoSuchRevision(symbol.to_owned()))
@@ -83,6 +75,32 @@ pub fn resolve_symbol(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError
Err(RevsetError::NoSuchRevision(symbol.to_owned()))
}
+
+// TODO: Decide if we should allow a single symbol to resolve to multiple
+// revisions. For example, we may want to resolve a change id to all the
+// matching commits. Depending on how we decide to handle divergent git refs and
+// similar, we may also want those to resolve to multiple commits.
+pub fn resolve_symbol(repo: RepoRef, symbol: &str) -> Result<Commit, RevsetError> {
+ // TODO: Support change ids.
+ if symbol == "@" {
+ Ok(repo.store().get_commit(repo.view().checkout())?)
+ } else if symbol == "root" {
+ Ok(repo.store().root_commit())
+ } else {
+ // Try to resolve as a git ref
+ let git_ref_result = resolve_git_ref(repo, symbol);
+ if !matches!(git_ref_result, Err(RevsetError::NoSuchRevision(_))) {
+ return git_ref_result;
+ }
+
+ // Try to resolve as a commit id.
+ let commit_id_result = resolve_commit_id(repo, symbol);
+ if !matches!(commit_id_result, Err(RevsetError::NoSuchRevision(_))) {
+ return commit_id_result;
+ }
+
+ Err(RevsetError::NoSuchRevision(symbol.to_owned()))
+ }
}
#[derive(Parser)]
