1 | #!/usr/bin/tclsh |
---|
2 | # repairfilemap.tcl |
---|
3 | # |
---|
4 | # Created by Kevin Ballard <kevin@sb.org> |
---|
5 | # This creates a new file_map based on the contents of the receipts. |
---|
6 | # Intended for use when file_map.db gets corrupted. |
---|
7 | # |
---|
8 | # The way this works is it parses all the receipts, pulls out the active ones, |
---|
9 | # pulls out the image contents of each receipt, removes the image directory from |
---|
10 | # the beginning of each path, and uses the resulting paths to construct an |
---|
11 | # old-style file_map file. Once this is done, simply delete your file_map.db |
---|
12 | # file and run a MacPorts command that access this file (such as deactivating |
---|
13 | # a port, getting a contents list, or asking what port provides a file) and |
---|
14 | # MacPorts will convert the file_map to a new file_map.db file. |
---|
15 | # |
---|
16 | # Note: this assumes you are using port images. If you aren't, this script will |
---|
17 | # not work for you. |
---|
18 | # |
---|
19 | # This script is in the public domain. Do whatever you want with it. The only |
---|
20 | # disclaimer is I am not liable for anything unexpected this script might do. |
---|
21 | |
---|
22 | catch { |
---|
23 | source [file join "/Library/Tcl" macports1.0 macports_fastload.tcl] |
---|
24 | } |
---|
25 | package require macports 1.0 |
---|
26 | |
---|
27 | if {[catch {mportinit} result]} { |
---|
28 | puts "Failed to initialize ports system, $result" |
---|
29 | exit 1 |
---|
30 | } |
---|
31 | |
---|
32 | set file_map {} |
---|
33 | |
---|
34 | proc parse_receipt {name} { |
---|
35 | global macports::registry.path |
---|
36 | |
---|
37 | set file_map {} |
---|
38 | |
---|
39 | set name [lindex [file split $name] end] |
---|
40 | |
---|
41 | set receipt_path [file join ${macports::registry.path} receipts $name] |
---|
42 | |
---|
43 | set versions {} |
---|
44 | set x [glob -nocomplain [file join $receipt_path *]] |
---|
45 | if { [string length $x] } { |
---|
46 | foreach path $x { |
---|
47 | lappend versions [lindex [file split $path] end] |
---|
48 | } |
---|
49 | } |
---|
50 | |
---|
51 | foreach version $versions { |
---|
52 | set receipt_file [file join $receipt_path $version receipt] |
---|
53 | |
---|
54 | if { [file exists $receipt_file.bz2] && [file exists /usr/bin/bzip2] } { |
---|
55 | set receipt_file $receipt_file.bz2 |
---|
56 | set receipt_contents [exec /usr/bin/bzip2 -d -c $receipt_file] |
---|
57 | } elseif { [file exists $receipt_file] } { |
---|
58 | set receipt_handle [open $receipt_file r] |
---|
59 | set receipt_contents [read $receipt_handle] |
---|
60 | close $receipt_handle |
---|
61 | } else { |
---|
62 | return -code error "Registry erryr: receipt for ${name} ${version} seems to be compressed, but bzip2 couldn't be found." |
---|
63 | } |
---|
64 | |
---|
65 | if {![string match "# Version: 1.0*" $receipt_contents]} { |
---|
66 | return -code error "Registry error: receipt $name $version is an unknown format." |
---|
67 | } |
---|
68 | |
---|
69 | # Remove any line starting with # |
---|
70 | while {[regexp "(^|\n)#.*\n(.*)\$" $receipt_contents match foo receipt_contents]} {} |
---|
71 | array set receipt $receipt_contents |
---|
72 | |
---|
73 | if { [info exists receipt(active)] && $receipt(active) != 0 } { |
---|
74 | puts "Parsing active receipt for $name $version" |
---|
75 | # parse the contents list |
---|
76 | set contents $receipt(contents) |
---|
77 | |
---|
78 | foreach entry $contents { |
---|
79 | set path [lindex $entry 0] |
---|
80 | if { [string first $receipt(imagedir) $path] == 0 } { |
---|
81 | set path [string range $path [string length $receipt(imagedir)] end] |
---|
82 | } else { |
---|
83 | return -code error "Receipt error: Referenced file does not live in image directory." |
---|
84 | } |
---|
85 | set map_entry {} |
---|
86 | lappend map_entry $path |
---|
87 | lappend map_entry $name |
---|
88 | lappend file_map $map_entry |
---|
89 | } |
---|
90 | } |
---|
91 | } |
---|
92 | return $file_map |
---|
93 | } |
---|
94 | |
---|
95 | set names [glob -nocomplain [file join ${macports::registry.path} receipts *]] |
---|
96 | |
---|
97 | set file_map {} |
---|
98 | |
---|
99 | puts "Parsing receipts..." |
---|
100 | |
---|
101 | foreach name $names { |
---|
102 | set file_map [concat $file_map [parse_receipt $name]] |
---|
103 | } |
---|
104 | |
---|
105 | set map_file [file join ${macports::registry.path} receipts file_map] |
---|
106 | set map_handle [open $map_file w] |
---|
107 | puts $map_handle $file_map |
---|
108 | close $map_handle |
---|
109 | puts "\n-- File map successfully built --" |
---|