def get_recipe(self, conan_reference): output = ScopedOutput(str(conan_reference), self._out) def _refresh(): export_path = self._client_cache.export(conan_reference) rmdir(export_path) # It might need to remove shortpath rm_conandir(self._client_cache.source(conan_reference)) current_remote, _ = self._get_remote(conan_reference) output.info("Retrieving from remote '%s'..." % current_remote.name) self._remote_manager.get_recipe(conan_reference, export_path, current_remote) if self._update: output.info("Updated!") else: output.info("Installed!") # check if it is in disk conanfile_path = self._client_cache.conanfile(conan_reference) if os.path.exists(conanfile_path): log_recipe_got_from_local_cache(conan_reference) if self._check_updates: ret = self.update_available(conan_reference) if ret != 0: # Found and not equal remote, ref_remote = self._get_remote(conan_reference) if ret == 1: if not self._update: if remote != ref_remote: # Forced new remote output.warn("There is a new conanfile in '%s' remote. " "Execute 'install -u -r %s' to update it." % (remote.name, remote.name)) else: output.warn("There is a new conanfile in '%s' remote. " "Execute 'install -u' to update it." % remote.name) output.warn("Refused to install!") else: if remote != ref_remote: # Delete packages, could be non coherent with new remote DiskRemover(self._client_cache).remove_packages(conan_reference) _refresh() elif ret == -1: if not self._update: output.info("Current conanfile is newer " "than %s's one" % remote.name) else: output.error("Current conanfile is newer than %s's one. " "Run 'conan remove %s' and run install again " "to replace it." % (remote.name, conan_reference)) else: self._retrieve_recipe(conan_reference, output) if self._manifest_manager: # Just make sure that the recipe sources are there to check self.get_recipe_sources(conan_reference) remote = self._registry.get_ref(conan_reference) self._manifest_manager.check_recipe(conan_reference, remote) return conanfile_path
def _get_recipe(self, reference, check_updates, update, remote_name): output = ScopedOutput(str(reference), self._out) # check if it is in disk conanfile_path = self._client_cache.conanfile(reference) # NOT in disk, must be retrieved from remotes if not os.path.exists(conanfile_path): ref_remote = self._download_recipe(reference, output, remote_name) status = RECIPE_DOWNLOADED return conanfile_path, status, ref_remote ref_remote = self._registry.get_ref(reference) check_updates = check_updates or update # Recipe exists in disk, but no need to check updates if not check_updates: status = RECIPE_INCACHE log_recipe_got_from_local_cache(reference) self._recorder.recipe_fetched_from_cache(reference) return conanfile_path, status, ref_remote named_remote = self._registry.remote( remote_name) if remote_name else None update_remote = named_remote or ref_remote if not update_remote: status = RECIPE_NO_REMOTE log_recipe_got_from_local_cache(reference) self._recorder.recipe_fetched_from_cache(reference) return conanfile_path, status, None try: # get_conan_manifest can fail, not in server upstream_manifest = self._remote_manager.get_conan_manifest( reference, update_remote) except NotFoundException: status = RECIPE_NOT_IN_REMOTE log_recipe_got_from_local_cache(reference) self._recorder.recipe_fetched_from_cache(reference) return conanfile_path, status, update_remote export = self._client_cache.export(reference) read_manifest = FileTreeManifest.load(export) if upstream_manifest != read_manifest: if upstream_manifest.time > read_manifest.time: if update: DiskRemover(self._client_cache).remove_recipe(reference) output.info("Retrieving from remote '%s'..." % update_remote.name) self._remote_manager.get_recipe(reference, update_remote) self._registry.set_ref(reference, update_remote) status = RECIPE_UPDATED else: status = RECIPE_UPDATEABLE else: status = RECIPE_NEWER else: status = RECIPE_INCACHE log_recipe_got_from_local_cache(reference) self._recorder.recipe_fetched_from_cache(reference) return conanfile_path, status, update_remote
def _get_recipe(self, conan_reference, check_updates, update): output = ScopedOutput(str(conan_reference), self._out) check_updates = check_updates or update # check if it is in disk conanfile_path = self._client_cache.conanfile(conan_reference) remote = None if os.path.exists(conanfile_path): if check_updates: ret = self.update_available(conan_reference) if ret != 0: # Found and not equal remote, ref_remote = self._get_remote(conan_reference) if ret == 1: if not update: if remote != ref_remote: # Forced new remote output.warn("There is a new conanfile in '%s' remote. " "Execute 'install -u -r %s' to update it." % (remote.name, remote.name)) else: output.warn("There is a new conanfile in '%s' remote. " "Execute 'install -u' to update it." % remote.name) output.warn("Refused to install!") else: DiskRemover(self._client_cache).remove(conan_reference) output.info("Retrieving from remote '%s'..." % remote.name) self._remote_manager.get_recipe(conan_reference, remote) self._registry.set_ref(conan_reference, remote) output.info("Updated!") elif ret == -1: if not update: output.info("Current conanfile is newer than %s's one" % remote.name) else: output.error("Current conanfile is newer than %s's one. " "Run 'conan remove %s' and run install again " "to replace it." % (remote.name, conan_reference)) log_recipe_got_from_local_cache(conan_reference) self._recorder.recipe_fetched_from_cache(conan_reference) else: remote = self._retrieve_recipe(conan_reference, output) if not remote: remote = self._registry.get_ref(conan_reference) return conanfile_path, remote
def cmd_export(app, conanfile_path, name, version, user, channel, keep_source, export=True, graph_lock=None): """ Export the recipe param conanfile_path: the original source directory of the user containing a conanfile.py """ loader, cache, hook_manager, output = app.loader, app.cache, app.hook_manager, app.out revisions_enabled = app.config.revisions_enabled conanfile = loader.load_export(conanfile_path, name, version, user, channel) # FIXME: Conan 2.0, deprecate CONAN_USER AND CONAN_CHANNEL and remove this try excepts # Take the default from the env vars if they exist to not break behavior try: user = conanfile.user except ConanException: user = None try: channel = conanfile.channel except ConanException: channel = None ref = ConanFileReference(conanfile.name, conanfile.version, user, channel) # If we receive lock information, python_requires could have been locked if graph_lock: node_id = graph_lock.get_node(ref) python_requires = graph_lock.python_requires(node_id) # TODO: check that the locked python_requires are different from the loaded ones # FIXME: private access, will be improved when api collaborators are improved loader._python_requires._range_resolver.output # invalidate previous version range output conanfile = loader.load_export(conanfile_path, conanfile.name, conanfile.version, conanfile.user, conanfile.channel, python_requires) check_casing_conflict(cache=cache, ref=ref) package_layout = cache.package_layout(ref, short_paths=conanfile.short_paths) if not export: metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision ref = ref.copy_with_rev(recipe_revision) if graph_lock: graph_lock.update_exported_ref(node_id, ref) return ref hook_manager.execute("pre_export", conanfile=conanfile, conanfile_path=conanfile_path, reference=package_layout.ref) logger.debug("EXPORT: %s" % conanfile_path) output.highlight("Exporting package recipe") conan_linter(conanfile_path, output) output = conanfile.output # Get previous digest try: previous_manifest = FileTreeManifest.load(package_layout.export()) except IOError: previous_manifest = None finally: _recreate_folders(package_layout.export(), package_layout.export_sources()) # Copy sources to target folders with package_layout.conanfile_write_lock(output=output): origin_folder = os.path.dirname(conanfile_path) export_recipe(conanfile, origin_folder, package_layout.export()) export_source(conanfile, origin_folder, package_layout.export_sources()) shutil.copy2(conanfile_path, package_layout.conanfile()) _capture_export_scm_data(conanfile, os.path.dirname(conanfile_path), package_layout.export(), output, scm_src_file=package_layout.scm_folder()) # Execute post-export hook before computing the digest hook_manager.execute("post_export", conanfile=conanfile, reference=package_layout.ref, conanfile_path=package_layout.conanfile()) # Compute the new digest manifest = FileTreeManifest.create(package_layout.export(), package_layout.export_sources()) 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' % package_layout.export()) else: output.info("The stored package has not changed") manifest = previous_manifest # Use the old one, keep old timestamp manifest.save(package_layout.export()) # 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) # FIXME: Conan 2.0 Clear the registry entry if the recipe has changed source_folder = package_layout.source() if os.path.exists(source_folder): try: if is_dirty(source_folder): output.info("Source folder is corrupted, forcing removal") rmdir(source_folder) elif modified_recipe and not keep_source: output.info( "Package recipe modified in export, forcing source folder removal" ) output.info("Use the --keep-source, -k option to skip it") rmdir(source_folder) except BaseException as e: output.error( "Unable to delete source folder. Will be marked as corrupted for deletion" ) output.warn(str(e)) set_dirty(source_folder) # When revisions enabled, remove the packages not matching the revision if revisions_enabled: packages = search_packages(package_layout, query=None) metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision to_remove = [ pid for pid in packages if metadata.packages.get(pid) and metadata.packages.get(pid).recipe_revision != recipe_revision ] if to_remove: output.info( "Removing the local binary packages from different recipe revisions" ) remover = DiskRemover() remover.remove_packages(package_layout, ids_filter=to_remove) ref = ref.copy_with_rev(revision) output.info("Exported revision: %s" % revision) if graph_lock: graph_lock.update_exported_ref(node_id, ref) return ref
def _get_recipe(self, ref, check_updates, update, remotes, recorder): output = ScopedOutput(str(ref), self._out) # check if it is in disk conanfile_path = self._cache.package_layout(ref).conanfile() # NOT in disk, must be retrieved from remotes if not os.path.exists(conanfile_path): remote, new_ref = self._download_recipe(ref, output, remotes, remotes.selected, recorder) status = RECIPE_DOWNLOADED return conanfile_path, status, remote, new_ref metadata = self._cache.package_layout(ref).load_metadata() cur_revision = metadata.recipe.revision cur_remote = metadata.recipe.remote cur_remote = remotes[cur_remote] if cur_remote else None selected_remote = remotes.selected or cur_remote check_updates = check_updates or update # Recipe exists in disk, but no need to check updates requested_different_revision = ( ref.revision is not None) and cur_revision != ref.revision if requested_different_revision and not check_updates: raise NotFoundException( "The recipe in the local cache doesn't match the specified " "revision. Use '--update' to check in the remote.") if not requested_different_revision: if not check_updates: status = RECIPE_INCACHE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, cur_remote, ref if not selected_remote: status = RECIPE_NO_REMOTE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, None, ref else: # Requested different revision and with --update remote, new_ref = self._download_recipe(ref, output, remotes, selected_remote, recorder) status = RECIPE_DOWNLOADED return conanfile_path, status, remote, new_ref try: # get_recipe_manifest can fail, not in server upstream_manifest, ref = self._remote_manager.get_recipe_manifest( ref, selected_remote) except NotFoundException: status = RECIPE_NOT_IN_REMOTE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, selected_remote, ref export = self._cache.package_layout(ref).export() read_manifest = FileTreeManifest.load(export) if upstream_manifest != read_manifest: if upstream_manifest.time > read_manifest.time: if update: DiskRemover().remove_recipe( self._cache.package_layout(ref), output=output) output.info("Retrieving from remote '%s'..." % selected_remote.name) self._download_recipe(ref, output, remotes, selected_remote, recorder) with self._cache.package_layout( ref).update_metadata() as metadata: metadata.recipe.remote = selected_remote.name status = RECIPE_UPDATED return conanfile_path, status, selected_remote, ref else: status = RECIPE_UPDATEABLE else: status = RECIPE_NEWER else: status = RECIPE_INCACHE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, selected_remote, ref
def cmd_export(conanfile_path, name, version, user, channel, keep_source, revisions_enabled, output, hook_manager, loader, cache, export=True): """ Export the recipe param conanfile_path: the original source directory of the user containing a conanfile.py """ conanfile = loader.load_export(conanfile_path, name, version, user, channel) ref = ConanFileReference(conanfile.name, conanfile.version, conanfile.user, conanfile.channel) check_casing_conflict(cache=cache, ref=ref) package_layout = cache.package_layout(ref, short_paths=conanfile.short_paths) if not export: metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision ref = ref.copy_with_rev(recipe_revision) return ref hook_manager.execute("pre_export", conanfile=conanfile, conanfile_path=conanfile_path, reference=package_layout.ref) logger.debug("EXPORT: %s" % conanfile_path) output.highlight("Exporting package recipe") conan_linter(conanfile_path, output) output = conanfile.output # Get previous digest try: previous_digest = FileTreeManifest.load(package_layout.export()) except IOError: previous_digest = None finally: _recreate_folders(package_layout.export(), package_layout.export_sources()) # Copy sources to target folders with package_layout.conanfile_write_lock(output=output): origin_folder = os.path.dirname(conanfile_path) export_recipe(conanfile, origin_folder, package_layout.export()) export_source(conanfile, origin_folder, package_layout.export_sources()) shutil.copy2(conanfile_path, package_layout.conanfile()) _capture_export_scm_data(conanfile, os.path.dirname(conanfile_path), package_layout.export(), output, scm_src_file=package_layout.scm_folder()) # Execute post-export hook before computing the digest hook_manager.execute("post_export", conanfile=conanfile, reference=package_layout.ref, conanfile_path=package_layout.conanfile()) # Compute the new digest digest = FileTreeManifest.create(package_layout.export(), package_layout.export_sources()) modified_recipe = not previous_digest or previous_digest != digest if modified_recipe: output.success('A new %s version was exported' % CONANFILE) output.info('Folder: %s' % package_layout.export()) else: output.info("The stored package has not changed") digest = previous_digest # Use the old one, keep old timestamp digest.save(package_layout.export()) # 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), digest=digest, revision_mode=conanfile.revision_mode) # FIXME: Conan 2.0 Clear the registry entry if the recipe has changed source_folder = package_layout.source() if os.path.exists(source_folder): try: if is_dirty(source_folder): output.info("Source folder is corrupted, forcing removal") rmdir(source_folder) elif modified_recipe and not keep_source: output.info( "Package recipe modified in export, forcing source folder removal" ) output.info("Use the --keep-source, -k option to skip it") rmdir(source_folder) except BaseException as e: output.error( "Unable to delete source folder. Will be marked as corrupted for deletion" ) output.warn(str(e)) set_dirty(source_folder) # When revisions enabled, remove the packages not matching the revision if revisions_enabled: packages = search_packages(package_layout, query=None) metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision to_remove = [ pid for pid in packages if metadata.packages.get(pid) and metadata.packages.get(pid).recipe_revision != recipe_revision ] if to_remove: output.info( "Removing the local binary packages from different recipe revisions" ) remover = DiskRemover() remover.remove_packages(package_layout, ids_filter=to_remove) ref = ref.copy_with_rev(revision) return ref
def _get_recipe(self, reference, check_updates, update, remote_name, recorder): output = ScopedOutput(str(reference), self._out) # check if it is in disk conanfile_path = self._client_cache.conanfile(reference) # NOT in disk, must be retrieved from remotes if not os.path.exists(conanfile_path): remote, new_ref = self._download_recipe(reference, output, remote_name, recorder) status = RECIPE_DOWNLOADED return conanfile_path, status, remote, new_ref metadata = self._client_cache.load_metadata(reference) cur_revision = metadata.recipe.revision remote = self._registry.refs.get(reference) named_remote = self._registry.remotes.get( remote_name) if remote_name else None update_remote = named_remote or remote # Check if we have a revision different from the requested one revisions_enabled = get_env("CONAN_CLIENT_REVISIONS_ENABLED", False) if revisions_enabled and reference.revision and cur_revision != reference.revision: output.info( "Different revision requested, removing current local recipe..." ) DiskRemover(self._client_cache).remove_recipe(reference) output.info("Retrieving from remote '%s'..." % update_remote.name) new_ref = self._remote_manager.get_recipe(reference, update_remote) self._registry.refs.set(new_ref, update_remote.name) status = RECIPE_UPDATED return conanfile_path, status, update_remote, new_ref check_updates = check_updates or update # Recipe exists in disk, but no need to check updates if not check_updates: status = RECIPE_INCACHE ref = reference.copy_with_rev(cur_revision) return conanfile_path, status, remote, ref if not update_remote: status = RECIPE_NO_REMOTE ref = reference.copy_with_rev(cur_revision) return conanfile_path, status, None, ref try: # get_conan_manifest can fail, not in server upstream_manifest = self._remote_manager.get_conan_manifest( reference, update_remote) except NotFoundException: status = RECIPE_NOT_IN_REMOTE ref = reference.copy_with_rev(cur_revision) return conanfile_path, status, update_remote, ref export = self._client_cache.export(reference) read_manifest = FileTreeManifest.load(export) if upstream_manifest != read_manifest: if upstream_manifest.time > read_manifest.time: if update: DiskRemover(self._client_cache).remove_recipe(reference) output.info("Retrieving from remote '%s'..." % update_remote.name) new_ref = self._remote_manager.get_recipe( reference, update_remote) self._registry.refs.set(new_ref, update_remote.name) status = RECIPE_UPDATED return conanfile_path, status, update_remote, new_ref else: status = RECIPE_UPDATEABLE else: status = RECIPE_NEWER else: status = RECIPE_INCACHE ref = reference.copy_with_rev(cur_revision) return conanfile_path, status, update_remote, ref
def cmd_export(app, conanfile_path, name, version, user, channel, keep_source, export=True, graph_lock=None, ignore_dirty=False): """ Export the recipe param conanfile_path: the original source directory of the user containing a conanfile.py """ loader, cache, hook_manager, output = app.loader, app.cache, app.hook_manager, app.out revisions_enabled = app.config.revisions_enabled scm_to_conandata = app.config.scm_to_conandata conanfile = loader.load_export(conanfile_path, name, version, user, channel) # FIXME: Conan 2.0, deprecate CONAN_USER AND CONAN_CHANNEL and remove this try excepts # Take the default from the env vars if they exist to not break behavior try: user = conanfile.user except ConanV2Exception: raise except ConanException: user = None try: channel = conanfile.channel except ConanV2Exception: raise except ConanException: channel = None ref = ConanFileReference(conanfile.name, conanfile.version, user, channel) # If we receive lock information, python_requires could have been locked if graph_lock: 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 conanfile = loader.load_export(conanfile_path, conanfile.name, conanfile.version, ref.user, ref.channel, python_requires) check_casing_conflict(cache=cache, ref=ref) package_layout = cache.package_layout(ref, short_paths=conanfile.short_paths) if not export: metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision ref = ref.copy_with_rev(recipe_revision) if graph_lock: graph_lock.update_exported_ref(node_id, ref) return ref _check_settings_for_warnings(conanfile, output) hook_manager.execute("pre_export", conanfile=conanfile, conanfile_path=conanfile_path, reference=package_layout.ref) logger.debug("EXPORT: %s" % conanfile_path) output.highlight("Exporting package recipe") output = conanfile.output # Copy sources to target folders with package_layout.conanfile_write_lock(output=output): # Get previous manifest try: previous_manifest = package_layout.recipe_manifest() except IOError: previous_manifest = None package_layout.export_remove() export_folder = package_layout.export() export_src_folder = package_layout.export_sources() mkdir(export_folder) mkdir(export_src_folder) origin_folder = os.path.dirname(conanfile_path) export_recipe(conanfile, origin_folder, export_folder) export_source(conanfile, origin_folder, export_src_folder) shutil.copy2(conanfile_path, package_layout.conanfile()) # Calculate the "auto" values and replace in conanfile.py scm_data, local_src_folder = _capture_scm_auto_fields( conanfile, os.path.dirname(conanfile_path), package_layout, output, ignore_dirty, scm_to_conandata) # Clear previous scm_folder modified_recipe = False scm_sources_folder = package_layout.scm_sources() if local_src_folder and not keep_source: # Copy the local scm folder to scm_sources in the cache mkdir(scm_sources_folder) _export_scm(scm_data, local_src_folder, scm_sources_folder, output) # https://github.com/conan-io/conan/issues/5195#issuecomment-551840597 # It will cause the source folder to be removed (needed because the recipe still has # the "auto" with uncommitted changes) modified_recipe = True # Execute post-export hook before computing the digest hook_manager.execute("post_export", conanfile=conanfile, reference=package_layout.ref, conanfile_path=package_layout.conanfile()) # 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) # 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) # FIXME: Conan 2.0 Clear the registry entry if the recipe has changed source_folder = package_layout.source() if os.path.exists(source_folder): try: if is_dirty(source_folder): output.info("Source folder is corrupted, forcing removal") rmdir(source_folder) clean_dirty(source_folder) elif modified_recipe and not keep_source: output.info( "Package recipe modified in export, forcing source folder removal" ) output.info("Use the --keep-source, -k option to skip it") rmdir(source_folder) except BaseException as e: output.error( "Unable to delete source folder. Will be marked as corrupted for deletion" ) output.warn(str(e)) set_dirty(source_folder) # When revisions enabled, remove the packages not matching the revision if revisions_enabled: packages = search_packages(package_layout, query=None) metadata = package_layout.load_metadata() recipe_revision = metadata.recipe.revision to_remove = [ pid for pid in packages if metadata.packages.get(pid) and metadata.packages.get(pid).recipe_revision != recipe_revision ] if to_remove: output.info( "Removing the local binary packages from different recipe revisions" ) remover = DiskRemover() remover.remove_packages(package_layout, ids_filter=to_remove) ref = ref.copy_with_rev(revision) output.info("Exported revision: %s" % revision) if graph_lock: graph_lock.update_exported_ref(node_id, ref) return ref
def _get_recipe(self, layout, ref, check_updates, update, remotes, recorder): output = ScopedOutput(str(ref), self._out) # check if it is in disk conanfile_path = layout.conanfile() # NOT in disk, must be retrieved from remotes if not os.path.exists(conanfile_path): remote, new_ref = self._download_recipe(layout, ref, output, remotes, remotes.selected, recorder) status = RECIPE_DOWNLOADED return conanfile_path, status, remote, new_ref metadata = layout.load_metadata() cur_revision = metadata.recipe.revision cur_remote = metadata.recipe.remote cur_remote = remotes[cur_remote] if cur_remote else None selected_remote = remotes.selected or cur_remote check_updates = check_updates or update requested_different_revision = ( ref.revision is not None) and cur_revision != ref.revision if requested_different_revision: if check_updates or self._cache.new_config[ "core:allow_explicit_revision_update"]: remote, new_ref = self._download_recipe( layout, ref, output, remotes, selected_remote, recorder) status = RECIPE_DOWNLOADED return conanfile_path, status, remote, new_ref else: raise NotFoundException( "The '%s' revision recipe in the local cache doesn't " "match the requested '%s'." " Use '--update' to check in the remote." % (cur_revision, repr(ref))) if not check_updates: status = RECIPE_INCACHE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, cur_remote, ref # Checking updates in the server if not selected_remote: status = RECIPE_NO_REMOTE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, None, ref try: # get_recipe_manifest can fail, not in server upstream_manifest, ref = self._remote_manager.get_recipe_manifest( ref, selected_remote) except NotFoundException: status = RECIPE_NOT_IN_REMOTE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, selected_remote, ref read_manifest = layout.recipe_manifest() if upstream_manifest != read_manifest: if upstream_manifest.time > read_manifest.time: if update: DiskRemover().remove_recipe(layout, output=output) output.info("Retrieving from remote '%s'..." % selected_remote.name) self._download_recipe(layout, ref, output, remotes, selected_remote, recorder) status = RECIPE_UPDATED return conanfile_path, status, selected_remote, ref else: status = RECIPE_UPDATEABLE else: status = RECIPE_NEWER else: status = RECIPE_INCACHE ref = ref.copy_with_rev(cur_revision) return conanfile_path, status, selected_remote, ref