Skip to content

Instantly share code, notes, and snippets.

@OscarL
Last active November 2, 2025 13:56
Show Gist options
  • Select an option

  • Save OscarL/0c9a8a33fa648bda43e24a08e959c485 to your computer and use it in GitHub Desktop.

Select an option

Save OscarL/0c9a8a33fa648bda43e24a08e959c485 to your computer and use it in GitHub Desktop.
Compare .hpkg locally built with haikuporter, with the one you have installed under /system/packages/
#!python3
"""
Compares the contents (disregarding files' sizes and timestamps) of Haiku packages (.hpkg).
Useful to see, at first glance, if our newly built package looks more or less like the older ones.
Usage:
> compare_packages.py <package_name>
> compare_packages.py <package1.hpkg> <package2.hpkg>
First one compares the given <package_name> from:
/system/packages/package_name-*.hpkg
with the one from:
{0}/package_name-*.hpkg
The second one compares the two given <package1> <package2> files.
Examples:
> compare_packages.py ncurses6
> compare_packages.py /foo/bar/some_package.hpkg ~/Downloads/some_package.hpkg
"""
from pprint import pprint
import os
import re
import subprocess
import sys
def usage():
print(__doc__.format(hp_packages_dir()))
exit()
def call(what, check_rc=True, shell=True):
"""Returns the text output of calling the `what` in a subprocess.
set check_rc=False if the subprocess may fail (and you can handle that).
"""
if check_rc:
return subprocess.check_output([what], shell=shell, text=True)
return subprocess.run([what], stdout=subprocess.PIPE, shell=shell, text=True).stdout
def get_package_filenames(package_name):
"""Returns a 2 items tuple of the first .hpkg filename that matches `package_name`.
The first item from `/system/packages/`, the second from haikuporter's $TREE_PATH.
"""
system = call('ls -1 /system/packages/%s-*.hpkg' % package_name, check_rc=False)
local = call('ls -1 %s/%s-*.hpkg' % (hp_packages_dir(), package_name), check_rc=False)
if system != '':
system = system.splitlines()[0]
if local != '':
local = local.splitlines()[0]
return system, local
def hp_packages_dir():
result = call('source ~/config/settings/haikuports.conf && echo $PACKAGES_PATH').splitlines()[0]
if result != "":
return result
result = call('source ~/config/settings/haikuports.conf && echo $TREE_PATH').splitlines()[0]
if result != "":
return result + '/packages'
raise Exception("Failed to detect HaikuPorts' packages dir location. Is your 'haikuports.conf' properly setup?")
def diff(old, new):
result = call('diff --color=always -u %s %s' % (old, new), check_rc=False)
return result
def get_package_info(filename):
pkg_info = call('package list -i %s' % filename).splitlines()
pkg_files = call('package list -p %s' % filename).splitlines()
return '\n'.join(pkg_info) + '\n' + '\n'.join(sorted(pkg_files))
def main(package_name=None, package1=None, package2=None):
if (package_name is not None) and (package1 is None and package2 is None):
package1, package2 = get_package_filenames(package_name)
errStr1 = 'Cannot locate a package named "%s" under /system/packages/' % package_name
errStr2 = 'Cannot locate a package named "%s" under "%s"' % (package_name, hp_packages_dir())
else:
errStr1 = 'File "%s" doesn\'t exist/' % package1
errStr2 = 'File "%s" doesn\'t exist/' % package2
if not os.path.exists(package1):
print(errStr1)
exit()
elif not os.path.exists(package2):
print(errStr2)
exit()
print('\nComparing package files:\n\t%s\n\t%s\n' % (package1, package2))
tmp_dir = '/boot/system/var/shared_memory'
hpkginfo1 = tmp_dir + '/hpkginfo1.txt'
hpkginfo2 = tmp_dir + '/hpkginfo2.txt'
with open(hpkginfo1, 'w') as of:
of.writelines(get_package_info(package1))
with open(hpkginfo2, 'w') as nf:
nf.writelines(get_package_info(package2))
print(diff(hpkginfo1, hpkginfo2))
os.unlink(hpkginfo1)
os.unlink(hpkginfo2)
if __name__ == '__main__':
if len(sys.argv) == 2:
main(package_name=sys.argv[1])
elif len(sys.argv) == 3:
main(package1=sys.argv[1], package2=sys.argv[2])
else:
usage()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment