Ticket #2725: repairfilemap.2.tcl

File repairfilemap.2.tcl, 3.4 KB (added by jmroot (Joshua Root), 15 years ago)

updated for current MacPorts

Line 
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
22catch {
23        source [file join "/Library/Tcl" macports1.0 macports_fastload.tcl]
24}
25package require macports 1.0
26
27if {[catch {mportinit} result]} {
28        puts "Failed to initialize ports system, $result"
29        exit 1
30}
31
32set file_map {}
33
34proc 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
95set names [glob -nocomplain [file join ${macports::registry.path} receipts *]]
96
97set file_map {}
98
99puts "Parsing receipts..."
100
101foreach name $names {
102        set file_map [concat $file_map [parse_receipt $name]]
103}
104
105set map_file [file join ${macports::registry.path} receipts file_map]
106set map_handle [open $map_file w]
107puts $map_handle $file_map
108close $map_handle
109puts "\n-- File map successfully built --"