@@ -16,7 +16,7 @@ use solana_sdk::{
1616use std:: {
1717 io:: Read ,
1818 path:: PathBuf ,
19- process:: { exit, Stdio } ,
19+ process:: { exit, Command , Stdio } ,
2020 sync:: {
2121 atomic:: { AtomicBool , Ordering } ,
2222 Arc ,
@@ -154,7 +154,7 @@ async fn main() -> anyhow::Result<()> {
154154 . arg ( Arg :: with_name ( "commit-hash" )
155155 . long ( "commit-hash" )
156156 . takes_value ( true )
157- . help ( "Optional commit hash to checkout" ) )
157+ . help ( "Commit hash to checkout. Required to know the correct program snapshot. Will fallback to HEAD if not provided " ) )
158158 . arg ( Arg :: with_name ( "program-id" )
159159 . long ( "program-id" )
160160 . required ( true )
@@ -279,7 +279,6 @@ async fn main() -> anyhow::Result<()> {
279279 let remote = sub_m. is_present ( "remote" ) ;
280280 let mount_path = sub_m. value_of ( "mount-path" ) . map ( |s| s. to_string ( ) ) . unwrap ( ) ;
281281 let repo_url = sub_m. value_of ( "repo-url" ) . map ( |s| s. to_string ( ) ) . unwrap ( ) ;
282- let commit_hash = sub_m. value_of ( "commit-hash" ) . map ( |s| s. to_string ( ) ) ;
283282 let program_id = sub_m. value_of ( "program-id" ) . unwrap ( ) ;
284283 let base_image = sub_m. value_of ( "base-image" ) . map ( |s| s. to_string ( ) ) ;
285284 let library_name = sub_m. value_of ( "library-name" ) . map ( |s| s. to_string ( ) ) ;
@@ -293,13 +292,27 @@ async fn main() -> anyhow::Result<()> {
293292 . map ( |s| s. to_string ( ) )
294293 . collect ( ) ;
295294
296- println ! ( " Skipping prompt: {}" , skip_prompt) ;
295+ let commit_hash = sub_m
296+ . value_of ( "commit-hash" )
297+ . map ( String :: from)
298+ . or_else ( || {
299+ get_commit_hash_from_remote ( & repo_url) . ok ( ) // Dynamically determine commit hash from remote
300+ } )
301+ . ok_or_else ( || {
302+ anyhow:: anyhow!(
303+ "Commit hash must be provided or inferred from the remote repository"
304+ )
305+ } ) ?;
306+
307+ println ! ( "Commit hash from remote: {}" , commit_hash) ;
308+
309+ println ! ( "Skipping prompt: {}" , skip_prompt) ;
297310 verify_from_repo (
298311 remote,
299312 mount_path,
300313 & connection,
301314 repo_url,
302- commit_hash,
315+ Some ( commit_hash) ,
303316 Pubkey :: try_from ( program_id) ?,
304317 base_image,
305318 library_name,
@@ -375,6 +388,70 @@ pub fn get_client(url: Option<String>) -> RpcClient {
375388 RpcClient :: new ( url)
376389}
377390
391+ fn get_commit_hash_from_remote ( repo_url : & str ) -> anyhow:: Result < String > {
392+ // Fetch the symbolic reference of the default branch
393+ let output = Command :: new ( "git" )
394+ . arg ( "ls-remote" )
395+ . arg ( "--symref" )
396+ . arg ( repo_url)
397+ . output ( )
398+ . map_err ( |e| anyhow:: anyhow!( "Failed to run git ls-remote: {}" , e) ) ?;
399+
400+ if !output. status . success ( ) {
401+ return Err ( anyhow:: anyhow!(
402+ "Failed to fetch default branch information: {}" ,
403+ String :: from_utf8_lossy( & output. stderr)
404+ ) ) ;
405+ }
406+
407+ // Find out if the branch is called master or main
408+ let output_str = String :: from_utf8 ( output. stdout ) ?;
409+ let default_branch = output_str
410+ . lines ( )
411+ . find_map ( |line| {
412+ if line. starts_with ( "ref: refs/heads/" ) {
413+ Some (
414+ line. trim_start_matches ( "ref: refs/heads/" )
415+ . split_whitespace ( )
416+ . next ( ) ?
417+ . to_string ( ) ,
418+ )
419+ } else {
420+ None
421+ }
422+ } )
423+ . ok_or_else ( || {
424+ anyhow:: anyhow!(
425+ "Unable to determine default branch from remote repository '{}'" ,
426+ repo_url
427+ )
428+ } ) ?;
429+
430+ println ! ( "Default branch detected: {}" , default_branch) ;
431+
432+ // Fetch the latest commit hash for the default branch
433+ let hash_output = Command :: new ( "git" )
434+ . arg ( "ls-remote" )
435+ . arg ( repo_url)
436+ . arg ( & default_branch)
437+ . output ( )
438+ . map_err ( |e| anyhow:: anyhow!( "Failed to fetch commit hash for default branch: {}" , e) ) ?;
439+
440+ if !hash_output. status . success ( ) {
441+ return Err ( anyhow:: anyhow!(
442+ "Failed to fetch commit hash: {}" ,
443+ String :: from_utf8_lossy( & hash_output. stderr)
444+ ) ) ;
445+ }
446+
447+ // Parse and return the commit hash
448+ String :: from_utf8 ( hash_output. stdout ) ?
449+ . split_whitespace ( )
450+ . next ( )
451+ . map ( |s| s. to_string ( ) )
452+ . ok_or_else ( || anyhow:: anyhow!( "Failed to parse commit hash from git ls-remote output" ) )
453+ }
454+
378455pub fn get_binary_hash ( program_data : Vec < u8 > ) -> String {
379456 let buffer = program_data
380457 . into_iter ( )
0 commit comments