340 lines · 12.2 KB · Rust
RawDownload
mod reflog {    mod packed {        use gix_ref::file::ReferenceExt;         use crate::file;         #[test]        fn iter() -> crate::Result {            let store = file::store_with_packed_refs()?;            let r = store.find("main")?;            assert_eq!(r.log_iter(&store).all()?.expect("log exists").count(), 1);            assert!(r.log_exists(&store), "it exists if its readable");            Ok(())        }         #[test]        fn iter_rev() -> crate::Result {            let store = file::store_with_packed_refs()?;            let r = store.find("main")?;            assert_eq!(r.log_iter(&store).rev()?.expect("log exists").count(), 1);            Ok(())        }    }     mod loose {        use crate::file;         #[test]        fn iter() -> crate::Result {            let store = file::store()?;            let r = store.find_loose("HEAD")?;            let mut buf = Vec::new();            assert_eq!(r.log_iter(&store, &mut buf)?.expect("log exists").count(), 1);            assert!(r.log_exists(&store), "it exists if its readable");            Ok(())        }         #[test]        fn iter_rev() -> crate::Result {            let store = file::store()?;            let r = store.find_loose("HEAD")?;            let mut buf = [0u8; 256];            assert_eq!(r.log_iter_rev(&store, &mut buf)?.expect("log exists").count(), 1);            Ok(())        }    }} mod peel {    use gix_object::FindExt;    use gix_ref::{Reference, file::ReferenceExt};     use crate::{        file,        file::{EmptyCommit, store_with_packed_refs},        hex_to_id,    };     #[test]    fn one_level() -> crate::Result {        let store = file::store()?;        let r = store.find_loose("HEAD")?;        assert_eq!(r.kind(), gix_ref::Kind::Symbolic, "there is something to peel");         let nr = Reference::from(r).follow(&store).expect("exists").expect("no failure");        assert!(            matches!(nr.target.to_ref(), gix_ref::TargetRef::Object(_)),            "iteration peels a single level"        );        assert!(nr.follow(&store).is_none(), "end of iteration");        assert_eq!(            nr.target.to_ref(),            gix_ref::TargetRef::Object(&hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03")),            "we still have the peeled target"        );        Ok(())    }     #[test]    fn peel_with_packed_involvement() -> crate::Result {        let store = store_with_packed_refs()?;        let mut head: Reference = store.find_loose("HEAD")?.into();        let expected = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");        assert_eq!(head.peel_to_id(&store, &EmptyCommit)?, expected);        assert_eq!(head.target.try_id().map(ToOwned::to_owned), Some(expected));         let mut head = store.find("dt1")?;        assert_eq!(head.peel_to_id(&store, &gix_object::find::Never)?, expected);        assert_eq!(head.target.into_id(), expected);        Ok(())    }     #[test]    fn peel_one_level_with_pack() -> crate::Result {        let store = store_with_packed_refs()?;         let mut head = store.find("dt1")?;        assert_eq!(            head.target.try_id().map(ToOwned::to_owned),            Some(hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3"))        );        assert_eq!(            head.kind(),            gix_ref::Kind::Object,            "its peeled, but does have another step to peel to…"        );        let final_stop = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");        assert_eq!(head.peeled, Some(final_stop), "…it knows its peeled object");         assert_eq!(            head.follow(&store).transpose()?,            None,            "but following doesn't do that, only real peeling does"        );         head.peel_to_id(&store, &EmptyCommit)?;        assert_eq!(            head.target.try_id().map(ToOwned::to_owned),            Some(final_stop),            "packed refs are always peeled (at least the ones we choose to read)"        );        assert_eq!(head.kind(), gix_ref::Kind::Object, "it's terminally peeled now");        assert_eq!(            head.follow(&store).transpose()?,            None,            "following doesn't change anything"        );        Ok(())    }     #[test]    fn to_id_multi_hop() -> crate::Result {        let store = file::store()?;        let mut r: Reference = store.find_loose("multi-link")?.into();        assert_eq!(r.kind(), gix_ref::Kind::Symbolic, "there is something to peel");         let commit = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");        assert_eq!(r.peel_to_id(&store, &EmptyCommit)?, commit);        assert_eq!(r.name.as_bstr(), "refs/remotes/origin/multi-link-target3");         let mut r: Reference = store.find_loose("dt1")?.into();        assert_eq!(            r.peel_to_id(&store, &EmptyCommit)?,            hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3"),            "points to a tag object without actual object lookup"        );         let odb = crate::file::odb_at(store.git_dir().join("objects"))?;        let mut r: Reference = store.find_loose("dt1")?.into();        assert_eq!(r.peel_to_id(&store, &odb)?, commit, "points to the commit with lookup");         Ok(())    }     #[test]    fn to_id_long_jump() -> crate::Result {        for packed in [None, Some("packed")] {            let store = file::store_at_with_args("make_multi_hop_ref.sh", packed)?;            let odb = crate::file::odb_at(store.git_dir().join("objects"))?;            let mut r: Reference = store.find("multi-hop")?;            r.peel_to_id(&store, &odb)?;             let commit_id = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");            assert_eq!(r.peeled, Some(commit_id));             let mut buf = Vec::new();            let obj = odb.find(&commit_id, &mut buf)?;            assert_eq!(obj.kind, gix_object::Kind::Commit, "always peeled to the first non-tag");             let mut r: Reference = store.find("multi-hop")?;            let tag_id = r.follow_to_object_packed(&store, store.cached_packed_buffer()?.as_ref().map(|p| &***p))?;            let obj = odb.find(&tag_id, &mut buf)?;            assert_eq!(obj.kind, gix_object::Kind::Tag, "the first direct object target");            assert_eq!(                obj.decode()?.into_tag().expect("tag").name,                "dt2",                "this is the first annotated tag, which points at dt1"            );            let mut r: Reference = store.find("multi-hop2")?;            let other_tag_id =                r.follow_to_object_packed(&store, store.cached_packed_buffer()?.as_ref().map(|p| &***p))?;            assert_eq!(other_tag_id, tag_id, "it can follow with multiple hops as well");        }        Ok(())    }     #[test]    fn to_id_cycle() -> crate::Result {        let store = file::store()?;        let mut r: Reference = store.find_loose("loop-a")?.into();        assert_eq!(r.kind(), gix_ref::Kind::Symbolic, "there is something to peel");        assert_eq!(r.name.as_bstr(), "refs/loop-a");         assert!(matches!(            r.peel_to_id(&store, &gix_object::find::Never).unwrap_err(),            gix_ref::peel::to_id::Error::FollowToObject(gix_ref::peel::to_object::Error::Cycle { .. })        ));        assert_eq!(r.name.as_bstr(), "refs/loop-a", "the ref is not changed on error");         let mut r: Reference = store.find_loose("loop-a")?.into();        let err = r            .follow_to_object_packed(&store, store.cached_packed_buffer()?.as_ref().map(|p| &***p))            .unwrap_err();        assert!(matches!(err, gix_ref::peel::to_object::Error::Cycle { .. }));        Ok(())    }} mod parse {    mod invalid {        use gix_ref::file::loose::Reference;         macro_rules! mktest {            ($name:ident, $input:literal, $err:literal) => {                #[test]                fn $name() {                    use std::convert::TryInto;                    let err = Reference::try_from_path(                        "HEAD".try_into().expect("this is a valid name"),                        $input,                        gix_hash::Kind::Sha1,                    )                    .unwrap_err();                    assert_eq!(err.to_string(), $err);                }            };        }         mktest!(hex_id, b"foobar", "\"foobar\" could not be parsed");        mktest!(ref_tag, b"reff: hello", "\"reff: hello\" could not be parsed");        mktest!(            sha256_sized_id_for_sha1,            b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n",            "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\n\" could not be parsed"        );        mktest!(            trailing_garbage_after_id,            b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaextra",            "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaextra\" could not be parsed"        );    }    mod valid {        use gix_object::bstr::ByteSlice;        use gix_ref::file::loose::Reference;         use crate::sha1_hex_to_id;         macro_rules! mktest {            ($name:ident, $input:literal, $kind:path, $id:expr, $ref:expr) => {                #[test]                fn $name() {                    use std::convert::TryInto;                    let reference = Reference::try_from_path(                        "HEAD".try_into().expect("valid static name"),                        $input,                        gix_hash::Kind::Sha1,                    )                    .unwrap();                    assert_eq!(reference.kind(), $kind);                    assert_eq!(reference.target.to_ref().try_id(), $id);                    assert_eq!(                        reference.target.to_ref().try_name().map(|n| n.as_bstr()),                        $ref                    );                }            };        }         mktest!(            peeled,            b"c5241b835b93af497cda80ce0dceb8f49800df1c\n",            gix_ref::Kind::Object,            Some(sha1_hex_to_id("c5241b835b93af497cda80ce0dceb8f49800df1c").as_ref()),            None        );         mktest!(            peeled_uppercase,            b"C5241B835B93AF497CDA80CE0DCEB8F49800DF1C\n",            gix_ref::Kind::Object,            Some(sha1_hex_to_id("c5241b835b93af497cda80ce0dceb8f49800df1c").as_ref()),            None        );         mktest!(            symbolic,            b"ref: refs/heads/main\n",            gix_ref::Kind::Symbolic,            None,            Some(b"refs/heads/main".as_bstr())        );         mktest!(            symbolic_more_than_one_space,            b"ref:        refs/foobar\n",            gix_ref::Kind::Symbolic,            None,            Some(b"refs/foobar".as_bstr())        );         #[test]        fn symbolic_ignores_nul_suffix_like_git() {            use std::convert::TryInto;             let reference = Reference::try_from_path(                "HEAD".try_into().expect("valid static name"),                b"ref: refs/heads/main\0hidden-head-metadata",                gix_hash::Kind::Sha1,            )            .expect("Git ignores bytes past the first NUL in symbolic ref files, so this parses as well");            assert_eq!(                reference.kind(),                gix_ref::Kind::Symbolic,                "the ref is still symbolic despite ignored trailing metadata"            );            assert_eq!(                reference.target.to_ref().try_name().map(gix_ref::FullNameRef::as_bstr),                Some(b"refs/heads/main".as_bstr()),                "only the target before the first NUL is used"            );        }         #[test]        fn peeled_sha256() {            use std::convert::TryInto;             let input = &b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"[..];            let reference = Reference::try_from_path(                "HEAD".try_into().expect("valid static name"),                input,                gix_hash::Kind::Sha256,            )            .unwrap();            assert_eq!(reference.kind(), gix_ref::Kind::Object);            let target_id = reference.target.to_ref().try_id().expect("non-symbolic").to_owned();            assert_eq!(target_id.kind(), gix_hash::Kind::Sha256);            assert_eq!(target_id, gix_hash::ObjectId::from_hex(input).unwrap());        }    }}