1+ use crate :: hasher:: registry:: HasherFn ;
12use crate :: repository:: github:: models:: { Asset , Release } ;
23use crate :: repository:: model:: Repository ;
34use crate :: repository:: Archive ;
45use crate :: Error :: {
56 ArchiveHashMismatch , AssetHashNotFound , AssetNotFound , RepositoryFailure , VersionNotFound ,
67} ;
7- use crate :: { matcher, Result } ;
8+ use crate :: { hasher , matcher, Result } ;
89use async_trait:: async_trait;
910use bytes:: Bytes ;
1011use http:: { header, Extensions } ;
@@ -16,7 +17,6 @@ use reqwest_retry::policies::ExponentialBackoff;
1617use reqwest_retry:: RetryTransientMiddleware ;
1718use reqwest_tracing:: TracingMiddleware ;
1819use semver:: { Version , VersionReq } ;
19- use sha2:: { Digest , Sha256 } ;
2020use std:: env;
2121use std:: str:: FromStr ;
2222use tracing:: { debug, instrument, warn} ;
@@ -26,7 +26,7 @@ const GITHUB_API_VERSION_HEADER: &str = "X-GitHub-Api-Version";
2626const GITHUB_API_VERSION : & str = "2022-11-28" ;
2727
2828lazy_static ! {
29- static ref GITHUB_TOKEN : Option <String > = match std :: env:: var( "GITHUB_TOKEN" ) {
29+ static ref GITHUB_TOKEN : Option <String > = match env:: var( "GITHUB_TOKEN" ) {
3030 Ok ( token) => {
3131 debug!( "GITHUB_TOKEN environment variable found" ) ;
3232 Some ( token)
@@ -200,7 +200,11 @@ impl GitHub {
200200 /// # Errors
201201 /// * If the asset is not found.
202202 #[ instrument( level = "debug" , skip( version, release) ) ]
203- fn get_asset ( & self , version : & Version , release : & Release ) -> Result < ( Asset , Option < Asset > ) > {
203+ fn get_asset (
204+ & self ,
205+ version : & Version ,
206+ release : & Release ,
207+ ) -> Result < ( Asset , Option < Asset > , Option < HasherFn > ) > {
204208 let matcher = matcher:: registry:: get ( & self . url ) ;
205209 let mut release_asset: Option < Asset > = None ;
206210 for asset in & release. assets {
@@ -214,16 +218,26 @@ impl GitHub {
214218 return Err ( AssetNotFound ) ;
215219 } ;
216220
221+ // Attempt to find the asset hash for the asset.
217222 let mut asset_hash: Option < Asset > = None ;
218- let hash_name = format ! ( "{}.sha256" , asset . name ) ;
223+ let mut asset_hasher_fn : Option < HasherFn > = None ;
219224 for release_asset in & release. assets {
220- if release_asset. name == hash_name {
225+ let release_asset_name = release_asset. name . as_str ( ) ;
226+ if !release_asset_name. starts_with ( & asset. name ) {
227+ continue ;
228+ }
229+ let extension = release_asset_name
230+ . strip_prefix ( format ! ( "{}." , asset. name. as_str( ) ) . as_str ( ) )
231+ . unwrap_or_default ( ) ;
232+
233+ if let Some ( hasher_fn) = hasher:: registry:: get ( extension) {
221234 asset_hash = Some ( release_asset. clone ( ) ) ;
235+ asset_hasher_fn = Some ( hasher_fn) ;
222236 break ;
223237 }
224238 }
225239
226- Ok ( ( asset, asset_hash) )
240+ Ok ( ( asset, asset_hash, asset_hasher_fn ) )
227241 }
228242}
229243
@@ -246,7 +260,7 @@ impl Repository for GitHub {
246260 async fn get_archive ( & self , version_req : & VersionReq ) -> Result < Archive > {
247261 let release = self . get_release ( version_req) . await ?;
248262 let version = Self :: get_version_from_tag_name ( release. tag_name . as_str ( ) ) ?;
249- let ( asset, asset_hash) = self . get_asset ( & version, & release) ?;
263+ let ( asset, asset_hash, asset_hasher_fn ) = self . get_asset ( & version, & release) ?;
250264 let name = asset. name . clone ( ) ;
251265
252266 let client = reqwest_client ( ) ;
@@ -280,9 +294,10 @@ impl Repository for GitHub {
280294 human_bytes( text. len( ) as f64 )
281295 ) ;
282296
283- let mut hasher = Sha256 :: new ( ) ;
284- hasher. update ( & archive) ;
285- let archive_hash = hex:: encode ( hasher. finalize ( ) ) ;
297+ let archive_hash = match asset_hasher_fn {
298+ Some ( hasher_fn) => hasher_fn ( & bytes) ?,
299+ None => String :: new ( ) ,
300+ } ;
286301
287302 if archive_hash != hash {
288303 return Err ( ArchiveHashMismatch { archive_hash, hash } ) ;
0 commit comments