don't
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(knot): align `sh.tangled.repo.tag` impl with upstream

Signed-off-by: tjh <x@tjh.dev>

tjh 8be780c7 d91c60de

+88 -14
+32 -7
crates/gordian-knot/src/model/convert.rs
··· 2 2 use std::collections::HashMap; 3 3 4 4 use data_encoding::BASE64URL; 5 + use gix::bstr::BStr; 5 6 use gix::bstr::ByteSlice; 6 7 use gordian_lexicon::sh_tangled::repo::refs; 7 8 use gordian_lexicon::sh_tangled::repo::tree; ··· 123 122 let hash = value.id.into(); 124 123 let decoded = value.decode()?; 125 124 126 - // cf. <https://github.com/git/git/blob/7014b55638da979331baf8dc31c4e1d697cf2d67/object.h#L97> 125 + // https://github.com/git/git/blob/7014b55638da979331baf8dc31c4e1d697cf2d67/object.h#L97 127 126 let target_type = match decoded.target_kind { 128 - Kind::Commit => 1, 127 + // Kind::Commit => 1, 128 + Kind::Commit => 4, 129 129 Kind::Tree => 2, 130 130 Kind::Blob => 3, 131 131 Kind::Tag => 4, 132 132 }; 133 + 134 + let message = BStr::new(decoded.message.trim_ascii()).to_string(); 133 135 134 136 Ok(TagAnnotation { 135 137 hash, ··· 140 136 tagger: decoded 141 137 .tagger()? 142 138 .and_then(|tagger| try_convert_signature(tagger).ok()), 143 - message: decoded.message.to_string(), 144 - pgp_signature: decoded.pgp_signature.map(ToString::to_string), 139 + message, 140 + pgp_signature: decoded 141 + .pgp_signature 142 + .map(ToString::to_string) 143 + .unwrap_or_default(), 145 144 target_type, 146 145 target: decoded.target().into(), 147 146 }) ··· 155 148 type Error = gix::objs::decode::Error; 156 149 157 150 fn try_from(mut value: gix::Reference<'_>) -> Result<Self, Self::Error> { 158 - let r#ref: refs::Reference = convert_reference(&value); 151 + let reference: refs::Reference = convert_reference(&value); 159 152 let annotation = value 160 153 .peel_to_tag() 161 154 .ok() 162 - .map(TryFrom::try_from) 155 + .map(TagAnnotation::try_from) 163 156 .transpose()?; 164 157 165 - Ok(Tag { r#ref, annotation }) 158 + let message = match &annotation { 159 + Some(annotation) => Some(annotation.message.to_string()), 160 + None => value 161 + .repo 162 + .find_commit(reference.hash.clone()) 163 + .ok() 164 + .and_then(|commit| { 165 + commit 166 + .message_raw() 167 + .map(|message| BStr::new(message.trim_ascii()).to_string()) 168 + .ok() 169 + }), 170 + }; 171 + 172 + Ok(Tag { 173 + reference, 174 + message: message.unwrap_or_default(), 175 + annotation, 176 + }) 166 177 } 167 178 }
+53 -5
crates/gordian-knot/src/public/xrpc/sh_tangled/repo/tag.rs
··· 30 30 ) -> XrpcResult<Json<Output>> { 31 31 tokio_rayon::spawn(move || { 32 32 let repository = repository.to_thread_local(); 33 - let reference = repository 34 - .find_reference(&format!("refs/tags/{tag}")) 35 - .map_err(TagNotFound)?; 33 + let reference = format!("refs/tags/{}", tag.trim_start_matches("refs/tags/")); 34 + let reference = repository.find_reference(&reference).map_err(TagNotFound)?; 36 35 let tag = reference.try_into()?; 37 36 Ok(Json(Output { tag }).into()) 38 37 }) ··· 60 61 .with_state(TestState::default()) 61 62 } 62 63 64 + // Response from: 65 + // https://knot1.tangled.sh/xrpc/sh.tangled.repo.tag?repo=did:plc:wshs7t2adsemcrrd4snkeqli/core&tag=v1.12.0-alpha 63 66 const V1_12_0_ALPHA: &str = r#"{"tag":{"name":"v1.12.0-alpha","hash":"efd0b8592e77867d014b41853729faa0e054e050","tag":{"Hash":[239,208,184,89,46,119,134,125,1,75,65,133,55,41,250,160,224,84,224,80],"Name":"v1.12.0-alpha","Tagger":{"Name":"Akshay","Email":"nerdy@peppe.rs","When":"2026-03-02T09:30:08Z"},"Message":"v1.12.0-alpha\n\n* fix minor patch application discrepancy between merge-check and merge\n* update blob and tree endpoints to include last-commit info\n* add pagination to tags and branches endpoints\n-----BEGIN SSH SIGNATURE-----\nU1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgyPUOf1i4WjYE2v33fKYFrqfPLI\ngoBREioxtS18jz7hcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5\nAAAAQIR2kUMXdS3xbwAuPNx8PTcWVfBGUqNHErS5oKhY//OINmKTpVd6JYmNhDUNWJWmfG\norMQIL40Lj2lLHhKD8OAQ=\n-----END SSH SIGNATURE-----","PGPSignature":"","TargetType":4,"Target":[143,126,97,191,81,55,60,65,124,111,152,51,159,76,123,236,181,96,210,153]},"message":"v1.12.0-alpha\n\n* fix minor patch application discrepancy between merge-check and merge\n* update blob and tree endpoints to include last-commit info\n* add pagination to tags and branches endpoints\n-----BEGIN SSH SIGNATURE-----\nU1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgyPUOf1i4WjYE2v33fKYFrqfPLI\ngoBREioxtS18jz7hcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5\nAAAAQIR2kUMXdS3xbwAuPNx8PTcWVfBGUqNHErS5oKhY//OINmKTpVd6JYmNhDUNWJWmfG\norMQIL40Lj2lLHhKD8OAQ=\n-----END SSH SIGNATURE-----"}}"#; 64 67 68 + // Response from: 69 + // https://knot1.tangled.sh/xrpc/sh.tangled.repo.tag?repo=did:plc:wshs7t2adsemcrrd4snkeqli/core&tag=v1.0.0-alpha 70 + const V1_0_0_ALPHA: &str = r#"{"tag":{"name":"v1.0.0-alpha","hash":"b322b595e7313382c6a61a84a9373a5442390ff9","message":"add chi router for handling delete requests\n\nadds the delete handle for delete a specified ssh key."}}"#; 71 + 65 72 #[tokio::test] 66 - async fn can_get_tag_with_short_name() { 73 + async fn can_fetch_annotated_tag_with_short_name() { 67 74 let client = Client::new(app()); 68 75 let output: Output = client 69 76 .get( ··· 85 80 } 86 81 87 82 #[tokio::test] 88 - async fn can_get_tag_with_full_name() { 83 + async fn can_fetch_simple_tag_with_short_name() { 84 + let client = Client::new(app()); 85 + let output: Output = client 86 + .get("/sh.tangled.repo.tag?repo=did:plc:65gha4t3avpfpzmvpbwovss7/core&tag=v1.0.0-alpha") 87 + .await 88 + .ok() 89 + .json() 90 + .await; 91 + 92 + let expected: Output = serde_json::from_str(V1_0_0_ALPHA).unwrap(); 93 + assert_eq!(output, expected); 94 + } 95 + 96 + #[tokio::test] 97 + async fn can_fetch_annotated_tag_with_full_name() { 89 98 let client = Client::new(app()); 90 99 let output: Output = client 91 100 .get( ··· 115 96 } 116 97 117 98 #[tokio::test] 99 + async fn can_fetch_simple_tag_with_full_name() { 100 + let client = Client::new(app()); 101 + let output: Output = client 102 + .get( 103 + "/sh.tangled.repo.tag?repo=did:plc:65gha4t3avpfpzmvpbwovss7/core&tag=refs/tags/v1.0.0-alpha", 104 + ) 105 + .await 106 + .ok() 107 + .json() 108 + .await; 109 + 110 + let expected: Output = serde_json::from_str(V1_0_0_ALPHA).unwrap(); 111 + assert_eq!(output, expected); 112 + } 113 + 114 + #[tokio::test] 118 115 async fn deny_unknown_tag_with_tag_not_found() { 119 116 let client = Client::new(app()); 120 117 let XrpcError { error, .. } = client 121 118 .get( 122 119 "/sh.tangled.repo.tag?repo=did:plc:65gha4t3avpfpzmvpbwovss7/core&tag=hopefully_this_tag_does_not_exist", 123 120 ) 121 + .await 122 + .not_found() 123 + .json() 124 + .await; 125 + 126 + assert_eq!(error, "TagNotFound"); 127 + } 128 + 129 + #[tokio::test] 130 + async fn deny_branch_as_tag_not_found() { 131 + let client = Client::new(app()); 132 + let XrpcError { error, .. } = client 133 + .get("/sh.tangled.repo.tag?repo=did:plc:65gha4t3avpfpzmvpbwovss7/core&tag=master") 124 134 .await 125 135 .not_found() 126 136 .json()
+3 -2
crates/gordian-knot/src/public/xrpc/sh_tangled/repo/tags.rs
··· 31 31 pub tagger: Option<Signature>, 32 32 pub message: String, 33 33 #[serde(rename = "PGPSignature")] 34 - pub pgp_signature: Option<String>, 34 + pub pgp_signature: String, 35 35 pub target_type: i32, 36 36 pub target: ObjectId<Array>, 37 37 } ··· 40 40 #[serde(deny_unknown_fields)] 41 41 pub struct Tag { 42 42 #[serde(flatten)] 43 - pub r#ref: Reference, 43 + pub reference: Reference, 44 + pub message: String, 44 45 #[serde(rename = "tag", skip_serializing_if = "Option::is_none")] 45 46 pub annotation: Option<TagAnnotation>, 46 47 }