#!/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()
