@@ -443,4 +443,107 @@ mod tests {
443443
444444 assert_eq ! ( msg, String :: from( "msg\n " ) ) ;
445445 }
446+
447+ #[ test]
448+ fn test_pre_push_hook_receives_correct_stdin ( ) {
449+ let ( _td, repo) = repo_init ( ) . unwrap ( ) ;
450+
451+ // Create a pre-push hook that captures and validates stdin
452+ let hook = b"#!/bin/sh
453+ # Validate we receive correct format
454+ stdin=$(cat)
455+
456+ # Check we receive 4 space-separated fields
457+ field_count=$(echo \" $stdin\" | awk '{print NF}')
458+ if [ \" $field_count\" != \" 4\" ]; then
459+ echo \" ERROR: Expected 4 fields, got $field_count\" >&2
460+ exit 1
461+ fi
462+
463+ # Check format contains refs/heads/
464+ if ! echo \" $stdin\" | grep -q \" ^refs/heads/\" ; then
465+ echo \" ERROR: Invalid ref format\" >&2
466+ exit 1
467+ fi
468+
469+ # Validate arguments
470+ if [ \" $1\" != \" origin\" ]; then
471+ echo \" ERROR: Wrong remote: $1\" >&2
472+ exit 1
473+ fi
474+
475+ exit 0
476+ " ;
477+
478+ git2_hooks:: create_hook (
479+ & repo,
480+ git2_hooks:: HOOK_PRE_PUSH ,
481+ hook,
482+ ) ;
483+
484+ // Directly test the git2-hooks layer with a simple update
485+ let branch =
486+ repo. head ( ) . unwrap ( ) . shorthand ( ) . unwrap ( ) . to_string ( ) ;
487+ let commit_id = repo. head ( ) . unwrap ( ) . target ( ) . unwrap ( ) ;
488+ let update = git2_hooks:: PrePushRef :: new (
489+ format ! ( "refs/heads/{}" , branch) ,
490+ Some ( commit_id) ,
491+ format ! ( "refs/heads/{}" , branch) ,
492+ None ,
493+ ) ;
494+
495+ let res = git2_hooks:: hooks_pre_push (
496+ & repo,
497+ None ,
498+ Some ( "origin" ) ,
499+ "https://github.com/test/repo.git" ,
500+ & [ update] ,
501+ )
502+ . unwrap ( ) ;
503+
504+ // Hook should succeed
505+ assert ! ( res. is_ok( ) ) ;
506+ }
507+
508+ #[ test]
509+ fn test_pre_push_hook_rejects_based_on_stdin ( ) {
510+ let ( _td, repo) = repo_init ( ) . unwrap ( ) ;
511+
512+ // Create a hook that rejects pushes to master branch
513+ let hook = b"#!/bin/sh
514+ stdin=$(cat)
515+ if echo \" $stdin\" | grep -q \" refs/heads/master\" ; then
516+ echo \" Direct pushes to master not allowed\" >&2
517+ exit 1
518+ fi
519+ exit 0
520+ " ;
521+
522+ git2_hooks:: create_hook (
523+ & repo,
524+ git2_hooks:: HOOK_PRE_PUSH ,
525+ hook,
526+ ) ;
527+
528+ // Try to push master branch
529+ let commit_id = repo. head ( ) . unwrap ( ) . target ( ) . unwrap ( ) ;
530+ let update = git2_hooks:: PrePushRef :: new (
531+ "refs/heads/master" ,
532+ Some ( commit_id) ,
533+ "refs/heads/master" ,
534+ None ,
535+ ) ;
536+
537+ let res = git2_hooks:: hooks_pre_push (
538+ & repo,
539+ None ,
540+ Some ( "origin" ) ,
541+ "https://github.com/test/repo.git" ,
542+ & [ update] ,
543+ )
544+ . unwrap ( ) ;
545+
546+ // Hook should reject
547+ assert ! ( res. is_not_successful( ) ) ;
548+ }
446549}
0 commit comments