Skip to content

Commit

Permalink
Introduce syntax for :squash(...) filter (#1097)
Browse files Browse the repository at this point in the history
Previously this filter could only be created programatically,
now it can be specified in the filter language.

Change: squash-syntax
  • Loading branch information
christian-schilling committed Jan 11, 2023
1 parent 34ccdc3 commit 73e34dd
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 36 deletions.
26 changes: 13 additions & 13 deletions src/bin/josh-filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,6 @@ fn run_filter(args: Vec<String>) -> josh::JoshResult<i32> {

let mut filterobj = josh::filter::parse(&specstr)?;

if args.get_flag("print-filter") {
let filterobj = if args.get_flag("reverse") {
josh::filter::invert(filterobj)?
} else {
filterobj
};
println!(
"{}",
josh::filter::pretty(filterobj, if args.contains_id("file") { 0 } else { 4 })
);
return Ok(0);
}

let repo = git2::Repository::open_from_env()?;
if !args.get_flag("no-cache") {
josh::cache::load(repo.path())?;
Expand Down Expand Up @@ -197,6 +184,19 @@ fn run_filter(args: Vec<String>) -> josh::JoshResult<i32> {
filterobj = josh::filter::chain(josh::filter::squash(Some(&ids)), filterobj);
};

if args.get_flag("print-filter") {
let filterobj = if args.get_flag("reverse") {
josh::filter::invert(filterobj)?
} else {
filterobj
};
println!(
"{}",
josh::filter::pretty(filterobj, if args.contains_id("file") { 0 } else { 4 })
);
return Ok(0);
}

let odb = repo.odb()?;
let mp = if args.get_flag("pack") {
let mempack = odb.add_new_mempack_backend(1000)?;
Expand Down
10 changes: 10 additions & 0 deletions src/filter/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ filter_spec = { (
filter_group
| filter_rev
| filter_replace
| filter_squash
| filter_presub
| filter_subdir
| filter_nop
Expand Down Expand Up @@ -52,6 +53,15 @@ filter_replace = {
~ ")"
}

filter_squash = {
CMD_START ~ "squash" ~ "("
~ NEWLINE*
~ (argument ~ ":" ~ string)?
~ (CMD_SEP+ ~ (argument ~ ":" ~ string))*
~ NEWLINE*
~ ")"
}

argument = { string | PATH }

cmd = { ALNUM+ }
Expand Down
28 changes: 20 additions & 8 deletions src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ fn pretty2(op: &Op, indent: usize, compose: bool) -> String {
.collect::<Vec<_>>();
format!(":replace(\n{}\n)", v.join("\n"))
}
Op::Squash(Some(ids)) => {
let mut v = ids
.iter()
.map(|(oid, msg)| {
format!(
"{}{}:{}",
" ".repeat(indent),
&oid.to_string(),
parse::quote(msg)
)
})
.collect::<Vec<_>>();
v.sort();
format!(":squash(\n{}\n)", v.join("\n"))
}
_ => spec2(op),
}
}
Expand Down Expand Up @@ -279,16 +294,13 @@ fn spec2(op: &Op) -> String {
Op::Index => ":INDEX".to_string(),
Op::Fold => ":FOLD".to_string(),
Op::Squash(None) => ":SQUASH".to_string(),
Op::Squash(Some(hs)) => {
let mut v = hs
Op::Squash(Some(ids)) => {
let mut v = ids
.iter()
.map(|(x, y)| format!("{}:{}", x, y))
.collect::<Vec<String>>();
.map(|(oid, msg)| format!("{}:{}", oid, parse::quote(msg)))
.collect::<Vec<_>>();
v.sort();
let s = v.join(",");
let s = git2::Oid::hash_object(git2::ObjectType::Blob, s.as_bytes())
.expect("hash_object filter");
format!(":SQUASH={}", s)
format!(":squash({})", v.join(","))
}
Op::Linear => ":linear".to_string(),
Op::Unsign => ":unsign".to_string(),
Expand Down
14 changes: 14 additions & 0 deletions src/filter/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ fn parse_item(pair: pest::iterators::Pair<Rule>) -> JoshResult<Op> {

Ok(Op::RegexReplace(replacements))
}
Rule::filter_squash => {
let ids = pair
.into_inner()
.tuples()
.map(|(oid, message)| {
Ok((
git2::Oid::from_str(oid.as_str())?,
unquote(message.as_str()),
))
})
.collect::<JoshResult<_>>()?;

Ok(Op::Squash(Some(ids)))
}

_ => Err(josh_error("parse_item: no match")),
}
Expand Down
3 changes: 3 additions & 0 deletions tests/filter/pretty_print.t
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
$ export TESTTMP=${PWD}

$ git init -q
$ git commit -q --allow-empty -m "empty"

$ josh-filter -p :/a
:/a
$ josh-filter -p :/"a"
Expand Down
67 changes: 53 additions & 14 deletions tests/filter/squash.t
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

$ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered
Warning: reference refs/heads/filtered wasn't updated
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
[1] :squash(

)

$ git log --graph --decorate --pretty=oneline refs/heads/filtered
fatal: ambiguous argument 'refs/heads/filtered': unknown revision or path not in the working tree.
Expand All @@ -39,9 +41,13 @@
[128]
$ git tag tag_a 1d69b7d
$ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
[1] :author="New Author";"new@e.mail"
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
[1] :squash(
)
[2] :squash(
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
)
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
* d8aa5a9937f4f0bd645dbc0b591bae5cd6b6d91b (tag: filtered/tag_a, filtered) refs/tags/tag_a
Expand All @@ -58,9 +64,17 @@
* 0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb (tag: tag_b) add file1
$ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
[3] :SQUASH=dd8bdf1d78a6cb9ffc9e2a0644a8bf41de56ad36
[1] :squash(
)
[2] :squash(
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
)
[3] :squash(
0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb:"refs/tags/tag_b"
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
d8aa5a9937f4f0bd645dbc0b591bae5cd6b6d91b:"refs/tags/filtered/tag_a"
)
[4] :author="New Author";"new@e.mail"
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
Expand All @@ -83,17 +97,42 @@
$ git tag tag_c 975d4c4
$ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
[3] :SQUASH=dd8bdf1d78a6cb9ffc9e2a0644a8bf41de56ad36
[6] :SQUASH=b2a9a51df03600d3b5858fa7fca044741f88e521
[9] :author="New Author";"new@e.mail"
$ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered -p > filter.josh
$ cat filter.josh
:squash(
0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb:"refs/tags/tag_b"
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
5b1a753860ca124024f6dfb4fd018fe7df8beae4:"refs/tags/filtered/tag_a"
68dc45079334d83e5b61d2ceeda035b96da4c838:"refs/tags/filtered/filtered/tag_a"
96a731a4d64a8928e6af7abb2d425df3812b4197:"refs/tags/filtered/tag_b"
975d4c4975912729482cc864d321c5196a969271:"refs/tags/tag_c"
):author="New Author";"new@e.mail"
$ josh-filter -s --file filter.josh --update refs/heads/filtered
[1] :squash(
)
[2] :squash(
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
)
[3] :squash(
0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb:"refs/tags/tag_b"
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
5b1a753860ca124024f6dfb4fd018fe7df8beae4:"refs/tags/filtered/tag_a"
68dc45079334d83e5b61d2ceeda035b96da4c838:"refs/tags/filtered/filtered/tag_a"
96a731a4d64a8928e6af7abb2d425df3812b4197:"refs/tags/filtered/tag_b"
975d4c4975912729482cc864d321c5196a969271:"refs/tags/tag_c"
)
[3] :squash(
0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb:"refs/tags/tag_b"
1d69b7d2651f744be3416f2ad526aeccefb99310:"refs/tags/tag_a"
d8aa5a9937f4f0bd645dbc0b591bae5cd6b6d91b:"refs/tags/filtered/tag_a"
)
[6] :author="New Author";"new@e.mail"
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
* 9fe45cb2bead844630852ab338ecd8e073f8ba50 (tag: filtered/tag_a, filtered) refs/tags/tag_a
* 9fe45cb2bead844630852ab338ecd8e073f8ba50 (filtered) refs/tags/tag_a
|\
| * d6b88d4c1cc566b7f4d9b51353ec6f3204a93b81 (tag: filtered/tag_c) refs/tags/tag_c
| * d6b88d4c1cc566b7f4d9b51353ec6f3204a93b81 refs/tags/tag_c
|/
* 96a731a4d64a8928e6af7abb2d425df3812b4197 (tag: filtered/tag_b) refs/tags/tag_b
2 changes: 1 addition & 1 deletion tests/proxy/workspace_errors.t
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,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_rev, or filter_replace
remote: = expected EOI, filter_group, filter_subdir, filter_nop, filter_presub, filter, filter_noarg, filter_rev, filter_replace, or filter_squash
remote:
remote: a/b = :b/sub2
remote: c = :/sub1
Expand Down

0 comments on commit 73e34dd

Please sign in to comment.