Merge ~liushuyu-011/ubuntu/+source/rust-criterion:ubuntu/devel into ubuntu/+source/rust-criterion:ubuntu/devel
- Git
- lp:~liushuyu-011/ubuntu/+source/rust-criterion
- ubuntu/devel
- Merge into ubuntu/devel
Proposed by
Zixing Liu
Status: | Merged |
---|---|
Merge reported by: | Robie Basak |
Merged at revision: | 1527df770fbfa26e06863ac33050518966f4859a |
Proposed branch: | ~liushuyu-011/ubuntu/+source/rust-criterion:ubuntu/devel |
Merge into: | ubuntu/+source/rust-criterion:ubuntu/devel |
Diff against target: |
413 lines (+400/-0) 2 files modified
debian/patches/0001-chore-wibbles-to-fix-CI-635.patch (+399/-0) debian/patches/series (+1/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Sponsors | Pending | ||
git-ubuntu import | Pending | ||
Review via email: mp+440546@code.launchpad.net |
Commit message
Description of the change
This patch backports https:/
To post a comment you must log in.
Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/debian/patches/0001-chore-wibbles-to-fix-CI-635.patch b/debian/patches/0001-chore-wibbles-to-fix-CI-635.patch |
2 | new file mode 100644 |
3 | index 0000000..90a50f0 |
4 | --- /dev/null |
5 | +++ b/debian/patches/0001-chore-wibbles-to-fix-CI-635.patch |
6 | @@ -0,0 +1,399 @@ |
7 | +From 562a05fb5ca8f5fe89c58a46a580fb341687b860 Mon Sep 17 00:00:00 2001 |
8 | +From: David Himmelstrup <lemmih@gmail.com> |
9 | +Date: Tue, 4 Apr 2023 17:08:36 -0600 |
10 | +Subject: [PATCH] chore: wibbles to fix CI (#635) |
11 | + |
12 | +--- |
13 | + .github/workflows/ci.yaml | 9 +++++---- |
14 | + src/analysis/mod.rs | 2 +- |
15 | + src/csv_report.rs | 1 + |
16 | + src/html/mod.rs | 14 ++++---------- |
17 | + src/lib.rs | 8 ++++---- |
18 | + src/plot/gnuplot_backend/summary.rs | 2 +- |
19 | + src/plot/plotters_backend/distributions.rs | 12 ++++++------ |
20 | + src/plot/plotters_backend/iteration_times.rs | 4 ++-- |
21 | + src/plot/plotters_backend/pdf.rs | 16 ++++++++-------- |
22 | + src/plot/plotters_backend/regression.rs | 10 +++++----- |
23 | + src/plot/plotters_backend/summary.rs | 6 +++--- |
24 | + src/plot/plotters_backend/t_test.rs | 4 ++-- |
25 | + 12 files changed, 42 insertions(+), 46 deletions(-) |
26 | + |
27 | +diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml |
28 | +index d7f39e4..168ce54 100644 |
29 | +--- a/.github/workflows/ci.yaml |
30 | ++++ b/.github/workflows/ci.yaml |
31 | +@@ -16,11 +16,11 @@ jobs: |
32 | + matrix: |
33 | + rust: |
34 | + - stable |
35 | +- - beta |
36 | +- - 1.57 # MSRV |
37 | ++ - 1.59 # MSRV |
38 | ++ - nightly |
39 | + |
40 | + steps: |
41 | +- - uses: actions/checkout@v2 |
42 | ++ - uses: actions/checkout@v3 |
43 | + |
44 | + - uses: actions-rs/toolchain@v1 |
45 | + name: Setup rust toolchain |
46 | +@@ -30,7 +30,7 @@ jobs: |
47 | + override: true |
48 | + components: rustfmt, clippy |
49 | + |
50 | +- - uses: Swatinem/rust-cache@v1 |
51 | ++ - uses: Swatinem/rust-cache@v2 |
52 | + name: Load dependencies from cache |
53 | + |
54 | + - uses: actions-rs/cargo@v1 |
55 | +@@ -73,6 +73,7 @@ jobs: |
56 | + |
57 | + - uses: actions-rs/cargo@v1 |
58 | + name: Check for clippy hints |
59 | ++ if: ${{ matrix.rust == 'stable' }} |
60 | + with: |
61 | + command: clippy |
62 | + args: -- -D warnings |
63 | +diff --git a/src/analysis/mod.rs b/src/analysis/mod.rs |
64 | +index 23647c1..1851d71 100644 |
65 | +--- a/src/analysis/mod.rs |
66 | ++++ b/src/analysis/mod.rs |
67 | +@@ -222,7 +222,7 @@ pub(crate) fn common<M: Measurement, T: ?Sized>( |
68 | + }; |
69 | + |
70 | + let measurement_data = crate::report::MeasurementData { |
71 | +- data: Data::new(&*iters, &*times), |
72 | ++ data: Data::new(&iters, ×), |
73 | + avg_times: labeled_sample, |
74 | + absolute_estimates: estimates, |
75 | + distributions, |
76 | +diff --git a/src/csv_report.rs b/src/csv_report.rs |
77 | +index 3b744df..f8e2a05 100644 |
78 | +--- a/src/csv_report.rs |
79 | ++++ b/src/csv_report.rs |
80 | +@@ -35,6 +35,7 @@ impl<W: Write> CsvReportWriter<W> { |
81 | + let value = id.value_str.as_deref(); |
82 | + let (throughput_num, throughput_type) = match id.throughput { |
83 | + Some(Throughput::Bytes(bytes)) => (Some(format!("{}", bytes)), Some("bytes")), |
84 | ++ Some(Throughput::BytesDecimal(bytes)) => (Some(format!("{}", bytes)), Some("bytes")), |
85 | + Some(Throughput::Elements(elems)) => (Some(format!("{}", elems)), Some("elements")), |
86 | + None => (None, None), |
87 | + }; |
88 | +diff --git a/src/html/mod.rs b/src/html/mod.rs |
89 | +index d360656..0809aae 100644 |
90 | +--- a/src/html/mod.rs |
91 | ++++ b/src/html/mod.rs |
92 | +@@ -438,7 +438,7 @@ impl Report for Html { |
93 | + |
94 | + // If all of the value strings can be parsed into a number, sort/dedupe |
95 | + // numerically. Otherwise sort lexicographically. |
96 | +- if value_strs.iter().all(|os| try_parse(*os).is_some()) { |
97 | ++ if value_strs.iter().all(|os| try_parse(os).is_some()) { |
98 | + value_strs.sort_unstable_by(|v1, v2| { |
99 | + let num1 = try_parse(v1); |
100 | + let num2 = try_parse(v2); |
101 | +@@ -464,7 +464,7 @@ impl Report for Html { |
102 | + |
103 | + self.generate_summary( |
104 | + &subgroup_id, |
105 | +- &*samples_with_function, |
106 | ++ &samples_with_function, |
107 | + context, |
108 | + formatter, |
109 | + false, |
110 | +@@ -483,13 +483,7 @@ impl Report for Html { |
111 | + let subgroup_id = |
112 | + BenchmarkId::new(group_id.clone(), None, Some(value_str.clone()), None); |
113 | + |
114 | +- self.generate_summary( |
115 | +- &subgroup_id, |
116 | +- &*samples_with_value, |
117 | +- context, |
118 | +- formatter, |
119 | +- false, |
120 | +- ); |
121 | ++ self.generate_summary(&subgroup_id, &samples_with_value, context, formatter, false); |
122 | + } |
123 | + } |
124 | + |
125 | +@@ -516,7 +510,7 @@ impl Report for Html { |
126 | + |
127 | + self.generate_summary( |
128 | + &BenchmarkId::new(group_id, None, None, None), |
129 | +- &*(all_data), |
130 | ++ &all_data, |
131 | + context, |
132 | + formatter, |
133 | + true, |
134 | +diff --git a/src/lib.rs b/src/lib.rs |
135 | +index 16e79cc..3bc31c8 100644 |
136 | +--- a/src/lib.rs |
137 | ++++ b/src/lib.rs |
138 | +@@ -365,7 +365,7 @@ fn cargo_target_directory() -> Option<PathBuf> { |
139 | + .map(PathBuf::from) |
140 | + .or_else(|| { |
141 | + let output = Command::new(env::var_os("CARGO")?) |
142 | +- .args(&["metadata", "--format-version", "1"]) |
143 | ++ .args(["metadata", "--format-version", "1"]) |
144 | + .output() |
145 | + .ok()?; |
146 | + let metadata: Metadata = serde_json::from_slice(&output.stdout).ok()?; |
147 | +@@ -740,7 +740,7 @@ impl<M: Measurement> Criterion<M> { |
148 | + .long("color") |
149 | + .alias("colour") |
150 | + .takes_value(true) |
151 | +- .possible_values(&["auto", "always", "never"]) |
152 | ++ .possible_values(["auto", "always", "never"]) |
153 | + .default_value("auto") |
154 | + .help("Configure coloring of output. always = always colorize output, never = never colorize output, auto = colorize output if output is a tty and compiled for unix.")) |
155 | + .arg(Arg::new("verbose") |
156 | +@@ -833,12 +833,12 @@ impl<M: Measurement> Criterion<M> { |
157 | + .arg(Arg::new("plotting-backend") |
158 | + .long("plotting-backend") |
159 | + .takes_value(true) |
160 | +- .possible_values(&["gnuplot", "plotters"]) |
161 | ++ .possible_values(["gnuplot", "plotters"]) |
162 | + .help("Set the plotting backend. By default, Criterion.rs will use the gnuplot backend if gnuplot is available, or the plotters backend if it isn't.")) |
163 | + .arg(Arg::new("output-format") |
164 | + .long("output-format") |
165 | + .takes_value(true) |
166 | +- .possible_values(&["criterion", "bencher"]) |
167 | ++ .possible_values(["criterion", "bencher"]) |
168 | + .default_value("criterion") |
169 | + .help("Change the CLI output format. By default, Criterion.rs will use its own format. If output format is set to 'bencher', Criterion.rs will print output in a format that resembles the 'bencher' crate.")) |
170 | + .arg(Arg::new("nocapture") |
171 | +diff --git a/src/plot/gnuplot_backend/summary.rs b/src/plot/gnuplot_backend/summary.rs |
172 | +index d57a174..529463b 100644 |
173 | +--- a/src/plot/gnuplot_backend/summary.rs |
174 | ++++ b/src/plot/gnuplot_backend/summary.rs |
175 | +@@ -130,7 +130,7 @@ pub fn violin( |
176 | + ) -> Child { |
177 | + let path = PathBuf::from(&path); |
178 | + let all_curves_vec = all_curves.iter().rev().cloned().collect::<Vec<_>>(); |
179 | +- let all_curves: &[&(&BenchmarkId, Vec<f64>)] = &*all_curves_vec; |
180 | ++ let all_curves: &[&(&BenchmarkId, Vec<f64>)] = &all_curves_vec; |
181 | + |
182 | + let kdes = all_curves |
183 | + .iter() |
184 | +diff --git a/src/plot/plotters_backend/distributions.rs b/src/plot/plotters_backend/distributions.rs |
185 | +index 82f9eae..8de1140 100644 |
186 | +--- a/src/plot/plotters_backend/distributions.rs |
187 | ++++ b/src/plot/plotters_backend/distributions.rs |
188 | +@@ -85,11 +85,11 @@ fn abs_distribution( |
189 | + chart |
190 | + .draw_series(LineSeries::new( |
191 | + kde_xs.iter().zip(ys.iter()).map(|(&x, &y)| (x, y)), |
192 | +- &DARK_BLUE, |
193 | ++ DARK_BLUE, |
194 | + )) |
195 | + .unwrap() |
196 | + .label("Bootstrap distribution") |
197 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
198 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
199 | + |
200 | + chart |
201 | + .draw_series(AreaSeries::new( |
202 | +@@ -115,7 +115,7 @@ fn abs_distribution( |
203 | + ))) |
204 | + .unwrap() |
205 | + .label("Point estimate") |
206 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
207 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
208 | + |
209 | + chart |
210 | + .configure_series_labels() |
211 | +@@ -240,11 +240,11 @@ fn rel_distribution( |
212 | + chart |
213 | + .draw_series(LineSeries::new( |
214 | + xs.iter().zip(ys.iter()).map(|(x, y)| (*x, *y)), |
215 | +- &DARK_BLUE, |
216 | ++ DARK_BLUE, |
217 | + )) |
218 | + .unwrap() |
219 | + .label("Bootstrap distribution") |
220 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
221 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
222 | + |
223 | + chart |
224 | + .draw_series(AreaSeries::new( |
225 | +@@ -269,7 +269,7 @@ fn rel_distribution( |
226 | + ))) |
227 | + .unwrap() |
228 | + .label("Point estimate") |
229 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
230 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
231 | + |
232 | + chart |
233 | + .draw_series(std::iter::once(Rectangle::new( |
234 | +diff --git a/src/plot/plotters_backend/iteration_times.rs b/src/plot/plotters_backend/iteration_times.rs |
235 | +index 4d0a22a..3ac4f1c 100644 |
236 | +--- a/src/plot/plotters_backend/iteration_times.rs |
237 | ++++ b/src/plot/plotters_backend/iteration_times.rs |
238 | +@@ -37,7 +37,7 @@ pub(crate) fn iteration_times_figure( |
239 | + .configure_mesh() |
240 | + .y_desc(format!("Average Iteration Time ({})", unit)) |
241 | + .x_label_formatter(&|x| pretty_print_float(*x, true)) |
242 | +- .light_line_style(&TRANSPARENT) |
243 | ++ .light_line_style(TRANSPARENT) |
244 | + .draw() |
245 | + .unwrap(); |
246 | + |
247 | +@@ -104,7 +104,7 @@ pub(crate) fn iteration_times_comparison_figure( |
248 | + .configure_mesh() |
249 | + .y_desc(format!("Average Iteration Time ({})", unit)) |
250 | + .x_label_formatter(&|x| pretty_print_float(*x, true)) |
251 | +- .light_line_style(&TRANSPARENT) |
252 | ++ .light_line_style(TRANSPARENT) |
253 | + .draw() |
254 | + .unwrap(); |
255 | + |
256 | +diff --git a/src/plot/plotters_backend/pdf.rs b/src/plot/plotters_backend/pdf.rs |
257 | +index 333893f..957bb44 100644 |
258 | +--- a/src/plot/plotters_backend/pdf.rs |
259 | ++++ b/src/plot/plotters_backend/pdf.rs |
260 | +@@ -93,7 +93,7 @@ pub(crate) fn pdf_comparison_figure( |
261 | + ))) |
262 | + .unwrap() |
263 | + .label("Base Mean") |
264 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_RED)); |
265 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_RED)); |
266 | + |
267 | + chart |
268 | + .draw_series(std::iter::once(PathElement::new( |
269 | +@@ -102,7 +102,7 @@ pub(crate) fn pdf_comparison_figure( |
270 | + ))) |
271 | + .unwrap() |
272 | + .label("New Mean") |
273 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
274 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
275 | + |
276 | + if title.is_some() { |
277 | + chart.configure_series_labels().draw().unwrap(); |
278 | +@@ -255,18 +255,18 @@ pub(crate) fn pdf( |
279 | + chart |
280 | + .draw_series(std::iter::once(PathElement::new( |
281 | + vec![(mean, 0.0), (mean, max_iters)], |
282 | +- &DARK_BLUE, |
283 | ++ DARK_BLUE, |
284 | + ))) |
285 | + .unwrap() |
286 | + .label("Mean") |
287 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
288 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
289 | + |
290 | + chart |
291 | + .draw_series(vec![ |
292 | +- PathElement::new(vec![(lomt, 0.0), (lomt, max_iters)], &DARK_ORANGE), |
293 | +- PathElement::new(vec![(himt, 0.0), (himt, max_iters)], &DARK_ORANGE), |
294 | +- PathElement::new(vec![(lost, 0.0), (lost, max_iters)], &DARK_RED), |
295 | +- PathElement::new(vec![(hist, 0.0), (hist, max_iters)], &DARK_RED), |
296 | ++ PathElement::new(vec![(lomt, 0.0), (lomt, max_iters)], DARK_ORANGE), |
297 | ++ PathElement::new(vec![(himt, 0.0), (himt, max_iters)], DARK_ORANGE), |
298 | ++ PathElement::new(vec![(lost, 0.0), (lost, max_iters)], DARK_RED), |
299 | ++ PathElement::new(vec![(hist, 0.0), (hist, max_iters)], DARK_RED), |
300 | + ]) |
301 | + .unwrap(); |
302 | + use crate::stats::univariate::outliers::tukey::Label; |
303 | +diff --git a/src/plot/plotters_backend/regression.rs b/src/plot/plotters_backend/regression.rs |
304 | +index c944dbb..1a9adec 100644 |
305 | +--- a/src/plot/plotters_backend/regression.rs |
306 | ++++ b/src/plot/plotters_backend/regression.rs |
307 | +@@ -61,7 +61,7 @@ pub(crate) fn regression_figure( |
308 | + .x_desc(x_label) |
309 | + .y_desc(format!("Total sample time ({})", unit)) |
310 | + .x_label_formatter(&|x| pretty_print_float(x * x_scale, true)) |
311 | +- .light_line_style(&TRANSPARENT) |
312 | ++ .light_line_style(TRANSPARENT) |
313 | + .draw() |
314 | + .unwrap(); |
315 | + |
316 | +@@ -79,7 +79,7 @@ pub(crate) fn regression_figure( |
317 | + chart |
318 | + .draw_series(std::iter::once(PathElement::new( |
319 | + vec![(0.0, 0.0), (max_iters, point)], |
320 | +- &DARK_BLUE, |
321 | ++ DARK_BLUE, |
322 | + ))) |
323 | + .unwrap() |
324 | + .label("Linear regression") |
325 | +@@ -187,13 +187,13 @@ pub(crate) fn regression_comparison_figure( |
326 | + .x_desc(x_label) |
327 | + .y_desc(format!("Total sample time ({})", unit)) |
328 | + .x_label_formatter(&|x| pretty_print_float(x * x_scale, true)) |
329 | +- .light_line_style(&TRANSPARENT) |
330 | ++ .light_line_style(TRANSPARENT) |
331 | + .draw() |
332 | + .unwrap(); |
333 | + |
334 | + chart |
335 | + .draw_series(vec![ |
336 | +- PathElement::new(vec![(0.0, 0.0), (max_iters, base_point)], &DARK_RED).into_dyn(), |
337 | ++ PathElement::new(vec![(0.0, 0.0), (max_iters, base_point)], DARK_RED).into_dyn(), |
338 | + Polygon::new( |
339 | + vec![(0.0, 0.0), (max_iters, base_lb), (max_iters, base_ub)], |
340 | + DARK_RED.mix(0.25).filled(), |
341 | +@@ -208,7 +208,7 @@ pub(crate) fn regression_comparison_figure( |
342 | + |
343 | + chart |
344 | + .draw_series(vec![ |
345 | +- PathElement::new(vec![(0.0, 0.0), (max_iters, point)], &DARK_BLUE).into_dyn(), |
346 | ++ PathElement::new(vec![(0.0, 0.0), (max_iters, point)], DARK_BLUE).into_dyn(), |
347 | + Polygon::new( |
348 | + vec![(0.0, 0.0), (max_iters, lb), (max_iters, ub)], |
349 | + DARK_BLUE.mix(0.25).filled(), |
350 | +diff --git a/src/plot/plotters_backend/summary.rs b/src/plot/plotters_backend/summary.rs |
351 | +index a5a410d..23f4053 100644 |
352 | +--- a/src/plot/plotters_backend/summary.rs |
353 | ++++ b/src/plot/plotters_backend/summary.rs |
354 | +@@ -159,7 +159,7 @@ pub fn violin( |
355 | + axis_scale: AxisScale, |
356 | + ) { |
357 | + let all_curves_vec = all_curves.iter().rev().cloned().collect::<Vec<_>>(); |
358 | +- let all_curves: &[&(&BenchmarkId, Vec<f64>)] = &*all_curves_vec; |
359 | ++ let all_curves: &[&(&BenchmarkId, Vec<f64>)] = &all_curves_vec; |
360 | + |
361 | + let mut kdes = all_curves |
362 | + .iter() |
363 | +@@ -250,7 +250,7 @@ fn draw_violin_figure<XR: AsRangedCoord<Value = f64>, YR: AsRangedCoord<Value = |
364 | + .draw_series(AreaSeries::new( |
365 | + x.iter().zip(y.iter()).map(|(x, y)| (*x, base + *y / 2.0)), |
366 | + base, |
367 | +- &DARK_BLUE, |
368 | ++ DARK_BLUE, |
369 | + )) |
370 | + .unwrap(); |
371 | + |
372 | +@@ -258,7 +258,7 @@ fn draw_violin_figure<XR: AsRangedCoord<Value = f64>, YR: AsRangedCoord<Value = |
373 | + .draw_series(AreaSeries::new( |
374 | + x.iter().zip(y.iter()).map(|(x, y)| (*x, base - *y / 2.0)), |
375 | + base, |
376 | +- &DARK_BLUE, |
377 | ++ DARK_BLUE, |
378 | + )) |
379 | + .unwrap(); |
380 | + } |
381 | +diff --git a/src/plot/plotters_backend/t_test.rs b/src/plot/plotters_backend/t_test.rs |
382 | +index d9c1508..c575c2f 100644 |
383 | +--- a/src/plot/plotters_backend/t_test.rs |
384 | ++++ b/src/plot/plotters_backend/t_test.rs |
385 | +@@ -38,7 +38,7 @@ pub(crate) fn t_test( |
386 | + .draw_series(AreaSeries::new( |
387 | + xs.iter().zip(ys.iter()).map(|(x, y)| (*x, *y)), |
388 | + 0.0, |
389 | +- &DARK_BLUE.mix(0.25), |
390 | ++ DARK_BLUE.mix(0.25), |
391 | + )) |
392 | + .unwrap() |
393 | + .label("t distribution") |
394 | +@@ -53,7 +53,7 @@ pub(crate) fn t_test( |
395 | + ))) |
396 | + .unwrap() |
397 | + .label("t statistic") |
398 | +- .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &DARK_BLUE)); |
399 | ++ .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], DARK_BLUE)); |
400 | + |
401 | + chart.configure_series_labels().draw().unwrap(); |
402 | + } |
403 | +-- |
404 | +2.40.0 |
405 | + |
406 | diff --git a/debian/patches/series b/debian/patches/series |
407 | index e59b546..6494a0c 100644 |
408 | --- a/debian/patches/series |
409 | +++ b/debian/patches/series |
410 | @@ -1,2 +1,3 @@ |
411 | +0001-chore-wibbles-to-fix-CI-635.patch |
412 | 2001_ciborium.patch |
413 | 2002_no_unstable_features.patch |
This has been uploaded in 0.4.0-2ubuntu1 and can be closed.