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