2
2
3
3
4
4
use super :: DocBuilder ;
5
- use rustc_serialize:: json:: Json ;
6
- use git2 ;
5
+ use rustc_serialize:: json:: { Json , Array } ;
6
+ use hyper ;
7
7
use db:: connect_db;
8
8
use errors:: * ;
9
9
10
10
11
11
impl DocBuilder {
12
12
/// Updates crates.io-index repository and adds new crates into build queue
13
- pub fn get_new_crates ( & self ) -> Result < ( ) > {
14
-
15
- let repo = try!( git2:: Repository :: open ( & self . options . crates_io_index_path ) ) ;
16
-
17
- let old_tree = try!( self . head_tree ( & repo) ) ;
18
- try!( self . update_repo ( & repo) ) ;
19
- let new_tree = try!( self . head_tree ( & repo) ) ;
20
-
21
- let diff = try!( repo. diff_tree_to_tree ( Some ( & old_tree) , Some ( & new_tree) , None ) ) ;
22
- let conn = try!( connect_db ( ) ) ;
23
- let mut line_n = 0 ;
24
-
25
- try!( diff. print ( git2:: DiffFormat :: Patch , |_, hunk, diffline| -> bool {
26
- let line = String :: from_utf8_lossy ( diffline. content ( ) ) . into_owned ( ) ;
27
- // crate strings starts with '{'
28
- // skip if line is not a crate string
29
- if line. chars ( ) . nth ( 0 ) != Some ( '{' ) {
30
- line_n = 0 ;
31
- return true ;
32
- }
33
-
34
- line_n += 1 ;
35
-
36
- if match hunk {
37
- Some ( hunk) => hunk. new_lines ( ) != line_n,
38
- None => true ,
39
- } {
40
- return true ;
41
- }
42
-
43
- let json = match Json :: from_str ( & line[ ..] ) {
44
- Ok ( j) => j,
45
- Err ( err) => {
46
- error ! ( "Failed to parse crate string: {}" , err) ;
47
- // just continue even if we get an error for a crate
48
- return true ;
13
+ pub fn get_new_crates ( & mut self ) -> Result < ( ) > {
14
+ try!( self . load_database_cache ( ) ) ;
15
+
16
+ let body = {
17
+ use std:: io:: Read ;
18
+ let client = hyper:: Client :: new ( ) ;
19
+ let mut res = try!( client. get ( "https://crates.io/summary" ) . send ( ) ) ;
20
+ let mut body = String :: new ( ) ;
21
+ try!( res. read_to_string ( & mut body) ) ;
22
+ body
23
+ } ;
24
+
25
+ let json = try!( Json :: from_str ( & body) ) ;
26
+
27
+ let crates = {
28
+ let mut crates: Vec < ( String , String ) > = Vec :: new ( ) ;
29
+ for section in [ "just_updated" , "new_crates" ] . iter ( ) {
30
+ match json. as_object ( )
31
+ . and_then ( |o| o. get ( & section[ ..] ) )
32
+ . and_then ( |j| j. as_array ( ) )
33
+ . map ( get_crates_from_array) {
34
+ Some ( mut c) => crates. append ( c. as_mut ( ) ) ,
35
+ None => continue ,
49
36
}
50
- } ;
51
-
52
- // check if a crate is yanked just in case
53
- if json. as_object ( )
54
- . and_then ( |obj| obj. get ( "yanked" ) )
55
- . and_then ( |y| y. as_boolean ( ) )
56
- . unwrap_or ( true ) {
57
- return true ;
58
37
}
38
+ crates
39
+ } ;
59
40
60
- if let Some ( ( krate, version) ) = json. as_object ( )
61
- . map ( |obj| {
62
- ( obj. get ( "name" )
63
- . and_then ( |n| n. as_string ( ) ) ,
64
- obj. get ( "vers" )
65
- . and_then ( |n| n. as_string ( ) ) )
66
- } ) {
67
-
68
- // Skip again if we can't get crate name and version
69
- if krate. is_none ( ) || version. is_none ( ) {
70
- return true ;
71
- }
72
-
73
- let _ = conn. execute ( "INSERT INTO queue (name, version) VALUES ($1, $2)" ,
74
- & [ & krate. unwrap ( ) , & version. unwrap ( ) ] ) ;
41
+ let conn = try!( connect_db ( ) ) ;
42
+ for ( name, version) in crates {
43
+ if self . db_cache . contains ( & format ! ( "{}-{}" , name, version) [ ..] ) {
44
+ continue ;
75
45
}
76
-
77
- true
78
- } ) ) ;
79
-
80
- Ok ( ( ) )
81
- }
82
-
83
-
84
- fn update_repo ( & self , repo : & git2:: Repository ) -> Result < ( ) > {
85
- let mut remote = try!( repo. find_remote ( "origin" ) ) ;
86
- try!( remote. fetch ( & [ "refs/heads/*:refs/remotes/origin/*" ] , None , None ) ) ;
87
-
88
- // checkout master
89
- try!( repo. refname_to_id ( "refs/remotes/origin/master" )
90
- . and_then ( |oid| repo. find_object ( oid, None ) )
91
- . and_then ( |object| repo. reset ( & object, git2:: ResetType :: Hard , None ) ) ) ;
46
+ let _ = conn. execute ( "INSERT INTO queue (name, version) VALUES ($1, $2)" ,
47
+ & [ & name, & version] ) ;
48
+ }
92
49
93
50
Ok ( ( ) )
94
51
}
95
52
96
53
97
- fn head_tree < ' a > ( & ' a self , repo : & ' a git2:: Repository ) -> Result < git2:: Tree > {
98
- repo. head ( )
99
- . ok ( )
100
- . and_then ( |head| head. target ( ) )
101
- . ok_or ( git2:: Error :: from_str ( "HEAD SHA1 not found" ) )
102
- . and_then ( |oid| repo. find_commit ( oid) )
103
- . and_then ( |commit| commit. tree ( ) )
104
- . or_else ( |e| Err ( ErrorKind :: Git2Error ( e) . into ( ) ) )
105
- }
106
-
107
-
108
54
/// Builds packages from queue
109
55
pub fn build_packages_queue ( & mut self ) -> Result < ( ) > {
110
56
let conn = try!( connect_db ( ) ) ;
@@ -117,7 +63,7 @@ impl DocBuilder {
117
63
match self . build_package ( & name[ ..] , & version[ ..] ) {
118
64
Ok ( _) => {
119
65
let _ = conn. execute ( "DELETE FROM queue WHERE id = $1" , & [ & id] ) ;
120
- } ,
66
+ }
121
67
Err ( e) => {
122
68
error ! ( "Failed to build package {}-{} from queue: {}" ,
123
69
name,
@@ -132,6 +78,29 @@ impl DocBuilder {
132
78
}
133
79
134
80
81
+ /// Returns Vec<CRATE_NAME, CRATE_VERSION> from a summary array
82
+ fn get_crates_from_array < ' a > ( crates : & ' a Array ) -> Vec < ( String , String ) > {
83
+ let mut crates_vec: Vec < ( String , String ) > = Vec :: new ( ) ;
84
+ for crte in crates {
85
+ let name = match crte. as_object ( )
86
+ . and_then ( |o| o. get ( "id" ) )
87
+ . and_then ( |i| i. as_string ( ) )
88
+ . map ( |s| s. to_owned ( ) ) {
89
+ Some ( s) => s,
90
+ None => continue ,
91
+ } ;
92
+ let version = match crte. as_object ( )
93
+ . and_then ( |o| o. get ( "max_version" ) )
94
+ . and_then ( |v| v. as_string ( ) )
95
+ . map ( |s| s. to_owned ( ) ) {
96
+ Some ( s) => s,
97
+ None => continue ,
98
+ } ;
99
+ crates_vec. push ( ( name, version) ) ;
100
+ }
101
+ crates_vec
102
+ }
103
+
135
104
136
105
137
106
@@ -146,8 +115,12 @@ mod test {
146
115
fn test_get_new_crates ( ) {
147
116
let _ = env_logger:: init ( ) ;
148
117
let options = DocBuilderOptions :: from_prefix ( PathBuf :: from ( "../cratesfyi-prefix" ) ) ;
149
- let docbuilder = DocBuilder :: new ( options) ;
150
- assert ! ( docbuilder. get_new_crates( ) . is_ok( ) ) ;
118
+ let mut docbuilder = DocBuilder :: new ( options) ;
119
+ let res = docbuilder. get_new_crates ( ) ;
120
+ if res. is_err ( ) {
121
+ error ! ( "{:?}" , res) ;
122
+ }
123
+ assert ! ( res. is_ok( ) ) ;
151
124
}
152
125
153
126
0 commit comments