mirror of
https://github.com/erkin/ponysay.git
synced 2024-11-22 04:27:58 +01:00
4415291c0c
The code path to handle these was confusing, as was their usage as the usage referred only to the commands while some error messages only referred to the options.
1222 lines
58 KiB
Python
Executable file
1222 lines
58 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import shutil
|
|
import sys
|
|
from zipfile import ZipFile
|
|
from subprocess import Popen, PIPE
|
|
|
|
PONYSAY_VERSION = '3.0.3'
|
|
|
|
project_dir = os.path.dirname(__file__)
|
|
|
|
manpages = [('en', 'English'), # must be first
|
|
('es', 'Spanish'),
|
|
('sv', 'Swedish'),
|
|
('tr', 'Turkish')]
|
|
|
|
sharedirs = [('ponies', 'xterm ponies', 'PONYDIR', True), # must be first
|
|
('ttyponies', 'tty ponies', 'TTYPONYDIR', True),
|
|
('extraponies', 'extra xterm ponies', 'XPONYDIR', True),
|
|
('extrattyponies', 'extra tty ponies', 'XTTYPONYDIR', True),
|
|
('quotes', 'pony quotes', 'QUOTEDIR', False),
|
|
('balloons', 'balloon styles', 'BALLOONDIR', False)]
|
|
|
|
sharefiles = [('ucs', 'ucsmap')]
|
|
|
|
commands = ['ponysay', 'ponythink', 'ponysay-tool']
|
|
|
|
shells = [('bash', '/usr/share/bash-completion/completions/ponysay', 'GNU Bash'),
|
|
('fish', '/usr/share/fish/completions/ponysay.fish', 'Friendly interactive shell'),
|
|
('zsh', '/usr/share/zsh/site-functions/_ponysay', 'zsh')]
|
|
|
|
mansections = [('ponysay', '6'),
|
|
('cowsay', '1'),
|
|
('fortune', '6')]
|
|
|
|
miscfiles = [('COPYING', '/usr/share/licenses/ponysay/COPYING'),
|
|
('LICENSE', '/usr/share/licenses/ponysay/LICENSE'),
|
|
('CREDITS', '/usr/share/licenses/ponysay/CREDITS')]
|
|
|
|
ponysaysrc = [i for i in os.listdir(os.path.join(project_dir, 'src')) if i.endswith('.py') and not i.startswith('.')]
|
|
|
|
COPY = 'copy'
|
|
HARD = 'hard'
|
|
SYMBOLIC = 'symbolic'
|
|
|
|
class Setup():
|
|
def __init__(self):
|
|
usage_script = '\033[34;1msetup.py\033[21;39m'
|
|
usage_help = '(--version | --help)'
|
|
usage_proc = '[\033[4mconfigurations\033[24m] ([build] | prebuilt | install | (uninstall|clean)[-old] | view)'
|
|
|
|
usage = '%s %s\n%s %s' % (usage_script, usage_help, usage_script, usage_proc)
|
|
|
|
usage = usage.replace('\033[', '\0')
|
|
for sym in ('[', ']', '(', ')', '|', '...'):
|
|
usage = usage.replace(sym, '\033[2m' + sym + '\033[22m')
|
|
usage = usage.replace('\0', '\033[')
|
|
|
|
opts = ArgParser(program = 'setup.py',
|
|
description = 'installer for ponysay',
|
|
usage = usage)
|
|
|
|
opts.add_argumentless(alternatives = ['--help'])
|
|
opts.add_argumentless(alternatives = ['--version'])
|
|
opts.add_argumented (alternatives = ['---DESTDIR'], arg="DESTDIR")
|
|
opts.add_argumented (alternatives = ['---PREFIX'], arg="PREFIX")
|
|
|
|
opts.add_argumentless(help = 'Install everything that is not explicitly excluded',
|
|
alternatives = ['--everything', '--with-everything'])
|
|
|
|
opts.add_argumentless(help = 'Install only the essentials\nNote that this can vary depending on the version',
|
|
alternatives = ['--minimal'])
|
|
|
|
opts.add_argumentless(help = 'Install nothing (except legal documents) that is not explicitly included',
|
|
alternatives = ['--nothing', '--with-nothing'])
|
|
|
|
for command in commands:
|
|
opts.add_argumentless(help = 'Do not install the %s command' % (command),
|
|
alternatives = ['--without-' + command, '--without-' + command + '-command'])
|
|
|
|
opts.add_argumented (help = 'Install the %s command, and set file name\nDefault = /usr/bin/%s' % (command, command),
|
|
alternatives = ['--with-' + command, '--with-' + command + '-command'], arg='EXEC')
|
|
|
|
opts.add_argumentless(help = 'Do not install a user shared cache',
|
|
alternatives = ['--without-shared-cache'])
|
|
|
|
opts.add_argumented (help = 'Install a user shared cache at CACHEDIR\nDefault = /var/cache/ponysay',
|
|
alternatives = [ '--with-shared-cache'], arg='CACHEDIR')
|
|
|
|
for shell in shells:
|
|
opts.add_argumentless(help = 'Do not install completion for ' + shell[2],
|
|
alternatives = ['--without-' + shell[0], '--without-' + shell[0] + '-completion'])
|
|
|
|
opts.add_argumented (help = 'Set file name for the completion for ponysay in' + shell[2],
|
|
alternatives = ['--with-' + shell[0], '--with-' + shell[0] + '-completion'], arg='PONYSAY_%s_FILE' % (shell[0].upper()))
|
|
|
|
opts.add_argumentless(help = 'Only install explicitly included shell completions',
|
|
alternatives = ['--without-shell', '--without-shell-completion'])
|
|
|
|
opts.add_argumented (help = 'Set share/ directory used for shell completions\nDefault = $SHAREDIR',
|
|
alternatives = ['--with-shell', '--with-shell-completion'], arg='SHAREDIR')
|
|
|
|
opts.add_argumentless(help = 'Do not install PDF manual\nDefault',
|
|
alternatives = ['--without-pdf', '--without-pdf-manual'])
|
|
|
|
opts.add_argumented (help = 'Set directory for PDF manual\nDefault = $PREFIX/doc',
|
|
alternatives = ['--with-pdf', '--with-pdf-manual'], arg='DOCDIR')
|
|
|
|
opts.add_argumentless(help = 'Do not compress PDF manual\nDefault',
|
|
alternatives = ['--without-pdf-compression', '--without-pdf-manual-compression'])
|
|
|
|
opts.add_argumented (help = 'Select compression for PDF manual\nDefault = gz, xz is also recognised',
|
|
alternatives = ['--with-pdf-compression', '--with-pdf-manual-compression'], arg='COMPRESSION')
|
|
|
|
opts.add_argumentless(help = 'Do not install info manual',
|
|
alternatives = ['--without-info', '--without-info-manual'])
|
|
|
|
opts.add_argumented (help = 'Set directory for info manual\nDefault = $SHARE/info',
|
|
alternatives = ['--with-info', '--with-info-manual'], arg='INFODIR')
|
|
|
|
opts.add_argumentless(help = 'Do not use install-info when installing info manual',
|
|
alternatives = ['--without-info-install', '--without-info-manual-install'])
|
|
|
|
opts.add_argumented (help = 'Use install-info when installing info manual, and set description\nDefault',
|
|
alternatives = ['--with-info-install', '--with-info-manual-install'], arg='DESCRIPTION')
|
|
|
|
opts.add_argumentless(help = 'Do not compress info manual',
|
|
alternatives = ['--without-info-compression', '--without-info-manual-compression'])
|
|
|
|
opts.add_argumented (help = 'Select compression for info manual\nDefault = gz, xz is also recognised',
|
|
alternatives = ['--with-info-compression', '--with-info-manual-compression'], arg='COMPRESSION')
|
|
|
|
for man in manpages:
|
|
opts.add_argumentless(help = 'Do not install %s manpage manual' % (man[1]),
|
|
alternatives = ['--without-man-%s' % (man[0]), '--without-manpage-%s' % (man[0]), '--without-man-manual-%s' % (man[0]),
|
|
'--without-%s-man' % (man[0]), '--without-%s-manpage' % (man[0]), '--without-%s-man-manual' % (man[0])])
|
|
|
|
opts.add_argumented (help = 'Set directory for %s manpage\nDefault = $SHARE/man' % (man[1]),
|
|
alternatives = ['--with-man-%s' % (man[0]), '--with-manpage-%s' % (man[0]), '--with-man-manual-%s' % (man[0]),
|
|
'--with-%s-man' % (man[0]), '--with-%s-manpage' % (man[0]), '--with-%s-man-manual' % (man[0])], arg='MANDIR')
|
|
|
|
opts.add_argumentless(help = 'Do not install any manpages',
|
|
alternatives = ['--without-man', '--without-manpage', '--without-man-manual'])
|
|
|
|
opts.add_argumented (help = 'Set directory for all man pages\nDefault = $SHARE/man',
|
|
alternatives = ['--with-man', '--with-manpage', '--with-man-manual'], arg='MANDIR')
|
|
|
|
for man in manpages:
|
|
opts.add_argumentless(help = 'Do not compress %s manpage' % (man[1]),
|
|
alternatives = ['--without-man-%s-compression' % (man[0]), '--without-manpage-%s-compression' % (man[0]), '--without-man-manual-%s-compression' % (man[0]),
|
|
'--without-%s-man-compression' % (man[0]), '--without-%s-manpage-compression' % (man[0]), '--without-%s-man-manual-compression' % (man[0])])
|
|
|
|
opts.add_argumented (help = 'Select compression for %s manpage\nDefault = gz, xz is also recognised' % (man[1]),
|
|
alternatives = ['--with-man-%s-compression' % (man[0]), '--with-manpage-%s-compression' % (man[0]), '--with-man-manual-%s-compression' % (man[0]),
|
|
'--with-%s-man-compression' % (man[0]), '--with-%s-manpage-compression' % (man[0]), '--with-%s-man-manual-compression' % (man[0])],
|
|
arg='COMPRESSION')
|
|
|
|
opts.add_argumentless(help = 'Do not compress any installed manpage',
|
|
alternatives = ['--without-man-compression', '--without-manpage-compression', '--without-man-manual-compression'])
|
|
|
|
opts.add_argumented (help = 'Select compression for installed manpages\nDefault = gz, xz is also recognised',
|
|
alternatives = ['--with-man-compression', '--with-manpage-compression', '--with-man-manual-compression'], arg='COMPRESSION')
|
|
|
|
for man in mansections:
|
|
opts.add_argumented (help = 'Change the section for the %s manpage\nDefault = %s' % man,
|
|
alternatives = ['--man-section-%s' % (man[0]), '--%s-manpage-section' % (man[0]),
|
|
'--man-section-%s' % (man[0]), '--%s-manpage-section' % (man[0])], arg='SECTION')
|
|
|
|
for dir in sharedirs:
|
|
opts.add_argumentless(help = 'Do not install ' + dir[1],
|
|
alternatives = ['--without-' + dir[0]])
|
|
|
|
opts.add_argumentless(help = 'Install %s\nDefault' % dir[1],
|
|
alternatives = [ '--with-' + dir[0]])
|
|
|
|
opts.add_argumentless(help = 'Do not install UCS pony name map',
|
|
alternatives = ['--without-ucs', '--without-ucs-names'])
|
|
|
|
opts.add_argumentless(help = 'Install UCS pony name map\nDefault',
|
|
alternatives = ['--with-ucs', '--with-ucs-names'])
|
|
|
|
opts.add_argumentless(help = 'Let the installer set the env name for python in ponysay\nDefault',
|
|
alternatives = ['--without-custom-env-python'])
|
|
|
|
opts.add_argumented (help = 'Set the env name for python in ponysay',
|
|
alternatives = ['--with-custom-env-python'], arg='PYTHON')
|
|
|
|
opts.add_argumented (help = 'Set a prefix to all implicit directories\nDefault = /usr',
|
|
alternatives = ['--prefix'], arg='PREFIX')
|
|
|
|
opts.add_argumentless(help = 'Change all implicit configurations to fit local user a installation for the current user',
|
|
alternatives = ['--private'])
|
|
|
|
opts.add_argumentless(help = 'Change all implicit directories to fit installation to /opt',
|
|
alternatives = ['--opt'])
|
|
|
|
opts.add_argumented (help = 'Set the system\'s directory for command executables\nDefault = $PREFIX/bin',
|
|
alternatives = ['--bin-dir', '--bindir'], arg='BINDIR')
|
|
|
|
opts.add_argumented (alternatives = ['--sbin-dir', '--sbindir'], arg='SBINDIR')
|
|
|
|
opts.add_argumented (help = 'Set the system\'s directory for non-executable libraries\nDefault = $PREFIX/lib/ponysay\nNot used.',
|
|
alternatives = ['--lib-dir', '--libdir'], arg='LIBDIR')
|
|
|
|
opts.add_argumented (help = 'Set the system\'s directory for non-command executables\nDefault = $PREFIX/libexec/ponysay\nNot used.',
|
|
alternatives = ['--libexec-dir', '--libexecdir'], arg='LIBEXECDIR')
|
|
|
|
opts.add_argumented (help = 'Set the system\'s directory for resource files\nDefault = $PREFIX/share',
|
|
alternatives = ['--share-dir', '--sharedir'], arg='SHAREDIR')
|
|
|
|
opts.add_argumented (help = 'Set the system\'s local specific configuration directory\nDefault = /etc',
|
|
alternatives = ['--sysconf-dir', '--sysconfdir'], arg='SYSCONFDIR')
|
|
|
|
opts.add_argumented (help = 'Set the system\'s directory for cache directories\nDefault = /var/cache',
|
|
alternatives = ['--cache-dir', '--cachedir'], arg='CACHEDIR')
|
|
|
|
opts.add_argumented (help = 'Set off environment for installation\nEmpty by default',
|
|
alternatives = ['--dest-dir', '--destdir'], arg='DESTDIR')
|
|
|
|
opts.add_argumented (help = 'Set how to link identical files\nDefault = symbolic, copy and hard are also recognised',
|
|
alternatives = ['--linking'], arg='TYPE')
|
|
|
|
opts.add_argumented (help = 'Install all ponies or only the completely free ponies\nThis option is manditory, use strict, full, true or yes ' +
|
|
'for only free ponies,\nand partial, sloppy, false or no for all ponies',
|
|
alternatives = ['--freedom'], arg='FREEDOM')
|
|
|
|
opts.parse()
|
|
|
|
self.linking = SYMBOLIC
|
|
if opts.opts['--linking'] is not None:
|
|
self.linking = opts.opts['--linking'][0]
|
|
|
|
self.free = None
|
|
if opts.opts['--freedom'] is not None:
|
|
if opts.opts['--freedom'][0].lower() in ('strict', 'full', 'true', 'yes'):
|
|
self.free = True
|
|
elif opts.opts['--freedom'][0].lower() in ('partial', 'sloppy', 'false', 'no'):
|
|
self.free = False
|
|
def checkFreedom():
|
|
if self.free is None:
|
|
if (opts.opts['--version'] is None) and ((len(opts.files) != 1) or (opts.files[0] != 'version')):
|
|
print('')
|
|
print('You need to select your freedom, add --freedom=strict or --freedom=partial.')
|
|
print('')
|
|
print('--freedom=strict will install only ponies that are completely free.')
|
|
print('--freedom=partial will install all ponies, even if they are not free.')
|
|
print('')
|
|
print('')
|
|
exit(255)
|
|
|
|
if (opts.opts['---DESTDIR'] is not None) and (opts.opts['--dest-dir'] is None):
|
|
destdir = opts.opts['---DESTDIR'][0]
|
|
if len(destdir) > 0:
|
|
opts.opts['--dest-dir'] = [destdir]
|
|
|
|
if (opts.opts['---PREFIX'] is not None) and (opts.opts['--prefix'] is None):
|
|
prefix = opts.opts['---PREFIX'][0]
|
|
if len(prefix) > 0:
|
|
opts.opts['--prefix'] = [prefix]
|
|
|
|
if opts.opts['--help'] is not None:
|
|
opts.help()
|
|
elif opts.opts['--version'] is not None:
|
|
print('Ponysay %s installer' % (PONYSAY_VERSION))
|
|
elif len(opts.files) != 1:
|
|
opts.print_fatal('A single command is expected on the command line.')
|
|
opts.usage()
|
|
else:
|
|
method = opts.files[0]
|
|
if method == 'clean': self.clean()
|
|
elif method == 'clean-old': self.cleanOld()
|
|
else:
|
|
conf = self.configure(opts.opts)
|
|
self.viewconf(conf)
|
|
os.umask(0o022)
|
|
|
|
if method == 'build':
|
|
checkFreedom()
|
|
self.build(conf)
|
|
|
|
elif method == 'prebuilt':
|
|
checkFreedom()
|
|
self.applyDestDir(conf)
|
|
self.install(conf)
|
|
|
|
elif method == 'install':
|
|
checkFreedom()
|
|
self.build(conf)
|
|
self.applyDestDir(conf)
|
|
self.install(conf)
|
|
self.clean()
|
|
|
|
elif method == 'uninstall':
|
|
self.uninstall(conf)
|
|
|
|
elif method == 'uninstall-old':
|
|
self.uninstallOld(conf)
|
|
|
|
elif not method == 'view':
|
|
opts.help()
|
|
|
|
def viewconf(self, conf):
|
|
'''
|
|
Display configurations
|
|
'''
|
|
|
|
RED = '\033[31m%s\033[39m'
|
|
GREEN = '%s\033[32m%s\033[39m'
|
|
YELLOW = '\033[33m%s\033[39m'
|
|
|
|
for command in commands:
|
|
if conf[command] is not None: print(GREEN % ('Installing command ' + command + ' as ', conf[command]))
|
|
else: print(RED % ('Skipping installion of command ' + command))
|
|
if conf['shared-cache'] is not None: print(GREEN % ('Installing shared cache at ', conf['shared-cache']))
|
|
else: print(RED % ('Skipping installation of shared cache'))
|
|
for shell in [item[0] for item in shells]:
|
|
if conf[shell] is not None: print(GREEN % ('Installing auto-completion for ' + shell + ' as ', conf[shell]))
|
|
else: print(RED % ('Skipping installation of auto-completion for ' + shell))
|
|
if conf['pdf'] is not None: print(GREEN % ('Installing PDF manual to ', conf['pdf']))
|
|
else: print(RED % ('Skipping installation of PDF manual'))
|
|
if conf['pdf-compression'] is not None: print(GREEN % ('Compressing PDF manual with ', conf['pdf-compression']))
|
|
else: print(RED % ('Skipping compression of PDF manual'))
|
|
if conf['info'] is not None: print(GREEN % ('Installing info manual to ', conf['info']))
|
|
else: print(RED % ('Skipping installation of info manual'))
|
|
if conf['info-install'] is not None: print(GREEN % ('Installing info manual with install-info with description: ', conf['info-install']))
|
|
else: print(RED % ('Skipping installation of info manual with install-info'))
|
|
if conf['info-compression'] is not None: print(GREEN % ('Compressing info manual with ', conf['info-compression']))
|
|
else: print(RED % ('Skipping compression of info manual'))
|
|
for man in manpages:
|
|
key = 'man-' + man[0]
|
|
if conf[key] is not None: print(GREEN % ('Installing ' + man[1] + ' manpage to ', conf[key]))
|
|
else: print(RED % ('Skipping installation of ' + man[1] + ' manpage'))
|
|
key += '-compression'
|
|
if conf[key] is not None: print(GREEN % ('Compressing ' + man[1] + ' manpage with ', conf[key]))
|
|
else: print(RED % ('Skipping compression of ' + man[1] + ' manpage'))
|
|
for man in mansections: print(GREEN % ('References to manpage for ' + man[0] + ' points to section ', conf['man-section-' + man[0]]))
|
|
for dir in sharedirs:
|
|
if conf[dir[0]] is not None: print(GREEN % ('Installing ' + dir[1] + ' to ', conf['share-dir'] + '/' + dir[0]))
|
|
else: print(RED % ('Skipping installation of ' + dir[1]))
|
|
for file in sharefiles:
|
|
if conf[file[0]] is not None: print(GREEN % ('Installing ' + file[1] + ' as ', conf['share-dir'] + '/' + file[0]))
|
|
else: print(RED % ('Skipping installation of ' + file[1]))
|
|
if conf['custom-env-python'] is not None: print(GREEN % ('Using custom env reference in python script shebang: ', conf['custom-env-python']))
|
|
else: print(YELLOW % ('Looking for best env reference in python script shebang'))
|
|
for miscfile in miscfiles: print(GREEN % ('Installing ' + miscfile[0] + ' to ', conf[miscfile[0]]))
|
|
print('Using system configuration directory: ' + conf['sysconf-dir'])
|
|
print('Prefered linking style: ' + self.linking)
|
|
print('Using umask: 022 (only owner can do modifications)')
|
|
if self.free is None: print(YELLOW % ('\033[01m--freedom is manditory and has not be specified\033[21m'))
|
|
elif self.free: print(GREEN % ('', 'Installing only fully free parts of the package'))
|
|
else: print(RED % ('Installing \033[1mnot\033[21m only fully free parts of the package'))
|
|
|
|
print()
|
|
|
|
def build(self, conf):
|
|
'''
|
|
Compile ponysay
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mCompiling...\033[21m')
|
|
|
|
def compressCommand(ext):
|
|
if ext == 'gz': return 'gzip -9 -f'
|
|
if ext == 'xz': return 'xz -9e -f'
|
|
|
|
def compress(source, destination, ext):
|
|
print('%s < %s > %s' % (compressCommand(ext), source, destination))
|
|
(fileout, filein) = (None, None)
|
|
try:
|
|
fileout = open(destination, 'w+')
|
|
filein = open(source, 'r')
|
|
Popen(compressCommand(ext).split(' '), stdout=fileout, stdin=filein).communicate()
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
|
|
(fileout, filein) = (None, None)
|
|
|
|
env = conf['custom-env-python']
|
|
if env is None:
|
|
try:
|
|
(out, err) = Popen(['env', 'python', '--version'], stdout=PIPE, stderr=PIPE).communicate()
|
|
out = out.decode('utf8', 'replace') + err.decode('utf8', 'replace')
|
|
out = out.replace('\n', '')
|
|
env = out.split(' ')[1].split('.')[0]
|
|
if int(env) < 3: env = 'python3'
|
|
else: env = 'python'
|
|
except:
|
|
env = 'python3'
|
|
mane = False
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
mane = True
|
|
break
|
|
if mane:
|
|
for src in ponysaysrc:
|
|
try:
|
|
fileout = open('src/%s.install' % src, 'wb+')
|
|
filein = open('src/%s' % src, 'rb')
|
|
data = filein.read().decode('utf-8', 'replace')
|
|
|
|
if '#!/usr/bin/env python3' in data:
|
|
data = data.replace('#!/usr/bin/env python3', '#!/usr/bin/env ' + env)
|
|
else:
|
|
data = data.replace('#!/usr/bin/env python', '#!/usr/bin/env ' + env)
|
|
data = data.replace('/usr/share/ponysay/', conf['share-dir'] + ('' if conf['share-dir'].endswith('/') else '/'))
|
|
data = data.replace('/etc/', conf['sysconf-dir'] + ('' if conf['sysconf-dir'].endswith('/') else '/'))
|
|
data = data.replace('\nVERSION = \'dev\'', '\nVERSION = \'%s\'' % (PONYSAY_VERSION))
|
|
|
|
fileout.write(data.encode('utf-8'))
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
print('Creating uncompressed zip file ponysay.zip with files from src: ' + ' '.join(ponysaysrc))
|
|
myzip = None
|
|
try:
|
|
myzip = ZipFile('ponysay.zip', 'w')
|
|
for src in ponysaysrc:
|
|
myzip.write('src/%s.install' % src, src)
|
|
finally:
|
|
myzip.close()
|
|
os.chmod('ponysay.zip', 0o755)
|
|
try:
|
|
fileout = open('ponysay.install', 'wb+')
|
|
filein = open('ponysay.zip', 'rb')
|
|
fileout.write(('#!/usr/bin/env %s\n' % env).encode('utf-8'))
|
|
fileout.write(filein.read())
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
|
|
for man in manpages:
|
|
key = 'man-' + man[0]
|
|
section = conf['man-section-ponysay']
|
|
if man is manpages[0]: lang = ''
|
|
else: lang = '.' + man[0]
|
|
if conf[key] is not None:
|
|
src = 'manuals/manpage' + lang + '.6'
|
|
dest = src + '.install'
|
|
(fileout, filein) = (None, None)
|
|
try:
|
|
fileout = open(dest, 'wb+')
|
|
filein = open(src, 'rb')
|
|
data = filein.read().decode('utf-8', 'replace')
|
|
|
|
data = data.replace('\n.TH PONYSAY 0', '\n.TH PONYSAY ' + conf['man-section-ponysay'])
|
|
for section in [item[0] for item in mansections]:
|
|
data = data.replace('\n.BR %s (0)' % (section), '\n.BR %s (%s)' % (section, conf['man-section-' + section]))
|
|
|
|
fileout.write(data.encode('utf-8'))
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
src = dest
|
|
ext = conf[key + '-compression']
|
|
if ext is not None:
|
|
dest = 'manuals/manpage' + lang + '.6.' + ext
|
|
compress(src, dest, ext)
|
|
|
|
if conf['info'] is not None:
|
|
print('makeinfo manuals/ponysay.texinfo')
|
|
os.system('makeinfo manuals/ponysay.texinfo')
|
|
ext = conf['info-compression']
|
|
if ext is not None:
|
|
compress('ponysay.info', 'ponysay.info.' + ext, ext)
|
|
|
|
if conf['pdf-compression'] is not None:
|
|
ext = conf['pdf-compression']
|
|
if ext is not None:
|
|
compress('ponysay.pdf', 'ponysay.pdf.' + ext, ext)
|
|
|
|
for command in commands:
|
|
source = 'completion/ponysay'
|
|
sourceed = 'completion/ponysay.%s' % (command)
|
|
try:
|
|
fileout = open(sourceed, 'wb+')
|
|
filein = open(source, 'rb')
|
|
data = filein.read().decode('utf-8', 'replace')
|
|
|
|
if data.startswith('(ponysay\n'):
|
|
data = ('(%s ' % command) + data[len('(ponysay\n'):]
|
|
elif data.startswith('(ponysay '):
|
|
data = ('(%s ' % command) + data[len('(ponysay '):]
|
|
elif '\n(ponysay\n' in data:
|
|
edpos = data.find('\n(ponysay\n')
|
|
data = data[:edpos] + ('\n(%s\n' % command) + data[edpas + len('\n(ponysay\n'):]
|
|
elif '\n(ponysay ' in data:
|
|
data = data[:edpos] + ('\n(%s ' % command) + data[edpas + len('\n(ponysay '):]
|
|
else:
|
|
raise Exception('File %s does not look like expected' % source)
|
|
|
|
fileout.write(data.encode('utf-8'))
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
|
|
for shell in [item[0] for item in shells]:
|
|
if conf[shell] is not None:
|
|
for command in commands:
|
|
sourceed = 'completion/ponysay.%s' % (command)
|
|
generated = 'completion/%s-completion.%s' % (shell, command)
|
|
generatorcmd = './completion/auto-auto-complete.py %s --output %s --source %s' % (shell, generated, sourceed)
|
|
Popen(generatorcmd.split(' ')).communicate()
|
|
if conf[command] is not None:
|
|
dest = generated + '.install'
|
|
(fileout, filein) = (None, None)
|
|
try:
|
|
fileout = open(dest, 'wb+')
|
|
filein = open(generated, 'rb')
|
|
data = filein.read().decode('utf-8', 'replace')
|
|
|
|
data = data.replace('/usr/bin/ponysay', conf[command])
|
|
data = data.replace('/ponysay', '\0')
|
|
data = data.replace('ponysay', command)
|
|
data = data.replace('/usr/share/ponysay/', conf['share-dir'] if conf['share-dir'].endswith('/') else (conf['share-dir'] + '/'))
|
|
data = data.replace('\0', '/ponysay')
|
|
|
|
fileout.write(data.encode('utf-8'))
|
|
finally:
|
|
if fileout is not None: fileout.close()
|
|
if filein is not None: filein .close()
|
|
|
|
if conf['quotes'] is not None:
|
|
self.removeLists([], ['quotes'])
|
|
os.mkdir('quotes')
|
|
ponymap = None
|
|
try:
|
|
ponymap = open('ponyquotes/ponies', 'rb')
|
|
ponies = [line for line in ponymap.read().decode('utf-8', 'replace').split('\n')]
|
|
for _ponies in ponies:
|
|
for pony in _ponies.split('+'):
|
|
if len(pony) > 0:
|
|
print('Generating quote files for \033[34m' + pony + '\033[39m')
|
|
for file in os.listdir('ponyquotes'):
|
|
if file.startswith(pony + '.'):
|
|
if os.path.isfile('ponyquotes/' + file):
|
|
shutil.copy('ponyquotes/' + file, 'quotes/' + _ponies + file[file.find('.'):])
|
|
finally:
|
|
if ponymap is not None:
|
|
ponymap.close()
|
|
|
|
for (sharedir, hasponies) in [(sharedir[0], sharedir[3]) for sharedir in sharedirs]:
|
|
if hasponies and os.path.isdir(sharedir):
|
|
for toolcommand in ('--dimensions', '--metadata'):
|
|
if not self.free:
|
|
print('%s, %s, %s' % ('./src/ponysaytool.py', toolcommand, sharedir))
|
|
Popen(['./src/ponysaytool.py', toolcommand, sharedir], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate()
|
|
else:
|
|
params = ['./src/ponysaytool.py', toolcommand, sharedir, '--']
|
|
for sharefile in os.listdir(sharedir):
|
|
if sharefile.endswith('.pony') and (sharefile != '.pony'):
|
|
if not Setup.validateFreedom(sharedir + '/' + sharefile):
|
|
print('Skipping metadata correction for %s/%s, did not pass validation process made by setup settings' % (sharedir, sharefile))
|
|
else:
|
|
params.append(sharefile)
|
|
print('%s, %s, %s (with files)' % ('./src/ponysaytool.py', toolcommand, sharedir))
|
|
Popen(params, stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate()
|
|
|
|
print()
|
|
|
|
def install(self, conf):
|
|
'''
|
|
Install compiled ponysay
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mInstalling...\033[21m')
|
|
|
|
dests = []
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
dests.append(conf[command])
|
|
if len(dests) > 0:
|
|
self.cp(False, 'ponysay.install', dests)
|
|
print('Setting mode for ponysay.install copies to 755')
|
|
if self.linking == COPY:
|
|
for dest in dests:
|
|
os.chmod(dest, 0o755)
|
|
else:
|
|
os.chmod(dests[0], 0o755)
|
|
if conf['shared-cache'] is not None:
|
|
dir = conf['shared-cache']
|
|
if not os.path.exists(dir):
|
|
pdir = dir[:dir.rfind('/') + 1]
|
|
if not os.path.exists(pdir):
|
|
print('Creating intermediate-level directories needed for ' + dir)
|
|
os.makedirs(pdir)
|
|
print('Creating directory ' + dir)
|
|
os.mkdir(dir)
|
|
print('Setting permission mode mask for ' + dir + ' to 7777')
|
|
Popen('chmod -R 7777 -- \'' + dir.replace('\'', '\'\\\'\'') + '\'', shell=True).wait()
|
|
print('Setting group for ' + dir + ' users')
|
|
Popen('chown -R :users -- \'' + dir.replace('\'', '\'\\\'\'') + '\'', shell=True).wait()
|
|
for shell in [item[0] for item in shells]:
|
|
if conf[shell] is not None:
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
src = 'completion/%s-completion.%s.install' % (shell, command)
|
|
dest = conf[shell].replace('ponysay', command)
|
|
self.cp(False, src, [dest])
|
|
if conf['pdf'] is not None:
|
|
src = 'ponysay.pdf' + ('' if conf['pdf-compression'] is None else '.' + conf['pdf-compression'])
|
|
dest = conf['pdf'] + '/' + src
|
|
self.cp(False, src, [dest])
|
|
if conf['info'] is not None:
|
|
installinfo = []
|
|
dests = []
|
|
ext = ('' if conf['info-compression'] is None else '.' + conf['info-compression'])
|
|
src = 'ponysay.info' + ext
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
dests.append(conf['info'] + '/' + command + '.info' + ext)
|
|
if conf['info-install'] is not None:
|
|
cmdarr = ['install-info', '--entry=Miscellaneous', '--description=' + conf['info-install'], '--dir-file=' + conf['info'] + '/dir', dest]
|
|
cmd = ' '.join(['\'%s\'' % (elem.replace('\'', '\'\\\'\'')) for elem in cmdarr])
|
|
installinfo.append((cmd, 'Installing info manual ' + dest + ' with install-info'))
|
|
self.cp(False, src, dests)
|
|
for pair in installinfo:
|
|
print(pair[1])
|
|
os.system(pair[0])
|
|
for man in manpages:
|
|
key = 'man-' + man[0]
|
|
section = conf['man-section-ponysay']
|
|
if man is manpages[0]: sub = 'man' + section
|
|
else: sub = man[0] + '/man' + section
|
|
if man is manpages[0]: lang = ''
|
|
else: lang = '.' + man[0]
|
|
if conf[key] is not None:
|
|
src = 'manuals/manpage' + lang + '.6.' + ('install' if conf[key + '-compression'] is None else conf[key + '-compression'])
|
|
dests = []
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
dest = '%s/%s/%s.%s%s' % (conf[key], sub, command, section, '' if conf[key + '-compression'] is None else '.' + conf[key + '-compression'])
|
|
dests.append(dest)
|
|
self.cp(False, src, dests)
|
|
ponyshare = conf['share-dir']
|
|
if not ponyshare.endswith('/'):
|
|
ponyshare += '/'
|
|
for dir in sharedirs:
|
|
if conf[dir[0]] is not None:
|
|
self.cp(True, dir[0], [ponyshare + dir[0]], Setup.validateFreedom if self.free else None)
|
|
for file in sharefiles:
|
|
if conf[file[0]] is not None:
|
|
self.cp(False, 'share/' + file[1], [ponyshare + file[0]], Setup.validateFreedom if self.free else None)
|
|
for file in miscfiles:
|
|
self.cp(False, file[0], [conf[file[0]]], Setup.validateFreedom if self.free else None)
|
|
print()
|
|
|
|
def uninstall(self, conf):
|
|
'''
|
|
Uninstall ponysay
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mUninstalling...\033[21m')
|
|
|
|
(files, dirs, infos) = ([], [], [])
|
|
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
files.append(conf[command])
|
|
if conf['shared-cache'] is not None:
|
|
dirs.append(conf['shared-cache'])
|
|
for shell in [item[0] for item in shells]:
|
|
if conf[shell] is not None:
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
files.append(conf[shell].replace('ponysay', command))
|
|
if conf['pdf'] is not None:
|
|
files.append(conf['pdf'] + '/ponysay.pdf' + ('' if conf['pdf-compression'] is None else '.' + conf['pdf-compression']))
|
|
if conf['info'] is not None:
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
file = conf['info'] + '/' + command + '.info' + ('' if conf['info-compression'] is None else '.' + conf['info-compression'])
|
|
files.append(file)
|
|
if conf['info-install'] is not None:
|
|
infos.append(file)
|
|
for man in [item[0] for item in manpages]:
|
|
key = 'man-' + man
|
|
section = conf['man-section-ponysay']
|
|
if man is manpages[0]: sub = 'man' + section
|
|
else: sub = man[0] + '/man' + section
|
|
if conf[key] is not None:
|
|
for command in commands:
|
|
if conf[command] is not None:
|
|
files.append('%s/%s/%s.%s%s' % (conf[key], sub, command, section, '' if conf[key + '-compression'] is None else '.' + conf[key + '-compression']))
|
|
ponyshare = conf['share-dir']
|
|
if not ponyshare.endswith('/'):
|
|
ponyshare += '/'
|
|
for dir in sharedirs:
|
|
if conf[dir[0]] is not None:
|
|
dirs.append(ponyshare + dir[0])
|
|
for file in sharefiles:
|
|
if conf[file[0]] is not None:
|
|
files.append(ponyshare + file[0])
|
|
for file in miscfiles:
|
|
files.append(conf[file[0]])
|
|
|
|
for info in infos:
|
|
cmdarr = ['install-info', '--delete', '--dir-file=' + conf['info'] + '/dir', info]
|
|
cmd = ' '.join(['\'%s\'' % (elem.replace('\'', '\'\\\'\'')) for elem in cmdarr])
|
|
print('Uninstalling info manual ' + info + ' with install-info')
|
|
os.system(cmd)
|
|
|
|
self.removeLists(files, dirs)
|
|
print()
|
|
|
|
def uninstallOld(self, conf):
|
|
'''
|
|
Uninstall file ponysay no longer uses
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mUninstalling old files...\033[21m')
|
|
|
|
instdir = conf['~prefix~'] + '/usr'
|
|
files = [instdir + f for f in ['bin/ponysaylist.pl', 'bin/ponysaytruncater', 'bin/ponysay.py', 'bin/ponythink.py']]
|
|
dirs = [instdir + d for d in ['lib/ponysay', 'share/ponies', 'share/ttyponies']]
|
|
#$(instdir)/lib/ponysay/truncater
|
|
#$(instdir)/lib/ponysay/list.pl
|
|
#$(instdir)/lib/ponysay/linklist.pl
|
|
#$(instdir)/lib/ponysay/pq4ps
|
|
#$(instdir)/lib/ponysay/pq4ps.pl
|
|
#$(instdir)/lib/ponysay/pq4ps-list
|
|
#$(instdir)/lib/ponysay/pq4ps-list.pl
|
|
|
|
self.removeLists(files, dirs)
|
|
print()
|
|
|
|
def clean(self):
|
|
'''
|
|
Remove compiled files
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mCleaning...\033[21m')
|
|
|
|
files = ['ponysay.info', 'ponysay.info.gz', 'ponysay.info.xz', 'ponysay.pdf.gz', 'ponysay.pdf.xz', 'ponysay.install', 'ponysay.zip']
|
|
files += ['src/%s.install' % file for file in ponysaysrc]
|
|
dirs = ['quotes']
|
|
for comp in ['install', 'gz', 'xz']:
|
|
for man in manpages:
|
|
if man is manpages[0]: man = ''
|
|
else: man = '.' + man[0]
|
|
for sec in range(0, 9):
|
|
files.append('manuals/manpage%s.%s.%s' % (man, str(sec), comp))
|
|
for shell in [item[0] for item in shells]:
|
|
for command in commands:
|
|
files.append('completion/%s-completion.%s' % (shell, command))
|
|
files.append('completion/%s-completion.%s.install' % (shell, command))
|
|
for sharedir in [sharedir[0] for sharedir in sharedirs]:
|
|
for dimfile in ('widths', 'heights', 'onlyheights'):
|
|
files.append(sharedir + '/' + dimfile)
|
|
|
|
self.removeLists(files, dirs)
|
|
print()
|
|
|
|
def cleanOld(self):
|
|
'''
|
|
Remove compiled files ponysay is no longer compiling
|
|
'''
|
|
|
|
print('\033[1;34m::\033[39mCleaning old files...\033[21m')
|
|
|
|
files = ['truncater', 'ponysaytruncater', 'ponysay.py.install', 'ponysay.install~', 'ponysay.zip']
|
|
dirs = []
|
|
for shell in [item[0] for item in shells]:
|
|
files.append('completion/%s-completion.%s.install' % (shell, 'sh' if shell == 'bash' else shell))
|
|
files.append('completion/%s-completion-think.%s' % (shell, 'sh' if shell == 'bash' else shell))
|
|
for shell in [item[0] for item in shells]:
|
|
for command in commands:
|
|
files.append('completion/%s-completion.%s.%s' % (shell, 'sh' if shell == 'bash' else shell, command))
|
|
|
|
self.removeLists(files, dirs)
|
|
print()
|
|
|
|
def removeLists(self, files, dirs):
|
|
'''
|
|
Removes listed files and directories
|
|
'''
|
|
|
|
for file in files:
|
|
if os.path.isfile(file) or os.path.islink(file):
|
|
print('Unlinking file %s' % (file))
|
|
os.unlink(file)
|
|
dir = file
|
|
while True:
|
|
dir = dir[:dir.rfind('/')]
|
|
if ('/ponysay/' in (dir + '/')) and (len(os.listdir(dir)) == 0):
|
|
print('Removing newly empty directory %s' % (dir))
|
|
os.rmdir(dir)
|
|
else:
|
|
break;
|
|
for dir in dirs:
|
|
if os.path.isdir(dir) or os.path.islink(dir):
|
|
print('Cascadingly removing directory %s' % (dir))
|
|
if os.path.islink(dir): os.unlink(dir)
|
|
else: shutil.rmtree(dir)
|
|
while True:
|
|
dir = dir[:dir.rfind('/')]
|
|
if ('/ponysay/' in (dir + '/')) and (len(os.listdir(dir)) == 0):
|
|
print('Removing newly empty directory %s' % (dir))
|
|
os.rmdir(dir)
|
|
else:
|
|
break;
|
|
|
|
@staticmethod
|
|
def validateFreedom(filename):
|
|
'''
|
|
Check whether a file is fully free
|
|
'''
|
|
|
|
if not os.path.isdir(filename):
|
|
if filename.endswith('.pony') and (filename != '.pony') and not filename.endswith('/.pony'):
|
|
with open(filename, 'rb') as file:
|
|
data = file.read().decode('utf8', 'replace')
|
|
if data.startswith('$$$\n') and ('\n$$$\n' in data) and not data.startswith('$$$\n$$$\n'):
|
|
data = data[4 : data.find('\n$$$\n')].split('\n')
|
|
for line in data:
|
|
if ':' not in line:
|
|
continue
|
|
line = [item.strip() for item in line.split(':')]
|
|
if (len(line) == 2) and (line[0] == 'FREE'):
|
|
return line[1].lower() == 'yes'
|
|
return False
|
|
return True
|
|
|
|
def cp(self, recursive, source, destinations, validatehook = None):
|
|
'''
|
|
Copys a files or directory to multiple destinations
|
|
'''
|
|
|
|
if validatehook is not None:
|
|
if not validatehook(source):
|
|
print('Ignoring installation of file %s (did not pass validation process made by setup settings)' % source)
|
|
return
|
|
if os.path.islink(source) and (self.linking != COPY) and os.path.isdir(os.path.realpath(source)):
|
|
target = os.readlink(source)
|
|
for dest in destinations:
|
|
print('Creating symbolic link %s with target directory %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
self.removeLists([], [dest])
|
|
self.symlink(target, dest)
|
|
if os.path.islink(source) and (self.linking != COPY) and os.path.isfile(os.path.realpath(source)):
|
|
target = os.readlink(source)
|
|
if self.linking == HARD:
|
|
for dest in destinations:
|
|
print('Creating hard link %s with target file %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
self.removeLists([], [dest])
|
|
mytarget = os.path.abspath(os.path.join(os.path.dirname(dest), target))
|
|
if os.path.exists(mytarget):
|
|
os.link(mytarget, dest)
|
|
else:
|
|
print('\033[31mTarget did not exists, using symlink instead\033[39m')
|
|
self.symlink(target, dest)
|
|
else:
|
|
for dest in destinations:
|
|
print('Creating symbolic link %s with target file %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
self.removeLists([], [dest])
|
|
self.symlink(target, dest)
|
|
for dest in destinations:
|
|
dir = dest[:dest.rfind('/') + 1]
|
|
if not os.path.exists(dir):
|
|
print('Making directory ' + dir + ' with parents')
|
|
os.makedirs(dir)
|
|
if recursive:
|
|
target = destinations[0]
|
|
for dest in destinations if self.linking == COPY else [target]:
|
|
print('Copying directory %s to %s' % (source, dest))
|
|
if not os.path.exists(dest):
|
|
os.mkdir(dest)
|
|
links = []
|
|
for file in os.listdir(source):
|
|
src = source + '/' + file
|
|
if os.path.exists(src) and os.path.islink(src):
|
|
links.append((os.path.isdir(src), src, [dest + '/' + file]))
|
|
else:
|
|
self.cp(os.path.isdir(src), src, [dest + '/' + file], validatehook)
|
|
for link in links:
|
|
self.cp(link[0], link[1], link[2], validatehook)
|
|
if self.linking != COPY:
|
|
for dest in destinations[1:]:
|
|
print('Creating symbolic link %s with target directory %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
self.removeLists([], [dest])
|
|
self.symlink(target, dest)
|
|
else:
|
|
target = destinations[0]
|
|
for dest in destinations if self.linking == COPY else [target]:
|
|
print('Copying file %s to %s' % (source, dest))
|
|
shutil.copyfile(source, dest)
|
|
if self.linking == HARD:
|
|
for dest in destinations[1:]:
|
|
print('Creating hard link %s with target file %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
os.unlink(dest)
|
|
os.link(target, dest)
|
|
elif self.linking == SYMBOLIC:
|
|
for dest in destinations[1:]:
|
|
print('Creating symbolic link %s with target file %s' % (dest, target))
|
|
if os.path.exists(dest):
|
|
os.unlink(dest)
|
|
self.symlink(target, dest)
|
|
|
|
def symlink(self, target, dest):
|
|
'''
|
|
Create a symlink with a relative path
|
|
'''
|
|
|
|
if target.startswith('./') or target.startswith('../'):
|
|
os.symlink(target, dest)
|
|
elif '/' not in target:
|
|
os.symlink('./' + target, dest)
|
|
else:
|
|
targets = target.split('/')
|
|
dests = dest.split('/')
|
|
|
|
while (len(targets) > 1) and (len(dests) > 1) and (targets[0] == dests[0]):
|
|
targets = targets[1:]
|
|
dests = dests[1:]
|
|
|
|
if (len(dests) == 1):
|
|
targets = ['.'] + targets
|
|
else:
|
|
targets = (['..'] * (len(dests) - 1)) + targets
|
|
|
|
os.symlink('/'.join(targets), dest)
|
|
|
|
def configure(self, opts):
|
|
'''
|
|
Parses configurations
|
|
'''
|
|
|
|
(defaults, conf) = ({}, {})
|
|
|
|
for command in commands:
|
|
conf[command] = '/usr/bin/' + command
|
|
conf['shared-cache'] = '/var/cache/ponysay'
|
|
for shell in shells:
|
|
conf[shell[0]] = shell[1]
|
|
conf['pdf'] = '/usr/doc'
|
|
conf['pdf-compression'] = 'gz'
|
|
conf['info'] = '/usr/share/info'
|
|
conf['info-install'] = 'My Little Ponies for your terminal'
|
|
conf['info-compression'] = 'gz'
|
|
for manpage in manpages:
|
|
conf['man-' + manpage[0]] = '/usr/share/man'
|
|
conf['man-' + manpage[0] + '-compression'] = 'gz'
|
|
conf['custom-env-python'] = 'python3'
|
|
for sharedir in sharedirs:
|
|
conf[sharedir[0]] = True
|
|
for sharefile in sharefiles:
|
|
conf[sharefile[0]] = True
|
|
for miscfile in miscfiles:
|
|
conf[miscfile[0]] = miscfile[1]
|
|
conf['sysconf-dir'] = '/etc'
|
|
conf['bin-dir'] = '/usr/bin'
|
|
conf['lib-dir'] = '/usr/lib/ponysay'
|
|
conf['libexec-dir'] = '/usr/libexec/ponysay'
|
|
conf['share-dir'] = '/usr/share'
|
|
|
|
if opts['--private'] is not None:
|
|
if opts['--prefix'] is None:
|
|
opts['--prefix'] = [os.environ['HOME'] + '/.local']
|
|
|
|
prefix = '/usr'
|
|
if opts['--prefix'] is not None:
|
|
prefix = opts['--prefix'][0]
|
|
for key in conf:
|
|
if conf[key] not in (None, False, True):
|
|
if conf[key].startswith('/usr'):
|
|
conf[key] = prefix + conf[key][4:]
|
|
conf['~prefix~'] = prefix
|
|
|
|
if opts['--opt'] is not None:
|
|
if opts['--bin-dir'] is None: opts['--bin-dir'] = ['/opt/ponysay']
|
|
if opts['--lib-dir'] is None: opts['--lib-dir'] = ['/opt/ponysay']
|
|
if opts['--libexec-dir'] is None: opts['--libexec-dir'] = ['/opt/ponysay']
|
|
if opts['--share-dir'] is None: opts['--share-dir'] = ['/opt/ponysay']
|
|
if opts['--with-shared-cache'] is None: opts['--with-shared-cache'] = ['/var/opt/ponysay/cache']
|
|
|
|
for dir in ['bin', 'lib', 'libexec', 'share']:
|
|
key = dir + '-dir'
|
|
if opts['--' + key] is not None:
|
|
conf[key] = opts['--' + key][0]
|
|
if (dir == 'share') and (opts['--opt'] is None):
|
|
conf[key] += '/ponysay'
|
|
if conf[key].startswith('usr/'):
|
|
conf[key] = prefix + conf[key][3:]
|
|
if opts['--cache-dir'] is not None:
|
|
dir = opts['--cache-dir'][0]
|
|
for key in conf:
|
|
if conf[key] not in (None, False, True):
|
|
if conf[key].startswith('/var/cache'):
|
|
conf[key] = dir + conf[key][10:]
|
|
|
|
if opts['--sysconf-dir'] is not None:
|
|
conf['sysconf-dir'] = opts['--sysconf-dir'][0]
|
|
|
|
for key in conf:
|
|
defaults[key] = conf[key]
|
|
|
|
if opts['--nothing'] is not None:
|
|
opts['--minimal'] = opts['--nothing']
|
|
|
|
for key in ['custom-env-python']:
|
|
conf[key] = None
|
|
|
|
if opts['--everything'] is None:
|
|
for key in ['pdf', 'pdf-compression']:
|
|
conf[key] = None
|
|
|
|
nomanen = opts['--minimal'] is not None
|
|
for manpage in manpages:
|
|
if (manpage is not manpages[0]) or nomanen:
|
|
for key in ['man-' + manpage[0]]:
|
|
conf[key] = None
|
|
|
|
if (opts['--private'] is not None) or (opts['--minimal'] is not None):
|
|
for key in ['info-install', 'shared-cache']:
|
|
conf[key] = None
|
|
|
|
if opts['--minimal'] is not None:
|
|
for key in ['info'] + [item[0] for item in shells]:
|
|
conf[key] = None
|
|
for sharedir in sharedirs:
|
|
if sharedir is not sharedirs[0]:
|
|
conf[sharedir[0]] = None
|
|
for sharefile in sharefiles:
|
|
conf[sharefile[0]] = None
|
|
|
|
if opts['--nothing'] is not None:
|
|
for command in commands:
|
|
conf[command] = None
|
|
conf[sharedirs[0][0]] = None
|
|
|
|
for coll in [['shell', '/usr/share', [item[0] for item in shells]],
|
|
['man', '/usr/share/man', ['man-' + item[0] for item in manpages]],
|
|
['man-compression', 'gz', ['man-' + item[0] + '-compression' for item in manpages]]
|
|
]:
|
|
if opts['--without-' + coll[0]] is not None:
|
|
for item in coll[2]:
|
|
conf[item] = None
|
|
if opts['--with-' + coll[0]] is not None:
|
|
for item in coll[2]:
|
|
defaults[item] = conf[item] = defaults[item].replace(coll[1], coll[1] if opts['--with-' + coll[0]][0] is None else opts['--with-' + coll[0]][0]);
|
|
|
|
for key in conf:
|
|
if '--with-' + key not in opts:
|
|
continue
|
|
if opts['--with-' + key] is not None:
|
|
if defaults[key] in (False, True):
|
|
conf[key] = True
|
|
else:
|
|
conf[key] = defaults[key] if opts['--with-' + key][0] is None else opts['--with-' + key][0]
|
|
if opts['--without-' + key] is not None:
|
|
conf[key] = False if defaults[key] in (False, True) else None
|
|
|
|
for mansection in mansections:
|
|
if opts['--man-section-' + mansection[0]] is not None:
|
|
conf['man-section-' + mansection[0]] = opts['--man-section-' + mansection[0]][0]
|
|
else:
|
|
conf['man-section-' + mansection[0]] = mansection[1]
|
|
|
|
self.destDir = None if opts['--dest-dir'] is None else opts['--dest-dir'][0]
|
|
|
|
return conf
|
|
|
|
def applyDestDir(self, conf):
|
|
if self.destDir is not None:
|
|
for key in conf:
|
|
if conf[key] not in (None, False, True):
|
|
if conf[key].startswith('/'):
|
|
conf[key] = self.destDir + conf[key]
|
|
|
|
def unapplyDestDir(self, conf):
|
|
if self.destDir is not None:
|
|
for key in conf:
|
|
if conf[key] not in (None, False, True):
|
|
if conf[key].startswith(self.destDir):
|
|
conf[key] = conf[key][len(self.destDir):]
|
|
|
|
|
|
ARGUMENTLESS = 0
|
|
ARGUMENTED = 1
|
|
|
|
class ArgParser():
|
|
'''
|
|
Simple argument parser, a strip down of the one in ponysay and slitly modified
|
|
'''
|
|
|
|
def __init__(self, program, description, usage, longdescription = None):
|
|
'''
|
|
Constructor.
|
|
The short description is printed on same line as the program name
|
|
'''
|
|
|
|
self.__program = program
|
|
self.__description = description
|
|
self.__usage = usage
|
|
self.__longdescription = longdescription
|
|
self.__arguments = []
|
|
(self.opts, self.optmap) = ({}, {})
|
|
|
|
def add_argumentless(self, alternatives, help = None):
|
|
'''
|
|
Add option that takes no arguments
|
|
'''
|
|
|
|
ARGUMENTLESS
|
|
self.__arguments.append((ARGUMENTLESS, alternatives, None, help))
|
|
(stdalt, self.opts[stdalt]) = (alternatives[0], None)
|
|
for alt in alternatives: self.optmap[alt] = (stdalt, ARGUMENTLESS)
|
|
|
|
def add_argumented(self, alternatives, arg, help = None):
|
|
'''
|
|
Add option that takes one argument
|
|
'''
|
|
|
|
self.__arguments.append((ARGUMENTED, alternatives, arg, help))
|
|
(stdalt, self.opts[stdalt]) = (alternatives[0], None)
|
|
for alt in alternatives: self.optmap[alt] = (stdalt, ARGUMENTED)
|
|
|
|
def parse(self, argv = sys.argv):
|
|
'''
|
|
Parse arguments
|
|
'''
|
|
|
|
self.argcount = len(argv) - 1
|
|
self.files = []
|
|
(argqueue, optqueue, get) = ([], [], False)
|
|
|
|
for arg in argv[1:]:
|
|
if get:
|
|
get = False
|
|
if (arg is argv[-1]) or ((len(arg) > 2) and (arg[:2] in ('--', '++'))):
|
|
argqueue.append(None)
|
|
else:
|
|
argqueue.append(arg)
|
|
continue
|
|
if (len(arg) > 2) and (arg[:2] in ('--', '++')):
|
|
if (arg in self.optmap) and (self.optmap[arg][1] == ARGUMENTLESS):
|
|
optqueue.append(arg)
|
|
argqueue.append(None)
|
|
elif '=' in arg:
|
|
arg_opt = arg[:arg.index('=')]
|
|
if (arg_opt in self.optmap) and (self.optmap[arg_opt][1] == ARGUMENTED):
|
|
optqueue.append(arg_opt)
|
|
argqueue.append(arg[arg.index('=') + 1:])
|
|
else:
|
|
self.print_fatal('Unrecognized option {}. Use --help or consult the manual.', arg)
|
|
exit(-1)
|
|
elif (arg in self.optmap) and (self.optmap[arg][1] == ARGUMENTED):
|
|
optqueue.append(arg)
|
|
get = True
|
|
else:
|
|
self.print_fatal('Unrecognized option {}. Use --help or consult the manual.', arg)
|
|
exit(-1)
|
|
else:
|
|
self.files.append(arg)
|
|
|
|
(i, n) = (0, len(optqueue))
|
|
if len(argqueue) < n:
|
|
argqueue.append(None)
|
|
while i < n:
|
|
(opt, arg, i) = (optqueue[i], argqueue[i], i + 1)
|
|
opt = self.optmap[opt][0]
|
|
if (opt not in self.opts) or (self.opts[opt] is None):
|
|
self.opts[opt] = [arg]
|
|
else:
|
|
self.print_fatal('duplicate option {}', arg)
|
|
exit(-1)
|
|
|
|
def print_fatal(self, message, *args):
|
|
sys.stderr.write('{}: fatal: {}\n'.format(self.__program, message.format(*args)))
|
|
|
|
def usage(self):
|
|
'''
|
|
Print a short usage message.
|
|
'''
|
|
|
|
if self.__longdescription is not None:
|
|
print(self.__longdescription)
|
|
print()
|
|
print('\n\033[1mUSAGE:\033[21m', end='')
|
|
first = True
|
|
for line in self.__usage.split('\n'):
|
|
if first: first = False
|
|
else: print(' or', end='')
|
|
print('\t{}'.format(line))
|
|
|
|
print()
|
|
|
|
def help(self):
|
|
'''
|
|
Prints a colourful help message.
|
|
'''
|
|
|
|
# The usage should be terse so this header is only included in the help command.
|
|
print('\033[1m{}\033[21m - {}\n'.format(self.__program, self.__description))
|
|
|
|
self.usage()
|
|
|
|
print('\033[1mCONFIGURATIONS:\033[21m\n')
|
|
for opt in self.__arguments:
|
|
(opt_type, opt_alts, opt_arg, opt_help) = opt[0:4]
|
|
if opt_help is not None:
|
|
for opt_alt in opt_alts:
|
|
if opt_alt is opt_alts[-1]:
|
|
print('\t%s=\033[4m%s\033[24m' % (opt_alt, opt_arg) if opt_type == ARGUMENTED else '\t' + opt_alt)
|
|
else:
|
|
print('\t\033[2m' + opt_alt + '\033[22m')
|
|
first = True
|
|
for line in opt_help.split('\n'):
|
|
print(('\t\t\033[32;1m%s\033[21;39m' if first else '\t\t%s') % (line))
|
|
first = False
|
|
print()
|
|
print()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
Setup()
|