def test_git_clone_fails_for_non_existent_branch(source_url: str): branch = uuid.uuid4().hex with pytest.raises(PoetrySimpleConsoleException) as e: Git.clone(url=source_url, branch=branch) assert f"Failed to clone {source_url} at '{branch}'" in str(e.value)
def test_git_clone_fails_for_non_existent_revision(source_url: str): revision = sha1(uuid.uuid4().bytes).hexdigest() with pytest.raises(PoetrySimpleConsoleException) as e: Git.clone(url=source_url, revision=revision) assert f"Failed to clone {source_url} at '{revision}'" in str(e.value)
def test_git_local_info(source_url: str, remote_refs: FetchPackResult, remote_default_ref: bytes) -> None: with Git.clone(url=source_url) as repo: info = Git.info(repo=repo) assert info.origin == source_url assert info.revision == remote_refs.refs[remote_default_ref].decode( "utf-8")
def _get_package_from_git( url: str, branch: str | None = None, tag: str | None = None, rev: str | None = None, subdirectory: str | None = None, source_root: Path | None = None, ) -> Package: source = Git.clone( url=url, source_root=source_root, branch=branch, tag=tag, revision=rev, clean=False, ) revision = Git.get_revision(source) path = Path(source.path) if subdirectory: path = path.joinpath(subdirectory) package = Provider.get_package_from_directory(path) package._source_type = "git" package._source_url = url package._source_reference = rev or tag or branch or "HEAD" package._source_resolved_reference = revision package._source_subdirectory = subdirectory return package
def load(cls, env): # type: (Env) -> InstalledRepository """ Load installed packages. For now, it uses the pip "freeze" command. """ repo = cls() seen = set() for entry in env.sys_path: for distribution in sorted( metadata.distributions(path=[entry]), key=lambda d: str(d._path), ): name = distribution.metadata["name"] version = distribution.metadata["version"] package = Package(name, version, version) package.description = distribution.metadata.get("summary", "") if package.name in seen: continue seen.add(package.name) repo.add_package(package) path = Path(str(distribution._path)) is_standard_package = True try: path.relative_to(env.site_packages) except ValueError: is_standard_package = False if is_standard_package: continue src_path = env.path / "src" # A VCS dependency should have been installed # in the src directory. If not, it's a path dependency try: path.relative_to(src_path) from poetry.vcs.git import Git git = Git() revision = git.rev_parse("HEAD", src_path / package.name).strip() url = git.remote_url(src_path / package.name) package.source_type = "git" package.source_url = url package.source_reference = revision except ValueError: package.source_type = "directory" package.source_url = str(path.parent) return repo
def _install_git(self, operation: Install | Update) -> int: from poetry.vcs.git import Git package = operation.package operation_message = self.get_operation_message(operation) message = ( f" <fg=blue;options=bold>•</> {operation_message}: <info>Cloning...</info>" ) self._write(operation, message) source = Git.clone( url=package.source_url, source_root=self._env.path / "src", revision=package.source_resolved_reference or package.source_reference, ) # Now we just need to install from the source directory original_url = package.source_url package._source_url = str(source.path) status_code = self._install_directory(operation) package._source_url = original_url return status_code
def test_git_clone_clones_submodules(source_url: str) -> None: with Git.clone(url=source_url) as repo: submodule_package_directory = (Path(repo.path) / "submodules" / "sample-namespace-packages") assert submodule_package_directory.exists() assert submodule_package_directory.joinpath("README.md").exists() assert len(list(submodule_package_directory.glob("*"))) > 1
def get_package_from_vcs( cls, vcs, url, reference=None, name=None ): # type: (str, str, Optional[str], Optional[str]) -> Package if vcs != "git": raise ValueError("Unsupported VCS dependency {}".format(vcs)) tmp_dir = Path( mkdtemp(prefix="pypoetry-git-{}".format( url.split("/")[-1].rstrip(".git")))) try: git = Git() git.clone(url, tmp_dir) if reference is not None: git.checkout(reference, tmp_dir) else: reference = "HEAD" revision = git.rev_parse(reference, tmp_dir).strip() package = cls.get_package_from_directory(tmp_dir, name=name) package.source_type = "git" package.source_url = url package.source_reference = revision except Exception: raise finally: safe_rmtree(str(tmp_dir)) return package
def assert_version(repo: Repo, expected_revision: str) -> None: version = PyProjectTOML(path=Path(repo.path).joinpath( "pyproject.toml")).poetry_config["version"] revision = Git.get_revision(repo=repo) assert revision == expected_revision assert revision in REVISION_TO_VERSION_MAP assert version == REVISION_TO_VERSION_MAP[revision]
def test_git_clone_default_branch_head( source_url: str, remote_refs: FetchPackResult, remote_default_ref: bytes, mocker: MockerFixture, ): spy = mocker.spy(Git, "_clone") spy_legacy = mocker.spy(Git, "_clone_legacy") with Git.clone(url=source_url) as repo: assert remote_refs.refs[remote_default_ref] == repo.head() spy_legacy.assert_not_called() spy.assert_called()
def test_username_password_parameter_is_not_passed_to_dulwich( mocker: MockerFixture, source_url: str, config: Config) -> None: from poetry.vcs.git import backend spy_clone = mocker.spy(Git, "_clone") spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path") with Git.clone(url=source_url, branch="0.1") as repo: assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"]) spy_clone.assert_called_once() spy_get_transport_and_path.assert_called_with(location=source_url, ) spy_get_transport_and_path.assert_called_once()
def test_system_git_fallback_on_http_401( mocker: MockerFixture, source_url: str, ) -> None: spy = mocker.spy(Git, "_clone_legacy") mocker.patch.object(Git, "_clone", side_effect=HTTPUnauthorized(None, None)) with Git.clone(url=source_url, branch="0.1") as repo: path = Path(repo.path) assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"]) spy.assert_called_with( url="https://github.com/python-poetry/test-fixture-vcs-repository.git", target=path, refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"), ) spy.assert_called_once()
def test_system_git_called_when_configured( mocker: MockerFixture, source_url: str, use_system_git_client: None) -> None: spy_legacy = mocker.spy(Git, "_clone_legacy") spy = mocker.spy(Git, "_clone") with Git.clone(url=source_url, branch="0.1") as repo: path = Path(repo.path) assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"]) spy.assert_not_called() spy_legacy.assert_called_once() spy_legacy.assert_called_with( url=source_url, target=path, refspec=GitRefSpec(branch="0.1", revision=None, tag=None, ref=b"HEAD"), )
def test_configured_repository_http_auth( mocker: MockerFixture, source_url: str, config: Config ) -> None: from poetry.vcs.git import backend spy_clone_legacy = mocker.spy(Git, "_clone_legacy") spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path") config.merge( { "repositories": {"git-repo": {"url": source_url}}, "http-basic": { "git-repo": { "username": GIT_USERNAME, "password": GIT_PASSWORD, } }, } ) dummy_git_config = ConfigFile() mocker.patch( "poetry.vcs.git.backend.Repo.get_config_stack", return_value=dummy_git_config, ) mocker.patch( "poetry.vcs.git.backend.get_default_authenticator", return_value=Authenticator(config=config), ) with Git.clone(url=source_url, branch="0.1") as repo: assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"]) spy_clone_legacy.assert_not_called() spy_get_transport_and_path.assert_called_with( location=source_url, config=dummy_git_config, username=GIT_USERNAME, password=GIT_PASSWORD, ) spy_get_transport_and_path.assert_called_once()
def install_git(self, package: Package) -> None: from poetry.core.packages.package import Package from poetry.vcs.git import Git source = Git.clone( url=package.source_url, source_root=self._env.path / "src", revision=package.source_resolved_reference or package.source_reference, ) # Now we just need to install from the source directory pkg = Package(package.name, package.version) pkg._source_type = "directory" pkg._source_url = str(source.path) pkg.develop = package.develop self.install_directory(pkg)
def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package] """ Search for the specifications that match the given VCS dependency. Basically, we clone the repository in a temporary directory and get the information we need by checking out the specified reference. """ if dependency.vcs != "git": raise ValueError("Unsupported VCS dependency {}".format( dependency.vcs)) tmp_dir = Path( mkdtemp(prefix="pypoetry-git-{}".format(dependency.name))) try: git = Git() git.clone(dependency.source, tmp_dir) git.checkout(dependency.reference, tmp_dir) revision = git.rev_parse(dependency.reference, tmp_dir).strip() if dependency.tag or dependency.rev: revision = dependency.reference directory_dependency = DirectoryDependency( dependency.name, tmp_dir, category=dependency.category, optional=dependency.is_optional(), ) for extra in dependency.extras: directory_dependency.extras.append(extra) package = self.search_for_directory(directory_dependency)[0] package.source_type = "git" package.source_url = dependency.source package.source_reference = revision except Exception: raise finally: safe_rmtree(str(tmp_dir)) return [package]
def __init__(self, project, version='0.1.0', readme_format='md', author=None): self._project = project self._package_name = module_name(project) self._version = version self._readme_format = readme_format self._dependencies = {} self._dev_dependencies = {} self._include = [] self._git = Git() git_config = self._git.config if not author: if (git_config.get('user.name') and git_config.get('user.email')): author = u'{} <{}>'.format(git_config['user.name'], git_config['user.email']) else: author = 'Your Name <*****@*****.**>' self._author = author
def solve(self, use_latest=None): # type: (...) -> List[Operation] with self._provider.progress(): start = time.time() packages, depths = self._solve(use_latest=use_latest) end = time.time() if len(self._branches) > 1: self._provider.debug( "Complete version solving took {:.3f} seconds for {} branches" .format(end - start, len(self._branches[1:]))) self._provider.debug("Resolved for branches: {}".format( ", ".join("({})".format(b) for b in self._branches[1:]))) operations = [] for package in packages: installed = False for pkg in self._installed.packages: if package.name == pkg.name: installed = True if pkg.source_type == "git" and package.source_type == "git": from poetry.vcs.git import Git # Trying to find the currently installed version pkg_source_url = Git.normalize_url(pkg.source_url) package_source_url = Git.normalize_url( package.source_url) for locked in self._locked.packages: locked_source_url = Git.normalize_url( locked.source_url) if (locked.name == pkg.name and locked.source_type == pkg.source_type and locked_source_url == pkg_source_url and locked.source_reference == pkg.source_reference): pkg = Package(pkg.name, locked.version) pkg.source_type = "git" pkg.source_url = locked.source_url pkg.source_reference = locked.source_reference break if pkg_source_url != package_source_url or ( pkg.source_reference != package.source_reference and not pkg.source_reference.startswith( package.source_reference)): operations.append(Update(pkg, package)) else: operations.append( Install(package).skip("Already installed")) elif package.version != pkg.version: # Checking version operations.append(Update(pkg, package)) elif package.source_type != pkg.source_type: operations.append(Update(pkg, package)) else: operations.append( Install(package).skip("Already installed")) break if not installed: operations.append(Install(package)) # Checking for removals for pkg in self._locked.packages: remove = True for package in packages: if pkg.name == package.name: remove = False break if remove: skip = True for installed in self._installed.packages: if installed.name == pkg.name: skip = False break op = Uninstall(pkg) if skip: op.skip("Not currently installed") operations.append(op) return sorted( operations, key=lambda o: ( o.job_type == "uninstall", # Packages to be uninstalled have no depth so we default to 0 # since it actually doesn't matter since removals are always on top. -depths[packages.index(o.package)] if o.job_type != "uninstall" else 0, o.package.name, o.package.version, ), )
def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package] """ Search for the specifications that match the given VCS dependency. Basically, we clone the repository in a temporary directory and get the information we need by checking out the specified reference. """ if dependency.vcs != "git": raise ValueError("Unsupported VCS dependency {}".format(dependency.vcs)) tmp_dir = Path(mkdtemp(prefix="pypoetry-git-{}".format(dependency.name))) try: git = Git() git.clone(dependency.source, tmp_dir) git.checkout(dependency.reference, tmp_dir) revision = git.rev_parse(dependency.reference, tmp_dir).strip() if dependency.tag or dependency.rev: revision = dependency.reference pyproject = TomlFile(tmp_dir / "pyproject.toml") pyproject_content = None has_poetry = False if pyproject.exists(): pyproject_content = pyproject.read() has_poetry = ( "tool" in pyproject_content and "poetry" in pyproject_content["tool"] ) if pyproject_content and has_poetry: # If a pyproject.toml file exists # We use it to get the information we need info = pyproject_content["tool"]["poetry"] name = info["name"] version = info["version"] package = Package(name, version, version) package.source_type = dependency.vcs package.source_url = dependency.source package.source_reference = dependency.reference for req_name, req_constraint in info["dependencies"].items(): if req_name == "python": package.python_versions = req_constraint continue package.add_dependency(req_name, req_constraint) else: # We need to use setup.py here # to figure the information we need # We need to place ourselves in the proper # folder for it to work venv = Venv.create(self._io) current_dir = os.getcwd() os.chdir(tmp_dir.as_posix()) try: venv.run("python", "setup.py", "egg_info") # Sometimes pathlib will fail on recursive # symbolic links, so we need to workaround it # and use the glob module instead. # Note that this does not happen with pathlib2 # so it's safe to use it for Python < 3.4. if PY35: egg_info = next( Path(p) for p in glob.glob( os.path.join(str(tmp_dir), "**", "*.egg-info"), recursive=True, ) ) else: egg_info = next(tmp_dir.glob("**/*.egg-info")) meta = pkginfo.UnpackedSDist(str(egg_info)) if meta.requires_dist: reqs = list(meta.requires_dist) else: reqs = [] requires = egg_info / "requires.txt" if requires.exists(): with requires.open() as f: reqs = parse_requires(f.read()) package = Package(meta.name, meta.version) for req in reqs: dep = dependency_from_pep_508(req) if dep.in_extras: for extra in dep.in_extras: if extra not in package.extras: package.extras[extra] = [] package.extras[extra].append(dep) package.requires.append(dep) except Exception: raise finally: os.chdir(current_dir) package.source_type = "git" package.source_url = dependency.source package.source_reference = revision except Exception: raise finally: shutil.rmtree(tmp_dir.as_posix()) if dependency.name != package.name: # For now, the dependency's name must match the actual package's name raise RuntimeError( "The dependency name for {} does not match the actual package's name: {}".format( dependency.name, package.name ) ) if dependency.extras: for extra in dependency.extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() return [package]
def _parse_requirements( self, requirements): # type: (List[str]) -> List[Dict[str, str]] from poetry.puzzle.provider import Provider result = [] try: cwd = self.poetry.file.parent except RuntimeError: cwd = Path.cwd() for requirement in requirements: requirement = requirement.strip() extras = [] extras_m = re.search(r"\[([\w\d,-_]+)\]$", requirement) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] requirement, _ = requirement.split("[") url_parsed = urlparse.urlparse(requirement) if url_parsed.scheme and url_parsed.netloc: # Url if url_parsed.scheme in ["git+https", "git+ssh"]: from poetry.vcs.git import Git from poetry.vcs.git import ParsedUrl parsed = ParsedUrl.parse(requirement) url = Git.normalize_url(requirement) pair = OrderedDict([("name", parsed.name), ("git", url.url)]) if parsed.rev: pair["rev"] = url.revision if extras: pair["extras"] = extras package = Provider.get_package_from_vcs( "git", url.url, reference=pair.get("rev")) pair["name"] = package.name result.append(pair) continue elif url_parsed.scheme in ["http", "https"]: package = Provider.get_package_from_url(requirement) pair = OrderedDict([("name", package.name), ("url", package.source_url)]) if extras: pair["extras"] = extras result.append(pair) continue elif (os.path.sep in requirement or "/" in requirement) and cwd.joinpath(requirement).exists(): path = cwd.joinpath(requirement) if path.is_file(): package = Provider.get_package_from_file(path.resolve()) else: package = Provider.get_package_from_directory(path) result.append( OrderedDict([ ("name", package.name), ("path", path.relative_to(cwd).as_posix()), ] + ([("extras", extras)] if extras else []))) continue pair = re.sub("^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirement) pair = pair.strip() require = OrderedDict() if " " in pair: name, version = pair.split(" ", 2) extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] name, _ = name.split("[") require["name"] = name if version != "latest": require["version"] = version else: m = re.match(r"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.strip()) if m: name, constraint = m.group(1), m.group(2) extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) if extras_m: extras = [ e.strip() for e in extras_m.group(1).split(",") ] name, _ = name.split("[") require["name"] = name require["version"] = constraint else: extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair) if extras_m: extras = [ e.strip() for e in extras_m.group(1).split(",") ] pair, _ = pair.split("[") require["name"] = pair if extras: require["extras"] = extras result.append(require) return result
def source_directory_name(source_url: str) -> str: return Git.get_name_from_source_url(url=source_url)
def search_for_vcs(self, dependency: VCSDependency) -> List[Package]: """ Search for the specifications that match the given VCS dependency. Basically, we clone the repository in a temporary directory and get the information we need by checking out the specified reference. """ if dependency.vcs != 'git': raise ValueError(f'Unsupported VCS dependency {dependency.vcs}') tmp_dir = Path(mkdtemp(prefix=f'pypoetry-git-{dependency.name}')) try: git = Git() git.clone(dependency.source, tmp_dir) git.checkout(dependency.reference, tmp_dir) revision = git.rev_parse(dependency.reference, tmp_dir).strip() if dependency.tag or dependency.rev: revision = dependency.reference poetry = TomlFile(tmp_dir / 'pyproject.toml') if poetry.exists(): # If a pyproject.toml file exists # We use it to get the information we need info = poetry.read() name = info['package']['name'] version = info['package']['version'] package = Package(name, version, version) for req_name, req_constraint in info['dependencies'].items(): package.add_dependency(req_name, req_constraint) else: # We need to use setup.py here # to figure the information we need # We need to place ourselves in the proper # folder for it to work current_dir = os.getcwd() os.chdir(tmp_dir.as_posix()) try: venv = Venv.create() output = venv.run('python', 'setup.py', '--name', '--version') output = output.split('\n') name = output[-3] version = output[-2] package = Package(name, version, version) # Figure out a way to get requirements except Exception: raise finally: os.chdir(current_dir) package.source_type = 'git' package.source_url = dependency.source package.source_reference = revision except Exception: raise finally: shutil.rmtree(tmp_dir.as_posix()) return [package]
def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package] """ Search for the specifications that match the given VCS dependency. Basically, we clone the repository in a temporary directory and get the information we need by checking out the specified reference. """ if dependency.vcs != 'git': raise ValueError('Unsupported VCS dependency {}'.format( dependency.vcs)) tmp_dir = Path( mkdtemp(prefix='pypoetry-git-{}'.format(dependency.name))) try: git = Git() git.clone(dependency.source, tmp_dir) git.checkout(dependency.reference, tmp_dir) revision = git.rev_parse(dependency.reference, tmp_dir).strip() if dependency.tag or dependency.rev: revision = dependency.reference pyproject = TomlFile(tmp_dir / 'pyproject.toml') pyproject_content = None has_poetry = False if pyproject.exists(): pyproject_content = pyproject.read(True) has_poetry = ('tool' in pyproject_content and 'poetry' in pyproject_content['tool']) if pyproject_content and has_poetry: # If a pyproject.toml file exists # We use it to get the information we need info = pyproject_content['tool']['poetry'] name = info['name'] version = info['version'] package = Package(name, version, version) package.source_type = dependency.vcs package.source_url = dependency.source package.source_reference = dependency.reference for req_name, req_constraint in info['dependencies'].items(): if req_name == 'python': package.python_versions = req_constraint continue package.add_dependency(req_name, req_constraint) else: # We need to use setup.py here # to figure the information we need # We need to place ourselves in the proper # folder for it to work venv = Venv.create(self._io) current_dir = os.getcwd() os.chdir(tmp_dir.as_posix()) try: venv.run('python', 'setup.py', 'egg_info') egg_info = list(tmp_dir.glob('*.egg-info'))[0] meta = pkginfo.UnpackedSDist(str(egg_info)) if meta.requires_dist: reqs = list(meta.requires_dist) else: reqs = [] requires = egg_info / 'requires.txt' if requires.exists(): with requires.open() as f: reqs = parse_requires(f.read()) package = Package(meta.name, meta.version) for req in reqs: package.requires.append(dependency_from_pep_508(req)) except Exception: raise finally: os.chdir(current_dir) package.source_type = 'git' package.source_url = dependency.source package.source_reference = revision except Exception: raise finally: shutil.rmtree(tmp_dir.as_posix()) return [package]
def test_git_clone_revision_is_tag(source_url: str, remote_refs: FetchPackResult, revision: str, expected_revision: str) -> None: with Git.clone(url=source_url, revision=revision) as repo: assert_version(repo, expected_revision)
def test_git_clone_revision_is_ref(source_url: str, remote_refs: FetchPackResult) -> None: with Git.clone(url=source_url, revision="refs/heads/0.1") as repo: assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])
def test_git_clone_multiple_times(source_url: str, remote_refs: FetchPackResult) -> None: for revision in REVISION_TO_VERSION_MAP: with Git.clone(url=source_url, revision=revision) as repo: assert_version(repo, revision)
def test_git_clone_tag(source_url: str, remote_refs: FetchPackResult, tag: str) -> None: with Git.clone(url=source_url, tag=tag) as repo: assert_version(repo, TAG_TO_REVISION_MAP[tag])
def test_normalize_url(url, normalized): assert normalized == Git.normalize_url(url)
def test_git_clone_when_branch_is_ref(source_url: str) -> None: with Git.clone(url=source_url, branch="refs/heads/0.1") as repo: assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])
def search_for_vcs(self, dependency): # type: (VCSDependency) -> List[Package] """ Search for the specifications that match the given VCS dependency. Basically, we clone the repository in a temporary directory and get the information we need by checking out the specified reference. """ if dependency.vcs != "git": raise ValueError("Unsupported VCS dependency {}".format( dependency.vcs)) tmp_dir = Path( mkdtemp(prefix="pypoetry-git-{}".format(dependency.name))) try: git = Git() git.clone(dependency.source, tmp_dir) git.checkout(dependency.reference, tmp_dir) revision = git.rev_parse(dependency.reference, tmp_dir).strip() if dependency.tag or dependency.rev: revision = dependency.reference pyproject = TomlFile(tmp_dir / "pyproject.toml") pyproject_content = None has_poetry = False if pyproject.exists(): pyproject_content = pyproject.read() has_poetry = ("tool" in pyproject_content and "poetry" in pyproject_content["tool"]) if pyproject_content and has_poetry: # If a pyproject.toml file exists # We use it to get the information we need info = pyproject_content["tool"]["poetry"] name = info["name"] version = info["version"] package = Package(name, version, version) package.source_type = dependency.vcs package.source_url = dependency.source package.source_reference = dependency.reference for req_name, req_constraint in info["dependencies"].items(): if req_name == "python": package.python_versions = req_constraint continue package.add_dependency(req_name, req_constraint) else: # We need to use setup.py here # to figure the information we need # We need to place ourselves in the proper # folder for it to work venv = Venv.create(self._io) current_dir = os.getcwd() os.chdir(tmp_dir.as_posix()) try: venv.run("python", "setup.py", "egg_info") # Sometimes pathlib will fail on recursive # symbolic links, so we need to workaround it # and use the glob module instead. # Note that this does not happen with pathlib2 # so it's safe to use it for Python < 3.4. if PY35: egg_info = next( Path(p) for p in glob.glob( os.path.join(str(tmp_dir), "**", "*.egg-info"), recursive=True, )) else: egg_info = next(tmp_dir.glob("**/*.egg-info")) meta = pkginfo.UnpackedSDist(str(egg_info)) if meta.requires_dist: reqs = list(meta.requires_dist) else: reqs = [] requires = egg_info / "requires.txt" if requires.exists(): with requires.open() as f: reqs = parse_requires(f.read()) package = Package(meta.name, meta.version) for req in reqs: dep = dependency_from_pep_508(req) if dep.in_extras: for extra in dep.in_extras: if extra not in package.extras: package.extras[extra] = [] package.extras[extra].append(dep) package.requires.append(dep) except Exception: raise finally: os.chdir(current_dir) package.source_type = "git" package.source_url = dependency.source package.source_reference = revision except Exception: raise finally: shutil.rmtree(tmp_dir.as_posix()) if dependency.name != package.name: # For now, the dependency's name must match the actual package's name raise RuntimeError( "The dependency name for {} does not match the actual package's name: {}" .format(dependency.name, package.name)) if dependency.extras: for extra in dependency.extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() return [package]
def test_git_clone_branch(source_url: str, remote_refs: FetchPackResult, branch: str) -> None: with Git.clone(url=source_url, branch=branch) as repo: assert_version(repo, BRANCH_TO_REVISION_MAP[branch])