1261 lines · 42.8 KB · Rust
RawDownload
use gix_diff::{    Rewrites,    blob::DiffLineStats,    rewrites,    rewrites::{        Copies, CopySource,        tracker::{            ChangeKind,            visit::{Source, SourceKind},        },    },    tree::visit::Relation,};use gix_object::tree::EntryKind;use pretty_assertions::assert_eq; use crate::{    hex_to_id,    rewrites::{Change, NULL_ID},}; #[test]fn rename_by_id() -> crate::Result {    // Limits are only applied when doing rewrite-checks    for limit in [0, 1] {        let rewrites = Rewrites {            copies: None,            percentage: None,            limit,            track_empty: false,        };        let mut track = util::new_tracker(rewrites);        assert!(            track.try_push_change(Change::modification(), "a".into()).is_some(),            "modifications play no role in rename tracking"        );        assert!(            track.try_push_change(Change::deletion(), "b".into()).is_none(),            "recorded for later matching"        );        assert!(            track.try_push_change(Change::addition(), "c".into()).is_none(),            "recorded for later matching"        );        let mut called = false;        let out = util::assert_emit(&mut track, |dst, src| {            assert!(!called, "only one rename pair is expected");            called = true;            assert_eq!(                src.unwrap(),                Source {                    entry_mode: EntryKind::Blob.into(),                    id: *NULL_ID,                    kind: SourceKind::Rename,                    location: "b".into(),                    change: &Change::deletion(),                    diff: None,                }            );            assert_eq!(dst.location, "c");            std::ops::ControlFlow::Continue(())        });        assert_eq!(            out,            rewrites::Outcome {                options: rewrites,                ..Default::default()            },            "no similarity check was performed, it was all matched by id"        );    }    Ok(())} #[test]fn gitlinks_are_renamed_only_by_id() {    let id = hex_to_id(        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",    );    let other_id = hex_to_id(        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",    );    let gitlink = |id, kind| Change {        id,        kind,        mode: EntryKind::Commit.into(),        relation: None,    };     let mut tracker = util::new_tracker(Default::default());    assert!(        tracker            .try_push_change(gitlink(id, ChangeKind::Deletion), "old".into())            .is_none()    );    assert!(        tracker            .try_push_change(gitlink(id, ChangeKind::Addition), "new".into())            .is_none()    );    let mut matched = false;    util::assert_emit(&mut tracker, |destination, source| {        assert_eq!(destination.location, "new");        assert_eq!(source.expect("equal gitlink IDs form an exact rename").location, "old");        matched = true;        std::ops::ControlFlow::Continue(())    });    assert!(matched, "the exact gitlink rename was emitted");     let mut tracker = util::new_tracker(Default::default());    assert!(        tracker            .try_push_change(gitlink(id, ChangeKind::Deletion), "old".into())            .is_none()    );    assert!(        tracker            .try_push_change(gitlink(other_id, ChangeKind::Addition), "new".into())            .is_none()    );    let mut unmatched = 0;    util::assert_emit(&mut tracker, |_destination, source| {        assert!(source.is_none(), "gitlink IDs are never compared by blob similarity");        unmatched += 1;        std::ops::ControlFlow::Continue(())    });    assert_eq!(unmatched, 2, "both unrelated gitlink changes remain unmatched");} #[test]fn copy_by_similarity_reports_limit_if_encountered() -> crate::Result {    let rewrites = Rewrites {        copies: Some(Copies {            source: CopySource::FromSetOfModifiedFiles,            percentage: Some(0.5),        }),        percentage: None,        limit: 1,        track_empty: false,    };    let mut track = util::new_tracker(rewrites);    let odb = util::add_retained_blobs(        &mut track,        [            (Change::modification(), "a", "a\n"),            (Change::addition(), "a-cpy-1", "a"),            (Change::addition(), "a-cpy-2", "a"),            (Change::modification(), "d", "ab"),        ],    )?;     let mut calls = 0;    let out = util::assert_emit_with_objects(        &mut track,        |dst, src| {            assert!(src.is_none());            match calls {                0 => assert_eq!(dst.location, "a"),                1 => assert_eq!(dst.location, "a-cpy-1"),                2 => assert_eq!(dst.location, "a-cpy-2"),                3 => assert_eq!(dst.location, "d"),                _ => panic!("too many emissions"),            }            calls += 1;            std::ops::ControlFlow::Continue(())        },        odb,    );    assert_eq!(        out,        rewrites::Outcome {            options: rewrites,            num_similarity_checks_skipped_for_copy_tracking_due_to_limit: 4,            ..Default::default()        },        "no similarity check was performed at all - all or nothing"    );    Ok(())} #[test]fn copy_by_id() -> crate::Result {    // Limits are only applied when doing rewrite-checks    for limit in [0, 1] {        let rewrites = Rewrites {            copies: Some(Copies {                source: CopySource::FromSetOfModifiedFiles,                percentage: None,            }),            percentage: None,            limit,            track_empty: false,        };        let mut track = util::new_tracker(rewrites);        let odb = util::add_retained_blobs(            &mut track,            [                (Change::modification(), "a", "a"),                (Change::addition(), "a-cpy-1", "a"),                (Change::addition(), "a-cpy-2", "a"),                (Change::modification(), "d", "a"),            ],        )?;         let mut calls = 0;        let out = util::assert_emit_with_objects(            &mut track,            |dst, src| {                let id = hex_to_id(                    "2e65efe2a145dda7ee51d1741299f848e5bf752e",                    "eb337bcee2061c5313c9a1392116b6c76039e9e30d71467ae359b36277e17dc7",                );                let source_a = Source {                    entry_mode: EntryKind::Blob.into(),                    id,                    kind: SourceKind::Copy,                    location: "a".into(),                    change: &Change {                        id,                        ..Change::modification()                    },                    diff: None,                };                match calls {                    0 => {                        assert_eq!(src.unwrap(), source_a);                        assert_eq!(                            dst.location, "a-cpy-1",                            "it just finds the first possible match in order, ignoring other candidates"                        );                    }                    1 => {                        assert_eq!(src.unwrap(), source_a, "copy-sources can be used multiple times");                        assert_eq!(dst.location, "a-cpy-2");                    }                    2 => {                        assert!(src.is_none());                        assert_eq!(dst.location, "d");                    }                    _ => panic!("too many emissions"),                }                calls += 1;                std::ops::ControlFlow::Continue(())            },            odb,        );        assert_eq!(            out,            rewrites::Outcome {                options: rewrites,                ..Default::default()            },            "no similarity check was performed, it was all matched by id"        );    }    Ok(())} #[test]fn copy_by_id_search_in_all_sources() -> crate::Result {    // Limits are only applied when doing rewrite-checks    for limit in [0, 1] {        let rewrites = Rewrites {            copies: Some(Copies {                source: CopySource::FromSetOfModifiedFilesAndAllSources,                percentage: None,            }),            percentage: None,            limit,            track_empty: false,        };        let mut track = util::new_tracker(rewrites);        let odb = util::add_retained_blobs(            &mut track,            [                (Change::addition(), "a-cpy-1", "a"),                (Change::addition(), "a-cpy-2", "a"),            ],        )?;         let content_id = hex_to_id(            "2e65efe2a145dda7ee51d1741299f848e5bf752e",            "eb337bcee2061c5313c9a1392116b6c76039e9e30d71467ae359b36277e17dc7",        );         let mut calls = 0;        let out = util::assert_emit_with_objects_and_sources(            &mut track,            |dst, src| {                let source_a = Source {                    entry_mode: EntryKind::Blob.into(),                    id: content_id,                    kind: SourceKind::Copy,                    location: "a-src".into(),                    change: &Change {                        id: content_id,                        ..Change::modification()                    },                    diff: None,                };                match calls {                    0 => {                        assert_eq!(src.unwrap(), source_a);                        assert_eq!(                            dst.location, "a-cpy-1",                            "it just finds the first possible match in order, ignoring other candidates"                        );                    }                    1 => {                        assert_eq!(src.unwrap(), source_a, "copy-sources can be used multiple times");                        assert_eq!(dst.location, "a-cpy-2");                    }                    2 => {                        assert!(src.is_none());                        assert_eq!(dst.location, "d");                    }                    _ => panic!("too many emissions"),                }                calls += 1;                std::ops::ControlFlow::Continue(())            },            odb,            [(                {                    let mut c = Change::modification();                    c.id = content_id;                    c                },                "a-src",            )],        );        assert_eq!(            out,            rewrites::Outcome {                options: rewrites,                ..Default::default()            },            "no similarity check was performed, it was all matched by id"        );    }    Ok(())} #[test]fn copy_by_50_percent_similarity() -> crate::Result {    let rewrites = Rewrites {        copies: Some(Copies {            source: CopySource::FromSetOfModifiedFiles,            percentage: Some(0.5),        }),        percentage: None,        limit: 0,        track_empty: false,    };    let mut track = util::new_tracker(rewrites);    let odb = util::add_retained_blobs(        &mut track,        [            (Change::modification(), "a", "a\n"),            (Change::addition(), "a-cpy-1", "a\nb"),            (Change::addition(), "a-cpy-2", "a\nc"),            (Change::modification(), "d", "a"),        ],    )?;     let mut calls = 0;    let out = util::assert_emit_with_objects(        &mut track,        |dst, src| {            let id = hex_to_id(                "78981922613b2afb6025042ff6bd878ac1994e85",                "f8625e43f9e04f24291f77cdbe4c71b3c2a3b0003f60419b3ed06a058d766c8b",            );            let source_a = Source {                entry_mode: EntryKind::Blob.into(),                id,                kind: SourceKind::Copy,                location: "a".into(),                change: &Change {                    id,                    ..Change::modification()                },                diff: Some(DiffLineStats {                    removals: 0,                    insertions: 1,                    before: 1,                    after: 2,                    similarity: 0.6666667,                }),            };            match calls {                0 => {                    assert_eq!(                        src.unwrap(),                        source_a,                        "it finds the first possible source, no candidates"                    );                    assert_eq!(dst.location, "a-cpy-1");                }                1 => {                    assert_eq!(src.unwrap(), source_a, "the same source can be reused as well");                    assert_eq!(dst.location, "a-cpy-2");                }                2 => {                    assert!(src.is_none());                    assert_eq!(dst.location, "d");                }                _ => panic!("too many emissions"),            }            calls += 1;            std::ops::ControlFlow::Continue(())        },        odb,    );    assert_eq!(        out,        rewrites::Outcome {            options: rewrites,            num_similarity_checks: 4,            ..Default::default()        },        "no similarity check was performed, it was all matched by id"    );    Ok(())} #[test]fn copy_by_id_in_additions_only() -> crate::Result {    let rewrites = Rewrites {        copies: Some(Copies {            source: CopySource::FromSetOfModifiedFiles,            percentage: None,        }),        percentage: None,        limit: 0,        track_empty: false,    };    let mut track = util::new_tracker(rewrites);    let odb = util::add_retained_blobs(        &mut track,        [            (Change::modification(), "a", "a"),            (Change::modification(), "a-cpy-1", "a"),        ],    )?;     let mut calls = 0;    let out = util::assert_emit_with_objects(        &mut track,        |dst, src| {            match calls {                0 => {                    assert!(src.is_none());                    assert_eq!(dst.location, "a");                }                1 => {                    assert!(src.is_none());                    assert_eq!(                        dst.location, "a-cpy-1",                        "copy detection is only done for additions, not within modifications"                    );                }                _ => panic!("too many emissions"),            }            calls += 1;            std::ops::ControlFlow::Continue(())        },        odb,    );    assert_eq!(        out,        rewrites::Outcome {            options: rewrites,            ..Default::default()        },        "no similarity check was performed, it was all matched by id"    );    Ok(())} #[test]fn rename_by_similarity_reports_limit_if_encountered() -> crate::Result {    let rewrites = Rewrites {        copies: None,        percentage: Some(0.5),        limit: 1,        track_empty: false,    };    let mut track = util::new_tracker(rewrites);    let odb = util::add_retained_blobs(        &mut track,        [            (Change::deletion(), "a", "first\nsecond\n"),            (Change::addition(), "b", "firt\nsecond\n"),            (Change::addition(), "c", "second\nunrelated\n"),        ],    )?; 

Lines 1–500 of 1261.