Skip to content

Commit

Permalink
xbps: Make pull-pack updatable
Browse files Browse the repository at this point in the history
Consider pull-pack to be out of date if the remote repository
has a newer version of the package.
  • Loading branch information
avdgrinten committed Nov 8, 2024
1 parent 7f8e853 commit a82eb46
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
13 changes: 13 additions & 0 deletions xbstrap/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,19 @@ def check_if_packed(self, settings):
def check_if_pull_needed(self, settings):
if self._cfg.use_xbps:
if self._have_xbps_package():
if settings.check_remotes:
# Local repodata exists (otherwise _have_xbps_package() would return false).
rd = self.get_local_xbps_repodata_entry()
if rd is None:
raise RuntimeError("Expected local xbps repodata to exist")

remote_rd = self.get_remote_xbps_repodata_entry()
if remote_rd is not None:
version = _xbps_utils.parse_version(rd["pkgver"])
remote_version = _xbps_utils.parse_version(remote_rd["pkgver"])
if _xbps_utils.compare_version(version, remote_version) < 0:
return ItemState(updatable=True)

return ItemState()
else:
return ItemState(missing=True)
Expand Down
85 changes: 85 additions & 0 deletions xbstrap/xbps_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import itertools
import plistlib
import shlex
import tarfile
Expand All @@ -18,6 +19,90 @@ def read_repodata(path):
return pkg_idx


class XbpsVersion:
def __init__(self, comps, revision=1):
self.comps = comps
self.revision = revision


# This matches the version parsing algorithm in xbps.
def parse_components(v):
modifiers = {
"alpha": -3,
"beta": -2,
"pre": -1,
"rc": -1,
"pl": 0,
".": 0,
}
alphas = "abcdefghijklmnopqrstuvwxyz"

n = 0
out = []

def consume_next_token():
nonlocal n

# Integers correspond to a single component.
if v[n].isdigit():
d = 0
while n < len(v) and v[n].isdigit():
d = (d * 10) + int(v[n])
n += 1
out.append(d)
return

# Modifiers correspond to a single component with a fixed value.
for modifier, prio in modifiers.items():
if v[n:].startswith(modifier):
out.append(prio)
n += len(modifier)
return

# Letters correspond to two components: (0, idx + 1).
# For example: versions "0.2" and "0b" are identical.
idx = alphas.find(v[n].lower())
if idx >= 0:
out.append(0)
out.append(idx + 1)

# Consume the character. It does _not_ contribute to the version.
n += 1

while n < len(v):
consume_next_token()

return out


def parse_version(v, *, strip_pkgname=True):
if strip_pkgname:
v = v.split("-")[-1]

# Split into components + revision.
# Technically, xbps's parsing code allows the revision to appear in the middle of a version.
# We only accept revision at the end of a version string.
parts = v.split("_")
comps = parse_components(parts[0])
if len(parts) > 1:
if len(parts) != 2:
raise RuntimeError("Expected at most one revision in xbps version")
revision = int(parts[1])
else:
revision = 1

return XbpsVersion(comps, revision)


def compare_version(v1, v2):
for c1, c2 in itertools.zip_longest(v1.comps, v2.comps, fillvalue=0):
if c1 != c2:
return c1 - c2
if v1.revision != v2.revision:
return v1.revision - v2.revision
return 0


# XBPS INSTALL/REMOVE scripts are called with arguments:
# <action> <pkgname> <version> <update yes/no> "no" <arch>

Expand Down

0 comments on commit a82eb46

Please sign in to comment.