diff --git a/README.md b/README.md index 68ab1b49e..66c102684 100644 --- a/README.md +++ b/README.md @@ -243,11 +243,11 @@ By default, `jj log` lists all revisions (commits) in the repo that have not been rewritten (roughly speaking). We can use the `-r` flag to restrict which revisions we want to list. The flag accepts a "revset", which is an expression in a simple language for specifying revision. For example, `@` refers to the -working copy commit, `root` refers to the root commit, `git_refs()` refers to -all commits pointed to by git refs. We can combine expression with `|` for +working copy commit, `root` refers to the root commit, `branches()` refers to +all commits pointed to by branches. We can combine expression with `|` for union, `&` for intersection and `-` for difference. For example: ```shell script -$ jj log -r '@ | root | git_refs()' +$ jj log -r '@ | root | branches()' @ 192b456b024b f39aeb1a0200 martinvonz@google.com 2021-05-23 23:10:27.000 -07:00 : o 080a9b37ff7e 6a91b4ba16c7 martinvonz@google.com 2021-05-23 22:08:37.000 -07:00 main diff --git a/lib/src/revset.rs b/lib/src/revset.rs index bd33d0fac..0c5e05c47 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -192,6 +192,8 @@ pub enum RevsetExpression { }, AllHeads, PublicHeads, + Branches, + Tags, GitRefs, NonObsoleteHeads(Rc), ParentCount { @@ -495,6 +497,26 @@ fn parse_function_expression( }) } } + "branches" => { + if arg_count == 0 { + Ok(RevsetExpression::Branches) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name, + message: "Expected 0 arguments".to_string(), + }) + } + } + "tags" => { + if arg_count == 0 { + Ok(RevsetExpression::Tags) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name, + message: "Expected 0 arguments".to_string(), + }) + } + } "git_refs" => { if arg_count == 0 { Ok(RevsetExpression::GitRefs) @@ -969,6 +991,37 @@ pub fn evaluate_expression<'repo>( index_entries.sort_by_key(|b| Reverse(b.position())); Ok(Box::new(EagerRevset { index_entries })) } + RevsetExpression::Branches => { + let index = repo.index(); + let mut index_entries = vec![]; + for branch_target in repo.view().branches().values() { + if let Some(local_target) = &branch_target.local_target { + for id in local_target.adds() { + index_entries.push(index.entry_by_id(&id).unwrap()); + } + } + for remote_target in branch_target.remote_targets.values() { + for id in remote_target.adds() { + index_entries.push(index.entry_by_id(&id).unwrap()); + } + } + } + index_entries.sort_by_key(|b| Reverse(b.position())); + index_entries.dedup(); + Ok(Box::new(EagerRevset { index_entries })) + } + RevsetExpression::Tags => { + let index = repo.index(); + let mut index_entries = vec![]; + for ref_target in repo.view().tags().values() { + for id in ref_target.adds() { + index_entries.push(index.entry_by_id(&id).unwrap()); + } + } + index_entries.sort_by_key(|b| Reverse(b.position())); + index_entries.dedup(); + Ok(Box::new(EagerRevset { index_entries })) + } RevsetExpression::GitRefs => { let index = repo.index(); let mut index_entries = vec![];