Skip to content

Commit 4c1dfb8

Browse files
committed
intermediate state
1 parent 77f4ab3 commit 4c1dfb8

5 files changed

Lines changed: 71 additions & 6 deletions

File tree

src/cpp_dev/dependency/conan/provider.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
from pathlib import Path
1111

1212
from cpp_dev.common.types import CppStandard
13+
from cpp_dev.common.utils import create_tmp_dir
1314
from cpp_dev.common.version import SemanticVersion
1415
from cpp_dev.dependency.conan.command_wrapper import conan_list
1516
from cpp_dev.dependency.conan.setup import CONAN_REMOTE
1617
from cpp_dev.dependency.conan.types import ConanPackageReference
17-
from cpp_dev.dependency.conan.utils import conan_env
18+
from cpp_dev.dependency.conan.utils import conan_env, create_conanfile
1819
from cpp_dev.dependency.provider import Dependency, DependencyProvider
1920
from cpp_dev.dependency.specifier import DependencySpecifier
2021

@@ -34,7 +35,9 @@ def fetch_versions(self, repository: str, name: str) -> list[SemanticVersion]:
3435
return available_versions
3536

3637
def collect_dependency_hull(self, deps: list[DependencySpecifier]) -> list[Dependency]:
37-
# with conan_env(get_conan_home_dir()):
38+
with conan_env(self._conan_home_dir):
39+
with create_tmp_dir() as tmp_dir:
40+
conanfile_path = create_conanfile(tmp_dir, deps)
3841
# with create_tmp_dir() as tmp_dir:
3942
# conanfile_path = create_conanfile(tmp_dir, package_refs)
4043
...

src/cpp_dev/project/config.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ def update_dependencies(
8989
return updated_config
9090

9191

92+
def validate_dependencies(project_config: ProjectConfig) -> None:
93+
"""Check that a dependency identified by its name (without repository) exists only once.
94+
95+
Dependencies are in general identified by a name and their repository, e.g. official/cpd.
96+
It is, however, possible to add a dependency with the same name from different repositories, e.g.
97+
official/cpd and user/cpd. In this case, it is assumed that both dependencies are the same which
98+
is not supported in C++ because it might lead to undefined behavior.
99+
"""
100+
seen_names = set()
101+
for dep in project_config.dependencies + project_config.dev_dependencies + project_config.cpd_dependencies:
102+
if dep.name in seen_names:
103+
raise ValueError(f"Dependency '{dep.name}' is defined multiple times.")
104+
seen_names.add(dep.name)
105+
106+
92107
###############################################################################
93108
# Implementation ###
94109
###############################################################################

src/cpp_dev/project/core.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77
from textwrap import dedent
88

99
from cpp_dev.common.version import SemanticVersionWithOptionalParts
10-
from cpp_dev.dependency.provider import DependencyProvider
10+
from cpp_dev.dependency.provider import Dependency, DependencyProvider
1111
from cpp_dev.dependency.specifier import DependencySpecifier
1212
from cpp_dev.dependency.types import DependencySpecifierParts, VersionSpecBound, VersionSpecBoundOperand
1313

14-
from .config import DependencyType, ProjectConfig, create_project_config, load_project_config, update_dependencies
14+
from .config import (
15+
DependencyType,
16+
ProjectConfig,
17+
create_project_config,
18+
load_project_config,
19+
store_project_config,
20+
update_dependencies,
21+
)
1522
from .lockfile import create_initial_lock_file
1623
from .path_composition import compose_include_file, compose_source_file
1724

@@ -37,6 +44,9 @@ def add_package_dependency(self, deps: list[DependencySpecifier], dep_type: Depe
3744
refined_deps = _refine_package_dependencies(self._dependency_provider, deps)
3845
project_config = load_project_config(self.project_dir)
3946
update_dependencies(project_config, refined_deps, dep_type)
47+
dependency_hull = _obtain_dependency_hull(project_config, self._dependency_provider)
48+
49+
store_project_config(self.project_dir, project_config)
4050

4151

4252
def setup_project(
@@ -173,3 +183,10 @@ def _refine_package_dependencies(
173183
DependencySpecifier.from_parts(DependencySpecifierParts(repository, dep.name, version_spec))
174184
)
175185
return updated_deps
186+
187+
188+
def _obtain_dependency_hull(project_config: ProjectConfig, dep_provider: DependencyProvider) -> list[Dependency]:
189+
"""Obtain the dependency hull for the given project configuration."""
190+
return dep_provider.collect_dependency_hull(
191+
project_config.dependencies + project_config.dev_dependencies + project_config.cpd_dependencies
192+
)

src/tests/cpp_dev/dependency/conan/test_provider.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
from tests.cpp_dev.dependency.conan.utils.env import (ConanTestEnv,
1616
ConanTestPackage,
1717
create_conan_test_env)
18-
from tests.cpp_dev.dependency.conan.utils.server import (
19-
ConanServer, launch_conan_test_server)
2018

2119

2220
@pytest.fixture

src/tests/cpp_dev/project/test_config.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
create_project_config,
1717
load_project_config,
1818
update_dependencies,
19+
validate_dependencies,
1920
)
2021
from cpp_dev.project.path_composition import compose_project_config_file
2122

@@ -83,3 +84,34 @@ def test_update_dependencies(
8384
assert new_config.get_dependencies(unchanged_type) == project_setup.project_config.get_dependencies(
8485
unchanged_type
8586
)
87+
88+
89+
def test_validate_dependencies_valid() -> None:
90+
valid_config = ProjectConfig(
91+
name="test",
92+
version=SemanticVersion("0.1.0"),
93+
std="c++17",
94+
author="author",
95+
license="license",
96+
description="description",
97+
dependencies=[DependencySpecifier("dep1"), DependencySpecifier("dep2")],
98+
dev_dependencies=[DependencySpecifier("dev1")],
99+
cpd_dependencies=[DependencySpecifier("cpd1")],
100+
)
101+
validate_dependencies(valid_config) # Should not raise an exception
102+
103+
104+
def test_validate_dependencies_invalid() -> None:
105+
invalid_config = ProjectConfig(
106+
name="test",
107+
version=SemanticVersion("0.1.0"),
108+
std="c++17",
109+
author="author",
110+
license="license",
111+
description="description",
112+
dependencies=[DependencySpecifier("dep1")],
113+
dev_dependencies=[DependencySpecifier("dep1")], # Duplicate dependency
114+
cpd_dependencies=[DependencySpecifier("cpd1")],
115+
)
116+
with pytest.raises(ValueError, match="Dependency 'dep1' is defined multiple times."):
117+
validate_dependencies(invalid_config)

0 commit comments

Comments
 (0)