Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/src/reference/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ commits that don't match any of the other shas.
Produce the history that would be the result of pushing the passed branches with the
passed filters into the upstream.

### Start filtering from a specific commit **:from(<sha>:filter)**

Produce a history that keeps the original history leading up to the specified commit `<sha>` unchanged,
but applies the given `:filter` to all commits from that commit onwards.

### Prune trivial merge commits **:prune=trivial-merge**

Produce a history that skips all merge commits whose tree is identical to the first parents
Expand Down
21 changes: 20 additions & 1 deletion josh-core/src/filter/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ filter_spec = { (
filter_group
| filter_message
| filter_rev
| filter_from
| filter_concat
| filter_join
| filter_replace
| filter_squash
Expand Down Expand Up @@ -51,6 +53,24 @@ filter_rev = {
~ ")"
}

filter_from = {
CMD_START ~ "from" ~ "("
~ NEWLINE*
~ (rev ~ filter_spec)?
~ (CMD_SEP+ ~ (rev ~ filter_spec))*
~ NEWLINE*
~ ")"
}

filter_concat = {
CMD_START ~ "from" ~ "("
~ NEWLINE*
~ (rev ~ filter_spec)?
~ (CMD_SEP+ ~ (rev ~ filter_spec))*
~ NEWLINE*
~ ")"
}

filter_join = {
CMD_START ~ "join" ~ "("
~ NEWLINE*
Expand All @@ -60,7 +80,6 @@ filter_join = {
~ ")"
}


filter_replace = {
CMD_START ~ "replace" ~ "("
~ NEWLINE*
Expand Down
44 changes: 44 additions & 0 deletions josh-core/src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ enum Op {
Pattern(String),
Message(String),

HistoryConcat(LazyRef, Filter),

Compose(Vec<Filter>),
Chain(Filter, Filter),
Subtract(Filter, Filter),
Expand Down Expand Up @@ -308,6 +310,13 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
av
}
Op::Rev(filters) => lazy_refs2(&Op::Join(filters.clone())),
Op::HistoryConcat(r, _) => {
let mut lr = Vec::new();
if let LazyRef::Lazy(s) = r {
lr.push(s.to_owned());
}
lr
}
Op::Join(filters) => {
let mut lr = lazy_refs2(&Op::Compose(filters.values().copied().collect()));
lr.extend(filters.keys().filter_map(|x| {
Expand Down Expand Up @@ -367,6 +376,19 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
.collect();
Op::Rev(lr)
}
Op::HistoryConcat(r, filter) => {
let f = resolve_refs(refs, *filter);
let resolved_ref = if let LazyRef::Lazy(s) = r {
if let Some(res) = refs.get(s) {
LazyRef::Resolved(*res)
} else {
r.clone()
}
} else {
r.clone()
};
Op::HistoryConcat(resolved_ref, f)
}
Op::Join(filters) => {
let lr = filters
.iter()
Expand Down Expand Up @@ -502,6 +524,9 @@ fn spec2(op: &Op) -> String {
Op::Message(m) => {
format!(":{}", parse::quote(m))
}
Op::HistoryConcat(r, filter) => {
format!(":concat({}{})", r.to_string(), spec(*filter))
}
}
}

Expand Down Expand Up @@ -974,6 +999,24 @@ fn apply_to_commit2(
&std::collections::HashMap::<String, &dyn strfmt::DisplayStr>::new(),
)?),
},
Op::HistoryConcat(r, f) => {
if let LazyRef::Resolved(c) = r {
let a = apply_to_commit2(&to_op(*f), &repo.find_commit(*c)?, transaction)?;
let a = some_or!(a, { return Ok(None) });
if commit.id() == a {
transaction.insert(filter, commit.id(), *c, true);
return Ok(Some(*c));
}
} else {
return Err(josh_error("unresolved lazy ref"));
}
RewriteData {
tree: commit.tree()?,
message: None,
author: None,
committer: None,
}
}
_ => RewriteData {
tree: apply(transaction, filter, commit.tree()?)?,
message: None,
Expand Down Expand Up @@ -1019,6 +1062,7 @@ fn apply2<'a>(
let repo = transaction.repo();
match op {
Op::Nop => Ok(tree),
Op::HistoryConcat(..) => Ok(tree),
Op::Empty => Ok(tree::empty(repo)),
Op::Fold => Ok(tree),
Op::Squash(None) => Ok(tree),
Expand Down
25 changes: 25 additions & 0 deletions josh-core/src/filter/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,31 @@ fn parse_item(pair: pest::iterators::Pair<Rule>) -> JoshResult<Op> {

Ok(Op::Rev(hm))
}
Rule::filter_from => {
let v: Vec<_> = pair.into_inner().map(|x| x.as_str()).collect();

if v.len() == 2 {
let oid = LazyRef::parse(v[0])?;
let filter = parse(v[1])?;
Ok(Op::Chain(
filter,
filter::to_filter(Op::HistoryConcat(oid, filter)),
))
} else {
Err(josh_error("wrong argument count for :from"))
}
}
Rule::filter_concat => {
let v: Vec<_> = pair.into_inner().map(|x| x.as_str()).collect();

if v.len() == 2 {
let oid = LazyRef::parse(v[0])?;
let filter = parse(v[1])?;
Ok(Op::HistoryConcat(oid, filter))
} else {
Err(josh_error("wrong argument count for :concat"))
}
}
Rule::filter_replace => {
let replacements = pair
.into_inner()
Expand Down
42 changes: 42 additions & 0 deletions tests/filter/concat.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
$ export TESTTMP=${PWD}

$ cd ${TESTTMP}
$ git init -q libs 1> /dev/null
$ cd libs

$ mkdir sub1
$ echo contents1 > sub1/file1
$ git add sub1
$ git commit -m "add file1" 1> /dev/null

$ echo contents2 > sub1/file2
$ git add sub1
$ git commit -m "add file2" 1> /dev/null
$ git update-ref refs/heads/from_here HEAD


$ mkdir sub2
$ echo contents1 > sub2/file3
$ git add sub2
$ git commit -m "add file3" 1> /dev/null

$ josh-filter ":\"x\""

$ git log --graph --pretty=%s:%H HEAD
* add file3:667a912db7482f3c8023082c9b4c7b267792633a
* add file2:81b10fb4984d20142cd275b89c91c346e536876a
* add file1:bb282e9cdc1b972fffd08fd21eead43bc0c83cb8

$ git log --graph --pretty=%s:%H FILTERED_HEAD
* x:9d117d96dfdba145df43ebe37d9e526acac4b17c
* x:b232aa8eefaadfb5e38b3ad7355118aa59fb651e
* x:6b4d1f87c2be08f7d0f9d40b6679aab612e259b1

$ josh-filter -p ":from(81b10fb4984d20142cd275b89c91c346e536876a:\"x\")"
:"x":concat(81b10fb4984d20142cd275b89c91c346e536876a:"x")
$ josh-filter ":from(81b10fb4984d20142cd275b89c91c346e536876a:\"x\")"

$ git log --graph --pretty=%s FILTERED_HEAD
* x
* add file2
* add file1
2 changes: 1 addition & 1 deletion tests/proxy/workspace_errors.t
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Error in filter
remote: 1 | a/b = :b/sub2
remote: | ^---
remote: |
remote: = expected EOI, filter_group, filter_subdir, filter_nop, filter_presub, filter, filter_noarg, filter_message, filter_rev, filter_join, filter_replace, or filter_squash
remote: = expected EOI, filter_group, filter_subdir, filter_nop, filter_presub, filter, filter_noarg, filter_message, filter_rev, filter_from, filter_concat, filter_join, filter_replace, or filter_squash
remote:
remote: a/b = :b/sub2
remote: c = :/sub1
Expand Down