1
1
use std:: collections:: HashMap ;
2
2
use std:: io:: prelude:: * ;
3
- use std:: fs:: { File , OpenOptions } ;
3
+ use std:: fs:: File ;
4
4
use std:: path:: Path ;
5
5
6
6
use rustc_serialize:: json;
7
7
8
8
use core:: dependency:: { Dependency , DependencyInner , Kind } ;
9
9
use core:: { SourceId , Summary , PackageId , Registry } ;
10
10
use sources:: registry:: { RegistryPackage , RegistryDependency , INDEX_LOCK } ;
11
- use util:: { CargoResult , ChainError , internal, Filesystem , human , Config } ;
11
+ use util:: { CargoResult , ChainError , internal, Filesystem , Config } ;
12
12
13
13
pub struct RegistryIndex < ' cfg > {
14
14
source_id : SourceId ,
15
15
path : Filesystem ,
16
16
cache : HashMap < String , Vec < ( Summary , bool ) > > ,
17
17
hashes : HashMap < ( String , String ) , String > , // (name, vers) => cksum
18
18
config : & ' cfg Config ,
19
+ locked : bool ,
19
20
}
20
21
21
22
impl < ' cfg > RegistryIndex < ' cfg > {
22
23
pub fn new ( id : & SourceId ,
23
24
path : & Filesystem ,
24
- config : & ' cfg Config ) -> RegistryIndex < ' cfg > {
25
+ config : & ' cfg Config ,
26
+ locked : bool ) -> RegistryIndex < ' cfg > {
25
27
RegistryIndex {
26
28
source_id : id. clone ( ) ,
27
29
path : path. clone ( ) ,
28
30
cache : HashMap :: new ( ) ,
29
31
hashes : HashMap :: new ( ) ,
30
32
config : config,
33
+ locked : locked,
31
34
}
32
35
}
33
36
@@ -52,53 +55,57 @@ impl<'cfg> RegistryIndex<'cfg> {
52
55
if self . cache . contains_key ( name) {
53
56
return Ok ( self . cache . get ( name) . unwrap ( ) ) ;
54
57
}
55
- // If the lock file doesn't already exist then this'll cause *someone*
56
- // to create it. We don't actually care who creates it, and if it's
57
- // already there this should have no effect.
58
- drop ( OpenOptions :: new ( )
59
- . write ( true )
60
- . create ( true )
61
- . open ( self . path . join ( INDEX_LOCK ) . into_path_unlocked ( ) ) ) ;
62
- let lock = self . path . open_ro ( Path :: new ( INDEX_LOCK ) ,
63
- self . config ,
64
- "the registry index" ) ;
65
- let file = lock. and_then ( |lock| {
66
- let path = lock. path ( ) . parent ( ) . unwrap ( ) ;
67
- let fs_name = name. chars ( ) . flat_map ( |c| {
68
- c. to_lowercase ( )
69
- } ) . collect :: < String > ( ) ;
70
-
71
- // see module comment for why this is structured the way it is
72
- let path = match fs_name. len ( ) {
73
- 1 => path. join ( "1" ) . join ( & fs_name) ,
74
- 2 => path. join ( "2" ) . join ( & fs_name) ,
75
- 3 => path. join ( "3" ) . join ( & fs_name[ ..1 ] ) . join ( & fs_name) ,
76
- _ => path. join ( & fs_name[ 0 ..2 ] )
77
- . join ( & fs_name[ 2 ..4 ] )
78
- . join ( & fs_name) ,
79
- } ;
80
- File :: open ( & path) . map_err ( human)
81
- } ) ;
82
- let summaries = match file {
58
+ let summaries = try!( self . load_summaries ( name) ) ;
59
+ let summaries = summaries. into_iter ( ) . filter ( |summary| {
60
+ summary. 0 . package_id ( ) . name ( ) == name
61
+ } ) . collect ( ) ;
62
+ self . cache . insert ( name. to_string ( ) , summaries) ;
63
+ Ok ( self . cache . get ( name) . unwrap ( ) )
64
+ }
65
+
66
+ fn load_summaries ( & mut self , name : & str ) -> CargoResult < Vec < ( Summary , bool ) > > {
67
+ let ( path, _lock) = if self . locked {
68
+ let lock = self . path . open_ro ( Path :: new ( INDEX_LOCK ) ,
69
+ self . config ,
70
+ "the registry index" ) ;
71
+ match lock {
72
+ Ok ( lock) => {
73
+ ( lock. path ( ) . parent ( ) . unwrap ( ) . to_path_buf ( ) , Some ( lock) )
74
+ }
75
+ Err ( _) => return Ok ( Vec :: new ( ) ) ,
76
+ }
77
+ } else {
78
+ ( self . path . clone ( ) . into_path_unlocked ( ) , None )
79
+ } ;
80
+
81
+ let fs_name = name. chars ( ) . flat_map ( |c| {
82
+ c. to_lowercase ( )
83
+ } ) . collect :: < String > ( ) ;
84
+
85
+ // see module comment for why this is structured the way it is
86
+ let path = match fs_name. len ( ) {
87
+ 1 => path. join ( "1" ) . join ( & fs_name) ,
88
+ 2 => path. join ( "2" ) . join ( & fs_name) ,
89
+ 3 => path. join ( "3" ) . join ( & fs_name[ ..1 ] ) . join ( & fs_name) ,
90
+ _ => path. join ( & fs_name[ 0 ..2 ] )
91
+ . join ( & fs_name[ 2 ..4 ] )
92
+ . join ( & fs_name) ,
93
+ } ;
94
+ match File :: open ( & path) {
83
95
Ok ( mut f) => {
84
96
let mut contents = String :: new ( ) ;
85
97
try!( f. read_to_string ( & mut contents) ) ;
86
98
let ret: CargoResult < Vec < ( Summary , bool ) > > ;
87
99
ret = contents. lines ( ) . filter ( |l| l. trim ( ) . len ( ) > 0 )
88
100
. map ( |l| self . parse_registry_package ( l) )
89
101
. collect ( ) ;
90
- try! ( ret. chain_error ( || {
102
+ ret. chain_error ( || {
91
103
internal ( format ! ( "failed to parse registry's information \
92
104
for: {}", name) )
93
- } ) )
105
+ } )
94
106
}
95
- Err ( ..) => Vec :: new ( ) ,
96
- } ;
97
- let summaries = summaries. into_iter ( ) . filter ( |summary| {
98
- summary. 0 . package_id ( ) . name ( ) == name
99
- } ) . collect ( ) ;
100
- self . cache . insert ( name. to_string ( ) , summaries) ;
101
- Ok ( self . cache . get ( name) . unwrap ( ) )
107
+ Err ( ..) => Ok ( Vec :: new ( ) ) ,
108
+ }
102
109
}
103
110
104
111
/// Parse a line from the registry's index file into a Summary for a
0 commit comments