mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
175 lines
4.4 KiB
Python
Executable file
175 lines
4.4 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# Create JSON with Linux libs needed for BeeRef appimage
|
|
|
|
import argparse
|
|
import json
|
|
import logging
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from urllib import request
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description=('Create JSON with Linux libs needed for BeeRef appimage'))
|
|
parser.add_argument(
|
|
'pid',
|
|
nargs=1,
|
|
default=None,
|
|
help='PID of running BeeRef process')
|
|
parser.add_argument(
|
|
'-l', '--loglevel',
|
|
default='INFO',
|
|
choices=list(logging._nameToLevel.keys()),
|
|
help='log level for console output')
|
|
parser.add_argument(
|
|
'--jsonfile',
|
|
default='linux_libs.json',
|
|
help='JSON input/output file')
|
|
parser.add_argument(
|
|
'--check-appimage',
|
|
default=False,
|
|
action='store_true',
|
|
help='Check a running appimage process for missing libraries')
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
def strip_minor_versions(path):
|
|
# foo2.so.2.1.1 -> foo2.so.2
|
|
return re.sub('(.so.[0-9]*)[.0-9]*$', r'\1', path)
|
|
|
|
|
|
def what_links_to(path):
|
|
links = set()
|
|
dirname = os.path.dirname(path)
|
|
for filename in os.listdir(dirname):
|
|
filename = os.path.join(dirname, filename)
|
|
if (os.path.islink(filename)
|
|
and str(pathlib.Path(filename).resolve()) == path):
|
|
links.add(filename)
|
|
return sorted(links, key=len)
|
|
|
|
|
|
def is_lib(path):
|
|
return ('.so' in path
|
|
and os.path.expanduser('~') not in path
|
|
and 'python3' not in path
|
|
and 'mesa-diverted' not in path)
|
|
|
|
|
|
def iter_lsofoutput(output):
|
|
for line in output.splitlines():
|
|
line = line.split()
|
|
if line[3] == 'mem':
|
|
path = line[-1]
|
|
if is_lib(path):
|
|
yield path
|
|
|
|
|
|
PID = args.pid[0]
|
|
logger = logging.getLogger(__name__)
|
|
logging.basicConfig(level=getattr(logging, args.loglevel))
|
|
|
|
|
|
result = subprocess.run(('lsof', '-p', PID), capture_output=True)
|
|
assert result.returncode == 0, result.stderr
|
|
output = result.stdout.decode('utf-8')
|
|
|
|
|
|
if args.check_appimage:
|
|
logger.info('Checking appimage...')
|
|
errors = False
|
|
for lib in iter_lsofoutput(output):
|
|
if 'mount_BeeRef' not in lib:
|
|
print(f'Not in appimage: {lib}')
|
|
errors = True
|
|
if not errors:
|
|
print('No missing libs found.')
|
|
sys.exit()
|
|
|
|
|
|
libs = []
|
|
|
|
if os.path.exists(args.jsonfile):
|
|
logger.info(f'Reading from: {args.jsonfile}')
|
|
with open(args.jsonfile, 'r') as f:
|
|
data = json.loads(f.read())
|
|
known_libs = data['libs']
|
|
packages = set(data['packages'])
|
|
excludes = set(data['excludes'])
|
|
else:
|
|
logger.info(f'No file {args.jsonfile}; starting from scratch')
|
|
known_libs = []
|
|
packages = set()
|
|
excludes = set()
|
|
|
|
|
|
for lib in iter_lsofoutput(output):
|
|
links = what_links_to(lib)
|
|
if len(links) == 0:
|
|
pass
|
|
elif len(links) == 1:
|
|
lib = links[0]
|
|
else:
|
|
logger.warning(f'Double check: {lib} {links}')
|
|
lib = links[0]
|
|
if lib in known_libs:
|
|
logger.debug(f'Found known lib: {lib}')
|
|
else:
|
|
logger.debug(f'Found new lib: {lib}')
|
|
libs.append(lib)
|
|
|
|
|
|
for lib in libs:
|
|
result = subprocess.run(('apt-file', 'search', lib), capture_output=True)
|
|
if result.returncode != 0:
|
|
logger.warning(f'Fix manually: {lib}')
|
|
continue
|
|
output = result.stdout.decode('utf-8')
|
|
pkgs = set()
|
|
for line in output.splitlines():
|
|
pkg = line.split(': ')[0]
|
|
if not (pkg.endswith('-dev') or pkg.endswith('-dbg')):
|
|
pkgs.add(pkg)
|
|
if len(pkgs) == 1:
|
|
pkg = pkgs.pop()
|
|
logger.debug(f'Found package: {pkg}')
|
|
packages.add(pkg)
|
|
else:
|
|
logger.warning(f'Fix manually: {lib}')
|
|
|
|
|
|
# Find the libs we shouldn't include in the appimage
|
|
with request.urlopen(
|
|
'https://raw.githubusercontent.com/AppImageCommunity/pkg2appimage/'
|
|
'master/excludelist') as f:
|
|
response = f.read().decode()
|
|
|
|
|
|
exclude_masterlist = set()
|
|
for line in response.splitlines():
|
|
if not line or line.startswith('#'):
|
|
continue
|
|
line = line.split()[0]
|
|
line = strip_minor_versions(line)
|
|
exclude_masterlist.add(line)
|
|
|
|
|
|
for ex in exclude_masterlist:
|
|
for lib in (libs + known_libs):
|
|
if lib.endswith(ex):
|
|
excludes.add(ex)
|
|
continue
|
|
|
|
|
|
logger.info(f'Writing to: {args.jsonfile}')
|
|
with open(args.jsonfile, 'w') as f:
|
|
data = {'libs': sorted(libs + known_libs),
|
|
'packages': sorted(packages),
|
|
'excludes': sorted(excludes)}
|
|
f.write(json.dumps(data, indent=4))
|