11
11
//! That command will first ensure that the required toolchain is installed and then
12
12
//! run `cargo install` for the driver with a specific toolchain. The version and
13
13
//! toolchain are hardcoded in this crate.
14
- //!
15
- //! If a driver is already installed. We'll first run the driver to request the
16
- //! required toolchain and then run the driver using that toolchain. Requesting
17
- //! the toolchain works, since the argument will be processed before rustc is run.
18
- //! At least, that's the idea.
19
14
20
- use std:: process:: Command ;
15
+ use std:: { path :: PathBuf , process:: Command } ;
21
16
22
17
use once_cell:: sync:: Lazy ;
23
18
@@ -28,11 +23,35 @@ use crate::ExitStatus;
28
23
static DEFAULT_DRIVER_INFO : Lazy < RustcDriverInfo > = Lazy :: new ( || RustcDriverInfo {
29
24
toolchain : "nightly-2022-11-03" . to_string ( ) ,
30
25
version : "0.1.0" . to_string ( ) ,
26
+ api_version : "0.1.0" . to_string ( ) ,
31
27
} ) ;
32
28
33
29
struct RustcDriverInfo {
34
30
toolchain : String ,
35
31
version : String ,
32
+ #[ allow( unused) ]
33
+ api_version : String ,
34
+ }
35
+
36
+ /// This tries to install the rustc driver specified in [`DEFAULT_DRIVER_INFO`].
37
+ pub fn install_driver ( verbose : bool ) -> Result < ( ) , ExitStatus > {
38
+ // The toolchain, driver version and api version should ideally be configurable.
39
+ // However, that will require more prototyping and has a low priority rn.
40
+ // See #60
41
+
42
+ // Prerequisites
43
+ let toolchain = & DEFAULT_DRIVER_INFO . toolchain ;
44
+ check_toolchain ( toolchain) ?;
45
+
46
+ build_driver (
47
+ toolchain,
48
+ & DEFAULT_DRIVER_INFO . version ,
49
+ verbose,
50
+ cfg ! ( feature = "dev-build" ) ,
51
+ ) ?;
52
+
53
+ // We don't want to advice the user, to install the driver again.
54
+ check_driver ( verbose, false )
36
55
}
37
56
38
57
/// This function checks if the specified toolchain is installed. This requires
@@ -41,7 +60,7 @@ fn check_toolchain(toolchain: &str) -> Result<(), ExitStatus> {
41
60
let mut cmd = Command :: new ( "cargo" ) ;
42
61
cmd. args ( [ & format ! ( "+{toolchain}" ) , "-V" ] ) ;
43
62
if cmd. output ( ) . is_err ( ) {
44
- eprintln ! ( "error: the required toolchain `{toolchain}` can't be found" ) ;
63
+ eprintln ! ( "Error: The required toolchain `{toolchain}` can't be found" ) ;
45
64
eprintln ! ( ) ;
46
65
eprintln ! ( "You can install the toolchain by running: rustup toolchain install {toolchain}" ) ;
47
66
Err ( ExitStatus :: InvalidToolchain )
@@ -50,29 +69,32 @@ fn check_toolchain(toolchain: &str) -> Result<(), ExitStatus> {
50
69
}
51
70
}
52
71
53
- /// This tries to install the rustc driver specified in [`DEFAULT_DRIVER_INFO`].
54
- pub fn install_driver ( verbose : bool ) -> Result < ( ) , ExitStatus > {
55
- // Prerequisites
56
- let toolchain = & DEFAULT_DRIVER_INFO . toolchain ;
57
- check_toolchain ( & toolchain) ?;
72
+ /// This tries to compile the driver. If successful the driver binary will
73
+ /// be places next to the executable of `cargo-linter`.
74
+ fn build_driver ( toolchain : & str , version : & str , verbose : bool , dev_build : bool ) -> Result < ( ) , ExitStatus > {
75
+ if dev_build {
76
+ println ! ( "Compiling rustc driver" ) ;
77
+ } else {
78
+ println ! ( "Compiling rustc driver v{version} with {toolchain}" ) ;
79
+ }
58
80
59
81
// Build driver
60
82
let mut cmd = Command :: new ( "cargo" ) ;
61
- cmd. arg ( & format ! ( "+{toolchain}" ) ) ;
83
+
84
+ if !dev_build {
85
+ cmd. arg ( & format ! ( "+{toolchain}" ) ) ;
86
+ }
62
87
63
88
if verbose {
64
89
cmd. arg ( "--verbose" ) ;
65
90
}
66
91
67
- #[ cfg( feature = "dev-build" ) ]
68
- cmd. args ( [ "build" , "--bin" , "linter_driver_rustc" ] ) ;
69
- #[ cfg( not( feature = "dev-build" ) ) ]
70
- cmd. args ( [
71
- "install" ,
72
- "marker_rustc_driver" ,
73
- "--version" ,
74
- & DEFAULT_DRIVER_INFO . version ,
75
- ] ) ;
92
+ if dev_build {
93
+ cmd. args ( [ "build" , "--bin" , "marker_driver_rustc" ] ) ;
94
+ } else {
95
+ // TODO Set output path to the local branch thingy
96
+ cmd. args ( [ "install" , "marker_rustc_driver" , "--version" , version] ) ;
97
+ }
76
98
77
99
let status = cmd
78
100
. spawn ( )
@@ -87,3 +109,34 @@ pub fn install_driver(verbose: bool) -> Result<(), ExitStatus> {
87
109
Err ( ExitStatus :: DriverInstallationFailed )
88
110
}
89
111
}
112
+
113
+ fn check_driver ( verbose : bool , print_advice : bool ) -> Result < ( ) , ExitStatus > {
114
+ let path = get_driver_path ( ) ;
115
+ if verbose {
116
+ println ! ( "Searching for driver at: {}" , path. display( ) ) ;
117
+ }
118
+
119
+ if !path. exists ( ) || !path. is_file ( ) {
120
+ if print_advice {
121
+ eprintln ! ( "Error: The driver binary could not be found." ) ;
122
+ eprintln ! ( ) ;
123
+ eprintln ! ( "Try installing it via `cargo marker setup`" ) ;
124
+ }
125
+
126
+ Err ( ExitStatus :: MissingDriver )
127
+ } else {
128
+ Ok ( ( ) )
129
+ }
130
+ }
131
+
132
+ pub fn get_driver_path ( ) -> PathBuf {
133
+ #[ allow( unused_mut) ]
134
+ let mut path = std:: env:: current_exe ( )
135
+ . expect ( "unable to retrieve the path of the current executable" )
136
+ . with_file_name ( "marker_driver_rustc" ) ;
137
+
138
+ #[ cfg( target_os = "windows" ) ]
139
+ path. set_extension ( "exe" ) ;
140
+
141
+ path
142
+ }
0 commit comments