1
+ use std:: path:: Path ;
2
+
1
3
use anyhow:: Context ;
2
4
3
5
use crate :: utils:: { path_type, PathBufExt } ;
@@ -30,53 +32,37 @@ path_type!(BinFile: file);
30
32
path_type ! ( BinDir : dir) ;
31
33
32
34
impl BinDir {
33
- pub fn version_dir ( & self , version : & semver :: Version ) -> VersionBinDir {
34
- VersionBinDir ( self . 0 . join ( version. to_string ( ) ) )
35
+ pub fn version_dir ( & self , version : & str ) -> VersionBinDir {
36
+ VersionBinDir ( self . 0 . join ( version) )
35
37
}
36
38
39
+ pub const CURRENT_VERSION_DIR_NAME : & str = "current" ;
37
40
pub fn current_version_dir ( & self ) -> VersionBinDir {
38
- VersionBinDir ( self . 0 . join ( "current" ) )
41
+ VersionBinDir ( self . 0 . join ( Self :: CURRENT_VERSION_DIR_NAME ) )
39
42
}
40
43
41
- pub fn set_current_version ( & self , version : & semver:: Version ) -> anyhow:: Result < ( ) > {
42
- let link_path = self . current_version_dir ( ) ;
43
- #[ cfg( unix) ]
44
- {
45
- // remove the link if it already exists
46
- std:: fs:: remove_file ( & link_path) . ok ( ) ;
47
- std:: os:: unix:: fs:: symlink ( version. to_string ( ) , link_path) ?;
48
- }
49
- #[ cfg( windows) ]
50
- {
51
- junction:: delete ( & link_path) . ok ( ) ;
52
- let version_path = self . version_dir ( version) ;
53
- // We won't be able to create a junction if the fs isn't NTFS, so fall back to trying
54
- // to make a symlink.
55
- junction:: create ( & version_path, & link_path)
56
- . or_else ( |err| std:: os:: windows:: fs:: symlink_dir ( version. to_string ( ) , & link_path) . or ( Err ( err) ) ) ?;
57
- }
58
- Ok ( ( ) )
44
+ pub fn set_current_version ( & self , version : & str ) -> anyhow:: Result < ( ) > {
45
+ self . current_version_dir ( ) . link_to ( self . version_dir ( version) . as_ref ( ) )
59
46
}
60
47
61
- pub fn current_version ( & self ) -> anyhow:: Result < Option < semver :: Version > > {
48
+ pub fn current_version ( & self ) -> anyhow:: Result < Option < String > > {
62
49
match std:: fs:: read_link ( self . current_version_dir ( ) ) {
63
- Ok ( path) => path
64
- . to_str ( )
65
- . context ( "not utf8" )
66
- . and_then ( |s| s. parse :: < semver:: Version > ( ) . map_err ( Into :: into) )
67
- . context ( "could not parse `current` symlink as a version number" )
68
- . map ( Some ) ,
50
+ Ok ( path) => path. into_os_string ( ) . into_string ( ) . ok ( ) . context ( "not utf8" ) . map ( Some ) ,
69
51
Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => Ok ( None ) ,
70
52
Err ( e) => Err ( e. into ( ) ) ,
71
53
}
72
54
}
73
55
74
- pub fn installed_versions ( & self ) -> anyhow:: Result < Vec < semver :: Version > > {
56
+ pub fn installed_versions ( & self ) -> anyhow:: Result < Vec < String > > {
75
57
self . read_dir ( ) ?
76
58
. filter_map ( |r| match r {
77
59
Ok ( entry) => {
78
- let parsed: semver:: Version = entry. file_name ( ) . to_str ( ) ?. parse ( ) . ok ( ) ?;
79
- Some ( anyhow:: Ok ( parsed) )
60
+ let name = entry. file_name ( ) ;
61
+ if name == Self :: CURRENT_VERSION_DIR_NAME {
62
+ None
63
+ } else {
64
+ entry. file_name ( ) . into_string ( ) . ok ( ) . map ( Ok )
65
+ }
80
66
}
81
67
Err ( e) => Some ( Err ( e. into ( ) ) ) ,
82
68
} )
@@ -90,6 +76,32 @@ impl VersionBinDir {
90
76
pub fn spacetimedb_cli ( self ) -> SpacetimedbCliBin {
91
77
SpacetimedbCliBin ( self . 0 . joined ( "spacetimedb-cli" ) . with_exe_ext ( ) )
92
78
}
79
+
80
+ pub fn create_custom ( & self , path : & Path ) -> anyhow:: Result < ( ) > {
81
+ if std:: fs:: symlink_metadata ( self ) . is_ok_and ( |m| m. file_type ( ) . is_dir ( ) ) {
82
+ anyhow:: bail!( "version already exists" ) ;
83
+ }
84
+ self . link_to ( path)
85
+ }
86
+
87
+ fn link_to ( & self , path : & Path ) -> anyhow:: Result < ( ) > {
88
+ let rel_path = path. strip_prefix ( self ) . unwrap_or ( path) ;
89
+ #[ cfg( unix) ]
90
+ {
91
+ // remove the link if it already exists
92
+ std:: fs:: remove_file ( self ) . ok ( ) ;
93
+ std:: os:: unix:: fs:: symlink ( rel_path, self ) ?;
94
+ }
95
+ #[ cfg( windows) ]
96
+ {
97
+ junction:: delete ( self ) . ok ( ) ;
98
+ // We won't be able to create a junction if the fs isn't NTFS, so fall back to trying
99
+ // to make a symlink.
100
+ junction:: create ( path, self )
101
+ . or_else ( |err| std:: os:: windows:: fs:: symlink_dir ( rel_path, self ) . or ( Err ( err) ) ) ?;
102
+ }
103
+ Ok ( ( ) )
104
+ }
93
105
}
94
106
95
107
path_type ! ( SpacetimedbCliBin : file) ;
0 commit comments