diff --git a/daily.yml b/daily.yml index 2f2f521..09d5573 100644 --- a/daily.yml +++ b/daily.yml @@ -1,67 +1,69 @@ --- data: - repo: /mnt/appimage + repo: https://appimages.libreitalia.org + remote_host: ciccio + remote_path: /var/lib/nethserver/vhost/appimages download: /var/tmp/downloads - force: no - sign: yes + force: false + sign: true builds: - query: daily language: basic - offline_help: no - portable: no - + offline_help: false + portable: false + - query: daily language: basic - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: daily language: basic - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: daily language: basic - offline_help: yes - portable: yes + offline_help: true + portable: true - query: daily language: standard - offline_help: no - portable: no - + offline_help: false + portable: false + - query: daily language: standard - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: daily language: standard - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: daily language: standard - offline_help: yes - portable: yes + offline_help: true + portable: true - query: daily language: full - offline_help: no - portable: no - + offline_help: false + portable: false + - query: daily language: full - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: daily language: full - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: daily language: full - offline_help: yes - portable: yes + offline_help: true + portable: true diff --git a/fresh.yml b/fresh.yml index e8ba85d..2c196e1 100644 --- a/fresh.yml +++ b/fresh.yml @@ -1,67 +1,69 @@ --- data: - repo: /mnt/appimage + repo: https://appimages.libreitalia.org + remote_host: ciccio + remote_path: /var/lib/nethserver/vhost/appimages download: /var/tmp/downloads - force: no - sign: yes + force: false + sign: true builds: - query: fresh language: basic - offline_help: no - portable: no - + offline_help: false + portable: false + - query: fresh language: basic - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: fresh language: basic - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: fresh language: basic - offline_help: yes - portable: yes + offline_help: true + portable: true - query: fresh language: standard - offline_help: no - portable: no - + offline_help: false + portable: false + - query: fresh language: standard - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: fresh language: standard - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: fresh language: standard - offline_help: yes - portable: yes + offline_help: true + portable: true - query: fresh language: full - offline_help: no - portable: no - + offline_help: false + portable: false + - query: fresh language: full - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: fresh language: full - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: fresh language: full - offline_help: yes - portable: yes + offline_help: true + portable: true diff --git a/loaih/build.py b/loaih/build.py index bbd0631..29218e3 100644 --- a/loaih/build.py +++ b/loaih/build.py @@ -1,21 +1,36 @@ #!/usr/bin/env python3 +# encoding: utf-8 +"""Classes and functions to build an AppImage.""" +import os +import glob +import subprocess +import shutil +import re +import shlex +import tempfile import urllib.request -import loaih +import hashlib from lxml import etree -import tempfile, os, sys, glob, subprocess, shutil, re, shlex +import loaih class Collection(list): + """Aggregates metadata on a collection of builds.""" def __init__(self, query, arch = ['x86', 'x86_64']): """Build a list of version to check/build for this round.""" super().__init__() - self.extend([ Build(query, arch, version) for version in loaih.Base.collectedbuilds(query) ]) + self.extend([ + Build(query, arch, version) for version in loaih.Base.collectedbuilds(query) + ]) class Build(loaih.RemoteBuild): - LANGSTD = [ 'ar', 'de', 'en-GB', 'es', 'fr', 'it', 'ja', 'ko', 'pt', 'pt-BR', 'ru', 'zh-CN', 'zh-TW' ] + """Builds a single version.""" + + LANGSTD = [ 'ar', 'de', 'en-GB', 'es', 'fr', 'it', 'ja', 'ko', 'pt', + 'pt-BR', 'ru', 'zh-CN', 'zh-TW' ] LANGBASIC = [ 'en-GB' ] - ARCHSTD = [ u'x86', u'x86_64' ] + ARCHSTD = [ 'x86', 'x86_64' ] def __init__(self, query, arch, version = None): super().__init__(query, version) @@ -32,19 +47,29 @@ class Build(loaih.RemoteBuild): self.portable = False self.updatable = True self.sign = True + self.remoterepo = False + self.remote_host = '' + self.remote_path = '' self.storage_path = '/mnt/appimage' self.download_path = '/var/tmp/downloads' + self.appnamedir = '' # Specific build version + self.appname = 'LibreOffice' self.appversion = '' + self.appimagedir = '' self.appimagefilename = {} self.zsyncfilename = {} + # Other variables by build + self.languagepart = '.' + self.language + self.helppart = '' + # Creating a tempfile self.builddir = tempfile.mkdtemp() self.tarballs = {} - self.built = { u'x86': False, u'x86_64': False } - + self.built = { 'x86': False, 'x86_64': False } + # Preparing the default for the relative path on the storage for # different versions. # The path will evaluated as part of the check() function, as it is @@ -55,8 +80,12 @@ class Build(loaih.RemoteBuild): def calculate(self): """Calculate exclusions and other variables.""" + + print("--- Calculate Phase ---") + # AppName - self.appname = 'LibreOffice' if not self.query == 'daily' and not self.query == 'prerelease' else 'LibreOfficeDev' + if self.query in { 'prerelease', 'daily' }: + self.appname = 'LibreOfficeDev' # Calculating languagepart self.languagepart = "." @@ -66,7 +95,8 @@ class Build(loaih.RemoteBuild): self.languagepart += self.language # Calculating help part - self.helppart = '.help' if self.offline_help else '' + if self.offline_help: + self.helppart = '.help' # Building the required names for arch in Build.ARCHSTD: @@ -90,7 +120,7 @@ class Build(loaih.RemoteBuild): if self.query == 'daily': self.relative_path.append('daily') elif self.query == 'prerelease': - self.relative_path.append('prerelease') + self.relative_path.append('prerelease') # Not the same check, an additional one if self.portable: @@ -105,29 +135,72 @@ class Build(loaih.RemoteBuild): def check(self): """Checking if the requested AppImage has been already built.""" - if not len(self.appimagefilename) == 2: + + print("--- Check Phase ---") + + if len(self.appimagefilename) != 2: self.calculate() for arch in self.arch: - print(f"Searching for {self.appimagefilename[arch]}") - res = subprocess.run(shlex.split(f"find {self.full_path} -name {self.appimagefilename[arch]}"), capture_output=True, env={ "LC_ALL": "C" }, text=True, encoding='utf-8') - if "No such file or directory" in res.stderr: - # Folder is not existent: so the version was not built - # Build stays false, and we go to the next arch - continue + # First, check if by metadata the repo is remote or not. + if self.remoterepo or 'http' in self.storage_path: + self.remoterepo = True + # Remote storage. I have to query a remote site to know if it + # was already built. + name = self.appimagefilename[arch] + if len(self.relative_path) == 0: + path_arr = [ self.storage_path, '' ] + elif len(self.relative_path) == 1: + path_arr = [ self.storage_path, self.relative_path[0], '' ] + else: + path_arr = self.relative_path.insert(0, self.storage_path) - if res.stdout and len(res.stdout.strip("\n")) > 0: - # All good, the command was executed fine. - print(f"Build for {self.version} found.") - self.built[arch] = True + path = str.join('/', path_arr) + print(f"DEBUG - Name: {name}, URL: {path}") + matching = [] + try: + with urllib.request.urlopen(path) as url: + matching = etree.HTML(url.read()).xpath( + f"//a[contains(@href, '{name}')]/@href" + ) + + if len(matching) > 0: + # Already built. + self.built[arch] = True + + except urllib.error.HTTPError: + # The URL specified do not exist. So it is to build. + pass + + else: + # Repo is local + print(f"Searching for {self.appimagefilename[arch]}") + command = f"find {self.full_path} -name {self.appimagefilename[arch]}" + res = subprocess.run(shlex.split(command), + capture_output=True, + env={ "LC_ALL": "C" }, + text=True, encoding='utf-8', check=True) + + if "No such file or directory" in res.stderr: + # Folder is not existent: so the version was not built + # Build stays false, and we go to the next arch + continue + + if res.stdout and len(res.stdout.strip("\n")) > 0: + # All good, the command was executed fine. + print(f"Build for {self.version} found.") + self.built[arch] = True if self.built[arch]: - print(f"The requested AppImage already exists on storage for {arch}. I'll skip downloading, building and moving the results.") + print(f"The requested AppImage already exists on storage for {arch}. I'll skip downloading, building and moving the results.") def download(self): """Downloads the contents of the URL as it was a folder.""" + + print("--- Download Phase ---") + print(f"Started downloads for {self.version}. Please wait.") for arch in self.arch: # Checking if a valid path has been provided @@ -142,10 +215,15 @@ class Build(loaih.RemoteBuild): continue # Identifying downloads - contents = etree.HTML(urllib.request.urlopen(self.url[arch]).read()).xpath("//td/a") - self.tarballs[arch] = [ x.text for x in contents if x.text.endswith('tar.gz') and 'deb' in x.text ] + contents = [] + with urllib.request.urlopen(self.url[arch]) as url: + contents = etree.HTML(url.read()).xpath("//td/a") + + self.tarballs[arch] = [ x.text + for x in contents + if x.text.endswith('tar.gz') and 'deb' in x.text + ] tarballs = self.tarballs[arch] - maintarball = tarballs[0] # Create and change directory to the download location os.makedirs(self.download_path, exist_ok = True) @@ -158,14 +236,16 @@ class Build(loaih.RemoteBuild): # Download the archive try: urllib.request.urlretrieve(self.url[arch] + archive, archive) - except: - print(f"Failed to download {archive}.") + except Exception as error: + print(f"Failed to download {archive}: {error}.") print(f"Finished downloads for {self.version}.") def build(self): """Building all the versions.""" + print("--- Building Phase ---") + for arch in self.arch: if self.built[arch]: # Already built for arch or path not available. User has already been warned. @@ -187,7 +267,7 @@ class Build(loaih.RemoteBuild): def __unpackbuild__(self, arch): # We start by filtering out tarballs from the list - buildtarballs = [ self.tarballs[arch][0] ] + buildtarballs = [ self.tarballs[arch][0] ] # Let's process standard languages and append results to the # buildtarball @@ -213,50 +293,75 @@ class Build(loaih.RemoteBuild): # Looping for each language in self.language for lang in self.language.split(","): if self.offline_help: - buildtarballs.extend([ x for x in self.tarballs[arch] if ('pack' + lang) in x ]) + buildtarballs.extend([ x for x in self.tarballs[arch] + if 'pack' + lang in x ]) else: - buildtarballs.extend([ x for x in self.tarballs[arch] if ('langpack' + lang) in x ]) - + buildtarballs.extend([ x for x in self.tarballs[arch] + if 'langpack' + lang in x ]) + os.chdir(self.appnamedir) # Unpacking the tarballs for archive in buildtarballs: - subprocess.run(shlex.split(f"tar xzf {self.download_path}/{archive}")) + subprocess.run(shlex.split( + f"tar xzf {self.download_path}/{archive}"), check=True) # create appimagedir self.appimagedir = os.path.join(self.builddir, self.appname, self.appname + '.AppDir') os.makedirs(self.appimagedir, exist_ok = True) # At this point, let's decompress the deb packages - subprocess.run(shlex.split("find .. -iname '*.deb' -exec dpkg -x {} . \;"), cwd=self.appimagedir) + subprocess.run(shlex.split( + r"find .. -iname '*.deb' -exec dpkg -x {} . \;" + ), cwd=self.appimagedir, check=True) if self.portable: - subprocess.run(shlex.split("find . -type f -iname 'bootstraprc' -exec sed -i 's|^UserInstallation=.*|UserInstallation=\$SYSUSERCONFIG/libreoffice/%s|g' {} \+" % self.short_version), cwd=self.appimagedir) + subprocess.run(shlex.split( + r"find . -type f -iname 'bootstraprc' " + + r"-exec sed -i 's|^UserInstallation=.*|" + + r"UserInstallation=\$SYSUSERCONFIG/libreoffice/%s|g' {} \+" % self.short_version + ), cwd=self.appimagedir, check=True) # Changing desktop file - subprocess.run(shlex.split("find . -iname startcenter.desktop -exec cp {} . \;"), cwd=self.appimagedir) - subprocess.run(shlex.split("sed --in-place 's:^Name=.*$:Name=%s:' startcenter.desktop > startcenter.desktop" % self.appname), cwd=self.appimagedir) + subprocess.run(shlex.split( + r"find . -iname startcenter.desktop -exec cp {} . \;" + ), cwd=self.appimagedir, check=True) - subprocess.run(shlex.split("find . -name '*startcenter.png' -path '*hicolor*48x48*' -exec cp {} . \;"), cwd=self.appimagedir) + subprocess.run(shlex.split( + f"sed --in-place \'s:^Name=.*$:Name={self.appname}:\' " + + r"startcenter.desktop" + ), cwd=self.appimagedir, check=False) + + subprocess.run(shlex.split( + r"find . -name '*startcenter.png' -path '*hicolor*48x48*' " + + r"-exec cp {} . \;" + ), cwd=self.appimagedir, check=True) # Find the name of the binary called in the desktop file. binaryname = '' - with open(os.path.join(self.appimagedir, 'startcenter.desktop'), 'r') as d: - a = d.readlines() - for line in a: + with open( + os.path.join(self.appimagedir, 'startcenter.desktop'), + 'r', encoding="utf-8" + ) as desktopfile: + for line in desktopfile.readlines(): if re.match(r'^Exec', line): binaryname = line.split('=')[-1].split(' ')[0] # Esci al primo match break + #binary_exec = subprocess.run(shlex.split(r"awk 'BEGIN { FS = \"=\" } /^Exec/ { print $2; exit }' startcenter.desktop | awk '{ print $1 }'"), cwd=self.appimagedir, text=True, encoding='utf-8') #binaryname = binary_exec.stdout.strip("\n") bindir=os.path.join(self.appimagedir, 'usr', 'bin') os.makedirs(bindir, exist_ok = True) - subprocess.run(shlex.split("find ../../opt -iname soffice -path '*program*' -exec ln -sf {} ./%s \;" % binaryname), cwd=bindir) + subprocess.run(shlex.split( + r"find ../../opt -iname soffice -path '*program*' " + + r"-exec ln -sf {} ./%s \;" % binaryname + ), cwd=bindir, check=True) # Download AppRun from github - apprunurl = f"https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-{arch}" + apprunurl = r"https://github.com/AppImage/AppImageKit/releases/" + apprunurl += f"download/continuous/AppRun-{arch}" dest = os.path.join(self.appimagedir, 'AppRun') urllib.request.urlretrieve(apprunurl, dest) os.chmod(dest, 0o755) @@ -272,59 +377,111 @@ class Build(loaih.RemoteBuild): buildopts_str = str.join(' ', buildopts) # Build the number-specific build - subprocess.run(shlex.split(f"{self.appnamedir}/appimagetool {buildopts_str} -v ./{self.appname}.AppDir/"), env={ "VERSION": self.appversion }) - + subprocess.run(shlex.split( + f"{self.appnamedir}/appimagetool {buildopts_str} -v " + + f"./{self.appname}.AppDir/" + ), env={ "VERSION": self.appversion }, check=True) + print(f"Built AppImage version {self.appversion}") # Cleanup phase, before new run. for deb in glob.glob(self.appnamedir + '/*.deb'): os.remove(deb) - subprocess.run(shlex.split("find . -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} \+")) + subprocess.run(shlex.split( + r"find . -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} \+" + ), check=True) def checksums(self): """Create checksums of the built versions.""" # Skip checksum if initally the build was already found in the storage directory - if all(self.built.values()): + + print("--- Checksum Phase ---") + + if all(self.built[arch] for arch in self.arch): return os.chdir(self.appnamedir) for arch in self.arch: - for item in [ self.appimagefilename[arch], self.zsyncfilename[arch] ]: - # For any built arch, find out if a file exist. - self.__create_checksum__(item) + if not self.built[arch]: + # Here's the contrary. A newly built package has not yet been + # marked as built. + for item in [ self.appimagefilename[arch], self.zsyncfilename[arch] ]: + itempath = os.path.join(self.appnamedir, item) + if os.path.exists(itempath): + # For any built arch, find out if a file exist. + print(f"DEBUG: checkumming {item}.") + self.__create_checksum__(item) def __create_checksum__(self, file): """Internal function to create checksum file.""" - checksum = subprocess.run(shlex.split(f"md5sum {file}"), capture_output=True, text=True, encoding='utf-8') + + checksum = subprocess.run(f"md5sum {file}", shell=True, + capture_output=True, text=True, encoding='utf-8', check=True, + cwd=self.appnamedir) + if checksum.stdout: - with open(f"{file}.md5", 'w') as c: - c.write(checksum.stdout) + with open(f"{file}.md5", 'w', encoding='utf-8') as checkfile: + print(f"DEBUG: writing checksum for {file}.") + checkfile.write(checksum.stdout) + def publish(self): """Moves built versions to definitive storage.""" - if all(self.built.values()): + + print("--- Publish Phase ---") + + if all(self.built[arch] for arch in self.arch): # All files are already present in the full_path return os.chdir(self.appnamedir) - # Forcing creation of subfolders, in case there is a new build - os.makedirs(self.full_path, exist_ok = True) - for file in glob.glob("*.AppImage*"): - subprocess.run(shlex.split(f"cp -f {file} {self.full_path}")) + # Two cases here: local and remote storage_path. + if self.remoterepo: + # Remote first. + # Build destination directory + if len(self.relative_path) == 0: + remotepath = str.join('/', [ self.remote_path, '' ]) + elif len(self.relative_path) == 1: + remotepath = str.join('/', [ self.remote_path, self.relative_path[0], '' ]) + else: + remotepath = str.join('/', self.relative_path.insert(0, self.remote_path)) + try: + subprocess.run( + r"rsync -rlIvz --munge-links *.AppImage* " + + f"{self.remote_host}:{remotepath}", + cwd=self.appnamedir, shell=True, check=True + ) + finally: + pass + + else: + # Local + # Forcing creation of subfolders, in case there is a new build + os.makedirs(self.full_path, exist_ok = True) + for file in glob.glob("*.AppImage*"): + subprocess.run(shlex.split( + f"cp -f {file} {self.full_path}" + ), check=True) - def generalize_and_link(self): + def generalize_and_link(self, chdir = 'default'): """Creates the needed generalized files if needed.""" + + print("--- Generalize and Link Phase ---") + # If called with a pointed version, no generalize and link necessary. if not self.branch_version: return # If a prerelease or a daily version, either. - if self.query == 'daily' or self.query == 'prerelease': + if self.query in { 'daily', 'prerelease' }: return + if chdir == 'default': + chdir = self.full_path + appimagefilename = {} zsyncfilename = {} @@ -335,7 +492,7 @@ class Build(loaih.RemoteBuild): if self.built[arch]: continue - os.chdir(self.full_path) + os.chdir(chdir) # if the appimage for the reported arch is not found, skip to next # arch if not os.path.exists(self.appimagefilename[arch]): @@ -343,7 +500,9 @@ class Build(loaih.RemoteBuild): # Doing it both for short_name and for branchname for version in versions: - appimagefilename[arch] = self.appname + '-' + version + self.languagepart + self.helppart + f'-{arch}.AppImage' + appimagefilename[arch] = self.appname + '-' + version + appimagefilename[arch] += self.languagepart + self.helppart + appimagefilename[arch] += f'-{arch}.AppImage' zsyncfilename[arch] = appimagefilename[arch] + '.zsync' # Create the symlink @@ -362,7 +521,10 @@ class Build(loaih.RemoteBuild): os.unlink(zsyncfilename[arch]) shutil.copyfile(self.zsyncfilename[arch], zsyncfilename[arch]) # Editing the zsyncfile - subprocess.run(shlex.split(f"sed --in-place 's/^Filename:.*$/Filename: {appimagefilename[arch]}/' {zsyncfilename[arch]}")) + subprocess.run(shlex.split( + r"sed --in-place 's/^Filename:.*$/Filename: " + + f"{appimagefilename[arch]}/' {zsyncfilename[arch]}" + ), check=True) self.__create_checksum__(zsyncfilename[arch]) diff --git a/loaih/script.py b/loaih/script.py index 40ddf36..4a4ed91 100644 --- a/loaih/script.py +++ b/loaih/script.py @@ -1,76 +1,106 @@ #!/usr/bin/env python # encoding: utf-8 +"""Helps with command line commands.""" +import json import click import yaml -import loaih, loaih.build -import re, sys, json +import loaih +import loaih.build @click.group() def cli(): - pass + """Helps with command line commands.""" @cli.command() -@click.option('-j', '--json', 'jsonout', default=False, is_flag=True, help="Output format in json.") +@click.option('-j', '--json', 'jsonout', default=False, is_flag=True, + help="Output format in json.") @click.argument('query') def getversion(query, jsonout): - b = [] + """Get the numeral version from a named version.""" + + batch = [] queries = [] if ',' in query: queries.extend(query.split(',')) else: queries.append(query) - for q in queries: - b.extend(loaih.Base.collectedbuilds(q)) + for singlequery in queries: + batch.extend(loaih.Base.collectedbuilds(singlequery)) - if len(b) > 0: + if len(batch) > 0: if jsonout: - click.echo(json.dumps([x.todict() for x in b])) + click.echo(json.dumps([x.todict() for x in batch])) else: - for v in b: - click.echo(v) + for value in batch: + click.echo(value) @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.option('-a', '--arch', 'arch', default='all', + type=click.Choice(['x86', 'x86_64', 'all'], case_sensitive=False), + 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): + """Builds an Appimage with the provided options.""" + # Parsing options arches = [] if arch.lower() == 'all': # We need to build it twice. - arches = [ u'x86', u'x86_64' ] + arches = [ 'x86', '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: + with open(query, 'r', encoding= 'utf-8') 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']: + for cbuild in config['builds']: # Loop a run for each build. - collection = loaih.build.Collection(build['query'], arches) + collection = loaih.build.Collection(cbuild['query'], arches) for obj in collection: # Configuration phase - obj.language = build['language'] - obj.offline_help = build['offline_help'] - obj.portable = build['portable'] + obj.language = cbuild['language'] + obj.offline_help = cbuild['offline_help'] + obj.portable = cbuild['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' + obj.storage_path = "/srv/http/appimage.sys42.eu" + if 'repo' in config['data'] and config['data']['repo']: + obj.storage_path = config['data']['repo'] + obj.download_path = "/var/tmp/downloads" + if 'download' in config['data'] and config['data']['download']: + obj.download_path = config['data']['download'] + if 'http' in obj.storage_path: + obj.remoterepo = True + obj.remote_host = "ciccio.libreitalia.org" + if 'remote_host' in config['data'] and config['data']['remote_host']: + obj.remote_host = config['data']['remote_host'] + obj.remote_path = "/var/lib/nethserver/vhost/appimages" + if 'remote_path' in config['data'] and config['data']['remote_path']: + obj.remote_path = config['data']['remote_path'] if 'sign' in config['data'] and config['data']['sign']: obj.sign = True @@ -83,8 +113,11 @@ def build(arch, language, offline, portable, updatable, download_path, repo_path obj.download() obj.build() obj.checksums() + if obj.remoterepo and obj.appnamedir: + obj.generalize_and_link(obj.appnamedir) obj.publish() - obj.generalize_and_link() + if not obj.remoterepo: + obj.generalize_and_link() del obj else: diff --git a/prerelease.yml b/prerelease.yml index 402f385..37e0e04 100644 --- a/prerelease.yml +++ b/prerelease.yml @@ -1,67 +1,69 @@ --- data: - repo: /mnt/appimage + repo: https://appimages.libreitalia.org + remote_host: ciccio + remote_path: /var/lib/nethserver/vhost/appimages download: /var/tmp/downloads - force: no - sign: yes + force: false + sign: true builds: - query: prerelease language: basic - offline_help: no - portable: no - + offline_help: false + portable: false + - query: prerelease language: basic - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: prerelease language: basic - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: prerelease language: basic - offline_help: yes - portable: yes + offline_help: true + portable: true - query: prerelease language: standard - offline_help: no - portable: no - + offline_help: false + portable: false + - query: prerelease language: standard - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: prerelease language: standard - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: prerelease language: standard - offline_help: yes - portable: yes + offline_help: true + portable: true - query: prerelease language: full - offline_help: no - portable: no - + offline_help: false + portable: false + - query: prerelease language: full - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: prerelease language: full - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: prerelease language: full - offline_help: yes - portable: yes + offline_help: true + portable: true diff --git a/setup.py b/setup.py index c41059f..23029eb 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,13 @@ #!/usr/bin/env python # encoding: utf-8 # vim:sts=4:sw=4 +"""Helps building and automatizing building LibreOffice AppImages.""" from setuptools import setup,find_packages setup( name="loaih", - version="1.2.0", + version="1.3.0", description="LOAIH - LibreOffice AppImage Helpers, help build a LibreOffice AppImage", author="Emiliano Vavassori", author_email="syntaxerrormmm@libreoffice.org", diff --git a/still.yml b/still.yml index 3f5a595..6fdb968 100644 --- a/still.yml +++ b/still.yml @@ -1,67 +1,69 @@ --- data: - repo: /mnt/appimage + repo: https://appimages.libreitalia.org + remote_host: ciccio + remote_path: /var/lib/nethserver/vhost/appimages download: /var/tmp/downloads - force: no - sign: yes + force: false + sign: true builds: - query: still language: basic - offline_help: no - portable: no - + offline_help: false + portable: false + - query: still language: basic - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: still language: basic - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: still language: basic - offline_help: yes - portable: yes + offline_help: true + portable: true - query: still language: standard - offline_help: no - portable: no - + offline_help: false + portable: false + - query: still language: standard - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: still language: standard - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: still language: standard - offline_help: yes - portable: yes + offline_help: true + portable: true - query: still language: full - offline_help: no - portable: no - + offline_help: false + portable: false + - query: still language: full - offline_help: yes - portable: no - + offline_help: true + portable: false + - query: still language: full - offline_help: no - portable: yes - + offline_help: false + portable: true + - query: still language: full - offline_help: yes - portable: yes + offline_help: true + portable: true diff --git a/test.yml b/test.yml index faf4464..8fcf1d7 100644 --- a/test.yml +++ b/test.yml @@ -1,12 +1,14 @@ --- data: - repo: /mnt/appimage + repo: https://appimages.libreitalia.org + remote_host: ciccio + remote_path: /var/lib/nethserver/vhost/appimages download: /var/tmp/downloads - force: yes - sign: yes + force: true + sign: true builds: - - query: fresh + - query: 7.2.3 language: basic - offline_help: no - portable: no + offline_help: false + portable: false