From 41f8373d62f8f9ff34c584608bf51d5815068c67 Mon Sep 17 00:00:00 2001 From: Morg42 <43153739+Morg42@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:00:42 +0100 Subject: [PATCH] githubplugin: enable updating forks/branches/PRs from github --- githubplugin/__init__.py | 14 +- githubplugin/webif/__init__.py | 79 +++++++-- githubplugin/webif/templates/index.html | 206 ++++++++++++++++-------- 3 files changed, 218 insertions(+), 81 deletions(-) diff --git a/githubplugin/__init__.py b/githubplugin/__init__.py index dc226016a..5608b4ca7 100644 --- a/githubplugin/__init__.py +++ b/githubplugin/__init__.py @@ -146,8 +146,10 @@ def get_pulls(self, fetch=False) -> bool: # succeed if cached pulls present and fetch not requested if not fetch: if self.pulls != {}: + self.logger.debug(f'using cached pulls: {self.pulls.keys()}') return True + self.logger.debug('fetching pulls from github') self.pulls = {} for pull in self.git_repo.get_pulls(): self.pulls[pull.number] = { @@ -198,9 +200,11 @@ def get_branches_from(self, fork=None, owner='', fetch=False) -> dict: except KeyError: pass else: + self.logger.debug(f'returning cached {b_list}') return b_list # fetch from github + self.logger.debug('refreshing branches from github') branches = fork.get_branches() b_list = {} for branch in branches: @@ -231,9 +235,11 @@ def get_plugins_from(self, fork=None, owner='', branch='', fetch=False) -> list: except KeyError: pass else: + self.logger.debug(f'returning cached plugins {plugins}') return plugins # plugins not yet cached, fetch from github + self.logger.debug('fetching plugins from github') contents = fork.get_contents("", ref=branch) plugins = [item.path for item in contents if item.type == 'dir' and not item.path.startswith('.')] @@ -634,17 +640,17 @@ def setup_github(self) -> bool: return self.gh.set_repo() - def fetch_github_forks(self) -> bool: + def fetch_github_forks(self, fetch=False) -> bool: """ fetch forks from github API """ if self.gh: - return self.gh.get_forks() + return self.gh.get_forks(fetch=fetch) else: return False - def fetch_github_pulls(self) -> bool: + def fetch_github_pulls(self, fetch=False) -> bool: """ fetch PRs from github API """ if self.gh: - return self.gh.get_pulls() + return self.gh.get_pulls(fetch=fetch) else: return False diff --git a/githubplugin/webif/__init__.py b/githubplugin/webif/__init__.py index dbaf92ea1..504df308d 100644 --- a/githubplugin/webif/__init__.py +++ b/githubplugin/webif/__init__.py @@ -24,18 +24,15 @@ # ######################################################################### -import os -import json - from lib.item import Items from lib.model.smartplugin import SmartPluginWebIf +import cherrypy + # ------------------------------------------ # Webinterface of the plugin # ------------------------------------------ -import cherrypy -import csv class WebInterface(SmartPluginWebIf): @@ -83,13 +80,17 @@ def index(self, action=None): # collect only PRs which (branches) are not already installed as a worktree pulls = {} for pr in self.plugin.gh.pulls: + skip = False if self.plugin.gh.pulls[pr]['owner'] in reposbyowner: - if self.plugin.gh.pulls[pr]['branch'] not in reposbyowner[self.plugin.gh.pulls[pr]['owner']]: - pulls[pr] = { - 'title': self.plugin.gh.pulls[pr]['title'], - 'owner': self.plugin.gh.pulls[pr]['owner'], - 'branch': self.plugin.gh.pulls[pr]['branch'] - } + if self.plugin.gh.pulls[pr]['branch'] in reposbyowner[self.plugin.gh.pulls[pr]['owner']]: + skip = True + + if not skip: + pulls[pr] = { + 'title': self.plugin.gh.pulls[pr]['title'], + 'owner': self.plugin.gh.pulls[pr]['owner'], + 'branch': self.plugin.gh.pulls[pr]['branch'] + } return tmpl.render(p=self.plugin, webif_pagelength=pagelength, @@ -100,14 +101,48 @@ def index(self, action=None): pulls=pulls, language=self.plugin.get_sh().get_defaultlanguage()) + @cherrypy.expose + @cherrypy.tools.json_out() + def updateForks(self): + if self.plugin.fetch_github_forks(fetch=True): + return {"operation": "request", "result": "success", "data": sorted(self.plugin.gh.forks.keys())} + + @cherrypy.expose + @cherrypy.tools.json_in() + @cherrypy.tools.json_out() + def getPull(self): + json = cherrypy.request.json + try: + pr = int(json.get("pull", 0)) + except Exception: + self.logger.error(f'invalid value for pr in {json}') + return + if pr > 0: + pull = self.plugin.get_github_pulls(number=pr) + b = pull.get('branch') + o = pull.get('owner') + if b and o: + return {"operation": "request", "result": "success", "owner": o, "branch": b} + else: + self.logger.error(f'invalid data on processing PR {pr}') + + @cherrypy.expose + @cherrypy.tools.json_out() + def updatePulls(self): + if self.plugin.fetch_github_pulls(fetch=True): + prn = list(self.plugin.get_github_pulls().keys()) + prt = [v['title'] for pr, v in self.plugin.get_github_pulls().items()] + return {"operation": "request", "result": "success", "prn": prn, "prt": prt} + @cherrypy.expose @cherrypy.tools.json_out() @cherrypy.tools.json_in() def updateBranches(self): json = cherrypy.request.json owner = json.get("owner") + force = json.get("force", False) if owner is not None and owner != '': - branches = self.plugin.fetch_github_branches_from(owner=owner) + branches = self.plugin.fetch_github_branches_from(owner=owner, fetch=force) if branches != {}: return {"operation": "request", "result": "success", "data": list(branches.keys())} @@ -116,10 +151,11 @@ def updateBranches(self): @cherrypy.tools.json_in() def updatePlugins(self): json = cherrypy.request.json + force = json.get("force", False) owner = json.get("owner") branch = json.get("branch") if owner is not None and owner != '' and branch is not None and branch != '': - plugins = self.plugin.fetch_github_plugins_from(owner=owner, branch=branch) + plugins = self.plugin.fetch_github_plugins_from(owner=owner, branch=branch, fetch=force) if plugins != {}: return {"operation": "request", "result": "success", "data": plugins} @@ -137,6 +173,23 @@ def removePlugin(self): if self.plugin.remove_plugin(name): return {"operation": "request", "result": "success"} + @cherrypy.expose + @cherrypy.tools.json_out() + @cherrypy.tools.json_in() + def removeInitPlugin(self): + json = cherrypy.request.json + name = json.get("name") + if name is None or name == '' or name not in self.plugin.init_repos: + msg = f'Plugin {name} nicht vorhanden.' + self.logger.error(msg) + return {"operation": "request", "result": "error", "data": msg} + + try: + del self.plugin.init_repos[name] + except Exception: + pass + return {"operation": "request", "result": "success"} + @cherrypy.expose @cherrypy.tools.json_out() @cherrypy.tools.json_in() diff --git a/githubplugin/webif/templates/index.html b/githubplugin/webif/templates/index.html index dd024a585..cf8ee0154 100644 --- a/githubplugin/webif/templates/index.html +++ b/githubplugin/webif/templates/index.html @@ -47,7 +47,7 @@ - Löschen wird ausgeführt. Bitte Geduld, dies kann etwas dauern... + Löschen wird ausgeführt. Bitte Geduld, dies kann etwas dauern... @@ -62,7 +62,7 @@
Plugin installieren aus:
- +
@@ -84,12 +85,14 @@ {% endfor %} + @@ -142,9 +146,14 @@ } } - function addOption(sel, val, def) { + function addOption(sel, text, def, val) { var option = document.createElement('option'); - option.text = val; + option.text = text; + if (val != undefined) { + option.value = val; + } else { + option.value = text; + } if (def) { option.selected = true; } @@ -180,21 +189,56 @@ document.getElementById('modalSpinner' + nr).style.display = 'block'; } + function sendData(url, data, error, success) { + $.ajax({ + type: "POST", + url: url, + data: JSON.stringify(data), + contentType: 'application/json', + dataType: 'json', + error: error, + success: success + }) + } + function selectedPR(selObj) { var PR = document.getElementById('pr').value; if (PR > 0) { - document.getElementById('owner').value = pulls[PR]['owner']; - var branch = document.getElementById('branch'); - clearSelect(branch); - addOption(branch, pulls[PR]['branch']); - branch.value = pulls[PR]['branch']; - document.getElementById('branch').disabled = false; - document.getElementById('btn-branch').disabled = false; - document.getElementById('btn-plugin').disabled = true; - clearPlugin(); + sendData('getPull', {'pull': PR}, + function(response){ + alert("Fehler beim Übermitteln der Daten. Bitte shng-Log prüfen!"); + }, + function(response){ + var branch = document.getElementById('branch'); + var powner = response['owner']; + var pbranch = response['branch']; + document.getElementById('owner').value = powner; + clearSelect(branch); + addOption(branch, pbranch); + branch.value = pbranch; + branch.disabled = false; + document.getElementById('btn-branch').disabled = false; + document.getElementById('btn-plugin').disabled = true; + clearPlugin(); + }) } } + function clearForks() { + var f = document.getElementById('owner'); + f.value = ''; + + clearBranches(); + } + + function clearBranches() { + var b = document.getElementById('branch'); + clearSelect(b); + b.disabled = true; + + clearPlugin(); + } + function clearPlugin() { var p = document.getElementById('plugin'); clearSelect(p); @@ -205,21 +249,39 @@ n.disabled = true; } - function updateBranches(selObj) { + function updatePulls(selObj, force) { + clearForks(); + + sendData('updatePulls', {}, function(response) { + alert("Fehler beim Übermitteln der Daten. Bitte shng-Log prüfen!"); + }, function(response) { + var item = document.getElementById('pr'); + + // clear options + clearSelect(pr); + + // add all pulls + prn = response['prn']; + prt = response['prt']; + for (var i = 0; i < prn.length; i++) { + addOption(item, prn[i] + ": " + prt[i], false, prn[i]); + } + } + ) + } + + function updateBranches(selObj, force) { var owner = document.getElementById('owner').value; clearPlugin(); if (owner != '') { - $.ajax({ - type: "POST", - url: "updateBranches", - data: JSON.stringify({'owner': owner}), - contentType: 'application/json', - dataType: 'json', - error: function(response) { + data = {'owner': owner} + if (force == true) { + data['force'] = true; + } + sendData('updateBranches', data, function(response) { alert("Fehler beim Übermitteln der Daten. Bitte shng-Log prüfen!"); - }, - success: function(response) { + }, function(response) { var item = document.getElementById('branch'); // enable branch options @@ -236,7 +298,7 @@ addOption(item, branch, false); } } - }) + ) } } @@ -249,23 +311,21 @@ } } - function updatePlugins(selObj) { + function updatePlugins(selObj, force) { var owner = document.getElementById('owner').value; var branch = document.getElementById('branch').value; document.getElementById('pr').value = ''; - if (owner != '' && branch != '') { - $.ajax({ - type: "POST", - url: "updatePlugins", - data: JSON.stringify({'owner': owner, 'branch': branch}), - contentType: 'application/json', - dataType: 'json', - error: function(response) { + data = {'owner': owner, 'branch': branch}; + if (force == true) { + data['force'] = true; + } + sendData("updatePlugins", data, + function(response) { alert("Fehler beim Übermitteln der Daten. Bitte shng-Log prüfen!"); }, - success: function(response) { + function(response) { var item = document.getElementById('plugin'); // enable branch options @@ -282,7 +342,7 @@ document.getElementById('btn-plugin').disabled = false; } - }) + ) } } @@ -304,19 +364,15 @@ var name = document.getElementById('name').value; if (owner != '' && branch != '' && plugin != '') { - $.ajax({ - type: "POST", - url: "selectPlugin", - data: JSON.stringify({'owner': owner, 'branch': branch, 'plugin': plugin, 'name': name, 'confirm': false}), - contentType: 'application/json', - dataType: 'json', - error: function(response) { + sendData("selectPlugin", {'owner': owner, 'branch': branch, 'plugin': plugin, 'name': name, 'confirm': false}, + function(response) { alert("Fehler beim Initialisieren: " + response['data']) }, - success: function(response) { + function(response) { + document.getElementById('installModal').style.display = 'none'; showModal(owner, branch, plugin, ''); } - }) + ) } } @@ -332,20 +388,29 @@ showModal(owner, branch, plugin, ''); if (owner != '' && branch != '' && plugin != '') { spinModal(''); - $.ajax({ - type: "POST", - url: "selectPlugin", - data: JSON.stringify({'owner': owner, 'branch': branch, 'plugin': plugin, 'name': name, 'confirm': true}), - contentType: 'application/json', - dataType: 'json', - error: function(response) { + sendData("selectPlugin", {'owner': owner, 'branch': branch, 'plugin': plugin, 'name': name, 'confirm': true}, + function(response) { alert("Fehler beim Installieren: " + response['data']) }, - success: function(response) { + function(response) { hideModal(''); setTimeout(window.location.reload(), 300); } - }) + ) + } + } + + function removeInitPlugin(name) { + if (name != '') { + spinModal(''); + sendData("removeInitPlugin", {'name': name}, + function(response) { + alert("Fehler beim Entfernen: " + response['data']) + }, + function(response) { + setTimeout(window.location.reload(), 300); + } + ) } } @@ -353,23 +418,34 @@ var name = document.getElementById('doname2').textContent; if (name != '') { spinModal('2'); - $.ajax({ - type: "POST", - url: "removePlugin", - data: JSON.stringify({'name': name}), - contentType: 'application/json', - dataType: 'json', - error: function(response) { + sendData("removePlugin", {'name': name}, + function(response) { alert("Fehler beim Entfernen: " + response['data']) }, - success: function(response) { + function(response) { hideModal('2'); - // setTimeout(window.location.reload(), 300); + setTimeout(window.location.reload(), 300); } - }) + ) } } + function refetch(what) { + if (what == 'owner') { + + } + if (what == 'pr') { + updatePulls(null, true); + } + if (what == 'branch') { + updateBranches(null, true); + } + if (what == 'plugin') { + updatePlugins(null, true); + } + + } + @@ -434,7 +510,9 @@ - {% endfor %}
PR: @@ -72,6 +72,7 @@ {% endfor %} +  
Branch: + @@ -101,6 +104,7 @@ + Name: {{ init_repos[plugin].owner }} {{ init_repos[plugin].branch }} {{ init_repos[plugin].full_wt_path }} + + +