diff options
author | Jordan Demeulenaere <jdemeulenaere@google.com> | 2023-02-09 16:12:15 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-02-09 16:12:15 +0000 |
commit | 1d2450dca6bb80f1b7a60d961056092b238ed61b (patch) | |
tree | ac75862b7d2bccb64dd92cbd8cf68795266b0785 | |
parent | e4302b1ffb33021ff000054292920f5ab6c311b5 (diff) | |
parent | ad7515c1cc7434597eed9b3f09a0f279afc72b03 (diff) | |
download | ktfmt-1d2450dca6bb80f1b7a60d961056092b238ed61b.tar.gz |
Replace prepare_upgrade.sh by a Python equivalent am: a56945eb52 am: ad7515c1cc
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/ktfmt/+/21147693
Change-Id: Ic2c84d5b12a2e98f7d181a236573ca26c5d34615
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rwxr-xr-x | prepare_upgrade.py | 257 | ||||
-rwxr-xr-x | prepare_upgrade.sh | 151 |
2 files changed, 257 insertions, 151 deletions
diff --git a/prepare_upgrade.py b/prepare_upgrade.py new file mode 100755 index 0000000..cccd909 --- /dev/null +++ b/prepare_upgrade.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 + +# +# Copyright 2023, The Android Open Source Project +# +# 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. +# +"""Script to prepare an update to a new version of ktfmt.""" + +import subprocess +import os +import sys +import re +import shutil +import argparse +import textwrap + +tmp_dir = "/tmp/ktfmt" +zip_path = os.path.join(tmp_dir, "common.zip") +jar_path = os.path.join(tmp_dir, "framework/ktfmt.jar") +copy_path = os.path.join(tmp_dir, "copy.jar") + + +def main(): + parser = argparse.ArgumentParser( + description="Prepare a repository for the upgrade of ktfmt to a new version." + ) + parser.add_argument( + "--build_id", + required=True, + help="The build ID of aosp-build-tools-release with the new version of ktfmt" + ) + parser.add_argument( + "--bug_id", + required=True, + help="The bug ID associated to each CL generated by this tool") + parser.add_argument( + "--repo", + required=True, + help="The relative path of the repository to upgrade, e.g. 'frameworks/base/'" + ) + args = parser.parse_args() + + build_id = args.build_id + bug_id = args.bug_id + repo_relative_path = args.repo + + build_top = os.environ["ANDROID_BUILD_TOP"] + repo_absolute_path = os.path.join(build_top, repo_relative_path) + + print("Preparing upgrade of ktfmt from build", build_id) + os.chdir(repo_absolute_path) + check_workspace_clean() + check_branches() + + print("Downloading ktfmt.jar from aosp-build-tools-release") + download_jar(build_id) + + print(f"Creating local branch ktfmt_update1") + run_cmd(["repo", "start", "ktfmt_update1"]) + + includes_file = find_includes_file(repo_relative_path) + if includes_file: + update_includes_file(build_top, includes_file, bug_id) + else: + print("No includes file found, skipping first CL") + + print(f"Creating local branch ktfmt_update2") + run_cmd(["repo", "start", "--head", "ktfmt_update2"]) + format_files(build_top, includes_file, repo_absolute_path, bug_id) + + print("Done. You can now submit the generated CL(s), if any.") + + +def run_cmd(cmd): + result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if result.returncode != 0: + print("Error running command: {}".format(" ".join(cmd))) + print("Output: {}".format(result.stderr.decode())) + sys.exit(1) + return result.stdout.decode("utf-8") + + +def is_workspace_clean(): + return run_cmd(["git", "status", "--porcelain"]) == "" + + +def check_workspace_clean(): + if not is_workspace_clean(): + print( + "The current repository contains uncommitted changes, please run this script in a clean workspace" + ) + sys.exit(1) + + +def check_branches(): + result = run_cmd(["git", "branch"]) + if "ktfmt_update1" in result or "ktfmt_update2" in result: + print( + "Branches ktfmt_update1 or ktfmt_update2 already exist, you should delete them before running this script" + ) + sys.exit(1) + + +def download_jar(build_id): + cmd = [ + "/google/data/ro/projects/android/fetch_artifact", "--branch", + "aosp-build-tools-release", "--bid", build_id, "--target", "linux", + "build-common-prebuilts.zip", zip_path + ] + run_cmd(cmd) + cmd = ["unzip", "-q", "-o", "-d", tmp_dir, zip_path] + run_cmd(cmd) + + if not os.path.isfile(jar_path): + print("Error: {} is not readable".format(jar_path)) + sys.exit(1) + + +def find_includes_file(repo_relative_path): + with open("PREUPLOAD.cfg") as f: + includes_line = [line for line in f if "ktfmt.py" in line][0].split(" ") + if "-i" not in includes_line: + return None + + index = includes_line.index("-i") + 1 + includes_file = includes_line[index][len("${REPO_ROOT}/") + + len(repo_relative_path):] + if not os.path.isfile(includes_file): + print("Error: {} does not exist or is not a file".format(includes_file)) + sys.exit(1) + return includes_file + + +def get_included_folders(includes_file): + with open(includes_file) as f: + return [line[1:] for line in f.read().splitlines() if line.startswith("+")] + + +def update_includes_file(build_top, includes_file, bug_id): + included_folders = get_included_folders(includes_file) + cmd = [ + f"{build_top}/external/ktfmt/generate_includes_file.py", + f"--output={includes_file}" + ] + included_folders + print(f"Updating {includes_file} with the command: {cmd}") + run_cmd(cmd) + + if is_workspace_clean(): + print(f"No change were made to {includes_file}, skipping first CL") + else: + print(f"Creating first CL with update of {includes_file}") + create_first_cl(bug_id) + + +def create_first_cl(bug_id): + sha1sum = get_sha1sum(jar_path) + change_id = f"I{sha1sum}" + command = " ".join(sys.argv) + cl_message = textwrap.dedent(f""" + Regenerate include file for ktfmt upgrade + + This CL was generated automatically from the following command: + + $ {command} + + This CL regenerates the inclusion file with the current version of ktfmt + so that it is up-to-date with files currently formatted or ignored by + ktfmt. + + Bug: {bug_id} + Test: Presubmits + Change-Id: {change_id} + Merged-In: {change_id} + """) + + run_cmd(["git", "add", "--all"]) + run_cmd(["git", "commit", "-m", cl_message]) + + +def get_sha1sum(file): + output = run_cmd(["sha1sum", file]) + regex = re.compile(r"[a-f0-9]{40}") + match = regex.search(output) + if not match: + print(f"sha1sum not found in output: {output}") + sys.exit(1) + return match.group() + + +def format_files(build_top, includes_file, repo_absolute_path, bug_id): + if (includes_file): + included_folders = get_included_folders(includes_file) + cmd = [ + f"{build_top}/external/ktfmt/ktfmt.py", "-i", includes_file, "--jar", + jar_path + ] + included_folders + else: + cmd = [ + f"{build_top}/external/ktfmt/ktfmt.py", "--jar", jar_path, + repo_absolute_path + ] + + print( + f"Formatting the files that are already formatted with the command: {cmd}" + ) + run_cmd(cmd) + + if is_workspace_clean(): + print("All files were already properly formatted, skipping second CL") + else: + print("Creating second CL that formats all files") + create_second_cl(bug_id) + + +def create_second_cl(bug_id): + # Append 'ktfmt_update' at the end of a copy of the jar file to get + # a different sha1sum. + shutil.copyfile(jar_path, copy_path) + with open(copy_path, "a") as file_object: + file_object.write("ktfmt_update") + + sha1sum = get_sha1sum(copy_path) + change_id = f"I{sha1sum}" + command = " ".join(sys.argv) + cl_message = textwrap.dedent(f""" + Format files with the upcoming version of ktfmt + + This CL was generated automatically from the following command: + + $ {command} + + This CL formats all files already correctly formatted with the upcoming + version of ktfmt. + + Bug: {bug_id} + Test: Presubmits + Change-Id: {change_id} + Merged-In: {change_id} + """) + + run_cmd(["git", "add", "--all"]) + run_cmd(["git", "commit", "-m", cl_message]) + + +if __name__ == "__main__": + main() diff --git a/prepare_upgrade.sh b/prepare_upgrade.sh deleted file mode 100755 index 5ee6f7f..0000000 --- a/prepare_upgrade.sh +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (C) 2023 The Android Open Source Project -# -# 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. - -# This script prepares the update to a new ktfmt version in a single git -# repository. This will create max 2 CLs: -# 1. One that regenerates the ktfmt_includes.txt with the current version -# of ktfmt, so that all files already properly formatted are checked -# and files that are not already formatted are ignored. If the file is -# already up-to-date, then this CL won't be created. -# 2. One that reformats all files with the new version of ktfmt. This CL -# won't be created if all files are already formatted. - -# Stop the script at the first error. -set -e - -# Stop the script if we try to access a variable that does not exist. -set -u - -# Fail if we didn't pass the correct args. -[ $# -ne 3 ] && { - echo "Usage: $0 build_tools_id relative/repo/path/ bug_id" - echo "Example: prepare_upgrade.sh 8932651 frameworks/base/ 266197805" - exit 1 -} - -build_id=$1 -repo_relative_path=$2 -bug_id=$3 -repo_absolute_path="${ANDROID_BUILD_TOP}/$repo_relative_path" - -echo "Preparing upgrade of ktfmt from build $build_id" - -cd $repo_absolute_path - -# Check that the ktfmt_update1 and ktfmt_update2 local branches don't exist yet. -existing_branches=$(git branch | grep 'ktfmt_update1\|ktfmt_update2' || echo "") -[[ ! -z "$existing_branches" ]] && { - echo "Branches ktfmt_update1 or ktfmt_update2 already exist, you should delete them before running this script" - exit 1 -} - -# Fail if the workspace is not clean. -git_status=$(git status --porcelain) -[[ ! -z "$git_status" ]] && { - echo "The current repository contains uncommitted changes, please run this script in a clean workspace" - exit 1 -} - -echo "Downloading ktfmt.jar from aosp-build-tools-release" -tmp=/tmp/ktfmt -mkdir -p $tmp -zip_path="$tmp/common.zip" -/google/data/ro/projects/android/fetch_artifact --branch aosp-build-tools-release --bid $build_id --target linux build-common-prebuilts.zip $zip_path -unzip -q -o -d $tmp $zip_path -new_jar="$tmp/framework/ktfmt.jar" -[ -r "$new_jar" ] || (echo "Error: $new_jar is not readable" && exit 1) -echo "Extracted jar in $new_jar" - -# Find the ktfmt_includes.txt and the folders/files that were included file -includes_file=$(cat PREUPLOAD.cfg | grep ktfmt.py | sed 's/.*-i \(.*\) .*/\1/' | cut -c 14-) -includes_file=${includes_file#"$repo_relative_path"} -[ -r "$includes_file" ] || (echo "Error: $includes_file is not readable" && exit 1) -included_folders=$(cat ktfmt_includes.txt | grep + | cut -c 2- | tr '\n' ' ') - -echo "Creating local branch ktfmt_update1" -repo start ktfmt_update1 - -echo "Updating $includes_file with the command: \$ANDROID_BUILD_TOP/external/ktfmt/generate_includes_file.py --output=$includes_file $included_folders" -$ANDROID_BUILD_TOP/external/ktfmt/generate_includes_file.py --output=$includes_file $included_folders - -git_status=$(git status --porcelain) -if [[ ! -z "$git_status" ]] -then - echo "Creating first CL with update of $includes_file" - - # Use the sha1 of the jar file for change ID. - change_id="I$(sha1sum $new_jar | sed 's/\([a-z0-9]\{40\}\) .*/\1/')" - cl_message=$(cat << EOF -Regenerate include file for ktfmt upgrade - -This CL was generated automatically from the following command: - -$ $0 $@ - -This CL regenerates the inclusion file with the current version of ktfmt -so that it is up-to-date with files currently formatted or ignored by -ktfmt. - -Bug: $bug_id -Test: Presubmits -Change-Id: $change_id -Merged-In: $change_id -EOF -) - git add --all - git commit -m "$cl_message" -else - echo "No change were made to $includes_file, skipping first CL" -fi - -echo "Creating local branch ktfmt_update2" -repo start --head ktfmt_update2 - -echo "Formatting the files that are already formatted with the command: \${ANDROID_BUILD_TOP}/external/ktfmt/ktfmt.py -i $includes_file --jar $new_jar $included_folders" -${ANDROID_BUILD_TOP}/external/ktfmt/ktfmt.py -i $includes_file --jar $new_jar $included_folders 2> /dev/null - -git_status=$(git status --porcelain) -if [[ ! -z "$git_status" ]] -then - echo "Creating second CL that format all files" - - # Use the sha1 of the jar file + some random salt for change ID. - jar_copy=/tmp/ktfmt/copy.jar - cp $new_jar $jar_copy - echo "ktfmt_update" >> $jar_copy - change_id="I$(sha1sum $jar_copy | sed 's/\([a-z0-9]\{40\}\) .*/\1/')" - cl_message=$(cat << EOF -Format files with the upcoming version of ktfmt - -This CL was generated automatically from the following command: - -$ $0 $@ - -This CL formats all files already correctly formatted with the upcoming -version of ktfmt. - -Bug: $bug_id -Test: Presubmits -Change-Id: $change_id -Merged-In: $change_id -EOF -) - git add --all - git commit -m "$cl_message" -else - echo "All files were already properly formatted, skipping second CL" -fi - -echo -echo "Done. You can now submit the generated CL(s), if any." |