def clone(repo_url, checkout=None, clone_to_dir='.', no_input=False): """ Clone a repo to the current directory. :param repo_url: Repo URL of unknown type. :param checkout: The branch, tag or commit ID to checkout after clone. :param clone_to_dir: The directory to clone to. Defaults to the current directory. :param no_input: Suppress all user prompts when calling via API. :returns: str with path to the new directory of the repository. """ # Ensure that clone_to_dir exists clone_to_dir = os.path.expanduser(clone_to_dir) make_sure_path_exists(clone_to_dir) # identify the repo_type vcs, repo_url = identify_repo(repo_url) # check that the appropriate VCS for the repo_type is installed if not vcs.is_installed(): msg = "'{0}' is not installed.".format(vcs.cmd) raise VCSNotInstalled(msg) repo_url = repo_url.rstrip('/') repo_name = os.path.split(repo_url)[1] repo_dir = vcs.get_repo_dir(repo_name, clone_to_dir) logger.debug('repo_dir is {0}'.format(repo_dir)) if os.path.isdir(repo_dir): clone = prompt_and_delete(repo_dir, no_input=no_input) else: clone = True if clone: try: vcs.clone(repo_url, checkout, clone_to_dir, repo_dir) except subprocess.CalledProcessError as clone_error: output = clone_error.output.decode('utf-8') # In case of error, print VCS output click.echo( 'Cloning of {} repository {} returned an error:\n{}'.format( vcs.cmd, repo_url, output)) if any(error in output.lower() for error in vcs.not_found_errors): raise RepositoryNotFound( 'The repository {} could not be found, ' 'have you made a typo?'.format(repo_url)) if any(error in output.lower() for error in vcs.branch_errors): raise RepositoryCloneFailed( 'The {} branch of repository {} could not found, ' 'have you made a typo?'.format(checkout, repo_url)) # Raise base subprocess error if SVN error can't be identified raise return repo_dir
def clone(repo_url, checkout=None, clone_to_dir='.', no_input=False): """Clone a repo to the current directory. :param repo_url: Repo URL of unknown type. :param checkout: The branch, tag or commit ID to checkout after clone. :param clone_to_dir: The directory to clone to. Defaults to the current directory. :param no_input: Suppress all user prompts when calling via API. :returns: str with path to the new directory of the repository. """ # Ensure that clone_to_dir exists clone_to_dir = os.path.expanduser(clone_to_dir) make_sure_path_exists(clone_to_dir) # identify the repo_type repo_type, repo_url = identify_repo(repo_url) # check that the appropriate VCS for the repo_type is installed if not is_vcs_installed(repo_type): msg = "'{0}' is not installed.".format(repo_type) raise VCSNotInstalled(msg) repo_url = repo_url.rstrip('/') repo_name = os.path.split(repo_url)[1] if repo_type == 'git': repo_name = repo_name.split(':')[-1].rsplit('.git')[0] repo_dir = os.path.normpath(os.path.join(clone_to_dir, repo_name)) elif repo_type == 'hg': repo_dir = os.path.normpath(os.path.join(clone_to_dir, repo_name)) logger.debug('repo_dir is {0}'.format(repo_dir)) if os.path.isdir(repo_dir): clone = prompt_and_delete(repo_dir, no_input=no_input) else: clone = True if clone: try: subprocess.check_output( # nosec [repo_type, 'clone', repo_url], cwd=clone_to_dir, stderr=subprocess.STDOUT, ) if checkout is not None: subprocess.check_output( # nosec [repo_type, 'checkout', checkout], cwd=repo_dir, stderr=subprocess.STDOUT, ) except subprocess.CalledProcessError as clone_error: output = clone_error.output.decode('utf-8') if 'not found' in output.lower(): raise RepositoryNotFound( 'The repository {} could not be found, ' 'have you made a typo?'.format(repo_url)) if any(error in output for error in BRANCH_ERRORS): raise RepositoryCloneFailed( 'The {} branch of repository {} could not found, ' 'have you made a typo?'.format(checkout, repo_url)) logger.error('git clone failed with error: %s', output) raise return repo_dir
cookie_dir = f'{fs.root_path}/.cookiecutters' os.mkdir(cookie_dir) DEFAULT_CONFIG['cookiecutters_dir'] = cookie_dir output_dir = f'{fs.root_path}/projects' os.mkdir(output_dir) with pytest.raises(ClickException): bootstrap_report_project(output_dir) assert mocked_cookiecutter.call_count == 1 assert mocked_dialogus.call_count == 1 @pytest.mark.parametrize( 'raise_exception', (subprocess.CalledProcessError(1, []), RepositoryCloneFailed())) def test_bootstrap_report_project_git_error(fs, mocker, raise_exception): mocker.patch( 'connect.cli.plugins.project.report.helpers.cookiecutter', return_value='project_dir', ) mocker.patch( 'connect.cli.plugins.project.report.helpers.dialogus', return_value={ 'project_name': 'foo', 'project_slug': 'foobar', 'package_name': 'bar', 'initial_report_name': 'first', 'initial_report_slug': 'initial_report_slug', 'initial_report_renderer': 'json', 'license': 'super one',
def clone(repo_url, checkout=None, clone_to_dir=".", no_input=False): """Clone a repo to the current directory. :param repo_url: Repo URL of unknown type. :param checkout: The branch, tag or commit ID to checkout after clone. :param clone_to_dir: The directory to clone to. Defaults to the current directory. :param no_input: Suppress all user prompts when calling via API. """ # Ensure that clone_to_dir exists clone_to_dir = os.path.expanduser(clone_to_dir) make_sure_path_exists(clone_to_dir) # identify the repo_type repo_type, repo_url = identify_repo(repo_url) # check that the appropriate VCS for the repo_type is installed if not is_vcs_installed(repo_type): msg = "'{0}' is not installed.".format(repo_type) raise VCSNotInstalled(msg) repo_url = repo_url.rstrip("/") tail = os.path.split(repo_url)[1] if repo_type == "git": repo_dir = os.path.normpath( os.path.join(clone_to_dir, tail.rsplit(".git")[0])) elif repo_type == "hg": repo_dir = os.path.normpath(os.path.join(clone_to_dir, tail)) logger.debug("repo_dir is {0}".format(repo_dir)) if os.path.isdir(repo_dir): clone = prompt_and_delete(repo_dir, no_input=no_input) else: clone = True if clone: try: subprocess.check_output( [repo_type, "clone", repo_url], cwd=clone_to_dir, stderr=subprocess.STDOUT, ) if checkout is not None: subprocess.check_output( [repo_type, "checkout", checkout], cwd=repo_dir, stderr=subprocess.STDOUT, ) except subprocess.CalledProcessError as clone_error: output = clone_error.output.decode("utf-8") if "not found" in output.lower(): raise RepositoryNotFound( "The repository {} could not be found, " "have you made a typo?".format(repo_url)) if any(error in output for error in BRANCH_ERRORS): raise RepositoryCloneFailed( "The {} branch of repository {} could not found, " "have you made a typo?".format(checkout, repo_url)) raise return repo_dir