コード例 #1
0
def remove_repository(repo):
    dialog = xbmcgui.Dialog()
    repos = get_repos()

    filename = repo["filename"]
    repo_defs = [i for i in repos.values()]

    indices = [i for i, x in enumerate(repo_defs) if x["filename"] == filename]
    if len(indices) > 1:
        remove = dialog.yesno(
            _addon_name,
            settings.get_localized_string(30026).format(", ".join(
                [repo_defs[i]["name"] for i in indices])),
        )
    else:
        remove = dialog.yesno(
            _addon_name,
            settings.get_localized_string(30027).format(repo["name"]))
    if remove:
        os.remove(filename)
        dialog.notification(
            _addon_name,
            settings.get_localized_string(30028 if len(indices) ==
                                          1 else 30029).format(len(indices)),
        )
    del dialog
コード例 #2
0
def revoke():
    dialog = xbmcgui.Dialog()
    if dialog.yesno(
            settings.get_localized_string(30045),
            settings.get_localized_string(30033).format(
                color.color_string(_auth_url)),
    ):
        _clear_oauth()
        dialog.notification(_addon_name, settings.get_localized_string(30034))
        settings.open_settings()
コード例 #3
0
def authorize(in_addon=False):
    init = API.authorize()

    dialog = xbmcgui.Dialog()
    qr_code = qr.generate_qr(init["verification_uri"], _addon_data, "auth.png")
    top = [
        (settings.get_localized_string(30077), "#efefefff"),
        (init["verification_uri"], _color),
    ]
    bottom = [
        (settings.get_localized_string(30078), "#efefefff"),
        (init["user_code"], _color),
    ]
    qr.qr_dialog(
        qr_code,
        top_text=top,
        bottom_text=bottom,
    )

    tools.execute_builtin("ShowPicture({})".format(qr_code))
    expires = time.time() + init["expires_in"]

    while True:
        time.sleep(init["interval"])

        token = API.authorize(init["device_code"])

        pct_timeout = (time.time() - expires) / init["expires_in"] * 100
        pct_timeout = 100 - int(abs(pct_timeout))

        if pct_timeout >= 100:
            tools.execute_builtin('Action(Back)')
            dialog.notification(_addon_name,
                                settings.get_localized_string(30030))
            break
        if not tools.get_condition("Window.IsActive(slideshow)"):
            dialog.notification(_addon_name,
                                settings.get_localized_string(30031))
            break

        if "access_token" in token:
            tools.execute_builtin('Action(Back)')
            _save_oauth(token)
            dialog.notification(_addon_name,
                                settings.get_localized_string(30032))
            break

    del dialog
    os.remove(qr_code)

    if in_addon:
        tools.execute_builtin("RunScript({})".format(_addon_id))
    else:
        settings.open_settings()
コード例 #4
0
def build_menu(items):
    action_items = []
    for action in items:
        li = xbmcgui.ListItem(
            settings.get_localized_string(action[0])
            if type(action[0]) == int else action[0],
            label2=settings.get_localized_string(action[1])
            if type(action[1]) == int else action[1],
        )
        li.setArt({"thumb": os.path.join(_media_path, action[3])})
        action_items.append(li)
    return (items, action_items)
コード例 #5
0
def repo_menu():
    dialog = xbmcgui.Dialog()
    repos = get_repos()

    repo_items = []
    with tools.busy_dialog():
        add = xbmcgui.ListItem(
            settings.get_localized_string(30002),
            label2=settings.get_localized_string(30056),
        )
        add.setArt({"thumb": os.path.join(_media_path, "plus.png")})
        repo_items.append(add)

        repo_defs = sorted(
            repos.values(),
            key=lambda b: b.get("timestamp", 0)
            if _sort_repos else b.get("name"),
            reverse=True,
        )
        for repo in repo_defs:
            user = repo["user"]
            repo_name = repo["repo_name"]
            name = repo["name"]
            plugin_id = repo["plugin_id"]

            li = xbmcgui.ListItem(
                name,
                label2="{} - ".format(repo_name) +
                settings.get_localized_string(30049).format(user),
            )

            if not _compact:
                li.setArt({"thumb": get_icon(user, repo_name, plugin_id)})

            repo_items.append(li)

    selection = dialog.select(settings.get_localized_string(30011),
                              repo_items,
                              useDetails=not _compact)
    if selection == -1:
        dialog.notification(_addon_name, settings.get_localized_string(30023))
        del dialog
        return None
    else:
        del dialog
        if selection == 0:
            add_repository()
        else:
            manage_menu(repo_defs[selection - 1])
コード例 #6
0
def _prompt_for_update(key):
    dialog = xbmcgui.Dialog()

    if dialog.yesno(_addon_name, settings.get_localized_string(30053)):
        tools.execute_builtin("RunScript({},action=update_addon,id={})".format(
            _addon_id, key))
    del dialog
コード例 #7
0
def manage_menu(repo):
    actions = tools.build_menu([
        (30000, 30054, update_addon.update_menu, "update.png", {
            "repo": repo
        }),
        (
            30001,
            30055,
            raise_issue.raise_issue,
            "issue.png",
            {
                "selection": repo
            },
        ),
        (30095, 30096, _exclude_filter, "xor.png", {
            "repo": repo
        }),
        (30003, 30057, remove_repository, "minus.png", {
            "repo": repo
        }),
    ])

    _update_repo(repo, timestamp=time.time())

    dialog = xbmcgui.Dialog()
    selection = dialog.select(settings.get_localized_string(30004),
                              actions[1],
                              useDetails=not _compact)
    del dialog

    if selection > -1:
        if len(actions[0][selection]) == 4:
            actions[0][selection][2]()
        elif len(actions[0][selection]) == 5:
            actions[0][selection][2](**actions[0][selection][4])
コード例 #8
0
def _add_repo(user,
              repo,
              name,
              plugin_id,
              timestamp=None,
              update=False,
              path=None):
    dialog = xbmcgui.Dialog()

    key = user + "-" + plugin_id
    addon_def = {
        key: {
            "user": user,
            "repo_name": repo,
            "name": name,
            "plugin_id": plugin_id,
            "exclude_items": [],
            "timestamp": timestamp or time.time(),
        }
    }
    filename = key + ".json"

    tools.create_folder(_json_path)
    tools.write_to_file(
        os.path.join(_json_path, filename) if path is None else path,
        json.dumps(addon_def, indent=4),
    )

    if not update:
        dialog.notification(_addon_name, settings.get_localized_string(30025))
        _prompt_for_update(key)
    del dialog
コード例 #9
0
def _format_issue(title, description, log_key):
    log_desc = "{}\n\n{}\n\nLog File - {}".format(
        settings.get_localized_string(30012).format(_addon_name),
        description,
        logging.log_url(log_key),
    )

    return {"title": title, "body": log_desc}
コード例 #10
0
def _check_repo(user, repo):
    dialog = xbmcgui.Dialog()

    can_get = API.get("repos/{}/{}".format(user, repo))
    if not can_get.ok:
        dialog.ok(_addon_name, settings.get_localized_string(30024))
        del dialog
        return False
    return True
コード例 #11
0
def _log_dialog(log_key):
    url = log_url(log_key)
    copied = tools.copy2clip(url)

    qr_code = qr.generate_qr(url, _addon_data, "{}.png".format(log_key))
    top = [(settings.get_localized_string(30068), "#efefefff"), (url, _color)]
    bottom = [(settings.get_localized_string(30072),
               "#efefefff")] if copied else []
    qr.qr_dialog(
        qr_code,
        top_text=top,
        bottom_text=bottom,
    )

    tools.execute_builtin("ShowPicture({})".format(qr_code))
    while tools.get_condition("Window.IsActive(slideshow)"):
        xbmc.sleep(1000)
    os.remove(qr_code)
コード例 #12
0
def to_local_time(utc_time):
    date_long = xbmc.getRegion("datelong")
    time_long = xbmc.getRegion("time")
    format_string = settings.get_localized_string(30035).format(
        date_long, time_long)

    utc_parsed = parser.parse(utc_time)
    local_time = utc_parsed.astimezone(tz.tzlocal())

    return local_time.strftime(format_string)
コード例 #13
0
def _branch_menu(repo, repo_branches):
    dialog = xbmcgui.Dialog()
    pool = ThreadPool()

    with tools.busy_dialog():
        for branch in repo_branches:
            if "message" in branch:
                break
            pool.put(repository.get_branch_info, repo, branch)
        branches = pool.wait_completion()
        default_branch, protected_branches, sorted_branches = repository.sort_branches(
            repo, branches)

        branch_items = []
        for i in sorted_branches:
            date = tools.to_local_time(i["updated_at"])
            li = xbmcgui.ListItem(
                "{} - ({})".format(i["branch"]["name"],
                                   color.color_string(i["sha"][:7])),
                label2=settings.get_localized_string(30016).format(date),
            )

            if not _compact:
                art = os.path.join(_media_path, "branch.png")
                if i in default_branch:
                    art = os.path.join(_media_path, "default-branch.png")
                elif i in protected_branches:
                    art = os.path.join(_media_path, "protected-branch.png")
                li.setArt({"thumb": art})

            branch_items.append(li)
    selection = dialog.select(settings.get_localized_string(30017),
                              branch_items,
                              useDetails=not _compact)
    if selection > -1:
        _commit_menu(repo, sorted_branches[selection])
    else:
        del dialog
        return
コード例 #14
0
def _select_log_file():
    dialog = xbmcgui.Dialog()
    log_files = _get_log_files()

    filenames = [os.path.split(i)[1] for i in log_files]
    f = dialog.select(
        settings.get_localized_string(30076),
        filenames,
        preselect=filenames.index("kodi.log"),
    )

    del dialog

    if f > -1:
        return log_files[f]
コード例 #15
0
def _tag_menu(repo, repo_tags):
    pool = ThreadPool()

    commits = []
    tag_items = []
    tags = []
    with tools.busy_dialog():
        for tag in repo_tags:
            if "message" in tag:
                break
            tags.append((os.path.split(tag["ref"])[1], tag["object"]["sha"]))
            pool.put(
                repository.get_commit_info,
                repo["user"],
                repo["repo_name"],
                tag["object"]["sha"],
            )
        commits = pool.wait_completion()

        sorted_commits = sorted(
            commits,
            key=lambda b: b["commit"]["author"]["date"]
            if "commit" in b else b["author"]["date"],
            reverse=True,
        )

        for commit in sorted_commits:
            tag = [i[0] for i in tags if i[1] == commit["sha"]][0]
            label = color.color_string(tag)
            if label not in [i.getLabel() for i in tag_items]:
                li = xbmcgui.ListItem(label)
                if not _compact:
                    li.setArt({"thumb": os.path.join(_media_path, "tag.png")})
                tag_items.append(li)

    dialog = xbmcgui.Dialog()
    selection = dialog.select(settings.get_localized_string(30014),
                              tag_items,
                              useDetails=not _compact)
    del dialog

    if selection > -1:
        sha = sorted_commits[selection]["sha"]
        update_addon(
            repo,
            sorted_commits[selection],
            [i[0] for i in tags if i[1] == sha][0],
        )
コード例 #16
0
def raise_issue(repo):
    dialog = xbmcgui.Dialog()
    title = dialog.input(settings.get_localized_string(30006))
    if title:
        description = dialog.input(settings.get_localized_string(30007))
        log_key = None
        response, log_key = logging.upload_log()

        if response:
            try:
                resp = API.raise_issue(
                    repo["user"],
                    repo["repo"],
                    _format_issue(title, description, log_key),
                )

                if "message" not in resp:
                    qr_code = qr.generate_qr(
                        resp["html_url"],
                        _addon_data,
                        "{}.png".format(resp["number"]),
                    )
                    top = [
                        (
                            settings.get_localized_string(30008),
                            "#efefefff",
                        ),
                        (
                            "{}/{}".format(repo["user"], repo["repo"]),
                            _color,
                        ),
                    ]
                    bottom = [
                        (settings.get_localized_string(30079), "#efefefff"),
                        (resp["html_url"], _color),
                    ]
                    qr.qr_dialog(
                        qr_code,
                        top_text=top,
                        bottom_text=bottom,
                    )

                    tools.execute_builtin("ShowPicture({})".format(qr_code))
                    while tools.get_condition("Window.IsActive(slideshow)"):
                        xbmc.sleep(1000)
                    os.remove(qr_code)
                else:
                    dialog.ok(_addon_name, resp["message"])
            except requests.exceptions.RequestException as e:
                dialog.notification(_addon_name,
                                    settings.get_localized_string(30009))
                tools.log("Error opening issue: {}".format(e), "error")
    else:
        dialog.ok(_addon_name, settings.get_localized_string(30010))
    del dialog
コード例 #17
0
def color_picker():
    select_list = []
    dialog = xbmcgui.Dialog()
    current_color = settings.get_setting_string("general.color")
    for i in _color_chart:
        select_list.append(color_string(i, i))
    color = dialog.select(
        "{}: {}".format(_addon_name, settings.get_localized_string(30036)),
        select_list,
        preselect=_color_chart.index(current_color),
    )
    if color > -1:
        settings.set_setting_string(
            "general.display_color",
            color_string(_color_chart[color], _color_chart[color]),
        )
        settings.set_setting_string("general.color", _color_chart[color])
コード例 #18
0
def main_menu():
    auth = oauth.check_auth()

    if auth:
        actions = tools.build_menu([
            (30074, 30075, repository.repo_menu, "github.png"),
            (
                30069,
                30070,
                logging.upload_log,
                "log.png",
                {
                    "choose": True,
                    "dialog": True
                },
            ),
        ])
    else:
        actions = tools.build_menu([
            (30043, 30071, oauth.authorize, "github.png", {
                "in_addon": True
            }),
            (
                30069,
                30070,
                logging.upload_log,
                "log.png",
                {
                    "choose": True,
                    "dialog": True
                },
            ),
        ])

    dialog = xbmcgui.Dialog()
    selection = dialog.select(settings.get_localized_string(30004),
                              actions[1],
                              useDetails=not _compact)
    del dialog

    if selection > -1:
        if len(actions[0][selection]) == 4:
            actions[0][selection][2]()
        elif len(actions[0][selection]) == 5:
            actions[0][selection][2](**actions[0][selection][4])
コード例 #19
0
def _exclude_filter(repo):
    excludes = repo.get("exclude_items")
    addon_path = os.path.join(_addons, repo["plugin_id"])

    dialog = xbmcgui.Dialog()
    if not os.path.exists(addon_path):
        dialog.ok(
            settings.get_localized_string(30095),
            settings.get_localized_string(30097),
        )
        return

    items = sorted([
        "/{}".format(i) for i in os.listdir(addon_path)
        if os.path.isdir(os.path.join(addon_path, i))
    ])
    items += sorted([
        i for i in os.listdir(addon_path)
        if not os.path.isdir(os.path.join(addon_path, i))
    ])
    if excludes is not None:
        items += excludes

    selected = []
    list_items = []
    for i in items:
        li = xbmcgui.ListItem(i)
        if not _compact:
            art = "file.png"
            if os.path.isdir(os.path.join(addon_path, i.lstrip('/'))):
                art = "folder.png"
            else:
                ext = i.split('.')[-1]
                file = os.path.join(_media_path, "{}.png".format(ext))
                if os.path.exists(file):
                    art = "{}.png".format(ext)
            li.setArt({"thumb": os.path.join(_media_path, art)})
        list_items.append(li)

        if i in excludes or i.startswith(('.', "/.")):
            selected.append(items.index(i))

    selection = dialog.multiselect(
        settings.get_localized_string(30100),
        list_items,
        preselect=selected,
        useDetails=not _compact,
    )

    if selection is None:
        dialog.notification(_addon_name, settings.get_localized_string(30101))
        del dialog
        return
    else:
        excluded_items = [items[i] for i in selection]
        if excluded_items == excludes:
            dialog.notification(_addon_name,
                                settings.get_localized_string(30101))
            del dialog
            return

    update = dialog.yesno(
        settings.get_localized_string(30095),
        settings.get_localized_string(30098).format(
            color.color_string(len(selection)),
            color.color_string(repo["repo_name"]),
        ),
    )

    if update:
        _update_repo(repo, exclude_items=excluded_items)
        delete = dialog.yesno(settings.get_localized_string(30095),
                              settings.get_localized_string(30099))
        del dialog
        if delete:
            for i in excluded_items:
                filepath = os.path.join(addon_path, i.lstrip('/'))
                if os.path.isdir(filepath):
                    tools.remove_folder(filepath)
                else:
                    tools.remove_file(filepath)
    else:
        dialog.notification(_addon_name, settings.get_localized_string(30101))
        del dialog
        return
コード例 #20
0
def update_menu(repo):
    action_items = []
    with tools.busy_dialog():
        if type(repo) != dict:
            repo = repository.get_repos(repo)
        if not repo:
            return

        repo_tags = list(API.get_tags(repo["user"], repo["repo_name"]))
        default_branch = API.get_default_branch(repo["user"],
                                                repo["repo_name"])
        repo_branches = list(
            API.get_repo_branches(repo["user"], repo["repo_name"]))

    action_items.append((
        30088,
        settings.get_localized_string(30089).format(
            color.color_string(default_branch)),
        update_addon,
        "default-branch.png",
        {
            "repo":
            repo,
            "commit":
            API.get_commit(repo["user"], repo["repo_name"], default_branch),
            "label":
            default_branch,
        },
    ))

    if len(repo_tags) > 0 and "message" not in repo_tags[0]:
        action_items.append((30084, 30094, _tag_menu, "tag.png", {
            "repo": repo,
            "repo_tags": repo_tags
        }))

    if len(repo_branches) > 1:
        action_items.append((
            30086,
            30087,
            _branch_menu,
            "branch.png",
            {
                "repo": repo,
                "repo_branches": repo_branches
            },
        ))
    elif len(repo_branches) == 1:
        action_items.append((
            30082,
            settings.get_localized_string(30090).format(
                color.color_string(default_branch)),
            _commit_menu,
            "commit.png",
            {
                "repo": repo,
                "branch": repository.get_branch_info(repo, default_branch),
            },
        ))

    actions = tools.build_menu(action_items)

    dialog = xbmcgui.Dialog()
    selection = dialog.select(settings.get_localized_string(30004),
                              actions[1],
                              useDetails=not _compact)
    del dialog

    if selection > -1:
        if len(actions[0][selection]) == 4:
            actions[0][selection][2]()
        elif len(actions[0][selection]) == 5:
            actions[0][selection][2](**actions[0][selection][4])
コード例 #21
0
def _commit_menu(repo, branch):
    pool = ThreadPool()

    commits = []
    commit_items = []
    with tools.busy_dialog():
        for branch_commit in list(
                API.get_branch_commits(repo["user"], repo["repo_name"],
                                       branch["name"])):
            pool.put(
                _get_commit_info,
                repo["user"],
                repo["repo_name"],
                branch_commit["sha"],
            )
        commits = pool.wait_completion()

        sorted_commits = sorted(
            commits,
            key=lambda b: b["commit"]["author"]["date"]
            if "commit" in b else b["author"]["date"],
            reverse=True,
        )

        for commit in sorted_commits:
            date = tools.to_local_time(commit["commit"]["author"]["date"])
            byline = settings.get_localized_string(30013).format(
                commit["commit"]["author"]["name"], date)
            if _commit_stats:
                stats = commit['stats']
                adds = stats.get("additions", 0)
                deletes = stats.get("deletions", 0)
                add_text = (color.color_string("[B]+[/B] {}".format(adds),
                                               "springgreen")
                            if adds > 0 else "[B]+[/B] {}".format(adds))
                delete_text = (color.color_string(
                    "[B]-[/B] {}".format(deletes), "crimson") if deletes > 0
                               else "[B]-[/B] {}".format(deletes))

                byline = "{} {}: ".format(add_text, delete_text) + byline
            li = xbmcgui.ListItem(
                "{} - {}".format(
                    color.color_string(commit["sha"][:7]),
                    commit["commit"]["message"].replace("\n", "; "),
                ),
                label2=byline,
            )

            if not _compact:
                art = os.path.join(_media_path, "commit.png")
                if "pull" in commit["commit"]["message"]:
                    art = os.path.join(_media_path, "pull.png")
                elif "merge" in commit["commit"]["message"]:
                    art = os.path.join(_media_path, "merge.png")

                li.setArt({"thumb": art})

            commit_items.append(li)

    dialog = xbmcgui.Dialog()
    selection = dialog.select(settings.get_localized_string(30014),
                              commit_items,
                              useDetails=not _compact)

    if selection > -1:
        del dialog
        update_addon(repo, sorted_commits[selection],
                     sorted_commits[selection]["sha"][:7])
    else:
        dialog.notification(_addon_name, settings.get_localized_string(30015))
        del dialog
コード例 #22
0
def add_repository():
    dialog = xbmcgui.Dialog()
    pool = ThreadPool()

    user = dialog.input(settings.get_localized_string(30022)).lower()
    if not user:
        dialog.notification(_addon_name, settings.get_localized_string(30023))
        del dialog
        return

    if API.get_user(user).get("type", "User") == "Organization":
        user_repos = API.get_org_repos(user)
    elif user == _user.lower():
        access_level = [
            "owner",
            "collaborator" if _collaborator else "",
            "organization_member" if _organization else "",
        ]
        user_repos = API.get_repos(",".join(access_level))
    else:
        user_repos = API.get_user_repos(user)

    addon_repos = []
    repo_items = []

    with tools.busy_dialog():
        for user_repo in user_repos:
            if "message" in user_repo:
                dialog.ok(_addon_name, settings.get_localized_string(30065))
                del dialog
                return
            pool.put(get_repo_info, user_repo)
        repos = pool.wait_completion()
        if not repos:
            dialog.ok(_addon_name, settings.get_localized_string(30066))
            del dialog
            return

        repos.sort(key=lambda b: b["updated_at"], reverse=True)
        addon_repos = [i["repo_name"] for i in repos]
        for i in repos:
            byline = ("{} - ".format(i["repo_name"]) + ", ".join([
                settings.get_localized_string(30049).format(i["user"]),
                settings.get_localized_string(30016).format(
                    tools.to_local_time(i["updated_at"])),
            ]) if i["user"].lower() != user else
                      "{} - ".format(i["repo_name"]) +
                      settings.get_localized_string(30016).format(
                          tools.to_local_time(i["updated_at"])))
            li = xbmcgui.ListItem(
                "{} - ({})".format(
                    i["name"],
                    ", ".join([e.title() for e in i["extensions"]])),
                label2=byline,
            )

            if not _compact:
                li.setArt({"thumb": i["icon"]})

            repo_items.append(li)

    if len(addon_repos) == 0:
        dialog.ok(_addon_name, settings.get_localized_string(30058))
        del dialog
        return

    selection = dialog.select(settings.get_localized_string(30011),
                              repo_items,
                              useDetails=not _compact)
    if selection < 0:
        del dialog
        return
    user = repos[selection]["user"]
    repo = addon_repos[selection]

    if not _check_repo(user, repo):
        del dialog
        return

    addon_xml = API.get_file(user, repo, "addon.xml", text=True)
    if not addon_xml:
        del dialog
        return

    tools.log("Reading addon.xml from {}/{}".format(user, repo))
    addon = tools.parse_xml(text=addon_xml.encode("utf-8"))

    name = addon.get("name")
    plugin_id = addon.get("id")

    if dialog.yesno(_addon_name,
                    settings.get_localized_string(30059).format(name)):
        _add_repo(user, repo, name, plugin_id)
    del dialog
コード例 #23
0
def force_auth():
    dialog = xbmcgui.Dialog()
    if not _access_token:
        if dialog.yesno(_addon_name, settings.get_localized_string(30005)):
            authorize(True)
    del dialog
コード例 #24
0
def update_addon(repo, commit=None, label=None):
    dialog = xbmcgui.Dialog()
    tools.cleanup_old_files()

    if not dialog.yesno(
            settings.get_localized_string(30000),
            settings.get_localized_string(30018).format(
                color.color_string(repo["name"]),
                color.color_string(label),
            ),
    ):
        dialog.notification(_addon_name, settings.get_localized_string(30015))
        del dialog
        return

    progress = xbmcgui.DialogProgress()
    progress.create(
        _addon_name,
        settings.get_localized_string(30019).format(
            color.color_string(repo["name"])),
    )
    progress.update(0)

    location = _get_zip_file(repo["user"],
                             repo["repo_name"],
                             sha=commit["sha"])

    if location:
        progress.update(
            25,
            settings.get_localized_string(30020).format(
                color.color_string(repo["name"])),
        )

        extensions = repository.get_extensions(repo["user"], repo["repo_name"])
        plugin_id = repo["plugin_id"]
        exists = _exists(plugin_id)
        is_service = "service" in extensions
        is_current_skin = "skin" in extensions and tools.get_current_skin(
        ) == plugin_id

        if is_service:
            _set_enabled(plugin_id, False, exists)

        tools.remove_folder(os.path.join(_addons, plugin_id))
        _extract_addon(location, repo)

        progress.update(
            50,
            settings.get_localized_string(30062).format(
                color.color_string(repo["name"])),
        )

        if _add_webpdb:
            _add_webpdb_to_addon(plugin_id)

        _rewrite_kodi_dependency_versions(plugin_id)
        _update_addon_version(
            plugin_id,
            commit["sha"],
        )

        failed_deps = []
        if _dependencies:
            progress.update(
                75,
                settings.get_localized_string(30063).format(
                    color.color_string(repo["name"])),
            )
            failed_deps = _install_deps(plugin_id)

        _set_enabled(plugin_id, True, exists)

        progress.update(
            100, settings.get_localized_string(30067 if not exists else 30021))

        if failed_deps:
            dialog.ok(
                _addon_name,
                settings.get_localized_string(30064).format(
                    ", ".join(failed_deps), repo["name"]),
            )

        if not exists:
            tools.reload_profile()
        elif is_current_skin:
            tools.reload_skin()

    progress.close()
    del progress
    del dialog