diff --git a/fixtures_git/gitfixture.py b/fixtures_git/gitfixture.py index b5bc1d5..60bac0a 100644 --- a/fixtures_git/gitfixture.py +++ b/fixtures_git/gitfixture.py @@ -23,6 +23,11 @@ import git from fixtures_git import utils +try: + import urlparse as parse +except ImportError: + from urllib import parse + class GitTree(object): """Helper class to build a git repository from a graph definition @@ -284,3 +289,53 @@ class GitFixture(fixtures.Fixture): for x in range(num): self._create_file_commit( change_id=ids[x], message_prefix=message_prefix) + + +class GitCloneFixture(fixtures.Fixture): + def __init__(self, repo_url, username=None, password=None, directory=None): + """ + Setup a fixture with a cloned git repo + + Clones a repo to a temporary directory that is deleted once the + fixture is cleaned up. + + To use tokens for cloning from Github private repos for testing, + set the username to '' and password to your token and it will + reconstruct a suitable URL to use if it doesn't make sense to + set the token in the original url passed. + + :param repo_url: Url to repository + :param username: Username to use when cloning, set to '' if you wish + to do authenticated clones using a token as the password without + a user. + :param password: Password to use when cloning + :param directory: target directory to clone to + """ + + self.username = username + self.password = password + self.repo_url = repo_url + self.directory = directory + + def _setUp(self): + if self.directory is None: + self.directory = self.useFixture(fixtures.TempDir()).path + + project = self.repo_url.rstrip('/').split('/')[-1] + if project.endswith('.git'): + project = project[:-4] + + clone_dir = os.path.join(self.directory, project) + if os.path.exists(clone_dir): + shutil.rmtree(clone_dir) + + if self.username is not None: + url_parts = list(parse.urlparse(self.repo_url)) + auth = ":".join(filter(None, (self.username, self.password))) + netloc = "@".join((auth, url_parts[1])) + url_parts[1] = netloc + clone_url = parse.urlunparse(url_parts) + else: + clone_url = self.repo_url + + self.repo = git.Repo.clone_from(url=clone_url, to_path=clone_dir)