1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-11-28 12:30:00 +00:00

Update updater

Update change logfile
code cosmetics js files
This commit is contained in:
Ozzieisaacs 2020-03-29 16:22:11 +02:00
parent 6d907094d7
commit 4eacb21259
8 changed files with 153 additions and 104 deletions

View File

@ -134,6 +134,4 @@ def get_timezone():
from .updater import Updater from .updater import Updater
updater_thread = Updater() updater_thread = Updater()
updater_thread.start()
__all__ = ['app']

View File

@ -604,8 +604,8 @@ def _configuration_update_helper():
{"active":0}) {"active":0})
element["active"] = 0 element["active"] = 0
_config_int("config_log_level") reboot_required |= _config_int("config_log_level")
_config_string("config_logfile") reboot_required |= _config_string("config_logfile")
if not logger.is_valid_logfile(config.config_logfile): if not logger.is_valid_logfile(config.config_logfile):
return _configuration_result('Logfile location is not valid, please enter correct path', gdriveError) return _configuration_result('Logfile location is not valid, please enter correct path', gdriveError)
@ -968,7 +968,7 @@ def get_updater_status():
} }
status['text'] = text status['text'] = text
updater_thread.status = 0 updater_thread.status = 0
updater_thread.start() updater_thread.resume()
status['status'] = updater_thread.get_update_status() status['status'] = updater_thread.get_update_status()
elif request.method == "GET": elif request.method == "GET":
try: try:

View File

@ -492,7 +492,7 @@ def get_book_cover_internal(book,
# saves book cover from url # saves book cover from url
def save_cover_from_url(url, book_path): def save_cover_from_url(url, book_path):
img = requests.get(url) img = requests.get(url, timeout=10) # ToDo: Error Handling
return save_cover(img, book_path) return save_cover(img, book_path)

View File

@ -24,7 +24,7 @@ import signal
import socket import socket
try: try:
from gevent.pywsgi import WSGIServer from gevent.pyewsgi import WSGIServer
from gevent.pool import Pool from gevent.pool import Pool
from gevent import __version__ as _version from gevent import __version__ as _version
VERSION = 'Gevent ' + _version VERSION = 'Gevent ' + _version
@ -193,6 +193,9 @@ class WebServer(object):
self.stop() self.stop()
def stop(self, restart=False): def stop(self, restart=False):
from . import updater_thread
updater_thread.stop()
log.info("webserver stop (restart=%s)", restart) log.info("webserver stop (restart=%s)", restart)
self.restart = restart self.restart = restart
if self.wsgiserver: if self.wsgiserver:

View File

@ -17,8 +17,7 @@
// Upon loading load the logfile for the first option (event log) // Upon loading load the logfile for the first option (event log)
$(function() { $(function() {
if ($("#log_group input").length) if ($("#log_group input").length) {
{
var element = $("#log_group input[type='radio']:checked").val(); var element = $("#log_group input[type='radio']:checked").val();
init(element); init(element);
} }

View File

@ -61,6 +61,20 @@ $(function() {
$("#RestartDialog").modal("hide"); $("#RestartDialog").modal("hide");
} }
function cleanUp() {
clearInterval(updateTimerID);
$("#spinner2").hide();
$("#updateFinished").removeClass("hidden");
$("#check_for_update").removeClass("hidden");
$("#perform_update").addClass("hidden");
$("#message").alert("close");
$("#update_table > tbody > tr").each(function () {
if ($(this).attr("id") !== "current_version") {
$(this).closest("tr").remove();
}
});
}
function updateTimer() { function updateTimer() {
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
@ -69,21 +83,12 @@ $(function() {
// console.log(data.status); // console.log(data.status);
$("#Updatecontent").html(updateText[data.status]); $("#Updatecontent").html(updateText[data.status]);
if (data.status > 6) { if (data.status > 6) {
clearInterval(updateTimerID); cleanUp();
$("#spinner2").hide();
$("#updateFinished").removeClass("hidden");
$("#check_for_update").removeClass("hidden");
$("#perform_update").addClass("hidden");
} }
}, },
error: function error() { error: function error() {
// console.log('Done');
clearInterval(updateTimerID);
$("#spinner2").hide();
$("#Updatecontent").html(updateText[7]); $("#Updatecontent").html(updateText[7]);
$("#updateFinished").removeClass("hidden"); cleanUp();
$("#check_for_update").removeClass("hidden");
$("#perform_update").addClass("hidden");
}, },
timeout: 2000 timeout: 2000
}); });
@ -141,6 +146,8 @@ $(function() {
var $this = $(this); var $this = $(this);
var buttonText = $this.html(); var buttonText = $this.html();
$this.html("..."); $this.html("...");
$("#Updatecontent").html("");
$("#updateFinished").addClass("hidden");
$("#update_error").addClass("hidden"); $("#update_error").addClass("hidden");
if ($("#message").length) { if ($("#message").length) {
$("#message").alert("close"); $("#message").alert("close");

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* exported TableActions */ /* exported TableActions, RestrictionActions*/
$(function() { $(function() {
@ -94,15 +94,15 @@ $(function() {
$(e.currentTarget).find("#btndeletedomain").data("domainId", domainId); $(e.currentTarget).find("#btndeletedomain").data("domainId", domainId);
}); });
$('#restrictModal').on('hidden.bs.modal', function () { $("#restrictModal").on("hidden.bs.modal", function () {
// Destroy table and remove hooks for buttons // Destroy table and remove hooks for buttons
$("#restrict-elements-table").unbind(); $("#restrict-elements-table").unbind();
$('#restrict-elements-table').bootstrapTable('destroy'); $("#restrict-elements-table").bootstrapTable("destroy");
$("[id^=submit_]").unbind(); $("[id^=submit_]").unbind();
$('#h1').addClass('hidden'); $("#h1").addClass("hidden");
$('#h2').addClass('hidden'); $("#h2").addClass("hidden");
$('#h3').addClass('hidden'); $("#h3").addClass("hidden");
$('#h4').addClass('hidden'); $("#h4").addClass("hidden");
}); });
function startTable(type) { function startTable(type) {
var pathname = document.getElementsByTagName("script"), src = pathname[pathname.length - 1].src; var pathname = document.getElementsByTagName("script"), src = pathname[pathname.length - 1].src;
@ -113,20 +113,18 @@ $(function() {
}, },
url: path + "/../../ajax/listrestriction/" + type, url: path + "/../../ajax/listrestriction/" + type,
rowStyle: function(row, index) { rowStyle: function(row, index) {
console.log('Reihe :' + row + ' Index :'+ index); // console.log('Reihe :' + row + " Index :" + index);
if (row.id.charAt(0) == 'a') { if (row.id.charAt(0) === "a") {
return {classes: 'bg-primary'} return {classes: "bg-primary"};
} } else {
else { return {classes: "bg-dark-danger"};
return {classes: 'bg-dark-danger'}
} }
}, },
onClickCell: function (field, value, row, $element) { onClickCell: function (field, value, row, $element) {
if (field == 3) { if (field == 3) {
console.log("element")
$.ajax ({ $.ajax ({
type: 'Post', type: "Post",
data: 'id=' + row.id + '&type=' + row.type + "&Element=" + row.Element, data: "id=" + row.id + "&type=" + row.type + "&Element=" + row.Element,
url: path + "/../../ajax/deleterestriction/" + type, url: path + "/../../ajax/deleterestriction/" + type,
async: true, async: true,
timeout: 900, timeout: 900,
@ -146,12 +144,11 @@ $(function() {
}, },
striped: false striped: false
}); });
$("#restrict-elements-table").removeClass('table-hover'); $("#restrict-elements-table").removeClass("table-hover");
$("#restrict-elements-table").on('editable-save.bs.table', function (e, field, row, old, $el) { $("#restrict-elements-table").on("editable-save.bs.table", function (e, field, row, old, $el) {
console.log("Hallo");
$.ajax({ $.ajax({
url: path + "/../../ajax/editrestriction/" + type, url: path + "/../../ajax/editrestriction/" + type,
type: 'Post', type: "Post",
data: row //$(this).closest("form").serialize() + "&" + $(this)[0].name + "=", data: row //$(this).closest("form").serialize() + "&" + $(this)[0].name + "=",
}); });
}); });
@ -159,10 +156,9 @@ $(function() {
// event.stopPropagation(); // event.stopPropagation();
// event.preventDefault(); // event.preventDefault();
$(this)[0].blur(); $(this)[0].blur();
console.log($(this)[0].name);
$.ajax({ $.ajax({
url: path + "/../../ajax/addrestriction/" + type, url: path + "/../../ajax/addrestriction/" + type,
type: 'Post', type: "Post",
data: $(this).closest("form").serialize() + "&" + $(this)[0].name + "=", data: $(this).closest("form").serialize() + "&" + $(this)[0].name + "=",
success: function () { success: function () {
$.ajax ({ $.ajax ({
@ -179,28 +175,24 @@ $(function() {
return; return;
}); });
} }
$('#get_column_values').on('click',function() $("#get_column_values").on("click", function() {
{
startTable(1); startTable(1);
$('#h2').removeClass('hidden'); $("#h2").removeClass("hidden");
}); });
$('#get_tags').on('click',function() $("#get_tags").on("click", function() {
{
startTable(0); startTable(0);
$('#h1').removeClass('hidden'); $("#h1").removeClass("hidden");
}); });
$('#get_user_column_values').on('click',function() $("#get_user_column_values").on("click", function() {
{
startTable(3); startTable(3);
$('#h4').removeClass('hidden'); $("#h4").removeClass("hidden");
}); });
$('#get_user_tags').on('click',function() $("#get_user_tags").on("click", function() {
{
startTable(2); startTable(2);
$(this)[0].blur(); $(this)[0].blur();
$('#h3').removeClass('hidden'); $("#h3").removeClass("hidden");
}); });
}); });

View File

@ -53,8 +53,13 @@ class Updater(threading.Thread):
def __init__(self): def __init__(self):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.paused = False
# self.pause_cond = threading.Condition(threading.Lock())
self.can_run = threading.Event()
self.pause()
self.status = -1 self.status = -1
self.updateIndex = None self.updateIndex = None
# self.run()
def get_current_version_info(self): def get_current_version_info(self):
if config.config_updatechannel == constants.UPDATE_STABLE: if config.config_updatechannel == constants.UPDATE_STABLE:
@ -66,12 +71,12 @@ class Updater(threading.Thread):
return self._stable_available_updates(request_method) return self._stable_available_updates(request_method)
return self._nightly_available_updates(request_method,locale) return self._nightly_available_updates(request_method,locale)
def run(self): def do_work(self):
try: try:
self.status = 1 self.status = 1
log.debug(u'Download update file') log.debug(u'Download update file')
headers = {'Accept': 'application/vnd.github.v3+json'} headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(self._get_request_path(), stream=True, headers=headers) r = requests.get(self._get_request_path(), stream=True, headers=headers, timeout=(10, 600))
r.raise_for_status() r.raise_for_status()
self.status = 2 self.status = 2
@ -85,7 +90,8 @@ class Updater(threading.Thread):
if not os.path.isdir(foldername): if not os.path.isdir(foldername):
self.status = 11 self.status = 11
log.info(u'Extracted contents of zipfile not found in temp folder') log.info(u'Extracted contents of zipfile not found in temp folder')
return self.pause()
return False
self.status = 4 self.status = 4
log.debug(u'Replacing files') log.debug(u'Replacing files')
self.update_source(foldername, constants.BASE_DIR) self.update_source(foldername, constants.BASE_DIR)
@ -95,6 +101,7 @@ class Updater(threading.Thread):
web_server.stop(True) web_server.stop(True)
self.status = 7 self.status = 7
time.sleep(2) time.sleep(2)
return True
except requests.exceptions.HTTPError as ex: except requests.exceptions.HTTPError as ex:
log.info(u'HTTP Error %s', ex) log.info(u'HTTP Error %s', ex)
self.status = 8 self.status = 8
@ -104,9 +111,31 @@ class Updater(threading.Thread):
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
log.info(u'Timeout while establishing connection') log.info(u'Timeout while establishing connection')
self.status = 10 self.status = 10
except requests.exceptions.RequestException: except (requests.exceptions.RequestException, zipfile.BadZipFile):
self.status = 11 self.status = 11
log.info(u'General error') log.info(u'General error')
self.pause()
return False
def run(self):
while True:
self.can_run.wait()
if self.status > -1:
if self.do_work():
break # stop loop and end thread for restart
else:
break
def pause(self):
self.can_run.clear()
#should just resume the thread
def resume(self):
self.can_run.set()
def stop(self):
self.status = -2
self.can_run.set()
def get_update_status(self): def get_update_status(self):
return self.status return self.status
@ -258,10 +287,10 @@ class Updater(threading.Thread):
parents = [] parents = []
if status['message'] != '': if status['message'] != '':
return json.dumps(status) return json.dumps(status)
if 'object' not in commit: if 'object' not in commit or 'url' not in commit['object']:
status['message'] = _(u'Unexpected data while reading update information') status['message'] = _(u'Unexpected data while reading update information')
return json.dumps(status) return json.dumps(status)
try:
if commit['object']['sha'] == status['current_commit_hash']: if commit['object']['sha'] == status['current_commit_hash']:
status.update({ status.update({
'update': False, 'update': False,
@ -269,28 +298,34 @@ class Updater(threading.Thread):
'message': _(u'No update available. You already have the latest version installed') 'message': _(u'No update available. You already have the latest version installed')
}) })
return json.dumps(status) return json.dumps(status)
except (TypeError, KeyError):
status['message'] = _(u'Unexpected data while reading update information')
return json.dumps(status)
# a new update is available # a new update is available
status['update'] = True status['update'] = True
try: try:
headers = {'Accept': 'application/vnd.github.v3+json'} headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(repository_url + '/git/commits/' + commit['object']['sha'], headers=headers) r = requests.get(repository_url + '/git/commits/' + commit['object']['sha'],
headers=headers,
timeout=10)
r.raise_for_status() r.raise_for_status()
update_data = r.json() update_data = r.json()
except requests.exceptions.HTTPError as e: except requests.exceptions.HTTPError as e:
status['error'] = _(u'HTTP Error') + ' ' + str(e) status['message'] = _(u'HTTP Error') + ' ' + str(e)
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
status['error'] = _(u'Connection error') status['message'] = _(u'Connection error')
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
status['error'] = _(u'Timeout while establishing connection') status['message'] = _(u'Timeout while establishing connection')
except requests.exceptions.RequestException: except (requests.exceptions.RequestException, ValueError):
status['error'] = _(u'General error') status['message'] = _(u'General error')
if status['message'] != '': if status['message'] != '':
return json.dumps(status) return json.dumps(status)
if 'committer' in update_data and 'message' in update_data: # if 'committer' in update_data and 'message' in update_data:
try:
status['success'] = True status['success'] = True
status['message'] = _( status['message'] = _(
u'A new update is available. Click on the button below to update to the latest version.') u'A new update is available. Click on the button below to update to the latest version.')
@ -304,14 +339,13 @@ class Updater(threading.Thread):
update_data['sha'] update_data['sha']
] ]
) )
# it only makes sense to analyze the parents if we know the current commit hash # it only makes sense to analyze the parents if we know the current commit hash
if status['current_commit_hash'] != '': if status['current_commit_hash'] != '':
try: try:
parent_commit = update_data['parents'][0] parent_commit = update_data['parents'][0]
# limit the maximum search depth # limit the maximum search depth
remaining_parents_cnt = 10 remaining_parents_cnt = 10
except IndexError: except (IndexError, KeyError):
remaining_parents_cnt = None remaining_parents_cnt = None
if remaining_parents_cnt is not None: if remaining_parents_cnt is not None:
@ -323,7 +357,7 @@ class Updater(threading.Thread):
if parent_commit['sha'] != status['current_commit_hash']: if parent_commit['sha'] != status['current_commit_hash']:
try: try:
headers = {'Accept': 'application/vnd.github.v3+json'} headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(parent_commit['url'], headers=headers) r = requests.get(parent_commit['url'], headers=headers, timeout=10)
r.raise_for_status() r.raise_for_status()
parent_data = r.json() parent_data = r.json()
@ -343,7 +377,7 @@ class Updater(threading.Thread):
# parent is our current version # parent is our current version
break break
status['history'] = parents[::-1] status['history'] = parents[::-1]
else: except (IndexError, KeyError):
status['success'] = False status['success'] = False
status['message'] = _(u'Could not fetch update information') status['message'] = _(u'Could not fetch update information')
return json.dumps(status) return json.dumps(status)
@ -377,8 +411,9 @@ class Updater(threading.Thread):
return json.dumps(status) return json.dumps(status)
i = len(commit) - 1 i = len(commit) - 1
newer = False
while i >= 0: while i >= 0:
if 'tag_name' not in commit[i] or 'body' not in commit[i]: if 'tag_name' not in commit[i] or 'body' not in commit[i] or 'zipball_url' not in commit[i]:
status['message'] = _(u'Unexpected data while reading update information') status['message'] = _(u'Unexpected data while reading update information')
return json.dumps(status) return json.dumps(status)
major_version_update = int(commit[i]['tag_name'].split('.')[0]) major_version_update = int(commit[i]['tag_name'].split('.')[0])
@ -392,12 +427,13 @@ class Updater(threading.Thread):
except ValueError: except ValueError:
current_version[2] = int(current_version[2].split(' ')[0])-1 current_version[2] = int(current_version[2].split(' ')[0])-1
# Check if major versions are identical search for newest nonenqual commit and update to this one # Check if major versions are identical search for newest non equal commit and update to this one
if major_version_update == current_version[0]: if major_version_update == current_version[0]:
if (minor_version_update == current_version[1] and if (minor_version_update == current_version[1] and
patch_version_update > current_version[2]) or \ patch_version_update > current_version[2]) or \
minor_version_update > current_version[1]: minor_version_update > current_version[1]:
parents.append([commit[i]['tag_name'], commit[i]['body'].replace('\r\n', '<p>')]) parents.append([commit[i]['tag_name'], commit[i]['body'].replace('\r\n', '<p>')])
newer=True
i -= 1 i -= 1
continue continue
if major_version_update < current_version[0]: if major_version_update < current_version[0]:
@ -406,7 +442,9 @@ class Updater(threading.Thread):
if major_version_update > current_version[0]: if major_version_update > current_version[0]:
# found update update to last version before major update, unless current version is on last version # found update update to last version before major update, unless current version is on last version
# before major update # before major update
if commit[i+1]['tag_name'].split('.')[1] == current_version[1]: if i == (len(commit) - 1):
i -= 1
if int(commit[i+1]['tag_name'].split('.')[1]) == current_version[1]:
parents.append([commit[i]['tag_name'], parents.append([commit[i]['tag_name'],
commit[i]['body'].replace('\r\n', '<p>').replace('\n', '<p>')]) commit[i]['body'].replace('\r\n', '<p>').replace('\n', '<p>')])
status.update({ status.update({
@ -418,16 +456,18 @@ class Updater(threading.Thread):
}) })
self.updateFile = commit[i]['zipball_url'] self.updateFile = commit[i]['zipball_url']
else: else:
parents.append([commit[i+1]['tag_name'],
commit[i+1]['body'].replace('\r\n', '<p>').replace('\n', '<p>')])
status.update({ status.update({
'update': True, 'update': True,
'success': True, 'success': True,
'message': _(u'A new update is available. Click on the button below to ' 'message': _(u'A new update is available. Click on the button below to '
u'update to version: %(version)s', version=commit[i]['tag_name']), u'update to version: %(version)s', version=commit[i+1]['tag_name']),
'history': parents 'history': parents
}) })
self.updateFile = commit[i+1]['zipball_url'] self.updateFile = commit[i+1]['zipball_url']
break break
if i == -1: if i == -1 and newer == False:
status.update({ status.update({
'update': True, 'update': True,
'success': True, 'success': True,
@ -436,6 +476,16 @@ class Updater(threading.Thread):
'history': parents 'history': parents
}) })
self.updateFile = commit[0]['zipball_url'] self.updateFile = commit[0]['zipball_url']
elif i == -1 and newer == True:
status.update({
'update': True,
'success': True,
'message': _(u'A new update is available. Click on the button below to '
u'update to version: %(version)s', version=commit[0]['tag_name']),
'history': parents
})
self.updateFile = commit[0]['zipball_url']
return json.dumps(status) return json.dumps(status)
def _get_request_path(self): def _get_request_path(self):
@ -458,7 +508,7 @@ class Updater(threading.Thread):
status['current_commit_hash'] = version['version'] status['current_commit_hash'] = version['version']
try: try:
headers = {'Accept': 'application/vnd.github.v3+json'} headers = {'Accept': 'application/vnd.github.v3+json'}
r = requests.get(repository_url, headers=headers) r = requests.get(repository_url, headers=headers, timeout=10)
commit = r.json() commit = r.json()
r.raise_for_status() r.raise_for_status()
except requests.exceptions.HTTPError as e: except requests.exceptions.HTTPError as e:
@ -471,7 +521,7 @@ class Updater(threading.Thread):
status['message'] = _(u'Connection error') status['message'] = _(u'Connection error')
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
status['message'] = _(u'Timeout while establishing connection') status['message'] = _(u'Timeout while establishing connection')
except requests.exceptions.RequestException: except (requests.exceptions.RequestException, ValueError):
status['message'] = _(u'General error') status['message'] = _(u'General error')
log.debug('Updater status: %s', status['message'])
return status, commit return status, commit