From ccd3752e2b802cef6d6e57dac211b7e92c58a81a7e4dd84b45e3122354874d26 Mon Sep 17 00:00:00 2001 From: Danilo Spinella Date: Wed, 22 Mar 2023 16:13:01 +0000 Subject: [PATCH] Accepting request 1072269 from home:marxin:libre - Rewrite the script to Python: * the current script is quite slow and delays libreoffice package build where we install all packages and then uninstall them * the script uses linkfile=${file/${datadir}/${libdir}} for replacement of $datadir prefix with $libdir (if the $file path starts with $datadir; if not, we end up with an empty string and we execute various shell scripts with it * the Python implementation should be more readable * the Python version runs about 200s faster when it comes to libreoffice package build (on a recent Ryzen 9 machine) OBS-URL: https://build.opensuse.org/request/show/1072269 OBS-URL: https://build.opensuse.org/package/show/LibreOffice:Factory/libreoffice-share-linker?expand=0&rev=12 --- libreoffice-share-linker.changes | 14 +++++ libreoffice-share-linker.py | 83 ++++++++++++++++++++++++ libreoffice-share-linker.spec | 11 ++-- link-to-ooo-home | 105 ------------------------------- 4 files changed, 103 insertions(+), 110 deletions(-) create mode 100644 libreoffice-share-linker.py delete mode 100644 link-to-ooo-home diff --git a/libreoffice-share-linker.changes b/libreoffice-share-linker.changes index 191b96b..615a195 100644 --- a/libreoffice-share-linker.changes +++ b/libreoffice-share-linker.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Thu Mar 16 07:30:43 UTC 2023 - Martin Liška + +- Rewrite the script to Python: + * the current script is quite slow and delays libreoffice package + build where we install all packages and then uninstall them + * the script uses linkfile=${file/${datadir}/${libdir}} for replacement + of $datadir prefix with $libdir (if the $file path starts with $datadir; + if not, we end up with an empty string and we execute various shell + scripts with it + * the Python implementation should be more readable + * the Python version runs about 200s faster when it comes to libreoffice + package build (on a recent Ryzen 9 machine) + ------------------------------------------------------------------- Tue Jul 2 08:11:43 UTC 2019 - Tomáš Chvátal diff --git a/libreoffice-share-linker.py b/libreoffice-share-linker.py new file mode 100644 index 0000000..c126c76 --- /dev/null +++ b/libreoffice-share-linker.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess +from pathlib import Path + +PREFIX = '/usr/share/libreoffice' +DATADIR = '/usr/share' +LIBDIRS = ( + Path('/usr/lib/'), + Path('/usr/lib64/'), + Path('/usr/lib32/'), +) +LEFTOVER_DIRS = ( + Path('/usr/share/libreoffice/help'), + Path('/usr/share/libreoffice/program'), + Path('/usr/share/libreoffice/share'), + Path('/usr/share/libreoffice'), +) + +parser = argparse.ArgumentParser(description='This script (un)links or unlinks the given to/from libreoffice home') +parser.add_argument('filelist', help='List of files') +parser.add_argument('--unlink', action='store_true', help='Unlink the files during package removal') +args = parser.parse_args() + +files = sorted([Path(x) for x in open(args.filelist).read().splitlines() if x.startswith(PREFIX)]) + + +def get_relative_folder(file, libdir): + try: + return libdir / file.relative_to(DATADIR) + except ValueError: + return None + + +for libdir in LIBDIRS: + # for each dir verify there is libreoffice folder, otherwise skip + lodir = libdir / 'libreoffice' + if not lodir.is_dir(): + continue + + # Decide if we are linking or wiping first + if args.unlink: + for file in files: + link = get_relative_folder(file, libdir) + if link: + # first just remove the symlinks + if link.is_symlink() and not link.is_dir(): + link.unlink() + + # continue by wiping out all EMPTY dirs + # we have to be sure it is not owned by anything else + # doing in 2nd run to ensure avoiding collisions + if link.is_dir() and not any(link.iterdir()): + r = subprocess.run(f'rpm -qf {file}', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) + if not r.stdout: + link.rmdir() + else: + for file in files: + # if we get ourselves folder then just create it + # it might not be around so lets be safe + link = get_relative_folder(file, libdir) + if link: + if file.is_dir(): + if not link.exists(): + link.mkdir(parents=True) + link.chmod(file.stat().st_mode) + else: + # if the file is already there, skip it + # this is true when the parent folder is link + if not link.exists(): + link.symlink_to(file) + + for leftover in LEFTOVER_DIRS: + if leftover.is_dir() and not any(leftover.iterdir()): + leftover.rmdir() + + # remove dangling links as they might happen when migratin from older + # libreoffice versions + # Run find directly as it's faster than os.walk run and a os.path.islink! + subprocess.run(f'find {str(lodir)} -type l -xtype l -delete', + shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) diff --git a/libreoffice-share-linker.spec b/libreoffice-share-linker.spec index 51969f0..c6845bf 100644 --- a/libreoffice-share-linker.spec +++ b/libreoffice-share-linker.spec @@ -1,7 +1,7 @@ # # spec file for package libreoffice-share-linker # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,9 +22,10 @@ Release: 0 Summary: Script to link/unlink files to libreoffice home License: MIT Group: Productivity/Office/Suite -Url: http://www.opensuse.org/ -Source0: link-to-ooo-home +URL: http://www.opensuse.org/ +Source0: libreoffice-share-linker.py BuildRoot: %{_tmppath}/%{name}-%{version}-build +Requires: python3 BuildArch: noarch %description @@ -42,13 +43,13 @@ install -Dm 755 %{SOURCE0} %{buildroot}%{_bindir}/%{name} # compat for migration from older releases openSUSE-13.1 and older mkdir -p %{buildroot}%{_datadir}/libreoffice pushd %{buildroot}%{_datadir}/libreoffice > /dev/null -ln -s %{_bindir}/%{name} link-to-ooo-home +ln -s %{_bindir}/%{name} libreoffice-share-linker.py popd > /dev/null %files %defattr(-,root,root) %{_bindir}/%{name} %dir %{_datadir}/libreoffice/ -%{_datadir}/libreoffice/link-to-ooo-home +%{_datadir}/libreoffice/libreoffice-share-linker.py %changelog diff --git a/link-to-ooo-home b/link-to-ooo-home deleted file mode 100644 index ad4df05..0000000 --- a/link-to-ooo-home +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -usage() { - echo "This script (un)links or unlinks the given to/from libreoffice home" - echo - echo "Usage: ${0##*/} [--unlink] filelist" -} - -change_linking() { - local libdir="$1" - local filelist="$2" - local linkfile="" - local linkdir="" - - # Decide if we are linking or wiping first - if ${link_mode}; then - # Grab all files from the proper folder - for file in `cat ${filelist} | grep "/usr/share/libreoffice" | sort`; do - # if we get ourselves folder then just create it - # it might not be around so lets be safe - if [[ -d "${file}" ]] ; then - dirname="${file/${datadir}/${libdir}}" - # if the location is already there skip it - if [[ ! -e "${dirname}" ]]; then - mkdir -p "${dirname}" - chmod --reference="${file}" "${dirname}" - fi - continue - fi - linkfile="${file/${datadir}/${libdir}}" - # if the file is already there, skip it - # this is true when the parent folder is link - if [[ ! -e "${linkfile}" ]]; then - ln -sf "${file}" "${linkfile}" || exit 1 - fi - done - else - # first just remove the symlinks - for file in `cat ${filelist} | grep "/usr/share/libreoffice" | sort`; do - linkfile=${file/${datadir}/${libdir}} - if [[ -L "${linkfile}" && ! -r "${linkfile}" && ! -d "${linkfile}" ]]; then - rm -f "${linkfile}" || exit 1 - fi - done - # continue by wiping out all EMPTY dirs - # we have to be sure it is not owned by anything else - # doing in 2nd run to ensure avoiding collisions - for file in `cat ${filelist} | grep "/usr/share/libreoffice" | sort`; do - linkdir="${file/${datadir}/${libdir}}" - if [[ -d "${linkdir}" && -z `ls "${linkdir}"/* 2>/dev/null` ]]; then - # check if nothing else owns the dir - if [[ $(rpm -qf "${file}" 2>/dev/null |wc -l) == 0 ]]; then - rmdir "${linkdir}" || exit 1 - fi - fi - done - leftover_dirs=" - /usr/share/libreoffice/help - /usr/share/libreoffice/program - /usr/share/libreoffice/share - /usr/share/libreoffice - " - for i in ${leftover_dirs}; do - if [[ -d ${i} && ! "$(ls -A ${i})" ]]; then - rmdir "${i}" || exit 1 - fi - done - fi -} - -# Global VARS -link_mode=true -datadir=/usr/share -libdirs=( - "/usr/lib/" - "/usr/lib64/" - "/usr/lib32/" -) - -if [[ "$1" == "--unlink" ]]; then - link_mode=false - shift -fi - -if [[ "$1" == "--help" ]]; then - usage - exit 0 -fi - -# Verify we have just one left argument which is the filelist -if [[ $# > 1 || ! -f "$1" ]]; then - usage - exit 1 -fi - -for libdir in ${libdirs[@]}; do - # for each dir verify there is libreoffice folder, otherwise skip - if [[ ! -d "${libdir}/libreoffice/" ]]; then - continue - fi - change_linking ${libdir} $1 - # remove dangling links as they might happen when migratin from older - # libreoffice versions - find ${libdir}/libreoffice -type l -xtype l -delete -done