mbed-os/tools/importer/importer.py

279 lines
9.4 KiB
Python
Raw Normal View History

2019-02-15 13:19:05 +00:00
"""
Copyright (c) 2017-2019 ARM Limited. All rights reserved.
SPDX-License-Identifier: Apache-2.0
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.
"""
import os
import json
import sys
import subprocess
import logging
import argparse
2018-12-20 11:30:41 +00:00
from os.path import dirname, abspath, join, isfile, normpath
# Be sure that the tools directory is in the search path
ROOT = abspath(join(dirname(__file__), "../.."))
sys.path.insert(0, ROOT)
from tools.utils import run_cmd, delete_dir_files, mkdir, copy_file
def del_file(name):
""" Delete the file in RTOS/CMSIS/features directory of mbed-os
Args:
name - name of the file
"""
result = []
search_path = [join(ROOT, 'rtos'), join(ROOT, 'cmsis'), join(ROOT, 'features')]
for path in search_path:
for root, dirs, files in os.walk(path):
if name in files:
2018-12-20 11:30:41 +00:00
result.append(join(root, name))
for file in result:
os.remove(file)
2018-12-20 11:30:41 +00:00
rel_log.debug("Deleted %s", os.path.relpath(file, ROOT))
def copy_folder(src, dest):
""" Copy contents of folder in mbed-os listed path
Args:
src - src folder path
dest - destination folder path
"""
files = os.listdir(src)
for file in files:
2018-12-20 11:30:41 +00:00
abs_src_file = join(src, file)
if os.path.isfile(abs_src_file):
2018-12-20 11:30:41 +00:00
abs_dst_file = join(dest, file)
mkdir(dirname(abs_dst_file))
copy_file(abs_src_file, abs_dst_file)
def run_cmd_with_output(command, exit_on_failure=False):
""" Passes a command to the system and returns a True/False result once the
command has been executed, indicating success/failure. If the command was
successful then the output from the command is returned to the caller.
Commands are passed as a list of tokens.
E.g. The command 'git remote -v' would be passed in as ['git', 'remote', '-v']
Args:
command - system command as a list of tokens
exit_on_failure - If True exit the program on failure (default = False)
Returns:
result - True/False indicating the success/failure of the command
output - The output of the command if it was successful, else empty string
"""
rel_log.debug('[Exec] %s', ' '.join(command))
returncode = 0
output = ""
try:
2018-12-20 11:30:41 +00:00
output = subprocess.check_output(command)
except subprocess.CalledProcessError as e:
returncode = e.returncode
if exit_on_failure:
rel_log.error("The command %s failed with return code: %s",
(' '.join(command)), returncode)
sys.exit(1)
return returncode, output
def get_curr_sha(repo_path):
""" Gets the latest SHA for the specified repo
Args:
repo_path - path to the repository
Returns:
sha - last commit SHA
"""
cwd = os.getcwd()
os.chdir(abspath(repo_path))
2018-12-20 11:30:41 +00:00
cmd = ['git', 'log', '--pretty=format:%h', '-n', '1']
_, sha = run_cmd_with_output(cmd, exit_on_failure=True)
os.chdir(cwd)
return sha
def branch_exists(name):
""" Check if branch already exists in mbed-os local repository.
It will not verify if branch is present in remote repository.
Args:
name - branch name
Returns:
True - If branch is already present
"""
2018-12-20 11:30:41 +00:00
cmd = ['git', 'branch']
_, output = run_cmd_with_output(cmd, exit_on_failure=False)
if name in output:
return True
return False
def branch_checkout(name):
"""
Checkout the required branch
Args:
name - branch name
"""
2018-12-20 11:30:41 +00:00
cmd = ['git', 'checkout', name]
_, _ = run_cmd_with_output(cmd, exit_on_failure=False)
rel_log.info("Checkout to branch %s", name)
def get_last_cherry_pick_sha(branch):
"""
SHA of last cherry pick commit is returned. SHA should be added to all
cherry-pick commits with -x option.
Args:
branch - Hash to be verified.
Returns - SHA if found, else None
"""
2018-12-20 11:30:41 +00:00
cmd = ['git', 'checkout', branch]
run_cmd_with_output(cmd, exit_on_failure=False)
sha = None
2018-12-20 11:30:41 +00:00
get_commit = ['git', 'log', '-n', '1']
_, output = run_cmd_with_output(get_commit, exit_on_failure=True)
lines = output.split('\n')
for line in lines:
if 'cherry picked from' in line:
sha = line.split(' ')[-1]
return sha[:-1]
return sha
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-l', '--log-level',
help="Level for providing logging output",
default='INFO')
parser.add_argument('-r', '--repo-path',
help="Git Repository to be imported",
default=None,
required=True)
parser.add_argument('-c', '--config-file',
help="Configuration file",
default=None,
required=True)
args = parser.parse_args()
level = getattr(logging, args.log_level.upper())
# Set logging level
logging.basicConfig(level=level)
rel_log = logging.getLogger("Importer")
if (args.repo_path is None) or (args.config_file is None):
rel_log.error("Repository path and config file required as input. Use \"--help\" for more info.")
exit(1)
2018-12-20 11:30:41 +00:00
json_file = abspath(args.config_file)
if not os.path.isfile(json_file):
rel_log.error("%s not found.", args.config_file)
exit(1)
2018-12-20 11:30:41 +00:00
repo = abspath(args.repo_path)
if not os.path.exists(repo):
rel_log.error("%s not found.", args.repo_path)
exit(1)
sha = get_curr_sha(repo)
if not sha:
rel_log.error("Could not obtain latest SHA")
exit(1)
rel_log.info("%s SHA = %s", os.path.basename(repo), sha)
branch = 'feature_' + os.path.basename(repo) + '_' + sha
commit_msg = "[" + os.path.basename(repo) + "]" + ": Updated to " + sha
# Read configuration data
with open(json_file, 'r') as config:
json_data = json.load(config)
'''
Check if branch exists already, in case branch is present
we will skip all file transfer and merge operations and will
jump to cherry-pick
'''
if branch_exists(branch):
rel_log.info("Branch present = %s", branch)
else:
data_files = json_data["files"]
data_folders = json_data["folders"]
## Remove all files listed in .json from mbed-os repo to avoid duplications
for file in data_files:
src_file = file['src_file']
del_file(os.path.basename(src_file))
2018-12-20 11:30:41 +00:00
dest_file = join(ROOT, file['dest_file'])
if isfile(dest_file):
os.remove(join(ROOT, dest_file))
rel_log.debug("Deleted %s", file['dest_file'])
for folder in data_folders:
dest_folder = folder['dest_folder']
delete_dir_files(dest_folder)
2018-12-20 11:30:41 +00:00
rel_log.debug("Deleted: %s", folder['dest_folder'])
rel_log.info("Removed files/folders listed in json file")
2018-12-20 11:30:41 +00:00
## Copy all the files listed in json file to mbed-os
for file in data_files:
2018-12-20 11:30:41 +00:00
repo_file = join(repo, file['src_file'])
mbed_path = join(ROOT, file['dest_file'])
mkdir(dirname(mbed_path))
copy_file(repo_file, mbed_path)
2018-12-20 11:30:41 +00:00
rel_log.debug("Copied %s to %s", normpath(repo_file), normpath(mbed_path))
for folder in data_folders:
2018-12-20 11:30:41 +00:00
repo_folder = join(repo, folder['src_folder'])
mbed_path = join(ROOT, folder['dest_folder'])
copy_folder(repo_folder, mbed_path)
2018-12-20 11:30:41 +00:00
rel_log.debug("Copied %s to %s", normpath(repo_folder), normpath(mbed_path))
## Create new branch with all changes
2018-12-20 11:30:41 +00:00
create_branch = ['git', 'checkout', '-b', branch]
run_cmd_with_output(create_branch, exit_on_failure=True)
2018-12-20 11:30:41 +00:00
rel_log.info("Branch created: %s", branch)
2018-12-20 11:30:41 +00:00
add_files = ['git', 'add', '-A']
run_cmd_with_output(add_files, exit_on_failure=True)
2018-12-20 11:30:41 +00:00
commit_branch = ['git', 'commit', '-m', commit_msg]
run_cmd_with_output(commit_branch, exit_on_failure=True)
2018-12-20 11:30:41 +00:00
rel_log.info('Commit added: "%s"', commit_msg)
## Checkout the feature branch
branch_checkout(branch)
commit_sha = json_data["commit_sha"]
last_sha = get_last_cherry_pick_sha(branch)
if not last_sha:
## Apply commits specific to mbed-os changes
for sha in commit_sha:
2018-12-20 11:30:41 +00:00
cherry_pick_sha = ['git', 'cherry-pick', '-x', sha]
run_cmd_with_output(cherry_pick_sha, exit_on_failure=True)
2018-12-20 11:30:41 +00:00
rel_log.info("Cherry-picked commit = %s", sha)
## Few commits are already applied, check the next in sequence
## and skip to last applied
else:
found = False
for sha in commit_sha:
if sha == last_sha:
found = True
continue
if found is True:
2018-12-20 11:30:41 +00:00
cherry_pick_sha = ['git', 'cherry-pick', '-x', sha]
run_cmd_with_output(cherry_pick_sha, exit_on_failure=True)
2018-12-20 11:30:41 +00:00
rel_log.info("Cherry-picked commit = %s", sha)