@@ -36,10 +36,14 @@ type package = {
36
36
type source = {
37
37
name : str ,
38
38
url : str ,
39
+ sig : option:: t < str > ,
40
+ key : option:: t < str > ,
41
+ keyfp : option:: t < str > ,
39
42
mutable packages: [ package ]
40
43
} ;
41
44
42
45
type cargo = {
46
+ pgp : bool ,
43
47
root : str ,
44
48
bindir : str ,
45
49
libdir : str ,
@@ -158,12 +162,32 @@ fn need_dir(s: str) {
158
162
fn parse_source ( name : str , j : json:: json ) -> source {
159
163
alt j {
160
164
json : : dict ( _j) {
161
- alt _j. find ( "url" ) {
165
+ let url = alt _j. find ( "url" ) {
162
166
some ( json:: string ( u) ) {
163
- ret { name : name , url : u , mutable packages : [ ] } ;
167
+ u
164
168
}
165
169
_ { fail "Needed 'url' field in source." ; }
166
170
} ;
171
+ let sig = alt _j. find ( "sig" ) {
172
+ some ( json:: string ( u) ) {
173
+ some ( u)
174
+ }
175
+ _ { none }
176
+ } ;
177
+ let key = alt _j. find ( "key" ) {
178
+ some ( json:: string ( u) ) {
179
+ some ( u)
180
+ }
181
+ _ { none }
182
+ } ;
183
+ let keyfp = alt _j. find ( "keyfp" ) {
184
+ some ( json:: string ( u) ) {
185
+ some ( u)
186
+ }
187
+ _ { none }
188
+ } ;
189
+ ret { name : name, url : url, sig : sig, key : key, keyfp : keyfp,
190
+ mutable packages : [ ] } ;
167
191
}
168
192
_ { fail "Needed dict value in source." ; }
169
193
} ;
@@ -269,6 +293,7 @@ fn configure() -> cargo {
269
293
try_parse_sources ( fs:: connect ( p, "sources.json" ) , sources) ;
270
294
try_parse_sources ( fs:: connect ( p, "local-sources.json" ) , sources) ;
271
295
let c = {
296
+ pgp: pgp:: supported ( ) ,
272
297
root: p,
273
298
bindir: fs:: connect ( p, "bin" ) ,
274
299
libdir: fs:: connect ( p, "lib" ) ,
@@ -289,6 +314,10 @@ fn configure() -> cargo {
289
314
sources. insert ( k, s) ;
290
315
} ;
291
316
317
+ if c. pgp {
318
+ pgp:: init ( c. root ) ;
319
+ }
320
+
292
321
c
293
322
}
294
323
@@ -501,7 +530,10 @@ fn cmd_install(c: cargo, argv: [str]) {
501
530
502
531
fn sync_one ( c : cargo , name : str , src : source ) {
503
532
let dir = fs:: connect ( c. sourcedir , name) ;
504
- let pkgfile = fs:: connect ( dir, "packages.json" ) ;
533
+ let pkgfile = fs:: connect ( dir, "packages.json.new" ) ;
534
+ let destpkgfile = fs:: connect ( dir, "packages.json" ) ;
535
+ let sigfile = fs:: connect ( dir, "packages.json.sig" ) ;
536
+ let keyfile = fs:: connect ( dir, "key.gpg" ) ;
505
537
let url = src. url ;
506
538
need_dir ( dir) ;
507
539
info ( #fmt[ "fetching source %s..." , name] ) ;
@@ -511,6 +543,40 @@ fn sync_one(c: cargo, name: str, src: source) {
511
543
} else {
512
544
info ( #fmt[ "fetched source: %s" , name] ) ;
513
545
}
546
+ alt src. sig {
547
+ some ( u) {
548
+ let p = run:: program_output ( "curl" , [ "-f" , "-s" , "-o" , sigfile, u] ) ;
549
+ if p. status != 0 {
550
+ warn ( #fmt[ "fetch for source %s (sig %s) failed" , name, u] ) ;
551
+ }
552
+ }
553
+ _ { }
554
+ }
555
+ alt src. key {
556
+ some ( u) {
557
+ let p = run:: program_output ( "curl" , [ "-f" , "-s" , "-o" , keyfile, u] ) ;
558
+ if p. status != 0 {
559
+ warn ( #fmt[ "fetch for source %s (key %s) failed" , name, u] ) ;
560
+ }
561
+ pgp:: add ( c. root , keyfile) ;
562
+ }
563
+ _ { }
564
+ }
565
+ alt ( src. sig , src. key , src. keyfp ) {
566
+ ( some ( _) , some ( _) , some ( f) ) {
567
+ let r = pgp:: verify ( c. root , pkgfile, sigfile, f) ;
568
+ if !r {
569
+ warn ( #fmt[ "signature verification failed for source %s" , name] ) ;
570
+ ret;
571
+ } else {
572
+ info ( #fmt[ "signature ok for source %s" , name] ) ;
573
+ }
574
+ }
575
+ _ {
576
+ info( #fmt[ "no signature for source %s" , name] ) ;
577
+ }
578
+ }
579
+ run:: run_program ( "cp" , [ pkgfile, destpkgfile] ) ;
514
580
}
515
581
516
582
fn cmd_sync ( c : cargo , argv : [ str ] ) {
@@ -523,8 +589,38 @@ fn cmd_sync(c: cargo, argv: [str]) {
523
589
}
524
590
}
525
591
592
+ fn cmd_init ( c : cargo , argv : [ str ] ) {
593
+ let srcurl = "http://www.rust-lang.org/cargo/sources.json" ;
594
+ let sigurl = "http://www.rust-lang.org/cargo/sources.json.sig" ;
595
+
596
+ let srcfile = fs:: connect ( c. root , "sources.json.new" ) ;
597
+ let sigfile = fs:: connect ( c. root , "sources.json.sig" ) ;
598
+ let destsrcfile = fs:: connect ( c. root , "sources.json" ) ;
599
+
600
+ let p = run:: program_output ( "curl" , [ "-f" , "-s" , "-o" , srcfile, srcurl] ) ;
601
+ if p. status != 0 {
602
+ warn ( #fmt[ "fetch of sources.json failed: %s" , p. out ] ) ;
603
+ ret;
604
+ }
605
+
606
+ let p = run:: program_output ( "curl" , [ "-f" , "-s" , "-o" , sigfile, sigurl] ) ;
607
+ if p. status != 0 {
608
+ warn ( #fmt[ "fetch of sources.json.sig failed: %s" , p. out ] ) ;
609
+ ret;
610
+ }
611
+
612
+ let r = pgp:: verify ( c. root , srcfile, sigfile, pgp:: signing_key_fp ( ) ) ;
613
+ if !r {
614
+ warn ( #fmt[ "signature verification failed for sources.json" ] ) ;
615
+ ret;
616
+ }
617
+ info ( #fmt[ "signature ok for sources.json" ] ) ;
618
+ run:: run_program ( "cp" , [ srcfile, destsrcfile] ) ;
619
+ }
620
+
526
621
fn cmd_usage ( ) {
527
622
print ( "Usage: cargo <verb> [args...]" ) ;
623
+ print ( " init Fetch default sources.json" ) ;
528
624
print ( " install [source/]package-name Install by name" ) ;
529
625
print ( " install uuid:[source/]package-uuid Install by uuid" ) ;
530
626
print ( " sync Sync all sources" ) ;
@@ -538,6 +634,7 @@ fn main(argv: [str]) {
538
634
}
539
635
let c = configure ( ) ;
540
636
alt argv[ 1 ] {
637
+ "init" { cmd_init ( c, argv) ; }
541
638
"install" { cmd_install ( c, argv) ; }
542
639
"sync" { cmd_sync ( c, argv) ; }
543
640
"usage" { cmd_usage ( ) ; }
0 commit comments