Refactor and improve git repository cloning
Issue-ID: OOM-1803
Change-Id: Ia8e222c2b70b58ed1f7dbc4254ea2f5cb5a9ef7b
Signed-off-by: Milan Verespej <m.verespej@partner.samsung.com>
diff --git a/build/download/git_downloader.py b/build/download/git_downloader.py
new file mode 100755
index 0000000..46faa8f
--- /dev/null
+++ b/build/download/git_downloader.py
@@ -0,0 +1,137 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# COPYRIGHT NOTICE STARTS HERE
+
+# Copyright 2019 © Samsung Electronics Co., Ltd.
+#
+# 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.
+
+# COPYRIGHT NOTICE ENDS HERE
+
+import argparse
+import datetime
+import logging
+import os
+import shutil
+import subprocess
+import sys
+import timeit
+
+from command_downloader import CommandDownloader
+
+log = logging.getLogger(name=__name__)
+
+
+class GitDownloader(CommandDownloader):
+ def __init__(self, *list_args):
+ super().__init__('git repositories', 'git', *list_args)
+
+ @property
+ def check_table(self):
+ """
+ Table with information which items from lists are downloaded
+ """
+ self.missing()
+ header = ['Name', 'Branch', 'Downloaded']
+ return self._check_table(header, {'Name': 'l'},
+ ((*item.split(), self._downloaded(item)) for item
+ in self._data_list))
+
+ @staticmethod
+ def _download_item(item):
+ repo, branch = item[0].split()
+ dst = '{}/{}'.format(item[1], repo)
+ command = 'git clone -b {} --single-branch https://{} --bare {}'.format(branch,
+ repo,
+ dst)
+ if os.path.exists(dst):
+ log.warning('File or directory exists {} removing and cloning'
+ ' to be sure it is latest.'.format(dst))
+ if os.path.isfile(dst):
+ os.remove(dst)
+ elif os.path.isdir(dst):
+ shutil.rmtree(dst)
+
+ log.info('Running: {}'.format(command))
+ log.info(
+ subprocess.check_output(command.split(), stderr=subprocess.STDOUT).decode())
+ log.info('Downloaded: {}'.format(repo))
+
+ def _is_missing(self, item):
+ """
+ Check if item is missing (not cloned)
+ :param item: item to check
+ :return: True if not present 'maybe' if directory exists
+ """
+ dst = '{}/{}'.format(self._data_list[item], item.split()[0])
+ if os.path.exists(dst):
+ # it is bare repo who knows
+ return 'maybe'
+ return True
+
+ def _downloaded(self, item):
+ """
+ Check if item is present (cloned)
+ :param item: item to check
+ :return: True if not cloned 'maybe' if directory exists
+ """
+ missing = self._is_missing(item)
+ if missing != 'maybe':
+ return False
+ # It is bare repo so who knows if it is latest version
+ return 'maybe'
+
+ def missing(self):
+ """
+ Check for missing data (not downloaded)
+ :return: dictionary of missing items
+ """
+ self._missing = {item: dst for item, dst in self._data_list.items()}
+ return self._missing
+
+
+def run_cli():
+ """
+ Run as cli tool
+ """
+ parser = argparse.ArgumentParser(description='Download git repositories from list')
+ parser.add_argument('git_list', metavar='git-list',
+ help='File with list of npm packages to download.')
+ parser.add_argument('--output-dir', '-o', default=os.getcwd(),
+ help='Download destination')
+ parser.add_argument('--check', '-c', action='store_true', default=False,
+ help='Check mode')
+
+ args = parser.parse_args()
+
+ logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(message)s')
+
+ downloader = GitDownloader([args.git_list, args.output_dir])
+ if args.check:
+ log.info('Check mode. No download will be executed.')
+ log.info(downloader.check_table)
+ sys.exit(0)
+
+ timer_start = timeit.default_timer()
+ try:
+ downloader.download()
+ except RuntimeError:
+ sys.exit(1)
+ finally:
+ log.info('Downloading finished in {}'.format(
+ datetime.timedelta(seconds=timeit.default_timer() - timer_start)))
+
+
+if __name__ == '__main__':
+ run_cli()