예제 #1
0
    def test_get_readme_url(self):
        github_urls = [
            "https://github.com/FreeCAD/FreeCAD",
        ]
        gitlab_urls = [
            "https://gitlab.com/freecad/FreeCAD",
            "https://framagit.org/freecad/FreeCAD",
            "https://salsa.debian.org/science-team/freecad",
            "https://unknown.location/and/path",
        ]

        # GitHub and Gitlab have two different schemes for file URLs: unrecognized URLs are
        # presumed to be local instances of a GitLab server. Note that in neither case does this
        # take into account the redirects that are used to actually fetch the data.

        for url in github_urls:
            branch = "branchname"
            expected_result = f"{url}/raw/{branch}/README.md"
            repo = Addon("Test Repo", url, Addon.Status.NOT_INSTALLED, branch)
            actual_result = get_readme_url(repo)
            self.assertEqual(actual_result, expected_result)

        for url in gitlab_urls:
            branch = "branchname"
            expected_result = f"{url}/-/raw/{branch}/README.md"
            repo = Addon("Test Repo", url, Addon.Status.NOT_INSTALLED, branch)
            actual_result = get_readme_url(repo)
            self.assertEqual(actual_result, expected_result)
예제 #2
0
    def run(self):

        self.progressbar_show.emit(True)
        self.info_label.emit(
            translate("AddonsInstaller", "Retrieving description..."))
        if len(self.repos[self.idx]) == 4:
            desc = self.repos[self.idx][3]
        else:
            u = None
            url = self.repos[self.idx][1]
            self.info_label.emit(
                translate("AddonsInstaller", "Retrieving info from") + " " +
                str(url))
            desc = ""
            regex = utils.get_readme_regex(url)
            if regex:
                # extract readme from html via regex
                readmeurl = utils.get_readme_html_url(url)
                if not readmeurl:
                    print("Debug: README not found for", url)
                u = utils.urlopen(readmeurl)
                if not u:
                    print("Debug: README not found at", readmeurl)
                u = utils.urlopen(readmeurl)
                if u:
                    p = u.read()
                    if sys.version_info.major >= 3 and isinstance(p, bytes):
                        p = p.decode("utf-8")
                    u.close()
                    readme = re.findall(regex,
                                        p,
                                        flags=re.MULTILINE | re.DOTALL)
                    if readme:
                        desc = readme[0]
                else:
                    print("Debug: README not found at", readmeurl)
            else:
                # convert raw markdown using lib
                readmeurl = utils.get_readme_url(url)
                if not readmeurl:
                    print("Debug: README not found for", url)
                u = utils.urlopen(readmeurl)
                if u:
                    p = u.read()
                    if sys.version_info.major >= 3 and isinstance(p, bytes):
                        p = p.decode("utf-8")
                    u.close()
                    desc = utils.fix_relative_links(
                        p,
                        readmeurl.rsplit("/README.md")[0])
                    if not NOMARKDOWN and have_markdown:
                        desc = markdown.markdown(desc,
                                                 extensions=["md_in_html"])
                    else:
                        message = """
<div style="width: 100%; text-align:center;background: #91bbe0;">
    <strong style="color: #FFFFFF;">
"""
                        message += translate("AddonsInstaller",
                                             "Raw markdown displayed")
                        message += "</strong><br/><br/>"
                        message += translate(
                            "AddonsInstaller",
                            "Python Markdown library is missing.")
                        message += "<br/></div><hr/><pre>" + desc + "</pre>"
                        desc = message
                else:
                    print("Debug: README not found at", readmeurl)
            if desc == "":
                # fall back to the description text
                u = utils.urlopen(url)
                if not u:
                    self.progressbar_show.emit(False)
                    self.stop = True
                    return
                p = u.read()
                if sys.version_info.major >= 3 and isinstance(p, bytes):
                    p = p.decode("utf-8")
                u.close()
                descregex = utils.get_desc_regex(url)
                if descregex:
                    desc = re.findall(descregex, p)
                    if desc:
                        desc = desc[0]
            if not desc:
                desc = "Unable to retrieve addon description"
            self.repos[self.idx].append(desc)
            self.addon_repos.emit(self.repos)
        # Addon is installed so lets check if it has an update
        if self.repos[self.idx][2] == 1:
            upd = False
            # checking for updates
            if not NOGIT and have_git:
                repo = self.repos[self.idx]
                clonedir = FreeCAD.getUserAppDataDir(
                ) + os.sep + "Mod" + os.sep + repo[0]
                if os.path.exists(clonedir):
                    if not os.path.exists(clonedir + os.sep + ".git"):
                        # Repair addon installed with raw download
                        bare_repo = git.Repo.clone_from(repo[1],
                                                        clonedir + os.sep +
                                                        ".git",
                                                        bare=True)
                        try:
                            with bare_repo.config_writer() as cw:
                                cw.set("core", "bare", False)
                        except AttributeError:
                            FreeCAD.Console.PrintWarning(
                                translate(
                                    "AddonsInstaller",
                                    "Outdated GitPython detected, "
                                    "consider upgrading with pip.") + "\n")
                            cw = bare_repo.config_writer()
                            cw.set("core", "bare", False)
                            del cw
                        repo = git.Repo(clonedir)
                        repo.head.reset("--hard")
                    gitrepo = git.Git(clonedir)
                    gitrepo.fetch()
                    if "git pull" in gitrepo.status():
                        upd = True
            # If there is an update pending, lets user know via the UI
            if upd:
                message = """
<div style="width: 100%;text-align: center;background: #75AFFD;">
    <br/>
    <strong style="background: #397FF7;color: #FFFFFF;">
"""
                message += translate("AddonsInstaller",
                                     "An update is available for this addon.")
                message += "</strong><br/></div><hr/>" + desc + '<br/><br/>Addon repository: <a href="'
                message += self.repos[self.idx][1] + '">' + self.repos[
                    self.idx][1] + "</a>"
                # mark as already installed AND already checked for updates AND update is available
                self.repos[self.idx][2] = 3
            # If there isn't, indicate that this addon is already installed
            else:
                message = """
<div style="width: 100%;text-align: center;background: #C1FEB2;">
    <br/>
    <strong style="background: #00B629;color: #FFFFFF;">
"""
                message += translate("AddonsInstaller",
                                     "This addon is already installed.")
                message += "</strong><br/></div><hr/>" + desc
                message += '<br/><br/>Addon repository: <a href="'
                message += self.repos[self.idx][1] + '">' + self.repos[
                    self.idx][1] + "</a>"
                self.repos[self.idx][
                    2] = 2  # mark as already installed AND already checked for updates
            # Let the user know the install path for this addon
            message += "<br/>" + translate("AddonInstaller",
                                           "Installed location") + ": "
            message += FreeCAD.getUserAppDataDir(
            ) + os.sep + "Mod" + os.sep + self.repos[self.idx][0]
            self.addon_repos.emit(self.repos)
        elif self.repos[self.idx][2] == 2:
            message = """
<div style="width: 100%;text-align: center;background: #C1FEB2;">
    <br/>
    <strong style="background: #00B629;color: #FFFFFF;">
"""
            message += translate("AddonsInstaller",
                                 "This addon is already installed.")
            message += "</strong><br></div><hr/>" + desc
            message += '<br/><br/>Addon repository: <a href="'
            message += self.repos[self.idx][1] + '">' + self.repos[
                self.idx][1] + "</a>"
            message += "<br/>" + translate("AddonInstaller",
                                           "Installed location") + ": "
            message += FreeCAD.getUserAppDataDir(
            ) + os.sep + "Mod" + os.sep + self.repos[self.idx][0]
        elif self.repos[self.idx][2] == 3:
            message = """
<div style="width: 100%;text-align: center;background: #75AFFD;">
    <br/>
    <strong style="background: #397FF7;color: #FFFFFF;">
"""
            message += translate("AddonsInstaller",
                                 "An update is available for this addon.")
            message += "</strong><br/></div><hr/>" + desc + '<br/><br/>Addon repository: <a href="'
            message += self.repos[self.idx][1] + '">' + self.repos[
                self.idx][1] + "</a>"
            message += "<br/>" + translate("AddonInstaller",
                                           "Installed location") + ": "
            message += FreeCAD.getUserAppDataDir(
            ) + os.sep + "Mod" + os.sep + self.repos[self.idx][0]
        else:
            message = desc + '<br/><br/>Addon repository: <a href="'
            message += self.repos[self.idx][1] + '">' + self.repos[
                self.idx][1] + '</a>'

        # If the Addon is obsolete, let the user know through the Addon UI
        if self.repos[self.idx][0] in obsolete:
            message = """
<div style="width: 100%; text-align:center; background: #FFB3B3;">
    <strong style="color: #FFFFFF; background: #FF0000;">
"""
            message += translate(
                "AddonsInstaller",
                "This addon is marked as obsolete") + "</strong><br/><br/>"
            message += translate(
                "AddonsInstaller",
                "This usually means it is no longer maintained, "
                "and some more advanced addon in this list "
                "provides the same functionality.") + "<br/></div><hr/>" + desc

        # If the Addon is Python 2 only, let the user know through the Addon UI
        if self.repos[self.idx][0] in py2only:
            message = """
<div style="width: 100%; text-align:center; background: #ffe9b3;">
    <strong style="color: #FFFFFF; background: #ff8000;">
"""
            message += translate("AddonsInstaller",
                                 "This addon is marked as Python 2 Only"
                                 ) + "</strong><br/><br/>"
            message += translate(
                "AddonsInstaller",
                "This workbench may no longer be maintained and "
                "installing it on a Python 3 system will more than "
                "likely result in errors at startup or while in use.")
            message += "<br/></div><hr/>" + desc

        self.info_label.emit(message)
        self.progressbar_show.emit(False)
        self.mustLoadImages = True
        label = self.loadImages(message, self.repos[self.idx][1],
                                self.repos[self.idx][0])
        if label:
            self.info_label.emit(label)
        self.stop = True