diff --git a/samcli/local/init/arbitrary_project.py b/samcli/local/init/arbitrary_project.py index 5f450a4afd..eaeb13aed0 100644 --- a/samcli/local/init/arbitrary_project.py +++ b/samcli/local/init/arbitrary_project.py @@ -8,6 +8,7 @@ from pathlib import Path from cookiecutter import repository +from cookiecutter import exceptions from cookiecutter import config from samcli.lib.utils import osutils @@ -17,6 +18,16 @@ LOG = logging.getLogger(__name__) +BAD_LOCATION_ERROR_MSG = ( + "Please verify your location. The following types of location are supported:" + "\n\n* Github: gh:user/repo (or) https://github.com/user/repo (or) git@github.com:user/repo.git" + "\n For Git repositories, you must use location of the root of the repository." + "\n\n* Mercurial: hg+ssh://hg@bitbucket.org/repo" + "\n\n* Http(s): https://example.com/code.zip" + "\n\n* Local Path: /path/to/code.zip" +) + + def generate_non_cookiecutter_project(location, output_dir): """ Uses Cookiecutter APIs to download a project at given ``location`` to the ``output_dir``. @@ -65,9 +76,13 @@ def generate_non_cookiecutter_project(location, output_dir): download_fn = functools.partial(repository.clone, repo_url=location, no_input=no_input) else: - raise ArbitraryProjectDownloadFailed(msg="Unsupported location {location}".format(location=location)) + raise ArbitraryProjectDownloadFailed(msg=BAD_LOCATION_ERROR_MSG) - return _download_and_copy(download_fn, output_dir) + try: + return _download_and_copy(download_fn, output_dir) + except exceptions.RepositoryNotFound: + # Download failed because the zip or the repository was not found + raise ArbitraryProjectDownloadFailed(msg=BAD_LOCATION_ERROR_MSG) def _download_and_copy(download_fn, output_dir): diff --git a/samcli/local/init/exceptions.py b/samcli/local/init/exceptions.py index 5fde33aaaf..43c4c5aab7 100644 --- a/samcli/local/init/exceptions.py +++ b/samcli/local/init/exceptions.py @@ -17,4 +17,4 @@ class GenerateProjectFailedError(InitErrorException): class ArbitraryProjectDownloadFailed(InitErrorException): - fmt = "An error occurred when downloading this project: {msg}" + fmt = "{msg}" diff --git a/tests/integration/init/test_init_command.py b/tests/integration/init/test_init_command.py index 527599a78e..641fbc58b1 100644 --- a/tests/integration/init/test_init_command.py +++ b/tests/integration/init/test_init_command.py @@ -189,6 +189,19 @@ def test_arbitrary_project(self, project_name): self.assertEqual(os.listdir(str(expected_output_folder)), ["test.txt"]) self.assertEqual(Path(expected_output_folder, "test.txt").read_text(), "hello world") + def test_zip_not_exists(self): + with tempfile.TemporaryDirectory() as temp: + args = [_get_command(), "init", "--location", str(Path("invalid", "zip", "path")), "-o", temp] + + process = Popen(args) + try: + process.communicate(timeout=TIMEOUT) + except TimeoutExpired: + process.kill() + raise + + self.assertEqual(process.returncode, 1) + def _get_command(): command = "sam" diff --git a/tests/unit/local/init/test_arbitrary_project.py b/tests/unit/local/init/test_arbitrary_project.py index b4472bd870..87b1b2a8a6 100644 --- a/tests/unit/local/init/test_arbitrary_project.py +++ b/tests/unit/local/init/test_arbitrary_project.py @@ -8,6 +8,7 @@ from pathlib import Path +from cookiecutter.exceptions import RepositoryNotFound from samcli.local.init.arbitrary_project import generate_non_cookiecutter_project, repository from samcli.local.init.exceptions import ArbitraryProjectDownloadFailed @@ -51,3 +52,12 @@ def test_must_fail_on_local_folders(self): with self.assertRaises(ArbitraryProjectDownloadFailed): generate_non_cookiecutter_project(location, self.output_dir) + + def test_must_fail_when_repo_not_found(self): + location = str(Path("my", "folder")) + + with patch.object(repository, "unzip") as unzip_mock: + unzip_mock.side_effect = RepositoryNotFound("repo") + + with self.assertRaises(ArbitraryProjectDownloadFailed): + generate_non_cookiecutter_project(location, self.output_dir)