@@ -2827,3 +2827,117 @@ internal server error
28272827 )
28282828 . run ( ) ;
28292829}
2830+
2831+ #[ cargo_test]
2832+ fn deleted_entry ( ) {
2833+ // Checks the behavior when a package is removed from the index.
2834+ // This is done occasionally on crates.io to handle things like
2835+ // copyright takedowns.
2836+ let p = project ( )
2837+ . file (
2838+ "Cargo.toml" ,
2839+ r#"
2840+ [package]
2841+ name = "foo"
2842+ version = "0.1.0"
2843+
2844+ [dependencies]
2845+ bar = "0.1"
2846+ "# ,
2847+ )
2848+ . file ( "src/lib.rs" , "" )
2849+ . build ( ) ;
2850+
2851+ // First, test removing a single version, but leaving an older version.
2852+ Package :: new ( "bar" , "0.1.0" ) . publish ( ) ;
2853+ let bar_path = Path :: new ( "3/b/bar" ) ;
2854+ let bar_reg_path = registry_path ( ) . join ( & bar_path) ;
2855+ let old_index = fs:: read_to_string ( & bar_reg_path) . unwrap ( ) ;
2856+ Package :: new ( "bar" , "0.1.1" ) . publish ( ) ;
2857+ p. cargo ( "tree" )
2858+ . with_stderr (
2859+ "\
2860+ [UPDATING] `dummy-registry` index
2861+ [DOWNLOADING] crates ...
2862+ [DOWNLOADED] bar v0.1.1 (registry `dummy-registry`)
2863+ " ,
2864+ )
2865+ . with_stdout (
2866+ "\
2867+ foo v0.1.0 ([ROOT]/foo)
2868+ └── bar v0.1.1
2869+ " ,
2870+ )
2871+ . run ( ) ;
2872+
2873+ // Remove 0.1.1
2874+ fs:: remove_file ( paths:: root ( ) . join ( "dl/bar/0.1.1/download" ) ) . unwrap ( ) ;
2875+ let repo = git2:: Repository :: open ( registry_path ( ) ) . unwrap ( ) ;
2876+ let mut index = repo. index ( ) . unwrap ( ) ;
2877+ fs:: write ( & bar_reg_path, & old_index) . unwrap ( ) ;
2878+ index. add_path ( & bar_path) . unwrap ( ) ;
2879+ index. write ( ) . unwrap ( ) ;
2880+ git:: commit ( & repo) ;
2881+
2882+ // With `Cargo.lock` unchanged, it shouldn't have an impact.
2883+ p. cargo ( "tree" )
2884+ . with_stderr ( "" )
2885+ . with_stdout (
2886+ "\
2887+ foo v0.1.0 ([ROOT]/foo)
2888+ └── bar v0.1.1
2889+ " ,
2890+ )
2891+ . run ( ) ;
2892+
2893+ // Regenerating Cargo.lock should switch to old version.
2894+ fs:: remove_file ( p. root ( ) . join ( "Cargo.lock" ) ) . unwrap ( ) ;
2895+ p. cargo ( "tree" )
2896+ . with_stderr (
2897+ "\
2898+ [UPDATING] `dummy-registry` index
2899+ [DOWNLOADING] crates ...
2900+ [DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)
2901+ " ,
2902+ )
2903+ . with_stdout (
2904+ "\
2905+ foo v0.1.0 ([ROOT]/foo)
2906+ └── bar v0.1.0
2907+ " ,
2908+ )
2909+ . run ( ) ;
2910+
2911+ // Remove the package entirely.
2912+ fs:: remove_file ( paths:: root ( ) . join ( "dl/bar/0.1.0/download" ) ) . unwrap ( ) ;
2913+ let mut index = repo. index ( ) . unwrap ( ) ;
2914+ index. remove ( & bar_path, 0 ) . unwrap ( ) ;
2915+ index. write ( ) . unwrap ( ) ;
2916+ git:: commit ( & repo) ;
2917+ fs:: remove_file ( & bar_reg_path) . unwrap ( ) ;
2918+
2919+ // With `Cargo.lock` unchanged, it shouldn't have an impact.
2920+ p. cargo ( "tree" )
2921+ . with_stderr ( "" )
2922+ . with_stdout (
2923+ "\
2924+ foo v0.1.0 ([ROOT]/foo)
2925+ └── bar v0.1.0
2926+ " ,
2927+ )
2928+ . run ( ) ;
2929+
2930+ // Regenerating Cargo.lock should fail.
2931+ fs:: remove_file ( p. root ( ) . join ( "Cargo.lock" ) ) . unwrap ( ) ;
2932+ p. cargo ( "tree" )
2933+ . with_stderr (
2934+ "\
2935+ [UPDATING] `dummy-registry` index
2936+ error: no matching package named `bar` found
2937+ location searched: registry `crates-io`
2938+ required by package `foo v0.1.0 ([ROOT]/foo)`
2939+ " ,
2940+ )
2941+ . with_status ( 101 )
2942+ . run ( ) ;
2943+ }
0 commit comments