revset.rs 1.84 KB
Newer Older
1
2
3
4
//! The revset query language
//!
//! <https://www.mercurial-scm.org/repo/hg/help/revsets>

5
use crate::errors::HgError;
6
7
8
9
use crate::repo::Repo;
use crate::revlog::changelog::Changelog;
use crate::revlog::revlog::{Revlog, RevlogError};
use crate::revlog::NodePrefix;
10
11
use crate::revlog::{Revision, NULL_REVISION, WORKING_DIRECTORY_HEX};
use crate::Node;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

/// Resolve a query string into a single revision.
///
/// Only some of the revset language is implemented yet.
pub fn resolve_single(
    input: &str,
    repo: &Repo,
) -> Result<Revision, RevlogError> {
    let changelog = Changelog::open(repo)?;

    match resolve_rev_number_or_hex_prefix(input, &changelog.revlog) {
        Err(RevlogError::InvalidRevision) => {} // Try other syntax
        result => return result,
    }

    if input == "null" {
        return Ok(NULL_REVISION);
    }

    // TODO: support for the rest of the language here.

33
34
35
36
    Err(
        HgError::unsupported(format!("cannot parse revset '{}'", input))
            .into(),
    )
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
}

/// Resolve the small subset of the language suitable for revlogs other than
/// the changelog, such as in `hg debugdata --manifest` CLI argument.
///
/// * A non-negative decimal integer for a revision number, or
/// * An hexadecimal string, for the unique node ID that starts with this
///   prefix
pub fn resolve_rev_number_or_hex_prefix(
    input: &str,
    revlog: &Revlog,
) -> Result<Revision, RevlogError> {
    if let Ok(integer) = input.parse::<i32>() {
        if integer >= 0 && revlog.has_rev(integer) {
            return Ok(integer);
        }
    }
    if let Ok(prefix) = NodePrefix::from_hex(input) {
55
56
57
58
        if prefix.is_prefix_of(&Node::from_hex(WORKING_DIRECTORY_HEX).unwrap())
        {
            return Err(RevlogError::WDirUnsupported);
        }
59
60
61
62
        return revlog.get_node_rev(prefix);
    }
    Err(RevlogError::InvalidRevision)
}