mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-12 15:16:35 +00:00
commit
5e7f69c4e8
14 changed files with 164 additions and 26 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.rs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
@ -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
|
||||
|
|
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -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"
|
||||
|
@ -251,6 +257,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 +573,7 @@ dependencies = [
|
|||
"clap_complete",
|
||||
"config",
|
||||
"criterion",
|
||||
"criterion_bencher_compat",
|
||||
"git2",
|
||||
"hex",
|
||||
"indoc",
|
||||
|
@ -578,6 +594,7 @@ dependencies = [
|
|||
name = "jujutsu-lib"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"backoff",
|
||||
"blake2",
|
||||
"byteorder",
|
||||
|
@ -601,6 +618,7 @@ dependencies = [
|
|||
"test-case",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"version_check",
|
||||
"whoami",
|
||||
"zstd",
|
||||
]
|
||||
|
@ -1416,9 +1434,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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
|
@ -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"
|
||||
|
@ -40,5 +41,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"
|
||||
|
|
|
@ -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\"");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ use std::ops::Range;
|
|||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::nightly_shims::BTreeMapExt;
|
||||
|
||||
pub fn find_line_ranges(text: &[u8]) -> Vec<Range<usize>> {
|
||||
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.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.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);
|
||||
|
|
|
@ -35,6 +35,9 @@ 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)]
|
||||
pub struct IndexPosition(u32);
|
||||
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![feature(assert_matches)]
|
||||
#![feature(map_first_last)]
|
||||
#![deny(unused_must_use)]
|
||||
#![cfg_attr(feature = "map_first_last", feature(map_first_last))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pest_derive;
|
||||
|
@ -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;
|
||||
|
|
92
lib/src/nightly_shims.rs
Normal file
92
lib/src/nightly_shims.rs
Normal file
|
@ -0,0 +1,92 @@
|
|||
#[cfg(feature = "map_first_last")]
|
||||
pub trait BTreeMapExt<K, V> {
|
||||
fn first_key(&self) -> Option<&K>;
|
||||
fn last_key(&self) -> Option<&K>;
|
||||
fn pop_first_value(&mut self) -> Option<V>;
|
||||
fn pop_last_value(&mut self) -> Option<V>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "map_first_last")]
|
||||
impl<K: Ord + Clone, V> BTreeMapExt<K, V> for std::collections::BTreeMap<K, V> {
|
||||
fn first_key(&self) -> Option<&K> {
|
||||
self.keys().next()
|
||||
}
|
||||
|
||||
fn last_key(&self) -> Option<&K> {
|
||||
self.keys().next_back()
|
||||
}
|
||||
fn pop_first_value(&mut self) -> Option<V> {
|
||||
self.first_entry().map(|x| x.remove())
|
||||
}
|
||||
|
||||
fn pop_last_value(&mut self) -> Option<V> {
|
||||
self.last_entry().map(|x| x.remove())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "map_first_last"))]
|
||||
pub trait BTreeMapExt<K, V> {
|
||||
fn first_key(&self) -> Option<&K>;
|
||||
fn last_key(&self) -> Option<&K>;
|
||||
fn pop_first_key(&mut self) -> Option<K>;
|
||||
fn pop_last_key(&mut self) -> Option<K>;
|
||||
fn pop_first_value(&mut self) -> Option<V>;
|
||||
fn pop_last_value(&mut self) -> Option<V>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "map_first_last"))]
|
||||
impl<K: Ord + Clone, V> BTreeMapExt<K, V> for std::collections::BTreeMap<K, V> {
|
||||
fn first_key(&self) -> Option<&K> {
|
||||
self.keys().next()
|
||||
}
|
||||
|
||||
fn last_key(&self) -> Option<&K> {
|
||||
self.keys().next_back()
|
||||
}
|
||||
|
||||
fn pop_first_key(&mut self) -> Option<K> {
|
||||
let key = self.first_key()?;
|
||||
let key = key.clone(); // ownership hack
|
||||
Some(self.remove_entry(&key).unwrap().0)
|
||||
}
|
||||
|
||||
fn pop_last_key(&mut self) -> Option<K> {
|
||||
let key = self.last_key()?;
|
||||
let key = key.clone(); // ownership hack
|
||||
Some(self.remove_entry(&key).unwrap().0)
|
||||
}
|
||||
|
||||
fn pop_first_value(&mut self) -> Option<V> {
|
||||
let key = self.first_key()?;
|
||||
let key = key.clone(); // ownership hack
|
||||
Some(self.remove_entry(&key).unwrap().1)
|
||||
}
|
||||
|
||||
fn pop_last_value(&mut self) -> Option<V> {
|
||||
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<K> {}
|
||||
|
||||
#[cfg(not(feature = "map_first_last"))]
|
||||
pub trait BTreeSetExt<K> {
|
||||
fn last(&self) -> Option<&K>;
|
||||
fn pop_last(&mut self) -> Option<K>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "map_first_last"))]
|
||||
impl<K: Ord + Clone> BTreeSetExt<K> for std::collections::BTreeSet<K> {
|
||||
fn last(&self) -> Option<&K> {
|
||||
self.iter().next_back()
|
||||
}
|
||||
|
||||
fn pop_last(&mut self) -> Option<K> {
|
||||
let key = self.last()?;
|
||||
let key = key.clone(); // ownership hack
|
||||
self.take(&key)
|
||||
}
|
||||
}
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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<IndexEntry<'repo>> {
|
||||
if let Some((_, index_entry)) = self.look_ahead.pop_last() {
|
||||
if let Some(index_entry) = self.look_ahead.pop_last_value() {
|
||||
return Some(index_entry);
|
||||
}
|
||||
self.input_set_iter.next()
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue