Conan Recipe Revision 和 Package Revision 计算流程
https://github.com/conan-io/conan/blob/1.59.0/conans/client/cmd/export.py#L169-L176
# Compute the revision for the recipe revision = _update_revision_in_metadata(package_layout=package_layout, revisions_enabled=revisions_enabled, output=output, path=os.path.dirname(conanfile_path), manifest=manifest, revision_mode=conanfile.revision_mode)
https://github.com/conan-io/conan/blob/1.59.0/conans/client/cmd/export.py#L402-L431
def _update_revision_in_metadata(package_layout, revisions_enabled, output, path, manifest, revision_mode): if revision_mode not in ["scm", "hash"]: raise ConanException("Revision mode should be one of 'hash' (default) or 'scm'") # Use the proper approach depending on 'revision_mode' if revision_mode == "hash": revision = manifest.summary_hash if revisions_enabled: output.info("Using the exported files summary hash as the recipe" " revision: {} ".format(revision)) else: try: rev_detected, repo_type, is_pristine = _detect_scm_revision(path) except Exception as exc: error_msg = "Cannot detect revision using '{}' mode from repository at " \ "'{}'".format(revision_mode, path) raise ConanException("{}: {}".format(error_msg, exc)) revision = rev_detected if revisions_enabled: output.info("Using %s commit as the recipe revision: %s" % (repo_type, revision)) if not is_pristine: output.warn("Repo status is not pristine: there might be modified files") with package_layout.update_metadata() as metadata: metadata.recipe.revision = revision return revision
https://github.com/conan-io/conan/blob/1.59.0/conans/model/manifest.py#L63-L67
@property def summary_hash(self): s = ["%s: %s" % (f, fmd5) for f, fmd5 in sorted(self.file_sums.items())] s.append("") return md5("\n".join(s))
https://github.com/conan-io/conan/blob/1.59.0/conans/model/manifest.py#L55-L58
def __init__(self, the_time, file_sums): """file_sums is a dict with filepaths and md5's: {filepath/to/file.txt: md5}""" self.time = the_time self.file_sums = file_sums
https://github.com/conan-io/conan/blob/1.59.0/conans/model/manifest.py#L119-L138
def create(cls, folder, exports_sources_folder=None): """ Walks a folder and create a FileTreeManifest for it, reading file contents from disk, and capturing current time """ files, _ = gather_files(folder) for f in (PACKAGE_TGZ_NAME, EXPORT_TGZ_NAME, CONAN_MANIFEST, EXPORT_SOURCES_TGZ_NAME): files.pop(f, None) file_dict = {} for name, filepath in files.items(): file_dict[name] = md5sum(filepath) if exports_sources_folder: export_files, _ = gather_files(exports_sources_folder) for name, filepath in export_files.items(): file_dict["export_source/%s" % name] = md5sum(filepath) date = timestamp_now() return cls(date, file_dict)
https://github.com/conan-io/conan/blob/1.59.0/conans/client/cmd/export.py#L158-L167
# Compute the new digest manifest = FileTreeManifest.create(export_folder, export_src_folder) modified_recipe |= not previous_manifest or previous_manifest != manifest if modified_recipe: output.success('A new %s version was exported' % CONANFILE) output.info('Folder: %s' % export_folder) else: output.info("The stored package has not changed") manifest = previous_manifest # Use the old one, keep old timestamp manifest.save(export_folder)
通过上面流程可以看出,Recipe Resivion 是对 export 和 export_sources 里每个文件进行 md5,再将这些 md5 值合起来再 md5 得到的值。
https://github.com/conan-io/conan/blob/1.59.0/conans/client/packager.py#L28-L36
manifest = FileTreeManifest.create(conanfile.package_folder) manifest.save(conanfile.package_folder) report_files_from_manifest(output, manifest) output.success("Package '%s' created" % package_id) prev = manifest.summary_hash output.info("Created package revision %s" % prev) return prev
通过上面流程可以看出,Package Resivion 是对 package_folder 里每个文件进行 md5,再将这些 md5 值合起来再 md5 得到的值。