1#!/usr/bin/env python
2# -*- Mode: python -*-
3
4#    Copyright (C) 2001-2007 Artifex Software Inc.
5#    All Rights Reserved.
6#
7# This software is provided AS-IS with no warranty, either express or
8# implied.
9#
10# This software is distributed under license and may not be copied, modified
11# or distributed except as expressly authorized under the terms of that
12# license.  Refer to licensing information at http://www.artifex.com/
13# or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
14# San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
15
16# $Id: update_specific 8409 2007-11-27 20:43:09Z giles $
17
18# update_specific [ <svn date spec> | -r <svn revision> ]
19#
20# pass files to update via stdin in the following format:
21# (N|P) <file>
22# N for normal regression test, P for pdfwrite regression test
23# <file> must not include a path and must be a file in the
24# comparefiles directory
25
26import os
27import sys
28import string
29import time
30import tempfile
31import anydbm
32import re
33from popen2 import Popen4
34
35import gstestgs
36import gsconf
37import gssum
38import gsparamsets
39import rasterdb
40
41def norm_entry(cmd, ifile, device, dpi, band, datespec):
42    ofile = "%s.%s.%d.%d" % (ifile, device, dpi, band)
43    print "updating entry: " + ofile + "...",
44    sys.stdout.flush()
45
46    gs = gstestgs.Ghostscript()
47    gs.command = cmd
48    gs.log_stdout = gsconf.log_stdout
49    gs.log_stderr = gsconf.log_stderr
50    gs.infile = gsconf.comparefiledir + ifile
51    gs.outfile = ofile
52    gs.device = device
53    gs.dpi = dpi
54    gs.band = band
55
56    if gs.process():
57        try:
58 	    if gsconf.log_baseline:
59	        log = open(gsconf.log_baseline, "a")
60	        log.write(time.ctime() + " " + ifile + " updated "\
61			  "[" + datespec + "]\n")
62	        log.close()
63            gssum.add_file(ofile)
64            rasterdb.put_file(ofile)
65            os.unlink(ofile)
66            print "done."
67        except OSError:
68            print "no output produced."
69    else:
70	print "error."
71
72def pdf_entry(cmd, ifile, device, dpi, band, datespec):
73    ofile = "%s.pdf.%s.%d.%d" % (ifile, device, dpi, band)
74    print "updating entry: " + ofile + "...",
75    sys.stdout.flush()
76
77    gs = gstestgs.Ghostscript()
78    gs.log_stdout = gsconf.log_stdout
79    gs.log_stderr = gsconf.log_stderr
80    gs.command = cmd
81    gs.infile = gsconf.comparefiledir + ifile
82    gs.dpi = dpi
83    gs.band = band
84
85    # make file->PDF
86
87    tfile = ofile + ".pdf"
88    gs.outfile = tfile
89    gs.device = 'pdfwrite'
90    gs.dpi = None
91
92    if not gs.process():
93        print "error."
94        return
95
96    gs.infile = tfile
97    gs.outfile = ofile
98    gs.device = device
99    gs.dpi = dpi
100
101    if gs.process():
102        try:
103	    if gsconf.log_baseline:
104	        log = open(gsconf.log_baseline, "a")
105		log.write(time.ctime() + " " + ifile + " updated (pdfwrite) "\
106			  "[" + datespec + "]\n")
107		log.close()
108            gssum.add_file(ofile)
109            rasterdb.put_file(ofile)
110            os.unlink(tfile)
111            os.unlink(ofile)
112            print "done."
113        except OSError:
114            print "no output produced."
115    else:
116        print "error."
117
118
119TMP_PREFIX = "REGBUILD."
120
121def make_temp_dir():
122    return tempfile.mkdtemp(prefix=TMP_PREFIX)
123
124def kill_temp_dir(dir):
125    if string.find(dir, TMP_PREFIX) == -1:
126        raise StandardError, "Tried to kill a non temp dir!"
127
128    for root, dirs, files in os.walk(dir, topdown=False):
129        for name in files:
130            os.remove(os.path.join(root, name))
131        for name in dirs:
132            os.rmdir(os.path.join(root, name))
133    os.rmdir(dir)
134
135def run(cmd, dir):
136    try:
137        os.chdir(dir)
138        pipe = Popen4(cmd)
139        line = pipe.fromchild.readline()
140        while len(line) > 0:
141            sys.stdout.write(line)
142            sys.stdout.flush()
143            line = pipe.fromchild.readline()
144        ret = pipe.wait()
145    except OSError, e:
146        print "ERROR: An exception occured:", e
147        ret = -1
148
149    return ret
150
151def change_gsproduct(file):
152    tmpfile = "%s.tmp" % (file,)
153
154    startre = re.compile("^#ifndef\ GS_PRODUCT$")
155    changere = re.compile("^.*?\"[A-Za-z -]+\".*?$")
156    endre = re.compile("^$")
157
158    old = open(file, "r")
159    new = open(tmpfile, "w")
160
161    state = 0
162    for line in old.readlines():
163        if state == 0:
164            m = startre.search(line)
165            if m:
166                state = 1
167
168            new.write(line)
169        elif state == 1:
170            m = changere.search(line)
171            if m:
172                state = 2
173                new.write("\t\"GPL Ghostscript\"\n")
174            else:
175                new.write(line)
176        elif state == 2:
177            m = endre.search(line)
178            if m:
179                state = 0
180
181            new.write(line)
182
183
184    old.close()
185    new.close()
186
187    os.unlink(file)
188    os.rename(tmpfile, file)
189
190if len(sys.argv) < 2:
191    print "Not enough arguments."
192    print "usage: update_specific [ -r <revision> | <svn date spec> ]"
193    print
194    sys.exit(1)
195
196if sys.argv[1] == '-r':
197    revspec = sys.argv[2]
198else:
199    revspec =  "{\"" + sys.argv[1] + "\"}"
200
201normset = []
202pdfset = []
203for line in sys.stdin.readlines():
204    line = string.strip(line)
205    if line[0] == 'N' and line[1] == ' ':
206        normset.append(string.replace(line[2:], '"', ''))
207    elif line[0] == 'P' and line[1] == ' ':
208        pdfset.append(string.replace(line[2:], '"', ''))
209    else:
210        print "Wrong format of arguments given:", line
211        sys.exit(1)
212
213print "normal:", normset
214print "pdf:", pdfset
215
216# create the build/install directories and subdirectories
217tmpdir = make_temp_dir()
218svndir = os.path.join(tmpdir, "svn")
219instdir = os.path.join(tmpdir, "inst")
220builddir = os.path.join(svndir, "gs")
221os.mkdir(svndir)
222os.mkdir(instdir)
223
224try:
225    # do the svn checkout
226    ret = run("svn checkout -r " + revspec +
227	" " + gsconf.repository + "/trunk/gs", svndir)
228    if ret != 0:
229        raise StandardError, "ERROR: SVN checkout failed"
230
231    # now configure and build Ghostscript
232    ret = run("./autogen.sh --prefix=" + instdir, builddir)
233    if ret != 0:
234        raise StandardError, "ERROR: configure failed"
235
236    os.chdir(builddir)
237    change_gsproduct(os.path.join(builddir, "src/gscdef.c"))
238
239    ret = run("make", builddir)
240    if ret != 0:
241        raise StandardError, "ERROR: make failed"
242
243    ret = run("make install", builddir)
244    if ret != 0:
245        raise StandardError, "ERROR: make install failed"
246
247    # install fonts
248    fontdir = os.path.join(instdir, "share", "ghostscript", "fonts")
249    os.mkdir(fontdir)
250    ret = run("cp " + gsconf.fontdir + "* " + fontdir, instdir)
251    if ret != 0:
252        raise StandardError, "ERROR: font installation failed"
253
254    # update baselines
255    os.chdir(tmpdir)
256    gscmd = os.path.join(instdir, "bin", "gs")
257    for f in normset:
258        for params in gsparamsets.testparamsets:
259            norm_entry(gscmd, f, params.device, params.resolution,
260                       params.banding, revspec)
261    for f in pdfset:
262        for params in gsparamsets.pdftestparamsets:
263            pdf_entry(gscmd, f, params.device, params.resolution,
264                      params.banding, revspec)
265
266except StandardError, e:
267    print "ERROR:", e
268
269# clean up our mess
270kill_temp_dir(tmpdir)
271