diff options
Diffstat (limited to 'deprecated/repo_to_repo.py')
-rwxr-xr-x | deprecated/repo_to_repo.py | 425 |
1 files changed, 0 insertions, 425 deletions
diff --git a/deprecated/repo_to_repo.py b/deprecated/repo_to_repo.py deleted file mode 100755 index 91c5d580..00000000 --- a/deprecated/repo_to_repo.py +++ /dev/null @@ -1,425 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright 2010 Google Inc. All Rights Reserved. -"""Module for transferring files between various types of repositories.""" - -from __future__ import print_function - -__author__ = 'asharif@google.com (Ahmad Sharif)' - -import argparse -import datetime -import json -import os -import re -import socket -import sys -import tempfile - -from automation.clients.helper import perforce -from cros_utils import command_executer -from cros_utils import logger -from cros_utils import misc - -# pylint: disable=anomalous-backslash-in-string - - -def GetCanonicalMappings(mappings): - canonical_mappings = [] - for mapping in mappings: - remote_path, local_path = mapping.split() - if local_path.endswith('/') and not remote_path.endswith('/'): - local_path = os.path.join(local_path, os.path.basename(remote_path)) - remote_path = remote_path.lstrip('/').split('/', 1)[1] - canonical_mappings.append(perforce.PathMapping(remote_path, local_path)) - return canonical_mappings - - -def SplitMapping(mapping): - parts = mapping.split() - assert len(parts) <= 2, 'Mapping %s invalid' % mapping - remote_path = parts[0] - if len(parts) == 2: - local_path = parts[1] - else: - local_path = '.' - return remote_path, local_path - - -class Repo(object): - """Basic repository base class.""" - - def __init__(self, no_create_tmp_dir=False): - self.repo_type = None - self.address = None - self.mappings = None - self.revision = None - self.ignores = ['.gitignore', '.p4config', 'README.google'] - if no_create_tmp_dir: - self._root_dir = None - else: - self._root_dir = tempfile.mkdtemp() - self._ce = command_executer.GetCommandExecuter() - self._logger = logger.GetLogger() - - def PullSources(self): - """Pull all sources into an internal dir.""" - pass - - def SetupForPush(self): - """Setup a repository for pushing later.""" - pass - - def PushSources(self, commit_message=None, dry_run=False, message_file=None): - """Push to the external repo with the commit message.""" - pass - - def _RsyncExcludingRepoDirs(self, source_dir, dest_dir): - for f in os.listdir(source_dir): - if f in ['.git', '.svn', '.p4config']: - continue - dest_file = os.path.join(dest_dir, f) - source_file = os.path.join(source_dir, f) - if os.path.exists(dest_file): - command = 'rm -rf %s' % dest_file - self._ce.RunCommand(command) - command = 'rsync -a %s %s' % (source_file, dest_dir) - self._ce.RunCommand(command) - return 0 - - def MapSources(self, dest_dir): - """Copy sources from the internal dir to root_dir.""" - return self._RsyncExcludingRepoDirs(self._root_dir, dest_dir) - - def GetRoot(self): - return self._root_dir - - def SetRoot(self, directory): - self._root_dir = directory - - def CleanupRoot(self): - command = 'rm -rf %s' % self._root_dir - return self._ce.RunCommand(command) - - def __str__(self): - return '\n'.join( - str(s) for s in [self.repo_type, self.address, self.mappings]) - - -# Note - this type of repo is used only for "readonly", in other words, this -# only serves as a incoming repo. -class FileRepo(Repo): - """Class for file repositories.""" - - def __init__(self, address, ignores=None): - Repo.__init__(self, no_create_tmp_dir=True) - self.repo_type = 'file' - self.address = address - self.mappings = None - self.branch = None - self.revision = '{0} (as of "{1}")'.format(address, datetime.datetime.now()) - self.gerrit = None - self._root_dir = self.address - if ignores: - self.ignores += ignores - - def CleanupRoot(self): - """Override to prevent deletion.""" - pass - - -class P4Repo(Repo): - """Class for P4 repositories.""" - - def __init__(self, address, mappings, revision=None): - Repo.__init__(self) - self.repo_type = 'p4' - self.address = address - self.mappings = mappings - self.revision = revision - - def PullSources(self): - client_name = socket.gethostname() - client_name += tempfile.mkstemp()[1].replace('/', '-') - mappings = self.mappings - p4view = perforce.View('depot2', GetCanonicalMappings(mappings)) - p4client = perforce.CommandsFactory( - self._root_dir, p4view, name=client_name) - command = p4client.SetupAndDo(p4client.Sync(self.revision)) - ret = self._ce.RunCommand(command) - assert ret == 0, 'Could not setup client.' - command = p4client.InCheckoutDir(p4client.SaveCurrentCLNumber()) - ret, o, _ = self._ce.RunCommandWOutput(command) - assert ret == 0, 'Could not get version from client.' - self.revision = re.search('^\d+$', o.strip(), re.MULTILINE).group(0) - command = p4client.InCheckoutDir(p4client.Remove()) - ret = self._ce.RunCommand(command) - assert ret == 0, 'Could not delete client.' - return 0 - - -class SvnRepo(Repo): - """Class for svn repositories.""" - - def __init__(self, address, mappings): - Repo.__init__(self) - self.repo_type = 'svn' - self.address = address - self.mappings = mappings - - def PullSources(self): - with misc.WorkingDirectory(self._root_dir): - for mapping in self.mappings: - remote_path, local_path = SplitMapping(mapping) - command = 'svn co %s/%s %s' % (self.address, remote_path, local_path) - ret = self._ce.RunCommand(command) - if ret: - return ret - - self.revision = '' - for mapping in self.mappings: - remote_path, local_path = SplitMapping(mapping) - command = 'cd %s && svnversion -c .' % (local_path) - ret, o, _ = self._ce.RunCommandWOutput(command) - self.revision += o.strip().split(':')[-1] - if ret: - return ret - return 0 - - -class GitRepo(Repo): - """Class for git repositories.""" - - def __init__(self, address, branch, mappings=None, ignores=None, gerrit=None): - Repo.__init__(self) - self.repo_type = 'git' - self.address = address - self.branch = branch or 'master' - if ignores: - self.ignores += ignores - self.mappings = mappings - self.gerrit = gerrit - - def _CloneSources(self): - with misc.WorkingDirectory(self._root_dir): - command = 'git clone %s .' % (self.address) - return self._ce.RunCommand(command) - - def PullSources(self): - with misc.WorkingDirectory(self._root_dir): - ret = self._CloneSources() - if ret: - return ret - - command = 'git checkout %s' % self.branch - ret = self._ce.RunCommand(command) - if ret: - return ret - - command = 'git describe --always' - ret, o, _ = self._ce.RunCommandWOutput(command) - self.revision = o.strip() - return ret - - def SetupForPush(self): - with misc.WorkingDirectory(self._root_dir): - ret = self._CloneSources() - logger.GetLogger().LogFatalIf( - ret, 'Could not clone git repo %s.' % self.address) - - command = 'git branch -a | grep -wq %s' % self.branch - ret = self._ce.RunCommand(command) - - if ret == 0: - if self.branch != 'master': - command = ('git branch --track %s remotes/origin/%s' % (self.branch, - self.branch)) - else: - command = 'pwd' - command += '&& git checkout %s' % self.branch - else: - command = 'git symbolic-ref HEAD refs/heads/%s' % self.branch - command += '&& rm -rf *' - ret = self._ce.RunCommand(command) - return ret - - def CommitLocally(self, commit_message=None, message_file=None): - with misc.WorkingDirectory(self._root_dir): - command = 'pwd' - for ignore in self.ignores: - command += '&& echo \'%s\' >> .git/info/exclude' % ignore - command += '&& git add -Av .' - if message_file: - message_arg = '-F %s' % message_file - elif commit_message: - message_arg = '-m \'%s\'' % commit_message - else: - raise RuntimeError('No commit message given!') - command += '&& git commit -v %s' % message_arg - return self._ce.RunCommand(command) - - def PushSources(self, commit_message=None, dry_run=False, message_file=None): - ret = self.CommitLocally(commit_message, message_file) - if ret: - return ret - push_args = '' - if dry_run: - push_args += ' -n ' - with misc.WorkingDirectory(self._root_dir): - if self.gerrit: - label = 'somelabel' - command = 'git remote add %s %s' % (label, self.address) - command += ('&& git push %s %s HEAD:refs/for/master' % (push_args, - label)) - else: - command = 'git push -v %s origin %s:%s' % (push_args, self.branch, - self.branch) - ret = self._ce.RunCommand(command) - return ret - - def MapSources(self, root_dir): - if not self.mappings: - self._RsyncExcludingRepoDirs(self._root_dir, root_dir) - return - with misc.WorkingDirectory(self._root_dir): - for mapping in self.mappings: - remote_path, local_path = SplitMapping(mapping) - remote_path.rstrip('...') - local_path.rstrip('...') - full_local_path = os.path.join(root_dir, local_path) - ret = self._RsyncExcludingRepoDirs(remote_path, full_local_path) - if ret: - return ret - return 0 - - -class RepoReader(object): - """Class for reading repositories.""" - - def __init__(self, filename): - self.filename = filename - self.main_dict = {} - self.input_repos = [] - self.output_repos = [] - - def ParseFile(self): - with open(self.filename) as f: - self.main_dict = json.load(f) - self.CreateReposFromDict(self.main_dict) - return [self.input_repos, self.output_repos] - - def CreateReposFromDict(self, main_dict): - for key, repo_list in main_dict.items(): - for repo_dict in repo_list: - repo = self.CreateRepoFromDict(repo_dict) - if key == 'input': - self.input_repos.append(repo) - elif key == 'output': - self.output_repos.append(repo) - else: - logger.GetLogger().LogFatal('Unknown key: %s found' % key) - - def CreateRepoFromDict(self, repo_dict): - repo_type = repo_dict.get('type', None) - repo_address = repo_dict.get('address', None) - repo_mappings = repo_dict.get('mappings', None) - repo_ignores = repo_dict.get('ignores', None) - repo_branch = repo_dict.get('branch', None) - gerrit = repo_dict.get('gerrit', None) - revision = repo_dict.get('revision', None) - - if repo_type == 'p4': - repo = P4Repo(repo_address, repo_mappings, revision=revision) - elif repo_type == 'svn': - repo = SvnRepo(repo_address, repo_mappings) - elif repo_type == 'git': - repo = GitRepo( - repo_address, - repo_branch, - mappings=repo_mappings, - ignores=repo_ignores, - gerrit=gerrit) - elif repo_type == 'file': - repo = FileRepo(repo_address) - else: - logger.GetLogger().LogFatal('Unknown repo type: %s' % repo_type) - return repo - - -@logger.HandleUncaughtExceptions -def Main(argv): - parser = argparse.ArgumentParser() - parser.add_argument( - '-i', - '--input_file', - dest='input_file', - help='The input file that contains repo descriptions.') - - parser.add_argument( - '-n', - '--dry_run', - dest='dry_run', - action='store_true', - default=False, - help='Do a dry run of the push.') - - parser.add_argument( - '-F', - '--message_file', - dest='message_file', - default=None, - help=('Use contents of the log file as the commit ' - 'message.')) - - options = parser.parse_args(argv) - if not options.input_file: - parser.print_help() - return 1 - rr = RepoReader(options.input_file) - [input_repos, output_repos] = rr.ParseFile() - - # Make sure FileRepo is not used as output destination. - for output_repo in output_repos: - if output_repo.repo_type == 'file': - logger.GetLogger().LogFatal( - 'FileRepo is only supported as an input repo.') - - for output_repo in output_repos: - ret = output_repo.SetupForPush() - if ret: - return ret - - input_revisions = [] - for input_repo in input_repos: - ret = input_repo.PullSources() - if ret: - return ret - input_revisions.append(input_repo.revision) - - for input_repo in input_repos: - for output_repo in output_repos: - ret = input_repo.MapSources(output_repo.GetRoot()) - if ret: - return ret - - commit_message = 'Synced repos to: %s' % ','.join(input_revisions) - for output_repo in output_repos: - ret = output_repo.PushSources( - commit_message=commit_message, - dry_run=options.dry_run, - message_file=options.message_file) - if ret: - return ret - - if not options.dry_run: - for output_repo in output_repos: - output_repo.CleanupRoot() - for input_repo in input_repos: - input_repo.CleanupRoot() - - return ret - - -if __name__ == '__main__': - retval = Main(sys.argv[1:]) - sys.exit(retval) |