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
This commit is contained in:
Danilo Spinella 2023-03-22 16:13:01 +00:00 committed by Git OBS Bridge
parent 625edd991f
commit ccd3752e2b
4 changed files with 103 additions and 110 deletions

View File

@ -1,3 +1,17 @@
-------------------------------------------------------------------
Thu Mar 16 07:30:43 UTC 2023 - Martin Liška <mliska@suse.cz>
- 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 <tchvatal@suse.com>

View File

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

View File

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

View File

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