@@ -497,12 +497,194 @@ pub fn cargo_home() -> Result<PathBuf> {
497
497
cargo_home. or ( user_home) . ok_or ( ErrorKind :: CargoHome . into ( ) )
498
498
}
499
499
500
+ // Convert the ~/.multirust folder to ~/.rustup while dealing with rustup.sh
501
+ // metadata, which used to also live in ~/.rustup, but now lives in ~/rustup.sh.
502
+ pub fn do_rustup_home_upgrade ( ) -> bool {
503
+
504
+ fn rustup_home_is_set ( ) -> bool {
505
+ env:: var_os ( "RUSTUP_HOME" ) . is_some ( )
506
+ }
507
+
508
+ fn rustup_dir ( ) -> Option < PathBuf > {
509
+ dot_dir ( ".rustup" )
510
+ }
511
+
512
+ fn rustup_sh_dir ( ) -> Option < PathBuf > {
513
+ dot_dir ( ".rustup.sh" )
514
+ }
515
+
516
+ fn multirust_dir ( ) -> Option < PathBuf > {
517
+ dot_dir ( ".multirust" )
518
+ }
519
+
520
+ fn rustup_dir_exists ( ) -> bool {
521
+ rustup_dir ( ) . map ( |p| p. exists ( ) ) . unwrap_or ( false )
522
+ }
523
+
524
+ fn rustup_sh_dir_exists ( ) -> bool {
525
+ rustup_sh_dir ( ) . map ( |p| p. exists ( ) ) . unwrap_or ( false )
526
+ }
527
+
528
+ fn multirust_dir_exists ( ) -> bool {
529
+ multirust_dir ( ) . map ( |p| p. exists ( ) ) . unwrap_or ( false )
530
+ }
531
+
532
+ fn rustup_old_version_exists ( ) -> bool {
533
+ rustup_dir ( )
534
+ . map ( |p| p. join ( "rustup-version" ) . exists ( ) )
535
+ . unwrap_or ( false )
536
+ }
537
+
538
+ fn delete_rustup_dir ( ) -> Result < ( ) > {
539
+ if let Some ( dir) = rustup_dir ( ) {
540
+ raw:: remove_dir ( & dir)
541
+ . chain_err ( || "unable to delete rustup dir" ) ?;
542
+ }
543
+
544
+ Ok ( ( ) )
545
+ }
546
+
547
+ fn rename_rustup_dir_to_rustup_sh ( ) -> Result < ( ) > {
548
+ let dirs = ( rustup_dir ( ) , rustup_sh_dir ( ) ) ;
549
+ if let ( Some ( rustup) , Some ( rustup_sh) ) = dirs {
550
+ fs:: rename ( & rustup, & rustup_sh)
551
+ . chain_err ( || "unable to rename rustup dir" ) ?;
552
+ }
553
+
554
+ Ok ( ( ) )
555
+ }
556
+
557
+ fn rename_multirust_dir_to_rustup ( ) -> Result < ( ) > {
558
+ let dirs = ( multirust_dir ( ) , rustup_dir ( ) ) ;
559
+ if let ( Some ( rustup) , Some ( rustup_sh) ) = dirs {
560
+ fs:: rename ( & rustup, & rustup_sh)
561
+ . chain_err ( || "unable to rename multirust dir" ) ?;
562
+ }
563
+
564
+ Ok ( ( ) )
565
+ }
566
+
567
+ // If RUSTUP_HOME is set then its default path doesn't matter, so we're
568
+ // not going to risk doing any I/O work and making a mess.
569
+ if rustup_home_is_set ( ) { return true }
570
+
571
+ // Now we are just trying to get a bogus, rustup.sh-created ~/.rustup out
572
+ // of the way in the manner that is least likely to take time and generate
573
+ // errors. First try to rename it to ~/.rustup.sh, then try to delete it.
574
+ // If that doesn't work we can't use the ~/.rustup name.
575
+ let old_rustup_dir_removed = if rustup_old_version_exists ( ) {
576
+ if !rustup_sh_dir_exists ( ) {
577
+ if rename_rustup_dir_to_rustup_sh ( ) . is_ok ( ) {
578
+ true
579
+ } else {
580
+ if delete_rustup_dir ( ) . is_ok ( ) {
581
+ true
582
+ } else {
583
+ false
584
+ }
585
+ }
586
+ } else {
587
+ if delete_rustup_dir ( ) . is_ok ( ) {
588
+ true
589
+ } else {
590
+ false
591
+ }
592
+ }
593
+ } else {
594
+ true
595
+ } ;
596
+
597
+ // Now we're trying to move ~/.multirust to ~/.rustup
598
+ old_rustup_dir_removed && if multirust_dir_exists ( ) {
599
+ if rustup_dir_exists ( ) {
600
+ // There appears to be both a ~/.multirust dir and a valid ~/.rustup
601
+ // dir. Most likely because one is a symlink to the other, as configured
602
+ // below.
603
+ true
604
+ } else {
605
+ if rename_multirust_dir_to_rustup ( ) . is_ok ( ) {
606
+ // Finally, making the hardlink from ~/.multirust back to
607
+ // ~/.rustup, for temporary compatibility.
608
+ let _ = create_legacy_multirust_symlink ( ) ;
609
+ true
610
+ } else {
611
+ false
612
+ }
613
+ }
614
+ } else {
615
+ true
616
+ }
617
+ }
618
+
619
+ // Creates a ~/.rustup folder and a ~/.multirust symlink
620
+ pub fn create_rustup_home ( ) -> Result < ( ) > {
621
+ // If RUSTUP_HOME is set then don't make any assumptions about where it's
622
+ // ok to put ~/.multirust
623
+ if env:: var_os ( "RUSTUP_HOME" ) . is_some ( ) { return Ok ( ( ) ) }
624
+
625
+ let home = rustup_home_in_user_dir ( ) ?;
626
+ fs:: create_dir_all ( & home)
627
+ . chain_err ( || "unable to create ~/.rustup" ) ?;
628
+
629
+ // This is a temporary compatibility symlink
630
+ create_legacy_multirust_symlink ( ) ?;
631
+
632
+ Ok ( ( ) )
633
+ }
634
+
635
+ // Create a symlink from ~/.multirust to ~/.rustup to temporarily
636
+ // accomodate old tools that are expecting that directory
637
+ fn create_legacy_multirust_symlink ( ) -> Result < ( ) > {
638
+ let newhome = rustup_home_in_user_dir ( ) ?;
639
+ let oldhome = legacy_multirust_home ( ) ?;
640
+
641
+ raw:: symlink_dir ( & newhome, & oldhome)
642
+ . chain_err ( || format ! ( "unable to symlink {} from {}" ,
643
+ newhome. display( ) , oldhome. display( ) ) ) ?;
644
+
645
+ Ok ( ( ) )
646
+ }
647
+
648
+ pub fn delete_legacy_multirust_symlink ( ) -> Result < ( ) > {
649
+ let oldhome = legacy_multirust_home ( ) ?;
650
+
651
+ if oldhome. exists ( ) {
652
+ let meta = fs:: symlink_metadata ( & oldhome)
653
+ . chain_err ( || "unable to get metadata for ~/.multirust" ) ?;
654
+ if meta. file_type ( ) . is_symlink ( ) {
655
+ // remove_dir handles unlinking symlinks
656
+ raw:: remove_dir ( & oldhome)
657
+ . chain_err ( || format ! ( "unable to delete legacy symlink {}" , oldhome. display( ) ) ) ?;
658
+ }
659
+ }
660
+
661
+ Ok ( ( ) )
662
+ }
663
+
664
+ fn dot_dir ( name : & str ) -> Option < PathBuf > {
665
+ home_dir ( ) . map ( |p| p. join ( name) )
666
+ }
667
+
668
+ pub fn legacy_multirust_home ( ) -> Result < PathBuf > {
669
+ dot_dir ( ".multirust" ) . ok_or ( ErrorKind :: MultirustHome . into ( ) )
670
+ }
671
+
672
+ pub fn rustup_home_in_user_dir ( ) -> Result < PathBuf > {
673
+ dot_dir ( ".rustup" ) . ok_or ( ErrorKind :: MultirustHome . into ( ) )
674
+ }
675
+
500
676
pub fn multirust_home ( ) -> Result < PathBuf > {
677
+ let use_rustup_dir = do_rustup_home_upgrade ( ) ;
678
+
501
679
let cwd = try!( env:: current_dir ( ) . chain_err ( || ErrorKind :: MultirustHome ) ) ;
502
680
let multirust_home = env:: var_os ( "RUSTUP_HOME" ) . map ( |home| {
503
681
cwd. join ( home)
504
682
} ) ;
505
- let user_home = home_dir ( ) . map ( |p| p. join ( ".multirust" ) ) ;
683
+ let user_home = if use_rustup_dir {
684
+ dot_dir ( ".rustup" )
685
+ } else {
686
+ dot_dir ( ".multirust" )
687
+ } ;
506
688
multirust_home. or ( user_home) . ok_or ( ErrorKind :: MultirustHome . into ( ) )
507
689
}
508
690
0 commit comments