1#!/usr/bin/env python
2
3import types
4import os
5import sys
6import json
7import getopt
8import posixpath
9from collections import OrderedDict
10try:
11    from urlparse import urlsplit
12    from urllib import unquote
13except ImportError: # Python 3
14    from urllib.parse import urlsplit, unquote
15
16
17def url2filename(url):
18    path = urlsplit(url).path
19    return posixpath.basename(unquote(path))
20
21def islocal(url):
22    result = urlsplit(url)
23    return result.scheme == "" and result.netloc == ""
24
25class SourceType:
26    contrib = 1
27    archive = 2
28
29class SourceEntry:
30    def __init__(self, url, entry_type, sha256=None):
31        self.url        = url
32        self.entry_type = entry_type
33        self.sha256     = sha256
34
35class FlatpakPluginManifest:
36    def __init__(self, runtime, template=None):
37        if template != None:
38            with open(template, 'r') as fp:
39                self.manifest = json.load(fp, object_pairs_hook=OrderedDict)
40
41        else:
42            self.manifest    = OrderedDict()
43
44        if runtime != None:
45            self.manifest["runtime-version"] = runtime
46
47class FlatpakManifest:
48    def __init__(self, source_list, runtime, qsv, template=None):
49        if template != None:
50            with open(template, 'r') as fp:
51                self.manifest = json.load(fp, object_pairs_hook=OrderedDict)
52
53            self.finish_args = self.manifest["finish-args"]
54            self.modules     = self.manifest["modules"]
55            self.hbmodule    = self.modules[len(self.modules) - 1]
56            self.hbconfig    = self.hbmodule["config-opts"]
57            self.sources     = [None]
58
59            self.hbmodule["sources"]     = self.sources
60        else:
61            self.manifest    = OrderedDict()
62            self.modules     = []
63            self.hbmodule    = OrderedDict()
64            self.sources     = [None]
65
66            self.manifest["finish-args"] = self.finish_args
67            self.manifest["modules"]     = self.modules
68            self.modules[0]              = self.hbmodule
69            self.hbmodule["sources"]     = self.sources
70            self.hbconfig                = [None]
71
72        if runtime != None:
73            self.manifest["runtime-version"] = runtime
74
75        if qsv:
76            self.hbconfig.append("--enable-qsv");
77
78        handbrake_found = False
79        for key, value in source_list.items():
80            source = OrderedDict()
81            if islocal(value.url):
82                source["path"] = value.url
83            else:
84                if value.sha256 == "" or value.sha256 == None:
85                    continue
86                source["url"] = value.url
87                source["sha256"] = value.sha256
88
89            if value.entry_type == SourceType.archive:
90                if handbrake_found:
91                    print("Error: only one archive source permitted")
92                    sys.exit(3)
93
94                source["type"] = "archive"
95                source["strip-components"] = 1
96                self.sources[0] = source
97                handbrake_found = True
98
99            elif value.entry_type == SourceType.contrib:
100                source["type"] = "file"
101                source["dest"] = "download"
102                source["dest-filename"] = url2filename(value.url)
103                self.sources.append(source)
104
105
106def usage():
107    print("create_flatpak_manifest [-a <archive>] [-c <contrib>] [-s <sha265>] [-t <template>] [-r <sdk-runtime-version] [-h] [<dst>]")
108    print("     -a --archive    - Main archive (a.k.a. HB sources)")
109    print("     -c --contrib    - Contrib download URL (can be repeated)")
110    print("     -s --sha256     - sha256 of previous file on command line")
111    print("     -t --template   - Flatpak manifest template")
112    print("     -r --runtime    - Flatpak SDK runtime version")
113    print("     -q --qsv        - Build with Intel QSV support")
114    print("     -p --plugin     - Manifest if for a HandBrake flatpak plugin")
115    print("     -h --help       - Show this message")
116
117if __name__ == "__main__":
118    try:
119        opts, args = getopt.getopt(sys.argv[1:], "a:c:s:t:r:qph",
120            ["archive=", "contrib=", "sha265=",
121             "template=", "runtime=", "qsv", "plugin", "help"])
122    except getopt.GetoptError:
123        print("Error: Invalid option")
124        usage()
125        sys.exit(2)
126
127    if len(args) > 1:
128        usage()
129        exit(2)
130
131    source_list = OrderedDict()
132    current_source = None
133    runtime = None
134    plugin = 0
135    qsv = 0
136    for opt, arg in opts:
137        if opt in ("-h", "--help"):
138            usage()
139            sys.exit()
140        elif opt in ("-a", "--archive"):
141            if arg != None and arg != "":
142                current_source = arg
143                source_list[arg] = SourceEntry(arg, SourceType.archive)
144            else:
145                current_source = None
146        elif opt in ("-c", "--contrib"):
147            if arg != None and arg != "":
148                current_source = arg
149                source_list[arg] = SourceEntry(arg, SourceType.contrib)
150            else:
151                current_source = None
152        elif opt in ("-s", "--sha256"):
153            if current_source != None:
154                source_list[current_source].sha256 = arg
155        elif opt in ("-t", "--template"):
156            template = arg
157        elif opt in ("-r", "--runtime"):
158            runtime = arg
159        elif opt in ("-q", "--qsv"):
160            qsv = 1;
161        elif opt in ("-p", "--plugin"):
162            plugin = 1;
163
164    if len(args) > 0:
165        dst = args[0]
166    else:
167        dst = None
168
169    if plugin:
170        manifest = FlatpakPluginManifest(runtime, template)
171    else:
172        manifest = FlatpakManifest(source_list, runtime, qsv, template)
173
174    if dst != None:
175        with open(dst, 'w') as fp:
176            json.dump(manifest.manifest, fp, ensure_ascii=False, indent=4)
177    else:
178        print(json.dumps(manifest.manifest, ensure_ascii=False, indent=4))
179
180