Example #1
0
    async def validate_repository(self):
        """Validate."""
        await self.common_validate()

        # Custom step 1: Validate content.
        if self.data.content_in_root:
            self.content.path.remote = ""

        if self.content.path.remote == "custom_components":
            name = get_first_directory_in_directory(self.tree,
                                                    "custom_components")
            if name is None:
                raise HacsException(
                    f"Repostitory structure for {self.ref.replace('tags/','')} is not compliant"
                )
            self.content.path.remote = f"custom_components/{name}"

        try:
            await get_integration_manifest(self)
        except HacsException as exception:
            if self.hacs.action:
                raise HacsException(exception)
            self.logger.error(exception)

        # Handle potential errors
        if self.validate.errors:
            for error in self.validate.errors:
                if not self.hacs.system.status.startup:
                    self.logger.error(error)
        return self.validate.success
Example #2
0
    async def get_repository_manifest_content(self):
        """Get the content of the hacs.json file."""
        if not "hacs.json" in [x.filename for x in self.tree]:
            if self.hacs.action:
                raise HacsException(
                    "No hacs.json file in the root of the repository.")
            return
        if self.hacs.action:
            self.logger.info("Found hacs.json")

        self.ref = version_to_install(self)

        try:
            manifest = await self.repository_object.get_contents(
                "hacs.json", self.ref)
            self.repository_manifest = HacsManifest.from_dict(
                json.loads(manifest.content))
            self.data.update_data(json.loads(manifest.content))
            if self.hacs.action:
                self.logger.info(json.loads(manifest.content))
        except (AIOGitHubAPIException,
                Exception) as exception:  # Gotta Catch 'Em All
            if self.hacs.action:
                raise HacsException(
                    f"hacs.json file is not valid ({exception}).")
        if self.hacs.action:
            self.logger.info("hacs.json is valid")
Example #3
0
async def get_integration_manifest(repository):
    """Return the integration manifest."""
    manifest_path = f"{repository.content.path.remote}/manifest.json"
    if not manifest_path in [x.full_path for x in repository.tree]:
        raise HacsException(f"No file found '{manifest_path}'")
    try:
        manifest = await repository.repository_object.get_contents(
            manifest_path, repository.ref)
        manifest = json.loads(manifest.content)
    except Exception as exception:  # pylint: disable=broad-except
        raise HacsException(f"Could not read manifest.json [{exception}]")

    try:
        repository.manifest = manifest
        repository.information.authors = manifest["codeowners"]
        repository.domain = manifest["domain"]
        repository.information.name = manifest["name"]
        repository.information.homeassistant_version = manifest.get(
            "homeassistant")

        # Set local path
        repository.content.path.local = repository.localpath

    except KeyError as exception:
        raise HacsException(
            f"Missing expected key {exception} in 'manifest.json'")
async def register_repository(full_name,
                              category,
                              check=True,
                              ref=None,
                              action=False):
    """Register a repository."""
    hacs = get_hacs()
    hacs.action = action
    from custom_components.hacs.repositories import (
        RERPOSITORY_CLASSES, )  # To hanle import error

    if full_name in hacs.common.skip:
        if full_name != "hacs/integration":
            raise HacsExpectedException(f"Skipping {full_name}")

    if category not in RERPOSITORY_CLASSES:
        raise HacsException(f"{category} is not a valid repository category.")

    repository = RERPOSITORY_CLASSES[category](full_name)
    if check:
        try:
            await repository.registration(ref)
            if hacs.system.status.new:
                repository.status.new = False
            if repository.validate.errors:
                hacs.common.skip.append(repository.data.full_name)
                if not hacs.system.status.startup:
                    hacs.logger.error(f"Validation for {full_name} failed.")
                if hacs.action:
                    raise HacsException(f"Validation for {full_name} failed.")
                return repository.validate.errors
            if hacs.action:
                repository.logger.info("Validation complete")
            else:
                repository.logger.info("Registration complete")
        except AIOGitHubException as exception:
            hacs.common.skip.append(repository.data.full_name)
            raise HacsException(
                f"Validation for {full_name} failed with {exception}.")

    if hacs.hass is not None:
        hacs.hass.bus.async_fire(
            "hacs/repository",
            {
                "id": 1337,
                "action": "registration",
                "repository": repository.data.full_name,
                "repository_id": repository.information.uid,
            },
        )
    hacs.repositories.append(repository)
Example #5
0
    async def uninstall(self):
        """Run uninstall tasks."""
        self.logger.info("Uninstalling")
        if not await self.remove_local_directory():
            raise HacsException("Could not uninstall")
        self.data.installed = False
        if self.data.category == "integration":
            if self.data.config_flow:
                await self.reload_custom_components()
            else:
                self.pending_restart = True
        elif self.data.category == "theme":
            try:
                await self.hacs.hass.services.async_call(
                    "frontend", "reload_themes", {})
            except Exception:  # pylint: disable=broad-except
                pass
        if self.data.full_name in self.hacs.common.installed:
            self.hacs.common.installed.remove(self.data.full_name)

        await async_remove_store(self.hacs.hass, f"hacs/{self.data.id}.hacs")

        self.data.installed_version = None
        self.data.installed_commit = None
        self.hacs.hass.bus.async_fire(
            "hacs/repository",
            {
                "id": 1337,
                "action": "uninstall",
                "repository": self.data.full_name
            },
        )
Example #6
0
    async def common_registration(self):
        """Common registration steps of the repository."""
        # Attach repository
        if self.repository_object is None:
            self.repository_object = await get_repository(
                self.hacs.session, self.hacs.configuration.token,
                self.data.full_name)
            self.data.update_data(self.repository_object.attributes)

        # Set id
        self.information.uid = str(self.data.id)

        # Set topics
        self.data.topics = self.data.topics

        # Set stargazers_count
        self.data.stargazers_count = self.data.stargazers_count

        # Set description
        self.data.description = self.data.description

        if self.hacs.action:
            if self.data.description is None or len(
                    self.data.description) == 0:
                raise HacsException("Missing repository description")
Example #7
0
async def run_action_checks(repository):
    """Checks to run as an action."""
    issues = []
    if os.getenv("SKIP_BRANDS_CHECK") is None:
        brands = await repository.hacs.github.get_repo("home-assistant/brands")
        brandstree = await get_tree(brands, "master")
        if repository.integration_manifest["domain"] not in [
                x.filename for x in brandstree
        ]:
            issues.append(f"Integration not added to {BRANDS_REPO}")
        else:
            repository.logger.info(
                f"Integration is added to {BRANDS_REPO}, nice!")

    if (repository.integration_manifest.get("requirements") is not None
            and len(repository.integration_manifest.get("requirements")) != 0):
        wheels = await repository.hacs.github.get_repo(
            "home-assistant/wheels-custom-integrations")
        wheeltree = await get_tree(wheels, "master")
        wheelfiles = [x.filename for x in wheeltree]
        if (f"{repository.integration_manifest['domain']}.json" in wheelfiles
                or repository.integration_manifest["domain"] in wheelfiles):
            repository.logger.info(
                f"Integration is added to {WHEEL_REPO}, nice!")
        else:
            issues.append(f"Integration not added to {WHEEL_REPO}")

    if issues:
        for issue in issues:
            repository.logger.error(issue)
        raise HacsException(f"Found issues while validating the repository")
Example #8
0
async def get_tree(repository, ref):
    """Return the repository tree."""
    try:
        tree = await repository.get_tree(ref)
        return tree
    except AIOGitHubException as exception:
        raise HacsException(exception)
Example #9
0
async def get_releases(repository, prerelease=False, returnlimit=5):
    """Return the repository releases."""
    try:
        releases = await repository.get_releases(prerelease, returnlimit)
        return releases
    except AIOGitHubException as exception:
        raise HacsException(exception)
Example #10
0
async def load_hacs_repository():
    """Load HACS repositroy."""
    hacs = get_hacs()

    try:
        repository = hacs.get_by_name("hacs/integration")
        if repository is None:
            await register_repository("hacs/integration", "integration")
            repository = hacs.get_by_name("hacs/integration")
        if repository is None:
            raise HacsException("Unknown error")
        repository.data.installed = True
        repository.data.installed_version = VERSION
        repository.data.new = False
        hacs.repo = repository.repository_object
        hacs.data_repo = await get_repository(hacs.session,
                                              hacs.configuration.token,
                                              "hacs/default")
    except HacsException as exception:
        if "403" in f"{exception}":
            hacs.logger.critical(
                "GitHub API is ratelimited, or the token is wrong.")
        else:
            hacs.logger.critical(f"[{exception}] - Could not load HACS!")
        return False
    return True
Example #11
0
async def get_repository(session, token, repository_full_name):
    """Return a repository object or None."""
    try:
        github = AIOGitHub(token, session)
        repository = await github.get_repo(repository_full_name)
        return repository
    except AIOGitHubException as exception:
        raise HacsException(exception)
Example #12
0
async def run_action_checks(repository):
    """Checks to run as an action."""
    brands = await repository.hacs.github.get_repo("home-assistant/brands")
    brandstree = await get_tree(brands, "master")
    if repository.integration_manifest["domain"] not in [
            x.filename for x in brandstree
    ]:
        raise HacsException(f"Integration not added to {BRANDS_REPO}")
    repository.logger.info(f"Integration is added to {BRANDS_REPO}, nice!")

    if (repository.integration_manifest.get("requirements") is not None
            and len(repository.integration_manifest.get("requirements")) != 0):
        wheels = await repository.hacs.github.get_repo(
            "home-assistant/wheels-custom-integrations")
        wheeltree = await get_tree(wheels, "master")
        if f"{repository.integration_manifest['domain']}.json" not in [
                x.filename for x in wheeltree
        ]:
            raise HacsException(f"Integration not added to {WHEEL_REPO}")
        repository.logger.info(f"Integration is added to {WHEEL_REPO}, nice!")
Example #13
0
    def from_dict(configuration: dict, options: dict):
        """Set attributes from dicts."""
        if isinstance(options, bool) or isinstance(configuration.get("options"), bool):
            raise HacsException("Configuration is not valid.")

        if options is None:
            options = {}

        if not configuration:
            raise HacsException("Configuration is not valid.")

        config = Configuration()

        config.config = configuration
        config.options = options

        for conf_type in [configuration, options]:
            for key in conf_type:
                setattr(config, key, conf_type[key])

        return config
Example #14
0
    def from_dict(manifest: dict):
        """Set attributes from dicts."""
        if manifest is None:
            raise HacsException("Missing manifest data")

        manifest_data = HacsManifest()

        manifest_data.manifest = manifest

        for key in manifest:
            setattr(manifest_data, key, manifest[key])
        return manifest_data
Example #15
0
async def get_integration_manifest(repository):
    """Return the integration manifest."""
    if repository.data.content_in_root:
        manifest_path = "manifest.json"
    else:
        manifest_path = f"{repository.content.path.remote}/manifest.json"
    if not manifest_path in [x.full_path for x in repository.tree]:
        raise HacsException(f"No file found '{manifest_path}'")
    try:
        manifest = await repository.repository_object.get_contents(
            manifest_path, repository.ref)
        manifest = json.loads(manifest.content)
    except Exception as exception:  # pylint: disable=broad-except
        raise HacsException(f"Could not read manifest.json [{exception}]")

    try:
        repository.integration_manifest = manifest
        repository.data.authors = manifest["codeowners"]
        repository.data.domain = manifest["domain"]
        repository.data.manifest_name = manifest["name"]
        repository.data.config_flow = manifest.get("config_flow", False)

        if repository.hacs.action:
            if manifest.get("documentation") is None:
                raise HacsException("manifest.json is missing documentation")
            if manifest.get("homeassistant") is not None:
                raise HacsException(
                    "The homeassistant key in manifest.json is no longer valid"
                )
            # if manifest.get("issue_tracker") is None:
            #    raise HacsException("The 'issue_tracker' is missing in manifest.json")

        # Set local path
        repository.content.path.local = repository.localpath

    except KeyError as exception:
        raise HacsException(
            f"Missing expected key {exception} in '{manifest_path}'")
Example #16
0
async def download_content(repository):
    """Download the content of a directory."""
    queue = QueueManager()
    contents = gather_files_to_download(repository)
    repository.logger.debug(repository.data.filename)
    if not contents:
        raise HacsException("No content to download")

    for content in contents:
        if repository.data.content_in_root and repository.data.filename:
            if content.name != repository.data.filename:
                continue
        queue.add(dowload_repository_content(repository, content))
    await queue.execute()
Example #17
0
async def download_content(repository, validate, local_directory):
    """Download the content of a directory."""
    contents = gather_files_to_download(repository)
    try:
        if not contents:
            raise HacsException("No content to download")

        for content in contents:
            if repository.repository_manifest.content_in_root:
                if repository.repository_manifest.filename is not None:
                    if content.name != repository.repository_manifest.filename:
                        continue
            repository.logger.debug(f"Downloading {content.name}")

            filecontent = await async_download_file(repository.hass,
                                                    content.download_url)

            if filecontent is None:
                validate.errors.append(f"[{content.name}] was not downloaded.")
                continue

            # Save the content of the file.
            if repository.content.single or content.path is None:
                local_directory = repository.content.path.local

            else:
                _content_path = content.path
                if not repository.repository_manifest.content_in_root:
                    _content_path = _content_path.replace(
                        f"{repository.content.path.remote}", "")

                local_directory = f"{repository.content.path.local}/{_content_path}"
                local_directory = local_directory.split("/")
                del local_directory[-1]
                local_directory = "/".join(local_directory)

            # Check local directory
            pathlib.Path(local_directory).mkdir(parents=True, exist_ok=True)

            local_file_path = f"{local_directory}/{content.name}"
            result = await async_save_file(local_file_path, filecontent)
            if result:
                repository.logger.info(f"download of {content.name} complete")
                continue
            validate.errors.append(f"[{content.name}] was not downloaded.")

    except Exception as exception:  # pylint: disable=broad-except
        validate.errors.append(f"Download was not complete [{exception}]")
    return validate
Example #18
0
async def get_info_md_content(repository):
    """Get the content of info.md"""
    filename = info_file(repository)
    if not filename:
        return ""
    try:
        info = await repository.repository_object.get_contents(filename, repository.ref)
        if info is None:
            return ""
        info = info.content.replace("<svg", "<disabled").replace("</svg", "</disabled")
        return render_template(info, repository)
    except (AIOGitHubException, Exception):  # pylint: disable=broad-except
        if repository.hacs.action:
            raise HacsException("No info file found")
    return ""
Example #19
0
async def download_content(repository):
    """Download the content of a directory."""
    contents = gather_files_to_download(repository)
    repository.logger.debug(repository.data.filename)
    if not contents:
        raise HacsException("No content to download")

    for content in contents:
        if repository.data.content_in_root and repository.data.filename:
            if content.name != repository.data.filename:
                continue
        repository.logger.debug(f"Downloading {content.name}")

        filecontent = await async_download_file(content.download_url)

        if filecontent is None:
            repository.validate.errors.append(
                f"[{content.name}] was not downloaded.")
            continue

        # Save the content of the file.
        if repository.content.single or content.path is None:
            local_directory = repository.content.path.local

        else:
            _content_path = content.path
            if not repository.data.content_in_root:
                _content_path = _content_path.replace(
                    f"{repository.content.path.remote}", "")

            local_directory = f"{repository.content.path.local}/{_content_path}"
            local_directory = local_directory.split("/")
            del local_directory[-1]
            local_directory = "/".join(local_directory)

        # Check local directory
        pathlib.Path(local_directory).mkdir(parents=True, exist_ok=True)

        local_file_path = (f"{local_directory}/{content.name}").replace(
            "//", "/")

        result = await async_save_file(local_file_path, filecontent)
        if result:
            repository.logger.info(f"download of {content.name} complete")
            continue
        repository.validate.errors.append(
            f"[{content.name}] was not downloaded.")
Example #20
0
    async def validate_repository(self):
        """Validate."""
        # Run common validation steps.
        await self.common_validate()

        # Custom step 1: Validate content.
        find_file_name(self)

        if self.content.path.remote is None:
            raise HacsException(
                f"Repostitory structure for {self.ref.replace('tags/','')} is not compliant"
            )

        if self.content.path.remote == "release":
            self.content.single = True

        # Handle potential errors
        if self.validate.errors:
            for error in self.validate.errors:
                if not self.hacs.system.status.startup:
                    self.logger.error(error)
        return self.validate.success
Example #21
0
async def download_content(repository, validate, local_directory):
    """Download the content of a directory."""
    contents = []
    try:
        if repository.releases.releases and repository.information.category in [
                "plugin",
                "theme",
        ]:
            for release in repository.releases.objects:
                if repository.status.selected_tag == release.tag_name:
                    for asset in release.assets:
                        contents.append(asset)
        if not contents:
            if repository.content.single:
                for repository_object in repository.content.objects:
                    contents.append(repository_object)
            else:
                tree = await repository.repository_object.get_tree(
                    repository.ref)
                for path in tree:
                    if path.is_directory:
                        continue
                    if repository.content.path.remote in path.full_path:
                        path.name = path.filename
                        contents.append(path)

        if not contents:
            raise HacsException("No content to download")

        for content in contents:
            repository.logger.debug(f"Downloading {content.name}")

            filecontent = await async_download_file(repository.hass,
                                                    content.download_url)

            if filecontent is None:
                validate.errors.append(f"[{content.name}] was not downloaded.")
                continue

            # Save the content of the file.
            if repository.content.single or content.path is None:
                local_directory = repository.content.path.local

            else:
                _content_path = content.path
                if not repository.repository_manifest.content_in_root:
                    _content_path = _content_path.replace(
                        f"{repository.content.path.remote}", "")

                local_directory = f"{repository.content.path.local}/{_content_path}"
                local_directory = local_directory.split("/")
                del local_directory[-1]
                local_directory = "/".join(local_directory)

            # Check local directory
            pathlib.Path(local_directory).mkdir(parents=True, exist_ok=True)

            local_file_path = f"{local_directory}/{content.name}"
            result = await async_save_file(local_file_path, filecontent)
            if result:
                repository.logger.info(f"download of {content.name} complete")
                continue
            validate.errors.append(f"[{content.name}] was not downloaded.")

    except Exception as exception:  # pylint: disable=broad-except
        validate.errors.append(f"Download was not complete [{exception}]")
    return validate
Example #22
0
async def install_repository(repository):
    """Common installation steps of the repository."""
    persistent_directory = None
    await repository.update_repository()

    if not repository.can_install:
        raise HacsException(
            "The version of Home Assistant is not compatible with this version"
        )

    version = version_to_install(repository)
    if version == repository.information.default_branch:
        repository.ref = version
    else:
        repository.ref = f"tags/{version}"

    if repository.repository_manifest:
        if repository.repository_manifest.persistent_directory:
            if os.path.exists(
                    f"{repository.content.path.local}/{repository.repository_manifest.persistent_directory}"
            ):
                persistent_directory = Backup(
                    f"{repository.content.path.local}/{repository.repository_manifest.persistent_directory}",
                    tempfile.gettempdir() + "/hacs_persistent_directory/",
                )
                persistent_directory.create()

    if repository.status.installed and not repository.content.single:
        backup = Backup(repository.content.path.local)
        backup.create()

    if (repository.repository_manifest.zip_release
            and version != repository.information.default_branch):
        validate = await repository.download_zip(repository.validate)
    else:
        validate = await repository.download_content(
            repository.validate,
            repository.content.path.remote,
            repository.content.path.local,
            repository.ref,
        )

    if validate.errors:
        for error in validate.errors:
            repository.logger.error(error)
        if repository.status.installed and not repository.content.single:
            backup.restore()

    if repository.status.installed and not repository.content.single:
        backup.cleanup()

    if persistent_directory is not None:
        persistent_directory.restore()
        persistent_directory.cleanup()

    if validate.success:
        if repository.information.full_name not in repository.common.installed:
            if repository.information.full_name == "hacs/integration":
                repository.common.installed.append(
                    repository.information.full_name)
        repository.status.installed = True
        repository.versions.installed_commit = repository.versions.available_commit

        if version == repository.information.default_branch:
            repository.versions.installed = None
        else:
            repository.versions.installed = version

        await reload_after_install(repository)
        installation_complete(repository)
Example #23
0
async def common_update_data(repository):
    """Common update data."""
    hacs = get_hacs()
    try:
        repository_object = await get_repository(hacs.session,
                                                 hacs.configuration.token,
                                                 repository.data.full_name)
        repository.repository_object = repository_object
        repository.data.update_data(repository_object.attributes)
    except (AIOGitHubException, HacsException) as exception:
        if not hacs.system.status.startup:
            repository.logger.error(exception)
        repository.validate.errors.append("Repository does not exist.")
        raise HacsException(exception)

    # Make sure the repository is not archived.
    if repository.data.archived:
        repository.validate.errors.append("Repository is archived.")
        raise HacsException("Repository is archived.")

    # Make sure the repository is not in the blacklist.
    if is_removed(repository.data.full_name):
        repository.validate.errors.append("Repository is in the blacklist.")
        raise HacsException("Repository is in the blacklist.")

    # Get releases.
    try:
        releases = await get_releases(
            repository.repository_object,
            repository.status.show_beta,
            hacs.configuration.release_limit,
        )
        if releases:
            repository.releases.releases = True
            repository.releases.objects = releases
            repository.releases.published_tags = [
                x.tag_name for x in releases if not x.draft
            ]
            repository.versions.available = next(iter(releases)).tag_name
            for release in releases:
                if release.tag_name == repository.ref:
                    assets = release.assets
                    if assets:
                        downloads = next(
                            iter(assets)).attributes.get("download_count")
                        repository.releases.downloads = downloads

    except (AIOGitHubException, HacsException):
        repository.releases.releases = False

    repository.ref = version_to_install(repository)

    repository.logger.debug(
        f"Running checks against {repository.ref.replace('tags/', '')}")

    try:
        repository.tree = await get_tree(repository.repository_object,
                                         repository.ref)
        if not repository.tree:
            raise HacsException("No files in tree")
        repository.treefiles = []
        for treefile in repository.tree:
            repository.treefiles.append(treefile.full_path)
    except (AIOGitHubException, HacsException) as exception:
        if not hacs.system.status.startup:
            repository.logger.error(exception)
        raise HacsException(exception)
Example #24
0
async def install_repository(repository):
    """Common installation steps of the repository."""
    persistent_directory = None
    await repository.update_repository()
    if repository.content.path.local is None:
        raise HacsException("repository.content.path.local is None")
    repository.validate.errors = []

    if not repository.can_install:
        raise HacsException(
            "The version of Home Assistant is not compatible with this version"
        )

    version = version_to_install(repository)
    if version == repository.data.default_branch:
        repository.ref = version
    else:
        repository.ref = f"tags/{version}"

    if repository.data.installed and repository.data.category == "netdaemon":
        persistent_directory = BackupNetDaemon(repository)
        persistent_directory.create()

    elif repository.data.persistent_directory:
        if os.path.exists(
                f"{repository.content.path.local}/{repository.data.persistent_directory}"
        ):
            persistent_directory = Backup(
                f"{repository.content.path.local}/{repository.data.persistent_directory}",
                tempfile.gettempdir() + "/hacs_persistent_directory/",
            )
            persistent_directory.create()

    if repository.data.installed and not repository.content.single:
        backup = Backup(repository.content.path.local)
        backup.create()

    if repository.data.zip_release and version != repository.data.default_branch:
        await repository.download_zip(repository)
    else:
        await download_content(repository)

    if repository.validate.errors:
        for error in repository.validate.errors:
            repository.logger.error(error)
        if repository.data.installed and not repository.content.single:
            backup.restore()

    if repository.data.installed and not repository.content.single:
        backup.cleanup()

    if persistent_directory is not None:
        persistent_directory.restore()
        persistent_directory.cleanup()

    if repository.validate.success:
        if repository.data.full_name not in repository.hacs.common.installed:
            if repository.data.full_name == "hacs/integration":
                repository.hacs.common.installed.append(
                    repository.data.full_name)
        repository.data.installed = True
        repository.data.installed_commit = repository.data.last_commit

        if version == repository.data.default_branch:
            repository.data.installed_version = None
        else:
            repository.data.installed_version = version

        await reload_after_install(repository)
        installation_complete(repository)
Example #25
0
async def common_validate(repository):
    """Common validation steps of the repository."""
    hacs = get_hacs()
    repository.validate.errors = []

    # Make sure the repository exist.
    repository.logger.debug("Checking repository.")
    try:
        repository_object = await get_repository(
            hacs.session, hacs.configuration.token,
            repository.information.full_name)
        repository.repository_object = repository_object
        repository.data = repository.data.create_from_dict(
            repository_object.attributes)
    except (AIOGitHubException, HacsException) as exception:
        if not hacs.system.status.startup:
            repository.logger.error(exception)
        repository.validate.errors.append("Repository does not exist.")
        raise HacsException(exception)

    # Make sure the repository is not archived.
    if repository.data.archived:
        repository.validate.errors.append("Repository is archived.")
        raise HacsException("Repository is archived.")

    # Make sure the repository is not in the blacklist.
    if repository.data.full_name in hacs.common.blacklist:
        repository.validate.errors.append("Repository is in the blacklist.")
        raise HacsException("Repository is in the blacklist.")

    # Get releases.
    try:
        releases = await get_releases(
            repository.repository_object,
            repository.status.show_beta,
            hacs.configuration.release_limit,
        )
        if releases:
            repository.releases.releases = True
            repository.releases.published_tags = [x.tag_name for x in releases]
            repository.versions.available = next(iter(releases)).tag_name
            assets = next(iter(releases)).assets
            if assets:
                downloads = next(iter(assets)).attributes.get("download_count")
                repository.releases.downloads = downloads

    except (AIOGitHubException, HacsException):
        repository.releases.releases = False

    repository.ref = version_to_install(repository)

    repository.logger.debug(
        f"Running checks against {repository.ref.replace('tags/', '')}")

    try:
        repository.tree = await get_tree(repository.repository_object,
                                         repository.ref)
        if not repository.tree:
            raise HacsException("No files in tree")
        repository.treefiles = []
        for treefile in repository.tree:
            repository.treefiles.append(treefile.full_path)
    except (AIOGitHubException, HacsException) as exception:
        if not hacs.system.status.startup:
            repository.logger.error(exception)
        raise HacsException(exception)

    # Step 6: Get the content of hacs.json
    await repository.get_repository_manifest_content()

    # Set repository name
    repository.information.name = repository.information.full_name.split(
        "/")[1]