blob: da3a477c4014c551a15078cb7c4213b644300250 [file] [log] [blame]
#!/usr/bin/python3
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Stamps a plugin xml with build information."""
import argparse
import io
import re
import sys
from xml.dom import minidom
parser = argparse.ArgumentParser()
parser.add_argument(
"--plugin_xml",
help="The plugin xml file",
)
parser.add_argument(
"--api_version_txt",
help="The file containing the api version info",
required=True,
)
parser.add_argument(
"--stamp_since_build",
action="store_true",
help="Stamp since-build with the build number",
)
parser.add_argument(
"--stamp_until_build",
action="store_true",
help=("Stamp until-build with the major release component of the build "
"number"),
)
parser.add_argument(
"--plugin_id",
help="plugin ID to stamp into the plugin.xml",
)
parser.add_argument(
"--plugin_name",
help="plugin name to stamp into the plugin.xml",
)
parser.add_argument(
"--version",
help="Version to stamp into the plugin.xml",
)
parser.add_argument(
"--version_file",
help="Version file to stamp into the plugin.xml",
)
parser.add_argument(
"--changelog_file",
help="Changelog file to add to plugin.xml",
)
parser.add_argument(
"--description_file",
help="File with description element data to add to plugin.xml",
)
parser.add_argument(
"--vendor_file",
help="File with vendor element data to add to plugin.xml",
)
def _read_changelog(changelog_file):
"""Reads the changelog and transforms it into trivial HTML if it's not HTML."""
with io.open(changelog_file, encoding="utf-8") as f:
if changelog_file.endswith("html"):
return f.read()
else:
return "\n".join("<p>" + line + "</p>" for line in f.readlines())
def _read_description(description_file):
"""Reads the description and transforms it into trivial HTML."""
with open(description_file) as f:
return f.read()
def _read_vendor(vendor_file):
"""Reads vendor data from an .xml file and returns the vendor element."""
dom = minidom.parse(vendor_file)
vendor_elements = dom.getElementsByTagName("vendor")
if len(vendor_elements) != 1:
raise ValueError("Ambigious or missing vendor element (%d elements)" %
len(vendor_elements))
return vendor_elements[0]
def main():
args = parser.parse_args()
if args.plugin_xml:
dom = minidom.parse(args.plugin_xml)
else:
dom = minidom.parseString("<idea-plugin/>")
with open(args.api_version_txt) as f:
# api_version formatted as AI-xxx.yyy.zzz.www.__BUILD_NUMBER__
# for example: AI-242.23339.11.2422.__BUILD_NUMBER__
api_version = f.readline().strip()
if api_version.endswith(" EAP"):
# remove the EAP suffix if present
api_version = api_version[:-4]
# remove AI- prefix
api_version = api_version[3:]
new_elements = []
idea_plugin = dom.documentElement
if args.version and args.version_file:
raise ValueError("Cannot supply both version and version_file")
if args.version or args.version_file:
version_elements = idea_plugin.getElementsByTagName("version")
for element in version_elements:
idea_plugin.removeChild(element)
version_element = dom.createElement("version")
new_elements.append(version_element)
build_number = None
if args.version:
build_number = args.version
else:
with open(args.version_file) as f:
build_number = f.read().strip()
# Since we are releasing a single version of the plugin from a given build
# then using the build number is enough.
# for example: the plugin version will be 12480590
# if built for Android Studio AI-242.23339.11.2422.12480590
version_text = dom.createTextNode(build_number)
version_element.appendChild(version_text)
if args.stamp_since_build or args.stamp_until_build:
if idea_plugin.getElementsByTagName("idea-version"):
raise ValueError("idea-version element already present")
idea_version_element = dom.createElement("idea-version")
new_elements.append(idea_version_element)
# use only the first 3 components from api_version in
# compatibility range because of b/298233757
idea_version = ".".join(api_version.split(".")[:3])
if args.stamp_since_build:
idea_version_element.setAttribute("since-build", idea_version)
if args.stamp_until_build:
idea_version_element.setAttribute("until-build", idea_version)
# TODO(b/349186243): add changelog to plugin.xml
if args.plugin_id:
if idea_plugin.getElementsByTagName("id"):
raise ValueError("id element already in plugin.xml")
id_element = dom.createElement("id")
new_elements.append(id_element)
id_text = dom.createTextNode(args.plugin_id)
id_element.appendChild(id_text)
if args.plugin_name:
if idea_plugin.getElementsByTagName("name"):
raise ValueError("name element already in plugin.xml")
name_element = dom.createElement("name")
new_elements.append(name_element)
name_text = dom.createTextNode(args.plugin_name)
name_element.appendChild(name_text)
if args.description_file:
if idea_plugin.getElementsByTagName("description"):
raise ValueError("description element already in plugin.xml")
description_element = dom.createElement("description")
description_text = _read_description(args.description_file)
description_cdata = dom.createCDATASection(description_text)
description_element.appendChild(description_cdata)
new_elements.append(description_element)
if args.vendor_file:
if idea_plugin.getElementsByTagName("vendor"):
raise ValueError("vendor element already in plugin.xml")
vendor_element = dom.createElement("vendor")
vendor_src_element = _read_vendor(args.vendor_file)
vendor_element.setAttribute("email",
vendor_src_element.getAttribute("email"))
vendor_element.setAttribute("url", vendor_src_element.getAttribute("url"))
vendor_text = dom.createTextNode(vendor_src_element.firstChild.data)
vendor_element.appendChild(vendor_text)
new_elements.append(vendor_element)
for new_element in new_elements:
idea_plugin.appendChild(new_element)
sys.stdout.buffer.write(dom.toxml(encoding="utf-8"))
if __name__ == "__main__":
main()