OmniROM's roomservice is now strictly blocking Unofficial Builds if the Device Tree is not available in their Gerrit/Github Organization.
These files are patched to bypass those restrictions.
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom2" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-10" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom2" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| remove = dependency.get("remove", None) | |
| if remove is not None: | |
| #print("found remove in ", repository) | |
| project = create_remove_project(remove) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| if device == "emulator": | |
| location = "vendor/omni/utils/emulator" | |
| else: | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-5.1" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(repository) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-6.0" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(repository) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-7.1" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(repository) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-8.1" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(repository) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |
| #!/usr/bin/env python | |
| # Copyright (C) 2013 Cybojenix <[email protected]> | |
| # Copyright (C) 2013 The OmniROM Project | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # 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 General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| import os | |
| import os.path | |
| import re | |
| from xml.etree import ElementTree as ES | |
| # Use the urllib importer from the Cyanogenmod roomservice | |
| try: | |
| # For python3 | |
| import urllib.request | |
| except ImportError: | |
| # For python2 | |
| import imp | |
| import urllib2 | |
| urllib = imp.new_module('urllib') | |
| urllib.request = urllib2 | |
| # Config | |
| # set this to the default remote to use in repo | |
| default_rem = "omnirom" | |
| # set this to the default revision to use (branch/tag name) | |
| default_rev = "android-9.0" | |
| # set this to the remote that you use for projects from your team repos | |
| # example fetch="https://github.com/omnirom" | |
| default_team_rem = "omnirom" | |
| # this shouldn't change unless google makes changes | |
| local_manifest_dir = ".repo/local_manifests" | |
| # change this to your name on github (or equivalent hosting) | |
| android_team = "omnirom" | |
| # url to gerrit repository | |
| gerrit_url = "gerrit.omnirom.org" | |
| def check_repo_exists(git_data, device): | |
| re_match = "^android_device_.*_{device}$".format(device=device) | |
| matches = list(filter(lambda x: re.match(re_match, x), git_data)) | |
| if len(matches) != 1: | |
| raise Exception("{device} not found," | |
| "exiting roomservice".format(device=device)) | |
| return git_data[matches[0]] | |
| def search_gerrit_for_device(device): | |
| # TODO: In next gerrit release regex search with r= should be supported! | |
| git_search_url = "https://{gerrit_url}/projects/?m={device}".format( | |
| gerrit_url=gerrit_url, | |
| device=device | |
| ) | |
| git_req = urllib.request.Request(git_search_url) | |
| try: | |
| response = urllib.request.urlopen(git_req) | |
| except urllib.request.HTTPError: | |
| print("There was an issue connecting to gerrit." | |
| " Please try again in a minute") | |
| except urllib.request.URLError: | |
| print("WARNING: No network connection available.") | |
| else: | |
| # Skip silly gerrit "header" | |
| response.readline() | |
| git_data = json.load(response) | |
| device_data = check_repo_exists(git_data, device) | |
| print("found the {} device repo".format(device)) | |
| return device_data | |
| def parse_device_directory(device_url, device): | |
| pattern = "^android_device_(?P<vendor>.+)_{}$".format(device) | |
| match = re.match(pattern, device_url) | |
| if match is None: | |
| raise Exception("Invalid project name {}".format(device_url)) | |
| return "device/{vendor}/{device}".format( | |
| vendor=match.group('vendor'), | |
| device=device, | |
| ) | |
| # Thank you RaYmAn | |
| def iterate_manifests(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("project"): | |
| yield project | |
| def iterate_manifests_remove_project(): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml"): | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| else: | |
| for project in man.findall("remove-project"): | |
| yield project | |
| def check_project_exists(url, revision, path): | |
| for project in iterate_manifests(): | |
| if project.get("name") == url \ | |
| and project.get("revision") == revision \ | |
| and project.get("path") == path: | |
| return True | |
| return False | |
| def check_remove_project_exists(url): | |
| for project in iterate_manifests_remove_project(): | |
| if project.get("name") == url: | |
| return True | |
| return False | |
| def check_target_exists(directory): | |
| return os.path.isdir(directory) | |
| # Use the indent function from http://stackoverflow.com/a/4590052 | |
| def indent(elem, level=0): | |
| i = ''.join(["\n", level*" "]) | |
| if len(elem): | |
| if not elem.text or not elem.text.strip(): | |
| elem.text = ''.join([i, " "]) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| for elem in elem: | |
| indent(elem, level+1) | |
| if not elem.tail or not elem.tail.strip(): | |
| elem.tail = i | |
| else: | |
| if level and (not elem.tail or not elem.tail.strip()): | |
| elem.tail = i | |
| def create_manifest_project(url, directory, | |
| remote=default_rem, | |
| revision=default_rev): | |
| project_exists = check_project_exists(url, revision, directory) | |
| if project_exists: | |
| return None | |
| project = ES.Element("project", | |
| attrib={ | |
| "path": directory, | |
| "name": url, | |
| "remote": remote, | |
| "revision": revision | |
| }) | |
| return project | |
| def create_remove_project(url): | |
| remove_project_exists = check_remove_project_exists(url) | |
| if remove_project_exists: | |
| return None | |
| project = ES.Element("remove-project", | |
| attrib={ | |
| "name": url | |
| }) | |
| return project | |
| # Avoid adding already in manifests declared repositories in the roomservice.xml | |
| def is_in_manifest(project): | |
| files = [] | |
| for file in os.listdir(local_manifest_dir): | |
| if file.endswith(".xml") and file != "roomservice.xml": | |
| files.append(os.path.join(local_manifest_dir, file)) | |
| files.append('.repo/manifest.xml') | |
| for file in files: | |
| try: | |
| man = ES.parse(file) | |
| man = man.getroot() | |
| for project_in_manifests in man.findall("project"): | |
| if project_in_manifests.get("path") == project.get("path") or project_in_manifests.get("path") == project.get("target_path"): # path -> def append_to_manifest(project) & target_path -> def check_manifest_problems(dependencies) | |
| return True | |
| except (IOError, ES.ParseError): | |
| print("WARNING: error while parsing %s" % file) | |
| return False | |
| def append_to_manifest(project): | |
| try: | |
| lm = ES.parse('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| lm = lm.getroot() | |
| except (IOError, ES.ParseError): | |
| lm = ES.Element("manifest") | |
| if is_in_manifest(project): | |
| print("HINT: The following repository is already defined in a manifest:", project.get("name")) | |
| return lm | |
| lm.append(project) | |
| return lm | |
| def write_to_manifest(manifest): | |
| indent(manifest) | |
| raw_xml = ES.tostring(manifest).decode() | |
| raw_xml = ''.join(['<?xml version="1.0" encoding="UTF-8"?>\n' | |
| '<!--Please do not manually edit this file-->\n', | |
| raw_xml]) | |
| with open('/'.join([local_manifest_dir, "roomservice.xml"]), 'w') as f: | |
| f.write(raw_xml) | |
| print("wrote the new roomservice manifest") | |
| def parse_device_from_manifest(device): | |
| for project in iterate_manifests(): | |
| name = project.get('name') | |
| if name.startswith("android_device_") and name.endswith(device): | |
| return project.get('path') | |
| return None | |
| def parse_device_from_folder(device): | |
| search = [] | |
| if not os.path.isdir("device"): | |
| os.mkdir("device") | |
| for sub_folder in os.listdir("device"): | |
| if os.path.isdir("device/%s/%s" % (sub_folder, device)): | |
| search.append("device/%s/%s" % (sub_folder, device)) | |
| if len(search) > 1: | |
| print("multiple devices under the name %s. " | |
| "defaulting to checking the manifest" % device) | |
| location = parse_device_from_manifest(device) | |
| elif len(search) == 1: | |
| location = search[0] | |
| else: | |
| print("Your device can't be found in device sources..") | |
| location = parse_device_from_manifest(device) | |
| return location | |
| def parse_dependency_file(location): | |
| dep_file = "omni.dependencies" | |
| dep_location = '/'.join([location, dep_file]) | |
| if not os.path.isfile(dep_location): | |
| print("WARNING: %s file not found" % dep_location) | |
| sys.exit() | |
| try: | |
| with open(dep_location, 'r') as f: | |
| dependencies = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| return dependencies | |
| # if there is any conflict with existing and new | |
| # delete the roomservice.xml file and create new | |
| def check_manifest_problems(dependencies): | |
| for dependency in dependencies: | |
| if is_in_manifest(dependency): | |
| continue | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| # check for existing projects | |
| for project in iterate_manifests(): | |
| if project.get("revision") is not None \ | |
| and project.get("path") is not None \ | |
| and project.get("path") == target_path \ | |
| and project.get("revision") != revision: | |
| print("WARNING: detected conflict in revisions for repository ", | |
| repository) | |
| current_dependency = str(project.get(repository)) | |
| file = ES.parse('/'.join([local_manifest_dir, | |
| "roomservice.xml"])) | |
| file_root = file.getroot() | |
| for current_project in file_root.findall('project'): | |
| new_dependency = str(current_project.find('revision')) | |
| if new_dependency == current_dependency: | |
| file_root.remove(current_project) | |
| file.write('/'.join([local_manifest_dir, "roomservice.xml"])) | |
| return | |
| def create_dependency_manifest(dependencies): | |
| projects = [] | |
| for dependency in dependencies: | |
| repository = dependency.get("repository") | |
| target_path = dependency.get("target_path") | |
| revision = dependency.get("revision", default_rev) | |
| remote = dependency.get("remote", default_rem) | |
| override = dependency.get("override", None) | |
| remove = dependency.get("remove", None) | |
| if remove is not None: | |
| #print("found remove in ", repository) | |
| project = create_remove_project(remove) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| else: | |
| if override is not None: | |
| #print("found override in ", repository) | |
| project = create_remove_project(override) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| #print(ES.tostring(manifest).decode()) | |
| write_to_manifest(manifest) | |
| # not adding an organization should default to android_team | |
| # only apply this to github | |
| if remote == "github": | |
| if "/" not in repository: | |
| repository = '/'.join([android_team, repository]) | |
| project = create_manifest_project(repository, | |
| target_path, | |
| remote=remote, | |
| revision=revision) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| projects.append(target_path) | |
| if len(projects) > 0: | |
| os.system("repo sync -f --no-clone-bundle %s" % " ".join(projects)) | |
| def create_common_dependencies_manifest(dependencies): | |
| dep_file = "omni.dependencies" | |
| common_list = [] | |
| if dependencies is not None: | |
| for dependency in dependencies: | |
| try: | |
| index = common_list.index(dependency['target_path']) | |
| except ValueError: | |
| index = None | |
| if index is None: | |
| common_list.append(dependency['target_path']) | |
| dep_location = '/'.join([dependency['target_path'], dep_file]) | |
| if not os.path.isfile(dep_location): | |
| sys.exit() | |
| else: | |
| try: | |
| with open(dep_location, 'r') as f: | |
| common_deps = json.loads(f.read()) | |
| except ValueError: | |
| raise Exception("ERROR: malformed dependency file") | |
| if common_deps is not None: | |
| print("Looking for dependencies on: ", | |
| dependency['target_path']) | |
| check_manifest_problems(common_deps) | |
| create_dependency_manifest(common_deps) | |
| create_common_dependencies_manifest(common_deps) | |
| def fetch_dependencies(device): | |
| if device == "emulator": | |
| location = "vendor/omni/utils/emulator" | |
| else: | |
| location = parse_device_from_folder(device) | |
| if location is None or not os.path.isdir(location): | |
| raise Exception("ERROR: could not find your device " | |
| "folder location, bailing out") | |
| dependencies = parse_dependency_file(location) | |
| check_manifest_problems(dependencies) | |
| create_dependency_manifest(dependencies) | |
| create_common_dependencies_manifest(dependencies) | |
| fetch_device(device) | |
| def check_device_exists(device): | |
| location = parse_device_from_folder(device) | |
| if location is None: | |
| return False | |
| return os.path.isdir(location) | |
| def fetch_device(device): | |
| if check_device_exists(device): | |
| print("HINT: Avoid fetching the already checked out device repo:", device) | |
| return | |
| git_data = search_gerrit_for_device(device) | |
| if git_data is not None: | |
| device_url = git_data['id'] | |
| device_dir = parse_device_directory(device_url, device) | |
| project = create_manifest_project(device_url, | |
| device_dir, | |
| remote=default_team_rem) | |
| if project is not None: | |
| manifest = append_to_manifest(project) | |
| write_to_manifest(manifest) | |
| # In case a project was written to manifest, but never synced | |
| if project is not None or not check_target_exists(device_dir): | |
| print("syncing the device config") | |
| os.system('repo sync -f --no-clone-bundle %s' % device_dir) | |
| if __name__ == '__main__': | |
| if not os.path.isdir(local_manifest_dir): | |
| os.mkdir(local_manifest_dir) | |
| product = sys.argv[1] | |
| try: | |
| device = product[product.index("_") + 1:] | |
| except ValueError: | |
| device = product | |
| if len(sys.argv) > 2: | |
| deps_only = sys.argv[2] | |
| else: | |
| deps_only = False | |
| if not deps_only: | |
| fetch_device(device) | |
| fetch_dependencies(device) |