-
-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate license files for WebRTC builds
For Android and Desktop we save the LICENSE.md that WebRTC's generate_licenses.py knows how to generate. For iOS we were already getting that via build_ios_libs.py, but we additionally convert that into a Settings bundle plist for ease of integration into the iOS app.
- Loading branch information
1 parent
ab32885
commit b0ef402
Showing
4 changed files
with
172 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# | ||
# Copyright 2023 Signal Messenger, LLC | ||
# SPDX-License-Identifier: AGPL-3.0-only | ||
# | ||
|
||
import argparse | ||
import html | ||
import plistlib | ||
import sys | ||
|
||
from collections.abc import Iterable | ||
from typing import Dict, Tuple, TextIO | ||
|
||
|
||
def parse(input: TextIO, filename: str) -> Dict[str, str]: | ||
# The format is | ||
# # webrtc | ||
# ``` | ||
# LICENSE INFO GOES HERE | ||
# POSSIBLY SEVERAL LINES OF IT | ||
# ``` | ||
# repeated for each library | ||
result = dict() | ||
line_number = 0 | ||
|
||
def readline() -> str: | ||
nonlocal line_number | ||
line_number += 1 | ||
return input.readline() | ||
|
||
def fatal(msg: str) -> None: | ||
raise Exception(f'{filename}:{line_number}: {msg}') | ||
|
||
while True: | ||
line = readline() | ||
if not line: | ||
# EOF | ||
break | ||
line = line.strip() | ||
if not line: | ||
# Ignore blank lines between dependencies. | ||
continue | ||
|
||
# Expect a dependency line. | ||
if not line.startswith('# '): | ||
fatal(f'unexpected line: "{line.strip()}"') | ||
name = line[2:] | ||
|
||
# Expect the start of a fenced license. | ||
line = readline() | ||
if line != '```\n': | ||
if not line: | ||
fatal('unexpected end of file') | ||
line = line.strip() | ||
if not line: | ||
fatal('unexpected blank line') | ||
fatal(f'unexpected line: "{line.strip()}"') | ||
|
||
license = '' | ||
while True: | ||
line = readline() | ||
if line == '' or line == '```\n': | ||
# Break on the end fence or on EOF. | ||
break | ||
# These probably shouldn't be escaped in the first place, but they are. | ||
license += html.unescape(line) | ||
|
||
result[name] = license | ||
|
||
return result | ||
|
||
|
||
def print_as_markdown(deps: Iterable[Tuple[str, str]]) -> None: | ||
for name, license in deps: | ||
print('#', name) | ||
print('```') | ||
# The license already has a trailing newline. | ||
print(license, end='') | ||
print('```') | ||
print() | ||
|
||
|
||
def print_as_plist(deps: Iterable[Tuple[str, str]]) -> None: | ||
# We're trying to match the format in Signal-iOS/Signal/Settings.bundle/Acknowledgements.plist | ||
# which comes from <https://developer.apple.com/library/archive/documentation/PreferenceSettings/Conceptual/SettingsApplicationSchemaReference/Introduction/Introduction.html>. | ||
plistlib.dump(fp=sys.stdout.buffer, value={ | ||
'PreferenceSpecifiers': [ | ||
{ | ||
'FooterText': 'RingRTC depends on the WebRTC project', | ||
'Title': 'Acknowledgments', | ||
'Type': 'PSGroupSpecifier', | ||
} | ||
] + [ | ||
{ | ||
'FooterText': license, | ||
'Title': name, | ||
'Type': 'PSGroupSpecifier', | ||
} for name, license in deps | ||
] + [ | ||
{ | ||
'FooterText': 'Generated in RingRTC', | ||
'Title': '', | ||
'Type': 'PSGroupSpecifier', | ||
} | ||
], | ||
'StringsTable': 'Acknowledgments', | ||
'Title': 'Acknowledgments', | ||
}) | ||
sys.stdout.flush() | ||
|
||
|
||
def main() -> None: | ||
parser = argparse.ArgumentParser( | ||
description='Convert WebRTC LICENSE.md to other formats') | ||
parser.add_argument('-f', '--format', choices=['md', 'plist'], | ||
help='Output format (Markdown or iOS Settings.plist)') | ||
parser.add_argument('files', nargs='+', metavar='LICENSE.md', | ||
help='License file(s) generated by WebRTC') | ||
args = parser.parse_args() | ||
|
||
dependencies = dict() | ||
for path in args.files: | ||
with open(path) as f: | ||
dependencies.update(parse(f, path)) | ||
|
||
# Sort the dependencies, but always put WebRTC first. | ||
webrtc_dep = dependencies.pop('webrtc') | ||
sorted_dependencies = [('webrtc', webrtc_dep)] + sorted(dependencies.items()) | ||
|
||
if args.format == 'md': | ||
# Same as input format, but merges multiple files. | ||
print_as_markdown(sorted_dependencies) | ||
elif args.format == 'plist': | ||
print_as_plist(sorted_dependencies) | ||
else: | ||
print([name for (name, _) in sorted_dependencies]) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |