Hex Artifact Content

Artifact d941737404b18ef955fc2625fbfa55458f8b6f14:


0000: 23 21 20 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20  #! /usr/bin/env 
0010: 74 63 6c 73 68 0a 0a 70 61 63 6b 61 67 65 20 72  tclsh..package r
0020: 65 71 75 69 72 65 20 68 74 74 70 20 32 2e 37 0a  equire http 2.7.
0030: 70 61 63 6b 61 67 65 20 72 65 71 75 69 72 65 20  package require 
0040: 73 71 6c 69 74 65 33 0a 0a 69 66 20 7b 5b 63 61  sqlite3..if {[ca
0050: 74 63 68 20 7b 0a 09 70 61 63 6b 61 67 65 20 72  tch {..package r
0060: 65 71 75 69 72 65 20 73 68 61 31 0a 7d 5d 7d 20  equire sha1.}]} 
0070: 7b 0a 09 40 40 53 48 41 31 2e 54 43 4c 40 40 0a  {..@@SHA1.TCL@@.
0080: 09 70 61 63 6b 61 67 65 20 72 65 71 75 69 72 65  .package require
0090: 20 73 68 61 31 0a 7d 0a 0a 6e 61 6d 65 73 70 61   sha1.}..namespa
00a0: 63 65 20 65 76 61 6c 20 3a 3a 61 70 70 66 73 20  ce eval ::appfs 
00b0: 7b 0a 09 76 61 72 69 61 62 6c 65 20 63 61 63 68  {..variable cach
00c0: 65 64 69 72 20 22 2f 74 6d 70 2f 61 70 70 66 73  edir "/tmp/appfs
00d0: 2d 63 61 63 68 65 22 0a 09 76 61 72 69 61 62 6c  -cache"..variabl
00e0: 65 20 74 74 6c 20 33 36 30 30 0a 09 76 61 72 69  e ttl 3600..vari
00f0: 61 62 6c 65 20 6e 74 74 6c 20 36 30 0a 0a 09 70  able nttl 60...p
0100: 72 6f 63 20 5f 68 61 73 68 5f 73 65 70 20 7b 68  roc _hash_sep {h
0110: 61 73 68 20 7b 73 65 70 73 20 34 7d 7d 20 7b 0a  ash {seps 4}} {.
0120: 09 09 66 6f 72 20 7b 73 65 74 20 69 64 78 20 30  ..for {set idx 0
0130: 7d 20 7b 24 69 64 78 20 3c 20 24 73 65 70 73 7d  } {$idx < $seps}
0140: 20 7b 69 6e 63 72 20 69 64 78 7d 20 7b 0a 09 09   {incr idx} {...
0150: 09 61 70 70 65 6e 64 20 72 65 74 76 61 6c 20 22  .append retval "
0160: 5b 73 74 72 69 6e 67 20 72 61 6e 67 65 20 24 68  [string range $h
0170: 61 73 68 20 5b 65 78 70 72 20 7b 24 69 64 78 20  ash [expr {$idx 
0180: 2a 20 32 7d 5d 20 5b 65 78 70 72 20 7b 28 24 69  * 2}] [expr {($i
0190: 64 78 20 2a 20 32 29 20 2b 20 31 7d 5d 5d 2f 22  dx * 2) + 1}]]/"
01a0: 0a 09 09 7d 0a 09 09 61 70 70 65 6e 64 20 72 65  ...}...append re
01b0: 74 76 61 6c 20 22 5b 73 74 72 69 6e 67 20 72 61  tval "[string ra
01c0: 6e 67 65 20 24 68 61 73 68 20 5b 65 78 70 72 20  nge $hash [expr 
01d0: 7b 24 69 64 78 20 2a 20 32 7d 5d 20 65 6e 64 5d  {$idx * 2}] end]
01e0: 22 0a 0a 09 09 72 65 74 75 72 6e 20 24 72 65 74  "....return $ret
01f0: 76 61 6c 0a 09 7d 0a 0a 09 70 72 6f 63 20 5f 63  val..}...proc _c
0200: 61 63 68 65 66 69 6c 65 20 7b 75 72 6c 20 6b 65  achefile {url ke
0210: 79 20 7b 6b 65 79 49 73 48 61 73 68 20 31 7d 7d  y {keyIsHash 1}}
0220: 20 7b 0a 09 09 73 65 74 20 66 69 6c 65 6b 65 79   {...set filekey
0230: 20 24 6b 65 79 0a 09 09 69 66 20 7b 24 6b 65 79   $key...if {$key
0240: 49 73 48 61 73 68 7d 20 7b 0a 09 09 09 73 65 74  IsHash} {....set
0250: 20 66 69 6c 65 6b 65 79 20 5b 5f 68 61 73 68 5f   filekey [_hash_
0260: 73 65 70 20 24 66 69 6c 65 6b 65 79 5d 0a 09 09  sep $filekey]...
0270: 7d 0a 0a 09 09 73 65 74 20 66 69 6c 65 20 5b 66  }....set file [f
0280: 69 6c 65 20 6a 6f 69 6e 20 24 3a 3a 61 70 70 66  ile join $::appf
0290: 73 3a 3a 63 61 63 68 65 64 69 72 20 24 66 69 6c  s::cachedir $fil
02a0: 65 6b 65 79 5d 0a 0a 09 09 66 69 6c 65 20 6d 6b  ekey]....file mk
02b0: 64 69 72 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d  dir [file dirnam
02c0: 65 20 24 66 69 6c 65 5d 0a 0a 09 09 69 66 20 7b  e $file]....if {
02d0: 21 5b 66 69 6c 65 20 65 78 69 73 74 73 20 24 66  ![file exists $f
02e0: 69 6c 65 5d 7d 20 7b 0a 09 09 09 73 65 74 20 74  ile]} {....set t
02f0: 6d 70 66 69 6c 65 20 22 24 7b 66 69 6c 65 7d 2e  mpfile "${file}.
0300: 6e 65 77 22 0a 0a 09 09 09 73 65 74 20 66 64 20  new".....set fd 
0310: 5b 6f 70 65 6e 20 24 74 6d 70 66 69 6c 65 20 22  [open $tmpfile "
0320: 77 22 5d 0a 09 09 09 66 63 6f 6e 66 69 67 75 72  w"]....fconfigur
0330: 65 20 24 66 64 20 2d 74 72 61 6e 73 6c 61 74 69  e $fd -translati
0340: 6f 6e 20 62 69 6e 61 72 79 0a 0a 09 09 09 63 61  on binary.....ca
0350: 74 63 68 20 7b 0a 09 09 09 09 73 65 74 20 74 6f  tch {.....set to
0360: 6b 65 6e 20 5b 3a 3a 68 74 74 70 3a 3a 67 65 74  ken [::http::get
0370: 75 72 6c 20 24 75 72 6c 20 2d 63 68 61 6e 6e 65  url $url -channe
0380: 6c 20 24 66 64 20 2d 62 69 6e 61 72 79 20 74 72  l $fd -binary tr
0390: 75 65 5d 0a 09 09 09 7d 0a 0a 09 09 09 69 66 20  ue]....}.....if 
03a0: 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 74 6f  {[info exists to
03b0: 6b 65 6e 5d 7d 20 7b 0a 09 09 09 09 73 65 74 20  ken]} {.....set 
03c0: 6e 63 6f 64 65 20 5b 3a 3a 68 74 74 70 3a 3a 6e  ncode [::http::n
03d0: 63 6f 64 65 20 24 74 6f 6b 65 6e 5d 0a 09 09 09  code $token]....
03e0: 09 3a 3a 68 74 74 70 3a 3a 72 65 73 65 74 20 24  .::http::reset $
03f0: 74 6f 6b 65 6e 0a 09 09 09 7d 20 65 6c 73 65 20  token....} else 
0400: 7b 0a 09 09 09 09 73 65 74 20 6e 63 6f 64 65 20  {.....set ncode 
0410: 22 39 30 30 22 0a 09 09 09 7d 0a 0a 09 09 09 63  "900"....}.....c
0420: 6c 6f 73 65 20 24 66 64 0a 0a 09 09 09 69 66 20  lose $fd.....if 
0430: 7b 24 6b 65 79 49 73 48 61 73 68 7d 20 7b 0a 09  {$keyIsHash} {..
0440: 09 09 09 73 65 74 20 68 61 73 68 20 5b 73 74 72  ...set hash [str
0450: 69 6e 67 20 74 6f 6c 6f 77 65 72 20 5b 73 68 61  ing tolower [sha
0460: 31 3a 3a 73 68 61 31 20 2d 68 65 78 20 2d 66 69  1::sha1 -hex -fi
0470: 6c 65 20 24 74 6d 70 66 69 6c 65 5d 5d 0a 09 09  le $tmpfile]]...
0480: 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 73 65  .} else {.....se
0490: 74 20 68 61 73 68 20 24 6b 65 79 0a 09 09 09 7d  t hash $key....}
04a0: 0a 0a 09 09 09 69 66 20 7b 24 6e 63 6f 64 65 20  .....if {$ncode 
04b0: 3d 3d 20 22 32 30 30 22 20 26 26 20 24 68 61 73  == "200" && $has
04c0: 68 20 3d 3d 20 24 6b 65 79 7d 20 7b 0a 09 09 09  h == $key} {....
04d0: 09 66 69 6c 65 20 72 65 6e 61 6d 65 20 2d 66 6f  .file rename -fo
04e0: 72 63 65 20 2d 2d 20 24 74 6d 70 66 69 6c 65 20  rce -- $tmpfile 
04f0: 24 66 69 6c 65 0a 09 09 09 7d 20 65 6c 73 65 20  $file....} else 
0500: 7b 0a 09 09 09 09 66 69 6c 65 20 64 65 6c 65 74  {.....file delet
0510: 65 20 2d 66 6f 72 63 65 20 2d 2d 20 24 74 6d 70  e -force -- $tmp
0520: 66 69 6c 65 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09  file....}...}...
0530: 09 72 65 74 75 72 6e 20 24 66 69 6c 65 0a 09 7d  .return $file..}
0540: 0a 0a 0a 09 70 72 6f 63 20 5f 69 73 48 61 73 68  ....proc _isHash
0550: 20 7b 76 61 6c 75 65 7d 20 7b 0a 09 09 73 65 74   {value} {...set
0560: 20 76 61 6c 75 65 20 5b 73 74 72 69 6e 67 20 74   value [string t
0570: 6f 6c 6f 77 65 72 20 24 76 61 6c 75 65 5d 0a 0a  olower $value]..
0580: 09 09 69 66 20 7b 5b 73 74 72 69 6e 67 20 6c 65  ..if {[string le
0590: 6e 67 74 68 20 24 76 61 6c 75 65 5d 20 21 3d 20  ngth $value] != 
05a0: 34 30 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20  40} {....return 
05b0: 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09 69 66 20  false...}....if 
05c0: 7b 21 5b 72 65 67 65 78 70 20 7b 5e 5b 30 2d 39  {![regexp {^[0-9
05d0: 61 2d 66 5d 2a 24 7d 20 24 76 61 6c 75 65 5d 7d  a-f]*$} $value]}
05e0: 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 66 61 6c   {....return fal
05f0: 73 65 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e  se...}....return
0600: 20 74 72 75 65 0a 09 7d 0a 0a 09 70 72 6f 63 20   true..}...proc 
0610: 5f 64 62 20 7b 61 72 67 73 7d 20 7b 0a 09 09 72  _db {args} {...r
0620: 65 74 75 72 6e 20 5b 75 70 6c 65 76 65 6c 20 31  eturn [uplevel 1
0630: 20 5b 6c 69 73 74 20 3a 3a 61 70 70 66 73 3a 3a   [list ::appfs::
0640: 64 62 20 7b 2a 7d 24 61 72 67 73 5d 5d 0a 09 7d  db {*}$args]]..}
0650: 0a 0a 09 70 72 6f 63 20 5f 6e 6f 72 6d 61 6c 69  ...proc _normali
0660: 7a 65 4f 53 20 7b 6f 73 7d 20 7b 0a 09 09 73 65  zeOS {os} {...se
0670: 74 20 6f 73 20 5b 73 74 72 69 6e 67 20 74 6f 6c  t os [string tol
0680: 6f 77 65 72 20 5b 73 74 72 69 6e 67 20 74 72 69  ower [string tri
0690: 6d 20 24 6f 73 5d 5d 0a 0a 09 09 73 77 69 74 63  m $os]]....switc
06a0: 68 20 2d 2d 20 24 6f 73 20 7b 0a 09 09 09 22 6c  h -- $os {...."l
06b0: 69 6e 75 78 22 20 2d 20 22 66 72 65 65 62 73 64  inux" - "freebsd
06c0: 22 20 2d 20 22 6f 70 65 6e 62 73 64 22 20 2d 20  " - "openbsd" - 
06d0: 22 6e 65 74 62 73 64 22 20 7b 0a 09 09 09 09 72  "netbsd" {.....r
06e0: 65 74 75 72 6e 20 24 6f 73 0a 09 09 09 7d 0a 09  eturn $os....}..
06f0: 09 09 22 73 75 6e 6f 73 22 20 7b 0a 09 09 09 09  .."sunos" {.....
0700: 72 65 74 75 72 6e 20 22 73 6f 6c 61 72 69 73 22  return "solaris"
0710: 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74  ....}...}....ret
0720: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20  urn -code error 
0730: 22 55 6e 61 62 6c 65 20 74 6f 20 6e 6f 72 6d 61  "Unable to norma
0740: 6c 69 7a 65 20 4f 53 3a 20 24 6f 73 22 0a 09 7d  lize OS: $os"..}
0750: 0a 0a 09 70 72 6f 63 20 5f 6e 6f 72 6d 61 6c 69  ...proc _normali
0760: 7a 65 43 50 55 20 7b 63 70 75 7d 20 7b 0a 09 09  zeCPU {cpu} {...
0770: 73 65 74 20 63 70 75 20 5b 73 74 72 69 6e 67 20  set cpu [string 
0780: 74 6f 6c 6f 77 65 72 20 5b 73 74 72 69 6e 67 20  tolower [string 
0790: 74 72 69 6d 20 24 63 70 75 5d 5d 0a 0a 09 09 73  trim $cpu]]....s
07a0: 77 69 74 63 68 20 2d 67 6c 6f 62 20 2d 2d 20 24  witch -glob -- $
07b0: 63 70 75 20 7b 0a 09 09 09 22 69 3f 38 36 22 20  cpu {...."i?86" 
07c0: 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 22 69 78  {.....return "ix
07d0: 38 36 22 0a 09 09 09 7d 0a 09 09 09 22 78 38 36  86"....}...."x86
07e0: 5f 36 34 22 20 7b 0a 09 09 09 09 72 65 74 75 72  _64" {.....retur
07f0: 6e 20 24 63 70 75 0a 09 09 09 7d 0a 09 09 7d 0a  n $cpu....}...}.
0800: 0a 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20  ...return -code 
0810: 65 72 72 6f 72 20 22 55 6e 61 62 6c 65 20 74 6f  error "Unable to
0820: 20 6e 6f 72 6d 61 6c 69 7a 65 20 43 50 55 3a 20   normalize CPU: 
0830: 24 63 70 75 22 0a 09 7d 0a 0a 09 70 72 6f 63 20  $cpu"..}...proc 
0840: 69 6e 69 74 20 7b 7d 20 7b 0a 09 09 69 66 20 7b  init {} {...if {
0850: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 3a 3a 61  [info exists ::a
0860: 70 70 66 73 3a 3a 69 6e 69 74 5f 63 61 6c 6c 65  ppfs::init_calle
0870: 64 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 0a  d]} {....return.
0880: 09 09 7d 0a 0a 09 09 73 65 74 20 3a 3a 61 70 70  ..}....set ::app
0890: 66 73 3a 3a 69 6e 69 74 5f 63 61 6c 6c 65 64 20  fs::init_called 
08a0: 31 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f 20  1....if {![info 
08b0: 65 78 69 73 74 73 20 3a 3a 61 70 70 66 73 3a 3a  exists ::appfs::
08c0: 64 62 5d 7d 20 7b 0a 09 09 09 66 69 6c 65 20 6d  db]} {....file m
08d0: 6b 64 69 72 20 24 3a 3a 61 70 70 66 73 3a 3a 63  kdir $::appfs::c
08e0: 61 63 68 65 64 69 72 0a 0a 09 09 09 73 71 6c 69  achedir.....sqli
08f0: 74 65 33 20 3a 3a 61 70 70 66 73 3a 3a 64 62 20  te3 ::appfs::db 
0900: 5b 66 69 6c 65 20 6a 6f 69 6e 20 24 3a 3a 61 70  [file join $::ap
0910: 70 66 73 3a 3a 63 61 63 68 65 64 69 72 20 63 61  pfs::cachedir ca
0920: 63 68 65 2e 64 62 5d 0a 09 09 7d 0a 0a 09 09 23  che.db]...}....#
0930: 20 43 72 65 61 74 65 20 74 61 62 6c 65 73 0a 09   Create tables..
0940: 09 5f 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54  ._db eval {CREAT
0950: 45 20 54 41 42 4c 45 20 49 46 20 4e 4f 54 20 45  E TABLE IF NOT E
0960: 58 49 53 54 53 20 73 69 74 65 73 28 68 6f 73 74  XISTS sites(host
0970: 6e 61 6d 65 20 50 52 49 4d 41 52 59 20 4b 45 59  name PRIMARY KEY
0980: 2c 20 6c 61 73 74 55 70 64 61 74 65 2c 20 74 74  , lastUpdate, tt
0990: 6c 29 3b 7d 0a 09 09 5f 64 62 20 65 76 61 6c 20  l);}..._db eval 
09a0: 7b 43 52 45 41 54 45 20 54 41 42 4c 45 20 49 46  {CREATE TABLE IF
09b0: 20 4e 4f 54 20 45 58 49 53 54 53 20 70 61 63 6b   NOT EXISTS pack
09c0: 61 67 65 73 28 68 6f 73 74 6e 61 6d 65 2c 20 73  ages(hostname, s
09d0: 68 61 31 2c 20 70 61 63 6b 61 67 65 2c 20 76 65  ha1, package, ve
09e0: 72 73 69 6f 6e 2c 20 6f 73 2c 20 63 70 75 41 72  rsion, os, cpuAr
09f0: 63 68 2c 20 69 73 4c 61 74 65 73 74 2c 20 68 61  ch, isLatest, ha
0a00: 76 65 4d 61 6e 69 66 65 73 74 29 3b 7d 0a 09 09  veManifest);}...
0a10: 5f 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54 45  _db eval {CREATE
0a20: 20 54 41 42 4c 45 20 49 46 20 4e 4f 54 20 45 58   TABLE IF NOT EX
0a30: 49 53 54 53 20 66 69 6c 65 73 28 70 61 63 6b 61  ISTS files(packa
0a40: 67 65 5f 73 68 61 31 2c 20 74 79 70 65 2c 20 74  ge_sha1, type, t
0a50: 69 6d 65 2c 20 73 6f 75 72 63 65 2c 20 73 69 7a  ime, source, siz
0a60: 65 2c 20 70 65 72 6d 73 2c 20 66 69 6c 65 5f 73  e, perms, file_s
0a70: 68 61 31 2c 20 66 69 6c 65 5f 6e 61 6d 65 2c 20  ha1, file_name, 
0a80: 66 69 6c 65 5f 64 69 72 65 63 74 6f 72 79 29 3b  file_directory);
0a90: 7d 0a 0a 09 09 23 20 43 72 65 61 74 65 20 69 6e  }....# Create in
0aa0: 64 65 78 65 73 0a 09 09 5f 64 62 20 65 76 61 6c  dexes..._db eval
0ab0: 20 7b 43 52 45 41 54 45 20 49 4e 44 45 58 20 49   {CREATE INDEX I
0ac0: 46 20 4e 4f 54 20 45 58 49 53 54 53 20 73 69 74  F NOT EXISTS sit
0ad0: 65 73 5f 69 6e 64 65 78 20 4f 4e 20 73 69 74 65  es_index ON site
0ae0: 73 20 28 68 6f 73 74 6e 61 6d 65 29 3b 7d 0a 09  s (hostname);}..
0af0: 09 5f 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54  ._db eval {CREAT
0b00: 45 20 49 4e 44 45 58 20 49 46 20 4e 4f 54 20 45  E INDEX IF NOT E
0b10: 58 49 53 54 53 20 70 61 63 6b 61 67 65 73 5f 69  XISTS packages_i
0b20: 6e 64 65 78 20 4f 4e 20 70 61 63 6b 61 67 65 73  ndex ON packages
0b30: 20 28 68 6f 73 74 6e 61 6d 65 2c 20 70 61 63 6b   (hostname, pack
0b40: 61 67 65 2c 20 76 65 72 73 69 6f 6e 2c 20 6f 73  age, version, os
0b50: 2c 20 63 70 75 41 72 63 68 29 3b 7d 0a 09 09 5f  , cpuArch);}..._
0b60: 64 62 20 65 76 61 6c 20 7b 43 52 45 41 54 45 20  db eval {CREATE 
0b70: 49 4e 44 45 58 20 49 46 20 4e 4f 54 20 45 58 49  INDEX IF NOT EXI
0b80: 53 54 53 20 66 69 6c 65 73 5f 69 6e 64 65 78 20  STS files_index 
0b90: 4f 4e 20 66 69 6c 65 73 20 28 70 61 63 6b 61 67  ON files (packag
0ba0: 65 5f 73 68 61 31 2c 20 66 69 6c 65 5f 6e 61 6d  e_sha1, file_nam
0bb0: 65 2c 20 66 69 6c 65 5f 64 69 72 65 63 74 6f 72  e, file_director
0bc0: 79 29 3b 7d 0a 09 7d 0a 0a 09 70 72 6f 63 20 64  y);}..}...proc d
0bd0: 6f 77 6e 6c 6f 61 64 20 7b 68 6f 73 74 6e 61 6d  ownload {hostnam
0be0: 65 20 68 61 73 68 20 7b 6d 65 74 68 6f 64 20 73  e hash {method s
0bf0: 68 61 31 7d 7d 20 7b 0a 09 09 73 65 74 20 75 72  ha1}} {...set ur
0c00: 6c 20 22 68 74 74 70 3a 2f 2f 24 68 6f 73 74 6e  l "http://$hostn
0c10: 61 6d 65 2f 61 70 70 66 73 2f 24 6d 65 74 68 6f  ame/appfs/$metho
0c20: 64 2f 24 68 61 73 68 22 0a 09 09 73 65 74 20 66  d/$hash"...set f
0c30: 69 6c 65 20 5b 5f 63 61 63 68 65 66 69 6c 65 20  ile [_cachefile 
0c40: 24 75 72 6c 20 24 68 61 73 68 5d 0a 0a 09 09 69  $url $hash]....i
0c50: 66 20 7b 21 5b 66 69 6c 65 20 65 78 69 73 74 73  f {![file exists
0c60: 20 24 66 69 6c 65 5d 7d 20 7b 0a 09 09 09 72 65   $file]} {....re
0c70: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72  turn -code error
0c80: 20 22 55 6e 61 62 6c 65 20 74 6f 20 66 65 74 63   "Unable to fetc
0c90: 68 22 0a 09 09 7d 0a 0a 09 09 72 65 74 75 72 6e  h"...}....return
0ca0: 20 24 66 69 6c 65 0a 09 7d 0a 0a 09 70 72 6f 63   $file..}...proc
0cb0: 20 67 65 74 69 6e 64 65 78 20 7b 68 6f 73 74 6e   getindex {hostn
0cc0: 61 6d 65 7d 20 7b 0a 09 09 73 65 74 20 6e 6f 77  ame} {...set now
0cd0: 20 5b 63 6c 6f 63 6b 20 73 65 63 6f 6e 64 73 5d   [clock seconds]
0ce0: 0a 0a 09 09 73 65 74 20 6c 61 73 74 55 70 64 61  ....set lastUpda
0cf0: 74 65 73 20 5b 5f 64 62 20 65 76 61 6c 20 7b 53  tes [_db eval {S
0d00: 45 4c 45 43 54 20 6c 61 73 74 55 70 64 61 74 65  ELECT lastUpdate
0d10: 2c 20 74 74 6c 20 46 52 4f 4d 20 73 69 74 65 73  , ttl FROM sites
0d20: 20 57 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 20   WHERE hostname 
0d30: 3d 20 24 68 6f 73 74 6e 61 6d 65 20 4c 49 4d 49  = $hostname LIMI
0d40: 54 20 31 3b 7d 5d 0a 09 09 69 66 20 7b 5b 6c 6c  T 1;}]...if {[ll
0d50: 65 6e 67 74 68 20 24 6c 61 73 74 55 70 64 61 74  ength $lastUpdat
0d60: 65 73 5d 20 3d 3d 20 30 7d 20 7b 0a 09 09 09 73  es] == 0} {....s
0d70: 65 74 20 6c 61 73 74 55 70 64 61 74 65 20 30 0a  et lastUpdate 0.
0d80: 09 09 09 73 65 74 20 74 74 6c 20 30 0a 09 09 7d  ...set ttl 0...}
0d90: 20 65 6c 73 65 20 7b 0a 09 09 09 73 65 74 20 6c   else {....set l
0da0: 61 73 74 55 70 64 61 74 65 20 5b 6c 69 6e 64 65  astUpdate [linde
0db0: 78 20 24 6c 61 73 74 55 70 64 61 74 65 73 20 30  x $lastUpdates 0
0dc0: 5d 0a 09 09 09 73 65 74 20 74 74 6c 20 5b 6c 69  ]....set ttl [li
0dd0: 6e 64 65 78 20 24 6c 61 73 74 55 70 64 61 74 65  ndex $lastUpdate
0de0: 73 20 31 5d 0a 09 09 7d 0a 0a 09 09 69 66 20 7b  s 1]...}....if {
0df0: 24 6e 6f 77 20 3c 20 28 24 6c 61 73 74 55 70 64  $now < ($lastUpd
0e00: 61 74 65 20 2b 20 24 74 74 6c 29 7d 20 7b 0a 09  ate + $ttl)} {..
0e10: 09 09 72 65 74 75 72 6e 20 43 4f 4d 50 4c 45 54  ..return COMPLET
0e20: 45 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 5b 73 74  E...}....if {[st
0e30: 72 69 6e 67 20 6d 61 74 63 68 20 22 2a 5c 5b 2f  ring match "*\[/
0e40: 7e 5c 5d 2a 22 20 24 68 6f 73 74 6e 61 6d 65 5d  ~\]*" $hostname]
0e50: 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 2d 63  } {....return -c
0e60: 6f 64 65 20 65 72 72 6f 72 20 22 49 6e 76 61 6c  ode error "Inval
0e70: 69 64 20 68 6f 73 74 6e 61 6d 65 22 0a 09 09 7d  id hostname"...}
0e80: 0a 0a 09 09 73 65 74 20 75 72 6c 20 22 68 74 74  ....set url "htt
0e90: 70 3a 2f 2f 24 68 6f 73 74 6e 61 6d 65 2f 61 70  p://$hostname/ap
0ea0: 70 66 73 2f 69 6e 64 65 78 22 0a 0a 09 09 63 61  pfs/index"....ca
0eb0: 74 63 68 20 7b 0a 09 09 09 73 65 74 20 74 6f 6b  tch {....set tok
0ec0: 65 6e 20 5b 3a 3a 68 74 74 70 3a 3a 67 65 74 75  en [::http::getu
0ed0: 72 6c 20 24 75 72 6c 5d 0a 09 09 09 69 66 20 7b  rl $url]....if {
0ee0: 5b 3a 3a 68 74 74 70 3a 3a 6e 63 6f 64 65 20 24  [::http::ncode $
0ef0: 74 6f 6b 65 6e 5d 20 3d 3d 20 22 32 30 30 22 7d  token] == "200"}
0f00: 20 7b 0a 09 09 09 09 73 65 74 20 69 6e 64 65 78   {.....set index
0f10: 68 61 73 68 5f 64 61 74 61 20 5b 3a 3a 68 74 74  hash_data [::htt
0f20: 70 3a 3a 64 61 74 61 20 24 74 6f 6b 65 6e 5d 0a  p::data $token].
0f30: 09 09 09 7d 0a 09 09 09 3a 3a 68 74 74 70 3a 3a  ...}....::http::
0f40: 72 65 73 65 74 20 24 74 6f 6b 65 6e 0a 09 09 09  reset $token....
0f50: 24 74 6f 6b 65 6e 20 63 6c 65 61 6e 75 70 0a 09  $token cleanup..
0f60: 09 7d 0a 0a 09 09 69 66 20 7b 21 5b 69 6e 66 6f  .}....if {![info
0f70: 20 65 78 69 73 74 73 20 69 6e 64 65 78 68 61 73   exists indexhas
0f80: 68 5f 64 61 74 61 5d 7d 20 7b 0a 09 09 09 23 20  h_data]} {....# 
0f90: 43 61 63 68 65 20 74 68 69 73 20 72 65 73 75 6c  Cache this resul
0fa0: 74 20 66 6f 72 20 36 30 20 73 65 63 6f 6e 64 73  t for 60 seconds
0fb0: 0a 09 09 09 5f 64 62 20 65 76 61 6c 20 7b 49 4e  ...._db eval {IN
0fc0: 53 45 52 54 20 4f 52 20 52 45 50 4c 41 43 45 20  SERT OR REPLACE 
0fd0: 49 4e 54 4f 20 73 69 74 65 73 20 28 68 6f 73 74  INTO sites (host
0fe0: 6e 61 6d 65 2c 20 6c 61 73 74 55 70 64 61 74 65  name, lastUpdate
0ff0: 2c 20 74 74 6c 29 20 56 41 4c 55 45 53 20 28 24  , ttl) VALUES ($
1000: 68 6f 73 74 6e 61 6d 65 2c 20 24 6e 6f 77 2c 20  hostname, $now, 
1010: 24 3a 3a 61 70 70 66 73 3a 3a 6e 74 74 6c 29 3b  $::appfs::nttl);
1020: 7d 0a 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f  }.....return -co
1030: 64 65 20 65 72 72 6f 72 20 22 55 6e 61 62 6c 65  de error "Unable
1040: 20 74 6f 20 66 65 74 63 68 20 24 75 72 6c 22 0a   to fetch $url".
1050: 09 09 7d 0a 0a 09 09 73 65 74 20 69 6e 64 65 78  ..}....set index
1060: 68 61 73 68 20 5b 6c 69 6e 64 65 78 20 5b 73 70  hash [lindex [sp
1070: 6c 69 74 20 24 69 6e 64 65 78 68 61 73 68 5f 64  lit $indexhash_d
1080: 61 74 61 20 22 2c 22 5d 20 30 5d 0a 0a 09 09 69  ata ","] 0]....i
1090: 66 20 7b 21 5b 5f 69 73 48 61 73 68 20 24 69 6e  f {![_isHash $in
10a0: 64 65 78 68 61 73 68 5d 7d 20 7b 0a 09 09 09 72  dexhash]} {....r
10b0: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f  eturn -code erro
10c0: 72 20 22 49 6e 76 61 6c 69 64 20 68 61 73 68 3a  r "Invalid hash:
10d0: 20 24 69 6e 64 65 78 68 61 73 68 22 0a 09 09 7d   $indexhash"...}
10e0: 0a 0a 09 09 73 65 74 20 66 69 6c 65 20 5b 64 6f  ....set file [do
10f0: 77 6e 6c 6f 61 64 20 24 68 6f 73 74 6e 61 6d 65  wnload $hostname
1100: 20 24 69 6e 64 65 78 68 61 73 68 5d 0a 09 09 73   $indexhash]...s
1110: 65 74 20 66 64 20 5b 6f 70 65 6e 20 24 66 69 6c  et fd [open $fil
1120: 65 5d 0a 09 09 73 65 74 20 64 61 74 61 20 5b 72  e]...set data [r
1130: 65 61 64 20 24 66 64 5d 0a 09 09 63 6c 6f 73 65  ead $fd]...close
1140: 20 24 66 64 0a 0a 09 09 73 65 74 20 63 75 72 72   $fd....set curr
1150: 5f 70 61 63 6b 61 67 65 73 20 5b 6c 69 73 74 5d  _packages [list]
1160: 0a 09 09 66 6f 72 65 61 63 68 20 6c 69 6e 65 20  ...foreach line 
1170: 5b 73 70 6c 69 74 20 24 64 61 74 61 20 22 5c 6e  [split $data "\n
1180: 22 5d 20 7b 0a 09 09 09 73 65 74 20 6c 69 6e 65  "] {....set line
1190: 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 24 6c   [string trim $l
11a0: 69 6e 65 5d 0a 0a 09 09 09 69 66 20 7b 5b 73 74  ine].....if {[st
11b0: 72 69 6e 67 20 6d 61 74 63 68 20 22 2a 2f 2a 22  ring match "*/*"
11c0: 20 24 6c 69 6e 65 5d 7d 20 7b 0a 09 09 09 09 63   $line]} {.....c
11d0: 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a 0a 09 09  ontinue....}....
11e0: 09 69 66 20 7b 24 6c 69 6e 65 20 3d 3d 20 22 22  .if {$line == ""
11f0: 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 6e 75 65  } {.....continue
1200: 0a 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 77 6f  ....}.....set wo
1210: 72 6b 20 5b 73 70 6c 69 74 20 24 6c 69 6e 65 20  rk [split $line 
1220: 22 2c 22 5d 0a 0a 09 09 09 75 6e 73 65 74 20 2d  ","].....unset -
1230: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 70 6b 67 49 6e  nocomplain pkgIn
1240: 66 6f 0a 09 09 09 73 65 74 20 70 6b 67 49 6e 66  fo....set pkgInf
1250: 6f 28 70 61 63 6b 61 67 65 29 20 20 5b 6c 69 6e  o(package)  [lin
1260: 64 65 78 20 24 77 6f 72 6b 20 30 5d 0a 09 09 09  dex $work 0]....
1270: 73 65 74 20 70 6b 67 49 6e 66 6f 28 76 65 72 73  set pkgInfo(vers
1280: 69 6f 6e 29 20 20 5b 6c 69 6e 64 65 78 20 24 77  ion)  [lindex $w
1290: 6f 72 6b 20 31 5d 0a 09 09 09 73 65 74 20 70 6b  ork 1]....set pk
12a0: 67 49 6e 66 6f 28 6f 73 29 20 20 20 20 20 20 20  gInfo(os)       
12b0: 5b 5f 6e 6f 72 6d 61 6c 69 7a 65 4f 53 20 5b 6c  [_normalizeOS [l
12c0: 69 6e 64 65 78 20 24 77 6f 72 6b 20 32 5d 5d 0a  index $work 2]].
12d0: 09 09 09 73 65 74 20 70 6b 67 49 6e 66 6f 28 63  ...set pkgInfo(c
12e0: 70 75 41 72 63 68 29 20 20 5b 5f 6e 6f 72 6d 61  puArch)  [_norma
12f0: 6c 69 7a 65 43 50 55 20 5b 6c 69 6e 64 65 78 20  lizeCPU [lindex 
1300: 24 77 6f 72 6b 20 33 5d 5d 0a 09 09 09 73 65 74  $work 3]]....set
1310: 20 70 6b 67 49 6e 66 6f 28 68 61 73 68 29 20 20   pkgInfo(hash)  
1320: 20 20 20 5b 73 74 72 69 6e 67 20 74 6f 6c 6f 77     [string tolow
1330: 65 72 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b  er [lindex $work
1340: 20 34 5d 5d 0a 09 09 09 73 65 74 20 70 6b 67 49   4]]....set pkgI
1350: 6e 66 6f 28 68 61 73 68 5f 74 79 70 65 29 20 22  nfo(hash_type) "
1360: 73 68 61 31 22 0a 09 09 09 73 65 74 20 70 6b 67  sha1"....set pkg
1370: 49 6e 66 6f 28 69 73 4c 61 74 65 73 74 29 20 5b  Info(isLatest) [
1380: 65 78 70 72 20 7b 21 21 5b 6c 69 6e 64 65 78 20  expr {!![lindex 
1390: 24 77 6f 72 6b 20 35 5d 7d 5d 0a 0a 09 09 09 69  $work 5]}].....i
13a0: 66 20 7b 21 5b 5f 69 73 48 61 73 68 20 24 70 6b  f {![_isHash $pk
13b0: 67 49 6e 66 6f 28 68 61 73 68 29 5d 7d 20 7b 0a  gInfo(hash)]} {.
13c0: 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09  ....continue....
13d0: 7d 0a 0a 09 09 09 6c 61 70 70 65 6e 64 20 63 75  }.....lappend cu
13e0: 72 72 5f 70 61 63 6b 61 67 65 73 20 24 70 6b 67  rr_packages $pkg
13f0: 49 6e 66 6f 28 68 61 73 68 29 0a 0a 09 09 09 23  Info(hash).....#
1400: 20 44 6f 20 6e 6f 74 20 64 6f 20 61 6e 79 20 61   Do not do any a
1410: 64 64 69 74 69 6f 6e 61 6c 20 77 6f 72 6b 20 69  dditional work i
1420: 66 20 77 65 20 61 6c 72 65 61 64 79 20 68 61 76  f we already hav
1430: 65 20 74 68 69 73 20 70 61 63 6b 61 67 65 0a 09  e this package..
1440: 09 09 73 65 74 20 65 78 69 73 74 69 6e 67 5f 70  ..set existing_p
1450: 61 63 6b 61 67 65 73 20 5b 5f 64 62 20 65 76 61  ackages [_db eva
1460: 6c 20 7b 53 45 4c 45 43 54 20 70 61 63 6b 61 67  l {SELECT packag
1470: 65 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 20  e FROM packages 
1480: 57 48 45 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d  WHERE hostname =
1490: 20 24 68 6f 73 74 6e 61 6d 65 20 41 4e 44 20 73   $hostname AND s
14a0: 68 61 31 20 3d 20 24 70 6b 67 49 6e 66 6f 28 68  ha1 = $pkgInfo(h
14b0: 61 73 68 29 3b 7d 5d 0a 09 09 09 69 66 20 7b 5b  ash);}]....if {[
14c0: 6c 73 65 61 72 63 68 20 2d 65 78 61 63 74 20 24  lsearch -exact $
14d0: 65 78 69 73 74 69 6e 67 5f 70 61 63 6b 61 67 65  existing_package
14e0: 73 20 24 70 6b 67 49 6e 66 6f 28 70 61 63 6b 61  s $pkgInfo(packa
14f0: 67 65 29 5d 20 21 3d 20 2d 31 7d 20 7b 0a 09 09  ge)] != -1} {...
1500: 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a  ..continue....}.
1510: 0a 09 09 09 69 66 20 7b 24 70 6b 67 49 6e 66 6f  ....if {$pkgInfo
1520: 28 69 73 4c 61 74 65 73 74 29 7d 20 7b 0a 09 09  (isLatest)} {...
1530: 09 09 5f 64 62 20 65 76 61 6c 20 7b 55 50 44 41  .._db eval {UPDA
1540: 54 45 20 70 61 63 6b 61 67 65 73 20 53 45 54 20  TE packages SET 
1550: 69 73 4c 61 74 65 73 74 20 3d 20 30 20 57 48 45  isLatest = 0 WHE
1560: 52 45 20 68 6f 73 74 6e 61 6d 65 20 3d 20 24 68  RE hostname = $h
1570: 6f 73 74 6e 61 6d 65 20 41 4e 44 20 70 61 63 6b  ostname AND pack
1580: 61 67 65 20 3d 20 24 70 6b 67 49 6e 66 6f 28 24  age = $pkgInfo($
1590: 70 61 63 6b 61 67 65 29 20 41 4e 44 20 6f 73 20  package) AND os 
15a0: 3d 20 24 70 6b 67 49 6e 66 6f 28 24 70 61 63 6b  = $pkgInfo($pack
15b0: 61 67 65 29 20 41 4e 44 20 63 70 75 41 72 63 68  age) AND cpuArch
15c0: 20 3d 20 24 70 6b 67 49 6e 66 6f 28 63 70 75 41   = $pkgInfo(cpuA
15d0: 72 63 68 29 3b 7d 0a 09 09 09 7d 0a 0a 09 09 09  rch);}....}.....
15e0: 5f 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 52 54  _db eval {INSERT
15f0: 20 49 4e 54 4f 20 70 61 63 6b 61 67 65 73 20 28   INTO packages (
1600: 68 6f 73 74 6e 61 6d 65 2c 20 73 68 61 31 2c 20  hostname, sha1, 
1610: 70 61 63 6b 61 67 65 2c 20 76 65 72 73 69 6f 6e  package, version
1620: 2c 20 6f 73 2c 20 63 70 75 41 72 63 68 2c 20 69  , os, cpuArch, i
1630: 73 4c 61 74 65 73 74 2c 20 68 61 76 65 4d 61 6e  sLatest, haveMan
1640: 69 66 65 73 74 29 20 56 41 4c 55 45 53 20 28 24  ifest) VALUES ($
1650: 68 6f 73 74 6e 61 6d 65 2c 20 24 70 6b 67 49 6e  hostname, $pkgIn
1660: 66 6f 28 68 61 73 68 29 2c 20 24 70 6b 67 49 6e  fo(hash), $pkgIn
1670: 66 6f 28 70 61 63 6b 61 67 65 29 2c 20 24 70 6b  fo(package), $pk
1680: 67 49 6e 66 6f 28 76 65 72 73 69 6f 6e 29 2c 20  gInfo(version), 
1690: 24 70 6b 67 49 6e 66 6f 28 6f 73 29 2c 20 24 70  $pkgInfo(os), $p
16a0: 6b 67 49 6e 66 6f 28 63 70 75 41 72 63 68 29 2c  kgInfo(cpuArch),
16b0: 20 24 70 6b 67 49 6e 66 6f 28 69 73 4c 61 74 65   $pkgInfo(isLate
16c0: 73 74 29 2c 20 30 29 3b 7d 0a 09 09 7d 0a 0a 09  st), 0);}...}...
16d0: 09 23 20 4c 6f 6f 6b 20 66 6f 72 20 70 61 63 6b  .# Look for pack
16e0: 61 67 65 73 20 74 68 61 74 20 68 61 76 65 20 62  ages that have b
16f0: 65 65 6e 20 64 65 6c 65 74 65 64 0a 09 09 73 65  een deleted...se
1700: 74 20 66 6f 75 6e 64 5f 70 61 63 6b 61 67 65 73  t found_packages
1710: 20 5b 5f 64 62 20 65 76 61 6c 20 7b 53 45 4c 45   [_db eval {SELE
1720: 43 54 20 73 68 61 31 20 46 52 4f 4d 20 70 61 63  CT sha1 FROM pac
1730: 6b 61 67 65 73 20 57 48 45 52 45 20 68 6f 73 74  kages WHERE host
1740: 6e 61 6d 65 20 3d 20 24 68 6f 73 74 6e 61 6d 65  name = $hostname
1750: 3b 7d 5d 0a 09 09 66 6f 72 65 61 63 68 20 70 61  ;}]...foreach pa
1760: 63 6b 61 67 65 20 24 66 6f 75 6e 64 5f 70 61 63  ckage $found_pac
1770: 6b 61 67 65 73 20 7b 0a 09 09 09 73 65 74 20 66  kages {....set f
1780: 6f 75 6e 64 5f 70 61 63 6b 61 67 65 73 5f 61 72  ound_packages_ar
1790: 72 28 24 70 61 63 6b 61 67 65 29 20 31 0a 09 09  r($package) 1...
17a0: 7d 0a 0a 09 09 66 6f 72 65 61 63 68 20 70 61 63  }....foreach pac
17b0: 6b 61 67 65 20 24 63 75 72 72 5f 70 61 63 6b 61  kage $curr_packa
17c0: 67 65 73 20 7b 0a 09 09 09 75 6e 73 65 74 20 2d  ges {....unset -
17d0: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 66 6f 75 6e 64  nocomplain found
17e0: 5f 70 61 63 6b 61 67 65 73 5f 61 72 72 28 24 70  _packages_arr($p
17f0: 61 63 6b 61 67 65 29 0a 09 09 7d 0a 0a 09 09 66  ackage)...}....f
1800: 6f 72 65 61 63 68 20 70 61 63 6b 61 67 65 20 5b  oreach package [
1810: 61 72 72 61 79 20 6e 61 6d 65 73 20 66 6f 75 6e  array names foun
1820: 64 5f 70 61 63 6b 61 67 65 73 5f 61 72 72 5d 20  d_packages_arr] 
1830: 7b 0a 09 09 09 5f 64 62 20 65 76 61 6c 20 7b 44  {...._db eval {D
1840: 45 4c 45 54 45 20 46 52 4f 4d 20 70 61 63 6b 61  ELETE FROM packa
1850: 67 65 73 20 57 48 45 52 45 20 68 6f 73 74 6e 61  ges WHERE hostna
1860: 6d 65 20 3d 20 24 68 6f 73 74 6e 61 6d 65 20 41  me = $hostname A
1870: 4e 44 20 73 68 61 31 20 3d 20 24 70 61 63 6b 61  ND sha1 = $packa
1880: 67 65 3b 7d 0a 09 09 7d 0a 0a 09 09 5f 64 62 20  ge;}...}...._db 
1890: 65 76 61 6c 20 7b 49 4e 53 45 52 54 20 4f 52 20  eval {INSERT OR 
18a0: 52 45 50 4c 41 43 45 20 49 4e 54 4f 20 73 69 74  REPLACE INTO sit
18b0: 65 73 20 28 68 6f 73 74 6e 61 6d 65 2c 20 6c 61  es (hostname, la
18c0: 73 74 55 70 64 61 74 65 2c 20 74 74 6c 29 20 56  stUpdate, ttl) V
18d0: 41 4c 55 45 53 20 28 24 68 6f 73 74 6e 61 6d 65  ALUES ($hostname
18e0: 2c 20 24 6e 6f 77 2c 20 24 3a 3a 61 70 70 66 73  , $now, $::appfs
18f0: 3a 3a 74 74 6c 29 3b 7d 0a 0a 09 09 72 65 74 75  ::ttl);}....retu
1900: 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 7d 0a 0a  rn COMPLETE..}..
1910: 09 70 72 6f 63 20 67 65 74 70 6b 67 6d 61 6e 69  .proc getpkgmani
1920: 66 65 73 74 20 7b 68 6f 73 74 6e 61 6d 65 20 70  fest {hostname p
1930: 61 63 6b 61 67 65 5f 73 68 61 31 7d 20 7b 0a 09  ackage_sha1} {..
1940: 09 73 65 74 20 68 61 76 65 4d 61 6e 69 66 65 73  .set haveManifes
1950: 74 73 20 5b 5f 64 62 20 65 76 61 6c 20 7b 53 45  ts [_db eval {SE
1960: 4c 45 43 54 20 68 61 76 65 4d 61 6e 69 66 65 73  LECT haveManifes
1970: 74 20 46 52 4f 4d 20 70 61 63 6b 61 67 65 73 20  t FROM packages 
1980: 57 48 45 52 45 20 73 68 61 31 20 3d 20 24 70 61  WHERE sha1 = $pa
1990: 63 6b 61 67 65 5f 73 68 61 31 20 4c 49 4d 49 54  ckage_sha1 LIMIT
19a0: 20 31 3b 7d 5d 0a 09 09 73 65 74 20 68 61 76 65   1;}]...set have
19b0: 4d 61 6e 69 66 65 73 74 20 5b 6c 69 6e 64 65 78  Manifest [lindex
19c0: 20 24 68 61 76 65 4d 61 6e 69 66 65 73 74 73 20   $haveManifests 
19d0: 30 5d 0a 0a 09 09 69 66 20 7b 24 68 61 76 65 4d  0]....if {$haveM
19e0: 61 6e 69 66 65 73 74 7d 20 7b 0a 09 09 09 72 65  anifest} {....re
19f0: 74 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 09  turn COMPLETE...
1a00: 7d 0a 0a 09 09 69 66 20 7b 21 5b 5f 69 73 48 61  }....if {![_isHa
1a10: 73 68 20 24 70 61 63 6b 61 67 65 5f 73 68 61 31  sh $package_sha1
1a20: 5d 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 46  ]} {....return F
1a30: 41 49 4c 0a 09 09 7d 0a 0a 09 09 73 65 74 20 66  AIL...}....set f
1a40: 69 6c 65 20 5b 64 6f 77 6e 6c 6f 61 64 20 24 68  ile [download $h
1a50: 6f 73 74 6e 61 6d 65 20 24 70 61 63 6b 61 67 65  ostname $package
1a60: 5f 73 68 61 31 5d 0a 09 09 73 65 74 20 66 64 20  _sha1]...set fd 
1a70: 5b 6f 70 65 6e 20 24 66 69 6c 65 5d 0a 09 09 73  [open $file]...s
1a80: 65 74 20 70 6b 67 64 61 74 61 20 5b 72 65 61 64  et pkgdata [read
1a90: 20 24 66 64 5d 0a 09 09 63 6c 6f 73 65 20 24 66   $fd]...close $f
1aa0: 64 0a 0a 09 09 5f 64 62 20 74 72 61 6e 73 61 63  d...._db transac
1ab0: 74 69 6f 6e 20 7b 0a 09 09 09 66 6f 72 65 61 63  tion {....foreac
1ac0: 68 20 6c 69 6e 65 20 5b 73 70 6c 69 74 20 24 70  h line [split $p
1ad0: 6b 67 64 61 74 61 20 22 5c 6e 22 5d 20 7b 0a 09  kgdata "\n"] {..
1ae0: 09 09 09 73 65 74 20 6c 69 6e 65 20 5b 73 74 72  ...set line [str
1af0: 69 6e 67 20 74 72 69 6d 20 24 6c 69 6e 65 5d 0a  ing trim $line].
1b00: 0a 09 09 09 09 69 66 20 7b 24 6c 69 6e 65 20 3d  .....if {$line =
1b10: 3d 20 22 22 7d 20 7b 0a 09 09 09 09 09 63 6f 6e  = ""} {......con
1b20: 74 69 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09 09  tinue.....}.....
1b30: 09 73 65 74 20 77 6f 72 6b 20 5b 73 70 6c 69 74  .set work [split
1b40: 20 24 6c 69 6e 65 20 22 2c 22 5d 0a 0a 09 09 09   $line ","].....
1b50: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
1b60: 69 6e 20 66 69 6c 65 49 6e 66 6f 0a 09 09 09 09  in fileInfo.....
1b70: 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 74 79 70  set fileInfo(typ
1b80: 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b  e) [lindex $work
1b90: 20 30 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65   0].....set file
1ba0: 49 6e 66 6f 28 74 69 6d 65 29 20 5b 6c 69 6e 64  Info(time) [lind
1bb0: 65 78 20 24 77 6f 72 6b 20 31 5d 0a 0a 09 09 09  ex $work 1].....
1bc0: 09 73 65 74 20 77 6f 72 6b 20 5b 6c 72 61 6e 67  .set work [lrang
1bd0: 65 20 24 77 6f 72 6b 20 32 20 65 6e 64 5d 0a 09  e $work 2 end]..
1be0: 09 09 09 73 77 69 74 63 68 20 2d 2d 20 24 66 69  ...switch -- $fi
1bf0: 6c 65 49 6e 66 6f 28 74 79 70 65 29 20 7b 0a 09  leInfo(type) {..
1c00: 09 09 09 09 22 66 69 6c 65 22 20 7b 0a 09 09 09  ...."file" {....
1c10: 09 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28  ...set fileInfo(
1c20: 73 69 7a 65 29 20 5b 6c 69 6e 64 65 78 20 24 77  size) [lindex $w
1c30: 6f 72 6b 20 30 5d 0a 09 09 09 09 09 09 73 65 74  ork 0].......set
1c40: 20 66 69 6c 65 49 6e 66 6f 28 70 65 72 6d 73 29   fileInfo(perms)
1c50: 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72 6b 20 31   [lindex $work 1
1c60: 5d 0a 09 09 09 09 09 09 73 65 74 20 66 69 6c 65  ].......set file
1c70: 49 6e 66 6f 28 73 68 61 31 29 20 5b 6c 69 6e 64  Info(sha1) [lind
1c80: 65 78 20 24 77 6f 72 6b 20 32 5d 0a 0a 09 09 09  ex $work 2].....
1c90: 09 09 09 73 65 74 20 77 6f 72 6b 20 5b 6c 72 61  ...set work [lra
1ca0: 6e 67 65 20 24 77 6f 72 6b 20 33 20 65 6e 64 5d  nge $work 3 end]
1cb0: 0a 09 09 09 09 09 7d 0a 09 09 09 09 09 22 73 79  ......}......"sy
1cc0: 6d 6c 69 6e 6b 22 20 7b 0a 09 09 09 09 09 09 73  mlink" {.......s
1cd0: 65 74 20 66 69 6c 65 49 6e 66 6f 28 73 6f 75 72  et fileInfo(sour
1ce0: 63 65 29 20 5b 6c 69 6e 64 65 78 20 24 77 6f 72  ce) [lindex $wor
1cf0: 6b 20 30 5d 0a 09 09 09 09 09 09 73 65 74 20 77  k 0].......set w
1d00: 6f 72 6b 20 5b 6c 72 61 6e 67 65 20 24 77 6f 72  ork [lrange $wor
1d10: 6b 20 31 20 65 6e 64 5d 0a 09 09 09 09 09 7d 0a  k 1 end]......}.
1d20: 09 09 09 09 7d 0a 0a 09 09 09 09 73 65 74 20 66  ....}......set f
1d30: 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 20 5b 6a  ileInfo(name) [j
1d40: 6f 69 6e 20 24 77 6f 72 6b 20 22 2c 22 5d 0a 09  oin $work ","]..
1d50: 09 09 09 73 65 74 20 66 69 6c 65 49 6e 66 6f 28  ...set fileInfo(
1d60: 6e 61 6d 65 29 20 5b 73 70 6c 69 74 20 5b 73 74  name) [split [st
1d70: 72 69 6e 67 20 74 72 69 6d 20 24 66 69 6c 65 49  ring trim $fileI
1d80: 6e 66 6f 28 6e 61 6d 65 29 20 22 2f 22 5d 20 22  nfo(name) "/"] "
1d90: 2f 22 5d 0a 09 09 09 09 73 65 74 20 66 69 6c 65  /"].....set file
1da0: 49 6e 66 6f 28 64 69 72 65 63 74 6f 72 79 29 20  Info(directory) 
1db0: 5b 6a 6f 69 6e 20 5b 6c 72 61 6e 67 65 20 24 66  [join [lrange $f
1dc0: 69 6c 65 49 6e 66 6f 28 6e 61 6d 65 29 20 30 20  ileInfo(name) 0 
1dd0: 65 6e 64 2d 31 5d 20 22 2f 22 5d 0a 09 09 09 09  end-1] "/"].....
1de0: 73 65 74 20 66 69 6c 65 49 6e 66 6f 28 6e 61 6d  set fileInfo(nam
1df0: 65 29 20 5b 6c 69 6e 64 65 78 20 24 66 69 6c 65  e) [lindex $file
1e00: 49 6e 66 6f 28 6e 61 6d 65 29 20 65 6e 64 5d 0a  Info(name) end].
1e10: 0a 09 09 09 09 5f 64 62 20 65 76 61 6c 20 7b 49  ....._db eval {I
1e20: 4e 53 45 52 54 20 49 4e 54 4f 20 66 69 6c 65 73  NSERT INTO files
1e30: 20 28 70 61 63 6b 61 67 65 5f 73 68 61 31 2c 20   (package_sha1, 
1e40: 74 79 70 65 2c 20 74 69 6d 65 2c 20 73 6f 75 72  type, time, sour
1e50: 63 65 2c 20 73 69 7a 65 2c 20 70 65 72 6d 73 2c  ce, size, perms,
1e60: 20 66 69 6c 65 5f 73 68 61 31 2c 20 66 69 6c 65   file_sha1, file
1e70: 5f 6e 61 6d 65 2c 20 66 69 6c 65 5f 64 69 72 65  _name, file_dire
1e80: 63 74 6f 72 79 29 20 56 41 4c 55 45 53 20 28 24  ctory) VALUES ($
1e90: 70 61 63 6b 61 67 65 5f 73 68 61 31 2c 20 24 66  package_sha1, $f
1ea0: 69 6c 65 49 6e 66 6f 28 74 79 70 65 29 2c 20 24  ileInfo(type), $
1eb0: 66 69 6c 65 49 6e 66 6f 28 74 69 6d 65 29 2c 20  fileInfo(time), 
1ec0: 24 66 69 6c 65 49 6e 66 6f 28 73 6f 75 72 63 65  $fileInfo(source
1ed0: 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 73 69 7a  ), $fileInfo(siz
1ee0: 65 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28 70 65  e), $fileInfo(pe
1ef0: 72 6d 73 29 2c 20 24 66 69 6c 65 49 6e 66 6f 28  rms), $fileInfo(
1f00: 73 68 61 31 29 2c 20 24 66 69 6c 65 49 6e 66 6f  sha1), $fileInfo
1f10: 28 6e 61 6d 65 29 2c 20 24 66 69 6c 65 49 6e 66  (name), $fileInf
1f20: 6f 28 64 69 72 65 63 74 6f 72 79 29 20 29 3b 7d  o(directory) );}
1f30: 0a 09 09 09 09 5f 64 62 20 65 76 61 6c 20 7b 55  ....._db eval {U
1f40: 50 44 41 54 45 20 70 61 63 6b 61 67 65 73 20 53  PDATE packages S
1f50: 45 54 20 68 61 76 65 4d 61 6e 69 66 65 73 74 20  ET haveManifest 
1f60: 3d 20 31 20 57 48 45 52 45 20 73 68 61 31 20 3d  = 1 WHERE sha1 =
1f70: 20 24 70 61 63 6b 61 67 65 5f 73 68 61 31 3b 7d   $package_sha1;}
1f80: 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 72 65 74  ....}...}....ret
1f90: 75 72 6e 20 43 4f 4d 50 4c 45 54 45 0a 09 7d 0a  urn COMPLETE..}.
1fa0: 7d 0a                                            }.