stack-orchestrator/app/setup_repositories.py

144 lines
5.4 KiB
Python
Raw Normal View History

2022-08-23 21:58:32 +00:00
# Copyright © 2022 Cerc
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
2022-08-23 17:32:55 +00:00
# env vars:
2022-08-23 22:02:38 +00:00
# CERC_REPO_BASE_DIR defaults to ~/cerc
2022-08-23 17:32:55 +00:00
import os
import sys
from decouple import config
import git
from tqdm import tqdm
2022-08-24 03:27:42 +00:00
import click
2022-08-23 17:32:55 +00:00
2022-10-04 01:37:18 +00:00
2022-08-23 17:32:55 +00:00
class GitProgress(git.RemoteProgress):
def __init__(self):
super().__init__()
2022-10-04 01:37:18 +00:00
self.pbar = tqdm(unit='B', ascii=True, unit_scale=True)
2022-08-23 17:32:55 +00:00
def update(self, op_code, cur_count, max_count=None, message=''):
self.pbar.total = max_count
self.pbar.n = cur_count
self.pbar.refresh()
2022-10-04 01:37:18 +00:00
2022-08-23 17:32:55 +00:00
def is_git_repo(path):
try:
_ = git.Repo(path).git_dir
return True
except git.exc.InvalidGitRepositoryError:
return False
2022-08-24 18:29:51 +00:00
# TODO: find a place for this in the context of click
2022-10-04 01:37:18 +00:00
# parser = argparse.ArgumentParser(
2022-08-24 18:29:51 +00:00
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
# )
2022-08-23 17:32:55 +00:00
2022-10-04 01:37:18 +00:00
2022-08-24 03:27:42 +00:00
@click.command()
2022-08-24 19:01:35 +00:00
@click.option('--check-only', is_flag=True, default=False)
@click.option('--pull', is_flag=True, default=False)
@click.option('--branches-file', help="checkout branches specified in this file")
2022-08-24 18:29:51 +00:00
@click.pass_context
def command(ctx, check_only, pull, branches_file):
2022-08-24 18:29:51 +00:00
'''git clone the set of repositories required to build the complete system from source'''
2022-08-24 03:27:42 +00:00
2022-08-24 18:29:51 +00:00
quiet = ctx.obj.quiet
verbose = ctx.obj.verbose
2022-08-24 19:01:35 +00:00
dry_run = ctx.obj.dry_run
2022-08-24 03:27:42 +00:00
branches = []
if branches_file:
if verbose:
print(f"loading branches from: {branches_file}")
with open(branches_file) as branches_file_open:
branches = branches_file_open.read().splitlines()
if verbose:
print(f"Branches are: {branches}")
local_stack = ctx.obj.local_stack
if local_stack:
2022-10-04 01:37:18 +00:00
dev_root_path = default = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
else:
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
2022-08-24 03:27:42 +00:00
2022-08-24 19:01:35 +00:00
if not quiet:
2022-08-24 03:27:42 +00:00
print(f'Dev Root is: {dev_root_path}')
if not os.path.isdir(dev_root_path):
if not quiet:
2022-10-04 01:37:18 +00:00
print('Dev root directory doesn\'t exist, creating')
2022-08-24 03:27:42 +00:00
os.makedirs(dev_root_path)
with open("repository-list.txt") as repository_list_file:
repos = repository_list_file.read().splitlines()
if verbose:
2022-10-04 01:37:18 +00:00
print(f'Repos: {repos}')
2022-08-24 03:27:42 +00:00
def process_repo(repo):
full_github_repo_path = f'git@github.com:{repo}'
repoName = repo.split("/")[-1]
full_filesystem_repo_path = os.path.join(dev_root_path, repoName)
is_present = os.path.isdir(full_filesystem_repo_path)
if not quiet:
2022-10-04 01:37:18 +00:00
present_text = f'already exists active branch: {git.Repo(full_filesystem_repo_path).active_branch}' if is_present \
else 'Needs to be fetched'
2022-08-24 03:27:42 +00:00
print(f'Checking: {full_filesystem_repo_path}: {present_text}')
# Quick check that it's actually a repo
if is_present:
if not is_git_repo(full_filesystem_repo_path):
print(f'Error: {full_filesystem_repo_path} does not contain a valid git repository')
sys.exit(1)
else:
2022-08-24 18:29:51 +00:00
if pull:
2022-08-24 03:27:42 +00:00
if verbose:
print(f'Running git pull for {full_filesystem_repo_path}')
2022-08-24 18:29:51 +00:00
if not check_only:
git_repo = git.Repo(full_filesystem_repo_path)
origin = git_repo.remotes.origin
2022-10-04 01:37:18 +00:00
origin.pull(progress=None if quiet else GitProgress())
2022-08-24 03:27:42 +00:00
else:
print("(git pull skipped)")
if not is_present:
# Clone
if verbose:
print(f'Running git clone for {full_github_repo_path} into {full_filesystem_repo_path}')
2022-08-24 18:29:51 +00:00
if not dry_run:
2022-10-04 01:37:18 +00:00
git.Repo.clone_from(full_github_repo_path,
full_filesystem_repo_path,
progress=None if quiet else GitProgress())
2022-08-24 03:27:42 +00:00
else:
print("(git clone skipped)")
# Checkout the requested branch, if one was specified
if branches:
# Find the current repo in the branches list
for repo_branch in branches:
repo_branch_tuple = repo_branch.split(" ")
if repo_branch_tuple[0] == repo:
# checkout specified branch
branch_to_checkout = repo_branch_tuple[1]
if verbose:
print(f"checking out branch {branch_to_checkout} in repo {repo}")
git_repo = git.Repo(full_filesystem_repo_path)
git_repo.git.checkout(branch_to_checkout)
2022-08-24 03:27:42 +00:00
for repo in repos:
process_repo(repo)