1
0
Fork 0

Refactor parziale dello script. Refactor della parte getversion.

This commit is contained in:
Emiliano Vavassori 2022-04-30 16:58:00 +02:00
parent 0fae769ec0
commit c30407a244
4 changed files with 104 additions and 77 deletions

119
loaih/script.py Normal file
View file

@ -0,0 +1,119 @@
#!/usr/bin/env python
# encoding: utf-8
import click
import yaml
import loaih
import re, sys, json
@click.group()
def cli():
pass
@cli.command()
@click.option('-j', '--json', 'jsonout', default=False, is_flag=True, help="Output format in json.")
@click.argument('query')
def getversion(query, jsonout):
b = []
queries = []
if ',' in query:
queries.extend(query.split(','))
else:
queries.append(query)
for q in queries:
if '.' in q:
# Numbered version. It is safe to send it to Build.
b.append(loaih.versions.Build(q))
else:
# Named version. For safety, we call a helper method for a collection
b.extend(loaih.versions.Base.collectedbuilds(q))
if len(b) > 0:
if jsonout:
click.echo(json.dumps([x.todict() for x in b]))
else:
for v in b:
click.echo(v)
@cli.command()
@click.option('-a', '--arch', 'arch', type=click.Choice(['x86', 'x86_64', 'all'], case_sensitive=False), default='all', help="Build the AppImage for a specific architecture. If there is no specific options, the process will build for both architectures (if available). Default: all")
@click.option('-c/-C', '--check/--no-check', 'check', default=True, help="Check in the final storage if the queried version is existent. Default: check")
@click.option('-d', '--download-path', 'download_path', default = '/var/tmp/downloads', type=str, help="Path to the download folder. Default: /var/tmp/downloads")
@click.option('-l', '--language', 'language', default = 'basic', type=str, help="Languages to be included. Options: basic, standard, full, a language string (e.g. 'it') or a list of languages comma separated (e.g.: 'en-US,en-GB,it'). Default: basic")
@click.option('-o/-O', '--offline-help/--no-offline-help', 'offline', default = False, help="Include or not the offline help for the chosen languages. Default: no offline help")
@click.option('-p/-P', '--portable/--no-portable', 'portable', default = False, help="Create a portable version of the AppImage or not. Default: no portable")
@click.option('-r', '--repo-path', 'repo_path', default = '/mnt/appimage', type=str, help="Path to the final storage of the AppImage. Default: /mnt/appimage")
@click.option('-s/-S', '--sign/--no-sign', 'sign', default=True, help="Wether to sign the build. Default: sign")
@click.option('-u/-U', '--updatable/--no-updatable', 'updatable', default = True, help="Create an updatable version of the AppImage or not. Default: updatable")
@click.argument('query')
def build(arch, language, offline, portable, updatable, download_path, repo_path, check, sign, query):
# Parsing options
arches = []
if arch.lower() == 'all':
# We need to build it twice.
arches = [ u'x86', u'x86_64' ]
else:
arches = [ arch.lower() ]
if query.endswith('.yml') or query.endswith('.yaml'):
# This is a buildfile. So we have to load the file and pass the build options ourselves.
config = {}
with open(query, 'r') as file:
config = yaml.safe_load(file)
# With the config file, we ignore all the command line options and set
# generic default.
for build in config['builds']:
# Loop a run for each build.
obj = loaih.Build(build['query'], arches)
# Configuration phase
obj.language = build['language']
obj.offline_help = build['offline_help']
obj.portable = build['portable']
obj.updatable = True
obj.storage_path = config['data']['repo'] if 'repo' in config['data'] and config['data']['repo'] else '/srv/http/appimage.sys42.eu'
obj.download_path = config['data']['download'] if 'download' in config['data'] and config['data']['download'] else '/var/tmp/downloads'
if 'sign' in config['data'] and config['data']['sign']:
obj.sign = True
# Build phase
obj.calculate()
if not 'force' in config['data'] or not config['data']['force']:
obj.check()
obj.download()
obj.build()
obj.checksums()
obj.publish()
obj.generalize_and_link()
del obj
else:
obj = loaih.Build(query, arches)
# Configuration phase
obj.language = language
obj.offline_help = offline
obj.portable = portable
obj.updatable = updatable
obj.storage_path = repo_path
obj.download_path = download_path
if sign:
obj.sign = True
# Running phase
obj.calculate()
if check:
obj.check()
obj.download()
obj.build()
obj.checksums()
obj.publish()
obj.generalize_and_link()
del obj

View file

@ -36,21 +36,6 @@ class Base(object):
# Class for static methods which might be useful even outside the build
# scripts.
@staticmethod
def dailyver(date = datetime.datetime.today()):
"""Returns versions present on the latest daily build."""
url = Base.dailyurl(date)['x86_64']
# Since it is possible that a daily build is not yet provided...
if url == '-':
return []
# Rerun the page parsing, this time to find out the versions built
b = etree.HTML(urllib.request.urlopen(Base.dailyurl(date)['x86_64']).read()).xpath("//td/a[contains(text(), '_deb.tar.gz')]/text()")
# This should have returned the main package for a version, but can
# have returned multiple ones, so let's treat it as a list
return [ x.split('_')[1] for x in b ]
@staticmethod
def dailyurl(date = datetime.datetime.today()):
"""Returns the URL for the latest valid daily build."""
@ -68,6 +53,20 @@ class Base(object):
# list and get the latest item
return { 'x86': '-', 'x86_64': Definitions.SELECTORS['daily']['URL'] + sorted(a)[-1] }
@staticmethod
def dailyver(date = datetime.datetime.today()):
"""Returns versions present on the latest daily build."""
url = Base.dailyurl(date)['x86_64']
# If no daily releases has been provided yet, return empty
if url == '-':
return []
# Rerun the page parsing, this time to find out the versions built
b = etree.HTML(urllib.request.urlopen(url).read()).xpath("//td/a[contains(text(), '_deb.tar.gz')]/text()")
# This should have returned the main package for a version, but can
# have returned multiple ones, so let's treat it as a list
return [ x.split('_')[1] for x in b ]
@staticmethod
def namedver(query):
"""Gets the version for a specific named version."""
@ -87,7 +86,7 @@ class Base(object):
@staticmethod
def fullversion(version):
"""Get latest full version from Archive based on partial version."""
versionlist = etree.HTML(urllib.request.urlopen(Definitions.ARCHIVE).read()).xpath("//td/a[starts-with(text(), '" + version + "')]/text()")
versionlist = etree.HTML(urllib.request.urlopen(Definitions.ARCHIVE).read()).xpath(f"//td/a[starts-with(text(), '{version}')]/text()")
cleanlist = sorted([ x.strip('/') for x in versionlist ])
# Sorting, then returning the last version
@ -112,7 +111,7 @@ class Base(object):
# If the version has only 2 points in it (or splits into three parts by '.'), that's not a full version and we will call the getlatestver() function
fullversion = version
if len(version.split('.')) == 3:
if len(version.split('.')) <= 3:
fullversion = Base.fullversion(version)
# So the final URL is the Archive one, plus the full versions, plus a
@ -130,31 +129,67 @@ class Base(object):
return retval
@staticmethod
def collectedbuilds(query):
"""Creates a list of Builds based on each namedver found."""
retval = []
a = Base.namedver(query)
if isinstance(a, list) and len(a) > 1:
retval = [ Build(query, version) for version in Base.namedver(query) ]
else:
retval.append(Build(query))
return retval
class Build(object):
def __init__(self, query):
def __init__(self, query, version = None):
"""Should simplify the single builded version."""
self.query = query
self.version = ''
self.basedirurl = {}
self.basedirurl = { 'x86': '-', 'x86_64': '-' }
# For simplification process, let's before see if there's a named query
# (it shouldn't)
if not '.' in self.query:
# Named version. Let's get the result of the query.
a = Base.namedver(self.query)
# Named version.
# Let's check if a specific version was requested.
if version:
self.version = version
else:
# In case it was not requested, we will carry on the generic
# namedver() query.
# If the results are more than one, we'll take the latest (since we are requested to provide a single build).
a = Base.namedver(self.query)
if isinstance(a, list) and len(a) == 0:
# No results from the query - let's return default values
return
if len(a) != 1:
raise Exception("Queried version for build does not return a single result. Please unfold manually. Exiting.")
# So if it is here, the version is one.
self.query = a[0]
if len(self.query.split('.')) == 4:
self.version = self.query
if len(a) == 1:
# version is a single one.
self.version = a[0]
else:
# In this case, we will select the latest release.
self.version = sorted(a)[-1]
else:
# In case of numbered queries, put it as initial version
self.version = self.query
if len(self.version.split('.')) < 4:
# If not 4 dotted, let's search for the 4 dotted version
self.version = Base.fullversion(self.query)
self.version = Base.fullversion(self.version)
self.basedirurl = Base.urlfromqueryandver(self.query, self.version)
def todict(self):
return {
'query': self.query,
'version': self.version,
'basedirurl': self.basedirurl
}
def __str__(self):
return f"""query: {self.query}
version: {self.version}
x86: {self.basedirurl['x86']}
x86_64: {self.basedirurl['x86_64']}"""