Merge branch 'wjt/glib-mkenums-filename-basename-in-fhead-ftail' into 'master'

glib-mkenums: forbid @filename@/@basename@ in fhead and ftail

See merge request GNOME/glib!241
diff --git a/gobject/glib-mkenums.in b/gobject/glib-mkenums.in
index de05232..985edd2 100755
--- a/gobject/glib-mkenums.in
+++ b/gobject/glib-mkenums.in
@@ -303,15 +303,15 @@
 parser.add_argument('--identifier-prefix', default='', dest='idprefix',
                     help='Identifier prefix')
 parser.add_argument('--symbol-prefix', default='', dest='symprefix',
-                    help='symbol-prefix')
+                    help='Symbol prefix')
 parser.add_argument('--fhead', default=[], dest='fhead', action='append',
                     help='Output file header')
 parser.add_argument('--ftail', default=[], dest='ftail', action='append',
-                    help='Per input file production')
+                    help='Output file footer')
 parser.add_argument('--fprod', default=[], dest='fprod', action='append',
-                    help='Put out TEXT everytime a new input file is being processed.')
+                    help='Put out TEXT every time a new input file is being processed.')
 parser.add_argument('--eprod', default=[], dest='eprod', action='append',
-                    help='Per enum text (produced prior to value iterations)')
+                    help='Per enum text, produced prior to value iterations')
 parser.add_argument('--vhead', default=[], dest='vhead', action='append',
                     help='Value header, produced before iterating over enum values')
 parser.add_argument('--vprod', default=[], dest='vprod', action='append',
@@ -324,8 +324,9 @@
                     help='Template file')
 parser.add_argument('--output', default=None, dest='output')
 parser.add_argument('--version', '-v', default=False, action='store_true', dest='version',
-                    help='Print version informations')
-parser.add_argument('args', nargs='*')
+                    help='Print version information')
+parser.add_argument('args', nargs='*',
+                    help='Input files')
 
 options = parser.parse_args()
 
@@ -415,12 +416,17 @@
     prod = prod.rstrip()
     return prod
 
+
+def warn_if_filename_basename_used(section, prod):
+    for substitution in ('\u0040filename\u0040',
+                         '\u0040basename\u0040'):
+        if substitution in prod:
+            print_warning('{} used in {} section.'.format(substitution,
+                                                          section))
+
 if len(fhead) > 0:
     prod = fhead
-    base = os.path.basename(options.args[0])
-
-    prod = prod.replace('\u0040filename\u0040', options.args[0])
-    prod = prod.replace('\u0040basename\u0040', base)
+    warn_if_filename_basename_used('file-header', prod)
     prod = replace_specials(prod)
     write_output(prod)
 
@@ -712,10 +718,7 @@
 
 if len(ftail) > 0:
     prod = ftail
-    base = os.path.basename(options.args[-1]) # FIXME, wrong
-
-    prod = prod.replace('\u0040filename\u0040', 'ARGV') # wrong too
-    prod = prod.replace('\u0040basename\u0040', base)
+    warn_if_filename_basename_used('file-tail', prod)
     prod = replace_specials(prod)
     write_output(prod)
 
diff --git a/gobject/tests/mkenums.py b/gobject/tests/mkenums.py
index 431453d..bb54433 100644
--- a/gobject/tests/mkenums.py
+++ b/gobject/tests/mkenums.py
@@ -20,14 +20,19 @@
 
 """Integration tests for glib-mkenums utility."""
 
+import collections
 import os
 import subprocess
 import tempfile
+import textwrap
 import unittest
 
 import taptestrunner
 
 
+Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
+
+
 class TestMkenums(unittest.TestCase):
     """Integration test for running glib-mkenums.
 
@@ -70,15 +75,40 @@
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               env=env)
-        print('Output:', info.stdout.decode('utf-8'))
-        return info
+        info.check_returncode()
+        out = info.stdout.decode('utf-8').strip()
+        err = info.stderr.decode('utf-8').strip()
 
-    def runMkenumsWithHeader(self, h_contents, encoding='utf-8', *args):
+        # Known substitutions for standard boilerplate
+        subs = {
+            'standard_top_comment':
+                'This file is generated by glib-mkenums, do not modify '
+                'it. This code is licensed under the same license as the '
+                'containing project. Note that it links to GLib, so must '
+                'comply with the LGPL linking clauses.',
+            'standard_bottom_comment': 'Generated data ends here'
+        }
+
+        result = Result(info, out, err, subs)
+
+        print('Output:', result.out)
+        return result
+
+    def runMkenumsWithTemplate(self, template_contents, *args):
+        with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
+                                         suffix='.template') as template_file:
+            # Write out the template.
+            template_file.write(template_contents.encode('utf-8'))
+            print(template_file.name + ':', template_contents)
+            template_file.flush()
+
+            return self.runMkenums('--template', template_file.name, *args)
+
+    def runMkenumsWithAllSubstitutions(self, *args):
+        '''Run glib-mkenums with a template which outputs all substitutions.'''
         template_contents = '''
 /*** BEGIN file-header ***/
 file-header
-filename: @filename@
-basename: @basename@
 /*** END file-header ***/
 
 /*** BEGIN file-production ***/
@@ -140,48 +170,30 @@
 
 /*** BEGIN file-tail ***/
 file-tail
-filename: @filename@
-basename: @basename@
 /*** END file-tail ***/
 '''
+        return self.runMkenumsWithTemplate(template_contents, *args)
 
+    def runMkenumsWithHeader(self, h_contents, encoding='utf-8'):
         with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
-                                         suffix='.template') as template_file, \
-             tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
                                          suffix='.h') as h_file:
-            # Write out the template.
-            template_file.write(template_contents.encode('utf-8'))
-            print(template_file.name + ':', template_contents)
-
             # Write out the header to be scanned.
             h_file.write(h_contents.encode(encoding))
             print(h_file.name + ':', h_contents)
-
-            template_file.flush()
             h_file.flush()
 
             # Run glib-mkenums with a template which outputs all substitutions.
-            info = self.runMkenums('--template', template_file.name,
-                                   h_file.name)
-            info.check_returncode()
-            out = info.stdout.decode('utf-8').strip()
-            err = info.stderr.decode('utf-8').strip()
+            result = self.runMkenumsWithAllSubstitutions(h_file.name)
 
             # Known substitutions for generated filenames.
-            subs = {
+            result.subs.update({
                 'filename': h_file.name,
                 'basename': os.path.basename(h_file.name),
-                'standard_top_comment':
-                    'This file is generated by glib-mkenums, do not modify '
-                    'it. This code is licensed under the same license as the '
-                    'containing project. Note that it links to GLib, so must '
-                    'comply with the LGPL linking clauses.',
-                'standard_bottom_comment': 'Generated data ends here'
-            }
+            })
 
-            return (info, out, err, subs)
+            return result
 
-    def assertSingleEnum(self, out, subs, enum_name_camel, enum_name_lower,
+    def assertSingleEnum(self, result, enum_name_camel, enum_name_lower,
                          enum_name_upper, enum_name_short, enum_prefix,
                          type_lower, type_camel, type_upper,
                          value_name, value_nick, value_num):
@@ -199,7 +211,7 @@
             'value_name': value_name,
             'value_nick': value_nick,
             'value_num': value_num,
-        }, **subs)
+        }, **result.subs)
 
         self.assertEqual('''
 comment
@@ -207,8 +219,6 @@
 
 
 file-header
-filename: {filename}
-basename: {basename}
 file-production
 filename: {filename}
 basename: {basename}
@@ -247,40 +257,67 @@
 Type: {type_camel}
 TYPE: {type_upper}
 file-tail
-filename: ARGV
-basename: {basename}
 
 comment
 comment: {standard_bottom_comment}
-'''.format(**subs).strip(), out)
+'''.format(**subs).strip(), result.out)
 
     def test_help(self):
         """Test the --help argument."""
-        info = self.runMkenums('--help')
-        info.check_returncode()
+        result = self.runMkenums('--help')
+        self.assertIn('usage: glib-mkenums', result.out)
 
-        out = info.stdout.decode('utf-8').strip()
-        self.assertIn('usage: glib-mkenums', out)
+    def test_no_args(self):
+        """Test running with no arguments at all."""
+        result = self.runMkenums()
+        self.assertEqual('', result.err)
+        self.assertEquals('''/* {standard_top_comment} */
+
+
+/* {standard_bottom_comment} */'''.format(**result.subs),
+                          result.out.strip())
+
+    def test_empty_template(self):
+        """Test running with an empty template and no header files."""
+        result = self.runMkenumsWithTemplate('')
+        self.assertEqual('', result.err)
+        self.assertEquals('''/* {standard_top_comment} */
+
+
+/* {standard_bottom_comment} */'''.format(**result.subs),
+                          result.out.strip())
+
+    def test_no_headers(self):
+        """Test running with a complete template, but no header files."""
+        result = self.runMkenumsWithAllSubstitutions()
+        self.assertEqual('', result.err)
+        self.assertEquals('''
+comment
+comment: {standard_top_comment}
+
+
+file-header
+file-tail
+
+comment
+comment: {standard_bottom_comment}
+'''.format(**result.subs).strip(), result.out)
 
     def test_empty_header(self):
         """Test an empty header."""
-        (info, out, err, subs) = self.runMkenumsWithHeader('')
-        self.assertEqual('', err)
+        result = self.runMkenumsWithHeader('')
+        self.assertEqual('', result.err)
         self.assertEqual('''
 comment
 comment: {standard_top_comment}
 
 
 file-header
-filename: {filename}
-basename: {basename}
 file-tail
-filename: ARGV
-basename: {basename}
 
 comment
 comment: {standard_bottom_comment}
-'''.format(**subs).strip(), out)
+'''.format(**result.subs).strip(), result.out)
 
     def test_enum_name(self):
         """Test typedefs with an enum and a typedef name. Bug #794506."""
@@ -289,9 +326,9 @@
           ENUM_VALUE
         } SomeEnumIdentifier;
         '''
-        (info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
-        self.assertEqual('', err)
-        self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
+        result = self.runMkenumsWithHeader(h_contents)
+        self.assertEqual('', result.err)
+        self.assertSingleEnum(result, 'SomeEnumIdentifier',
                               'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
                               'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
                               'ENUM', 'ENUM_VALUE', 'value', '0')
@@ -304,10 +341,9 @@
           ENUM_VALUE
         } SomeEnumIdentifier;
         '''
-        (info, out, err, subs) = \
-            self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
-        self.assertIn('WARNING: UnicodeWarning: ', err)
-        self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
+        result = self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
+        self.assertIn('WARNING: UnicodeWarning: ', result.err)
+        self.assertSingleEnum(result, 'SomeEnumIdentifier',
                               'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
                               'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
                               'ENUM', 'ENUM_VALUE', 'value', '0')
@@ -315,6 +351,8 @@
     def test_reproducible(self):
         """Test builds are reproducible regardless of file ordering.
         Bug #691436."""
+        template_contents = 'template'
+
         h_contents1 = '''
         typedef enum {
           FIRST,
@@ -328,36 +366,28 @@
         '''
 
         with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
-                                         suffix='.template') as template_file, \
-             tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
                                          suffix='1.h') as h_file1, \
-             tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
-                                         suffix='2.h') as h_file2:
-            # Write out the template and headers.
-            template_file.write('template'.encode('utf-8'))
+                tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
+                                            suffix='2.h') as h_file2:
+            # Write out the headers.
             h_file1.write(h_contents1.encode('utf-8'))
             h_file2.write(h_contents2.encode('utf-8'))
 
-            template_file.flush()
             h_file1.flush()
             h_file2.flush()
 
             # Run glib-mkenums with the headers in one order, and then again
             # in another order.
-            info1 = self.runMkenums('--template', template_file.name,
-                                    h_file1.name, h_file2.name)
-            info1.check_returncode()
-            out1 = info1.stdout.decode('utf-8').strip()
-            self.assertEqual('', info1.stderr.decode('utf-8').strip())
+            result1 = self.runMkenumsWithTemplate(template_contents,
+                                                  h_file1.name, h_file2.name)
+            self.assertEqual('', result1.err)
 
-            info2 = self.runMkenums('--template', template_file.name,
-                                    h_file2.name, h_file1.name)
-            info2.check_returncode()
-            out2 = info2.stdout.decode('utf-8').strip()
-            self.assertEqual('', info2.stderr.decode('utf-8').strip())
+            result2 = self.runMkenumsWithTemplate(template_contents,
+                                                  h_file2.name, h_file1.name)
+            self.assertEqual('', result2.err)
 
             # The output should be the same.
-            self.assertEqual(out1, out2)
+            self.assertEqual(result1.out, result2.out)
 
     def test_no_nick(self):
         """Test trigraphs with a desc but no nick. Issue #1360."""
@@ -366,13 +396,57 @@
           GEGL_SAMPLER_NEAREST = 0,   /*< desc="nearest"      >*/
         } GeglSamplerType;
         '''
-        (info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
-        self.assertEqual('', err)
-        self.assertSingleEnum(out, subs, 'GeglSamplerType',
+        result = self.runMkenumsWithHeader(h_contents)
+        self.assertEqual('', result.err)
+        self.assertSingleEnum(result, 'GeglSamplerType',
                               'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
                               'SAMPLER_TYPE', 'GEGL', 'enum', 'Enum',
                               'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
 
+    def test_filename_basename_in_fhead_ftail(self):
+        template_contents = '''
+/*** BEGIN file-header ***/
+file-header
+filename: @filename@
+basename: @basename@
+/*** END file-header ***/
+
+/*** BEGIN comment ***/
+comment
+comment: @comment@
+/*** END comment ***/
+
+/*** BEGIN file-tail ***/
+file-tail
+filename: @filename@
+basename: @basename@
+/*** END file-tail ***/'''
+        result = self.runMkenumsWithTemplate(template_contents)
+        self.assertEqual(
+            textwrap.dedent(
+                '''
+                WARNING: @filename@ used in file-header section.
+                WARNING: @basename@ used in file-header section.
+                WARNING: @filename@ used in file-tail section.
+                WARNING: @basename@ used in file-tail section.
+                ''').strip(),
+            result.err)
+        self.assertEqual('''
+comment
+comment: {standard_top_comment}
+
+
+file-header
+filename: @filename@
+basename: @basename@
+file-tail
+filename: @filename@
+basename: @basename@
+
+comment
+comment: {standard_bottom_comment}
+'''.format(**result.subs).strip(), result.out)
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=taptestrunner.TAPTestRunner())