@@ -3282,3 +3282,105 @@ fn metadata_master_consistency() {
32823282 let bar_source = format ! ( "git+{}" , git_project. url( ) ) ;
32833283 p. cargo ( "metadata" ) . with_json ( & metadata ( & bar_source) ) . run ( ) ;
32843284}
3285+
3286+ #[ cargo_test]
3287+ fn git_with_force_push ( ) {
3288+ // Checks that cargo can handle force-pushes to git repos.
3289+ // This works by having a git dependency that is updated with an amend
3290+ // commit, and tries with various forms (default branch, branch, rev,
3291+ // tag).
3292+ let main = |text| format ! ( r#"pub fn f() {{ println!("{}"); }}"# , text) ;
3293+ let ( git_project, repo) = git:: new_repo ( "dep1" , |project| {
3294+ project
3295+ . file ( "Cargo.toml" , & basic_lib_manifest ( "dep1" ) )
3296+ . file ( "src/lib.rs" , & main ( "one" ) )
3297+ } ) ;
3298+ let manifest = |extra| {
3299+ format ! (
3300+ r#"
3301+ [project]
3302+ name = "foo"
3303+ version = "0.0.1"
3304+ edition = "2018"
3305+
3306+ [dependencies]
3307+ dep1 = {{ git = "{}"{} }}
3308+ "# ,
3309+ git_project. url( ) ,
3310+ extra
3311+ )
3312+ } ;
3313+ let p = project ( )
3314+ . file ( "Cargo.toml" , & manifest ( "" ) )
3315+ . file ( "src/main.rs" , "fn main() { dep1::f(); }" )
3316+ . build ( ) ;
3317+ // Download the original and make sure it is OK.
3318+ p. cargo ( "build" ) . run ( ) ;
3319+ p. rename_run ( "foo" , "foo1" ) . with_stdout ( "one" ) . run ( ) ;
3320+
3321+ let find_head = || t ! ( t!( repo. head( ) ) . peel_to_commit( ) ) ;
3322+
3323+ let amend_commit = |text| {
3324+ // commit --amend a change that will require a force fetch.
3325+ git_project. change_file ( "src/lib.rs" , & main ( text) ) ;
3326+ git:: add ( & repo) ;
3327+ let commit = find_head ( ) ;
3328+ let tree_id = t ! ( t!( repo. index( ) ) . write_tree( ) ) ;
3329+ t ! ( commit. amend(
3330+ Some ( "HEAD" ) ,
3331+ None ,
3332+ None ,
3333+ None ,
3334+ None ,
3335+ Some ( & t!( repo. find_tree( tree_id) ) )
3336+ ) ) ;
3337+ } ;
3338+
3339+ let mut rename_annoyance = 1 ;
3340+
3341+ let mut verify = |text : & str | {
3342+ // Perform the fetch.
3343+ p. cargo ( "update" ) . run ( ) ;
3344+ p. cargo ( "build" ) . run ( ) ;
3345+ rename_annoyance += 1 ;
3346+ p. rename_run ( "foo" , & format ! ( "foo{}" , rename_annoyance) )
3347+ . with_stdout ( text)
3348+ . run ( ) ;
3349+ } ;
3350+
3351+ amend_commit ( "two" ) ;
3352+ verify ( "two" ) ;
3353+
3354+ // Try with a rev.
3355+ let head1 = find_head ( ) . id ( ) . to_string ( ) ;
3356+ let extra = format ! ( ", rev = \" {}\" " , head1) ;
3357+ p. change_file ( "Cargo.toml" , & manifest ( & extra) ) ;
3358+ verify ( "two" ) ;
3359+ amend_commit ( "three" ) ;
3360+ let head2 = find_head ( ) . id ( ) . to_string ( ) ;
3361+ assert_ne ! ( & head1, & head2) ;
3362+ let extra = format ! ( ", rev = \" {}\" " , head2) ;
3363+ p. change_file ( "Cargo.toml" , & manifest ( & extra) ) ;
3364+ verify ( "three" ) ;
3365+
3366+ // Try with a tag.
3367+ git:: tag ( & repo, "my-tag" ) ;
3368+ p. change_file ( "Cargo.toml" , & manifest ( ", tag = \" my-tag\" " ) ) ;
3369+ verify ( "three" ) ;
3370+ amend_commit ( "tag-three" ) ;
3371+ let head = t ! ( t!( repo. head( ) ) . peel( git2:: ObjectType :: Commit ) ) ;
3372+ t ! ( repo. tag( "my-tag" , & head, & t!( repo. signature( ) ) , "move tag" , true ) ) ;
3373+ verify ( "tag-three" ) ;
3374+
3375+ // Try with a branch.
3376+ let br = t ! ( repo. branch( "awesome-stuff" , & find_head( ) , false ) ) ;
3377+ t ! ( repo. checkout_tree( & t!( br. get( ) . peel( git2:: ObjectType :: Tree ) ) , None ) ) ;
3378+ t ! ( repo. set_head( "refs/heads/awesome-stuff" ) ) ;
3379+ git_project. change_file ( "src/lib.rs" , & main ( "awesome-three" ) ) ;
3380+ git:: add ( & repo) ;
3381+ git:: commit ( & repo) ;
3382+ p. change_file ( "Cargo.toml" , & manifest ( ", branch = \" awesome-stuff\" " ) ) ;
3383+ verify ( "awesome-three" ) ;
3384+ amend_commit ( "awesome-four" ) ;
3385+ verify ( "awesome-four" ) ;
3386+ }
0 commit comments