diff --git a/.travis.yml b/.travis.yml
index 7182e95d..6bd4679c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,15 +5,15 @@ addons:
apt:
sources:
- debian-sid
- packages:
- - shellcheck
-install: "pip install flake8 pytest-cov python-coveralls"
+install:
+ - sudo apt install shellcheck qemu-system-x86
+ - pip install flake8 pytest-cov python-coveralls
script:
- test/static_code_analysis.sh
- yes "" | ./pmbootstrap.py init
- ./pmbootstrap.py kconfig_check
+ - test/check_checksums.py --build
- test/testcases_fast.sh
- - test/check_checksums.py
after_success:
- coveralls
after_failure:
diff --git a/aports/main/hello-world/APKBUILD b/aports/main/hello-world/APKBUILD
index 2ed7a700..37ee6ca1 100644
--- a/aports/main/hello-world/APKBUILD
+++ b/aports/main/hello-world/APKBUILD
@@ -1,6 +1,6 @@
pkgname=hello-world
pkgver=1
-pkgrel=3
+pkgrel=4
pkgdesc="hello world program to be built in the testsuite"
url="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program"
arch="all"
diff --git a/pmb/build/autodetect.py b/pmb/build/autodetect.py
index 2d1c1fd1..51648efb 100644
--- a/pmb/build/autodetect.py
+++ b/pmb/build/autodetect.py
@@ -17,11 +17,37 @@ You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see .
"""
import fnmatch
+import logging
+import os
+
import pmb.config
import pmb.chroot.apk
import pmb.parse.arch
+def arch_from_deviceinfo(args, pkgname, aport):
+ """
+ The device- packages are noarch packages. But it only makes sense to build
+ them for the device's architecture, which is specified in the deviceinfo
+ file.
+
+ :returns: None (no deviceinfo file)
+ arch from the deviceinfo (e.g. "armhf")
+ """
+ # Require a deviceinfo file in the aport
+ if not pkgname.startswith("device-"):
+ return
+ deviceinfo = aport + "/deviceinfo"
+ if not os.path.exists(deviceinfo):
+ return
+
+ # Return its arch
+ device = pkgname.split("-", 1)[1]
+ arch = pmb.parse.deviceinfo(args, device)["arch"]
+ logging.verbose(pkgname + ": arch from deviceinfo: " + arch)
+ return arch
+
+
def arch(args, pkgname):
"""
Find a good default in case the user did not specify for which architecture
@@ -32,6 +58,10 @@ def arch(args, pkgname):
APKBUILD.
"""
aport = pmb.build.find_aport(args, pkgname)
+ ret = arch_from_deviceinfo(args, pkgname, aport)
+ if ret:
+ return ret
+
apkbuild = pmb.parse.apkbuild(args, aport + "/APKBUILD")
if "noarch" in apkbuild["arch"] or "all" in apkbuild["arch"]:
return args.arch_native
diff --git a/pmb/helpers/frontend.py b/pmb/helpers/frontend.py
index d9958758..3aeb74ab 100644
--- a/pmb/helpers/frontend.py
+++ b/pmb/helpers/frontend.py
@@ -43,48 +43,28 @@ import pmb.parse
import pmb.qemu
-def _build_verify_usage_device_package(args, pkgname):
+def _build_device_depends_note(args, pkgname):
"""
- Detect if the user is about to build a device- package for the wrong
- architecture. The package is noarch, but the dependencies (kernel!) will get
- pulled in with the same arch as dependency.
+ Previously 'pmbootstrap build device-...' built the device package in the
+ native chroot without installing its dependencies (e.g. armhf kernel!) and
+ created a symlink to all supported architectures.
+
+ Not installing depends while building is incompatible with how Alpine's
+ abuild does it, so we changed the behavior. Now pmbootstrap reads the
+ device's architecture from the deviceinfo file and automatically builds
+ for that architecture, if you did not specify any architecture. And the
+ dependencies get installed correctly before the build.
+
+ To make migration easier for the users, we show a hint if building a device
+ package was requested.
"""
- # Skip non-device-packages
- if not pkgname.startswith("device-"):
+ # Only relevant for device packages when -i is not set
+ if not pkgname.startswith("device-") or getattr(args, "ignore_depends"):
return
- # Only continue when the --arch parameter is *not* the device architecture
- deviceinfo = args.aports + "/device/" + pkgname + "/deviceinfo"
- if not os.path.exists(deviceinfo):
- return
device = pkgname.split("-", 1)[1]
- arch = pmb.parse.deviceinfo(args, device)["arch"]
- if args.arch == arch:
- return
-
- # Abort with a big note
- logging.info("Dependency handling in 'pmbootstrap build' has been"
- " changed.")
- logging.info("Previously we only built and installed the 'makedepends'"
- " from the APKBUILDs, now we use the 'depends', too.")
- logging.info("")
- logging.info("Your options:")
- logging.info("* Ignore depends (fast, old behavior, may cause problems"
- " with some packages):")
- logging.info(" pmbootstrap build " + pkgname + " -i")
- logging.info("* Build with depends (kernel!) and specify the right"
- " architecture:")
- logging.info(" pmbootstrap build " + pkgname + " --arch=" + arch)
- logging.info("")
- logging.info("This change was necessary to be more compatible with Alpine's"
- " abuild.")
- logging.info("The default architecture is the native one (" +
- args.arch_native + " in your case), so you need to overwrite")
- logging.info("it now to get the kernel dependency of your device package"
- " for the right architecture.")
- logging.info("Sorry for the inconvenience.")
- logging.info("")
- raise RuntimeError("Missing -i or --arch parameter")
+ logging.info("NOTE: " + device + "'s kernel will be installed as dependency"
+ " before building (old behavior: 'pmbootstrap build -i')")
def _parse_flavor(args):
@@ -135,10 +115,10 @@ def build(args):
if args.strict:
pmb.chroot.zap(args, False)
- # Detect wrong usage for device- packages
+ # Detect old usage for device- packages
if not args.ignore_depends:
for package in args.packages:
- _build_verify_usage_device_package(args, package)
+ _build_device_depends_note(args, package)
# Build all packages
for package in args.packages:
diff --git a/pmb/qemu/run.py b/pmb/qemu/run.py
index aca73a13..4645f0e7 100644
--- a/pmb/qemu/run.py
+++ b/pmb/qemu/run.py
@@ -18,8 +18,9 @@ along with pmbootstrap. If not, see .
"""
import logging
import os
-import shutil
import re
+import signal
+import shutil
import pmb.build
import pmb.chroot
@@ -218,6 +219,11 @@ def resize_image(args, img_size_new, img_path):
raise RuntimeError("The system image size must be " + img_size_str + " or greater")
+def sigterm_handler(number, frame):
+ raise RuntimeError("pmbootstrap was terminated by another process,"
+ " and killed the Qemu VM it was running.")
+
+
def run(args):
"""
Run a postmarketOS image in qemu
@@ -253,13 +259,15 @@ def run(args):
logging.info("* (ssh) ssh -p {port} {user}@localhost".format(**vars(args)))
logging.info("* (telnet) telnet localhost " + str(args.port + 1))
- # Run Qemu (or Qemu + SPICE)
+ # Run Qemu (or Qemu + SPICE) and kill it together with pmbootstrap
process = None
try:
+ signal.signal(signal.SIGTERM, sigterm_handler)
process = pmb.helpers.run.user(args, qemu, background=spice_enabled)
if spice:
pmb.helpers.run.user(args, spice)
except KeyboardInterrupt:
+ # Don't show a trace when pressing ^C
pass
finally:
if process:
diff --git a/test/check_checksums.py b/test/check_checksums.py
index 2ed067d8..c1999fa3 100755
--- a/test/check_checksums.py
+++ b/test/check_checksums.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import os
import subprocess
+import sys
def get_changed_files():
@@ -62,7 +63,27 @@ def check_checksums(package):
exit(1)
+def check_build(packages):
+ command = (["./pmbootstrap.py", "--details-to-stdout", "build",
+ "--strict"] + list(packages))
+ try:
+ process = subprocess.Popen(command)
+ process.communicate()
+ except subprocess.CalledProcessError as e:
+ print("** Building failed")
+ exit(1)
+
+
if __name__ == "__main__":
+ # Allow to specify "--build" to build instead of only verifying checksums
+ build = False
+ if len(sys.argv) > 1:
+ if sys.argv[1] == "--build":
+ build = True
+ else:
+ print("usage: {} [--build]".format(sys.argv[0]))
+ exit(1)
+
if 'TRAVIS_COMMIT_RANGE' in os.environ:
print('Checking commit range: {}'.format(os.environ['TRAVIS_COMMIT_RANGE']))
if 'TRAVIS_PULL_REQUEST_BRANCH' in os.environ:
@@ -74,6 +95,10 @@ if __name__ == "__main__":
print("No aports packages changed in this commit")
exit(0)
- for package in packages:
- print("Checking {} for correct checksums".format(package))
- check_checksums(package)
+ if build:
+ print("Building in strict mode: " + ", ".join(packages))
+ check_build(packages)
+ else:
+ for package in packages:
+ print("Checking {} for correct checksums".format(package))
+ check_checksums(package)
diff --git a/test/test_qemu_running_processes.py b/test/test_qemu_running_processes.py
new file mode 100644
index 00000000..741f1020
--- /dev/null
+++ b/test/test_qemu_running_processes.py
@@ -0,0 +1,169 @@
+"""
+Copyright 2017 Oliver Smith
+
+This file is part of pmbootstrap.
+
+pmbootstrap is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+pmbootstrap is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmbootstrap. If not, see .
+"""
+
+"""
+This file runs various installations and boots into them with Qemu, then checks
+via SSH if expected processes are running.
+
+We use an extra config file (based on ~/.config/pmbootstrap.cfg), because we
+need to change it a lot (e.g. UI, username, ...).
+"""
+
+import os
+import pytest
+import sys
+import shutil
+import shlex
+import time
+import logging
+
+# Import from parent directory
+pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
+sys.path.append(pmb_src)
+import pmb.chroot.apk_static
+import pmb.parse.apkindex
+import pmb.helpers.logging
+import pmb.helpers.run
+import pmb.parse.bootimg
+
+
+@pytest.fixture
+def args(request):
+ import pmb.parse
+ sys.argv = ["pmbootstrap.py", "chroot"]
+ args = pmb.parse.arguments()
+ args.log = args.work + "/log_testsuite.txt"
+ pmb.helpers.logging.init(args)
+ request.addfinalizer(args.logfd.close)
+ return args
+
+
+def ssh_create_askpass_script(args):
+ """Create /tmp/y.sh, which we need to automatically login via SSH."""
+ with open(args.work + "/chroot_native/tmp/y.sh", "w") as handle:
+ handle.write("#!/bin/sh\necho y\n")
+ pmb.chroot.root(args, ["chmod", "+x", "/tmp/y.sh"])
+
+
+def pmbootstrap_run(args, config, parameters, background=False):
+ """Execute pmbootstrap.py with a test pmbootstrap.conf."""
+ return pmb.helpers.run.user(args, ["./pmbootstrap.py", "-c", config] +
+ parameters, working_dir=pmb_src,
+ background=background)
+
+
+def pmbootstrap_yes(args, config, parameters):
+ """
+ Execute pmbootstrap.py with a test pmbootstrap.conf, and pipe "yes"
+ into it (so we can do a fully automated installation, using "y" as
+ password everywhere).
+ """
+ command = "yes | ./pmbootstrap.py -c " + shlex.quote(config)
+ for parameter in parameters:
+ command += " " + shlex.quote(parameter)
+ return pmb.helpers.run.user(args, ["/bin/sh", "-c", command],
+ working_dir=pmb_src)
+
+
+class Qemu(object):
+ def __init__(self, request):
+ self.process = None
+ request.addfinalizer(self.terminate)
+
+ def terminate(self):
+ if self.process:
+ self.process.terminate()
+ else:
+ print("WARNING: The Qemu process wasn't set, so it could not be"
+ " terminated.")
+
+ def run(self, args, tmpdir, ui="none"):
+ # Copy and adjust user's pmbootstrap.cfg
+ config = str(tmpdir) + "/pmbootstrap.cfg"
+ shutil.copyfile(os.path.expanduser("~") + "/.config/pmbootstrap.cfg",
+ config)
+ pmbootstrap_run(args, config, ["config", "device", "qemu-amd64"])
+ pmbootstrap_run(args, config, ["config", "extra_packages", "none"])
+ pmbootstrap_run(args, config, ["config", "user", "testuser"])
+ pmbootstrap_run(args, config, ["config", "ui", ui])
+ pmbootstrap_run(args, config, ["config", "qemu_native_mesa_driver", "dri-swrast"])
+
+ # Prepare native chroot
+ pmbootstrap_run(args, config, ["-y", "zap"])
+ pmb.chroot.apk.install(args, ["openssh-client"])
+ ssh_create_askpass_script(args)
+
+ # Create and run system image
+ pmbootstrap_yes(args, config, ["install", "--no-fde"])
+ self.process = pmbootstrap_run(args, config, ["qemu", "--display",
+ "none"], background=True)
+ logging.info("(test) wait 90s until the VM booted up")
+ time.sleep(90)
+
+
+@pytest.fixture
+def qemu(request):
+ return Qemu(request)
+
+
+def ssh_run(args, command):
+ """
+ Run a command in the Qemu VM on localhost via SSH.
+
+ :param command: flat string of the command to execute, e.g. "ps au"
+ :returns: the result from the SSH server
+ """
+ ret = pmb.chroot.user(args, ["SSH_ASKPASS=/tmp/y.sh", "DISPLAY=", "ssh",
+ "-o", "UserKnownHostsFile=/dev/null",
+ "-o", "StrictHostKeyChecking=no",
+ "-p", "2222", "testuser@localhost", "--",
+ command],
+ return_stdout=True)
+ return ret
+
+
+def is_running(args, programs):
+ """
+ Simple check that looks for program names in the output of "ps ax".
+ This is error-prone, only use it with programs that have a unique name.
+ """
+ all = ssh_run(args, "ps ax")
+ ret = True
+ for program in programs:
+ if program in all:
+ continue
+ print(program + ": not found in 'ps ax'!")
+ ret = False
+ return ret
+
+
+def test_xfce4(args, tmpdir, qemu):
+ qemu.run(args, tmpdir, "xfce4")
+ assert is_running(args, ["xfce4-session", "xfdesktop", "xfce4-panel",
+ "Thunar", "dbus-daemon", "xfwm4"])
+
+ # self-test of is_running()
+ assert is_running(args, ["invalid-process"]) is False
+
+
+def test_plasma_mobile(args, tmpdir, qemu):
+ # NOTE: Once we have plasma mobile running properly without GL, we can check
+ # for more processes
+ qemu.run(args, tmpdir, "plasma-mobile")
+ assert is_running(args, ["polkitd"])
diff --git a/test/test_version.py b/test/test_version.py
index 5f5ea600..0f5e711c 100644
--- a/test/test_version.py
+++ b/test/test_version.py
@@ -21,8 +21,8 @@ import sys
import pytest
# Import from parent directory
-sys.path.append(os.path.realpath(
- os.path.join(os.path.dirname(__file__) + "/..")))
+pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
+sys.path.append(pmb_src)
import pmb.helpers.git
import pmb.helpers.logging
import pmb.parse.version
@@ -43,11 +43,8 @@ def test_version(args):
# Fail after the first error or print a grand total of failures
keep_going = False
- # Clone official test file from apk-tools
- pmb.helpers.git.clone(args, "apk-tools")
- path = args.work + "/cache_git/apk-tools/test/version.data"
-
- # Iterate over the cases from the list
+ # Iterate over the version tests from apk-tools
+ path = pmb_src + "/test/testdata/version/version.data"
mapping = {-1: "<", 0: "=", 1: ">"}
count = 0
errors = []
@@ -64,8 +61,7 @@ def test_version(args):
count += 1
if real != expected:
if keep_going:
- errors.append(line.rstrip() + " (got: '" + real +
- "')")
+ errors.append(line.rstrip() + " (got: '" + real + "')")
else:
assert real == expected
diff --git a/test/testcases_fast.sh b/test/testcases_fast.sh
index 1d993661..8e6f2064 100755
--- a/test/testcases_fast.sh
+++ b/test/testcases_fast.sh
@@ -3,11 +3,9 @@
# Disable slow testcases
# aport_in_sync_with_git: clones Alpine's aports repo
# aportgen: clones Alpine's aports repo
-# version: clones Alpine's apk repo
disabled="
aport_in_sync_with_git
aportgen
- version
"
# Make sure we have a valid device (#1128)
diff --git a/test/testdata/version/README b/test/testdata/version/README
new file mode 100644
index 00000000..86cf2e07
--- /dev/null
+++ b/test/testdata/version/README
@@ -0,0 +1,2 @@
+Source:
+https://git.alpinelinux.org/cgit/apk-tools/tree/test/version.data
diff --git a/test/testdata/version/version.data b/test/testdata/version/version.data
new file mode 100644
index 00000000..59d93cf2
--- /dev/null
+++ b/test/testdata/version/version.data
@@ -0,0 +1,728 @@
+2.34 > 0.1.0_alpha
+23_foo > 4_beta
+1.0 < 1.0bc # invalid. do string sort
+0.1.0_alpha = 0.1.0_alpha
+0.1.0_alpha < 0.1.3_alpha
+0.1.3_alpha > 0.1.0_alpha
+0.1.0_alpha2 > 0.1.0_alpha
+0.1.0_alpha < 2.2.39-r1
+2.2.39-r1 > 1.0.4-r3
+1.0.4-r3 < 1.0.4-r4
+1.0.4-r4 < 1.6
+1.6 > 1.0.2
+1.0.2 > 0.7-r1
+0.7-r1 < 1.0.0
+1.0.0 < 1.0.1
+1.0.1 < 1.1
+1.1 > 1.1_alpha1
+1.1_alpha1 < 1.2.1
+1.2.1 > 1.2
+1.2 < 1.3_alpha
+1.3_alpha < 1.3_alpha2
+1.3_alpha2 < 1.3_alpha3
+1.3_alpha8 > 0.6.0
+0.6.0 < 0.6.1
+0.6.1 < 0.7.0
+0.7.0 < 0.8_beta1
+0.8_beta1 < 0.8_beta2
+0.8_beta4 < 4.8-r1
+4.8-r1 > 3.10.18-r1
+3.10.18-r1 > 2.3.0b-r1
+2.3.0b-r1 < 2.3.0b-r2
+2.3.0b-r2 < 2.3.0b-r3
+2.3.0b-r3 < 2.3.0b-r4
+2.3.0b-r4 > 0.12.1
+0.12.1 < 0.12.2
+0.12.2 < 0.12.3
+0.12.3 > 0.12
+0.12 < 0.13_beta1
+0.13_beta1 < 0.13_beta2
+0.13_beta2 < 0.13_beta3
+0.13_beta3 < 0.13_beta4
+0.13_beta4 < 0.13_beta5
+0.13_beta5 > 0.9.12
+0.9.12 < 0.9.13
+0.9.13 > 0.9.12
+0.9.12 < 0.9.13
+0.9.13 > 0.0.16
+0.0.16 < 0.6
+0.6 < 2.1.13-r3
+2.1.13-r3 < 2.1.15-r2
+2.1.15-r2 < 2.1.15-r3
+2.1.15-r3 > 1.2.11
+1.2.11 < 1.2.12.1
+1.2.12.1 < 1.2.13
+1.2.13 < 1.2.14-r1
+1.2.14-r1 > 0.7.1
+0.7.1 > 0.5.4
+0.5.4 < 0.7.0
+0.7.0 < 1.2.13
+1.2.13 > 1.0.8
+1.0.8 < 1.2.1
+1.2.1 > 0.7-r1
+0.7-r1 < 2.4.32
+2.4.32 < 2.8-r4
+2.8-r4 > 0.9.6
+0.9.6 > 0.2.0-r1
+0.2.0-r1 = 0.2.0-r1
+0.2.0-r1 < 3.1_p16
+3.1_p16 < 3.1_p17
+3.1_p17 > 1.06-r6
+1.06-r6 < 006
+006 > 1.0.0
+1.0.0 < 1.2.2-r1
+1.2.2-r1 > 1.2.2
+1.2.2 > 0.3-r1
+0.3-r1 < 9.3.2-r4
+9.3.2-r4 < 9.3.4-r2
+9.3.4-r2 > 9.3.4
+9.3.4 > 9.3.2
+9.3.2 < 9.3.4
+9.3.4 > 1.1.3
+1.1.3 < 2.16.1-r3
+2.16.1-r3 = 2.16.1-r3
+2.16.1-r3 > 2.1.0-r2
+2.1.0-r2 < 2.9.3-r1
+2.9.3-r1 > 0.9-r1
+0.9-r1 > 0.8-r1
+0.8-r1 < 1.0.6-r3
+1.0.6-r3 > 0.11
+0.11 < 0.12
+0.12 < 1.2.1-r1
+1.2.1-r1 < 1.2.2.1
+1.2.2.1 < 1.4.1-r1
+1.4.1-r1 < 1.4.1-r2
+1.4.1-r2 > 1.2.2
+1.2.2 < 1.3
+1.3 > 1.0.3-r6
+1.0.3-r6 < 1.0.4
+1.0.4 < 2.59
+2.59 < 20050718-r1
+20050718-r1 < 20050718-r2
+20050718-r2 > 3.9.8-r5
+3.9.8-r5 > 2.01.01_alpha10
+2.01.01_alpha10 > 0.94
+0.94 < 1.0
+1.0 > 0.99.3.20040818
+0.99.3.20040818 > 0.7
+0.7 < 1.21-r1
+1.21-r1 > 0.13
+0.13 < 0.90.1-r1
+0.90.1-r1 > 0.10.2
+0.10.2 < 0.10.3
+0.10.3 < 1.6
+1.6 < 1.39
+1.39 > 1.00_beta2
+1.00_beta2 > 0.9.2
+0.9.2 < 5.94-r1
+5.94-r1 < 6.4
+6.4 > 2.6-r5
+2.6-r5 > 1.4
+1.4 < 2.8.9-r1
+2.8.9-r1 > 2.8.9
+2.8.9 > 1.1
+1.1 > 1.0.3-r2
+1.0.3-r2 < 1.3.4-r3
+1.3.4-r3 < 2.2
+2.2 > 1.2.6
+1.2.6 < 7.15.1-r1
+7.15.1-r1 > 1.02
+1.02 < 1.03-r1
+1.03-r1 < 1.12.12-r2
+1.12.12-r2 < 2.8.0.6-r1
+2.8.0.6-r1 > 0.5.2.7
+0.5.2.7 < 4.2.52_p2-r1
+4.2.52_p2-r1 < 4.2.52_p4-r2
+4.2.52_p4-r2 > 1.02.07
+1.02.07 < 1.02.10-r1
+1.02.10-r1 < 3.0.3-r9
+3.0.3-r9 > 2.0.5-r1
+2.0.5-r1 < 4.5
+4.5 > 2.8.7-r1
+2.8.7-r1 > 1.0.5
+1.0.5 < 8
+8 < 9
+9 > 2.18.3-r10
+2.18.3-r10 > 1.05-r18
+1.05-r18 < 1.05-r19
+1.05-r19 < 2.2.5
+2.2.5 < 2.8
+2.8 < 2.20.1
+2.20.1 < 2.20.3
+2.20.3 < 2.31
+2.31 < 2.34
+2.34 < 2.38
+2.38 < 20050405
+20050405 > 1.8
+1.8 < 2.11-r1
+2.11-r1 > 2.11
+2.11 > 0.1.6-r3
+0.1.6-r3 < 0.47-r1
+0.47-r1 < 0.49
+0.49 < 3.6.8-r2
+3.6.8-r2 > 1.39
+1.39 < 2.43
+2.43 > 2.0.6-r1
+2.0.6-r1 > 0.2-r6
+0.2-r6 < 0.4
+0.4 < 1.0.0
+1.0.0 < 10-r1
+10-r1 > 4
+4 > 0.7.3-r2
+0.7.3-r2 > 0.7.3
+0.7.3 < 1.95.8
+1.95.8 > 1.1.19
+1.1.19 > 1.1.5
+1.1.5 < 6.3.2-r1
+6.3.2-r1 < 6.3.3
+6.3.3 > 4.17-r1
+4.17-r1 < 4.18
+4.18 < 4.19
+4.19 > 4.3.0
+4.3.0 < 4.3.2-r1
+4.3.2-r1 > 4.3.2
+4.3.2 > 0.68-r3
+0.68-r3 < 1.0.0
+1.0.0 < 1.0.1
+1.0.1 > 1.0.0
+1.0.0 = 1.0.0
+1.0.0 < 1.0.1
+1.0.1 < 2.3.2-r1
+2.3.2-r1 < 2.4.2
+2.4.2 < 20060720
+20060720 > 3.0.20060720
+3.0.20060720 < 20060720
+20060720 > 1.1
+1.1 = 1.1
+1.1 < 1.1.1-r1
+1.1.1-r1 < 1.1.3-r1
+1.1.3-r1 < 1.1.3-r2
+1.1.3-r2 < 2.1.10-r2
+2.1.10-r2 > 0.7.18-r2
+0.7.18-r2 < 0.17-r6
+0.17-r6 < 2.6.1
+2.6.1 < 2.6.3
+2.6.3 < 3.1.5-r2
+3.1.5-r2 < 3.4.6-r1
+3.4.6-r1 < 3.4.6-r2
+3.4.6-r2 = 3.4.6-r2
+3.4.6-r2 > 2.0.33
+2.0.33 < 2.0.34
+2.0.34 > 1.8.3-r2
+1.8.3-r2 < 1.8.3-r3
+1.8.3-r3 < 4.1
+4.1 < 8.54
+8.54 > 4.1.4
+4.1.4 > 1.2.10-r5
+1.2.10-r5 < 4.1.4-r3
+4.1.4-r3 = 4.1.4-r3
+4.1.4-r3 < 4.2.1
+4.2.1 > 4.1.0
+4.1.0 < 8.11
+8.11 > 1.4.4-r1
+1.4.4-r1 < 2.1.9.200602141850
+2.1.9.200602141850 > 1.6
+1.6 < 2.5.1-r8
+2.5.1-r8 < 2.5.1a-r1
+2.5.1a-r1 > 1.19.2-r1
+1.19.2-r1 > 0.97-r2
+0.97-r2 < 0.97-r3
+0.97-r3 < 1.3.5-r10
+1.3.5-r10 > 1.3.5-r8
+1.3.5-r8 < 1.3.5-r9
+1.3.5-r9 > 1.0
+1.0 < 1.1
+1.1 > 0.9.11
+0.9.11 < 0.9.12
+0.9.12 < 0.9.13
+0.9.13 < 0.9.14
+0.9.14 < 0.9.15
+0.9.15 < 0.9.16
+0.9.16 > 0.3-r2
+0.3-r2 < 6.3
+6.3 < 6.6
+6.6 < 6.9
+6.9 > 0.7.2-r3
+0.7.2-r3 < 1.2.10
+1.2.10 < 20040923-r2
+20040923-r2 > 20040401
+20040401 > 2.0.0_rc3-r1
+2.0.0_rc3-r1 > 1.5
+1.5 < 4.4
+4.4 > 1.0.1
+1.0.1 < 2.2.0
+2.2.0 > 1.1.0-r2
+1.1.0-r2 > 0.3
+0.3 < 20020207-r2
+20020207-r2 > 1.31-r2
+1.31-r2 < 3.7
+3.7 > 2.0.1
+2.0.1 < 2.0.2
+2.0.2 > 0.99.163
+0.99.163 < 2.6.15.20060110
+2.6.15.20060110 < 2.6.16.20060323
+2.6.16.20060323 < 2.6.19.20061214
+2.6.19.20061214 > 0.6.2-r1
+0.6.2-r1 < 0.6.3
+0.6.3 < 0.6.5
+0.6.5 < 1.3.5-r1
+1.3.5-r1 < 1.3.5-r4
+1.3.5-r4 < 3.0.0-r2
+3.0.0-r2 < 021109-r3
+021109-r3 < 20060512
+20060512 > 1.24
+1.24 > 0.9.16-r1
+0.9.16-r1 < 3.9_pre20060124
+3.9_pre20060124 > 0.01
+0.01 < 0.06
+0.06 < 1.1.7
+1.1.7 < 6b-r7
+6b-r7 > 1.12-r7
+1.12-r7 < 1.12-r8
+1.12-r8 > 1.1.12
+1.1.12 < 1.1.13
+1.1.13 > 0.3
+0.3 < 0.5
+0.5 < 3.96.1
+3.96.1 < 3.97
+3.97 > 0.10.0-r1
+0.10.0-r1 > 0.10.0
+0.10.0 < 0.10.1_rc1
+0.10.1_rc1 > 0.9.11
+0.9.11 < 394
+394 > 2.31
+2.31 > 1.0.1
+1.0.1 = 1.0.1
+1.0.1 < 1.0.3
+1.0.3 > 1.0.2
+1.0.2 = 1.0.2
+1.0.2 > 1.0.1
+1.0.1 = 1.0.1
+1.0.1 < 1.2.2
+1.2.2 < 2.1.10
+2.1.10 > 1.0.1
+1.0.1 < 1.0.2
+1.0.2 < 3.5.5
+3.5.5 > 1.1.1
+1.1.1 > 0.9.1
+0.9.1 < 1.0.2
+1.0.2 > 1.0.1
+1.0.1 < 1.0.2
+1.0.2 > 1.0.1
+1.0.1 = 1.0.1
+1.0.1 < 1.0.5
+1.0.5 > 0.8.5
+0.8.5 < 0.8.6-r3
+0.8.6-r3 < 2.3.17
+2.3.17 > 1.10-r5
+1.10-r5 < 1.10-r9
+1.10-r9 < 2.0.2
+2.0.2 > 1.1a
+1.1a < 1.3a
+1.3a > 1.0.2
+1.0.2 < 1.2.2-r1
+1.2.2-r1 > 1.0-r1
+1.0-r1 > 0.15.1b
+0.15.1b < 1.0.1
+1.0.1 < 1.06-r1
+1.06-r1 < 1.06-r2
+1.06-r2 > 0.15.1b-r2
+0.15.1b-r2 > 0.15.1b
+0.15.1b < 2.5.7
+2.5.7 > 1.1.2.1-r1
+1.1.2.1-r1 > 0.0.31
+0.0.31 < 0.0.50
+0.0.50 > 0.0.16
+0.0.16 < 0.0.25
+0.0.25 < 0.17
+0.17 > 0.5.0
+0.5.0 < 1.1.2
+1.1.2 < 1.1.3
+1.1.3 < 1.1.20
+1.1.20 > 0.9.4
+0.9.4 < 0.9.5
+0.9.5 < 6.3
+6.3 < 6.6
+6.6 > 6.3
+6.3 < 6.6
+6.6 > 1.2.12-r1
+1.2.12-r1 < 1.2.13
+1.2.13 < 1.2.14
+1.2.14 < 1.2.15
+1.2.15 < 8.0.12
+8.0.12 > 8.0.9
+8.0.9 > 1.2.3-r1
+1.2.3-r1 < 1.2.4-r1
+1.2.4-r1 > 0.1
+0.1 < 0.3.5
+0.3.5 < 1.5.22
+1.5.22 > 0.1.11
+0.1.11 < 0.1.12
+0.1.12 < 1.1.4.1
+1.1.4.1 > 1.1.0
+1.1.0 < 1.1.2
+1.1.2 > 1.0.3
+1.0.3 > 1.0.2
+1.0.2 < 2.6.26
+2.6.26 < 2.6.27
+2.6.27 > 1.1.17
+1.1.17 < 1.4.11
+1.4.11 < 22.7-r1
+22.7-r1 < 22.7.3-r1
+22.7.3-r1 > 22.7
+22.7 > 2.1_pre20
+2.1_pre20 < 2.1_pre26
+2.1_pre26 > 0.2.3-r2
+0.2.3-r2 > 0.2.2
+0.2.2 < 2.10.0
+2.10.0 < 2.10.1
+2.10.1 > 02.08.01b
+02.08.01b < 4.77
+4.77 > 0.17
+0.17 < 5.1.1-r1
+5.1.1-r1 < 5.1.1-r2
+5.1.1-r2 > 5.1.1
+5.1.1 > 1.2
+1.2 < 5.1
+5.1 > 2.02.06
+2.02.06 < 2.02.10
+2.02.10 < 2.8.5-r3
+2.8.5-r3 < 2.8.6-r1
+2.8.6-r1 < 2.8.6-r2
+2.8.6-r2 > 2.02-r1
+2.02-r1 > 1.5.0-r1
+1.5.0-r1 > 1.5.0
+1.5.0 > 0.9.2
+0.9.2 < 8.1.2.20040524-r1
+8.1.2.20040524-r1 < 8.1.2.20050715-r1
+8.1.2.20050715-r1 < 20030215
+20030215 > 3.80-r4
+3.80-r4 < 3.81
+3.81 > 1.6d
+1.6d > 1.2.07.8
+1.2.07.8 < 1.2.12.04
+1.2.12.04 < 1.2.12.05
+1.2.12.05 < 1.3.3
+1.3.3 < 2.6.4
+2.6.4 > 2.5.2
+2.5.2 < 2.6.1
+2.6.1 > 2.6
+2.6 < 6.5.1-r1
+6.5.1-r1 > 1.1.35-r1
+1.1.35-r1 < 1.1.35-r2
+1.1.35-r2 > 0.9.2
+0.9.2 < 1.07-r1
+1.07-r1 < 1.07.5
+1.07.5 > 1.07
+1.07 < 1.19
+1.19 < 2.1-r2
+2.1-r2 < 2.2
+2.2 > 1.0.4
+1.0.4 < 20060811
+20060811 < 20061003
+20061003 > 0.1_pre20060810
+0.1_pre20060810 < 0.1_pre20060817
+0.1_pre20060817 < 1.0.3
+1.0.3 > 1.0.2
+1.0.2 > 1.0.1
+1.0.1 < 3.2.2-r1
+3.2.2-r1 < 3.2.2-r2
+3.2.2-r2 < 3.3.17
+3.3.17 > 0.59s-r11
+0.59s-r11 < 0.65
+0.65 > 0.2.10-r2
+0.2.10-r2 < 2.01
+2.01 < 3.9.10
+3.9.10 > 1.2.18
+1.2.18 < 1.5.11-r2
+1.5.11-r2 < 1.5.13-r1
+1.5.13-r1 > 1.3.12-r1
+1.3.12-r1 < 2.0.1
+2.0.1 < 2.0.2
+2.0.2 < 2.0.3
+2.0.3 > 0.2.0
+0.2.0 < 5.5-r2
+5.5-r2 < 5.5-r3
+5.5-r3 > 0.25.3
+0.25.3 < 0.26.1-r1
+0.26.1-r1 < 5.2.1.2-r1
+5.2.1.2-r1 < 5.4
+5.4 > 1.60-r11
+1.60-r11 < 1.60-r12
+1.60-r12 < 110-r8
+110-r8 > 0.17-r2
+0.17-r2 < 1.05-r4
+1.05-r4 < 5.28.0
+5.28.0 > 0.51.6-r1
+0.51.6-r1 < 1.0.6-r6
+1.0.6-r6 > 0.8.3
+0.8.3 < 1.42
+1.42 < 20030719
+20030719 > 4.01
+4.01 < 4.20
+4.20 > 0.20070118
+0.20070118 < 0.20070207_rc1
+0.20070207_rc1 < 1.0
+1.0 < 1.13.0
+1.13.0 < 1.13.1
+1.13.1 > 0.21
+0.21 > 0.3.7-r3
+0.3.7-r3 < 0.4.10
+0.4.10 < 0.5.0
+0.5.0 < 0.5.5
+0.5.5 < 0.5.7
+0.5.7 < 0.6.11-r1
+0.6.11-r1 < 2.3.30-r2
+2.3.30-r2 < 3.7_p1
+3.7_p1 > 1.3
+1.3 > 0.10.1
+0.10.1 < 4.3_p2-r1
+4.3_p2-r1 < 4.3_p2-r5
+4.3_p2-r5 < 4.4_p1-r6
+4.4_p1-r6 < 4.5_p1-r1
+4.5_p1-r1 > 4.5_p1
+4.5_p1 < 4.5_p1-r1
+4.5_p1-r1 > 4.5_p1
+4.5_p1 > 0.9.8c-r1
+0.9.8c-r1 < 0.9.8d
+0.9.8d < 2.4.4
+2.4.4 < 2.4.7
+2.4.7 > 2.0.6
+2.0.6 = 2.0.6
+2.0.6 > 0.78-r3
+0.78-r3 > 0.3.2
+0.3.2 < 1.7.1-r1
+1.7.1-r1 < 2.5.9
+2.5.9 > 0.1.13
+0.1.13 < 0.1.15
+0.1.15 < 0.4
+0.4 < 0.9.6
+0.9.6 < 2.2.0-r1
+2.2.0-r1 < 2.2.3-r2
+2.2.3-r2 < 013
+013 < 014-r1
+014-r1 > 1.3.1-r1
+1.3.1-r1 < 5.8.8-r2
+5.8.8-r2 > 5.1.6-r4
+5.1.6-r4 < 5.1.6-r6
+5.1.6-r6 < 5.2.1-r3
+5.2.1-r3 > 0.11.3
+0.11.3 = 0.11.3
+0.11.3 < 1.10.7
+1.10.7 > 1.7-r1
+1.7-r1 > 0.1.20
+0.1.20 < 0.1.23
+0.1.23 < 5b-r9
+5b-r9 > 2.2.10
+2.2.10 < 2.3.6
+2.3.6 < 8.0.12
+8.0.12 > 2.4.3-r16
+2.4.3-r16 < 2.4.4-r4
+2.4.4-r4 < 3.0.3-r5
+3.0.3-r5 < 3.0.6
+3.0.6 < 3.2.6
+3.2.6 < 3.2.7
+3.2.7 > 0.3.1_rc8
+0.3.1_rc8 < 22.2
+22.2 < 22.3
+22.3 > 1.2.2
+1.2.2 < 2.04
+2.04 < 2.4.3-r1
+2.4.3-r1 < 2.4.3-r4
+2.4.3-r4 > 0.98.6-r1
+0.98.6-r1 < 5.7-r2
+5.7-r2 < 5.7-r3
+5.7-r3 > 5.1_p4
+5.1_p4 > 1.0.5
+1.0.5 < 3.6.19-r1
+3.6.19-r1 > 3.6.19
+3.6.19 > 1.0.1
+1.0.1 < 3.8
+3.8 > 0.2.3
+0.2.3 < 1.2.15-r3
+1.2.15-r3 > 1.2.6-r1
+1.2.6-r1 < 2.6.8-r2
+2.6.8-r2 < 2.6.9-r1
+2.6.9-r1 > 1.7
+1.7 < 1.7b
+1.7b < 1.8.4-r3
+1.8.4-r3 < 1.8.5
+1.8.5 < 1.8.5_p2
+1.8.5_p2 > 1.1.3
+1.1.3 < 3.0.22-r3
+3.0.22-r3 < 3.0.24
+3.0.24 = 3.0.24
+3.0.24 = 3.0.24
+3.0.24 < 4.0.2-r5
+4.0.2-r5 < 4.0.3
+4.0.3 > 0.98
+0.98 < 1.00
+1.00 < 4.1.4-r1
+4.1.4-r1 < 4.1.5
+4.1.5 > 2.3
+2.3 < 2.17-r3
+2.17-r3 > 0.1.7
+0.1.7 < 1.11
+1.11 < 4.2.1-r11
+4.2.1-r11 > 3.2.3
+3.2.3 < 3.2.4
+3.2.4 < 3.2.8
+3.2.8 < 3.2.9
+3.2.9 > 3.2.3
+3.2.3 < 3.2.4
+3.2.4 < 3.2.8
+3.2.8 < 3.2.9
+3.2.9 > 1.4.9-r2
+1.4.9-r2 < 2.9.11_pre20051101-r2
+2.9.11_pre20051101-r2 < 2.9.11_pre20051101-r3
+2.9.11_pre20051101-r3 > 2.9.11_pre20051101
+2.9.11_pre20051101 < 2.9.11_pre20061021-r1
+2.9.11_pre20061021-r1 < 2.9.11_pre20061021-r2
+2.9.11_pre20061021-r2 < 5.36-r1
+5.36-r1 > 1.0.1
+1.0.1 < 7.0-r2
+7.0-r2 > 2.4.5
+2.4.5 < 2.6.1.2
+2.6.1.2 < 2.6.1.3-r1
+2.6.1.3-r1 > 2.6.1.3
+2.6.1.3 < 2.6.1.3-r1
+2.6.1.3-r1 < 12.17.9
+12.17.9 > 1.1.12
+1.1.12 > 1.1.7
+1.1.7 < 2.5.14
+2.5.14 < 2.6.6-r1
+2.6.6-r1 < 2.6.7
+2.6.7 < 2.6.9-r1
+2.6.9-r1 > 2.6.9
+2.6.9 > 1.39
+1.39 > 0.9
+0.9 < 2.61-r2
+2.61-r2 < 4.5.14
+4.5.14 > 4.09-r1
+4.09-r1 > 1.3.1
+1.3.1 < 1.3.2-r3
+1.3.2-r3 < 1.6.8_p12-r1
+1.6.8_p12-r1 > 1.6.8_p9-r2
+1.6.8_p9-r2 > 1.3.0-r1
+1.3.0-r1 < 3.11
+3.11 < 3.20
+3.20 > 1.6.11-r1
+1.6.11-r1 > 1.6.9
+1.6.9 < 5.0.5-r2
+5.0.5-r2 > 2.86-r5
+2.86-r5 < 2.86-r6
+2.86-r6 > 1.15.1-r1
+1.15.1-r1 < 8.4.9
+8.4.9 > 7.6-r8
+7.6-r8 > 3.9.4-r2
+3.9.4-r2 < 3.9.4-r3
+3.9.4-r3 < 3.9.5-r2
+3.9.5-r2 > 1.1.9
+1.1.9 > 1.0.6
+1.0.6 < 5.9
+5.9 < 6.5
+6.5 > 0.40-r1
+0.40-r1 < 2.25b-r5
+2.25b-r5 < 2.25b-r6
+2.25b-r6 > 1.0.4
+1.0.4 < 1.0.5
+1.0.5 < 1.4_p12-r2
+1.4_p12-r2 < 1.4_p12-r5
+1.4_p12-r5 > 1.1
+1.1 > 0.2.0-r1
+0.2.0-r1 < 0.2.1
+0.2.1 < 0.9.28-r1
+0.9.28-r1 < 0.9.28-r2
+0.9.28-r2 < 0.9.28.1
+0.9.28.1 > 0.9.28
+0.9.28 < 0.9.28.1
+0.9.28.1 < 087-r1
+087-r1 < 103
+103 < 104-r11
+104-r11 > 104-r9
+104-r9 > 1.23-r1
+1.23-r1 > 1.23
+1.23 < 1.23-r1
+1.23-r1 > 1.0.2
+1.0.2 < 5.52-r1
+5.52-r1 > 1.2.5_rc2
+1.2.5_rc2 > 0.1
+0.1 < 0.71-r1
+0.71-r1 < 20040406-r1
+20040406-r1 > 2.12r-r4
+2.12r-r4 < 2.12r-r5
+2.12r-r5 > 0.0.7
+0.0.7 < 1.0.3
+1.0.3 < 1.8
+1.8 < 7.0.17
+7.0.17 < 7.0.174
+7.0.174 > 7.0.17
+7.0.17 < 7.0.174
+7.0.174 > 1.0.1
+1.0.1 < 1.1.1-r3
+1.1.1-r3 > 0.3.4_pre20061029
+0.3.4_pre20061029 < 0.4.0
+0.4.0 > 0.1.2
+0.1.2 < 1.10.2
+1.10.2 < 2.16
+2.16 < 28
+28 > 0.99.4
+0.99.4 < 1.13
+1.13 > 1.0.1
+1.0.1 < 1.1.2-r2
+1.1.2-r2 > 1.1.0
+1.1.0 < 1.1.1
+1.1.1 = 1.1.1
+1.1.1 > 0.6.0
+0.6.0 < 6.6.3
+6.6.3 > 1.1.1
+1.1.1 > 1.1.0
+1.1.0 = 1.1.0
+1.1.0 > 0.2.0
+0.2.0 < 0.3.0
+0.3.0 < 1.1.1
+1.1.1 < 1.2.0
+1.2.0 > 1.1.0
+1.1.0 < 1.6.5
+1.6.5 > 1.1.0
+1.1.0 < 1.4.2
+1.4.2 > 1.1.1
+1.1.1 < 2.8.1
+2.8.1 > 1.2.0
+1.2.0 < 4.1.0
+4.1.0 > 0.4.1
+0.4.1 < 1.9.1
+1.9.1 < 2.1.1
+2.1.1 > 1.4.1
+1.4.1 > 0.9.1-r1
+0.9.1-r1 > 0.8.1
+0.8.1 < 1.2.1-r1
+1.2.1-r1 > 1.1.0
+1.1.0 < 1.2.1
+1.2.1 > 1.1.0
+1.1.0 > 0.1.1
+0.1.1 < 1.2.1
+1.2.1 < 4.1.0
+4.1.0 > 0.2.1-r1
+0.2.1-r1 < 1.1.0
+1.1.0 < 2.7.11
+2.7.11 > 1.0.2-r6
+1.0.2-r6 > 1.0.2
+1.0.2 > 0.8
+0.8 < 1.1.1-r4
+1.1.1-r4 < 222
+222 > 1.0.1
+1.0.1 < 1.2.12-r1
+1.2.12-r1 > 1.2.8
+1.2.8 < 1.2.9.1-r1
+1.2.9.1-r1 > 1.2.9.1
+1.2.9.1 < 2.31-r1
+2.31-r1 > 2.31
+2.31 > 1.2.3-r1
+1.2.3-r1 > 1.2.3
+1.2.3 < 4.2.5
+4.2.5 < 4.3.2-r2
+1.3-r0 < 1.3.1-r0
+1.3_pre1-r1 < 1.3.2
+1.0_p10-r0 > 1.0_p9-r0
+0.1.0_alpha_pre2 < 0.1.0_alpha