1
0
Fork 0

Compare commits

...

38 Commits
v1.2.0 ... main

Author SHA1 Message Date
Emiliano Vavassori b087e85ec5 Semplificati alcuni messaggi nell'output.
continuous-integration/drone/push Build is passing Details
2023-01-07 23:22:35 +01:00
Emiliano Vavassori 3a9f13594c Fix probabilmente definitivo.
continuous-integration/drone/push Build is passing Details
2023-01-07 23:08:33 +01:00
Emiliano Vavassori 1f83db6105 Ristrutturazione codice di verifica.
continuous-integration/drone/push Build is passing Details
2023-01-07 22:57:15 +01:00
Emiliano Vavassori 8b5c87f801 Correzioni su full path.
continuous-integration/drone/push Build is passing Details
2023-01-07 22:52:11 +01:00
Emiliano Vavassori 0bea7a81bc Correzione di un paio di errori di sintassi sui percorsi multipli.
continuous-integration/drone/push Build is passing Details
2023-01-07 22:17:18 +01:00
Emiliano Vavassori 78a43350ed Cambio versione loaih.
continuous-integration/drone/push Build is passing Details
2023-01-07 21:48:24 +01:00
Emiliano Vavassori 8c3e649a25 Correzione file yaml per le build.
continuous-integration/drone/push Build is passing Details
2023-01-07 21:46:40 +01:00
Emiliano Vavassori db01651251 Gestito errore di verifica delle build con cartella quando non trovate.
continuous-integration/drone/push Build is passing Details
2023-01-07 02:23:34 +01:00
Emiliano Vavassori 64effab3d7 Corrette tutte le occorrenze di variabile rinominata.
continuous-integration/drone/push Build is passing Details
2023-01-07 02:06:05 +01:00
Emiliano Vavassori 0a3f475fa6 script è linted. Corretto codice in check su build.
continuous-integration/drone/push Build is passing Details
2023-01-07 02:03:31 +01:00
Emiliano Vavassori 03620cf013 Correzione append percorsi.
continuous-integration/drone/push Build is passing Details
2023-01-07 01:37:17 +01:00
Emiliano Vavassori c015aeea99 Correzione codice checksum.
continuous-integration/drone/push Build is passing Details
2023-01-07 01:25:32 +01:00
Emiliano Vavassori 0a18586201 Aggiunta testo per fasi. Rivista procedura.
continuous-integration/drone/push Build is passing Details
2023-01-07 01:03:21 +01:00
Emiliano Vavassori 5df2c5dbdb Ancora sul build. Aggiunte stringhe per debugging. 2023-01-07 00:59:38 +01:00
Emiliano Vavassori 41dcbe1718 Aggiunto codice per debug, corretto lancio comando di checksum.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:52:21 +01:00
Emiliano Vavassori 2405601d2d Sistemato codice per build.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:46:45 +01:00
Emiliano Vavassori dff74f0a35 Ripristinate istruzioni originali, con chiamata a comando locale.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:30:56 +01:00
Emiliano Vavassori 6bfa6a3707 Ancora correzioni al processo di checksum.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:24:35 +01:00
Emiliano Vavassori 059518ccbf Ancora qualche correzione al codice per generare checksum.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:20:56 +01:00
Emiliano Vavassori 7013318188 Sostituito lancio programma con codice python.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:15:42 +01:00
Emiliano Vavassori f6bcf610ba Correzione md5.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:07:03 +01:00
Emiliano Vavassori 3aab2626ed Correzione script.
continuous-integration/drone/push Build is passing Details
2023-01-07 00:02:20 +01:00
Emiliano Vavassori df079c91b5 Correzione pubblicazione.
continuous-integration/drone/push Build is passing Details
2023-01-06 23:55:30 +01:00
Emiliano Vavassori a0c4fbcad0 Correzione rsync.
continuous-integration/drone/push Build is passing Details
2023-01-06 23:39:29 +01:00
Emiliano Vavassori a316b85afe Correzione comando sbagliato da console - 1.
continuous-integration/drone/push Build is passing Details
2023-01-06 23:29:27 +01:00
Emiliano Vavassori 60b246c548 Correzione comando sbagliato da console.
continuous-integration/drone/push Build is passing Details
2023-01-06 23:23:30 +01:00
Emiliano Vavassori a0c6217d95 Sistemazione build.
continuous-integration/drone/push Build is passing Details
2023-01-05 19:58:45 +01:00
Emiliano Vavassori f95c4d4b1d Sistemazione upload con rsync.
continuous-integration/drone/push Build is passing Details
2023-01-05 18:28:11 +01:00
Emiliano Vavassori 9d259c4aa5 Cambiata la logica di build in caso di assenza di build.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:59:55 +01:00
Emiliano Vavassori 07a895c86c Fix checksum che torna valore non valido.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:56:33 +01:00
Emiliano Vavassori 05533bf5e2 Fix sintassi xpath.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:36:53 +01:00
Emiliano Vavassori 38a78860b0 Fix procedura dopo codice debug.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:33:26 +01:00
Emiliano Vavassori da31e1655b Aggiunta codice debug.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:30:06 +01:00
Emiliano Vavassori ae9668554a Cambiamenti per esecuzione corretta verifica online.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:24:37 +01:00
Emiliano Vavassori 9cf3119489 Correzione sintassi in build.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:14:28 +01:00
Emiliano Vavassori cbaf6b2e3c Corretto anche il file di build per il test.
continuous-integration/drone/push Build is passing Details
2023-01-05 01:08:35 +01:00
Emiliano Vavassori df5012eedd Prima implementazione controllo build remota e caricamento con rsync + ssh. 2023-01-05 01:07:12 +01:00
Emiliano Vavassori 2c19eefa05 Rimozione passaggi superflui pipeline.
continuous-integration/drone/push Build is passing Details
2023-01-04 23:44:10 +01:00
9 changed files with 457 additions and 266 deletions

View File

@ -8,8 +8,6 @@ steps:
commands:
- pip install wheel
- python setup.py bdist_wheel
- mkdir out
- cp dist/*.whl out/
when:
event: tag
@ -19,22 +17,8 @@ steps:
api_key:
from_secret: gitea-deploy
base_url: https://git.sys42.eu/
files: out/*.whl
checksum:
- md5
files: dist/*.whl
checksum: md5
draft: true
when:
event: tag
- name: handycopy
image: drillster/drone-rsync
settings:
hosts: deimos.sys42.eu
user: syntaxerrormmm
port: 45454
key:
from_secret: fisso-ssh-key
source: out/*.whl
target: ~/
when:
event: tag

View File

@ -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

View File

@ -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

View File

@ -1,21 +1,35 @@
#!/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
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 +46,29 @@ class Build(loaih.RemoteBuild):
self.portable = False
self.updatable = True
self.sign = True
self.repo_type = 'local'
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 +79,21 @@ class Build(loaih.RemoteBuild):
def calculate(self):
"""Calculate exclusions and other variables."""
print("--- Calculate Phase ---")
# let's check here if we are on a remote repo or local.
if self.storage_path.startswith("http"):
# Final repository is remote
self.repo_type = 'remote'
print("Repo is remote.")
else:
self.repo_type = 'local'
print("Repo is local.")
# 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 +103,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,49 +128,92 @@ 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:
self.relative_path.append('portable')
fullpath_arr = self.storage_path.split('/')
# Joining relative path only if it is not null
if len(self.relative_path) > 0:
fullpath_arr.extend(self.relative_path)
self.full_path = re.sub(r"/+", '/', str.join('/', fullpath_arr))
# Fullpath might be intended two ways:
if self.repo_type == 'remote':
# Repository is remote
# we build full_path as it is absolute to the root of the
# storage_path.
self.full_path = '/'
if len(self.relative_path) >= 1:
self.full_path += str.join('/', self.relative_path)
else:
# Repository is local
# If it is remote or if it is local
fullpath_arr = self.storage_path.split('/')
# Joining relative path only if it is not null
if len(self.relative_path) > 0:
fullpath_arr.extend(self.relative_path)
self.full_path = re.sub(r"/+", '/', str.join('/', fullpath_arr))
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')
# First, check if by metadata the repo is remote or not.
if self.repo_type == 'remote':
# Remote storage. I have to query a remote site to know if it
# was already built.
name = self.appimagefilename[arch]
url = self.storage_path.rstrip('/') + self.full_path + '/'
matching = []
try:
with urllib.request.urlopen(url) as response:
matching = etree.HTML(response.read()).xpath(
f"//a[contains(@href, '{name}')]/@href"
)
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 len(matching) > 0:
# Already built.
self.built[arch] = True
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
except urllib.error.HTTPError:
# The URL specified do not exist. So it is to build.
pass
else:
# Repo is local
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.
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"Found requested AppImage: {self.appimagefilename[arch]}.")
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
if self.url[arch] == '-':
print(f"No build has been provided for the requested AppImage for {arch}. Continue with other options.")
print(f"Cannot build for arch {arch}. Continuing with other arches.")
# Faking already built it so to skip other checks.
self.built[arch] = True
continue
@ -142,10 +223,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 +244,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 +275,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 +301,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 +385,104 @@ 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.
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:
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.repo_type == 'remote':
# Remote first.
# Build destination directory
remotepath = self.remote_path.rstrip('/') + self.full_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 +493,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 +501,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 +522,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])

View File

@ -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:

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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