File: dh_makefont

package info (click to toggle)
dh-make 2.202003
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 360 kB
  • sloc: python: 917; sh: 80; makefile: 11
file content (425 lines) | stat: -rwxr-xr-x 16,648 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
#!/usr/bin/python3
#
# Copyright (C) 2012-2013 Vasudev Kamath <kamathvasudev@gmail.com>
#               2011-2012 Muneeb Shaikh <iammuneeb@gmail.com>
#               2011-2012 Shravan Aras <123.shravan@gmail.com>
#
# License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl2.html>.

import os
import re
import argparse

__version__ = 0.3
##########################################################################
#                                                                        #
# Variables                                                              #
#                                                                        #
##########################################################################

required_files = ["control", "copyright", "changelog", "source", "compat",
                  "rules", "format"]

DEFAULT_MAINTAINER = \
        "Debian Fonts Task Force <pkg-fonts-devel@lists.alioth.debian.org>"

UPLOADERS = (os.environ.get('DEBFULLNAME') +
             " <" + os.environ.get('DEBEMAIL') + ">")\
    if 'DEBEMAIL' in os.environ else "#Please fill in your name and email"

PACKAGE = ""

version_string = '''
dh_makefont - prepare Debian packaging for fonts, version {}

Copyright (C)
 2012-2013 Vasudev Kamath <kamathvasudev@gmail.com>
 2011-2012 Muneeb Shaikh <iammuneeb@gmail.com>
 2011-2012 Shravan Aras <123.shravan@gmail.com>
'''.format(__version__)

GENERATES_TTF = False
GENERATES_OTF = False

font_reg_exp = re.compile("((.)*\.ttf|sfd|otf)")  # RE to check
font_sfd_regx = re.compile("((.)*\.sfd)")         # RE check font source file
generate_function = re.compile("Generate\(.*\)")

font_source = False

watch = '''
version=3
#please put upstream url for watch expression
'''


# This section of code parses the command line arguments.
arguments = argparse.ArgumentParser(
    prog='dh_makefont',
    description='dh_makefont',
    formatter_class=argparse.RawTextHelpFormatter,
    epilog='Font package helper')
arguments.add_argument('-c', '--copyright',
                       help='''use <type> of license in copyright file
                            (apache|artistic|bsd|gpl|gpl2|gpl3|lgpl|lgpl2|
                             lgpl3|x11)''')
arguments.add_argument('-p', '--package',
                       help='''force package name to be <name>
                            if name_version is given this will set version
                            number of package bypassing the directory
                            checking.''')
arguments.add_argument('--maint',
                       help='''Override default *Maintainer* which is
                             Debian Fonts Task Force
                             <pkg-fonts-devel@lists.alioth.debian.org>''')
arguments.add_argument('foldername',
                       help='Extracted folder containing fonts')

arguments.add_argument('-u', '--upstream',
                       help='''Provide an upstream URL. If this value is provided
                               it will be substituted in control and copyright
                               file''')

arguments.add_argument('-v', '--version', action='version',
                       help='Show the version number of dh_makefont',
                       version=version_string)


###########################################################################
#                                                                         #
#  Validation functions                                                   #
#                                                                         #
###########################################################################

def check_files():
    """
    This function checks if there is either .ttf .otf or .sfd
    file in the given folder. If that file is present only then
    we will continue after all this tool is for font packaging :)

    `-return` 0 if one of the .sfd .ttf or .otf file is present
    -1 other wise
    """
    global font_source
    # We need to perform a directory traversal to find .ttf .otf or .sfd.
    # Any one will do. [We are so kind arn't we]
    for dirpath, dirnames, filenames in os.walk('.'):
        for filename in filenames:
            if font_reg_exp.search(filename):
                if font_sfd_regx.search(filename):
                    font_source = True
                return 0
        return -1  # No need to go into sub directories
    return -1


def check_generatepe(filepath):
    global GENERATES_TTF, GENERATES_OTF
    with open(filepath) as fd:
        content = fd.read()
        if generate_function.search(content):
            # We did find Generate function
            for function in generate_function.findall(content):
                if function.find('.ttf') != -1:
                    GENERATES_TTF = True
                    break
                elif function.find('.otf') != -1:
                    GENERATES_OTF = True
                    break


###########################################################################
#                                                                         #
# Functions which edit the files inside debian/ folder of package         #
#                                                                         #
###########################################################################

def update_control_file(args):
    """
    This function updates the control file which is generated by dh_make
    1. Section is set to fonts
    2. Priority optional
    3. if Maintainer is not overridden by --maint DEFAULT_MAINTAINER
       else use value given by user with --maint
    4. Uploaders is added using DEBEMAIL and DEBFULLNAME environment
       variable
    5. Build-Depends will have fontforge dependency as a comment in
       case upstream provides .sfd, user can uncomment it.
    6. Architecture is changed to all
    7. shlibs depends is removed from Depends

    All remaining are kept as is and finally written back to control file
    """
    control_content = ""
    with open('control', "rb") as fd:
        contents = fd.read().split('\n')
        for line in contents:
            if line.startswith('Maintainer:'):
                if args.maint:
                    control_content += "Maintainer: "+args.maint
                else:
                    control_content += "Maintainer: " + DEFAULT_MAINTAINER
                    control_content += "\nUploaders: "+UPLOADERS
            elif line.startswith('Build-Depends:'):
                if font_source:
                    control_content += line + ", fontforge"
                else:
                    control_content += line
            elif line.startswith('Architecture:'):
                control_content += "Architecture: all"
            elif line.startswith('Section:'):
                control_content += "Section: fonts"
            elif line.startswith('Priority:'):
                control_content += "Priority: optional"
            elif line.startswith('Depends:'):
                control_content += "Depends: ${misc:Depends}"
            elif line.startswith('Homepage:') and args.upstream:
                control_content += "Homepage: " + args.upstream
            elif line.startswith('#Vcs-Git:') and not args.maint:
                control_content += '#Vcs-Git:' +\
                        'https://salsa.debian.org/debian/{}.git'.\
                        format(PACKAGE)
            elif line.startswith('#Vcs-Browser:') and not args.maint:
                control_content += "Vcs-Browser: " +\
                        'https://salsa.debian.org/debian/{}'.\
                        format(PACKAGE)
            else:
                control_content += line

            control_content += "\n"

    with open('control', 'wb') as fd:
        fd.write(control_content)


def update_copyright_file(args):
    """
    `args`: Command line arguments
    This function prepares copyright file in debian copyright-format 1.0.
    """
    copyright_content = ""
    with open('copyright', 'rb') as fd:
        contents = fd.read()
        contents = contents.split('\n')
        for line in contents:
            if line.startswith('Format:'):
                copyright_content += "Format: "\
                        "http://www.debian.org/doc/packaging-manuals/"\
                        "copyright-format/1.0/"
            elif line.startswith('Source:') and args.upstream:
                copyright_content += "Source: " + args.upstream
            else:
                copyright_content += line

            copyright_content += '\n'

    with open('copyright', 'wb') as fd:
        fd.write(copyright_content)


def create_install_and_links():
    """
    This function writes install file it checks for availability of
    ttf or otf file and writes a proper install file also if a font
    config .conf file is available creates a links file to do proper
    linking
    """
    global PACKAGE
    install = ""
    install_dir = PACKAGE.split('fonts-')[1]

    for dirpath, dirnames, filenames in os.walk('..'):
        if dirnames != 'debian':
            for filename in filenames:
                if filename.endswith('.ttf'):
                    install += "./{} usr/share/fonts/truetype/{}/\n".format(
                            filename, install_dir)
                elif filename.endswith('.otf'):
                    install += "./{} usr/share/fonts/truetype/{}/\n".format(
                            filename, install_dir)
                elif filename.endswith('.sfd'):
                    if 'generate.pe' in filenames:
                        check_generatepe(os.path.join(dirpath,
                                         filenames[filenames.index(
                                             'generate.pe')]))
                        if GENERATES_TTF:
                            install += "./{} usr/share/fonts/truetype/{}/\n".\
                                    format(filename.replace('sfd', 'ttf'),
                                           install_dir)
                        elif GENERATES_OTF:
                            install += "./{} usr/share/fonts/opentype/{}/\n".\
                                    format(filename.replace('sfd', 'otf'),
                                           install_dir)
                        else:
                            print("\n*Unable to determine if source generates"\
                                    "TTF or OTF file.\n\Please manually edit"\
                                    "the debian/install file*")
                    else:
                        print("\n*Unable to determine if source generates"\
                                "TTF or OTF file.\nPlease manually edit"\
                                "the debian/install file*")

                elif filename.endswith('.conf'):
                    install += "./{} etc/fonts/conf.avail".format(filename)
                    print("\nFound a fontconfig configuration file."\
                          "Added it to debian/install")
                    with open('links', 'w') as fd:
                        fd.write('etc/fonts/conf.avail/'+filename +
                                 ' etc/fonts/conf.d/'+filename)
                        print("\nI've symlinked conf file in etc/fonts/conf.d"\
                              ".\nPlease update fontconfig priority"\
                              "appropriately")

    with open('install', 'w') as fd:
        fd.write(install)


###########################################################################
#                                                                         #
#  dh_make helper function                                                #
#                                                                         #
###########################################################################

def call_dh_make(args):
    """
    `-args`: Arguments passed to this script this is of type NameSpace
             class returned by argparse.parse_args
    `-return`: Returns 0 like all other *nix utilities on success and non
               zero value on error. Error should be documented in dh_make
               manual

   This function is a wrapper over the dh_make command
    """
    global PACKAGE

    # Stores the final argument to be passed to dh_make
    args_string = " --createorig"

    if(args.copyright):
        args_string += " -c "+args.copyright
    if(args.package):
        args_string += " -p "+args.package
        PACKAGE = args.package.split('_')[0] \
            if args.package.find('_') else args.package
    else:
        """
        If user has not supplied -p or --package option which should be
        passed to dh_make then we will do it ourselves rather than allowing
        dh_make to decide

        According to pkg-fonts policy font package should be named
        `fonts-<foundry>-something` where foundry is optional.

        1. We will check if folder name begins with fonts- if yes we will pass
           it to dh_make with -p option.
        2. If it doesn't we will create package name by appending fonts- to
           `foldername`

        Additionally foldername-version is changed to foldername_version which
        is expected by dh_make as value for -p option

        In case of any error dh_make will bark at you and not me :)
        """

        folder = ""
        if args.foldername.count('-') > 1:
            """
            If we have more than one - in foldername that means foldername is
            in format folder-name-version. So lets split on - and join first
            2 part again on - and join last part with the latter with _ in
            between

            #FIXME: Bad English?
            #FIXME: Any better way?
            """
            folder_split = args.foldername.split('-')
            folder = ('-').join(folder_split[:-1]) + '_' + folder_split[-1]
        elif args.foldername.count('-') == 1:
            """
            If there is only one - we are happy :)
            """
            folder = args.foldername.replace('-', '_')

        if not folder.startswith('fonts-'):
            args_string += " -p fonts-" + folder
            folder = 'fonts-' + folder
        else:
            args_string += " -p " + folder

        PACKAGE = folder.split('_')[0] if folder.find('_') else folder

    # Make a call to the system function.
    return os.system("dh_make"+args_string)


###########################################################################
#                                                                         #
#  Generic functions                                                      #
#                                                                         #
###########################################################################

def print_todo():
        print("""
**************************************************
       TODO for the maintainers
**************************************************

    1. Please add short and long description in debian/control file
    2. Please add appropriate lines in debian/changelog
    3. Please add DEP5 format URI in debian/copyright
    4. Please add fonts copyright in debian/copyright
    5. Check debian/install and debian/links if they exist
    6. If font is built from source make sure font name and install target is
       proper in debian/install
    8. Please check Vcs-* field and modify accordingly, if maintaining under
       pkg-fonts its preferred to leave as is.
    7. Build the package and enjoy!
""")


def main():
    """
    Main part of the script. Kept in separate function to have a good
    redability
    """
    args = arguments.parse_args()

    os.chdir(os.path.abspath(args.foldername))

    if(check_files()):
        print("I could not find .ttf, .sfd, .otf."\
              "At least one should be present.")
        exit(256)

    if(call_dh_make(args)):
        print("dh_makefont: dh_make died so I die.")
        exit(256)

    # Lets get into Debian directory and work there
    os.chdir(os.path.abspath('debian'))

    # Remove unwanted files for font package
    for dirpath, dirname, filenames in os.walk('.'):
        for filename in filenames:
            if filename not in required_files:
                os.remove(filename)

    # Write a proper watch file
    with open('watch', 'w') as fd:
        fd.write(watch)

    # Fix control file
    update_control_file(args)

    # Fix copyright ile
    update_copyright_file(args)

    # Create install and links file
    create_install_and_links()

    # We are done tell packager what he needs to check
    print_todo()


if __name__ == "__main__":
        main()