1#!/usr/bin/env python3
2
3from __future__ import print_function
4import argparse
5import os
6import json
7import zipfile
8
9from hashlib import md5
10from subprocess import check_call
11
12from get_plugin_data import get_plugin_data
13
14VERSION_TO_BRANCH = {
15    None: '2.0',
16    '1.0': '1.0',
17    '2.0': '2.0',
18}
19
20
21def build_json(dest_dir):
22    """
23    Traverse the plugins directory to generate json data.
24    """
25
26    plugins = {}
27
28    # All top level directories in plugin_dir are plugins
29    for dirname in next(os.walk(plugin_dir))[1]:
30
31        files = {}
32        data = {}
33
34        if dirname in [".git"]:
35            continue
36
37        dirpath = os.path.join(plugin_dir, dirname)
38        for root, dirs, filenames in os.walk(dirpath):
39            for filename in filenames:
40                ext = os.path.splitext(filename)[1]
41
42                if ext not in [".pyc"]:
43                    file_path = os.path.join(root, filename)
44                    with open(file_path, "rb") as md5file:
45                        md5Hash = md5(md5file.read()).hexdigest()
46                    files[file_path.split(os.path.join(dirpath, ''))[1]] = md5Hash
47
48                    if ext in ['.py'] and not data:
49                        data = get_plugin_data(os.path.join(plugin_dir, dirname, filename))
50
51        if files and data:
52            print("Added: " + dirname)
53            data['files'] = files
54            plugins[dirname] = data
55    out_path = os.path.join(dest_dir, plugin_file)
56    with open(out_path, "w") as out_file:
57        json.dump({"plugins": plugins}, out_file, sort_keys=True, indent=2)
58
59
60def zip_files(dest_dir):
61    """
62    Zip up plugin folders
63    """
64
65    for dirname in next(os.walk(plugin_dir))[1]:
66        archive_path = os.path.join(dest_dir, dirname)
67        archive = zipfile.ZipFile(archive_path + ".zip", "w")
68
69        dirpath = os.path.join(plugin_dir, dirname)
70        plugin_files = []
71
72        for root, dirs, filenames in os.walk(dirpath):
73            for filename in filenames:
74                file_path = os.path.join(root, filename)
75                plugin_files.append(file_path)
76
77        if (len(plugin_files) == 1
78            and os.path.basename(plugin_files[0]) != '__init__.py'):
79            # There's only one file, put it directly into the zipfile
80            archive.write(plugin_files[0],
81                          os.path.basename(plugin_files[0]),
82                          compress_type=zipfile.ZIP_DEFLATED)
83        else:
84            for filename in plugin_files:
85                # Preserve the folder structure relative to plugin_dir
86                # in the zip file
87                name_in_zip = os.path.join(os.path.relpath(filename,
88                                                           plugin_dir))
89                archive.write(filename,
90                              name_in_zip,
91                              compress_type=zipfile.ZIP_DEFLATED)
92
93        print("Created: " + dirname + ".zip")
94
95
96# The file that contains json data
97plugin_file = "plugins.json"
98
99# The directory which contains plugin files
100plugin_dir = "plugins"
101
102if __name__ == '__main__':
103    parser = argparse.ArgumentParser(description='Generate plugin files for Picard website.')
104    parser.add_argument('version', nargs='?', help="Build output files for the specified version")
105    parser.add_argument('--build_dir', default="build", help="Path for the build output. DEFAULT = %(default)s")
106    parser.add_argument('--pull', action='store_true', dest='pull', help="Pulls the remote origin and updates the files before building")
107    parser.add_argument('--no-zip', action='store_false', dest='zip', help="Do not generate the zip files in the build output")
108    parser.add_argument('--no-json', action='store_false', dest='json', help="Do not generate the json file in the build output")
109    args = parser.parse_args()
110    check_call(["git", "checkout", "-q", VERSION_TO_BRANCH[args.version], '--', 'plugins'])
111    dest_dir = os.path.abspath(os.path.join(args.build_dir, args.version or ''))
112    if not os.path.exists(dest_dir):
113        os.makedirs(dest_dir)
114    if args.pull:
115        check_call(["git", "pull", "-q"])
116    if args.json:
117        build_json(dest_dir)
118    if args.zip:
119        zip_files(dest_dir)
120