source: trunk/base/portmgr/PortIndex2MySQL.tcl @ 29193

Last change on this file since 29193 was 29193, checked in by jmpp@…, 12 years ago

Whitespace changes only.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1#!/usr/bin/env tclsh
2# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4
3#
4# PortIndex2MySQL.tcl
5# Kevin Van Vechten | kevin@opendarwin.org
6# 3-Oct-2002
7# Juan Manuel Palacios | jmpp@macports.org
8# 30-Jul-2007
9# $Id: PortIndex2MySQL.tcl 29193 2007-09-17 08:17:38Z jmpp@macports.org $
10#
11# Copyright (c) 2007 Juan Manuel Palacios, MacPorts Team.
12# Copyright (c) 2003 Apple Computer, Inc.
13# Copyright (c) 2002 Kevin Van Vechten.
14# All rights reserved.
15#
16# Redistribution and use in source and binary forms, with or without
17# modification, are permitted provided that the following conditions
18# are met:
19# 1. Redistributions of source code must retain the above copyright
20#    notice, this list of conditions and the following disclaimer.
21# 2. Redistributions in binary form must reproduce the above copyright
22#    notice, this list of conditions and the following disclaimer in the
23#    documentation and/or other materials provided with the distribution.
24# 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
25#    may be used to endorse or promote products derived from this software
26#    without specific prior written permission.
27#
28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38# POSSIBILITY OF SUCH DAMAGE.
39
40#####
41# The PortIndex2MySQL script populates a database with key information extracted
42# from the Portfiles in the ports tree pointed to by the sources.conf file in a
43# MacPorts installation, found by loading its macports1.0 tcl package and initializing
44# it with 'mportinit' below. Main use of the resulting database is providing live
45# information to the ports.php page, a client tailored to poll it. For this very reason,
46# information fed to the database always has to be kept up to date in order to remain
47# meaningful, which is accomplished simply by calling 'macports::selfupdate' (which
48# updates the ports tree in use) and by installing the script on cron/launchd to be run
49# on a timely schedule (not any more frequent than the run of the mprsyncup script on
50# the MacPorts server, which is every half hour).
51#
52# Remaining requirement to successfully run this script is performing the necessary
53# MySQL admin tasks on the host box to create the database in the first place and the
54# MySQL user that will be given enough privileges to alter it. Values in the database
55# related variables provided below have to be adapted accordingly to match the chosen
56# setup.
57#####
58
59
60# Error messages reciepient.
61set SPAM_LOVERS macports-dev@lists.macosforge.org
62
63# Place holder proc for error catching and processing.
64proc bail_on_error {error_log} {
65   
66}
67
68
69# Load macports1.0 so that we can use some of its procs and the portinfo array.
70catch {source \
71    [file join "@TCL_PACKAGE_DIR@" macports1.0 macports_fastload.tcl]}
72package require macports
73
74# Initialize MacPorts to find the sources.conf file, wherefrom we'll
75# get the PortIndex that'll feed the database.
76#more work needs to be done than just initializing and passing the
77#ui_options array to get mportinit to output verbose/debugging info;
78#I'm currently looking into this.
79array set ui_options {ports_verbose yes}
80mportinit
81
82# Call the selfupdate procedure to make sure the MacPorts installation
83# is up-to-date and with a fresh ports tree.
84macports::selfupdate
85
86
87# Procedure to catch the database password from a protected file.
88proc getpasswd {passwdfile} {
89    if {[catch {open $passwdfile r} passwdfile_fd]} {
90        ui_error "${::errorCode}: $passwdfile_fd"
91        exit 1
92    }
93    if {[gets $passwdfile_fd passwd] <= 0} {
94        ui_error "No password found in $passwdfile!"
95        exit 1
96    }
97    close $passwdfile_fd
98    return $passwd
99}
100
101# Database abstraction variables:
102set sqlfile [file join /tmp ports.sql]
103set dbcmd [macports::findBinary mysql5]
104set dbhost 127.0.0.1
105set dbuser macports
106set passwdfile [file join . password_file]
107set dbpasswd [getpasswd $passwdfile]
108set dbname macports_ports
109
110# Flat text file to which sql statements are written.
111if {[catch {open $sqlfile w+} sqlfile_fd]} {
112    ui_error "${::errorCode}: $sqlfile_fd"
113    exit 1
114}
115
116
117# SQL string escaping.
118proc sql_escape {str} {
119    regsub -all -- {'} $str {\\'} str
120    regsub -all -- {"} $str {\\"} str
121    regsub -all -- {\n} $str {\\n} str
122    return $str
123}
124
125# Initial creation of database tables: log, portfiles, categories, maintainers, dependencies, variants and platforms.
126# Do we need any other?
127puts $sqlfile_fd "DROP TABLE IF EXISTS log;"
128puts $sqlfile_fd "CREATE TABLE IF NOT EXISTS log (activity VARCHAR(255), activity_time TIMESTAMP(14));"
129puts $sqlfile_fd "INSERT INTO log VALUES ('update', NOW());"
130
131puts $sqlfile_fd "DROP TABLE IF EXISTS portfiles;"
132puts $sqlfile_fd "CREATE TABLE portfiles (name VARCHAR(255) PRIMARY KEY NOT NULL, path VARCHAR(255), version VARCHAR(255),  description TEXT);"
133
134puts $sqlfile_fd "DROP TABLE IF EXISTS categories;"
135puts $sqlfile_fd "CREATE TABLE categories (portfile VARCHAR(255), category VARCHAR(255), is_primary INTEGER);"
136
137puts $sqlfile_fd "DROP TABLE IF EXISTS maintainers;"
138puts $sqlfile_fd "CREATE TABLE maintainers (portfile VARCHAR(255), maintainer VARCHAR(255), is_primary INTEGER);"
139
140puts $sqlfile_fd "DROP TABLE IF EXISTS dependencies;"
141puts $sqlfile_fd "CREATE TABLE dependencies (portfile VARCHAR(255), library VARCHAR(255));"
142
143puts $sqlfile_fd "DROP TABLE IF EXISTS variants;"
144puts $sqlfile_fd "CREATE TABLE variants (portfile VARCHAR(255), variant VARCHAR(255));"
145
146puts $sqlfile_fd "DROP TABLE IF EXISTS platforms;"
147puts $sqlfile_fd "CREATE TABLE platforms (portfile VARCHAR(255), platform VARCHAR(255));"
148
149
150# Load every port in the index through a search matching everything.
151if {[catch {set ports [mportsearch ".+"]} errstr]} {
152    ui_error "port search failed: $errstr"
153    exit 1
154}
155
156# Iterate over each matching port, extracting its information from the
157# portinfo array.
158foreach {name array} $ports {
159
160    array unset portinfo
161    array set portinfo $array
162
163    set portname [sql_escape $portinfo(name)]
164    if {[info exists portinfo(version)]} {
165        set portversion [sql_escape $portinfo(version)]
166    } else {
167        set portversion ""
168    }
169    set portdir [sql_escape $portinfo(portdir)]
170    if {[info exists portinfo(description)]} {
171        set description [sql_escape $portinfo(description)]
172    } else {
173        set description ""
174    }
175    if {[info exists portinfo(categories)]} {
176        set categories $portinfo(categories)
177    } else {
178        set categories ""
179    }
180    if {[info exists portinfo(maintainers)]} {
181        set maintainers $portinfo(maintainers)
182    } else {
183        set maintainers ""
184    }
185    if {[info exists portinfo(variants)]} {
186        set variants $portinfo(variants)
187    } else {
188        set variants ""
189    }
190    if {[info exists portinfo(depends_build)]} {
191        set depends_build $portinfo(depends_build)
192    } else {
193        set depends_build ""
194    }
195    if {[info exists portinfo(depends_lib)]} {
196        set depends_lib $portinfo(depends_lib)
197    } else {
198        set depends_lib ""
199    }
200    if {[info exists portinfo(depends_run)]} {
201        set depends_run $portinfo(depends_run)
202    } else {
203        set depends_run ""
204    }
205    if {[info exists portinfo(platforms)]} {
206        set platforms $portinfo(platforms)
207    } else {
208        set platforms ""
209    }
210
211    puts $sqlfile_fd "INSERT INTO portfiles VALUES ('$portname', '$portdir', '$portversion', '$description');"
212
213    set primary 1
214    foreach category $categories {
215        set category [sql_escape $category]
216        puts $sqlfile_fd "INSERT INTO categories VALUES ('$portname', '$category', $primary);"
217        incr primary
218    }
219   
220    set primary 1
221    foreach maintainer $maintainers {
222        set maintainer [sql_escape $maintainer]
223        puts $sqlfile_fd "INSERT INTO maintainers VALUES ('$portname', '$maintainer', $primary);"
224        incr primary
225    }
226
227    foreach build_dep $depends_build {
228        set build_dep [sql_escape $build_dep]
229        puts $sqlfile_fd "INSERT INTO dependencies VALUES ('$portname', '$build_dep');"
230    }
231
232    foreach lib $depends_lib {
233        set lib [sql_escape $lib]
234        puts $sqlfile_fd "INSERT INTO dependencies VALUES ('$portname', '$lib');"
235    }
236
237    foreach run_dep $depends_run {
238        set run_dep [sql_escape $run_dep]
239        puts $sqlfile_fd "INSERT INTO dependencies VALUES ('$portname', '$run_dep');"
240    }
241
242    foreach variant $variants {
243        set variant [sql_escape $variant]
244        puts $sqlfile_fd "INSERT INTO variants VALUES ('$portname', '$variant');"
245    }
246
247    foreach platform $platforms {
248        set platform [sql_escape $platform]
249        puts $sqlfile_fd "INSERT INTO platforms VALUES ('$portname', '$platform');"
250    }
251
252}
253
254
255# Pipe the contents of the generated sql file to the database command,
256# reading from the file descriptor for the raw sql file to assure completeness.
257if {[catch {seek $sqlfile_fd 0 start} errstr]} {
258    ui_error "${::errorCode}: $errstr"
259    exit 1
260}
261if {[catch {exec -- $dbcmd --host=$dbhost --user=$dbuser --password=$dbpasswd --database=$dbname <@ $sqlfile_fd} errstr]} {
262    ui_error "${::errorCode}: $errstr"
263    exit 1
264}
265
266
267# And we're done regen'ing the MacPorts dabase! (cleanup)
268close $sqlfile_fd
269file delete -force $sqlfile
Note: See TracBrowser for help on using the repository browser.