tvheadend/support/mkbundle

170 lines
4.3 KiB
Python
Executable file

#!/usr/bin/env python
#
# Replacement for old mkbundle script that creates a full file heirarchy
#
import os, sys, re
import gzip
try:
from cStringIO import StringIO as BytesIO
except:
from io import BytesIO
from optparse import OptionParser
# Add reverse path split
def rsplit ( p ):
i = p.find(os.path.sep)
if i != -1:
return (p[:i], p[i+1:])
else:
return (p, '')
# Process command line
optp = OptionParser()
optp.add_option('-z', '--gzip', action='store_true',
help='Compress the files with gzip')
optp.add_option('-l', '--gzlevel', type='int', default=9,
help='Specify compression level if using gzip')
optp.add_option('-o', '--output', default=None,
help='Specify output file (default /dev/stdout)')
optp.add_option('-d', '--deps', default=None,
help='Specify deps file to update during run')
(opts, args) = optp.parse_args()
# Setup
outf = sys.stdout
if opts.output:
outf = open(opts.output, 'w')
depf = None
if opts.deps:
depf = open(opts.deps, 'w')
depf.write('%s: \\\n' % opts.output)
# Build heirarchy
root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
ents = {}
for path in args:
for (p, ds, fs) in os.walk(path, followlinks=True):
p = os.path.abspath(p)
n = p.replace(root+'/', '')
t = ents
while True:
(d,n) = rsplit(n)
if d.startswith('.'):
fs = []
break
if d not in t:
t[d] = {}
t = t[d]
if not n: break
for f in fs:
if f.startswith('.'): continue
t[f] = None
# Output a file
def output_file ( path, name, idx, next = -1 ):
n = 'NULL'
if next >= 0: n = '&filebundle_entry_%06d' % next
p = os.path.join(root, path, name);
# Dep file
if depf:
depf.write(' %s\\\n' % p)
# First the data
outf.write('/* FILE : %s %s %d %d */\n' % (path, name, idx, next))
outf.write('static const uint8_t filebundle_data_%06d[] = {' % idx)
o = -1
d = open(p, 'rb').read()
if opts.gzip:
o = len(d)
l = opts.gzlevel
t = BytesIO()
if l < 0: l = 1
if l > 9: l = 9
z = gzip.GzipFile(filename=name, mode='w', compresslevel=l, fileobj=t)
z.write(d)
z.close()
d = t.getvalue()
t.close()
i = 0
for b in d:
if not (i % 12): outf.write('\n ')
if type(b) == str:
b = ord(b)
outf.write('0x%02x,' % b)
i = i + 1
outf.write('\n')
outf.write('};\n')
outf.write('static filebundle_entry_t filebundle_entry_%06d = {\n' % idx)
outf.write(' .type = FB_FILE,\n')
outf.write(' .name = "%s",\n' % name)
outf.write(' .next = %s,\n' % n)
outf.write(' {\n')
outf.write(' .f.size = %d,\n' % len(d))
outf.write(' .f.orig = %d,\n' % o)
outf.write(' .f.data = filebundle_data_%06d\n' % idx)
outf.write(' },\n')
outf.write('};\n')
outf.write('\n')
# Output a directory
def output_dir ( path, name, idx, child, count, next = -1 ):
n = 'NULL'
if next >= 0: n = '&filebundle_entry_%06d' % next
outf.write('/* DIR: %s %s %d %d %d %d */\n' \
% (path, name, idx, child, count, next))
outf.write('static filebundle_entry_t filebundle_entry_%06d = {\n' % idx)
outf.write(' .type = FB_DIR,\n')
outf.write(' .name = "%s",\n' % name)
outf.write(' .next = %s,\n' % n)
outf.write(' {\n')
outf.write(' .d.count = %d,\n' % count)
outf.write(' .d.child = &filebundle_entry_%06d\n' % child)
outf.write(' },\n')
outf.write('};\n')
outf.write('\n')
# Create output
def add_entry ( ents, path = "", name = "", idx = -1, next = -1 ):
# Add children
d = os.path.join(path, name)
p = -1
c = 0
for k in ents:
# File
if ents[k] is None:
output_file(d, k, idx+1, p)
p = idx = idx + 1
c = c + 1
# Directory
else:
tmp = add_entry(ents[k], d, k, idx, p)
if tmp != idx:
p = idx = tmp
c = c + 1
# Add directory
if p >= 0:
if name:
output_dir(path, name, idx+1, p, c, next)
idx = idx + 1
return idx
# Output header
outf.write('/* Auto-generated - DO NOT EDIT */\n')
outf.write('/* COMMAND: [%s] */\n' % (' '.join(sys.argv)))
outf.write('\n')
outf.write('#include "filebundle.h"\n')
outf.write('\n')
# Output entries
idx = add_entry(ents)
# Output top link
outf.write('filebundle_entry_t *filebundle_root = &filebundle_entry_%06d;\n' % idx)