Make CI pass again
Unified · Split
| @@ -1924,6 +1924,8 @@ dependencies = [ · 1923 unmodified lines | ||
| 1924 | 1924 | "bstr", |
| 1925 | 1925 | "cov-mark", |
| 1926 | 1926 | "expect-test", |
| 1927 | + "gix-hash", | |
| 1928 | + "gix-object", | |
| 1927 | 1929 | "hashbrown 0.16.1", |
| 1928 | 1930 | "memchr", |
| 1929 | 1931 | ] |
| @@ -1,13 +1,16 @@ | ||
| 1 | +# Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +# Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:Cargo.toml | |
| 3 | + | |
| 1 | 4 | [package] |
| 2 | 5 | name = "gix-imara-diff" |
| 3 | 6 | version = "0.2.0" |
| 4 | 7 | edition = "2021" |
| 5 | −authors = ["pascalkuthe <pascalkuthe@pm.me>"] | |
| 8 | +authors = ["pascalkuthe <pascalkuthe@pm.me>", "Sebastian Thiel <sebastian.thiel@icloud.com>"] | |
| 6 | 9 | rust-version = "1.71" |
| 7 | 10 | license = "Apache-2.0" |
| 8 | 11 | |
| 9 | −description = "A high performance library for computing diffs." | |
| 10 | −repository = "https://github.com/pascalkuthe/imara-diff" | |
| 12 | +description = "A high performance library for computing diffs, maintained as a modified copy of upstream imara-diff for gitoxide." | |
| 13 | +repository = "https://github.com/GitoxideLabs/gitoxide" | |
| 11 | 14 | keywords = ["diff", "difference", "myers", "compare", "changes"] |
| 12 | 15 | readme = "README.md" |
| 13 | 16 | exclude = [ |
| @@ -26,6 +29,8 @@ default = ["unified_diff"] · 12 unmodified lines | ||
| 26 | 29 | unified_diff = [] |
| 27 | 30 | |
| 28 | 31 | [dev-dependencies] |
| 32 | +gix-hash = { version = "^0.23.0", path = "../gix-hash", features = ["sha1"] } | |
| 33 | +gix-object = { version = "^0.58.0", path = "../gix-object", features = ["sha1"] } | |
| 29 | 34 | cov-mark = "2.1.0" |
| 30 | 35 | expect-test = "1.4.0" |
| 31 | 36 | |
| @@ -1,5 +1,8 @@ | ||
| 1 | 1 | # imara-diff |
| 2 | 2 | |
| 3 | +> Modified for gitoxide from the upstream imara-diff crate. | |
| 4 | +> Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:README.md | |
| 5 | + | |
| 3 | 6 | [](https://crates.io/crates/imara-diff) |
| 4 | 7 | [](https://docs.rs/imara-diff/latest/imara_diff/) |
| 5 | 8 |  |
| @@ -0,0 +1,24 @@ | ||
| 1 | +# upstream-repo: https://github.com/pascalkuthe/imara-diff | |
| 2 | +# upstream-branch: fix-timeout-window-0.2 | |
| 3 | +# upstream-commit: 32d1e45d3df061e6ccba6db7fdce92db29e345d8 | |
| 4 | +# columns: path<TAB>origin<TAB>status<TAB>upstream-blob<TAB>cat-file | |
| 5 | +.cargo_vcs_info.json generated generated - - | |
| 6 | +Cargo.lock generated generated - - | |
| 7 | +Cargo.toml upstream modified af703a238ed9f159d5c41e2bd5e86e0cc2031cf0 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:Cargo.toml | |
| 8 | +Cargo.toml.orig generated generated - - | |
| 9 | +LICENSE upstream unchanged 16fe87b06e802f094b3fbb0894b137bca2b16ef1 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:LICENSE | |
| 10 | +README.md upstream modified b1e722e2d0731797b708b56369ed8f1fbd742f09 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:README.md | |
| 11 | +src/histogram.rs upstream modified ff2cb0e341d18c28931e01fba01674f071827f2b git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram.rs | |
| 12 | +src/histogram/lcs.rs upstream modified 5a86e13fa324a589d9bc4ffb8ac38824a619ed18 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram/lcs.rs | |
| 13 | +src/histogram/list_pool.rs upstream modified 0f014216ac53750764a816b39929b892aa75097f git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram/list_pool.rs | |
| 14 | +src/intern.rs upstream modified f93fb54425a0d0f35eb1bb7071e34e94aede0750 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/intern.rs | |
| 15 | +src/lib.rs upstream modified 6a6eea650debc7897e6a58c9ced5b4c3454be711 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/lib.rs | |
| 16 | +src/myers.rs upstream modified 2ace530c0e282436c1b639e5ce89bcf3a1a6b901 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers.rs | |
| 17 | +src/myers/middle_snake.rs upstream modified a5cb5197c948821f5da2d377bdc729152745f9d4 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers/middle_snake.rs | |
| 18 | +src/myers/preprocess.rs upstream modified 2ef5debd763f5859bc73ad0c54b6d558b1db44ec git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers/preprocess.rs | |
| 19 | +src/myers/slice.rs upstream unchanged f266fa7e17f07eb4a8c6d61fa942607a4beca52b git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers/slice.rs | |
| 20 | +src/postprocess.rs upstream modified 651b12b3a49019a6e2238d51c38d137c09f3ba27 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/postprocess.rs | |
| 21 | +src/slider_heuristic.rs upstream modified f3f85914427df381dcee42e44d406cb54663f91c git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/slider_heuristic.rs | |
| 22 | +src/sources.rs upstream modified e8ddcfc592b0a8b287b1b6923408ac91e79dbe50 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/sources.rs | |
| 23 | +src/unified_diff.rs upstream modified 725331afc30774b0ecc0d85cca804a94b7751578 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/unified_diff.rs | |
| 24 | +src/util.rs upstream modified e85c3aa9ab46352d4d729acc7b86d4ac1be594d6 git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/util.rs | |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram.rs | |
| 3 | + | |
| 1 | 4 | use crate::histogram::lcs::find_lcs; |
| 2 | 5 | use crate::histogram::list_pool::{ListHandle, ListPool}; |
| 3 | 6 | use crate::intern::Token; |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram/lcs.rs | |
| 3 | + | |
| 1 | 4 | use crate::histogram::{Histogram, MAX_CHAIN_LEN}; |
| 2 | 5 | use crate::intern::Token; |
| 3 | 6 | |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/histogram/list_pool.rs | |
| 3 | + | |
| 1 | 4 | use crate::histogram::MAX_CHAIN_LEN; |
| 2 | 5 | |
| 3 | 6 | /// A small list of entity references allocated from a pool. |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/intern.rs | |
| 3 | + | |
| 1 | 4 | use std::hash::{BuildHasher as _, Hash}; |
| 2 | 5 | use std::ops::Index; |
| 3 | 6 | |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/lib.rs | |
| 3 | + | |
| 1 | 4 | #![deny(missing_docs)] |
| 2 | 5 | //! Imara-diff is a solid (imara in Swahili) diff library for Rust. |
| 3 | 6 | //! Solid refers to the fact that imara-diff provides very good runtime performance even |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers.rs | |
| 3 | + | |
| 1 | 4 | use std::ptr::NonNull; |
| 2 | 5 | |
| 3 | 6 | use crate::intern::Token; |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers/middle_snake.rs | |
| 3 | + | |
| 1 | 4 | use std::ptr::NonNull; |
| 2 | 5 | |
| 3 | 6 | use crate::myers::slice::FileSlice; |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/myers/preprocess.rs | |
| 3 | + | |
| 1 | 4 | use crate::intern::Token; |
| 2 | 5 | use crate::myers::sqrt; |
| 3 | 6 | |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/postprocess.rs | |
| 3 | + | |
| 1 | 4 | use crate::intern::{InternedInput, Token}; |
| 2 | 5 | use crate::slider_heuristic::SliderHeuristic; |
| 3 | 6 | use crate::util::{find_hunk_end, find_hunk_start}; |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/slider_heuristic.rs | |
| 3 | + | |
| 1 | 4 | use std::cmp::Ordering; |
| 2 | 5 | use std::hash::Hash; |
| 3 | 6 | use std::ops::{Add, Range}; |
| @@ -1,3 +1,6 @@ | ||
| 1 | +//! Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +//! Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/sources.rs | |
| 3 | +//! | |
| 1 | 4 | //! Utilities for creating token sources from common data types. |
| 2 | 5 | //! |
| 3 | 6 | //! This module provides implementations of [`TokenSource`] for |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/unified_diff.rs | |
| 3 | + | |
| 1 | 4 | use std::fmt::{self, Display}; |
| 2 | 5 | use std::hash::Hash; |
| 3 | 6 | |
| @@ -1,3 +1,6 @@ | ||
| 1 | +// Modified for gitoxide from the upstream imara-diff crate. | |
| 2 | +// Upstream source: git cat-file -p 32d1e45d3df061e6ccba6db7fdce92db29e345d8:src/util.rs | |
| 3 | + | |
| 1 | 4 | use crate::intern::Token; |
| 2 | 5 | use crate::Hunk; |
| 3 | 6 | |
| @@ -0,0 +1,219 @@ | ||
| 1 | +//! Verifies that the published `gix-imara-diff` package has explicit provenance metadata for every | |
| 2 | +//! packaged file, and that files tracked as upstream or modified still match the | |
| 3 | +//! `UPSTREAM-PROVENANCE.tsv` manifest. | |
| 4 | + | |
| 5 | +use std::collections::{BTreeMap, BTreeSet}; | |
| 6 | +use std::env; | |
| 7 | +use std::fs; | |
| 8 | +use std::path::{Path, PathBuf}; | |
| 9 | +use std::process::Command; | |
| 10 | + | |
| 11 | +#[derive(Debug)] | |
| 12 | +struct Provenance { | |
| 13 | + upstream_commit: String, | |
| 14 | + entries: BTreeMap<String, Entry>, | |
| 15 | +} | |
| 16 | + | |
| 17 | +#[derive(Debug)] | |
| 18 | +struct Entry { | |
| 19 | + origin: String, | |
| 20 | + status: String, | |
| 21 | + upstream_blob: String, | |
| 22 | + cat_file: String, | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Verifies the release-time provenance contract for the `gix-imara-diff` package. | |
| 26 | +/// | |
| 27 | +/// Specifically, it checks that: | |
| 28 | +/// - every file that would be included by `cargo package` has exactly one matching entry in | |
| 29 | +/// `UPSTREAM-PROVENANCE.tsv` | |
| 30 | +/// - upstream-derived files record the expected upstream commit and retrieval command | |
| 31 | +/// - upstream files marked `unchanged` still match the recorded upstream blob | |
| 32 | +/// - upstream files marked `modified` no longer match upstream and carry an in-file notice that | |
| 33 | +/// they were changed, along with the upstream retrieval command | |
| 34 | +/// - generated and local-only files do not claim an upstream blob or retrieval command | |
| 35 | +#[test] | |
| 36 | +#[cfg(unix)] | |
| 37 | +fn packaged_files_have_matching_provenance_and_modified_files_have_notices() { | |
| 38 | + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); | |
| 39 | + let workspace_root = manifest_dir | |
| 40 | + .parent() | |
| 41 | + .expect("workspace root is the parent of the crate manifest directory"); | |
| 42 | + let provenance_path = manifest_dir.join("UPSTREAM-PROVENANCE.tsv"); | |
| 43 | + let provenance = parse_provenance(&provenance_path); | |
| 44 | + let packaged_files = cargo_package_list(workspace_root); | |
| 45 | + | |
| 46 | + let packaged_set: BTreeSet<_> = packaged_files.into_iter().collect(); | |
| 47 | + let manifest_set: BTreeSet<_> = provenance.entries.keys().cloned().collect(); | |
| 48 | + assert_eq!( | |
| 49 | + manifest_set, packaged_set, | |
| 50 | + "package surface and provenance manifest diverged" | |
| 51 | + ); | |
| 52 | + | |
| 53 | + for (path, entry) in &provenance.entries { | |
| 54 | + match entry.origin.as_str() { | |
| 55 | + "upstream" => { | |
| 56 | + assert_ne!( | |
| 57 | + entry.upstream_blob, "-", | |
| 58 | + "{path}: upstream files need an upstream blob id" | |
| 59 | + ); | |
| 60 | + let expected_cat_file = format!("git cat-file -p {}:{}", provenance.upstream_commit, path); | |
| 61 | + assert_eq!( | |
| 62 | + entry.cat_file, expected_cat_file, | |
| 63 | + "{path}: upstream retrieval command must point at the recorded upstream commit" | |
| 64 | + ); | |
| 65 | + | |
| 66 | + let file_path = manifest_dir.join(path); | |
| 67 | + assert!( | |
| 68 | + file_path.is_file(), | |
| 69 | + "{path}: upstream-backed packaged files must exist on disk" | |
| 70 | + ); | |
| 71 | + | |
| 72 | + let is_modified = is_modified_from_upstream(&file_path, &entry.upstream_blob); | |
| 73 | + match entry.status.as_str() { | |
| 74 | + "modified" => { | |
| 75 | + assert!( | |
| 76 | + is_modified, | |
| 77 | + "{path}: manifest says modified but current blob matches upstream" | |
| 78 | + ); | |
| 79 | + assert_has_notice(&file_path, &expected_cat_file); | |
| 80 | + } | |
| 81 | + "unchanged" => { | |
| 82 | + assert!( | |
| 83 | + !is_modified, | |
| 84 | + "{path}: manifest says unchanged but current blob no longer matches upstream" | |
| 85 | + ); | |
| 86 | + } | |
| 87 | + other => panic!("{path}: unexpected upstream status {other}"), | |
| 88 | + } | |
| 89 | + } | |
| 90 | + "generated" => { | |
| 91 | + assert_eq!( | |
| 92 | + entry.status, "generated", | |
| 93 | + "{path}: generated files must use generated status" | |
| 94 | + ); | |
| 95 | + assert_eq!( | |
| 96 | + entry.upstream_blob, "-", | |
| 97 | + "{path}: generated files must not have upstream blobs" | |
| 98 | + ); | |
| 99 | + assert_eq!( | |
| 100 | + entry.cat_file, "-", | |
| 101 | + "{path}: generated files must not have upstream cat-file commands" | |
| 102 | + ); | |
| 103 | + } | |
| 104 | + "local-only" => { | |
| 105 | + assert_eq!( | |
| 106 | + entry.status, "local-only", | |
| 107 | + "{path}: local-only files must use local-only status" | |
| 108 | + ); | |
| 109 | + assert_eq!( | |
| 110 | + entry.upstream_blob, "-", | |
| 111 | + "{path}: local-only files must not have upstream blobs" | |
| 112 | + ); | |
| 113 | + assert_eq!( | |
| 114 | + entry.cat_file, "-", | |
| 115 | + "{path}: local-only files must not have upstream cat-file commands" | |
| 116 | + ); | |
| 117 | + } | |
| 118 | + other => panic!("{path}: unknown origin {other}"), | |
| 119 | + } | |
| 120 | + } | |
| 121 | +} | |
| 122 | + | |
| 123 | +fn parse_provenance(tsv_path: &Path) -> Provenance { | |
| 124 | + let mut upstream_commit = None; | |
| 125 | + let mut entries = BTreeMap::new(); | |
| 126 | + | |
| 127 | + for line in fs::read_to_string(tsv_path) | |
| 128 | + .expect("provenance manifest to be readable") | |
| 129 | + .lines() | |
| 130 | + { | |
| 131 | + if line.is_empty() { | |
| 132 | + continue; | |
| 133 | + } | |
| 134 | + if let Some(rest) = line.strip_prefix("# upstream-commit: ") { | |
| 135 | + upstream_commit = Some(rest.to_owned()); | |
| 136 | + continue; | |
| 137 | + } | |
| 138 | + if line.starts_with('#') { | |
| 139 | + continue; | |
| 140 | + } | |
| 141 | + | |
| 142 | + let mut fields = line.split('\t'); | |
| 143 | + let path = fields.next().expect("path").to_owned(); | |
| 144 | + let origin = fields.next().expect("origin").to_owned(); | |
| 145 | + let status = fields.next().expect("status").to_owned(); | |
| 146 | + let upstream_blob = fields.next().expect("blob").to_owned(); | |
| 147 | + let cat_file = fields.next().expect("cat-file").to_owned(); | |
| 148 | + assert!( | |
| 149 | + fields.next().is_none(), | |
| 150 | + "{path}: provenance entries must have exactly five tab-separated columns" | |
| 151 | + ); | |
| 152 | + let previous = entries.insert( | |
| 153 | + path.clone(), | |
| 154 | + Entry { | |
| 155 | + origin, | |
| 156 | + status, | |
| 157 | + upstream_blob, | |
| 158 | + cat_file, | |
| 159 | + }, | |
| 160 | + ); | |
| 161 | + assert!(previous.is_none(), "{path}: duplicate provenance entry"); | |
| 162 | + } | |
| 163 | + | |
| 164 | + Provenance { | |
| 165 | + upstream_commit: upstream_commit.expect("provenance manifest to record upstream commit"), | |
| 166 | + entries, | |
| 167 | + } | |
| 168 | +} | |
| 169 | + | |
| 170 | +fn cargo_package_list(workspace_root: &Path) -> Vec<String> { | |
| 171 | + let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()); | |
| 172 | + let output = Command::new(cargo) | |
| 173 | + .arg("package") | |
| 174 | + .arg("-p") | |
| 175 | + .arg("gix-imara-diff") | |
| 176 | + .arg("--allow-dirty") | |
| 177 | + .arg("--list") | |
| 178 | + .current_dir(workspace_root) | |
| 179 | + .output() | |
| 180 | + .expect("cargo package --list to run"); | |
| 181 | + assert!( | |
| 182 | + output.status.success(), | |
| 183 | + "cargo package --list failed: {}", | |
| 184 | + String::from_utf8_lossy(&output.stderr) | |
| 185 | + ); | |
| 186 | + | |
| 187 | + String::from_utf8(output.stdout) | |
| 188 | + .expect("cargo package --list output to be utf8") | |
| 189 | + .lines() | |
| 190 | + .filter(|line| !line.is_empty()) | |
| 191 | + .map(ToOwned::to_owned) | |
| 192 | + .collect() | |
| 193 | +} | |
| 194 | + | |
| 195 | +fn is_modified_from_upstream(path: &Path, upstream_blob: &str) -> bool { | |
| 196 | + let current = fs::read(path).expect("file content to be readable"); | |
| 197 | + git_blob(¤t) != upstream_blob | |
| 198 | +} | |
| 199 | + | |
| 200 | +fn git_blob(input: &[u8]) -> String { | |
| 201 | + gix_object::compute_hash(gix_hash::Kind::Sha1, gix_object::Kind::Blob, input) | |
| 202 | + .expect("blob hash to be computable") | |
| 203 | + .to_string() | |
| 204 | +} | |
| 205 | + | |
| 206 | +fn assert_has_notice(path: &Path, cat_file: &str) { | |
| 207 | + let content = fs::read_to_string(path).expect("modified text file to be readable as utf8"); | |
| 208 | + assert!( | |
| 209 | + content.contains("Modified for gitoxide from the upstream imara-diff crate."), | |
| 210 | + "{}: modified upstream-derived files must carry a prominent modification notice", | |
| 211 | + path.display() | |
| 212 | + ); | |
| 213 | + let expected = format!("Upstream source: {cat_file}"); | |
| 214 | + assert!( | |
| 215 | + content.contains(&expected), | |
| 216 | + "{}: modified upstream-derived files must record the upstream retrieval command", | |
| 217 | + path.display() | |
| 218 | + ); | |
| 219 | +} | |