#! /usr/bin/env python3
##
## jarsnap.py - make fat jar files
## Copyright (C) 2015 Delwink, LLC
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as published by
## the Free Software Foundation, version 3 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Affero General Public License for more details.
##
## You should have received a copy of the GNU Affero General Public License
## along with this program. If not, see .
##
from datetime import datetime
from getopt import GetoptError, gnu_getopt
from os import listdir, mkdir, remove, rename
from os.path import join, exists
from shutil import copy, make_archive, rmtree, unpack_archive
from sys import argv
from tempfile import gettempdir
__title__ = 'jarsnap.py'
__version__ = '1.1.1'
__author__ = 'David McMackins II'
def make_fat_jar(jars, main_class, output_path='fat.jar', data=[]):
now = datetime.now()
workdir = join(gettempdir(), '{} {}'.format(__title__, now))
if not exists(workdir):
mkdir(workdir)
meta_inf = join(workdir, 'META-INF')
mkdir(meta_inf)
manifest = """Manifest-Version: 1.0
Created-By: {} {} on {}
Main-Class: {}
""".replace('\n', '\r\n').format(__title__, __version__, now, main_class)
try:
for jar in jars:
unpack_archive(jar, workdir, 'zip')
for datum in data:
copy(datum, workdir)
for f in listdir(meta_inf):
if f.endswith('.SF') or f.endswith('.DSA') or f.endswith('.RSA'):
remove(join(meta_inf, f))
with open(join(meta_inf, 'MANIFEST.MF'), 'w') as mf:
mf.write(manifest)
out_name = make_archive(output_path, 'zip', root_dir=workdir)
rename(out_name, output_path)
finally:
rmtree(workdir)
def main(argv, name='jarsnap'):
_HELP = """{} - make fat jars
Usage: {} [options] <-m|--main-class MAIN> file1 [file2 [file3...]]
Files with .jar extension will be extracted; others will be included normally.
Options:
-h, --help
Displays this help and exits.
-m, --main-class=MAIN
Sets the main class path to MAIN.
-o, --output=OUTPUT
Sets the output file path to OUTPUT. Defaults to 'fat.jar'
-v, --version
Displays version information and exits.""".format(__title__,
name)
_VERSION = """{} {}
Copyright (C) 2015 Delwink, LLC
License AGPLv3: GNU AGPL version 3 only .
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by {}""".format(__title__, __version__, __author__)
_HELPEXIT = 'Use `{} --help` for more information.'.format(name)
try:
opts, args = gnu_getopt(argv, 'dhm:o:v',
['debug', 'help', 'main-class=', 'output=',
'version'])
except GetoptError as e:
print('{}: {}'.format(__title__, e))
exit(_HELPEXIT)
debug = False
main_class = ''
output_path = 'fat.jar'
for key, value in opts:
if key in ('-d', '--debug'):
debug = True
elif key in ('-h', '--help'):
print(_HELP)
exit(0)
elif key in ('-m', '--main-class'):
main_class = value
elif key in ('-o', '--output'):
output_path = value
elif key in ('-v', '--version'):
print(_VERSION)
exit(0)
if not main_class:
print('{}: main class was not set!'.format(__title__))
exit(_HELPEXIT)
jars = []
data = []
for path in args:
if path.lower().endswith('.jar'):
jars.append(path)
else:
data.append(path)
try:
make_fat_jar(jars, main_class, output_path, data)
except Exception as e:
if debug:
raise
print('{}: {}'.format(name, e))
if __name__ == '__main__':
main(argv[1:])