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 lockfiles iteration. Including version-only lockfiles. #7243

Merged
merged 124 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
e080737
try to reproduce error in lockfile
jgsogo Jun 3, 2020
223829f
iterate build_order
jgsogo Jun 3, 2020
19f3aa9
package in requires and build_requires
jgsogo Jun 3, 2020
5c67cb1
rename test file
jgsogo Jun 4, 2020
46bc4f6
removing constraint multiple packages
memsharded Jun 10, 2020
38fc47c
minor improvements
memsharded Jun 10, 2020
5046689
first lock-recipe version working
memsharded Jun 11, 2020
6987db5
working
memsharded Jun 15, 2020
4bea6b4
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 15, 2020
444d15e
working
memsharded Jun 15, 2020
e7e7e48
working 75%, but revisions not managed
memsharded Jun 16, 2020
3f4414c
working
memsharded Jun 17, 2020
aeb1b47
working
memsharded Jun 18, 2020
a610c07
working...
memsharded Jun 19, 2020
6188a7a
allow no user/channel match in --build
memsharded Jun 19, 2020
88352a3
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 19, 2020
a782093
build order
memsharded Jun 21, 2020
3b2dad6
Merge branch 'feature/build_mode_match' into feature/lock_recipe
memsharded Jun 21, 2020
bd6c91c
working
memsharded Jun 21, 2020
7719122
working
memsharded Jun 21, 2020
2c3efe8
working
memsharded Jun 22, 2020
aa357c8
not working...
memsharded Jun 22, 2020
80889fc
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 23, 2020
28f7dcc
working
memsharded Jun 23, 2020
d2205fd
tests passing without revisions
memsharded Jun 23, 2020
f28ac74
working
memsharded Jun 23, 2020
b394f07
Merge branch 'develop' into feature/build_mode_match
memsharded Jun 23, 2020
e10133f
review and patterns for rrevs
memsharded Jun 23, 2020
6488079
new tests
memsharded Jun 23, 2020
f65f579
merged build modes
memsharded Jun 23, 2020
6ccf210
Merge branch 'develop' into feature/build_mode_match
memsharded Jun 23, 2020
46983b4
Merge branch 'feature/build_mode_match' into feature/lock_recipe
memsharded Jun 23, 2020
1279dc7
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 24, 2020
8a06895
some fixes
memsharded Jun 24, 2020
664ad69
more fixes
memsharded Jun 24, 2020
d9a8cfa
skip build-info
memsharded Jun 24, 2020
e93fa68
fix revision test msg
memsharded Jun 24, 2020
b0dbb93
removed global activation of revisions
memsharded Jun 24, 2020
42d6e40
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 24, 2020
0c0eb7f
Merge branch 'test/lockfile_brs' into feature/lock_recipe
memsharded Jun 24, 2020
acbef5c
multiple br test
memsharded Jun 24, 2020
1873a38
cli changes
memsharded Jun 25, 2020
e10fc6c
working
memsharded Jun 25, 2020
5c9611e
new cli syntax
memsharded Jun 25, 2020
0a91756
fixing tests
memsharded Jun 25, 2020
e6a98d7
partial lockfiles
memsharded Jun 26, 2020
1133dc7
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 30, 2020
1296853
Merge branch 'develop' into feature/lock_recipe
memsharded Jun 30, 2020
7aecdde
CI partial lock working
memsharded Jun 30, 2020
cd060b2
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 1, 2020
ba45ee1
make sure partial lockfiles are used completely and from its root
memsharded Jul 1, 2020
ff36400
version ranges and py_requires working
memsharded Jul 2, 2020
63c114f
partial CI with python_requires
memsharded Jul 2, 2020
839162e
merged develop
memsharded Jul 2, 2020
dec1872
comment
memsharded Jul 3, 2020
1bd7d90
tests passing
memsharded Jul 3, 2020
502a0ed
working
memsharded Jul 3, 2020
8197bba
working in build_requires
memsharded Jul 5, 2020
99832a3
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 7, 2020
5ddf935
CI for build-requires test
memsharded Jul 7, 2020
ce0c65d
recovering conan_build_info tests
memsharded Jul 7, 2020
9f08ae6
broken py27
memsharded Jul 7, 2020
2396efb
clean-modified, stricter locks
memsharded Jul 8, 2020
538ee0f
partial arranged
memsharded Jul 8, 2020
4ac8a7c
minor style fixes
memsharded Jul 8, 2020
08da1b0
compacting lockfile search for nodes
memsharded Jul 8, 2020
072acb6
remove unnecessary --build=missing
memsharded Jul 8, 2020
5552ef5
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 9, 2020
8b322b3
processing --update
memsharded Jul 9, 2020
8d8637d
testing the --update necessary for revisions non matching
memsharded Jul 9, 2020
052e249
make the lockfile-out compulsory
memsharded Jul 10, 2020
f7ac68e
fixed conan_build_info
memsharded Jul 10, 2020
aabf755
forcing --lockfile-out
memsharded Jul 10, 2020
84dc4f3
workspace change
memsharded Jul 10, 2020
8fbe43f
Update conans/client/command.py
memsharded Jul 15, 2020
362c76c
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 15, 2020
29acaf2
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 16, 2020
a223f1e
make lock_node.path relative
memsharded Jul 16, 2020
fb1abc3
Merge branch 'feature/lock_recipe' of github.com:memsharded/conan int…
memsharded Jul 16, 2020
e35bb23
new tests and fixes
memsharded Jul 17, 2020
b141508
remove hardcoded os.environ
memsharded Jul 17, 2020
31a187c
make lockfile-out required
memsharded Jul 17, 2020
5458fe0
fix test
memsharded Jul 17, 2020
40cd73c
fixing os.path.relpath in Win
memsharded Jul 17, 2020
af65667
more tests
memsharded Jul 17, 2020
d492f25
fix test
memsharded Jul 17, 2020
8050b80
fix test
memsharded Jul 17, 2020
a741662
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 19, 2020
71c7906
checking --lockfile-out requires --lockfile
memsharded Jul 19, 2020
521d73b
merged develop
memsharded Jul 20, 2020
e3aa65b
working
memsharded Jul 20, 2020
8827988
review
memsharded Jul 20, 2020
0c19985
rename get_consumer
memsharded Jul 20, 2020
4c0b9f6
a partial lock can match more than 1 require
memsharded Jul 21, 2020
b1b4ec8
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 21, 2020
a1ad4b0
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 21, 2020
d869c3a
solve conflicts
memsharded Jul 21, 2020
d2f0b9b
error msg
memsharded Jul 21, 2020
a1c245f
merged
memsharded Jul 22, 2020
d03e359
working
memsharded Jul 22, 2020
f5d6e2a
check that profile is not passed when using lockfiles
memsharded Jul 22, 2020
69259fc
Merge branch 'feature/lock_recipe' into feature/lock_recipe2
memsharded Jul 22, 2020
757f163
working
memsharded Jul 22, 2020
d5c98d8
working
memsharded Jul 22, 2020
dab7fd1
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 22, 2020
106352b
conflicts solved
memsharded Jul 22, 2020
526786d
recover profile_build from lockfile
memsharded Jul 22, 2020
49c3acb
Merge branch 'feature/lock_recipe' into feature/lock_recipe2
memsharded Jul 22, 2020
a031588
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 23, 2020
8c8ec02
Merge branch 'feature/lock_recipe' into feature/lock_recipe2
memsharded Jul 23, 2020
79d0851
add new test for --update
memsharded Jul 23, 2020
ed88e21
Merge branch 'feature/lock_recipe' into feature/lock_recipe2
memsharded Jul 24, 2020
c29c44a
make sure modified is propagated
memsharded Jul 24, 2020
2d57857
no revisions working
memsharded Jul 24, 2020
9e7fde0
with revisions
memsharded Jul 24, 2020
ad7b69a
format
memsharded Jul 24, 2020
afc7f56
changed build-order order of output
memsharded Jul 26, 2020
b6485e9
Merge branch 'develop' into feature/lock_recipe
memsharded Jul 27, 2020
d3090cc
update cmd line
memsharded Jul 27, 2020
3a522e9
review
memsharded Jul 28, 2020
412f09c
Update conans/client/command.py
memsharded Jul 28, 2020
b7850f3
Update conans/client/command.py
memsharded Jul 28, 2020
4500d5a
Update conans/client/command.py
memsharded Jul 28, 2020
fb82897
forbidding version ranges when using lockfiles, in command line
memsharded Jul 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
101 changes: 57 additions & 44 deletions conans/build_info/build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from conans.errors import AuthenticationException, RequestErrorException, ConanException
from conans.model.graph_lock import LOCKFILE_VERSION
from conans.model.ref import ConanFileReference
from conans.model.version import Version
from conans.paths import ARTIFACTS_PROPERTIES_PUT_PREFIX
from conans.paths import get_conan_user_home
from conans.util.files import save
Expand Down Expand Up @@ -49,31 +48,27 @@ def __init__(self, output, build_info_file, lockfile, user=None, password=None,
self._output = output
self._conan_cache = ClientCache(os.path.join(get_conan_user_home(), ".conan"), output)

def parse_pref(self, pref):
ref = ConanFileReference.loads(pref, validate=False)
rrev = ref.revision.split("#")[0].split(":")[0]
pid = ref.revision.split("#")[0].split(":")[1]
prev = "" if len(ref.revision.split("#")) == 1 else ref.revision.split("#")[1]
def parse_ref(self, ref):
ref = ConanFileReference.loads(ref, validate=False)
rrev = ref.revision
return {
"name": ref.name,
"version": ref.version,
"user": ref.user,
"channel": ref.channel,
"rrev": rrev,
"pid": pid,
"prev": prev
}

def _get_reference(self, pref):
r = self.parse_pref(pref)
def _get_reference(self, ref):
r = self.parse_ref(ref)
if r.get("user") and r.get("channel"):
return "{name}/{version}@{user}/{channel}".format(**r)
else:
return "{name}/{version}".format(**r)

def _get_package_reference(self, pref):
r = self.parse_pref(pref)
return "{reference}:{pid}".format(reference=self._get_reference(pref), **r)
def _get_package_reference(self, ref, pid):
r = self.parse_ref(ref)
return "{reference}:{pid}".format(reference=self._get_reference(ref), pid=pid)

def _get_metadata_artifacts(self, metadata, request_path, use_id=False, name_format="{}",
package_id=None):
Expand Down Expand Up @@ -112,86 +107,104 @@ def _get_metadata_artifacts(self, metadata, request_path, use_id=False, name_for
"id": "conan_sources.tgz" if use_id else None}
return set([Artifact(k, **v) for k, v in ret.items()])

def _get_recipe_artifacts(self, pref, is_dependency):
r = self.parse_pref(pref)
def _get_recipe_artifacts(self, ref, is_dependency):
r = self.parse_ref(ref)
if r.get("user") and r.get("channel"):
ref = "{name}/{version}@{user}/{channel}#{rrev}".format(**r)
else:
ref = "{name}/{version}#{rrev}".format(**r)
reference = ConanFileReference.loads(ref)
package_layout = self._conan_cache.package_layout(reference)
metadata = package_layout.load_metadata()
name_format = "{} :: {{}}".format(self._get_reference(pref)) if is_dependency else "{}"
name_format = "{} :: {{}}".format(self._get_reference(ref)) if is_dependency else "{}"
if r.get("user") and r.get("channel"):
url = "{user}/{name}/{version}/{channel}/{rrev}/export".format(**r)
else:
url = "_/{name}/{version}/_/{rrev}/export".format(**r)

return self._get_metadata_artifacts(metadata, url, name_format=name_format, use_id=is_dependency)
return self._get_metadata_artifacts(metadata, url, name_format=name_format,
use_id=is_dependency)

def _get_package_artifacts(self, pref, is_dependency):
r = self.parse_pref(pref)
def _get_package_artifacts(self, ref, pid, prev, is_dependency):
r = self.parse_ref(ref)
if r.get("user") and r.get("channel"):
ref = "{name}/{version}@{user}/{channel}#{rrev}".format(**r)
else:
ref = "{name}/{version}#{rrev}".format(**r)
reference = ConanFileReference.loads(ref)
package_layout = self._conan_cache.package_layout(reference)
metadata = package_layout.load_metadata()
name_format = "{} :: {{}}".format(self._get_package_reference(pref)) if is_dependency else "{}"
if is_dependency:
name_format = "{} :: {{}}".format(self._get_package_reference(ref, pid))
else:
name_format = "{}"
if r.get("user") and r.get("channel"):
url = "{user}/{name}/{version}/{channel}/{rrev}/package/{pid}/{prev}".format(**r)
url = "{user}/{name}/{version}/{channel}/{rrev}/package/{pid}/{prev}"
else:
url = "_/{name}/{version}/_/{rrev}/package/{pid}/{prev}".format(**r)
arts = self._get_metadata_artifacts(metadata, url, name_format=name_format, use_id=is_dependency,
package_id=r["pid"])
url = "_/{name}/{version}/_/{rrev}/package/{pid}/{prev}"
url = url.format(pid=pid, prev=prev, **r)
arts = self._get_metadata_artifacts(metadata, url, name_format=name_format,
use_id=is_dependency, package_id=pid)
return arts

def process_lockfile(self):
modules = defaultdict(lambda: {"id": None, "artifacts": set(), "dependencies": set()})

def _gather_deps(node_uid, contents, func):
node_content = contents["graph_lock"]["nodes"].get(node_uid)
artifacts = func(node_content["pref"], is_dependency=True)
for id_node in node_content.get("requires", []):
artifacts.update(_gather_deps(id_node, contents, func))
for id_node in node_content.get("build_requires", []):
artifacts.update(_gather_deps(id_node, contents, func))
def _gather_transitive_recipes(nid, contents):
n = contents["graph_lock"]["nodes"][nid]
artifacts = self._get_recipe_artifacts(n["ref"], is_dependency=True)
for id_node in n.get("requires", []):
artifacts.update(_gather_transitive_recipes(id_node, contents))
for id_node in n.get("build_requires", []):
artifacts.update(_gather_transitive_recipes(id_node, contents))
return artifacts

def _gather_transitive_packages(nid, contents):
n = contents["graph_lock"]["nodes"][nid]
artifacts = self._get_package_artifacts(n["ref"], n["package_id"], n["prev"],
is_dependency=True)
for id_node in n.get("requires", []):
artifacts.update(_gather_transitive_packages(id_node, contents))
for id_node in n.get("build_requires", []):
artifacts.update(_gather_transitive_packages(id_node, contents))
return artifacts

with open(self._lockfile) as json_data:
data = json.load(json_data)

version = Version(data["version"])
if version < LOCKFILE_VERSION:
raise ConanException("This lockfile was created with a previous incompatible version "
version = data["version"]
if version != LOCKFILE_VERSION:
raise ConanException("This lockfile was created with an incompatible version "
"of Conan. Please update all your Conan clients")

# Gather modules, their artifacts and recursively all required artifacts
for _, node in data["graph_lock"]["nodes"].items():
pref = node["pref"]
ref = node["ref"]
pid = node.get("package_id")
prev = node.get("prev")
if node.get("modified"): # Work only on generated nodes
# Create module for the recipe reference
recipe_key = self._get_reference(pref)
recipe_key = self._get_reference(ref)
modules[recipe_key]["id"] = recipe_key
modules[recipe_key]["artifacts"].update(
self._get_recipe_artifacts(pref, is_dependency=False))
self._get_recipe_artifacts(ref, is_dependency=False))
# TODO: what about `python_requires`?
# TODO: can we associate any properties to the recipe? Profile/options may be different per lockfile
# TODO: can we associate any properties to the recipe? Profile/options may
# TODO: be different per lockfile

# Create module for the package_id
package_key = self._get_package_reference(pref)
package_key = self._get_package_reference(ref, pid)
modules[package_key]["id"] = package_key
modules[package_key]["artifacts"].update(
self._get_package_artifacts(pref, is_dependency=False))
self._get_package_artifacts(ref, pid, prev, is_dependency=False))

# Recurse requires
node_ids = node.get("requires", []) + node.get("build_requires", [])
for node_id in node_ids:
modules[recipe_key]["dependencies"].update(
_gather_deps(node_id, data, self._get_recipe_artifacts))
modules[package_key]["dependencies"].update(
_gather_deps(node_id, data, self._get_package_artifacts))
modules[recipe_key]["dependencies"].update(_gather_transitive_recipes(node_id,
data))
modules[package_key]["dependencies"].update(_gather_transitive_packages(node_id,
data))

# TODO: Is the recipe a 'dependency' of the package

Expand Down
50 changes: 42 additions & 8 deletions conans/client/cmd/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,48 @@ def create(app, ref, graph_info, remotes, update, build_modes,
test_conanfile_path = _get_test_conanfile_path(test_folder, conanfile_path)

if test_conanfile_path:
install_build_and_test(app, test_conanfile_path, ref, graph_info, remotes, update,
build_modes=build_modes,
manifest_folder=manifest_folder,
manifest_verify=manifest_verify,
manifest_interactive=manifest_interactive,
keep_build=keep_build,
test_build_folder=test_build_folder,
recorder=recorder)
if graph_info.graph_lock:
# If we have a lockfile, then we are first going to make sure the lockfile is used
# correctly to build the package in the cache, and only later will try to run
# test_package
out = app.out
out.info("Installing and building %s" % repr(ref))
deps_install(app=app,
ref_or_path=ref,
create_reference=ref,
install_folder=None, # Not output anything
manifest_folder=manifest_folder,
manifest_verify=manifest_verify,
manifest_interactive=manifest_interactive,
remotes=remotes,
graph_info=graph_info,
build_modes=build_modes,
update=update,
keep_build=keep_build,
recorder=recorder)
out.info("Executing test_package %s" % repr(ref))
try:
graph_info.graph_lock.relax()
# FIXME: It needs to clear the cache, otherwise it fails
app.binaries_analyzer._evaluated = {}
# FIXME: Forcing now not building test dependencies, binaries should be there
install_build_and_test(app, test_conanfile_path, ref, graph_info, remotes,
update, build_modes=None,
test_build_folder=test_build_folder, recorder=recorder)
except Exception as e:
raise ConanException("Something failed while testing '%s' test_package after "
"it was built using the lockfile. Please report this error: %s"
% (str(ref), str(e)))

else:
install_build_and_test(app, test_conanfile_path, ref, graph_info, remotes, update,
build_modes=build_modes,
manifest_folder=manifest_folder,
manifest_verify=manifest_verify,
manifest_interactive=manifest_interactive,
keep_build=keep_build,
test_build_folder=test_build_folder,
recorder=recorder)
else:
deps_install(app=app,
ref_or_path=ref,
Expand Down
2 changes: 1 addition & 1 deletion conans/client/cmd/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,

# If we receive lock information, python_requires could have been locked
if graph_lock:
node_id = graph_lock.get_node(ref)
node_id = graph_lock.get_consumer(ref)
python_requires = graph_lock.python_requires(node_id)
# TODO: check that the locked python_requires are different from the loaded ones
app.range_resolver.clear_output() # invalidate previous version range output
Expand Down
4 changes: 2 additions & 2 deletions conans/client/cmd/export_pkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ def _init_conanfile_infos():

packager.update_package_metadata(prev, layout, package_id, full_ref.revision)
pref = PackageReference(pref.ref, pref.id, prev)
if graph_info.graph_lock:
if pkg_node.graph_lock_node:
# after the package has been created we need to update the node PREV
pkg_node.prev = pref.revision
graph_info.graph_lock.update_check_graph(deps_graph, output)
pkg_node.graph_lock_node.prev = pref.revision
recorder.package_exported(pref)