]> git.donarmstrong.com Git - lilypond.git/blobdiff - scripts/build/output-distance.py
Issue 5126: Prevent Ghostscript's unwanted automatic page rotation
[lilypond.git] / scripts / build / output-distance.py
old mode 100644 (file)
new mode 100755 (executable)
index 537363b..625ce12
@@ -3,6 +3,9 @@ import sys
 import optparse
 import os
 import math
+import re
+
+import cgi
 
 ## so we can call directly as scripts/build/output-distance.py
 me_path = os.path.abspath (os.path.split (sys.argv[0])[0])
@@ -50,8 +53,7 @@ def system (c):
         raise Exception ("failed")
     return
 
-def shorten_string (s):
-    threshold = 15
+def shorten_string (s, threshold = 15):
     if len (s) > 2*threshold:
         s = s[:threshold] + '..' + s[-threshold:]
     return s
@@ -87,7 +89,7 @@ def compare_png_images (old, new, dest_dir):
     system ('convert -depth 8 -crop %dx%d+0+0 %s %s/crop1.png' % (dims + (old, dir)))
     system ('convert -depth 8 -crop %dx%d+0+0 %s %s/crop2.png' % (dims + (new, dir)))
 
-    system ('compare -depth 8 -dissimilarity-threshold 1 %(dir)s/crop1.png %(dir)s/crop2.png %(dir)s/diff.png' % locals ())
+    system1 ('compare -depth 8 -dissimilarity-threshold 1 %(dir)s/crop1.png %(dir)s/crop2.png %(dir)s/diff.png' % locals ())
 
     system ("convert  -depth 8 %(dir)s/diff.png -blur 0x3 -negate -channel alpha,blue -type TrueColorMatte -fx 'intensity'    %(dir)s/matte.png" % locals ())
 
@@ -314,7 +316,9 @@ class SystemLink:
                 self.geometric_distance ())
 
 def scheme_float (s) :
-  return float(s) if 'nan' not in s else float(s.split('.')[0])
+    if 'nan' not in s :
+        return float(s)
+    return float(s.split('.')[0])
 
 def read_signature_file (name):
     print 'reading', name
@@ -372,12 +376,18 @@ class FileLink:
 
         return ''
 
+    def directories (self):
+        return map (os.path.dirname, self.file_names)
+
     def name (self):
         base = os.path.basename (self.file_names[1])
         base = os.path.splitext (base)[0]
         base = hash_to_original_name.get (base, base)
         base = os.path.splitext (base)[0]
-        return base
+        return os.path.join (self.prefix (), base)
+
+    def prefix (self):
+        return os.path.dirname (os.path.commonprefix (self.file_names))
 
     def extension (self):
         return os.path.splitext (self.file_names[1])[1]
@@ -454,7 +464,7 @@ class GitFileCompareLink (FileCompareLink):
         str = '\n'.join ([l[:80] for l in str.split ('\n')])
 
 
-        str = '<font size="-2"><pre>%s</pre></font>' % str
+        str = '<font size="-2"><pre>%s</pre></font>' % cgi.escape (str)
         return str
 
     def calc_distance (self):
@@ -466,11 +476,22 @@ class GitFileCompareLink (FileCompareLink):
         return d
 
 
+snippet_fn_re = re.compile (r"`\./([0-9a-f]{2}/lily-[0-9a-f]{8}).eps'");
 class TextFileCompareLink (FileCompareLink):
     def calc_distance (self):
         import difflib
-        diff = difflib.unified_diff (self.contents[0].strip().split ('\n'),
-                                     self.contents[1].strip().split ('\n'),
+        # Extract the old and the new hashed snippet names from the log file
+        # and replace the old by the new, so file name changes don't show
+        # up as log differences...
+        cont0 = self.contents[0].strip();
+        cont1 = self.contents[1].strip();
+        m0 = re.search (snippet_fn_re, cont0);
+        m1 = re.search (snippet_fn_re, cont1);
+        if (m0 and m1 and (m0.group(1) != m1.group(1))):
+            cont0 = cont0.replace (m0.group(1), m1.group(1));
+
+        diff = difflib.unified_diff (cont0.split ('\n'),
+                                     cont1.split ('\n'),
                                      fromfiledate = self.file_names[0],
                                      tofiledate = self.file_names[1]
                                      )
@@ -484,7 +505,7 @@ class TextFileCompareLink (FileCompareLink):
         str = ''
         if oldnew == 1:
             str = '\n'.join ([d.replace ('\n','') for d in self.diff_lines])
-        str = '<font size="-2"><pre>%s</pre></font>' % str
+        str = '<font size="-2"><pre>%s</pre></font>' % cgi.escape (str)
         return str
 
 class LogFileCompareLink (TextFileCompareLink):
@@ -507,7 +528,7 @@ class ProfileFileLink (FileCompareLink):
                 str += '%-8s: %8d (%5.3f)\n' % (k, int (self.results[oldnew][k]),
                                                 self.get_ratio (k))
 
-        return '<pre>%s</pre>' % str
+        return '<pre>%s</pre>' % cgi.escape (str)
 
     def get_ratio (self, key):
         (v1,v2) = (self.results[0].get (key, -1),
@@ -621,6 +642,7 @@ class SignatureFileLink (FileLink):
                 cmd = ('gs -sDEVICE=png16m -dGraphicsAlphaBits=4 -dTextAlphaBits=4 '
                        ' %(data_option)s '
                        ' -r101 '
+                       ' -dAutoRotatePages=/None '
                        ' -sOutputFile=%(outfile)s -dNOSAFER -dEPSCrop -q -dNOPAUSE '
                        ' %(infile)s  -c quit ') % locals ()
 
@@ -752,7 +774,6 @@ class SignatureFileLink (FileLink):
 # Files/directories
 
 import glob
-import re
 
 def compare_signature_files (f1, f2):
     s1 = read_signature_file (f1)
@@ -807,13 +828,25 @@ class ComparisonData:
                 re.sub (r'\\sourcefilename "([^"]+)"',
                         note_original, open (sf).read ())
             else:
-                print 'no source for', val
+                print 'no source for', val.file_names[1]
 
     def compare_trees (self, dir1, dir2):
         self.compare_directories (dir1, dir2)
 
-        (root, dirs, files) = os.walk (dir1).next ()
+        try:
+            (root, dirs, files) = os.walk (dir1).next ()
+        except StopIteration:
+            if dir1.endswith("-baseline"):
+                sys.stderr.write("Failed to walk through %s. This can be caused by forgetting to run make test-baseline.\n" % dir1)
+            else:
+                sys.stderr.write("Failed to walk through %s; please check it exists.\n" % dir1)
+            sys.exit(1)
+
         for d in dirs:
+            # don't walk the share folders
+            if d.startswith("share"):
+                continue
+
             d1 = os.path.join (dir1, d)
             d2 = os.path.join (dir2, d)
 
@@ -859,14 +892,18 @@ class ComparisonData:
                 self.compare_general_files (klasses[ext], f1, f2)
 
     def compare_general_files (self, klass, f1, f2):
+        prefix = os.path.commonprefix ([f1, f2])
         name = os.path.split (f1)[1]
+        name = os.path.join (prefix, name)
 
         file_link = klass (f1, f2)
         self.file_links[name] = file_link
 
     def compare_signature_files (self, f1, f2):
+        prefix = os.path.commonprefix ([f1, f2])
         name = os.path.split (f1)[1]
         name = re.sub ('-[0-9]+.signature', '', name)
+        name = os.path.join (prefix, name)
 
         file_link = None
         try:
@@ -919,42 +956,84 @@ class ComparisonData:
         out.write ('%d below threshold\n' % len (below))
         out.write ('%d unchanged\n' % len (unchanged))
 
-    def create_text_result_page (self, dir1, dir2, dest_dir, threshold):
+    def create_text_result_page (self, dest_dir, threshold):
         self.write_text_result_page (dest_dir + '/index.txt', threshold)
 
-    def create_html_result_page (self, dir1, dir2, dest_dir, threshold):
-        dir1 = dir1.replace ('//', '/')
-        dir2 = dir2.replace ('//', '/')
-
+    def create_html_result_page (self, dest_dir, threshold):
         (changed, below, unchanged) = self.thresholded_results (threshold)
 
-
-        html = ''
-        old_prefix = os.path.split (dir1)[1]
-        for link in changed:
-            html += link.html_record_string (dest_dir)
-
-
-        short_dir1 = shorten_string (dir1)
-        short_dir2 = shorten_string (dir2)
-        html = '''<html>
-<table rules="rows" border bordercolor="blue">
+        header_row = '''
 <tr>
 <th>distance</th>
 <th>%(short_dir1)s</th>
 <th>%(short_dir2)s</th>
 </tr>
-%(html)s
-</table>
-</html>''' % locals()
+'''
 
-        html += ('<p>')
+        table_rows = ''
+        old_prefix = None
+        for link in changed:
+            this_prefix = link.prefix ()
+            if (old_prefix != this_prefix):
+                old_prefix = this_prefix
+                short_dir1 = shorten_string (link.directories ()[0], 30)
+                short_dir2 = shorten_string (link.directories ()[1], 30)
+                table_rows += header_row % locals()
+            table_rows += link.html_record_string (dest_dir)
+
+        summary = ''
         below_count = len (below)
 
         if below_count:
-            html += ('<p>%d below threshold</p>' % below_count)
+            summary += '<p>%d below threshold</p>' % below_count
+
+        summary += '<p>%d unchanged</p>' % len (unchanged)
+
+        me = sys.argv[0]
+
+        html = '''<html>
+<head>
+<title>LilyPond regression test results</title>
+<meta name="author" content="This file was autogenerated by %(me)s">
+<script language="javascript" type="text/javascript">
+// <![CDATA[
+    var rows = document.getElementsByTagName("tr");
+    function showOnlyMatchingRows(substring) {
+        var rowcount = rows.length;
+        for (var i = 0; i < rowcount; i++) {
+            row = rows[i];
+            html = row.innerHTML;
+            row.style.display =
+                ((html.indexOf('>distance<') != -1) ||
+                 (html.indexOf(substring + '">') != -1)) ? "" : "none";
+        }
+    }
+// ]]>
+</script>
+</head>
+<body>
+<p>
+  click to filter rows by type:
+  <a href="#" onClick="showOnlyMatchingRows('.ly')">ly</a> /
+  <a href="#" onClick="showOnlyMatchingRows('.profile')">profiling</a> /
+  <a href="#" onClick="showOnlyMatchingRows('.signature')">signature</a> /
+  <a href="#" onClick="showOnlyMatchingRows('.midi')">midi</a> /
+  <a href="#" onClick="showOnlyMatchingRows('.log')">log</a> /
+  <a href="#" onClick="showOnlyMatchingRows('.gittxt')">gittxt</a> /
+  <a href="#" onClick="showOnlyMatchingRows('')">reset to all</a>
+</p>
+
+<hr />
 
-        html += ('<p>%d unchanged</p>' % len (unchanged))
+%(summary)s
+
+<hr />
+
+<table rules="rows" border bordercolor="blue">
+%(table_rows)s
+</table>
+</body>
+</html>''' % locals()
 
         dest_file = dest_dir + '/index.html'
         open_write_file (dest_file).write (html)
@@ -979,8 +1058,8 @@ def compare_tree_pairs (tree_pairs, dest_dir, threshold):
         system ('rm -rf %s '% dest_dir)
 
     data.write_changed (dest_dir, threshold)
-    data.create_html_result_page (dir1, dir2, dest_dir, threshold)
-    data.create_text_result_page (dir1, dir2, dest_dir, threshold)
+    data.create_html_result_page (dest_dir, threshold)
+    data.create_text_result_page (dest_dir, threshold)
 
 ################################################################
 # TESTING
@@ -1011,6 +1090,12 @@ def system (x):
     stat = os.system (x)
     assert stat == 0
 
+def system1 (x):
+# Allow exit status 0 and 1
+    print 'invoking', x
+    stat = os.system (x)
+    assert (stat == 0) or (stat == 256) # This return value convention is sick.
+
 
 def test_paired_files ():
     print paired_files (os.environ["HOME"] + "/src/lilypond/scripts/",
@@ -1249,7 +1334,7 @@ def main ():
         run_tests ()
         sys.exit (0)
 
-    if len (args) % 2:
+    if len (args) % 2 == 1:
         p.print_usage ()
         sys.exit (2)