1
0
Fork 0

Compare commits

..

No commits in common. "78a43350ed22b1fb68c7c7ee6e8bb780420a9108" and "2c19eefa056d0170e0ce18711c495d6f9c0d597a" have entirely different histories.

8 changed files with 243 additions and 449 deletions

View file

@ -1,69 +1,67 @@
--- ---
data: data:
repo: https://appimages.libreitalia.org repo: /mnt/appimage
remote_host: ciccio
remote_path: /var/lib/nethserver/vhost/appimages
download: /var/tmp/downloads download: /var/tmp/downloads
force: false force: no
sign: true sign: yes
builds: builds:
- query: daily - query: daily
language: basic language: basic
offline_help: false offline_help: no
portable: false portable: no
- query: daily - query: daily
language: basic language: basic
offline_help: true offline_help: yes
portable: false portable: no
- query: daily - query: daily
language: basic language: basic
offline_help: false offline_help: no
portable: true portable: yes
- query: daily - query: daily
language: basic language: basic
offline_help: true offline_help: yes
portable: true portable: yes
- query: daily - query: daily
language: standard language: standard
offline_help: false offline_help: no
portable: false portable: no
- query: daily - query: daily
language: standard language: standard
offline_help: true offline_help: yes
portable: false portable: no
- query: daily - query: daily
language: standard language: standard
offline_help: false offline_help: no
portable: true portable: yes
- query: daily - query: daily
language: standard language: standard
offline_help: true offline_help: yes
portable: true portable: yes
- query: daily - query: daily
language: full language: full
offline_help: false offline_help: no
portable: false portable: no
- query: daily - query: daily
language: full language: full
offline_help: true offline_help: yes
portable: false portable: no
- query: daily - query: daily
language: full language: full
offline_help: false offline_help: no
portable: true portable: yes
- query: daily - query: daily
language: full language: full
offline_help: true offline_help: yes
portable: true portable: yes

View file

@ -1,69 +1,67 @@
--- ---
data: data:
repo: https://appimages.libreitalia.org repo: /mnt/appimage
remote_host: ciccio
remote_path: /var/lib/nethserver/vhost/appimages
download: /var/tmp/downloads download: /var/tmp/downloads
force: false force: no
sign: true sign: yes
builds: builds:
- query: fresh - query: fresh
language: basic language: basic
offline_help: false offline_help: no
portable: false portable: no
- query: fresh - query: fresh
language: basic language: basic
offline_help: true offline_help: yes
portable: false portable: no
- query: fresh - query: fresh
language: basic language: basic
offline_help: false offline_help: no
portable: true portable: yes
- query: fresh - query: fresh
language: basic language: basic
offline_help: true offline_help: yes
portable: true portable: yes
- query: fresh - query: fresh
language: standard language: standard
offline_help: false offline_help: no
portable: false portable: no
- query: fresh - query: fresh
language: standard language: standard
offline_help: true offline_help: yes
portable: false portable: no
- query: fresh - query: fresh
language: standard language: standard
offline_help: false offline_help: no
portable: true portable: yes
- query: fresh - query: fresh
language: standard language: standard
offline_help: true offline_help: yes
portable: true portable: yes
- query: fresh - query: fresh
language: full language: full
offline_help: false offline_help: no
portable: false portable: no
- query: fresh - query: fresh
language: full language: full
offline_help: true offline_help: yes
portable: false portable: no
- query: fresh - query: fresh
language: full language: full
offline_help: false offline_help: no
portable: true portable: yes
- query: fresh - query: fresh
language: full language: full
offline_help: true offline_help: yes
portable: true portable: yes

View file

@ -1,36 +1,21 @@
#!/usr/bin/env python3 #!/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 urllib.request
import hashlib
from lxml import etree
import loaih import loaih
from lxml import etree
import tempfile, os, sys, glob, subprocess, shutil, re, shlex
class Collection(list): class Collection(list):
"""Aggregates metadata on a collection of builds."""
def __init__(self, query, arch = ['x86', 'x86_64']): def __init__(self, query, arch = ['x86', 'x86_64']):
"""Build a list of version to check/build for this round.""" """Build a list of version to check/build for this round."""
super().__init__() super().__init__()
self.extend([ self.extend([ Build(query, arch, version) for version in loaih.Base.collectedbuilds(query) ])
Build(query, arch, version) for version in loaih.Base.collectedbuilds(query)
])
class Build(loaih.RemoteBuild): class Build(loaih.RemoteBuild):
"""Builds a single version.""" LANGSTD = [ 'ar', 'de', 'en-GB', 'es', 'fr', 'it', 'ja', 'ko', 'pt', 'pt-BR', 'ru', 'zh-CN', 'zh-TW' ]
LANGSTD = [ 'ar', 'de', 'en-GB', 'es', 'fr', 'it', 'ja', 'ko', 'pt',
'pt-BR', 'ru', 'zh-CN', 'zh-TW' ]
LANGBASIC = [ 'en-GB' ] LANGBASIC = [ 'en-GB' ]
ARCHSTD = [ 'x86', 'x86_64' ] ARCHSTD = [ u'x86', u'x86_64' ]
def __init__(self, query, arch, version = None): def __init__(self, query, arch, version = None):
super().__init__(query, version) super().__init__(query, version)
@ -47,29 +32,19 @@ class Build(loaih.RemoteBuild):
self.portable = False self.portable = False
self.updatable = True self.updatable = True
self.sign = True self.sign = True
self.remoterepo = False
self.remote_host = ''
self.remote_path = ''
self.storage_path = '/mnt/appimage' self.storage_path = '/mnt/appimage'
self.download_path = '/var/tmp/downloads' self.download_path = '/var/tmp/downloads'
self.appnamedir = ''
# Specific build version # Specific build version
self.appname = 'LibreOffice'
self.appversion = '' self.appversion = ''
self.appimagedir = ''
self.appimagefilename = {} self.appimagefilename = {}
self.zsyncfilename = {} self.zsyncfilename = {}
# Other variables by build
self.languagepart = '.' + self.language
self.helppart = ''
# Creating a tempfile # Creating a tempfile
self.builddir = tempfile.mkdtemp() self.builddir = tempfile.mkdtemp()
self.tarballs = {} self.tarballs = {}
self.built = { 'x86': False, 'x86_64': False } self.built = { u'x86': False, u'x86_64': False }
# Preparing the default for the relative path on the storage for # Preparing the default for the relative path on the storage for
# different versions. # different versions.
# The path will evaluated as part of the check() function, as it is # The path will evaluated as part of the check() function, as it is
@ -80,12 +55,8 @@ class Build(loaih.RemoteBuild):
def calculate(self): def calculate(self):
"""Calculate exclusions and other variables.""" """Calculate exclusions and other variables."""
print("--- Calculate Phase ---")
# AppName # AppName
if self.query in { 'prerelease', 'daily' }: self.appname = 'LibreOffice' if not self.query == 'daily' and not self.query == 'prerelease' else 'LibreOfficeDev'
self.appname = 'LibreOfficeDev'
# Calculating languagepart # Calculating languagepart
self.languagepart = "." self.languagepart = "."
@ -95,8 +66,7 @@ class Build(loaih.RemoteBuild):
self.languagepart += self.language self.languagepart += self.language
# Calculating help part # Calculating help part
if self.offline_help: self.helppart = '.help' if self.offline_help else ''
self.helppart = '.help'
# Building the required names # Building the required names
for arch in Build.ARCHSTD: for arch in Build.ARCHSTD:
@ -120,7 +90,7 @@ class Build(loaih.RemoteBuild):
if self.query == 'daily': if self.query == 'daily':
self.relative_path.append('daily') self.relative_path.append('daily')
elif self.query == 'prerelease': elif self.query == 'prerelease':
self.relative_path.append('prerelease') self.relative_path.append('prerelease')
# Not the same check, an additional one # Not the same check, an additional one
if self.portable: if self.portable:
@ -135,72 +105,29 @@ class Build(loaih.RemoteBuild):
def check(self): def check(self):
"""Checking if the requested AppImage has been already built.""" """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() self.calculate()
for arch in self.arch: 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')
# First, check if by metadata the repo is remote or not. if "No such file or directory" in res.stderr:
if self.remoterepo or 'http' in self.storage_path: # Folder is not existent: so the version was not built
self.remoterepo = True # Build stays false, and we go to the next arch
# Remote storage. I have to query a remote site to know if it continue
# 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)
path = str.join('/', path_arr) if res.stdout and len(res.stdout.strip("\n")) > 0:
print(f"DEBUG - Name: {name}, URL: {path}") # All good, the command was executed fine.
matching = [] print(f"Build for {self.version} found.")
try: self.built[arch] = True
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]: 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): def download(self):
"""Downloads the contents of the URL as it was a folder.""" """Downloads the contents of the URL as it was a folder."""
print("--- Download Phase ---")
print(f"Started downloads for {self.version}. Please wait.") print(f"Started downloads for {self.version}. Please wait.")
for arch in self.arch: for arch in self.arch:
# Checking if a valid path has been provided # Checking if a valid path has been provided
@ -215,15 +142,10 @@ class Build(loaih.RemoteBuild):
continue continue
# Identifying downloads # Identifying downloads
contents = [] contents = etree.HTML(urllib.request.urlopen(self.url[arch]).read()).xpath("//td/a")
with urllib.request.urlopen(self.url[arch]) as url: self.tarballs[arch] = [ x.text for x in contents if x.text.endswith('tar.gz') and 'deb' in x.text ]
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] tarballs = self.tarballs[arch]
maintarball = tarballs[0]
# Create and change directory to the download location # Create and change directory to the download location
os.makedirs(self.download_path, exist_ok = True) os.makedirs(self.download_path, exist_ok = True)
@ -236,16 +158,14 @@ class Build(loaih.RemoteBuild):
# Download the archive # Download the archive
try: try:
urllib.request.urlretrieve(self.url[arch] + archive, archive) urllib.request.urlretrieve(self.url[arch] + archive, archive)
except Exception as error: except:
print(f"Failed to download {archive}: {error}.") print(f"Failed to download {archive}.")
print(f"Finished downloads for {self.version}.") print(f"Finished downloads for {self.version}.")
def build(self): def build(self):
"""Building all the versions.""" """Building all the versions."""
print("--- Building Phase ---")
for arch in self.arch: for arch in self.arch:
if self.built[arch]: if self.built[arch]:
# Already built for arch or path not available. User has already been warned. # Already built for arch or path not available. User has already been warned.
@ -267,7 +187,7 @@ class Build(loaih.RemoteBuild):
def __unpackbuild__(self, arch): def __unpackbuild__(self, arch):
# We start by filtering out tarballs from the list # 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 # Let's process standard languages and append results to the
# buildtarball # buildtarball
@ -293,75 +213,50 @@ class Build(loaih.RemoteBuild):
# Looping for each language in self.language # Looping for each language in self.language
for lang in self.language.split(","): for lang in self.language.split(","):
if self.offline_help: if self.offline_help:
buildtarballs.extend([ x for x in self.tarballs[arch] buildtarballs.extend([ x for x in self.tarballs[arch] if ('pack' + lang) in x ])
if 'pack' + lang in x ])
else: else:
buildtarballs.extend([ x for x in self.tarballs[arch] buildtarballs.extend([ x for x in self.tarballs[arch] if ('langpack' + lang) in x ])
if 'langpack' + lang in x ])
os.chdir(self.appnamedir) os.chdir(self.appnamedir)
# Unpacking the tarballs # Unpacking the tarballs
for archive in buildtarballs: for archive in buildtarballs:
subprocess.run(shlex.split( subprocess.run(shlex.split(f"tar xzf {self.download_path}/{archive}"))
f"tar xzf {self.download_path}/{archive}"), check=True)
# create appimagedir # create appimagedir
self.appimagedir = os.path.join(self.builddir, self.appname, self.appname + '.AppDir') self.appimagedir = os.path.join(self.builddir, self.appname, self.appname + '.AppDir')
os.makedirs(self.appimagedir, exist_ok = True) os.makedirs(self.appimagedir, exist_ok = True)
# At this point, let's decompress the deb packages # At this point, let's decompress the deb packages
subprocess.run(shlex.split( subprocess.run(shlex.split("find .. -iname '*.deb' -exec dpkg -x {} . \;"), cwd=self.appimagedir)
r"find .. -iname '*.deb' -exec dpkg -x {} . \;"
), cwd=self.appimagedir, check=True)
if self.portable: if self.portable:
subprocess.run(shlex.split( 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)
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 # Changing desktop file
subprocess.run(shlex.split( subprocess.run(shlex.split("find . -iname startcenter.desktop -exec cp {} . \;"), cwd=self.appimagedir)
r"find . -iname startcenter.desktop -exec cp {} . \;" subprocess.run(shlex.split("sed --in-place 's:^Name=.*$:Name=%s:' startcenter.desktop > startcenter.desktop" % self.appname), cwd=self.appimagedir)
), cwd=self.appimagedir, check=True)
subprocess.run(shlex.split( subprocess.run(shlex.split("find . -name '*startcenter.png' -path '*hicolor*48x48*' -exec cp {} . \;"), cwd=self.appimagedir)
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. # Find the name of the binary called in the desktop file.
binaryname = '' binaryname = ''
with open( with open(os.path.join(self.appimagedir, 'startcenter.desktop'), 'r') as d:
os.path.join(self.appimagedir, 'startcenter.desktop'), a = d.readlines()
'r', encoding="utf-8" for line in a:
) as desktopfile:
for line in desktopfile.readlines():
if re.match(r'^Exec', line): if re.match(r'^Exec', line):
binaryname = line.split('=')[-1].split(' ')[0] binaryname = line.split('=')[-1].split(' ')[0]
# Esci al primo match # Esci al primo match
break 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') #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") #binaryname = binary_exec.stdout.strip("\n")
bindir=os.path.join(self.appimagedir, 'usr', 'bin') bindir=os.path.join(self.appimagedir, 'usr', 'bin')
os.makedirs(bindir, exist_ok = True) os.makedirs(bindir, exist_ok = True)
subprocess.run(shlex.split( subprocess.run(shlex.split("find ../../opt -iname soffice -path '*program*' -exec ln -sf {} ./%s \;" % binaryname), cwd=bindir)
r"find ../../opt -iname soffice -path '*program*' " +
r"-exec ln -sf {} ./%s \;" % binaryname
), cwd=bindir, check=True)
# Download AppRun from github # Download AppRun from github
apprunurl = r"https://github.com/AppImage/AppImageKit/releases/" apprunurl = f"https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-{arch}"
apprunurl += f"download/continuous/AppRun-{arch}"
dest = os.path.join(self.appimagedir, 'AppRun') dest = os.path.join(self.appimagedir, 'AppRun')
urllib.request.urlretrieve(apprunurl, dest) urllib.request.urlretrieve(apprunurl, dest)
os.chmod(dest, 0o755) os.chmod(dest, 0o755)
@ -377,111 +272,59 @@ class Build(loaih.RemoteBuild):
buildopts_str = str.join(' ', buildopts) buildopts_str = str.join(' ', buildopts)
# Build the number-specific build # Build the number-specific build
subprocess.run(shlex.split( subprocess.run(shlex.split(f"{self.appnamedir}/appimagetool {buildopts_str} -v ./{self.appname}.AppDir/"), env={ "VERSION": self.appversion })
f"{self.appnamedir}/appimagetool {buildopts_str} -v " +
f"./{self.appname}.AppDir/"
), env={ "VERSION": self.appversion }, check=True)
print(f"Built AppImage version {self.appversion}") print(f"Built AppImage version {self.appversion}")
# Cleanup phase, before new run. # Cleanup phase, before new run.
for deb in glob.glob(self.appnamedir + '/*.deb'): for deb in glob.glob(self.appnamedir + '/*.deb'):
os.remove(deb) os.remove(deb)
subprocess.run(shlex.split( subprocess.run(shlex.split("find . -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} \+"))
r"find . -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} \+"
), check=True)
def checksums(self): def checksums(self):
"""Create checksums of the built versions.""" """Create checksums of the built versions."""
# Skip checksum if initally the build was already found in the storage directory # 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 return
os.chdir(self.appnamedir) os.chdir(self.appnamedir)
for arch in self.arch: for arch in self.arch:
if not self.built[arch]: for item in [ self.appimagefilename[arch], self.zsyncfilename[arch] ]:
# Here's the contrary. A newly built package has not yet been # For any built arch, find out if a file exist.
# marked as built. self.__create_checksum__(item)
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): def __create_checksum__(self, file):
"""Internal function to create checksum 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: if checksum.stdout:
with open(f"{file}.md5", 'w', encoding='utf-8') as checkfile: with open(f"{file}.md5", 'w') as c:
print(f"DEBUG: writing checksum for {file}.") c.write(checksum.stdout)
checkfile.write(checksum.stdout)
def publish(self): def publish(self):
"""Moves built versions to definitive storage.""" """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 # All files are already present in the full_path
return return
os.chdir(self.appnamedir) os.chdir(self.appnamedir)
# Two cases here: local and remote storage_path. # Forcing creation of subfolders, in case there is a new build
if self.remoterepo: os.makedirs(self.full_path, exist_ok = True)
# Remote first. for file in glob.glob("*.AppImage*"):
# Build destination directory subprocess.run(shlex.split(f"cp -f {file} {self.full_path}"))
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, chdir = 'default'): def generalize_and_link(self):
"""Creates the needed generalized files if needed.""" """Creates the needed generalized files if needed."""
print("--- Generalize and Link Phase ---")
# If called with a pointed version, no generalize and link necessary. # If called with a pointed version, no generalize and link necessary.
if not self.branch_version: if not self.branch_version:
return return
# If a prerelease or a daily version, either. # If a prerelease or a daily version, either.
if self.query in { 'daily', 'prerelease' }: if self.query == 'daily' or self.query == 'prerelease':
return return
if chdir == 'default':
chdir = self.full_path
appimagefilename = {} appimagefilename = {}
zsyncfilename = {} zsyncfilename = {}
@ -492,7 +335,7 @@ class Build(loaih.RemoteBuild):
if self.built[arch]: if self.built[arch]:
continue continue
os.chdir(chdir) os.chdir(self.full_path)
# if the appimage for the reported arch is not found, skip to next # if the appimage for the reported arch is not found, skip to next
# arch # arch
if not os.path.exists(self.appimagefilename[arch]): if not os.path.exists(self.appimagefilename[arch]):
@ -500,9 +343,7 @@ class Build(loaih.RemoteBuild):
# Doing it both for short_name and for branchname # Doing it both for short_name and for branchname
for version in versions: for version in versions:
appimagefilename[arch] = self.appname + '-' + version appimagefilename[arch] = self.appname + '-' + version + self.languagepart + self.helppart + f'-{arch}.AppImage'
appimagefilename[arch] += self.languagepart + self.helppart
appimagefilename[arch] += f'-{arch}.AppImage'
zsyncfilename[arch] = appimagefilename[arch] + '.zsync' zsyncfilename[arch] = appimagefilename[arch] + '.zsync'
# Create the symlink # Create the symlink
@ -521,10 +362,7 @@ class Build(loaih.RemoteBuild):
os.unlink(zsyncfilename[arch]) os.unlink(zsyncfilename[arch])
shutil.copyfile(self.zsyncfilename[arch], zsyncfilename[arch]) shutil.copyfile(self.zsyncfilename[arch], zsyncfilename[arch])
# Editing the zsyncfile # Editing the zsyncfile
subprocess.run(shlex.split( subprocess.run(shlex.split(f"sed --in-place 's/^Filename:.*$/Filename: {appimagefilename[arch]}/' {zsyncfilename[arch]}"))
r"sed --in-place 's/^Filename:.*$/Filename: " +
f"{appimagefilename[arch]}/' {zsyncfilename[arch]}"
), check=True)
self.__create_checksum__(zsyncfilename[arch]) self.__create_checksum__(zsyncfilename[arch])

View file

@ -1,106 +1,76 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""Helps with command line commands."""
import json
import click import click
import yaml import yaml
import loaih import loaih, loaih.build
import loaih.build import re, sys, json
@click.group() @click.group()
def cli(): def cli():
"""Helps with command line commands.""" pass
@cli.command() @cli.command()
@click.option('-j', '--json', 'jsonout', default=False, is_flag=True, @click.option('-j', '--json', 'jsonout', default=False, is_flag=True, help="Output format in json.")
help="Output format in json.")
@click.argument('query') @click.argument('query')
def getversion(query, jsonout): def getversion(query, jsonout):
"""Get the numeral version from a named version.""" b = []
batch = []
queries = [] queries = []
if ',' in query: if ',' in query:
queries.extend(query.split(',')) queries.extend(query.split(','))
else: else:
queries.append(query) queries.append(query)
for singlequery in queries: for q in queries:
batch.extend(loaih.Base.collectedbuilds(singlequery)) b.extend(loaih.Base.collectedbuilds(q))
if len(batch) > 0: if len(b) > 0:
if jsonout: if jsonout:
click.echo(json.dumps([x.todict() for x in batch])) click.echo(json.dumps([x.todict() for x in b]))
else: else:
for value in batch: for v in b:
click.echo(value) click.echo(v)
@cli.command() @cli.command()
@click.option('-a', '--arch', 'arch', default='all', @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")
type=click.Choice(['x86', 'x86_64', 'all'], case_sensitive=False), @click.option('-c/-C', '--check/--no-check', 'check', default=True, help="Check in the final storage if the queried version is existent. Default: check")
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('-d', '--download-path', 'download_path', default = '/var/tmp/downloads', type=str, help="Path to the download folder. Default: /var/tmp/downloads")
@click.option('-c/-C', '--check/--no-check', 'check', default=True, @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")
help="Check in the final storage if the queried version is existent. Default: check") @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('-d', '--download-path', 'download_path', @click.option('-p/-P', '--portable/--no-portable', 'portable', default = False, help="Create a portable version of the AppImage or not. Default: no portable")
default = '/var/tmp/downloads', type=str, @click.option('-r', '--repo-path', 'repo_path', default = '/mnt/appimage', type=str, help="Path to the final storage of the AppImage. Default: /mnt/appimage")
help="Path to the download folder. Default: /var/tmp/downloads") @click.option('-s/-S', '--sign/--no-sign', 'sign', default=True, help="Wether to sign the build. Default: sign")
@click.option('-l', '--language', 'language', default = 'basic', type=str, @click.option('-u/-U', '--updatable/--no-updatable', 'updatable', default = True, help="Create an updatable version of the AppImage or not. Default: updatable")
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') @click.argument('query')
def build(arch, language, offline, portable, updatable, download_path, repo_path, check, sign, query): def build(arch, language, offline, portable, updatable, download_path, repo_path, check, sign, query):
"""Builds an Appimage with the provided options."""
# Parsing options # Parsing options
arches = [] arches = []
if arch.lower() == 'all': if arch.lower() == 'all':
# We need to build it twice. # We need to build it twice.
arches = [ 'x86', 'x86_64' ] arches = [ u'x86', u'x86_64' ]
else: else:
arches = [ arch.lower() ] arches = [ arch.lower() ]
if query.endswith('.yml') or query.endswith('.yaml'): 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. # This is a buildfile. So we have to load the file and pass the build options ourselves.
config = {} config = {}
with open(query, 'r', encoding= 'utf-8') as file: with open(query, 'r') as file:
config = yaml.safe_load(file) config = yaml.safe_load(file)
# With the config file, we ignore all the command line options and set # With the config file, we ignore all the command line options and set
# generic default. # generic default.
for cbuild in config['builds']: for build in config['builds']:
# Loop a run for each build. # Loop a run for each build.
collection = loaih.build.Collection(cbuild['query'], arches) collection = loaih.build.Collection(build['query'], arches)
for obj in collection: for obj in collection:
# Configuration phase # Configuration phase
obj.language = cbuild['language'] obj.language = build['language']
obj.offline_help = cbuild['offline_help'] obj.offline_help = build['offline_help']
obj.portable = cbuild['portable'] obj.portable = build['portable']
obj.updatable = True obj.updatable = True
obj.storage_path = "/srv/http/appimage.sys42.eu" obj.storage_path = config['data']['repo'] if 'repo' in config['data'] and config['data']['repo'] else '/srv/http/appimage.sys42.eu'
if 'repo' in config['data'] and config['data']['repo']: obj.download_path = config['data']['download'] if 'download' in config['data'] and config['data']['download'] else '/var/tmp/downloads'
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']: if 'sign' in config['data'] and config['data']['sign']:
obj.sign = True obj.sign = True
@ -113,11 +83,8 @@ def build(arch, language, offline, portable, updatable, download_path, repo_path
obj.download() obj.download()
obj.build() obj.build()
obj.checksums() obj.checksums()
if obj.remoterepo and obj.appnamedir:
obj.generalize_and_link(obj.appnamedir)
obj.publish() obj.publish()
if not obj.remoterepo: obj.generalize_and_link()
obj.generalize_and_link()
del obj del obj
else: else:

View file

@ -1,69 +1,67 @@
--- ---
data: data:
repo: https://appimages.libreitalia.org repo: /mnt/appimage
remote_host: ciccio
remote_path: /var/lib/nethserver/vhost/appimages
download: /var/tmp/downloads download: /var/tmp/downloads
force: false force: no
sign: true sign: yes
builds: builds:
- query: prerelease - query: prerelease
language: basic language: basic
offline_help: false offline_help: no
portable: false portable: no
- query: prerelease - query: prerelease
language: basic language: basic
offline_help: true offline_help: yes
portable: false portable: no
- query: prerelease - query: prerelease
language: basic language: basic
offline_help: false offline_help: no
portable: true portable: yes
- query: prerelease - query: prerelease
language: basic language: basic
offline_help: true offline_help: yes
portable: true portable: yes
- query: prerelease - query: prerelease
language: standard language: standard
offline_help: false offline_help: no
portable: false portable: no
- query: prerelease - query: prerelease
language: standard language: standard
offline_help: true offline_help: yes
portable: false portable: no
- query: prerelease - query: prerelease
language: standard language: standard
offline_help: false offline_help: no
portable: true portable: yes
- query: prerelease - query: prerelease
language: standard language: standard
offline_help: true offline_help: yes
portable: true portable: yes
- query: prerelease - query: prerelease
language: full language: full
offline_help: false offline_help: no
portable: false portable: no
- query: prerelease - query: prerelease
language: full language: full
offline_help: true offline_help: yes
portable: false portable: no
- query: prerelease - query: prerelease
language: full language: full
offline_help: false offline_help: no
portable: true portable: yes
- query: prerelease - query: prerelease
language: full language: full
offline_help: true offline_help: yes
portable: true portable: yes

View file

@ -1,13 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
# vim:sts=4:sw=4 # vim:sts=4:sw=4
"""Helps building and automatizing building LibreOffice AppImages."""
from setuptools import setup,find_packages from setuptools import setup,find_packages
setup( setup(
name="loaih", name="loaih",
version="1.3.0", version="1.2.0",
description="LOAIH - LibreOffice AppImage Helpers, help build a LibreOffice AppImage", description="LOAIH - LibreOffice AppImage Helpers, help build a LibreOffice AppImage",
author="Emiliano Vavassori", author="Emiliano Vavassori",
author_email="syntaxerrormmm@libreoffice.org", author_email="syntaxerrormmm@libreoffice.org",

View file

@ -1,69 +1,67 @@
--- ---
data: data:
repo: https://appimages.libreitalia.org repo: /mnt/appimage
remote_host: ciccio
remote_path: /var/lib/nethserver/vhost/appimages
download: /var/tmp/downloads download: /var/tmp/downloads
force: false force: no
sign: true sign: yes
builds: builds:
- query: still - query: still
language: basic language: basic
offline_help: false offline_help: no
portable: false portable: no
- query: still - query: still
language: basic language: basic
offline_help: true offline_help: yes
portable: false portable: no
- query: still - query: still
language: basic language: basic
offline_help: false offline_help: no
portable: true portable: yes
- query: still - query: still
language: basic language: basic
offline_help: true offline_help: yes
portable: true portable: yes
- query: still - query: still
language: standard language: standard
offline_help: false offline_help: no
portable: false portable: no
- query: still - query: still
language: standard language: standard
offline_help: true offline_help: yes
portable: false portable: no
- query: still - query: still
language: standard language: standard
offline_help: false offline_help: no
portable: true portable: yes
- query: still - query: still
language: standard language: standard
offline_help: true offline_help: yes
portable: true portable: yes
- query: still - query: still
language: full language: full
offline_help: false offline_help: no
portable: false portable: no
- query: still - query: still
language: full language: full
offline_help: true offline_help: yes
portable: false portable: no
- query: still - query: still
language: full language: full
offline_help: false offline_help: no
portable: true portable: yes
- query: still - query: still
language: full language: full
offline_help: true offline_help: yes
portable: true portable: yes

View file

@ -1,14 +1,12 @@
--- ---
data: data:
repo: https://appimages.libreitalia.org repo: /mnt/appimage
remote_host: ciccio
remote_path: /var/lib/nethserver/vhost/appimages
download: /var/tmp/downloads download: /var/tmp/downloads
force: true force: yes
sign: true sign: yes
builds: builds:
- query: 7.2.3 - query: fresh
language: basic language: basic
offline_help: false offline_help: no
portable: false portable: no