From 325eb4f4ca44918f74e9d218519920e7c460a25f Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 21:17:36 -0800 Subject: [PATCH 1/6] Add .editorconfig This file sets formatting defaults for editors. See https://editorconfig.org/. --- .editorconfig | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..bf1ef9cc2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true + +[*.rs] +indent_style = space +indent_size = 4 From 261cd1a1c4a5da445157193e2da6160cd3fb948b Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 21:14:48 -0800 Subject: [PATCH 2/6] build: add shims for nightly feature `map_first_last` --- lib/src/diff.rs | 6 ++-- lib/src/index.rs | 13 +++---- lib/src/lib.rs | 2 +- lib/src/nightly_shims.rs | 61 ++++++++++++++++++++++++++++++++ lib/src/revset_graph_iterator.rs | 3 +- 5 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 lib/src/nightly_shims.rs diff --git a/lib/src/diff.rs b/lib/src/diff.rs index c4d59c4c3..b11b1eb98 100644 --- a/lib/src/diff.rs +++ b/lib/src/diff.rs @@ -19,6 +19,8 @@ use std::ops::Range; use itertools::Itertools; +use crate::nightly_shims::BTreeMapExt; + pub fn find_line_ranges(text: &[u8]) -> Vec> { let mut ranges = vec![]; let mut start = 0; @@ -175,7 +177,7 @@ pub(crate) fn unchanged_ranges( let max_occurrences = 100; let mut left_histogram = Histogram::calculate(left, left_ranges, max_occurrences); - if *left_histogram.count_to_words.first_entry().unwrap().key() > max_occurrences { + if *left_histogram.count_to_words.ext_first_key().unwrap() > max_occurrences { // If there are very many occurrences of all words, then we just give up. return vec![]; } @@ -185,7 +187,7 @@ pub(crate) fn unchanged_ranges( // the LCS. let mut uncommon_shared_words = vec![]; while !left_histogram.count_to_words.is_empty() && uncommon_shared_words.is_empty() { - let left_words = left_histogram.count_to_words.pop_first().unwrap().1; + let left_words = left_histogram.count_to_words.ext_pop_first_value().unwrap(); for left_word in left_words { if right_histogram.word_to_positions.contains_key(left_word) { uncommon_shared_words.push(left_word); diff --git a/lib/src/index.rs b/lib/src/index.rs index 6e322843a..87d6282bb 100644 --- a/lib/src/index.rs +++ b/lib/src/index.rs @@ -34,6 +34,7 @@ use thiserror::Error; use crate::backend::{ChangeId, CommitId}; use crate::commit::Commit; use crate::file_util::persist_content_addressed_temp_file; +use crate::nightly_shims::BTreeSetExt; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] pub struct IndexPosition(u32); @@ -812,25 +813,25 @@ impl<'a> CompositeIndex<'a> { let mut result = BTreeSet::new(); while !(items1.is_empty() || items2.is_empty()) { - let entry1 = items1.last().unwrap(); - let entry2 = items2.last().unwrap(); + let entry1 = items1.ext_last().unwrap(); + let entry2 = items2.ext_last().unwrap(); match entry1.cmp(entry2) { Ordering::Greater => { - let entry1 = items1.pop_last().unwrap(); + let entry1 = items1.ext_pop_last().unwrap(); for parent_entry in entry1.0.parents() { items1.insert(IndexEntryByGeneration(parent_entry)); } } Ordering::Less => { - let entry2 = items2.pop_last().unwrap(); + let entry2 = items2.ext_pop_last().unwrap(); for parent_entry in entry2.0.parents() { items2.insert(IndexEntryByGeneration(parent_entry)); } } Ordering::Equal => { result.insert(entry1.0.pos); - items1.pop_last(); - items2.pop_last(); + items1.ext_pop_last(); + items2.ext_pop_last(); } } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 950798692..6b1502dda 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -13,7 +13,6 @@ // limitations under the License. #![feature(assert_matches)] -#![feature(map_first_last)] #![deny(unused_must_use)] #[macro_use] @@ -39,6 +38,7 @@ pub mod index_store; pub mod local_backend; pub mod lock; pub mod matchers; +pub mod nightly_shims; pub mod op_heads_store; pub mod op_store; pub mod operation; diff --git a/lib/src/nightly_shims.rs b/lib/src/nightly_shims.rs new file mode 100644 index 000000000..c9d7301ef --- /dev/null +++ b/lib/src/nightly_shims.rs @@ -0,0 +1,61 @@ +use std::collections::{BTreeMap, BTreeSet}; + +pub trait BTreeMapExt { + fn ext_first_key(&self) -> Option<&K>; + fn ext_last_key(&self) -> Option<&K>; + fn ext_pop_first_key(&mut self) -> Option; + fn ext_pop_last_key(&mut self) -> Option; + fn ext_pop_first_value(&mut self) -> Option; + fn ext_pop_last_value(&mut self) -> Option; +} + +impl BTreeMapExt for BTreeMap { + fn ext_first_key(&self) -> Option<&K> { + self.keys().next() + } + + fn ext_last_key(&self) -> Option<&K> { + self.keys().next_back() + } + + fn ext_pop_first_key(&mut self) -> Option { + let key = self.ext_first_key()?; + let key = key.clone(); // ownership hack + Some(self.remove_entry(&key).unwrap().0) + } + + fn ext_pop_last_key(&mut self) -> Option { + let key = self.ext_last_key()?; + let key = key.clone(); // ownership hack + Some(self.remove_entry(&key).unwrap().0) + } + + fn ext_pop_first_value(&mut self) -> Option { + let key = self.ext_first_key()?; + let key = key.clone(); // ownership hack + Some(self.remove_entry(&key).unwrap().1) + } + + fn ext_pop_last_value(&mut self) -> Option { + let key = self.ext_last_key()?; + let key = key.clone(); // ownership hack + Some(self.remove_entry(&key).unwrap().1) + } +} + +pub trait BTreeSetExt { + fn ext_last(&self) -> Option<&K>; + fn ext_pop_last(&mut self) -> Option; +} + +impl BTreeSetExt for BTreeSet { + fn ext_last(&self) -> Option<&K> { + self.iter().next_back() + } + + fn ext_pop_last(&mut self) -> Option { + let key = self.ext_last()?; + let key = key.clone(); // ownership hack + self.take(&key) + } +} diff --git a/lib/src/revset_graph_iterator.rs b/lib/src/revset_graph_iterator.rs index 7ea4c9a69..c1f6920a1 100644 --- a/lib/src/revset_graph_iterator.rs +++ b/lib/src/revset_graph_iterator.rs @@ -16,6 +16,7 @@ use std::cmp::min; use std::collections::{BTreeMap, HashSet}; use crate::index::{IndexEntry, IndexPosition}; +use crate::nightly_shims::BTreeMapExt; use crate::revset::RevsetIterator; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -149,7 +150,7 @@ impl<'revset, 'repo> RevsetGraphIterator<'revset, 'repo> { } fn next_index_entry(&mut self) -> Option> { - if let Some((_, index_entry)) = self.look_ahead.pop_last() { + if let Some(index_entry) = self.look_ahead.ext_pop_last_value() { return Some(index_entry); } self.input_set_iter.next() From 75480c2bdc827ffb89e6f65e6cf5623fe8610066 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 22:21:14 -0800 Subject: [PATCH 3/6] build: migrate `diff_bench` to `criterion` Benchmarking is currently nightly-only, so to get `jujutsu` to build on stable, we need to use a stable benchmarking library. --- Cargo.lock | 10 ++++++++++ Cargo.toml | 6 ++++++ {lib/benches => benches}/diff_bench.rs | 25 ++++++++++++++----------- 3 files changed, 30 insertions(+), 11 deletions(-) rename {lib/benches => benches}/diff_bench.rs (92%) diff --git a/Cargo.lock b/Cargo.lock index ce7e025f5..1e6a4aa4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,6 +251,15 @@ dependencies = [ "itertools", ] +[[package]] +name = "criterion_bencher_compat" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb92ac87446e7097e0f429c0bb509a1040bfae23bc0320acac30d9fec23d1ed" +dependencies = [ + "criterion", +] + [[package]] name = "crossbeam-channel" version = "0.5.1" @@ -558,6 +567,7 @@ dependencies = [ "clap_complete", "config", "criterion", + "criterion_bencher_compat", "git2", "hex", "indoc", diff --git a/Cargo.toml b/Cargo.toml index 5cdc15916..e06983678 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,10 @@ categories = ["command-line-utilities", "development-tools"] name = "jj" path = "src/main.rs" +[[bench]] +name = "diff_bench" +harness = false + [workspace] members = ["lib"] @@ -42,3 +46,5 @@ thiserror = "1.0.30" [dev-dependencies] test-case = "1.2.3" regex = "1.5.4" +criterion = "0.3.5" +criterion_bencher_compat = "0.3.4" diff --git a/lib/benches/diff_bench.rs b/benches/diff_bench.rs similarity index 92% rename from lib/benches/diff_bench.rs rename to benches/diff_bench.rs index 09c82f36a..3cd4217d1 100644 --- a/lib/benches/diff_bench.rs +++ b/benches/diff_bench.rs @@ -1,9 +1,7 @@ -#![feature(test)] - -extern crate test; +use bencher::{benchmark_group, benchmark_main, Bencher}; +use criterion_bencher_compat as bencher; use jujutsu_lib::diff; -use test::Bencher; fn unchanged_lines(count: usize) -> (String, String) { let mut lines = vec![]; @@ -33,43 +31,36 @@ fn reversed_lines(count: usize) -> (String, String) { (left_lines.join(""), right_lines.join("")) } -#[bench] fn bench_diff_1k_unchanged_lines(b: &mut Bencher) { let (left, right) = unchanged_lines(1000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_10k_unchanged_lines(b: &mut Bencher) { let (left, right) = unchanged_lines(10000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_1k_modified_lines(b: &mut Bencher) { let (left, right) = modified_lines(1000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_10k_modified_lines(b: &mut Bencher) { let (left, right) = modified_lines(10000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_1k_lines_reversed(b: &mut Bencher) { let (left, right) = reversed_lines(1000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_10k_lines_reversed(b: &mut Bencher) { let (left, right) = reversed_lines(10000); b.iter(|| diff::diff(left.as_bytes(), right.as_bytes())); } -#[bench] fn bench_diff_git_git_read_tree_c(b: &mut Bencher) { b.iter(|| { diff::diff( @@ -214,3 +205,15 @@ int main(int argc, char **argv) ) }); } + +benchmark_group!( + benches, + bench_diff_1k_unchanged_lines, + bench_diff_10k_unchanged_lines, + bench_diff_1k_modified_lines, + bench_diff_10k_modified_lines, + bench_diff_1k_lines_reversed, + bench_diff_10k_lines_reversed, + bench_diff_git_git_read_tree_c, +); +benchmark_main!(benches); From dd3272fe909a19969fcd666fd639abd4a3a90e22 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 21:45:09 -0800 Subject: [PATCH 4/6] build: use `assert_matches` crate The `assert_matches` feature is nightly-only, so use this crate as a shim. --- Cargo.lock | 11 +++++++++-- lib/Cargo.toml | 1 + lib/src/lib.rs | 1 - lib/src/revset.rs | 2 +- lib/tests/test_merge_trees.rs | 5 +---- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e6a4aa4d..f5a150c99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "atty" version = "0.2.14" @@ -588,6 +594,7 @@ dependencies = [ name = "jujutsu-lib" version = "0.2.0" dependencies = [ + "assert_matches", "backoff", "blake2", "byteorder", @@ -1426,9 +1433,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 961577c9b..40a7df8b8 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -40,5 +40,6 @@ whoami = "1.2.1" zstd = "0.10.0" [dev-dependencies] +assert_matches = "1.5.0" num_cpus = "1.13.1" test-case = "1.2.3" diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 6b1502dda..da9b4f27e 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(assert_matches)] #![deny(unused_must_use)] #[macro_use] diff --git a/lib/src/revset.rs b/lib/src/revset.rs index 147316f84..c1347e0a8 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -1311,7 +1311,7 @@ pub fn revset_for_commits<'revset, 'repo: 'revset>( #[cfg(test)] mod tests { - use std::assert_matches::assert_matches; + use assert_matches::assert_matches; use super::*; diff --git a/lib/tests/test_merge_trees.rs b/lib/tests/test_merge_trees.rs index aa39bd511..af281ee30 100644 --- a/lib/tests/test_merge_trees.rs +++ b/lib/tests/test_merge_trees.rs @@ -12,10 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(assert_matches)] - -use std::assert_matches::assert_matches; - +use assert_matches::assert_matches; use itertools::Itertools; use jujutsu_lib::backend::{ConflictPart, TreeValue}; use jujutsu_lib::commit_builder::CommitBuilder; From 9202aae8b1d3f8f10840064731605b39a6ce9d09 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 22:14:13 -0800 Subject: [PATCH 5/6] build: conditionally use `map_first_last` feature if available --- Cargo.lock | 1 + lib/Cargo.toml | 1 + lib/build.rs | 5 ++ lib/src/diff.rs | 4 +- lib/src/index.rs | 14 +++--- lib/src/lib.rs | 1 + lib/src/nightly_shims.rs | 81 ++++++++++++++++++++++---------- lib/src/revset_graph_iterator.rs | 2 +- 8 files changed, 75 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5a150c99..1a861afa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -618,6 +618,7 @@ dependencies = [ "test-case", "thiserror", "uuid", + "version_check", "whoami", "zstd", ] diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 40a7df8b8..c4e59799d 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -14,6 +14,7 @@ readme = "../README.md" [build-dependencies] protobuf-codegen-pure = "2.27.1" +version_check = "0.9.4" [dependencies] backoff = "0.4.0" diff --git a/lib/build.rs b/lib/build.rs index 56e497b67..743214ba0 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -13,6 +13,7 @@ // limitations under the License. extern crate protobuf_codegen_pure; +extern crate version_check; use std::path::Path; @@ -45,4 +46,8 @@ fn main() { for file in input { println!("cargo:rerun-if-changed={}", file); } + + if let Some(true) = version_check::supports_feature("map_first_last") { + println!("cargo:rustc-cfg=feature=\"map_first_last\""); + } } diff --git a/lib/src/diff.rs b/lib/src/diff.rs index b11b1eb98..dc3dd13d9 100644 --- a/lib/src/diff.rs +++ b/lib/src/diff.rs @@ -177,7 +177,7 @@ pub(crate) fn unchanged_ranges( let max_occurrences = 100; let mut left_histogram = Histogram::calculate(left, left_ranges, max_occurrences); - if *left_histogram.count_to_words.ext_first_key().unwrap() > max_occurrences { + if *left_histogram.count_to_words.first_key().unwrap() > max_occurrences { // If there are very many occurrences of all words, then we just give up. return vec![]; } @@ -187,7 +187,7 @@ pub(crate) fn unchanged_ranges( // the LCS. let mut uncommon_shared_words = vec![]; while !left_histogram.count_to_words.is_empty() && uncommon_shared_words.is_empty() { - let left_words = left_histogram.count_to_words.ext_pop_first_value().unwrap(); + let left_words = left_histogram.count_to_words.pop_first_value().unwrap(); for left_word in left_words { if right_histogram.word_to_positions.contains_key(left_word) { uncommon_shared_words.push(left_word); diff --git a/lib/src/index.rs b/lib/src/index.rs index 87d6282bb..b2f190225 100644 --- a/lib/src/index.rs +++ b/lib/src/index.rs @@ -34,6 +34,8 @@ use thiserror::Error; use crate::backend::{ChangeId, CommitId}; use crate::commit::Commit; use crate::file_util::persist_content_addressed_temp_file; + +#[cfg(not(feature = "map_first_last"))] use crate::nightly_shims::BTreeSetExt; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] @@ -813,25 +815,25 @@ impl<'a> CompositeIndex<'a> { let mut result = BTreeSet::new(); while !(items1.is_empty() || items2.is_empty()) { - let entry1 = items1.ext_last().unwrap(); - let entry2 = items2.ext_last().unwrap(); + let entry1 = items1.last().unwrap(); + let entry2 = items2.last().unwrap(); match entry1.cmp(entry2) { Ordering::Greater => { - let entry1 = items1.ext_pop_last().unwrap(); + let entry1 = items1.pop_last().unwrap(); for parent_entry in entry1.0.parents() { items1.insert(IndexEntryByGeneration(parent_entry)); } } Ordering::Less => { - let entry2 = items2.ext_pop_last().unwrap(); + let entry2 = items2.pop_last().unwrap(); for parent_entry in entry2.0.parents() { items2.insert(IndexEntryByGeneration(parent_entry)); } } Ordering::Equal => { result.insert(entry1.0.pos); - items1.ext_pop_last(); - items2.ext_pop_last(); + items1.pop_last(); + items2.pop_last(); } } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index da9b4f27e..8a2a39c82 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -13,6 +13,7 @@ // limitations under the License. #![deny(unused_must_use)] +#![cfg_attr(feature = "map_first_last", feature(map_first_last))] #[macro_use] extern crate pest_derive; diff --git a/lib/src/nightly_shims.rs b/lib/src/nightly_shims.rs index c9d7301ef..6350273ba 100644 --- a/lib/src/nightly_shims.rs +++ b/lib/src/nightly_shims.rs @@ -1,60 +1,91 @@ -use std::collections::{BTreeMap, BTreeSet}; - +#[cfg(feature = "map_first_last")] pub trait BTreeMapExt { - fn ext_first_key(&self) -> Option<&K>; - fn ext_last_key(&self) -> Option<&K>; - fn ext_pop_first_key(&mut self) -> Option; - fn ext_pop_last_key(&mut self) -> Option; - fn ext_pop_first_value(&mut self) -> Option; - fn ext_pop_last_value(&mut self) -> Option; + fn first_key(&self) -> Option<&K>; + fn last_key(&self) -> Option<&K>; + fn pop_first_value(&mut self) -> Option; + fn pop_last_value(&mut self) -> Option; } -impl BTreeMapExt for BTreeMap { - fn ext_first_key(&self) -> Option<&K> { +#[cfg(feature = "map_first_last")] +impl BTreeMapExt for std::collections::BTreeMap { + fn first_key(&self) -> Option<&K> { self.keys().next() } - fn ext_last_key(&self) -> Option<&K> { + fn last_key(&self) -> Option<&K> { + self.keys().next_back() + } + fn pop_first_value(&mut self) -> Option { + self.first_entry().map(|x| x.remove()) + } + + fn pop_last_value(&mut self) -> Option { + self.last_entry().map(|x| x.remove()) + } +} + +#[cfg(not(feature = "map_first_last"))] +pub trait BTreeMapExt { + fn first_key(&self) -> Option<&K>; + fn last_key(&self) -> Option<&K>; + fn pop_first_key(&mut self) -> Option; + fn pop_last_key(&mut self) -> Option; + fn pop_first_value(&mut self) -> Option; + fn pop_last_value(&mut self) -> Option; +} + +#[cfg(not(feature = "map_first_last"))] +impl BTreeMapExt for std::collections::BTreeMap { + fn first_key(&self) -> Option<&K> { + self.keys().next() + } + + fn last_key(&self) -> Option<&K> { self.keys().next_back() } - fn ext_pop_first_key(&mut self) -> Option { - let key = self.ext_first_key()?; + fn pop_first_key(&mut self) -> Option { + let key = self.first_key()?; let key = key.clone(); // ownership hack Some(self.remove_entry(&key).unwrap().0) } - fn ext_pop_last_key(&mut self) -> Option { - let key = self.ext_last_key()?; + fn pop_last_key(&mut self) -> Option { + let key = self.last_key()?; let key = key.clone(); // ownership hack Some(self.remove_entry(&key).unwrap().0) } - fn ext_pop_first_value(&mut self) -> Option { - let key = self.ext_first_key()?; + fn pop_first_value(&mut self) -> Option { + let key = self.first_key()?; let key = key.clone(); // ownership hack Some(self.remove_entry(&key).unwrap().1) } - fn ext_pop_last_value(&mut self) -> Option { - let key = self.ext_last_key()?; + fn pop_last_value(&mut self) -> Option { + let key = self.last_key()?; let key = key.clone(); // ownership hack Some(self.remove_entry(&key).unwrap().1) } } +#[cfg(feature = "map_first_last")] +pub trait BTreeSetExt {} + +#[cfg(not(feature = "map_first_last"))] pub trait BTreeSetExt { - fn ext_last(&self) -> Option<&K>; - fn ext_pop_last(&mut self) -> Option; + fn last(&self) -> Option<&K>; + fn pop_last(&mut self) -> Option; } -impl BTreeSetExt for BTreeSet { - fn ext_last(&self) -> Option<&K> { +#[cfg(not(feature = "map_first_last"))] +impl BTreeSetExt for std::collections::BTreeSet { + fn last(&self) -> Option<&K> { self.iter().next_back() } - fn ext_pop_last(&mut self) -> Option { - let key = self.ext_last()?; + fn pop_last(&mut self) -> Option { + let key = self.last()?; let key = key.clone(); // ownership hack self.take(&key) } diff --git a/lib/src/revset_graph_iterator.rs b/lib/src/revset_graph_iterator.rs index c1f6920a1..d3725007d 100644 --- a/lib/src/revset_graph_iterator.rs +++ b/lib/src/revset_graph_iterator.rs @@ -150,7 +150,7 @@ impl<'revset, 'repo> RevsetGraphIterator<'revset, 'repo> { } fn next_index_entry(&mut self) -> Option> { - if let Some(index_entry) = self.look_ahead.ext_pop_last_value() { + if let Some(index_entry) = self.look_ahead.pop_last_value() { return Some(index_entry); } self.input_set_iter.next() From b011805fc7dd14353ec9a55dfe8adb81127bb2c6 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Sun, 20 Feb 2022 22:18:43 -0800 Subject: [PATCH 6/6] ci: use stable Rust for builds We still use nightly Clippy to ensure that 1) it builds under nightly and 2) that we pick up any new lints. --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01c80448c..3e8027e8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install Rust nightly + - name: Install Rust (stable) uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true profile: minimal - name: Build @@ -31,7 +31,7 @@ jobs: RUST_BACKTRACE: 1 clippy: - name: Clippy check + name: Clippy check (nightly) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2