Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
    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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
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
Exemplo n.º 9
0
    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