You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.6 KiB
203 lines
6.6 KiB
#!/usr/bin/python2
|
|
import logging, mox, os, shutil, tempfile, unittest, utils
|
|
|
|
# This makes autotest_lib imports available.
|
|
import common
|
|
from autotest_lib.client.common_lib import revision_control
|
|
|
|
|
|
class GitRepoManager(object):
|
|
"""
|
|
A wrapper for GitRepo.
|
|
"""
|
|
commit_hash = None
|
|
commit_msg = None
|
|
repodir = None
|
|
git_repo_manager = None
|
|
|
|
|
|
def __init__(self, main_repo=None):
|
|
"""
|
|
Setup self.git_repo_manager.
|
|
|
|
If a main_repo is present clone it.
|
|
Otherwise create a directory in /tmp and init it.
|
|
|
|
@param main_repo: GitRepo representing main.
|
|
"""
|
|
if main_repo is None:
|
|
self.repodir = tempfile.mktemp(suffix='main')
|
|
self._create_git_repo(self.repodir)
|
|
self.git_repo_manager = revision_control.GitRepo(
|
|
self.repodir,
|
|
self.repodir,
|
|
abs_work_tree=self.repodir)
|
|
self._setup_git_environment()
|
|
# Create an initial commit. We really care about the common case
|
|
# where there exists a commit in the upstream repo.
|
|
self._edit('initial_commit_file', 'is_non_empty')
|
|
self.add()
|
|
self.commit('initial_commit')
|
|
else:
|
|
self.repodir = tempfile.mktemp(suffix='dependent')
|
|
self.git_repo_manager = revision_control.GitRepo(
|
|
self.repodir,
|
|
main_repo.repodir,
|
|
abs_work_tree=self.repodir)
|
|
self.git_repo_manager.clone()
|
|
self._setup_git_environment()
|
|
|
|
|
|
def _setup_git_environment(self):
|
|
"""
|
|
Mock out basic git environment to keep tests deterministic.
|
|
"""
|
|
# Set user and email for the test git checkout.
|
|
self.git_repo_manager.gitcmd('config user.name Unittests')
|
|
self.git_repo_manager.gitcmd('config user.email utests@chromium.org')
|
|
|
|
|
|
def _edit(self, filename='foo', msg='bar'):
|
|
"""
|
|
Write msg into a file in the repodir.
|
|
|
|
@param filename: Name of the file in current repo.
|
|
If none exists one will be created.
|
|
@param msg: A message to write into the file.
|
|
"""
|
|
local_file_name = os.path.join(self.git_repo_manager.repodir,
|
|
filename)
|
|
with open(local_file_name, 'w') as f:
|
|
f.write(msg)
|
|
|
|
|
|
def _create_git_repo(self, repodir):
|
|
"""
|
|
Init a new git repository.
|
|
|
|
@param repodir: directory for repo.
|
|
"""
|
|
logging.info('initializing git repo in: %s', repodir)
|
|
gitcmd = 'git init %s' % repodir
|
|
rv = utils.run(gitcmd)
|
|
if rv.exit_status != 0:
|
|
logging.error(rv.stderr)
|
|
raise revision_control.revision_control.GitError(gitcmd + 'failed')
|
|
|
|
|
|
def add(self):
|
|
"""
|
|
Add all unadded files in repodir to repo.
|
|
"""
|
|
rv = self.git_repo_manager.gitcmd('add .')
|
|
if rv.exit_status != 0:
|
|
logging.error(rv.stderr)
|
|
raise revision_control.GitError('Unable to add files to repo', rv)
|
|
|
|
|
|
def commit(self, msg='default'):
|
|
"""
|
|
Commit changes to repo with the supplied commit msg.
|
|
Also updates commit_hash with the hash for this commit.
|
|
|
|
@param msg: A message that goes with the commit.
|
|
"""
|
|
self.git_repo_manager.commit(msg)
|
|
self.commit_hash = self.git_repo_manager.get_latest_commit_hash()
|
|
|
|
|
|
def get_main_tot(self):
|
|
"""
|
|
Get everything from mains TOT squashing local changes.
|
|
If the dependent repo is empty pull from main.
|
|
"""
|
|
# TODO b:169251326 terms below are set outside of this codebase
|
|
# and should be updated when possible. ("master" -> "main")
|
|
# Currently (but I believe it will eventually) does not support
|
|
# `reset --hard origin/main` (must be origin/master).
|
|
self.git_repo_manager.reinit_repo_at('master')
|
|
self.commit_hash = self.git_repo_manager.get_latest_commit_hash()
|
|
|
|
|
|
class RevisionControlUnittest(mox.MoxTestBase):
|
|
"""
|
|
A unittest to exercise build_externals.py's usage
|
|
of revision_control.py's Git wrappers.
|
|
"""
|
|
main_repo=None
|
|
dependent_repo=None
|
|
|
|
def setUp(self):
|
|
"""
|
|
Create a main repo and clone it into a dependent repo.
|
|
"""
|
|
super(RevisionControlUnittest, self).setUp()
|
|
self.main_repo = GitRepoManager()
|
|
self.dependent_repo = GitRepoManager(self.main_repo)
|
|
|
|
|
|
def tearDown(self):
|
|
"""
|
|
Delete temporary directories.
|
|
"""
|
|
shutil.rmtree(self.main_repo.repodir)
|
|
shutil.rmtree(self.dependent_repo.repodir)
|
|
super(RevisionControlUnittest, self).tearDown()
|
|
|
|
|
|
def testCommit(self):
|
|
"""
|
|
Test add, commit, pull, clone.
|
|
"""
|
|
self.main_repo._edit()
|
|
self.main_repo.add()
|
|
self.main_repo.commit()
|
|
self.dependent_repo.get_main_tot()
|
|
self.assertEquals(self.dependent_repo.commit_hash,
|
|
self.main_repo.commit_hash,
|
|
msg=(("hashes don't match after clone, main and dependent repo"
|
|
"out of sync: %r != %r") %
|
|
(self.dependent_repo.commit_hash,
|
|
self.main_repo.commit_hash)))
|
|
|
|
self.main_repo._edit(msg='foobar')
|
|
self.main_repo.commit()
|
|
self.dependent_repo.get_main_tot()
|
|
self.assertEquals(self.dependent_repo.commit_hash,
|
|
self.main_repo.commit_hash,
|
|
msg=(("hashes don't match after pull, main and dependent repo"
|
|
"out of sync: %r != %r") %
|
|
(self.dependent_repo.commit_hash,
|
|
self.main_repo.commit_hash)))
|
|
|
|
|
|
def testGitUrlClone(self):
|
|
"""
|
|
Test that git clone raises a ValueError if giturl is unset.
|
|
"""
|
|
self.dependent_repo.git_repo_manager._giturl = None
|
|
self.assertRaises(ValueError,
|
|
self.dependent_repo.git_repo_manager.clone)
|
|
|
|
|
|
def testGitUrlPull(self):
|
|
"""
|
|
Test that git pull raises a ValueError if giturl is unset.
|
|
"""
|
|
self.dependent_repo.git_repo_manager._giturl = None
|
|
self.assertRaises(ValueError,
|
|
self.dependent_repo.git_repo_manager.pull)
|
|
|
|
|
|
def testGitUrlFetch(self):
|
|
"""
|
|
Test that git fetch raises a ValueError if giturl is unset.
|
|
"""
|
|
self.dependent_repo.git_repo_manager._giturl = None
|
|
self.assertRaises(ValueError,
|
|
self.dependent_repo.git_repo_manager.fetch_remote)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|