Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New local-recipes-index feature #13930

Merged
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c38521f
proposal for adding a conan-center-index clone as remote
memsharded May 22, 2023
4cbd200
urls
memsharded May 22, 2023
2841ca5
Merge branch 'release/2.0' into feature/git_conancenter_remote
memsharded May 23, 2023
91fe970
Merge branch 'release/2.0' into feature/git_conancenter_remote
memsharded May 23, 2023
2bd20d8
wip
memsharded May 23, 2023
ece5ea1
Merge branch 'release/2.0' into feature/git_conancenter_remote
memsharded May 24, 2023
6d9f80b
raise on uploads
memsharded May 24, 2023
c0d3e65
Merge branch 'release/2.0' into feature/git_conancenter_remote
memsharded May 29, 2023
8ff0154
remove file:/// protocol, use explicit --type=local
memsharded May 29, 2023
bcc2576
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Dec 20, 2023
18e2a08
wip
memsharded Dec 20, 2023
95eae24
review
memsharded Dec 21, 2023
b27e49f
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Dec 21, 2023
43d4d8c
fix boost
memsharded Dec 21, 2023
aa8a0f4
wip
memsharded Dec 21, 2023
46e0f07
add hook
memsharded Dec 21, 2023
6731af9
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Dec 26, 2023
8c7e330
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Dec 27, 2023
421477a
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 12, 2024
ff269e5
review
memsharded Jan 12, 2024
1b1cc2a
fixes
memsharded Jan 12, 2024
73f0d9f
wip
memsharded Jan 12, 2024
2ba7404
wip
memsharded Jan 12, 2024
f4f03b3
Update conan/internal/api/new/oss_recipe.py
memsharded Jan 15, 2024
88433c7
Update conan/internal/api/new/oss_recipe.py
memsharded Jan 15, 2024
63d77b1
fix
memsharded Jan 15, 2024
0abdde7
strip-root
memsharded Jan 15, 2024
c555d7b
not warn remote-add
memsharded Jan 15, 2024
c1c4b53
test_package in template and remove clone in conan remote remove
memsharded Jan 15, 2024
d8048d0
fix export patches
memsharded Jan 15, 2024
70943cc
cover patches export too
memsharded Jan 15, 2024
3bfd99e
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 15, 2024
e81694f
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 16, 2024
5889246
fix remove
memsharded Jan 16, 2024
90baa0a
refactor add/remove remote
memsharded Jan 16, 2024
09ba83c
fix
memsharded Jan 16, 2024
c8f8323
removed git type
memsharded Jan 16, 2024
3e3ff70
unused imports
memsharded Jan 16, 2024
b58ae63
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 17, 2024
bafcd97
review and automatic deduction
memsharded Jan 17, 2024
56dcf7c
merged develop2
memsharded Jan 19, 2024
b2da389
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 22, 2024
74bf893
renaming all
memsharded Jan 22, 2024
f7f99b1
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Jan 23, 2024
a4854bb
wip
memsharded Jan 31, 2024
b7793e6
Merge branch 'develop2' into feature/git_conancenter_remote
memsharded Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion conan/api/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@
from conans.util.files import load
from conans.model.version_range import VersionRange

LOCAL_RECIPES_INDEX = "local-recipes-index"


class Remote:

def __init__(self, name, url, verify_ssl=True, disabled=False, allowed_packages=None):
def __init__(self, name, url, verify_ssl=True, disabled=False, allowed_packages=None,
remote_type=None):
self.name = name # Read only, is the key
self.url = url
self.verify_ssl = verify_ssl
self.disabled = disabled
self.allowed_packages = allowed_packages
self.remote_type = remote_type

def __eq__(self, other):
if other is None:
Expand All @@ -29,6 +33,9 @@ def __str__(self):
allowed_msg = ""
if self.allowed_packages:
allowed_msg = ", Allowed packages: {}".format(", ".join(self.allowed_packages))
if self.remote_type == LOCAL_RECIPES_INDEX:
return "{}: {} [{}, Enabled: {}{}]".format(self.name, self.url, LOCAL_RECIPES_INDEX,
not self.disabled, allowed_msg)
return "{}: {} [Verify SSL: {}, Enabled: {}{}]".format(self.name, self.url, self.verify_ssl,
not self.disabled, allowed_msg)

Expand Down
7 changes: 5 additions & 2 deletions conan/api/subapi/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class NewAPI:
def __init__(self, conan_api):
self.conan_api = conan_api

def get_builtin_template(self, template_name):
@staticmethod
def get_builtin_template(template_name):
from conan.internal.api.new.basic import basic_file
from conan.internal.api.new.alias_new import alias_file
from conan.internal.api.new.cmake_exe import cmake_exe_files
Expand All @@ -27,6 +28,7 @@ def get_builtin_template(self, template_name):
from conan.internal.api.new.bazel_exe import bazel_exe_files
from conan.internal.api.new.autotools_lib import autotools_lib_files
from conan.internal.api.new.autoools_exe import autotools_exe_files
from conan.internal.api.new.local_recipes_index import local_recipes_index_files
new_templates = {"basic": basic_file,
"cmake_lib": cmake_lib_files,
"cmake_exe": cmake_exe_files,
Expand All @@ -38,7 +40,8 @@ def get_builtin_template(self, template_name):
"bazel_exe": bazel_exe_files,
"autotools_lib": autotools_lib_files,
"autotools_exe": autotools_exe_files,
"alias": alias_file}
"alias": alias_file,
"local_recipes_index": local_recipes_index_files}
memsharded marked this conversation as resolved.
Show resolved Hide resolved
template_files = new_templates.get(template_name)
return template_files

Expand Down
18 changes: 13 additions & 5 deletions conan/api/subapi/remotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import os
from urllib.parse import urlparse

from conan.api.model import Remote
from conan.api.model import Remote, LOCAL_RECIPES_INDEX
from conan.api.output import ConanOutput
from conan.internal.cache.home_paths import HomePaths
from conan.internal.conan_app import ConanApp

from conans.client.rest_client_local_recipe_index import add_local_recipes_index_remote, \
remove_local_recipes_index_remote
from conans.errors import ConanException
from conans.util.files import save, load

Expand Down Expand Up @@ -99,13 +100,16 @@ def add(self, remote: Remote, force=False, index=None):
"""
Add a new ``Remote`` object to the existing ones


:param remote: a ``Remote`` object to be added
:param force: do not fail if the remote already exist (but default it failes)
:param index: if not defined, the new remote will be last one. Pass an integer to insert
the remote in that position instead of the last one
"""
add_local_recipes_index_remote(self.conan_api, remote)
remotes = _load(self._remotes_file)
_validate_url(remote.url)
if remote.remote_type != LOCAL_RECIPES_INDEX:
_validate_url(remote.url)
current = {r.name: r for r in remotes}.get(remote.name)
if current: # same name remote existing!
if not force:
Expand Down Expand Up @@ -139,6 +143,7 @@ def remove(self, pattern):
_save(self._remotes_file, remotes)
app = ConanApp(self.conan_api)
for remote in removed:
remove_local_recipes_index_remote(self.conan_api, remote)
app.cache.localdb.clean(remote_url=remote.url)
return removed

Expand All @@ -160,7 +165,8 @@ def update(self, remote_name: str, url=None, secure=None, disabled=None, index=N
except KeyError:
raise ConanException(f"Remote '{remote_name}' doesn't exist")
if url is not None:
_validate_url(url)
if remote.remote_type != LOCAL_RECIPES_INDEX:
_validate_url(url)
_check_urls(remotes, url, force=False, current=remote)
remote.url = url
if secure is not None:
Expand Down Expand Up @@ -255,7 +261,7 @@ def _load(remotes_file):
result = []
for r in data.get("remotes", []):
remote = Remote(r["name"], r["url"], r["verify_ssl"], r.get("disabled", False),
r.get("allowed_packages"))
r.get("allowed_packages"), r.get("remote_type"))
result.append(remote)
return result

Expand All @@ -268,6 +274,8 @@ def _save(remotes_file, remotes):
remote["disabled"] = True
if r.allowed_packages:
remote["allowed_packages"] = r.allowed_packages
if r.remote_type:
remote["remote_type"] = r.remote_type
remote_list.append(remote)
save(remotes_file, json.dumps({"remotes": remote_list}, indent=True))

Expand Down
20 changes: 15 additions & 5 deletions conan/cli/commands/remote.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import json
import os
from collections import OrderedDict

from conan.api.output import cli_out_write, Color
from conan.api.conan_api import ConanAPI
from conan.api.model import Remote
from conan.api.model import Remote, LOCAL_RECIPES_INDEX
from conan.api.output import cli_out_write, Color
from conan.cli import make_abs_path
from conan.cli.command import conan_command, conan_subcommand, OnceArgument
from conan.cli.commands.list import remote_color, error_color, recipe_color, \
reference_color
from conans.client.rest.remote_credentials import RemoteCredentials
from conan.errors import ConanException
from conans.client.rest.remote_credentials import RemoteCredentials


def formatter_remote_list_json(remotes):
Expand Down Expand Up @@ -74,10 +76,18 @@ def remote_add(conan_api, parser, subparser, *args):
subparser.add_argument("-f", "--force", action='store_true',
help="Force the definition of the remote even if duplicated")
subparser.add_argument("-ap", "--allowed-packages", action="append", default=None,
help="Add recipe reference pattern to list of allowed packages for this remote")
help="Add recipe reference pattern to list of allowed packages for "
"this remote")
subparser.add_argument("-t", "--type", choices=[LOCAL_RECIPES_INDEX],
help="Define the remote type")
memsharded marked this conversation as resolved.
Show resolved Hide resolved
subparser.set_defaults(secure=True)
args = parser.parse_args(*args)
r = Remote(args.name, args.url, args.secure, disabled=False, allowed_packages=args.allowed_packages)

url_folder = make_abs_path(args.url)
remote_type = args.type or (LOCAL_RECIPES_INDEX if os.path.isdir(url_folder) else None)
url = url_folder if remote_type == LOCAL_RECIPES_INDEX else args.url
r = Remote(args.name, url, args.secure, disabled=False, remote_type=remote_type,
allowed_packages=args.allowed_packages)
conan_api.remotes.add(r, force=args.force, index=args.index)


Expand Down
113 changes: 113 additions & 0 deletions conan/internal/api/new/local_recipes_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from conan.internal.api.new.cmake_lib import test_conanfile_v2, test_cmake_v2

config_yml = """\
versions:
"{{version}}":
folder: all
"""

conandata_yml = """\
sources:
"{{version}}":
url:
{% if url is defined -%}
- "{{url}}"
{% else -%}
- "http://put/here/the/url/to/release.1.2.3.zip"
{% endif %}
{% if sha256 is defined -%}
sha256: "{{sha256}}"
{%- else -%}
sha256: "Put here your tarball sha256"
{% endif -%}
"""


conanfile = """\
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
from conan.tools.files import apply_conandata_patches, export_conandata_patches, get


class {{package_name}}Recipe(ConanFile):
name = "{{name}}"
package_type = "library"

# Optional metadata
license = "<Put the package license here>"
author = "<Put your name here> <And your email here>"
url = "<Package recipe repository url here, for issues about the package>"
description = "<Description of {{ name }} package here>"
topics = ("<Put some tag here>", "<here>", "<and here>")

# Binary configuration
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}

def config_options(self):
if self.settings.os == "Windows":
self.options.rm_safe("fPIC")

def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")

def export_sources(self):
export_conandata_patches(self)

def source(self):
get(self, **self.conan_data["sources"][self.version], destination=self.source_folder,
strip_root=True)
apply_conandata_patches(self)

def layout(self):
cmake_layout(self, src_folder="src")

def generate(self):
deps = CMakeDeps(self)
deps.generate()
tc = CMakeToolchain(self)
tc.generate()

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
cmake = CMake(self)
cmake.install()

def package_info(self):
self.cpp_info.libs = ["{{name}}"]

{% if requires is defined -%}
def requirements(self):
{% for require in requires -%}
self.requires("{{ require }}")
{% endfor %}
{%- endif %}

{% if tool_requires is defined -%}
def build_requirements(self):
{% for require in tool_requires -%}
self.tool_requires("{{ require }}")
{% endfor %}
{%- endif %}
"""


test_main = """#include "{{name}}.h"

int main() {
{{package_name}}();
}
"""

local_recipes_index_files = {"recipes/{{name}}/config.yml": config_yml,
"recipes/{{name}}/all/conandata.yml": conandata_yml,
"recipes/{{name}}/all/conanfile.py": conanfile,
"recipes/{{name}}/all/test_package/conanfile.py": test_conanfile_v2,
"recipes/{{name}}/all/test_package/CMakeLists.txt": test_cmake_v2,
"recipes/{{name}}/all/test_package/src/example.cpp": test_main}
4 changes: 4 additions & 0 deletions conan/internal/cache/home_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class HomePaths:
def __init__(self, home_folder):
self._home = home_folder

@property
def local_recipes_index_path(self):
return os.path.join(self._home, ".local_recipes_index")

@property
def global_conf_path(self):
return os.path.join(self._home, "global.conf")
Expand Down
23 changes: 21 additions & 2 deletions conans/client/remote_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from requests.exceptions import ConnectionError

from conan.api.model import LOCAL_RECIPES_INDEX
from conans.client.rest_client_local_recipe_index import RestApiClientLocalRecipesIndex
from conan.api.model import Remote
from conan.api.output import ConanOutput
from conan.internal.cache.conan_reference_layout import METADATA
Expand All @@ -18,14 +20,17 @@
from conans.util.files import mkdir, tar_extract


class RemoteManager(object):
class RemoteManager:
""" Will handle the remotes to get recipes, packages etc """

def __init__(self, cache, auth_manager):
self._cache = cache
self._auth_manager = auth_manager
self._signer = PkgSignaturesPlugin(cache)

def _local_folder_remote(self, remote):
if remote.remote_type == LOCAL_RECIPES_INDEX:
return RestApiClientLocalRecipesIndex(remote, self._cache)

def check_credentials(self, remote):
self._call_remote(remote, "check_credentials")

Expand All @@ -46,6 +51,12 @@ def get_recipe(self, ref, remote, metadata=None):
layout = self._cache.get_or_create_ref_layout(ref)
layout.export_remove()

export_folder = layout.export()
local_folder_remote = self._local_folder_remote(remote)
if local_folder_remote is not None:
local_folder_remote.get_recipe(ref, export_folder)
return layout

download_export = layout.download_export()
try:
zipped_files = self._call_remote(remote, "get_recipe", ref, download_export, metadata,
Expand Down Expand Up @@ -100,6 +111,11 @@ def get_recipe_sources(self, ref, layout, remote):

download_folder = layout.download_export()
export_sources_folder = layout.export_sources()
local_folder_remote = self._local_folder_remote(remote)
if local_folder_remote is not None:
local_folder_remote.get_recipe_sources(ref, export_sources_folder)
return

zipped_files = self._call_remote(remote, "get_recipe_sources", ref, download_folder)
if not zipped_files:
mkdir(export_sources_folder) # create the folder even if no source files
Expand Down Expand Up @@ -234,6 +250,9 @@ def _call_remote(self, remote, method, *args, **kwargs):
enforce_disabled = kwargs.pop("enforce_disabled", True)
if remote.disabled and enforce_disabled:
raise ConanException("Remote '%s' is disabled" % remote.name)
local_folder_remote = self._local_folder_remote(remote)
if local_folder_remote is not None:
return local_folder_remote.call_method(method, *args, **kwargs)
try:
return self._auth_manager.call_rest_api_method(remote, method, *args, **kwargs)
except ConnectionError as exc:
Expand Down
Loading