@@ -16,6 +16,7 @@ use std::{fmt, fs::write, path::PathBuf};
16
16
use clap:: ArgMatches ;
17
17
use serde:: { Deserialize , Serialize } ;
18
18
use serde_json:: Value ;
19
+ //use git2::Repository;
19
20
20
21
// use this to store the crates when interacting with the crates.toml file
21
22
#[ derive( Debug , Serialize , Deserialize ) ]
@@ -35,12 +36,13 @@ struct TomlCrate {
35
36
36
37
// represents an archive we download from crates.io
37
38
#[ derive( Debug , Serialize , Deserialize , Eq , Hash , PartialEq ) ]
38
- struct CrateSource {
39
- name : String ,
40
- version : String ,
39
+ enum CrateSource {
40
+ CratesIo { name : String , version : String } ,
41
+ Git { name : String , url : String , commit : String } ,
41
42
}
42
43
43
44
// represents the extracted sourcecode of a crate
45
+ // we actually don't need to special-case git repos here because it does not matter for clippy, yay! (clippy only needs a simple path)
44
46
#[ derive( Debug ) ]
45
47
struct Crate {
46
48
version : String ,
@@ -72,40 +74,70 @@ impl std::fmt::Display for ClippyWarning {
72
74
73
75
impl CrateSource {
74
76
fn download_and_extract ( & self ) -> Crate {
75
- let extract_dir = PathBuf :: from ( "target/lintcheck/crates" ) ;
76
- let krate_download_dir = PathBuf :: from ( "target/lintcheck/downloads" ) ;
77
-
78
- // url to download the crate from crates.io
79
- let url = format ! (
80
- "https://crates.io/api/v1/crates/{}/{}/download" ,
81
- self . name, self . version
82
- ) ;
83
- println ! ( "Downloading and extracting {} {} from {}" , self . name, self . version, url) ;
84
- let _ = std:: fs:: create_dir ( "target/lintcheck/" ) ;
85
- let _ = std:: fs:: create_dir ( & krate_download_dir) ;
86
- let _ = std:: fs:: create_dir ( & extract_dir) ;
87
-
88
- let krate_file_path = krate_download_dir. join ( format ! ( "{}-{}.crate.tar.gz" , & self . name, & self . version) ) ;
89
- // don't download/extract if we already have done so
90
- if !krate_file_path. is_file ( ) {
91
- // create a file path to download and write the crate data into
92
- let mut krate_dest = std:: fs:: File :: create ( & krate_file_path) . unwrap ( ) ;
93
- let mut krate_req = ureq:: get ( & url) . call ( ) . unwrap ( ) . into_reader ( ) ;
94
- // copy the crate into the file
95
- std:: io:: copy ( & mut krate_req, & mut krate_dest) . unwrap ( ) ;
96
-
97
- // unzip the tarball
98
- let ungz_tar = flate2:: read:: GzDecoder :: new ( std:: fs:: File :: open ( & krate_file_path) . unwrap ( ) ) ;
99
- // extract the tar archive
100
- let mut archive = tar:: Archive :: new ( ungz_tar) ;
101
- archive. unpack ( & extract_dir) . expect ( "Failed to extract!" ) ;
102
- }
103
- // crate is extracted, return a new Krate object which contains the path to the extracted
104
- // sources that clippy can check
105
- Crate {
106
- version : self . version . clone ( ) ,
107
- name : self . name . clone ( ) ,
108
- path : extract_dir. join ( format ! ( "{}-{}/" , self . name, self . version) ) ,
77
+ match self {
78
+ CrateSource :: CratesIo { name, version } => {
79
+ let extract_dir = PathBuf :: from ( "target/lintcheck/crates" ) ;
80
+ let krate_download_dir = PathBuf :: from ( "target/lintcheck/downloads" ) ;
81
+
82
+ // url to download the crate from crates.io
83
+ let url = format ! ( "https://crates.io/api/v1/crates/{}/{}/download" , name, version) ;
84
+ println ! ( "Downloading and extracting {} {} from {}" , name, version, url) ;
85
+ let _ = std:: fs:: create_dir ( "target/lintcheck/" ) ;
86
+ let _ = std:: fs:: create_dir ( & krate_download_dir) ;
87
+ let _ = std:: fs:: create_dir ( & extract_dir) ;
88
+
89
+ let krate_file_path = krate_download_dir. join ( format ! ( "{}-{}.crate.tar.gz" , name, version) ) ;
90
+ // don't download/extract if we already have done so
91
+ if !krate_file_path. is_file ( ) {
92
+ // create a file path to download and write the crate data into
93
+ let mut krate_dest = std:: fs:: File :: create ( & krate_file_path) . unwrap ( ) ;
94
+ let mut krate_req = ureq:: get ( & url) . call ( ) . unwrap ( ) . into_reader ( ) ;
95
+ // copy the crate into the file
96
+ std:: io:: copy ( & mut krate_req, & mut krate_dest) . unwrap ( ) ;
97
+
98
+ // unzip the tarball
99
+ let ungz_tar = flate2:: read:: GzDecoder :: new ( std:: fs:: File :: open ( & krate_file_path) . unwrap ( ) ) ;
100
+ // extract the tar archive
101
+ let mut archive = tar:: Archive :: new ( ungz_tar) ;
102
+ archive. unpack ( & extract_dir) . expect ( "Failed to extract!" ) ;
103
+ }
104
+ // crate is extracted, return a new Krate object which contains the path to the extracted
105
+ // sources that clippy can check
106
+ Crate {
107
+ version : version. clone ( ) ,
108
+ name : name. clone ( ) ,
109
+ path : extract_dir. join ( format ! ( "{}-{}/" , name, version) ) ,
110
+ }
111
+ } ,
112
+ CrateSource :: Git { name, url, commit } => {
113
+ let repo_path = {
114
+ let mut repo_path = PathBuf :: from ( "target/lintcheck/downloads" ) ;
115
+ // add a -git suffix in case we have the same crate from crates.io and a git repo
116
+ repo_path. push ( format ! ( "{}-git" , name) ) ;
117
+ repo_path
118
+ } ;
119
+ // clone the repo if we have not done so
120
+ if !repo_path. is_dir ( ) {
121
+ Command :: new ( "git" )
122
+ . arg ( "clone" )
123
+ . arg ( url)
124
+ . arg ( & repo_path)
125
+ . output ( )
126
+ . expect ( "Failed to clone git repo!" ) ;
127
+ }
128
+ // check out the commit/branch/whatever
129
+ Command :: new ( "git" )
130
+ . arg ( "checkout" )
131
+ . arg ( commit)
132
+ . output ( )
133
+ . expect ( "Failed to check out commit" ) ;
134
+
135
+ Crate {
136
+ version : commit. clone ( ) ,
137
+ name : name. clone ( ) ,
138
+ path : repo_path,
139
+ }
140
+ } ,
109
141
}
110
142
}
111
143
}
@@ -175,14 +207,30 @@ fn read_crates() -> Vec<CrateSource> {
175
207
// multiple Cratesources)
176
208
let mut crate_sources = Vec :: new ( ) ;
177
209
tomlcrates. into_iter ( ) . for_each ( |tk| {
210
+ // if we have multiple versions, save each one
178
211
if let Some ( ref versions) = tk. versions {
179
212
versions. iter ( ) . for_each ( |ver| {
180
- crate_sources. push ( CrateSource {
213
+ crate_sources. push ( CrateSource :: CratesIo {
181
214
name : tk. name . clone ( ) ,
182
215
version : ver. to_string ( ) ,
183
216
} ) ;
184
217
} )
185
218
}
219
+ // otherwise, we should have a git source
220
+ if tk. git_url . is_some ( ) && tk. git_hash . is_some ( ) {
221
+ crate_sources. push ( CrateSource :: Git {
222
+ name : tk. name . clone ( ) ,
223
+ url : tk. git_url . clone ( ) . unwrap ( ) ,
224
+ commit : tk. git_hash . clone ( ) . unwrap ( ) ,
225
+ } ) ;
226
+ }
227
+ // if we have a version as well as a git data OR only one git data, something is funky
228
+ if tk. versions . is_some ( ) && ( tk. git_url . is_some ( ) || tk. git_hash . is_some ( ) )
229
+ || tk. git_hash . is_some ( ) != tk. git_url . is_some ( )
230
+ {
231
+ dbg ! ( tk) ;
232
+ unreachable ! ( "Failed to translate TomlCrate into CrateSource!" ) ;
233
+ }
186
234
} ) ;
187
235
crate_sources
188
236
}
@@ -239,13 +287,13 @@ pub fn run(clap_config: &ArgMatches) {
239
287
240
288
let clippy_warnings: Vec < ClippyWarning > = if let Some ( only_one_crate) = clap_config. value_of ( "only" ) {
241
289
// if we don't have the specified crated in the .toml, throw an error
242
- if !crates. iter ( ) . any ( |krate| krate. name == only_one_crate) {
290
+ /* if !crates.iter().any(|krate| krate.name == only_one_crate) {
243
291
eprintln!(
244
292
"ERROR: could not find crate '{}' in clippy_dev/lintcheck_crates.toml",
245
293
only_one_crate
246
294
);
247
295
std::process::exit(1);
248
- }
296
+ } */ //@FIXME
249
297
250
298
// only check a single crate that was passed via cmdline
251
299
crates
0 commit comments