summaryrefslogtreecommitdiffstats
path: root/zarb-ml/mageia-sysadm/2011-February/002825.html
diff options
context:
space:
mode:
Diffstat (limited to 'zarb-ml/mageia-sysadm/2011-February/002825.html')
-rw-r--r--zarb-ml/mageia-sysadm/2011-February/002825.html12989
1 files changed, 12989 insertions, 0 deletions
diff --git a/zarb-ml/mageia-sysadm/2011-February/002825.html b/zarb-ml/mageia-sysadm/2011-February/002825.html
new file mode 100644
index 000000000..e3014b4dc
--- /dev/null
+++ b/zarb-ml/mageia-sysadm/2011-February/002825.html
@@ -0,0 +1,12989 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+ <HEAD>
+ <TITLE> [Mageia-sysadm] [419] Import cleaned perl-URPM
+ </TITLE>
+ <LINK REL="Index" HREF="index.html" >
+ <LINK REL="made" HREF="mailto:mageia-sysadm%40mageia.org?Subject=Re%3A%20%5BMageia-sysadm%5D%20%5B419%5D%20Import%20cleaned%20perl-URPM&In-Reply-To=%3C20110204134150.A7AE93FFE7%40valstar.mageia.org%3E">
+ <META NAME="robots" CONTENT="index,nofollow">
+ <META http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <LINK REL="Previous" HREF="002554.html">
+ <LINK REL="Next" HREF="002555.html">
+ </HEAD>
+ <BODY BGCOLOR="#ffffff">
+ <H1>[Mageia-sysadm] [419] Import cleaned perl-URPM</H1>
+ <B>root at mageia.org</B>
+ <A HREF="mailto:mageia-sysadm%40mageia.org?Subject=Re%3A%20%5BMageia-sysadm%5D%20%5B419%5D%20Import%20cleaned%20perl-URPM&In-Reply-To=%3C20110204134150.A7AE93FFE7%40valstar.mageia.org%3E"
+ TITLE="[Mageia-sysadm] [419] Import cleaned perl-URPM">root at mageia.org
+ </A><BR>
+ <I>Fri Feb 4 14:43:09 CET 2011</I>
+ <P><UL>
+ <LI>Previous message: <A HREF="002554.html">[Mageia-sysadm] [418] add README file
+</A></li>
+ <LI>Next message: <A HREF="002555.html">[Mageia-sysadm] [420] - import cleaned mageia-lxde-config
+</A></li>
+ <LI> <B>Messages sorted by:</B>
+ <a href="date.html#2825">[ date ]</a>
+ <a href="thread.html#2825">[ thread ]</a>
+ <a href="subject.html#2825">[ subject ]</a>
+ <a href="author.html#2825">[ author ]</a>
+ </LI>
+ </UL>
+ <HR>
+<!--beginarticle-->
+<PRE>Revision: 419
+Author: dmorgan
+Date: 2011-02-04 14:41:50 +0100 (Fri, 04 Feb 2011)
+Log Message:
+-----------
+Import cleaned perl-URPM
+
+Added Paths:
+-----------
+ rpm/perl-URPM/
+ rpm/perl-URPM/trunk/
+ rpm/perl-URPM/trunk/.perl_checker
+ rpm/perl-URPM/trunk/ChangeLog
+ rpm/perl-URPM/trunk/MANIFEST
+ rpm/perl-URPM/trunk/META.yml
+ rpm/perl-URPM/trunk/Makefile.PL
+ rpm/perl-URPM/trunk/NEWS
+ rpm/perl-URPM/trunk/README
+ rpm/perl-URPM/trunk/URPM/
+ rpm/perl-URPM/trunk/URPM/.perl_checker
+ rpm/perl-URPM/trunk/URPM/Build.pm
+ rpm/perl-URPM/trunk/URPM/Query.pm
+ rpm/perl-URPM/trunk/URPM/Resolve.pm
+ rpm/perl-URPM/trunk/URPM/Signature.pm
+ rpm/perl-URPM/trunk/URPM.pm
+ rpm/perl-URPM/trunk/URPM.xs
+ rpm/perl-URPM/trunk/t/
+ rpm/perl-URPM/trunk/t/00prepare.t
+ rpm/perl-URPM/trunk/t/buggy_synthesis.cz
+ rpm/perl-URPM/trunk/t/empty_synthesis.cz
+ rpm/perl-URPM/trunk/t/fatal.t
+ rpm/perl-URPM/trunk/t/parse.t
+ rpm/perl-URPM/trunk/t/pod.t
+ rpm/perl-URPM/trunk/t/rpmdb.t
+ rpm/perl-URPM/trunk/t/sort_graph.t
+ rpm/perl-URPM/trunk/t/synthesis.t
+ rpm/perl-URPM/trunk/t/test-rpm.spec
+ rpm/perl-URPM/trunk/typemap
+
+Added: rpm/perl-URPM/trunk/.perl_checker
+===================================================================
+--- rpm/perl-URPM/trunk/.perl_checker (rev 0)
++++ rpm/perl-URPM/trunk/.perl_checker 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,2 @@
++Compress::Zlib
++File::Path
+
+Added: rpm/perl-URPM/trunk/ChangeLog
+===================================================================
+--- rpm/perl-URPM/trunk/ChangeLog (rev 0)
++++ rpm/perl-URPM/trunk/ChangeLog 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,4159 @@
++2010-07-23 02:43
++
++ * - fix deferencement on hash (instead hashref), warning triggered
++ by perl 5.12
++
++2010-04-23 16:06
++
++ * only print debug message if debug callback is defined
++
++2010-04-23 15:40
++
++ * 3.35
++
++2010-04-23 15:39
++
++ * honour search medias when using --auto-select
++
++2010-03-23 15:48
++
++ * 3.34.1
++
++2010-03-23 15:47
++
++ * check selected packages for unsatisfied requires when a promoted
++ package is backtracked and no replacement is found
++
++ (#57224, Anssi Hannula)
++
++2010-03-23 15:47
++
++ * 3.34
++
++2010-02-24 11:01
++
++ * adjust rpm.org/rpm5.org detection code
++
++ It used to assume that rpm.org had version numbers &lt; 4.7, but
++ it's
++ no longer true with rpm 4.8 being released. Test against 5.0
++ since
++ rpm5.org releases started at 5.0
++
++2010-02-12 15:58
++
++ * check for conflicting selected packages before selecting a
++ package
++
++ check for conflicting selected packages before selecting a
++ package
++ instead of after selecting it, to avoid having to unselect
++ package
++ in case of conflict (which incorrectly unselected packages with
++ unsatisfied dependencies as well, making the following
++ backtrack_selected
++ call behave wrongly as it simply noticed that the package is no
++ longer
++ required)
++
++ Here's the second patch again, now with the function comment
++ updated
++ and added _remove_all_rejected_from() call so that prerejections
++ are
++ still cleared (this was previously called from the
++ removed disable_selected() call). Testsuites pass.
++
++ Patch by Anssi Hannula, fixes #57224
++
++2009-10-05 09:48
++
++ * 3.33
++
++2009-10-03 15:18
++
++ * Improve previous fix
++
++2009-10-03 14:56
++
++ * fix lookup of existing pubkeys (#53710)
++
++2009-08-10 14:37
++
++ * update NEWS for 3.32
++
++2009-08-10 14:37
++
++ * 3.32
++
++2009-08-10 14:37
++
++ * comment out unused code
++
++2009-08-10 14:37
++
++ * use set_rejected_and_compute_diff_provides for package removal
++
++ Patch by Anssi Hannula, fixes bug #52667
++
++ k1-1 provides k, but not k1-2
++ l-1 and l-2 requires k
++ m-1 requires k but not m-2
++ n requires m
++
++ User has l-1, m-1, n-1, k1-1.
++
++ There is only one upgrade path:
++ k1-1 -&gt; k1-2
++ m-1 -&gt; m-2
++ removal of l-1
++
++ When transaction is created with all of them (e.g. what
++ --auto-select does
++ first), the path is resolved correctly.
++ However, when the upgrade is triggered with the upgrade of k1,
++ and l is in RPM
++ db before n, resolving proceeds as follows:
++ 1. k1 selected and old version rejected
++ 2. l is promoted
++ 3. m is promoted
++ 4. l-2 is therefore selected
++ 5. no packages are found for k (as k1-1 was rejected in step 1)
++ 6. backtrack_selected calls resolve_rejected to reject the chain
++ 7. rejection process rejects l, m, n
++ 8. m-2 is selected because of step 3
++ End result: n is wrongly removed.
++
++ Therefore, when using --auto-select (with --split-length 1
++ --split-level 1 in
++ this small case, to force splitting) to trigger the upgrade, the
++ early resolve
++ is done correctly, but the first splitted transaction (&quot;rpms
++ sorted by
++ dependencies&quot; has k1 and m separately, so split is tried) tries
++ to remove n and
++ URPM fallbacks to single big transaction.
++
++ In reverse, when using &quot;urpmi k1&quot; to trigger the upgrade, urpmi
++ asks user
++ confirmation for n removal, but the transaction is created with
++ both k1 and m
++ (&quot;rpms sorted by dependencies&quot; has k1+m, so they are put in same
++ transaction),
++ thus triggering the correct behaviour and n is not really removed
++ after all,
++ even if user agreed to it.
++
++ Attached patch fixes this by switching backtrack_selected() to
++ use
++ set_rejected_and_compute_diff_provides() for package removal
++ instead of
++ resolve_rejected_(). The code already contained a comment
++ indicating that
++ diff_provides code should be applied.
++ The patch introduces no regression in the urpmi and perl-URPM
++ testsuites.
++
++2009-08-05 20:24
++
++ * Obey options (keep, nodeps) when unselecting current package in
++ the case
++ that was added in 3.31 (Anssi Hannula). In a simple mistake,
++ %options was
++ not passed to backtrack_selected.
++
++2009-08-05 20:17
++
++ * remove extra newline from NEWS
++
++2009-08-05 11:15
++
++ * remove no longer used SPEC_VERIFY constant
++
++2009-08-04 16:47
++
++ * disttag &amp; distepoch isn't utf8&#8230;
++
++2009-08-04 16:28
++
++ * cast (es-s) to U32 (as the hv_fetch prototype expects) rather
++ than casting strlen(s) to signed
++
++2009-07-28 16:15
++
++ * 3.31
++
++2009-07-28 16:15
++
++ * we need to link with rpmbuild with rpm 4.6
++
++2009-07-28 13:16
++
++ * update NEWS file
++
++2009-07-28 13:16
++
++ * add a backtrack entry &quot;conflicts&quot; for avoided packages in
++ backtrack_selected
++
++ Patch from Anssi Hannula, fixes part of bug #52153
++
++2009-07-28 13:15
++
++ * do not try to promote to an older package
++
++ Patch by Anssi Hannula, fixes bug #52460
++
++ When searching for possible promotions, _handle_diff_provides()
++ allows
++ downgrade as well as upgrade.
++
++ However, downgrade is not currently supported, and will fail
++ early in
++ _no_more_recent_installed_and_providing(), called from
++ resolve_requested__no_suggests_().
++
++ As no backtracking is done for early failures in this function
++ (should it be?
++ dunno), the promotion gets forgotten and a failing transaction
++ will occur.
++
++ Simple fix is to only allow upgrade before doing the promotion.
++ Patch attached.
++ It introduces no regressions in urpmi or perl-URPM testsuite.
++
++2009-07-28 13:15
++
++ * unselect current package if an avoided package is already
++ selected
++
++ Patch by Anssi Hannula, fixes bug #52145
++
++ If package 'a' Conflicts on 'b', and user (or a dependency chain)
++ tries to
++ install both at the same time, perl-URPM will only detect the
++ conflict if
++ package 'a' gets selected first (this depends on hdlist order),
++ as
++ _set_rejected_from is only called in one direction from
++ _handle_conflicts and
++ it does not detect that a package it is about to reject_from is
++ already
++ selected.
++
++ This bug currently causes a failure in urpmi
++ handle-conflict-deps2 testcase.
++
++ This commit checks if avoided package is already selected, and
++ unselects
++ current package in such a case
++
++2009-07-28 13:15
++
++ * move part of _handle_conflicts to _handle_conflicts_with_selected
++
++ Patch by Anssi Hannula, first step toward fixing bug #52145
++
++ If package 'a' Conflicts on 'b', and user (or a dependency chain)
++ tries to
++ install both at the same time, perl-URPM will only detect the
++ conflict if
++ package 'a' gets selected first (this depends on hdlist order),
++ as
++ _set_rejected_from is only called in one direction from
++ _handle_conflicts and
++ it does not detect that a package it is about to reject_from is
++ already
++ selected.
++
++ This patch moves part of _handle_conflicts to
++ _handle_conflicts_with_selected
++ to be called before dependencies get added, needed by next patch
++
++2009-07-28 13:14
++
++ * _handle_conflicts: check all provides for conflicts, not just
++ package name
++
++ Patch by Anssi Hannula, fixes bug #52135
++
++ If package a has &quot;Conflicts: x&quot; and b has &quot;Provides: x&quot;,
++ installing both at the
++ same time creates a failing transaction (instead of producing the
++ &quot;cannot
++ install a (or b), continue?&quot;) as perl-URPM does not detect the
++ conflict, as it
++ just checks the conflicts on the package name (it does the
++ correct thing with
++ installed packages, though).
++
++ _handle_conflicts: call _set_rejected_from if any provides match
++ the conflict,
++ instead of just package name
++
++2009-07-28 13:13
++
++ * keep psel/promote info and remove deadlocked pkg instead of
++ aborting upgrade
++
++ Patch from Anssi Hannula, fixes bug #52105
++
++ lib64gcj9 has to be removed (conflicts), therefore so does
++ libgcj9-src (x86_64)
++ that depends on it. Installed java-1.5.0-gcj-src depends on
++ libgcj9-src, so
++ perl-URPM tries to promote the i586 libgcj9-src for it. However,
++ strict_arch
++ check prohibits changing the arch, so it falls back to
++ backtracking.
++ Backtracking finds libgcj9-src again and tries to select it;
++ however, it drops
++ $dep-&gt;{psel} and $dep-&gt;{promote}, so when it fails again,
++ perl-URPM does not
++ know java-1.5.0-gcj-src should also be removed due to the failed
++ promotion.
++
++ This patch changes the code in backtrack_selected in two ways:
++
++ 1) When a replacement package is found, keep {promote} and {psel}
++ info, so that
++ when backtrack_selected is run the second time it correctly
++ handles the failed
++ promotion.
++ 2) When such a replacement fails as well and the deadlock
++ protection is
++ triggered, do not switch to keep mode for the package that caused
++ the promotion
++ (it would unselect all the packages involved in the update that
++ caused the
++ promotion). Instead proceed to remove it as usual.
++
++ The patch introduces no failures on the urpmi testsuite.
++
++2009-07-28 13:12
++
++ * keep track of sources for obsoleted/removed levels
++
++ Patch by Anssi Hannula, fixes bug #50666
++
++ removed/obsoleted levels are set in set_rejected() when a package
++ is rejected
++ (i.e. removed) or a rejection reason is added. They keep track on
++ whether the
++ package is removed and/or obsoleted.
++
++ When the package has both flags and one of the rejection reasons
++ is removed by
++ _remove_rejected_from(), appropriate flags do not get removed.
++
++ The case I encountered: the package is set for removal when a
++ package it
++ depends on fails upgrade due to unsatisfied dependency and has to
++ be removed
++ (backtrack_selected =&gt; resolve_rejected, causing removed=1), and
++ the package is
++ then promoted (causing obsoleted=1). However, the promotion fails
++ due to the
++ same unsatisfied dependency and backtrack_selected =&gt;
++ disable_selected_and_unrequested_dependencies =&gt; disable_selected
++ =&gt;
++ _remove_all_rejected_from =&gt; _remove_rejected_from gets called.
++ This removes
++ the latter rejection reason, but leaves flags, including the now
++ wrong
++ obsoleted=1. Thus the package is not explicitely removed as an
++ obsoletion is
++ assumed, therefore failing the transaction.
++
++2009-07-27 12:42
++
++ * use pkg-config for rpm 4.x too
++
++2009-07-27 12:41
++
++ * remove unused variable
++
++2009-07-26 16:07
++
++ * rephrase wording, only support for querying %disttag &amp; %distepoch
++ so far, no support
++ for using %distepoch i version comparisions yet...
++
++2009-07-26 16:06
++
++ * add support for %disttag &amp; %distepoch
++
++2009-07-26 08:36
++
++ * just use (void) rather than assign rpmtsFree() since it seems to
++ cause crashy behaviour certain places...
++
++2009-07-26 08:07
++
++ * bumping version was forgotten for 3.30 release, might as well
++ bump it up to
++ 3.31 now for next release&#8230;
++
++2009-07-26 08:05
++
++ * update changelog regarding rpm5
++
++2009-07-26 07:08
++
++ * oops, put back line that accidentally got removed in the previous
++ commit&#8230;
++
++2009-07-26 06:50
++
++ * enable and fix additional (-Wextra) warnings
++
++2009-07-26 06:38
++
++ * fix gcc warnings about values not being used
++
++2009-07-26 06:23
++
++ * * clean out compatibility code for older rpm versions that's not
++ really
++ supported anymore anyways and move out as much as possible
++ rpm5.org
++ compatibility code out of URPM into new rpm46compat.h @ rpm5.org
++
++2009-07-25 20:50
++
++ * add support for specifying custom filter for compression with
++ build_synthesis()
++
++2009-07-22 18:21
++
++ * really clean up temporary files &amp; directories properly
++
++2009-07-22 18:19
++
++ * prevent distepoch &amp; disttag to be added and appended to package
++ filename
++
++2009-05-11 13:26
++
++ * Removed forgotten debugging logs
++
++2009-05-11 13:22
++
++ * Add bug #
++
++2009-05-11 13:17
++
++ * Release 3.30
++
++2009-05-11 13:17
++
++ * Use key IDs to check if a key is already known or not
++
++ This has the side-effect that if we get a newer public key
++ corresponding
++ to an already known key id, it won't get updated, but for now RPM
++ doesn't let us do that anyway. If a pubkey file contains multiple
++ keys,
++ we no longer handle this case, but I don't think this has been
++ widely
++ tested, if ever...
++
++2009-05-11 13:17
++
++ * Fix comment
++
++2009-05-11 13:17
++
++ * Introduce get_gpg_fingerprint XS function
++
++2009-03-27 14:58
++
++ * 3.29
++
++2009-03-27 14:58
++
++ * Fix regression introduced in fix for bug #47803
++
++ This reverts the previous commit
++
++ only compute diff_provides when the package is newly rejected, in
++ set_rejected_and_compute_diff_provides
++
++ Try this incremental patch. It fixes
++ set_rejected_and_compute_diff_provides to
++ not compute diff_provides if package was already rejected (and
++ thus the
++ dependencies properly handled already).
++
++2009-03-27 10:28
++
++ * Revert part of the fix for bug #47803 since it breaks upgrades
++ from 2008.1
++
++2009-03-25 13:41
++
++ * 3.28:
++
++2009-03-25 13:22
++
++ * Postpone user choices as much as possible
++
++ Fixes bug #48100, patch from Anssi Hannula
++ Package A requires D and E.
++ Package B provides D and E.
++ Package C provides E.
++
++ If the require on E happens to be resolved first, then perl-URPM
++ will
++ prompt the user, even though installing B is enough.
++
++2009-03-24 16:50
++
++ * Change format of &quot;rpm sorted by dependencies&quot; string
++
++2009-03-24 15:55
++
++ * 3.27
++
++2009-03-23 10:03
++
++ * Don't silently install Suggests:, fixes bug #47934
++
++ When installing a package which suggests an uninstalled package,
++ urpmi
++ currently installs both packages without asking the user while it
++ asks
++ when installing a package which requires an uninstalled package.
++ This is
++ because we call resolve_requested__no_suggests to find which
++ suggested
++ package to install, but this mark the package as requested as
++ well (and
++ we don't ask for confirmation before installing a requested
++ package).
++ This patch calls resolve_requested__no_suggests_ (with a trailing
++ '_')
++ instead which is the same as resolve_requested__no_suggests but
++ does not
++ mark the packages as requested.
++
++2009-03-23 09:40
++
++ * fix _handle_diff_provides in case of impossible-to-satisfy
++ selected packages
++
++ Fixes bug #48223, patch from Anssi Hannula
++
++ Currently, if _handle_diff_provides finds unsatisfied requires on
++ an already
++ selected package, and cannot find any packages from the repo that
++ satisfy
++ these, it calls resolve_rejected_ (or
++ set_rejected_and_compute_diff_provides
++ after fix to bug #47803) (as it does when those unsatisfied
++ requires are on an
++ installed package, which was always the case before r242656).
++ However, those should be called with installed packages only.
++
++ Attached patch makes _handle_diff_provides call
++ disable_selected_and_unrequested_dependencies and
++ _set_rejected_from in case of
++ selected packages.
++
++2009-03-20 18:32
++
++ * check rep for another pkg providing X if the prev pkg gets
++ removed due to a conflict
++
++ Fixes bug #47803, patch from Anssi Hannula
++
++ Closer look at urpmi revealed it only does this if a provide X is
++ removed from
++ an upgraded package, not when a package providing X has to be
++ removed.
++
++ i.e. this works:
++
++ A provides foo
++ B provides foo
++ C requires foo
++
++ Installed A,C.
++
++ A is upgraded and Provides:foo is dropped, B gets installed in
++ order to
++ keep C.
++
++ But this won't:
++
++ A provides foo
++ A requires dep
++ B provides foo
++ C requires foo
++ D provides dep
++
++ Installed A,C,D.
++
++ D is upgraded and Provides:dep is dropped, A gets removed, C gets
++ removed.
++
++2009-03-05 11:14
++
++ * 3.26
++
++2009-03-05 11:13
++
++ * (verify_signature) make checking urpmi signatures works in
++ chrooted environments
++ (especially important for installer where there's no rpmdb in /
++ (really
++ /var/lib/rpm) and thus no keys to check against)
++
++2009-01-16 14:48
++
++ * Release 3.25
++
++2009-01-16 14:48
++
++ * Really fix bug #46874
++
++2009-01-13 14:27
++
++ * Version 3.24 - 13 January 2009, by Christophe Fergeau
++
++ - fix sorting choices on provided version (feature introduced in
++ 3.08,
++ but was not working if packages were coming from different
++ repository)
++ - when a &quot;Requires:&quot; can be fullfilled by several different
++ packages and
++ one of those packages is explicitly required by another package
++ which
++ is also being installed, silently choose this package instead of
++ letting
++ the choice up to perl-URPM user (fixes bug #46874)
++
++2009-01-12 08:04
++
++ * add comments
++
++2009-01-12 08:03
++
++ * - drop parse_rpms (unused, parse_rpms_build_headers or parse_rpm
++ are used instead)
++ - add a comment
++
++2009-01-12 07:59
++
++ * add a comment
++
++2009-01-12 07:56
++
++ * - drop function fuzzy_parse() (it is unused)
++ - add some comment
++
++2009-01-09 14:40
++
++ * add a comment
++
++2009-01-09 14:39
++
++ * add some comment
++
++2009-01-09 14:24
++
++ * - @unsatisfied is a better var name than @l
++ - add some comment
++
++2009-01-08 13:46
++
++ * make it clear the func is local
++
++2009-01-08 13:45
++
++ * add a comment
++
++2009-01-08 09:24
++
++ * Favour required packages when we have several choices to fulfill
++ a &quot;requires&quot;, fixes bug #46874
++
++2009-01-06 15:55
++
++ * - add some comment
++ - enhance a comment
++
++2009-01-06 14:05
++
++ * document a &quot;hack&quot;
++
++2008-12-15 17:02
++
++ * - fix sorting choices on provided version (feature introduced in
++ 3.08,
++ but was not working if packages were coming from different
++ repository)
++
++2008-12-15 11:08
++
++ * 3.23
++
++2008-12-15 11:05
++
++ * - fix bad free() (thanks to glibc for detecting it)
++
++2008-12-12 11:04
++
++ * 3.22
++
++2008-12-12 09:19
++
++ * - fix scriptlet failing:
++ adapt to librpm4.6, rpmtsSetRootDir(ts, &quot;&quot;) is forbidden
++
++2008-12-09 16:40
++
++ * revert wrong commit
++
++2008-12-09 16:33
++
++ * correctly clean temp directories
++
++2008-12-09 16:05
++
++ * 3.21
++
++2008-12-09 16:04
++
++ * - adapt to librpm4.6
++
++2008-12-09 16:03
++
++ * - adapt to rpm 4.6 changes:
++ - headerNextIterator -&gt; headerNext
++ - headerAddEntry -&gt; headerPut
++ - headerModifyEntry -&gt; headerMod
++
++2008-12-09 16:02
++
++ * - adapt to rpm 4.6 changes: headerGetEntry -&gt; headerGet
++
++2008-12-09 16:00
++
++ * - adapt to some easy rpm 4.6 changes:
++ - headerSprintf -&gt; headerFormat
++ - headerAddEntry -&gt; headerPutString
++ - headerRemoveEntry -&gt; headerDel
++ - rpmProblemGetLong -&gt; rpmProblemGetDiskNeed
++
++2008-12-09 15:55
++
++ * free the iterator *after* use
++ (otherwise it segfaults with 4.6.0-rc1, and i wonder how it
++ worked before...)
++
++2008-12-09 15:52
++
++ * do free the ts after user, this is especially needed since
++ rpmVerifySignature
++ (wrongly) called in rpmReadPackageFile can open the rpmdb which
++ won't get
++ closed if ts is not closed
++
++2008-12-09 15:50
++
++ * - don't handle %_sourcedir specially, it's not needed
++ - use an absolute filename for %_topdir, it seems to help
++ (bug in rpm 4.6.0-rc1?)
++
++2008-12-09 15:49
++
++ * - list_rpm_tag() is no more
++ - remove a failing test (old)
++
++2008-12-09 15:47
++
++ * - drop list_rpm_tag()
++
++2008-12-09 15:45
++
++ * adapt types to rpm-4.6.x
++
++2008-12-08 17:35
++
++ * fix rpmRelocation usage with rpm 5.2
++
++2008-10-14 17:35
++
++ * 3.20
++
++2008-10-14 17:35
++
++ * - $trans-&gt;run can now return both the translated errors, and some
++ parsable
++ errors (useful for example to detect diskspace issues)
++
++2008-10-14 08:51
++
++ * use rpmuint64_t rather than long long, we know that it should
++ stay compatible:)
++
++2008-10-10 09:14
++
++ * fix build with rpm5.org HEAD
++
++2008-10-07 10:47
++
++ * 3.19
++
++2008-10-07 10:46
++
++ * - handle flag &quot;replacefiles&quot;
++
++2008-07-18 18:09
++
++ * add filelinktos() &amp; dirnames() to URPM::Package
++
++2008-07-17 20:03
++
++ * ensure that initSourceHeader gets run for rpm5.org, otherwise
++ querying of spec files won't work
++
++2008-07-14 16:49
++
++ * fix build with rpm5.org HEAD
++
++2008-07-07 21:53
++
++ * 3.18
++
++2008-07-07 14:08
++
++ * - revert change introduced in 3.16 (it breaks too much, eg
++ superuser--priority-upgrade.t test case), and introduce
++ $state-&gt;{rejected_already_installed} instead
++
++2008-07-07 13:23
++
++ * fix typo in description
++
++2008-07-04 13:06
++
++ * 3.17
++
++2008-07-04 13:05
++
++ * add removed_or_obsoleted_packages()
++
++2008-07-04 13:04
++
++ * - handle $state-&gt;{orphans_to_remove} in selected_size() and
++ build_transaction_set()
++
++2008-07-04 11:25
++
++ * - add traverse_tag_find()
++
++2008-07-03 11:25
++
++ * perl_checker compliance
++
++2008-07-03 11:23
++
++ * remove unused vars
++
++2008-07-03 11:22
++
++ * create packages_to_remove() and use it to factorize code
++
++2008-07-01 15:26
++
++ * create rpmtag_from_string() out of Db_traverse_tag
++
++2008-06-26 12:47
++
++ * 3.16
++
++2008-06-26 09:46
++
++ * - when not selecting a package because already installed,
++ but it in $state-&gt;{rejected} with flags {installed}
++
++2008-06-24 09:06
++
++ * adapt tests to -&gt;compare change
++
++2008-06-23 08:42
++
++ * 3.15
++
++2008-06-17 09:39
++
++ * add Anssi name in the log
++
++2008-06-17 09:38
++
++ * - fix urpmi wrongly considering epochless conflicts to match any
++ epoch in a
++ case when urpmi should upgrade a conflicting package to an
++ actually
++ non-conflicting version (cf epochless-conflict-with-promotion
++ urpmi test)
++
++ from Anssi.
++
++ i tested various upgrades from some chroot with 2008.0, 2007.1,
++ 2007.0, and it
++ didn't change the result, so it should be quite safe :)
++
++2008-05-23 08:24
++
++ * 3.14
++
++2008-05-23 08:23
++
++ * - add is_package_installed() in URPM/Resolve.pm
++ (to be used in urpmi 5.20)
++
++2008-05-20 09:54
++
++ * 3.13
++
++2008-05-19 15:17
++
++ * - do not ignore dropped provide from updated package
++ (mdvbz#40842)
++
++2008-05-15 12:04
++
++ * enhance error message
++
++2008-04-14 17:11
++
++ * un-revert rpm5.org cosmetics now that cooker has reopened
++
++2008-04-10 08:16
++
++ * update authors and copyright notic
++
++2008-03-25 13:15
++
++ * revert unneeded commit for now
++
++2008-03-19 04:37
++
++ * fix a typo in a comment &lt;/pedanticlamer&gt;
++
++2008-03-19 04:34
++
++ * make URPM more portable by using standard %{_target_vendor} &amp;
++ %{_target_cpu} macros in stead of Mandriva specific
++ %{_real_vendor} &amp; (now dead) %{_real_arch}
++
++2008-03-19 04:18
++
++ * change x,y check to y,x. More intuitive, for me at least, other
++ order frequently confuses me ;p
++
++2008-03-19 03:24
++
++ * d'oh, argument to hexversion() must of course be passed as
++ strings
++
++2008-03-19 03:12
++
++ * improve rpm version detection
++ really fix callback size for rpm5.org versions
++
++2008-03-07 16:50
++
++ * 3.12
++
++2008-03-07 16:49
++
++ * - do allow to promoting a pkg even if it has unsatisfied require
++ (since the
++ code will then fix the unsatisfied require). fixes &quot;big
++ transaction&quot;
++ (cf urpmi split-transactions--strict-require.t test_efgh())
++
++ this code was introduced long ago (*), the code has
++ changed quite a lot, and it's hard to tell for which reason it
++ was introduced.
++ Maybe the check &quot;obsoletes_overlap&quot; replaces it for good?
++
++ (*) in &quot;r11064 | fpons | 2002-06-13&quot;, search for &quot;try if
++ upgrading the package
++ will be satisfying all the requires&quot;
++
++2008-03-06 16:59
++
++ * ouch, add back 'case RPMPROB_DISKNODES:' removed by mistake :/
++
++2008-03-06 15:25
++
++ * revert back to long long since they're of same size anyways and
++ we avoid warnings that way :)
++
++2008-03-06 14:24
++
++ * simplify as pixel suggested
++ use uint64_t in stead of unsigned long long (which is really the
++ same, but nicer and more consistent with rpm5:)
++
++2008-03-03 12:06
++
++ * minor cosmetics
++
++2008-03-03 00:50
++
++ * move compatibility wrapper to rpm5.org upstream
++
++2008-03-02 23:29
++
++ * more fixes, makes apt-get build succesfully :D
++
++2008-03-02 22:22
++
++ * make all functions inline functions
++
++2008-03-02 22:02
++
++ * some more functions for apt-get..
++
++2008-03-02 18:18
++
++ * make C++ compliant
++ add som function wrappers for apt-get
++
++2008-03-01 12:33
++
++ * define WITH_DB in rpm5compat.h in stead of in Makefile
++ drop useless conditionals for headers as they're already
++ conditional in themself ;)
++
++2008-03-01 12:29
++
++ * do better &quot;detection&quot; of callback size without having to define
++ it in Makefile (inspired by apt)
++
++2008-02-29 21:26
++
++ * try improve on freeing up memory
++
++2008-02-29 19:06
++
++ * be sure to return NULL in case of RPMRC_NOTFOUND
++
++2008-02-29 19:00
++
++ * provide function name in logging
++
++2008-02-29 18:45
++
++ * be sure to always initialize in headerGetEntry
++
++2008-02-29 15:36
++
++ * add rpm5.org support to NEWS :)
++
++2008-02-29 15:33
++
++ * rpm 4.5 and newer uses unsigned long long ulong1 in stead of
++ unsigned long ulong1 for rpmProblemGetLong, therefore use %lld in
++ stead of %ld
++
++2008-02-29 15:03
++
++ * add back copyright field manually since svn wouldn't set it..
++
++2008-02-29 14:57
++
++ * try add svn properties to top of file
++
++2008-02-29 14:42
++
++ * add svn keywords properties
++
++2008-02-29 14:40
++
++ * make inclusion of headers conditional
++
++2008-02-29 14:29
++
++ * be sure to set return value to NULL in headerGetEntry when Epoch
++ isn't set
++
++2008-02-29 14:24
++
++ * fix assignment from incompatible pointer type in
++ Urpm_list_rpm_tag for rpm5
++
++2008-02-29 14:14
++
++ * be sure to use same data type for check_flag
++
++2008-02-28 17:07
++
++ * make sure to use same type (signess) in pack_rpm_header
++
++2008-02-28 16:45
++
++ * do not define RPM_CALLBACK_LONGLONG for rpm 5.0
++
++2008-02-28 16:20
++
++ * add copyright notice
++
++2008-02-28 15:30
++
++ * fix return type and variable of headerRead()
++
++2008-02-28 13:29
++
++ * 3.11
++
++2008-02-28 13:29
++
++ * - restore FILENAME_TAG in generated hdlist (to be compatible with
++ older
++ distros where -&gt;filename can rely on it) (thanks to Nanar)
++
++2008-02-28 11:04
++
++ * fix double _free of msg in headerWrite() &amp; headerRead()
++ do rpmlog for headerWrite() &amp; headerRead()
++ drop unused variable in cointainer for headerNextIterator()
++
++2008-02-28 02:35
++
++ * drop unused variable
++
++2008-02-28 02:28
++
++ * get rid of some warnings
++
++2008-02-28 02:03
++
++ * add wrapper function for rpmMachineScore
++
++2008-02-28 01:38
++
++ * add wrapper function for headerRead
++
++2008-02-28 01:24
++
++ * add wrapper function for headerModifyEntry
++
++2008-02-28 01:06
++
++ * fix define of _RPMTAG_INTERNAL at right place and drop redundant
++ include of rpmtag.h
++
++2008-02-28 00:56
++
++ * add rpm5 wrapper functions, work in progress, URPM builds now at
++ least :o)
++
++2008-02-27 21:45
++
++ * fix building with rpm5 DEVEL version
++
++2008-02-25 23:39
++
++ * do not mark as deprecated -&gt;filename and
++ URPM::Build::build_hdlist()
++
++2008-02-25 23:22
++
++ * 3.10
++
++2008-02-25 21:57
++
++ * adding filesize to synthesis on @info@ will break backward
++ compatibility for
++ no good reason, so switching to a new @filesize@ line
++
++2008-02-25 21:37
++
++ * make -&gt;filename work (again) on header
++
++2008-02-25 21:17
++
++ * 3.09
++
++2008-02-25 21:13
++
++ * do not do &quot;uniq&quot; on &quot;fullname&quot; since gpg-pubkey-xxxxxxxx-xxxxxxxx
++ can be installed twice
++
++2008-02-25 21:05
++
++ * since -&gt;filename is deprecated, do not use it, esp where not
++ needed
++
++2008-02-25 20:43
++
++ * - add filesize to synthesis, add -&gt;filesize to get it, and add
++ selected_size_filesize() to compute the sum
++
++2008-02-25 20:41
++
++ * fix previous commit (XS comments are perl-style, not C-style)
++
++2008-02-25 19:17
++
++ * - do not add FILENAME_TAG and FILESIZE_TAG to hdlist anymore,
++ deprecate -&gt;filename and -&gt;header_filename,
++ deprecate URPM::Build build_hdlist and parse_rpms_build_headers
++
++2008-02-25 16:18
++
++ * - allow fixing &quot;using one big transaction&quot; that occurs when using
++ --keep
++ (#30198)
++
++ nb: since build_transaction_set calls resolve_requested, it must
++ use the same
++ options to select the same packages
++
++2008-02-25 16:16
++
++ * - allow urpmi to know a package was not selected because a newer
++ version is
++ installed (#29838)
++
++2008-02-25 13:34
++
++ * - fix sort choices changed in perl-URPM 3.08
++
++2008-02-25 13:33
++
++ * - handle new package providing xxx which conflicts with an
++ installed package (#17106)
++
++2008-02-25 09:20
++
++ * 3.08
++
++2008-02-25 09:19
++
++ * - sort choices on virtual package by provided version (#12645)
++
++2007-09-12 15:11 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : better indicate the test case in urpmi
++
++2007-09-12 15:04 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : update doc
++
++2007-09-12 15:04 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : update doc
++
++2007-09-12 15:01 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : update doc
++
++2007-09-12 15:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _remove_all_rejected_from() out of disable_selected()
++
++2007-09-12 14:57 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _remove_rejected_from()
++
++2007-09-12 14:47 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : update doc
++
++2007-09-12 14:44 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : factorize code into _set_rejected_from()
++
++2007-09-12 14:38 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : replacing {backtrack}{closure} with {closure} since it looks
++ like it was a typo
++
++2007-09-12 14:27 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : adapt doc to is really done (may kill {backtrack}{closure}
++ later)
++
++2007-09-12 13:16 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : update doc
++
++2007-09-12 13:12 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix typo in previous commit: pass $urpm to set_selected() for
++ debug message
++ - {from} options to resolve_rejected_ and set_selected is now a
++ pkg object
++ instead of a fullname string
++
++2007-09-12 13:08 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add debug message
++
++2007-09-12 13:07 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify
++
++2007-09-12 13:06 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : handle {size} in set_rejected()
++
++2007-09-12 12:59 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - add ability to merge {closure} fields in set_rejected (from
++ $options{why})
++ - {from} is a fullname here
++ - {why} is a hash
++ - use set_rejected() to factorize code
++
++2007-09-12 12:12 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : cleanup
++
++2007-09-12 12:11 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in previous commit
++
++2007-09-12 12:03 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create set_rejected() out of resolve_rejected_()
++
++2007-09-12 11:03 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : dep field &quot;choices&quot; is here for debug purpose, rename it
++ _choices
++
++2007-09-12 11:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _dep_to_name() and use it
++
++2007-09-12 10:50 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : drop unused option &quot;closure_as_removed&quot;
++
++2007-09-12 10:14 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : backtrack_selected() was always returning empty list, so
++ backtrack_selected_psel_keep() should return empty list. but it's
++ simply to
++ modify callers to take into account the return value is ()
++
++2007-09-12 10:07 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : move var declaration where it's used
++
++2007-09-12 10:06 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : move function created in previous commit
++
++2007-09-12 10:04 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _choose_required() out of
++ resolve_requested__no_suggests_()
++
++2007-09-12 09:50 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : this is good to have in NEWS
++
++2007-09-11 16:27 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : document side-effects of each functions
++
++2007-09-11 15:41 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add some doc
++
++2007-09-11 15:35 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename disable_selected_unrequested_dependencies() into
++ disable_selected_and_unrequested_dependencies()
++
++2007-09-11 15:09 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : don't keep a hash when we really want its values
++
++2007-09-11 15:03 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - create strict_arch_check() out of find_required_package()
++ - and factorize some more code into $may_add_to_packages
++
++2007-09-11 14:46 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create backtrack_selected_psel_keep() out of
++ backtrack_selected() and use it
++
++2007-09-11 14:12 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : drop keep_unrequested_dependencies option (it is unused)
++
++2007-09-11 14:10 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : drop keep_requested_flag by creating
++ resolve_requested__no_suggests_()
++
++2007-09-11 14:04 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify
++
++2007-09-11 14:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : define var where it's needed
++
++2007-09-11 13:59 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename var, $dep will only be used as an element from
++ @properties
++
++2007-09-11 13:58 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename var, $dep will only be used as an element from
++ @properties
++
++2007-09-11 13:52 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add doc
++
++2007-09-11 13:37 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add some doc
++
++2007-09-11 13:37 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify
++
++2007-09-11 13:32 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify
++
++2007-09-11 13:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify: make find_candidate_packages() the wrapper around
++ find_candidate_packages_() instead of the other way round
++
++2007-09-11 13:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create find_candidate_packages_(), wrapper around
++ find_candidate_packages()
++
++2007-09-11 13:16 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : drop callback_backtrack, unused for a long time
++
++2007-09-11 11:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix old typo in comment
++
++2007-09-11 11:51 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add a comment
++
++2007-09-11 10:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix old typo (rejected field is unused anyway afaik)
++
++2007-09-11 10:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in previous typo fix
++
++2007-09-11 10:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in previous commit :-/
++
++2007-09-11 09:58 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - speedup is_arch_compat (x7) by keeping the platform in a
++ cache
++
++2007-09-11 09:55 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add missing free()
++
++2007-09-11 08:44 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : move doc where it belongs
++
++2007-09-11 07:28 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add comment
++
++2007-09-10 16:58 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify prototype of find_candidate_packages()
++
++2007-09-10 16:56 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename find_chosen_packages() into find_required_package()
++ (better name)
++
++2007-09-10 16:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - pass the prefered choices to {callback_choices}: this allows
++ urpmi to select
++ all the prefered packages according to installed locales
++
++2007-09-10 15:48 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - do not propose packages for non installed locales
++
++2007-09-10 15:48 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - do not propose packages for non installed locales
++ - cleanup code
++
++2007-09-10 15:46 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in previous commit
++
++2007-09-10 15:16 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _find_chosen_packages__sort() out of
++ find_chosen_packages()
++
++2007-09-08 20:29 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : more detailed doc
++
++2007-09-08 09:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : typo in comment
++
++2007-09-08 09:16 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename lists with &quot;closure&quot; in the name to things like
++ &quot;xxx_todo&quot; or
++ &quot;all_xxx&quot;, i find it more readable, and it helps making the
++ difference with
++ {closure} field
++
++2007-09-08 09:10 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename local var for clarity
++
++2007-09-08 09:07 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename local var
++
++2007-09-08 09:05 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : document $state fields
++
++2007-09-08 08:10 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : rename a local variable for clarity
++
++2007-09-08 08:09 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _handle_conflicts() out of
++ resolve_requested__no_suggests()
++
++2007-09-08 07:39 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in older commit
++
++2007-09-08 07:38 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : use function calls instead of method calls (it allows
++ perl_checker checks when
++ temporarilly renaming URPM/Resolve.pm package name to URPM)
++
++2007-09-07 21:56 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _handle_diff_provides() out of
++ resolve_requested__no_suggests()
++
++2007-09-07 20:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _compute_diff_provides() and
++ _compute_diff_provides_one() out of
++ resolve_requested__no_suggests()
++
++2007-09-07 20:31 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : factorize regexps into functions
++
++2007-09-07 19:45 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : make it more clear
++
++2007-09-07 19:35 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : cleanup
++
++2007-09-07 19:32 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : create _ids_to_fullnames() and _ids_to_names()
++
++2007-09-07 19:19 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix typo in recent commit
++
++2007-09-07 19:18 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : make it clear that resolve_rejected_ is modifying @properties
++ from
++ resolve_requested()
++
++2007-09-07 18:39 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : revert previous commit: compute_deps() is still used by mkcd
++
++2007-09-07 17:55 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : remove unused compute_deps() \o/
++
++2007-09-07 17:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify: nopromoteepoch is always 1 (no caller ever define it)
++
++2007-09-07 17:43 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : cleanup: nopromoteepoch is 1 by default in
++ find_candidate_packages
++
++2007-09-07 15:44 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : factorize code in functions whatrequires() and
++ whatrequires_id()
++
++2007-09-07 15:30 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : simplify: whatrequires is a hash with provides_nosense as key,
++ don't need to
++ use -&gt;provides then remove the sense
++
++2007-09-07 15:19 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : hoist a debug message so that it occurs for other uses of
++ with_db_unsatisfied_requires()
++
++2007-09-07 15:06 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : re-use same code for conflict from installed package as is used
++ for conflict
++ from selected package. this fixes test_gh() from urpmi
++ split-transactions--promote test case
++
++2007-09-07 14:44 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : move code from resolve_requested__no_suggests() into new
++ function _handle_provides_overlap()
++
++2007-09-07 14:30 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : prepare to factorize code handling property becoming
++ unavailable.
++
++ it really seems {why}{conflicts} is only used for debugging
++ purpose, so this
++ change won't break.
++
++2007-09-07 14:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : one more debug message
++
++2007-09-07 11:26 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : small cleanup
++
++2007-09-07 11:26 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add some debug messages
++
++2007-09-05 15:19 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix displaying @sorted whereas some elements have been
++ removed from it
++ - more complete error message
++
++2007-09-05 09:37 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add debug code
++
++2007-09-03 15:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.80, bugfix release
++
++2007-09-03 15:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix bug in sort_graph (used by build_transaction_set)
++
++2007-09-03 15:20 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.79
++
++2007-09-03 12:59 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add a test
++
++2007-09-03 08:08 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix bug in sort_graph (used by build_transaction_set)
++
++2007-09-03 08:07 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.78
++
++2007-08-31 15:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix dead-loop in build_transaction_set (#33020)
++
++ and ensure the resulting graph is correct by checking it
++
++2007-08-31 07:02 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add a comment
++
++2007-08-29 09:33 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.77
++
++2007-08-29 09:33 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - disable &quot;dropping tags from rpm header&quot; until we can safely
++ use it
++
++2007-08-29 09:32 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.76
++
++2007-08-28 14:12 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : ensure #31969 doesn't occur anymore. if somethings goes wrong:
++ - display error message
++ - then default to one big transaction
++
++ also display error message &quot;using one big transaction&quot; in the old
++ check (which
++ i don't really know what it does)
++
++2007-08-28 13:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - build_transaction_set: new sort algorithm which allow
++ returning sets of
++ circular dependent packages, taking into account obsoleted
++ packages
++ (fixes #31969). It may still fail in presence of conflicts
++
++ a better fix would be to make -&gt;resolve_requested__no_suggests
++ handle
++ obsolete. ie:
++ - a requires b : bb or b
++ - bb requires c-1
++ - b requires c-2
++ - b obsoletes bb
++ =&gt; with a, bb and c-1 installed, &quot;urpmi c&quot; should upgrade bb into
++ b instead of
++ removing a and bb.
++
++2007-08-28 11:03 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - spec2srcheader: workaround parseSpec returning a header where
++ -&gt;arch is set
++ to %{_target_cpu} whereas we really want a header similar to
++ .src.rpm
++ (see #32824)
++
++2007-08-24 12:01 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix split_length &gt; 1
++ (eg: &quot;urpmi --split-length 2 a b c&quot; will only install 2 pkgs)
++ (this bug has not been reported, just discovered it while reading
++ the code)
++
++ - cleanup
++
++2007-08-24 11:50 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - more debug messages
++ - little rewrite
++
++2007-08-23 13:22 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - allow running transaction with justdb option
++
++2007-08-12 20:45 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.75
++
++2007-08-12 20:44 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix dropping tags from rpm header.
++ it hasn't work since MDK8.1 and rpm 4.0.
++ it may break urpmi!! but potentially allows a much smaller
++ hdlist.cz :)
++
++2007-08-12 11:32 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.74
++
++2007-08-12 11:29 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - sort choices per media, then per version
++
++ nb:
++
++ on 2004-12-13, rgs replaced &quot;$a-&gt;id &lt;=&gt; $b-&gt;id&quot; with
++ &quot;$b-&gt;compare_pkg($a) || $a-&gt;id &lt;=&gt; $b-&gt;id&quot;
++
++ Return the list of chosen packages sorted by descending
++ version (bug #12645).
++
++ the end result is the sorting by media was dropped :-/
++
++2007-08-12 10:15 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : cleanup (easier to read)
++
++2007-08-11 12:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.73
++
++2007-08-11 12:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - allow running transaction with replagekgs option
++
++2007-08-10 18:01 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.72
++
++2007-08-10 17:50 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - modify parse_hdlist so that partial hdlist reading can be
++ used
++ (needed when some stuff is already done in the callback)
++
++2007-08-10 17:35 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : add documentation
++
++2007-08-10 17:34 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : there is no use retrying after a headerRead failure since
++ headerRead may have
++ consumed part of the input, and so next headerRead will read in
++ the middle of
++ a header, and so always fail. The only real solution is to ensure
++ rpmlib don't
++ timeout too quickly (and fd-&gt;rd_timeoutsecs is rpmlib internal
++ only, so we
++ can't hint it from here. in any case 1sec timeout is really too
++ low)
++
++2007-08-09 15:25 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.71
++
++2007-08-09 15:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - compilation fixes on rpm &lt; 4.4.8
++
++2007-08-09 14:58 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.70
++
++2007-08-09 14:58 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : compilation fixes on rpm &lt; 4.4.8
++
++2007-08-09 13:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.69
++
++2007-08-09 13:24 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - &quot;suggests&quot; are no more handled as &quot;requires&quot;
++ - resolve_requested support &quot;suggests&quot;: a newly suggested package
++ is installed
++ as if required (can be disabled with option no_suggests)
++
++ nb: URPM.xs change is quite complex since suggests are mostly
++ seen as requires
++ inside rpmlib.
++
++2007-08-08 18:18 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : factorize some code into with_db_unsatisfied_requires:
++
++ #- this function is &quot;suggests vs requires&quot; safe:
++ #- 'whatrequires' will give both requires &amp; suggests, but
++ unsatisfied_requires
++ #- will check $p-&gt;requires and so filter out suggests
++
++2007-08-08 17:38 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : &quot;nopromoteepoch =&gt; 1&quot; is the default option in
++ -&gt;unsatisfied_requires
++
++2007-08-03 14:43 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.68
++
++2007-08-03 14:42 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - add $trans-&gt;Element_version and $trans-&gt;Element_release
++
++2007-07-05 13:36 nanardon
++
++ * : - 0.67
++
++2007-07-04 22:26 nanardon
++
++ * : - Urpm_read_config_files properly return the value to perl
++ - kill useless var dcl
++
++2007-07-04 22:21 nanardon
++
++ * : - fix parseSpec argument
++
++2007-07-04 16:43 nanardon
++
++ * : - add osscore() and archscore() function to evaluate computer
++ compatiblity to an arbitrary value
++
++2007-07-04 15:53 nanardon
++
++ * : - add Pkg_is_platform_compat() and Urpm_platformscore() coming
++ with rpm 4.4.8
++
++2007-07-02 15:14 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.66
++
++2007-07-02 15:11 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - fix --auto-select skipping some packages because of other
++ packages providing
++ a more recent version, but no obsolete between those packages.
++ the fix is to revert commit from Aug 2002:
++ &quot;fixed propable old package (according provides) requested by
++ request_packages_to_upgrade.&quot;
++
++ hopefully this change won't break too much...
++
++ for the record, a few issues:
++ - skipping java-1.5.0-gcj-1.5.0.0-14.7mdv2008.0.i586 since
++ java-1.7.0-icedtea-1.7.0.0-1.3mdv2008.0.i586 provides a more
++ recent version of jre (1.7.0 vs 1.5.0)
++ - skipping emacs-common-22.1-2mdv2008.0.i586 since
++ gnus-emacs-5.10.8-1mdv2007.0.noarch provides a more recent vers
++ whereas java-1.5.0-gcj-1.5.0.0-14.6mdv and emacs-common-22.1-1mdv
++ are installed
++
++2007-07-02 15:05 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : help perl_checker
++
++2007-07-02 14:38 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : help debugging the strange behaviour of this code
++
++2007-06-21 14:13 nanardon
++
++ * : - 1.42
++
++2007-06-19 14:44 nanardon
++
++ * : - make is_arch_compat rpm 4.4.8 compliant
++
++2007-06-15 20:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : document the fact that build_synthesis returns true on success
++
++2007-06-12 14:03 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : fix release date
++
++2007-06-12 13:57 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.64
++
++2007-06-12 13:56 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - hack on $pkg-&gt;is_arch_compat to make it return true for
++ noarch packages
++ when using rpm 4.4.8 (#31314)
++
++2007-05-09 16:00 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - new release, 1.63
++ - add $trans-&gt;Element_fullname
++
++2007-05-03 14:51 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.61 has not been released
++
++2007-05-03 14:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : 1.62
++
++2007-05-03 14:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - pass the virtual package name as a parameter to
++ {callback_choices} in
++ -&gt;resolve_requested
++
++2007-04-27 12:37 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : re-sync after the big svn loss
++
++2007-04-27 12:37 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : re-sync after the big svn loss
++
++2007-04-27 12:31 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : - 1.61
++ - add $trans-&gt;NElements and $trans-&gt;Element_name
++ to be able to display name of uninstalled package in
++ callback_uninst
++ - fix b--obsoletes--&gt;a and c--conflicts--&gt;a prompting for
++ upgrading a
++ (need a fix in urpmi which rely on the $state-&gt;{rejected}
++ to upgrade (-U) b instead of installing (-i) it)
++
++2007-04-27 12:30 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : re-sync after the big svn loss
++
++2007-04-24 19:11 Pixel &lt;pixel at mandriva.com&gt;
++
++ * : re-sync after the big svn loss
++
++2006-12-04 10:28 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: correctly set &quot;\0&quot;
++
++2006-12-04 10:23 Pixel &lt;pixel at mandriva.com&gt;
++
++ * t/parse.t: remove temp file
++
++2006-12-04 09:43 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: correctly handle gzread error code
++
++2006-12-01 16:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: rpmReadPackageFile() can return ok but no header :-/
++
++2006-12-01 16:14 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: rpmReadPackageFile() can return ok but no
++ header :-/
++
++2006-11-29 22:24 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) factorize size to allocate
++
++2006-11-29 22:23 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) adjust allocated memory
++
++2006-11-29 22:22 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) remove guard, proper fix is now enough
++
++2006-11-29 22:21 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) fix segfault on ia32 (when one replace
++ &quot;struct foobar&quot; by
++ &quot;foobar*&quot;, he should expect sizeof() to *slightly* differ in
++ results)
++
++2006-11-29 17:08 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm: 1.50 new release
++
++2006-11-29 16:59 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) fix segfault when using --excludepath
++
++2006-11-29 15:36 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) fix the segfault when using --excludepath
++ (introduced in
++ r32435:32440). however, using --excludepath will still
++ segfaults, but
++ later, in rpmtsAddInstallElement() ...
++
++2006-11-29 13:56 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (Trans_add) fix segfault
++
++2006-11-24 10:12 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm, URPM/Resolve.pm: strict-arch should not imply that
++ noarch can't upgrade the real arch (#22558)
++
++2006-11-21 07:59 Pixel &lt;pixel at mandriva.com&gt;
++
++ * ChangeLog: - default to strict-arch on 64bits (tvignaud)
++ - handle empty hdlist.cz/synthesis.cz (in build_hdlist,
++ build_synthesis, parse_hdlist, parse_synthesis)
++ - parse_rpms_build_headers: allow asking for packing (and so
++ fixing an error in urpmi)
++ - documentation &amp; comments enhancement
++ - release 1.48
++
++2006-11-21 07:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm: resolve_rejected: nodeps is also recognised
++ (through backtrack_selected)
++
++2006-11-21 07:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm: resolve_rejected: nodeps is also recognised
++ (through backtrack_selected)
++
++2006-11-17 17:46 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Build.pm: parse_rpms_build_headers: allow asking for
++ packing (fixes an error in urpmi)
++
++2006-11-17 16:43 Pixel &lt;pixel at mandriva.com&gt;
++
++ * t/parse.t: add some tests on empty header, buggy header, empty
++ hdlist
++
++2006-11-17 16:42 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: at least one good header is needed for non compressed
++ hdlist and non empty file
++ * URPM/Build.pm: allow building empty hdlist &amp; synthesis
++
++2006-11-17 16:25 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs, t/parse.t: - parse_hdlist on a simple header was broken
++ because pid was left unset,
++ - add some tests for this
++
++2006-11-15 12:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * t/rpmdb.t: do display on which pkgs the 2 sorted lists disagree
++
++2006-11-15 11:49 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: add a wrapper in perl around parse_hdlist and
++ parse_synthesis
++
++2006-11-15 11:47 Pixel &lt;pixel at mandriva.com&gt;
++
++ * t/rpmdb.t: remove debug stuff
++
++2006-11-15 11:28 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm: make the prototype of parse_synthesis more clear in the
++ pod
++
++2006-11-15 11:14 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: parse_synthesis, parse_hdlist: handle gzip error status
++ instead of relying on
++ wether we did read at least one header. This allow &quot;empty&quot;
++ hdlist/synthesis.
++ But it means it is getting stricter, and the headers added to
++ {depslist} would
++ need to be removed if an error occured. Alas i don't know how to
++ do it (a
++ simple splice) in XS. If no better solution, i'll create a
++ wrapper function in
++ perl.
++
++2006-11-10 14:18 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Build.pm: use the documented way to call -&gt;parse_hdlist,
++ not the deprecated one
++
++2006-11-09 15:05 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM/Resolve.pm: (find_chosen_packages) default to strict-arch
++ on 64bits
++
++2006-11-07 13:27 Pixel &lt;pixel at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm: new release, no real change except
++ perl_checker compliant
++
++2006-11-03 15:41 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm: perl_checker compliance
++
++2006-11-03 15:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * .perl_checker, URPM.pm, URPM/.perl_checker, URPM/Build.pm,
++ URPM/Resolve.pm: perl_checker compliance
++
++2006-11-03 15:41 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm: perl_checker compliance
++
++2006-11-03 15:21 Pixel &lt;pixel at mandriva.com&gt;
++
++ * .perl_checker, URPM.pm, URPM/.perl_checker, URPM/Build.pm,
++ URPM/Resolve.pm: perl_checker compliance
++
++2006-10-16 10:11 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Patch by Pixel to ignore self-obsoletes
++
++2006-09-21 09:49 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Invert bogus check
++
++2006-09-07 09:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST, URPM/Build.pm, t/pod.t: Add POD test, remove sole pod
++ fragment in URPM::Build
++
++2006-09-06 11:37 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm: Bump version to 1.46
++
++2006-09-06 09:15 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Oops, remove debug code
++
++2006-09-06 09:13 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: prefer kernel-source-stripped over kernel-source
++
++2006-09-05 16:14 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Micro-optimisation, and make comments more
++ explicit
++
++2006-08-07 14:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm: Bump version, regen changelog
++
++2006-08-07 14:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST, perl-URPM.spec: Remove perl-URPM.spec, checked in in
++ repsys
++
++2006-08-07 14:30 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - cleanup useless imported rpm dcl
++
++2006-08-07 14:25 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - remove useless declaration
++
++2006-08-07 14:30 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - cleanup useless imported rpm dcl
++
++2006-08-07 14:25 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - remove useless declaration
++
++2006-08-04 09:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix a FD leak (patch by Pascal Terjan, bug #24112)
++
++2006-08-01 13:21 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: strict-arch doesn't apply to src packages
++
++2006-07-25 21:50 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - add comment into code, need review
++
++2006-07-04 12:35 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: One might have an undefined package in the
++ depslist (not sure why)
++
++2006-06-14 10:08 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM/Signature.pm: Verify if we can open the rpmdb, and
++ abort if we can't (bug #22527)
++
++2006-06-12 10:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: That wasn't actually necessary
++
++2006-06-12 10:31 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: Bump version number
++
++2006-06-12 10:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix passing of rpmRelocation structure with new layout
++ in 4.4.6
++
++2006-06-12 10:20 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Fix rpm version detection. Generate ChangeLog under
++ C locale.
++
++2006-06-07 09:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * .cvsignore: Remove cvsignore file
++
++2006-06-07 09:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, Makefile.PL: Use svn2cl to generate ChangeLog, and
++ regenerate it
++
++2006-06-01 11:47 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL, URPM.xs: It's nice to be able to compile with rpm
++ 4.4.6, but it's nice to be able to
++ compile with older rpms too.
++
++2006-05-31 21:10 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - rpm 4.4.6 fixes
++
++2006-05-23 21:53 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * META.yml: Add metafile
++
++2006-05-23 21:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.43
++
++2006-05-23 21:32 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - fix urpmi .spec: aka ensure the rpm config is read
++ with all macros before parsing a spec
++
++2006-05-22 13:43 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Don't clobber rpm's changelog with too many
++ details, there is a real changelog for that
++
++2006-05-22 13:32 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * perl-URPM.spec: add bug reference in 1.42-1mdk's changelog
++
++2006-05-22 11:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.42
++
++2006-05-22 10:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Patch by Pascal Terjan to fix a FD leak (bug #22632)
++
++2006-05-02 08:33 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.41
++
++2006-04-07 10:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add function to traverse transactions
++
++2006-04-02 23:02 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: RPMTAG_SOURCEPACKAGE is going to be obsolete. Replace
++ it by RPMTAG_SOURCERPM.
++
++2006-03-15 12:42 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.40
++
++2006-03-13 16:51 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Get version comparison right
++
++2006-03-13 16:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Define new symbol in Makefile.PL depending on
++ detected rpm version
++ (no simpler way to get it from the C preprocessor, it seems)
++
++2006-03-13 16:37 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix for undocumented ABI changes in rpm 4.4.5 callback
++ interface
++
++2006-03-13 15:56 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Protection when no data is passed to transaction
++ callbacks
++
++2006-03-13 14:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix misplaced break in switch statement
++
++2006-03-10 16:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: &quot;triggeredby&quot; in traverse_tag never worked.
++
++2006-03-08 15:51 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix small memleak on db open error
++
++2006-03-07 10:35 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.39
++
++2006-03-07 10:27 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Clean up gcc options
++
++2006-03-07 10:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Protect rpmtsRun with a new link to the transaction
++ object
++
++2006-03-06 14:11 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Spec file nit.
++ * URPM.xs: Also, increase refcounts.
++
++2006-03-06 13:59 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.38
++
++2006-03-06 13:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/rpmdb.t: Perform this test faster
++
++2006-03-06 13:45 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/parse.t: Be more Test::More-ish, add a TODO test
++
++2006-03-06 13:31 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: It wasn't a good idea to completely remove the
++ refcount, because it's used to
++ free the underlying C glue structure.
++ Also, and rpmtsLink was misplaced.
++
++2006-03-06 11:09 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Don't use our own reference counter, but the rpmlib's,
++ for transactions.
++
++2006-03-03 15:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.37
++
++2006-03-03 15:08 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document URPM::verify_signature()
++
++2006-03-03 15:05 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Include key id in verify_signature()'s OK output. Also,
++ avoid a header leak.
++
++2006-03-03 14:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: New function verify_signature
++
++2006-03-03 13:50 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Don't display error messages from rpmVerifySignatures
++
++2006-03-03 13:14 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document (new-ish) return value of verify_rpm()
++
++2006-03-03 13:00 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Reimplement verify_rpm, using the rpm cli
++ interface
++
++2006-03-03 10:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Remove support for the (broken) db option to
++ verify_rpm
++
++2006-03-03 09:26 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Use a smaller buffer for the return value of
++ verify_rpm, and guard against overflows
++
++2006-03-02 17:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Honor verification flags in verif_rpm() even when
++ reading from a file without
++ having open the rpmdb
++
++2006-03-02 17:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Nits in verify_rpm.
++
++2006-03-01 11:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix a couple of compilation warnings. URPM.xs is now
++ warning-clean.
++
++2006-03-01 11:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Make sure -fno-strict-aliasing is used (gcc option)
++
++2006-02-13 13:17 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document the is_arch_compat package method
++
++2006-02-13 10:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: 1.36-1mdk
++
++2006-02-13 10:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document new ignorearch flag
++
++2006-02-13 10:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Add ignorearch option to run transactions
++
++2006-02-10 17:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.35-1mdk
++
++2006-02-10 17:06 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: repackage also when only the rpm macro is defined.
++ Maybe rpm ought to do this,
++ but obviously, as of 4.4.4, it does not.
++
++2006-02-10 09:03 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.34-1mdk
++
++2006-02-10 08:55 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Doc nits
++
++2006-02-10 08:53 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Remove unused variable
++
++2006-02-09 17:33 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Fix code example in URPM's synopsis
++
++2006-02-09 17:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add installtid method
++
++2006-02-09 14:47 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document keep_all_tags option to parse rpms
++
++2006-02-09 13:57 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: No need to make an explicit dependency on
++ perl-base
++
++2006-02-09 13:56 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog: Update Changelog
++
++2006-02-09 13:52 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, perl-URPM.spec: 1.33-1mdk
++
++2006-02-09 13:50 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document new flag repackage in run()
++
++2006-02-09 13:25 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix repackage option, oops
++
++2006-02-09 12:57 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Add repackage flag to run transactions
++
++2006-01-25 14:21 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, URPM.xs, perl-URPM.spec: 1.32-1mdk
++
++2006-01-25 14:18 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Flag headers returned by spec2srcheader() as source
++ packages
++
++2006-01-24 11:38 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Pod formatting fix
++
++2006-01-19 13:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.31
++
++2006-01-19 13:31 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Rewrite and relocate doc at a more proper place. Update
++ copyright notice.
++
++2006-01-19 13:24 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs, t/parse.t: In spec2srcheader(): extend stack; fudge
++ with errno.
++
++2006-01-19 13:05 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs, t/parse.t: Return undef on spec parsing failure
++
++2006-01-19 12:52 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.pm: - add doc for Urpm_spec2srcheader
++
++2006-01-19 11:36 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * Makefile.PL, URPM.xs, t/parse.t: - add Urpm_spec2srcheader():
++ return header of src.rpm from a specfile
++
++2006-01-06 16:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.30-2mdk
++
++2006-01-06 11:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, t/rpmdb.t: Use --qf in test to accomodate variations
++ in %_query_all_fmt values
++
++2005-12-08 09:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Update copyrights
++
++2005-12-07 16:54 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.30
++
++2005-12-07 16:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm, perl-URPM.spec: Fix longstanding epoch
++ promotion bug, caused by braindead API design
++
++2005-12-07 16:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Document trap in that braindead stupid API.
++
++2005-12-01 16:53 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Be verbose about the detected RPM version
++
++2005-12-01 13:57 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: RPMTAG_SERIAL (old name of RPMTAG_EPOCH) has been
++ removed in rpm 4.4.3
++
++2005-11-30 13:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix a couple of compilation warnings
++
++2005-11-30 13:45 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Fix cast error
++
++2005-11-30 13:21 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: libbzip2 is actually not used by URPM.
++
++2005-11-15 16:14 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Add an URPM::Package::dump_flags method, to help
++ debugging the depsolver
++
++2005-11-15 10:45 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ., .cvsignore: Ignore MakeMaker build files
++
++2005-11-02 14:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.29-1mdk
++
++2005-11-02 10:42 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Mention noscripts option in docs
++
++2005-10-28 14:30 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Doc neatification
++
++2005-10-28 14:15 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Require MDV::Packdrakeng in Makefile.PL
++
++2005-10-28 14:10 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm, t/parse.t: Use new MDV namespace
++
++2005-10-18 16:46 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: More docs for confusing method names
++
++2005-10-10 18:21 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Add the RPMPROB_FILTER_DISKNODES flag for running
++ transactions with the
++ nosize option. Although rpm doesn't seem to use it internally,
++ it sets
++ it on the --ignoresize command-line option.
++
++2005-10-04 12:19 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/parse.t: Don't require Packdrakeng for running tests
++
++2005-10-04 12:00 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Remove buildrequires on bzip2.
++ Simplify buildreq_perl_devel conditional dependency per Buchan's
++ suggestion.
++
++2005-10-03 09:25 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.28-1mdk
++
++2005-10-03 09:19 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Documentation encoding fix
++
++2005-10-03 09:17 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST, Makefile.PL, t/00prepare.t, t/parse.t,
++ test-rpm-1.0-1mdk.noarch.rpm: Rebuild test rpm when running
++ tests. Add cleanup to files.
++
++2005-10-03 08:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST: Update MANIFEST
++
++2005-10-03 08:38 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * build_rpm: Remove obsolete script
++
++2005-10-03 08:36 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Add an rpm makefile target
++
++2005-10-03 08:20 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Makefile.PL cleanup
++
++2005-09-14 13:17 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - add some options to parse_rpm (nomd5, nopayload)
++
++2005-09-12 15:13 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Minor comment fixes
++
++2005-09-09 12:54 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: 1.27-1mdk
++
++2005-09-09 12:53 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Make URPM::add_macro expand literal \n to \\\n
++ in macro definitions.
++ add URPM::add_macro_noexpand to get the old (rpmlib like)
++ behaviour
++
++2005-09-01 16:19 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, perl-URPM.spec: 1.26-1mdk
++
++2005-09-01 15:43 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Add a &quot;noscripts&quot; option to run transactions. Inhibits
++ pre, preun, post and
++ postun scritps.
++
++2005-08-23 12:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.25-1mdk
++
++2005-08-23 12:15 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.xs: correctly handle -1 fileno returned by callback_open
++
++2005-08-23 10:33 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Doc fixes
++
++2005-08-18 15:54 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.24-3mdk
++
++2005-08-18 15:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Allow to rebuild URPM under non-C locales (Boris
++ Filipovic)
++
++2005-07-28 05:06 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.24-2mdk
++
++2005-07-28 02:26 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Doc bits
++
++2005-07-28 02:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * README, URPM.pm, URPM.xs: update copyright and maintainer
++
++2005-07-04 09:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Documentation fix
++
++2005-06-30 05:01 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.24
++
++2005-06-30 04:58 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add function rpmErrorWriteTo($fd)
++
++2005-06-30 04:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: add rpmErrorString function
++
++2005-06-29 09:02 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Doclet
++
++2005-06-16 10:27 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Forgot to commit changelog
++
++2005-06-16 10:05 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.23-1mdk
++
++2005-06-16 10:03 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add a binding for rpm internal debugging
++ function setVerbosity()
++
++2005-06-07 01:43 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.22-1mdk
++
++2005-06-01 09:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Warning fixes and documentation
++
++2005-06-01 03:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Ensure archs are identical
++
++2005-06-01 03:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Integrate a function to produce deltarpms
++
++2005-05-31 09:33 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.21-1mdk
++
++2005-05-31 08:45 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Removes obsolete code
++
++2005-05-30 09:37 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add the URPM::Package::payload_format method
++
++2005-05-11 06:58 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Remove the return value of
++ compute_installed_flags, it's not used anywhere
++
++2005-05-10 13:11 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * perl-URPM.spec: - 0.3 for amd64
++
++2005-05-09 10:09 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.20-mdk
++
++2005-05-09 06:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Update buildrequires
++
++2005-05-09 05:37 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Make spec mandriva-compliant
++
++2005-05-04 03:06 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Don't hardcode distribution name
++
++2005-05-04 03:01 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.20-1mdk
++
++2005-05-02 10:58 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL, URPM.xs: Remove rpm 4.0 support
++
++2005-05-02 10:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Remove dead code
++
++2005-05-02 10:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Patch by Olivier Thauvin to adapt URPM for rpm 4.4
++
++2005-04-28 23:50 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * perl-URPM.spec: - use mkrel
++
++2005-04-28 16:44 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Fix bug 15628 : when no preferred locale is
++ found, put locales-en in front of
++ choice list
++
++2005-03-09 16:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: More RPMSENSE_PREREQ deprecation. (this should do
++ nothing with rpm 4.2)
++
++2005-03-07 09:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.11-1mdk
++
++2005-03-03 09:37 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Speed optimisation for updating media
++
++2005-03-02 15:13 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.10-1mdk
++
++2005-03-02 14:38 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Prepare for obsolescence of PREREQ, introduce
++ equivalent RPMSENSE_SCRIPT_* tags
++
++2005-02-15 12:54 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.09-1mdk
++
++2005-02-15 12:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Comments and indentation
++
++2005-02-15 11:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Force recomputation of rejected packages when
++ deleting some in installation
++ dependency resolution
++
++2005-02-11 14:17 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: POD fix.
++
++2005-02-11 14:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.08-1mdk
++
++2005-02-11 13:59 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Add macro handling code from Olivier Thauvin
++
++2005-02-02 09:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.07-4mdk
++
++2005-02-02 09:00 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Ooops, missing epoch
++
++2005-01-21 09:53 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.07-3mdk
++
++2005-01-20 20:35 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Require perl-base &gt;= 5.8.6, so perl will be
++ upgraded early in the process
++ 10.1 to 10.2
++
++2005-01-04 11:06 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Croak if build_base_files can't write files
++
++2004-12-21 15:38 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Typos in documentation
++
++2004-12-21 14:25 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Indentation and comments
++
++2004-12-13 17:21 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.07-2mdk
++
++2004-12-13 13:43 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.07-1mdk
++
++2004-12-13 13:34 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Return the list of chosen packages sorted by
++ descending version
++ (bug #12645).
++
++2004-12-09 15:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.06-1mdk
++
++2004-12-09 15:16 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: trust packdrake's defaults
++
++2004-12-09 15:10 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Remove external call to packdrake.
++
++2004-12-09 14:27 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/parse.t: Silence warnings
++
++2004-12-09 14:24 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/parse.t: Adjust test count
++
++2004-11-26 07:45 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.05-1mdk
++
++2004-11-25 19:18 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM/Build.pm: Inspired changes on top of Olivier's
++ changes
++
++2004-11-25 14:28 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.pm, URPM/Build.pm, URPM/Resolve.pm: - allow to use an array
++ of id instead (start .. end) in functions.
++
++2004-11-10 17:31 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.04-1mdk
++
++2004-11-10 17:26 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm: Version bump
++
++2004-11-10 17:14 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: When resolving dependencies, keep track of the
++ packages that we just
++ deselected because newer versions were found, but that were not
++ actually
++ installed.
++
++2004-11-10 14:17 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Indentation, documentation
++
++2004-10-27 09:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: Release for amd64
++
++2004-10-27 08:18 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Support for the 'strict-arch' option : upgrade
++ only packages that have
++ the same architecture than the one of the already-installed
++ version.
++
++2004-10-25 12:04 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Comments
++
++2004-10-19 14:47 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, perl-URPM.spec: 1.03-2mdk
++
++2004-10-18 08:34 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: A few perl_checker fixes
++
++2004-10-18 08:31 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Patch by Gwenole Beauchesne to prefer packages
++ which have the closest
++ architecture compatibility over others when version/release are
++ the same
++ (using rpm's scoring system).
++
++2004-10-14 03:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Fix method description
++
++2004-10-13 02:35 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Small comment fixes
++
++2004-09-03 05:06 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: If $TMPDIR is not writable, don't use it
++
++2004-08-29 12:33 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * ChangeLog: Rebuild
++
++2004-08-29 12:29 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.pm, perl-URPM.spec: - 1.03
++
++2004-08-29 11:56 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs, t/parse.t: - backport rpmvercmp binding from perl-Hdlist
++
++2004-08-24 09:43 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.02-1mdk
++
++2004-08-24 09:29 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: From now, the nopromoteepoch argument will always
++ default to 1
++
++2004-08-24 08:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, URPM.xs: Minor doc fixes
++
++2004-08-11 05:07 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.01-1mdk
++
++2004-08-11 04:57 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Don't panic on bad rpm fullnames
++
++2004-08-02 10:42 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed deadlock caused with libgc1 obsoleting
++ itself ;-) and in the case were an
++ older package is already installed and an older package is
++ present in urpmi
++ db. The problems comes with a badly interpreted comparison
++ without an operator
++ checked.
++
++2004-08-02 09:24 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 1.00 !
++
++2004-08-02 09:01 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Protection against packages that obsolete
++ themselves.
++
++2004-08-02 08:42 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs, t/parse.t: - remove test that can't works
++
++2004-08-02 07:22 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - backward compatibility with perl 5.6
++
++2004-08-02 07:14 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * Makefile.PL: - don't check rpm rpm version but rpm binary version
++
++2004-08-02 00:27 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Silence a compilation warning
++
++2004-08-02 00:03 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm, URPM/Query.pm, URPM/Resolve.pm: Make perl_checker
++ a bit more happy
++
++2004-07-30 09:03 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * perl-URPM.spec: put back lost 0.98-2mdk's changelog
++
++2004-07-30 07:48 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: 0.99-1mdk
++
++2004-07-30 06:10 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Resolution of requested packages: by default,
++ don't propose a choice when
++ multiple found packages are already installed.
++
++2004-07-28 08:47 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Build.pm: Use lexical filehandles.
++
++2004-07-22 09:39 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: Version 0.98
++
++2004-07-22 03:15 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs, t/parse.t: Add URPM::stream2header (borrowed from
++ perl-Hdlist, thanks to Olivier
++ Thauvin)
++
++2004-07-14 09:14 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * Makefile.PL, URPM.pm, perl-URPM.spec: - generate the manpage
++ - 0.97
++
++2004-07-12 06:12 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * ChangeLog, URPM.pm, perl-URPM.spec: Version 0.96
++
++2004-07-12 01:23 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Don't use keys() in scalar context
++
++2004-07-12 01:04 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Add a ChangeLog target in the makefile
++
++2004-07-09 08:56 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Simplify the compute_flags function (used for
++ the {skip,inst}.list files)
++
++2004-06-27 18:31 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - fix segfault in queryformat if tag does not exist
++ (return nothing instead)
++
++2004-06-23 06:47 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs, t/fatal.t: Clarify error message when a synthesis file
++ can't be read or gunzipped
++
++2004-05-21 11:33 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: 0.95-2mdk
++
++2004-05-21 11:19 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: Allow urpmi to downgrade packages if it was
++ invoked with --allow-force
++
++2004-05-19 15:28 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Resolve.pm: When an rpm installed locally had a version
++ greater than the one found
++ in the update media, urpmi was trying to downgrade it.
++
++2004-05-06 09:42 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, perl-URPM.spec: Version 0.95
++
++2004-05-06 09:22 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST, URPM.pm, URPM.xs, URPM/Resolve.pm, t/fatal.t: Add a
++ way to downgrade some errors (file not found) to non-fatal
++
++2004-04-30 08:32 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: 0.94-13mdk
++
++2004-04-27 05:56 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Query.pm: - fix tag2id on old mdk, ensure all test are ok
++ on 9.1
++
++2004-04-26 14:40 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * t/parse.t: Silence warnings
++
++2004-04-25 21:33 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs, t/parse.t: - make parse.t pass all test
++ - add $pkg-&gt;queryformat test
++
++2004-04-25 10:44 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.pm, URPM.xs, URPM/Query.pm: - add $pkg-&gt;queryformat()
++ function
++ - $&#251;rpm-&gt;list_rpm_tag show all tag, value for unparsable tag is
++ 'undef' in hash
++
++2004-04-23 13:55 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * ChangeLog: *** empty log message ***
++
++2004-04-23 08:01 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - urpm optional arg to Urpm_list_rpm_tag function
++
++2004-04-22 14:14 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Better diagnostics in $package-&gt;build_info()
++
++2004-04-22 09:54 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * t/parse.t: - test rpm parsing and hdlist generation
++
++2004-04-22 09:28 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST: Add missing files in the MANIFEST
++ * perl-URPM.spec: Remove hardcoded packager
++
++2004-04-22 06:40 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Build.pm: - Don't pass whole %options to parse_rpm in
++ parse_rpms_build_headers
++
++2004-04-22 06:34 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.xs: (return_list_tag) factorize common local variables
++ declaration (though
++ it wastes 4 pointer slots on stack in RPMTAG_SUMMARY case)
++
++2004-04-22 05:43 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Query.pm, t/parse.t, test-rpm-1.0-1mdk.noarch.rpm,
++ test-rpm.spec: - remove unusefull function
++ - start to add parsing test
++
++2004-04-22 05:33 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Build.pm: - export keep_all_tags trought function in
++ parse_rpm_build_headers
++
++2004-04-22 05:32 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - return_list_tag is able to return some basic tags
++ from synthesis
++
++2004-04-21 13:13 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.xs: - cleaning return_list_tag
++
++2004-04-21 09:25 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM.pm, URPM.xs, URPM/Query.pm: - add list_rpm_tag function
++
++2004-04-21 09:17 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * perl-URPM.spec: 0.94-12mdk
++
++2004-04-21 09:16 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Signature.pm: More cleanup.
++
++2004-04-21 09:15 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Don't install manpages.
++
++2004-04-21 08:08 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM/Signature.pm: Minor cleanup
++
++2004-04-18 23:15 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Build.pm, URPM/Query.pm: - add query_pkg function
++ - transmit %options to parse_rpm in parse_rpms_build_headers
++
++2004-04-17 23:31 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Build.pm, URPM/Query.pm: - add Query.pm (starting to code)
++ - add fuzzy_parse function, transparency parse hdlist,
++ synthesis, rpms or dir (dir/*.rpm)
++ - add parse_rpms function to have same behaviours than
++ parse_{hdlists,synthesis}
++
++2004-04-15 09:34 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.xs: Improve some diagnostics
++
++2004-04-09 15:51 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * Makefile.PL: Force INSTALLDIRS=vendor in the Makefile.PL, for
++ local testing
++
++2004-04-06 14:41 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * URPM.pm, t/rpmdb.t, t/synthesis.t: Deprecate the pseudo-packages
++ URPM::Build, URPM::Resolve and URPM::Signature.
++ Documentation fixes. Tidy up the tests (and add a few ones.)
++
++2004-04-02 14:02 Rafael Garcia-Suarez &lt;rgarciasuarez at mandriva.com&gt;
++
++ * MANIFEST, Makefile.PL, URPM.pm, t/synthesis.t: Add some API
++ documentation for the URPM module.
++ Plus, some minor nits in auxiliary files.
++
++2004-04-01 10:40 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * ChangeLog: *** empty log message ***
++
++2004-02-25 22:35 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * perl-URPM.spec: 0.94-11mdk
++
++2004-01-18 02:25 Olivier Thauvin &lt;thauvin at aerov.jussieu.fr&gt;
++
++ * URPM/Build.pm: - parse_rpm_build_headers have same behaviour
++ with dontdie and callback
++ when using cache or the rpm
++
++2004-01-15 18:20 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * ChangeLog: *** empty log message ***
++
++2003-12-09 19:40 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: added support for RH
++ 7.3
++
++2003-11-17 21:01 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.98-9mdk
++
++2003-11-17 20:59 Fan&#231;ois Pons
++
++ * URPM/Build.pm: fixed bad use of option idlist for checking its
++ presence
++
++2003-11-15 19:47 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-8mdk
++
++2003-11-15 19:44 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm: fixed indentation and reworked code to
++ be simpler
++
++2003-11-15 19:33 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm: applied patch from Olivier Thauvin
++
++2003-10-13 12:36 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-7mdk
++
++2003-10-13 12:34 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed to find package with full provides on
++ whatrequires obsoleted, so that
++ pam-devel is upgraded correctly for example.
++
++2003-09-10 15:12 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-6mdk
++
++2003-09-10 15:11 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: removed STDERR log.
++ * URPM/Resolve.pm: diff_provides on obsoleted provides are needed.
++
++2003-09-10 11:46 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-5mdk
++
++2003-09-10 11:45 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed bad ARRAY reference (promote).
++
++2003-09-05 10:33 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.94-4mdk
++
++2003-09-02 17:19 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-3mdk
++ * URPM/Resolve.pm: removed log.
++
++2003-09-02 17:18 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed package badly removed.
++
++2003-08-22 13:53 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.94-2mdk
++
++2003-08-22 13:52 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: removed potential deadlock.
++
++2003-08-21 13:04 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Signature.pm, perl-URPM.spec: 0.94-1mdk
++ (URPM::Signature fixes and changes)
++
++2003-08-21 11:25 Fan&#231;ois Pons
++
++ * URPM/Signature.pm: fixed with gc suggestion which are really
++ fine (and right).
++
++2003-08-20 16:17 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: final 0.93-7mdk
++
++2003-08-20 15:10 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Signature.pm, perl-URPM.spec: 0.93-7mdk (signature
++ comparison workaround)
++
++2003-08-19 16:33 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.93-6mdk
++
++2003-08-19 16:32 Fan&#231;ois Pons
++
++ * URPM.xs: added URPM::import_pubkey to import a key (only one)
++ directly to opened rpm
++ database or by opening the database on the fly.
++
++2003-08-19 16:31 Fan&#231;ois Pons
++
++ * URPM/Signature.pm: fixed URPM::import_armored_file to use
++ internal XS function to import directly
++ to database, handle importation of multiple keys by file.
++
++2003-08-18 15:29 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm, perl-URPM.spec: perl_checker compliance
++
++2003-08-13 12:04 Guillaume Cottenceau
++
++ * perl-URPM.spec: provide URPM::Signature as well
++
++2003-08-11 15:27 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.93-3mdk
++ * URPM.xs: fixed files_md5sum returning not the same number as
++ files method.
++ removed unsatisfied_requires2 not used (and doing nothing
++ usefull).
++
++2003-08-11 14:04 Fan&#231;ois Pons
++
++ * URPM/Signature.pm, perl-URPM.spec: 0.93-2mdk
++
++2003-08-06 17:45 Fan&#231;ois Pons
++
++ * URPM/Signature.pm: final 0.93-1mdk
++
++2003-08-06 15:54 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Build.pm, URPM/Signature.pm, perl-URPM.spec:
++ 0.93-1mdk
++
++2003-08-06 09:52 Fan&#231;ois Pons
++
++ * MANIFEST: added signature management.
++
++2003-08-06 09:50 Fan&#231;ois Pons
++
++ * URPM/Signature.pm: initial support for parsing armored file
++ (without gpg) and registering rpmdb pubkeys.
++
++2003-08-04 17:51 Fan&#231;ois Pons
++
++ * MANIFEST, URPM/Resolve.pm, perl-URPM.spec: 0.92-4mdk
++
++2003-08-01 19:29 Pixel &lt;pixel at mandriva.com&gt;
++
++ * perl-URPM.spec: - rebuild for new perl (it helps DrakX build
++ script)
++ - use DESTDIR
++
++2003-07-30 16:59 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.92-2mdk
++
++2003-07-30 16:57 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed some missing unsatisfied in reason of
++ rejected packages.
++ fixed provide obsoleted which should not be taken into account
++ when looking for
++ obsoletes.
++
++2003-07-28 15:13 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.92-1mdk
++
++2003-07-24 15:28 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-14mdk
++
++2003-07-24 10:10 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm, URPM/Resolve.pm, perl-URPM.spec:
++ 0.91-13mdk
++
++2003-07-16 13:34 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.91-12mdk
++
++2003-07-16 13:10 Fan&#231;ois Pons
++
++ * URPM/Build.pm: fixed cache not taken into account.
++
++2003-07-16 12:07 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed small typo on regex for
++ URPM::compute_flags
++
++2003-07-10 16:09 Fan&#231;ois Pons
++
++ * URPM.xs: fixed SvPV typos.
++
++2003-07-10 16:05 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.91-11mdk
++
++2003-07-10 16:04 Fan&#231;ois Pons
++
++ * Makefile.PL: removed -f-no-rtti as no C++ code is used.
++
++2003-07-10 16:03 Fan&#231;ois Pons
++
++ * URPM.xs: starting coding unsatisfied_requires in C, incomplete.
++ modified return_list_str to allow getting strings list in C
++ easily and quickly.
++
++2003-07-10 16:02 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: optimized URPM::compute_flags method by an
++ almost unlimited factor.
++
++2003-07-07 17:28 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-10mdk
++
++2003-07-07 15:14 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-9mdk
++
++2003-07-04 12:18 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-8mdk
++
++2003-06-26 15:26 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-7mdk
++
++2003-06-19 14:24 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-6mdk
++
++2003-06-19 11:12 Fan&#231;ois Pons
++
++ * URPM.xs: make sure a callback parameter is taken into account
++ only if a reference is
++ used.
++
++2003-06-19 10:31 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-5mdk
++
++2003-06-18 17:02 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: added missing fix on bad
++ conflicts listing,
++ removed stderr logs.
++
++2003-06-18 16:53 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-4mdk
++
++2003-06-18 16:14 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-4mdk
++
++2003-06-18 11:52 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.91-3mdk
++
++2003-06-17 15:59 Fan&#231;ois Pons
++
++ * perl-URPM.spec: added compilable on rpm-4.0.4 of rpm.
++
++2003-06-17 15:54 Fan&#231;ois Pons
++
++ * URPM.xs: fixed compilation on rpm 4.0.4.
++
++2003-06-17 15:35 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: fixed 0.91-2mdk
++
++2003-06-17 13:39 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.91-2mdk
++
++2003-06-16 17:57 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec, t/rpmdb.t:
++ 0.91-1mdk
++
++2003-06-12 15:52 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.90-10mdk
++ * URPM.xs: improved return value of verify_rpm.
++
++2003-06-11 15:42 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: removed $v-&gt; (for rejected hash value) by $rv
++ in order to avoid name clash
++ with $v (version).
++
++2003-06-11 11:34 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.90-9mdk
++
++2003-06-05 18:41 Fan&#231;ois Pons
++
++ * URPM.xs: fixed memory leak in parse_rpm.
++
++2003-06-05 17:46 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.90-8mdk
++
++2003-06-05 13:53 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.90-7mdk
++
++2003-06-05 08:47 Fan&#231;ois Pons
++
++ * URPM/Build.pm, URPM/Resolve.pm: added clever cache header
++ management during build of hdlist.
++ removed no_flag_update obsoleted.
++
++2003-06-04 09:47 Warly &lt;warly at mandriva.com&gt;
++
++ * URPM.xs, perl-URPM.spec: Add Pkg_buildtime to get
++ RPMTAG_BUILDTIME
++
++2003-06-03 10:21 Fan&#231;ois Pons
++
++ * perl-URPM.spec: a newer version for a newer package.
++
++2003-06-03 10:14 Fan&#231;ois Pons
++
++ * URPM.xs: fixed sutpid typo (strange compiler didn't notice
++ anything)
++
++2003-06-02 16:38 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.90-4mdk
++
++2003-05-30 11:32 Warly &lt;warly at mandriva.com&gt;
++
++ * URPM.xs: move packing and keep_all_tags declaration in
++ Urpm_parse_rpm to the begining of the function in order to get
++ the argument initialisation correctly working (otherwize they
++ were overriden and systematically set to 0).
++
++2003-05-30 10:11 Warly &lt;warly at mandriva.com&gt;
++
++ * URPM.xs, perl-URPM.spec: add Pkg_license function to URPM.xs
++ (URPM::Package)
++
++2003-05-26 15:13 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.90-2mdk
++
++2003-05-23 15:26 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.90-1mdk
++ first backtrackable method, still lacking backtrack of remove and
++ better handling of choices during backtrack, too much simplist.
++
++2003-05-16 15:11 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.84-1mdk
++
++2003-05-14 17:43 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.83-4mdk
++
++2003-05-13 21:02 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm, perl-URPM.spec: 0.83-3mdk
++
++2003-05-13 20:46 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM/Build.pm: perl_checker fixes
++
++2003-05-13 20:35 Thierry Vignaud &lt;tvignaud at mandriva.com&gt;
++
++ * URPM.pm: perl_checker fix
++
++2003-05-12 16:43 Guillaume Cottenceau
++
++ * perl-URPM.spec: - rebuild for new perl requires/provides
++ - provide perl packages URPM::Resolve and URPM::Build since the
++ perl packages are URPM for object export
++
++2003-04-29 17:16 Fan&#231;ois Pons
++
++ * Makefile.PL, URPM.pm, URPM.xs, build_rpm, perl-URPM.spec: first
++ try of 4.2 compatible perl-URPM,
++ missing verify_signature,
++ new version 0.83
++
++2003-04-24 15:51 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.82-4mdk
++
++2003-04-22 14:35 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.82-3mdk
++
++2003-04-14 13:07 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.82-2mdk
++
++2003-04-11 16:29 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fixed stupid typo in compute_skip_flags
++
++2003-04-11 16:06 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: brand new
++ 0.82 version (flag_skip, excludedocs, fix NULL get_name)
++
++2003-03-12 18:16 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.81-13mdk
++
++2003-03-10 16:44 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Build.pm, URPM/Resolve.pm, perl-URPM.spec:
++ 0.81-12mdk
++
++2003-03-03 13:09 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.81-11mdk
++
++2003-02-27 13:22 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.81-10mdk
++
++2003-02-27 13:13 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: allow choices to return multiple selection.
++
++2003-02-19 13:28 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.81-9mdk
++
++2003-02-13 18:37 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.81-8mdk
++
++2003-02-13 17:53 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: fix rpmdrake woes on incompatible arch.
++
++2003-01-23 14:29 Fan&#231;ois Pons
++
++ * URPM/Build.pm, URPM/Resolve.pm, perl-URPM.spec: 0.81-7mdk
++
++2003-01-06 16:33 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.81-6mdk
++
++2003-01-06 11:25 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.81-5mdk
++
++2002-12-20 11:05 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM/Resolve.pm, perl-URPM.spec: perl_checker fixes (syntax only)
++
++2002-12-18 14:57 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm, perl-URPM.spec: help perl_checker recognise packages
++ used as classes
++
++2002-12-18 12:54 Pixel &lt;pixel at mandriva.com&gt;
++
++ * URPM.pm, perl-URPM.spec: perl_checker fixes
++
++2002-12-17 13:57 Fan&#231;ois Pons
++
++ * URPM.pm, perl-URPM.spec: added very faster code, 3 times faster
++ on traverse_tag with --env.
++
++2002-12-17 13:46 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.81-1mdk
++
++2002-12-11 11:27 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.80-2mdk
++
++2002-12-05 17:58 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, perl-URPM.spec: 0.80-1mdk
++
++2002-12-03 14:43 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, perl-URPM.spec: 0.71-1mdk
++
++2002-09-17 13:16 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-10mdk
++
++2002-09-09 14:25 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-9mdk
++
++2002-09-02 14:46 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-8mdk
++
++2002-08-30 15:52 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-7mdk
++
++2002-08-30 13:08 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-6mdk
++
++2002-08-29 15:48 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-5mdk
++
++2002-08-29 09:41 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.70-4mdk
++
++2002-08-28 14:15 Fan&#231;ois Pons
++
++ * perl-URPM.spec: added URL (cvsweb at least).
++
++2002-08-28 14:06 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.70-3mdk
++
++2002-08-26 18:29 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.70-2mdk
++
++2002-08-23 13:08 Fan&#231;ois Pons
++
++ * URPM.pm: fixed VERSION to 0.70.
++
++2002-08-23 13:06 Fan&#231;ois Pons
++
++ * URPM.pm, perl-URPM.spec: 0.70-1mdk.
++
++2002-08-13 10:05 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-8mdk
++
++2002-08-12 16:00 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-7mdk
++
++2002-08-12 13:34 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-6mdk
++
++2002-08-09 17:12 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-5mdk
++
++2002-08-09 16:47 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-4mdk
++
++2002-08-07 14:25 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.60-3mdk
++
++2002-08-06 15:04 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.60-2mdk
++
++2002-08-05 16:57 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.60-1mdk
++
++2002-07-25 11:19 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.50-6mdk
++
++2002-07-25 07:27 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.50-5mdk
++
++2002-07-25 07:08 Fan&#231;ois Pons
++
++ * URPM/Build.pm: fixed typo (stupid).
++
++2002-07-24 12:36 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm, URPM/Resolve.pm, perl-URPM.spec:
++ 0.50-4mdk
++
++2002-07-24 09:18 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.50-3mdk
++
++2002-07-23 15:14 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.50-2mdk
++
++2002-07-23 13:17 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.50-1mdk
++
++2002-07-23 11:59 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.20-2mdk
++
++2002-07-22 17:53 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.20-1mdk
++
++2002-07-22 08:35 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.11-2mdk
++
++2002-07-19 08:50 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.11-1mdk
++
++2002-07-16 18:07 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.10-2mdk
++
++2002-07-15 16:53 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.10-1mdk
++
++2002-07-11 13:14 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.09-2mdk
++
++2002-07-10 10:19 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.09-1mdk
++
++2002-07-09 15:06 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm, perl-URPM.spec: 0.08-4mdk
++
++2002-07-09 10:55 Pixel &lt;pixel at mandriva.com&gt;
++
++ * perl-URPM.spec: adapt to perl 5.8.0
++
++2002-07-08 14:47 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.08-2mdk
++
++2002-07-08 09:55 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, perl-URPM.spec: 0.08-1mdk
++
++2002-07-05 15:25 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.07-2mdk
++
++2002-07-04 17:53 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, perl-URPM.spec, typemap: 0.07-1mdk
++
++2002-07-03 16:11 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.06-2mdk
++
++2002-07-03 12:40 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Build.pm, URPM/Resolve.pm,
++ perl-URPM.spec: 0.06-1mdk
++
++2002-07-01 11:55 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.05-2mdk
++
++2002-06-28 08:44 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Resolve.pm, perl-URPM.spec: 0.05-1mdk
++
++2002-06-26 12:37 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.04-6mdk
++
++2002-06-18 14:17 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.04-5mdk
++
++2002-06-13 17:56 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm, perl-URPM.spec: 0.04-4mdk
++
++2002-06-13 16:16 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec: 0.04-3mdk
++
++2002-06-13 15:19 Fan&#231;ois Pons
++
++ * URPM/Resolve.pm: added compute_installed_flags for yoyotte.
++
++2002-06-13 10:48 Fan&#231;ois Pons
++
++ * perl-URPM.spec: 0.04-2mdk
++
++2002-06-13 10:24 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.04-1mdk
++
++2002-06-11 18:02 Fan&#231;ois Pons
++
++ * MANIFEST: added missing entry Resolve.pm
++
++2002-06-11 17:59 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, URPM/Resolve.pm, perl-URPM.spec: 0.04-1mdk
++
++2002-06-06 15:44 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, perl-URPM.spec: 0.03-2mdk
++
++2002-06-06 09:57 Fan&#231;ois Pons
++
++ * URPM.pm, URPM.xs, build_rpm, perl-URPM.spec: 0.03-1mdk
++
++2002-06-05 16:44 Fan&#231;ois Pons
++
++ * URPM.xs, perl-URPM.spec, t/rpmdb.t: 0.02-3mdk
++
++2002-06-05 08:03 Fan&#231;ois Pons
++
++ * URPM.xs, URPM/Build.pm, perl-URPM.spec: log on rpmdb open/close.
++
++2002-06-03 11:00 Fan&#231;ois Pons
++
++ * URPM.pm, URPM/Build.pm, perl-URPM.spec: cleaned URPM::Build to
++ accept extended parameter list and -w clean.
++ 0.02.
++
++2002-05-31 10:48 Fan&#231;ois Pons
++
++ * perl-URPM.spec: added Packager field.
++
++2002-05-31 10:45 Fan&#231;ois Pons
++
++ * build_rpm, perl-URPM.spec: initial revision.
++
++2002-05-31 10:21 Fan&#231;ois Pons
++
++ * MANIFEST, Makefile.PL, README, URPM, URPM.pm, URPM.xs,
++ URPM/Build.pm, t, t/rpmdb.t, t/synthesis.t, typemap: initial
++ revision.
++
++2002-05-31 10:21
++
++ * soft/rpm/perl-URPM/branches, soft/rpm/perl-URPM/tags, .: New
++ repository initialized by cvs2svn.
++
+
+Added: rpm/perl-URPM/trunk/MANIFEST
+===================================================================
+--- rpm/perl-URPM/trunk/MANIFEST (rev 0)
++++ rpm/perl-URPM/trunk/MANIFEST 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,22 @@
++README
++MANIFEST
++Makefile.PL
++typemap
++URPM.xs
++URPM.pm
++URPM/Build.pm
++URPM/Query.pm
++URPM/Resolve.pm
++URPM/Signature.pm
++t/00prepare.t
++t/buggy_synthesis.cz
++t/empty_synthesis.cz
++t/fatal.t
++t/parse.t
++t/pod.t
++t/rpmdb.t
++t/sort_graph.t
++t/synthesis.t
++t/test-rpm.spec
++ChangeLog
++META.yml Module meta-data (added by MakeMaker)
+
+Added: rpm/perl-URPM/trunk/META.yml
+===================================================================
+--- rpm/perl-URPM/trunk/META.yml (rev 0)
++++ rpm/perl-URPM/trunk/META.yml 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,11 @@
++# <A HREF="http://module-build.sourceforge.net/META-spec.html">http://module-build.sourceforge.net/META-spec.html</A>
++#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
++name: URPM
++version: 1.43
++version_from: URPM.pm
++installdirs: site
++requires:
++ MDV::Packdrakeng: 1.00
++
++distribution_type: module
++generated_by: ExtUtils::MakeMaker version 6.30_01
+
+Added: rpm/perl-URPM/trunk/Makefile.PL
+===================================================================
+--- rpm/perl-URPM/trunk/Makefile.PL (rev 0)
++++ rpm/perl-URPM/trunk/Makefile.PL 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,74 @@
++use strict;
++use ExtUtils::MakeMaker;
++
++# where to find the rpm utility
++
++my $rpm_path = $ENV{RPM_PATH}; # this overrides
++
++unless (defined $rpm_path) {
++ for (qw(/bin/rpm /usr/bin/rpm)) {
++ if (-x) {
++ $rpm_path = $_;
++ last;
++ }
++ }
++}
++
++defined $rpm_path or die &quot;Can't find rpm on this system\n&quot;;
++
++sub hexversion {
++ my ($major, $minor, $micro) = (@_[0] =~ /(\d+)\.(\d+)\.?(\d+)?/);
++ return int($major&lt;&lt;16) + int($minor&lt;&lt;8) + int($micro&lt;&lt;0)
++}
++
++my $version = `LC_ALL=C $rpm_path --version`;
++# fix compiling with RCs:
++$version =~ s/(-.*)|(\.DEVEL)//;
++chomp $version;
++$version =~ s/(RPM version )|(rpm \(RPM\) )//;
++my $hversion = hexversion($version);
++$hversion ge hexversion(&quot;4.2&quot;) or die &quot;Unable to build URPM with too old (or undetected) rpm version $version\n&quot;;
++
++# to generate the ChangeLog depending on the checkout layout
++my $commonusername = &quot;../common/&quot;;
++-d $commonusername or do {
++ $commonusername = &quot;../../common/&quot;;
++ -d $commonusername or do {
++ $commonusername = &quot;../../../common/&quot;;
++ -d $commonusername or $commonusername = &quot;&quot;;
++ };
++};
++
++sub MY::postamble {
++ &lt;&lt;&quot;**MM**&quot;;
++.PHONY: ChangeLog
++
++ChangeLog:
++ LC_ALL=C svn2cl --accum --strip-prefix=soft/rpm/perl-URPM/trunk --authors ${commonusername}username.xml
++ rm -f *.bak
++**MM**
++}
++
++my @rpmflags;
++my $ldflags = `pkg-config --libs rpm`;
++if ($hversion ge hexversion(&quot;4.4.90&quot;) &amp;&amp; $hversion lt hexversion(&quot;5.0&quot;)) {
++ # rpm.org version
++ push @rpmflags, &quot;-DRPM_ORG&quot;;
++ $ldflags .= ' -lrpmbuild';
++}
++my $ccflags = join(' ', '-Wall -Wextra -fno-strict-aliasing', @rpmflags);
++
++print &quot;Found RPM version $version (compiling with flags: $ccflags)\n&quot;;
++
++WriteMakefile(
++ NAME =&gt; 'URPM',
++ PREREQ_PM =&gt; {
++ 'MDV::Packdrakeng' =&gt; '1.00',
++ },
++ CCFLAGS =&gt; $ccflags,
++ VERSION_FROM =&gt; 'URPM.pm',
++ LIBS =&gt; [ $ldflags ],
++ INC =&gt; '-I/usr/include/rpm',
++ dist =&gt; { COMPRESS =&gt; &quot;bzip2&quot;, SUFFIX =&gt; &quot;.bz2&quot; },
++ realclean =&gt; { FILES =&gt; &quot;t/RPMS/noarch/*&quot; },
++);
+
+Added: rpm/perl-URPM/trunk/NEWS
+===================================================================
+--- rpm/perl-URPM/trunk/NEWS (rev 0)
++++ rpm/perl-URPM/trunk/NEWS 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,426 @@
++Version 3.38 - 16 November 2010
++
++- fix the key parsing to handle PEM encapsulated header portion (bug
++#61636)
++
++Version 3.37 - 20 September 2010
++
++- fix crashing on undefined packages (#54521)
++
++Version 3.36 - 23 July 2010
++
++- Fix wrong deferencement on HASH (warning triggered by perl 5.12)
++
++Version 3.35 - 23 April 2010
++
++- when using auto-select, honour search-medias if some were specified
++
++Version 3.34.1 - 23 March 2010
++
++- check selected packages for unsatisfied requires when a promoted package is
++ backtracked and no replacement is found (#57224, Anssi Hannula)
++
++Version 3.34 - 24 February 2010
++
++- check for conflicting selected packages before selecting a package (#57224)
++ (by Anssi Hannula)
++
++Version 3.33 - 5 October 2009, by Christophe Fergeau
++
++- fix lookup of existing pubkeys (#53710) (by Pascal Terjan)
++
++Version 3.32 - 10 August 2009, by Christophe Fergeau
++
++- backtrack_selected: use set_rejected_and_compute_diff_provides for package
++ removal (Anssi Hannula)
++- obey options (keep, nodeps) when unselecting current package in the case
++ that was added in 3.31 (Anssi Hannula)
++
++Version 3.31 - 28 July 2009, by Christophe Fergeau
++
++- add support for querying %disttag &amp; %distepoch (by Per &#216;yvind Karlsen)
++- clean up and bring back rpm5.org support (by Per &#216;yvind Karlsen)
++- keep track of sources for obsoleted/removed levels (#50666) Anssi Hannula)
++- keep psel/promote info and remove deadlocked pkg instead of aborting upgrade
++ (#52105, Anssi Hannula)
++- _handle_conflicts: check all provides for conflicts, not just package name
++ (#52135, Anssi Hannula)
++- unselect current package if an avoided package is already selected (#52145,
++ Anssi Hannula)
++- do not try to promote to an older package (#52460, Anssi Hannula)
++- add a backtrack entry &quot;conflicts&quot; for avoided packages in backtrack_selected
++ (#52153, Anssi Hannula)
++
++Version 3.30 - 11 May 2009, by Christophe Fergeau
++
++- rework public key handling since librpm behaviour has changed. It's no longer
++ possible to tell it to add the same key multiple times which was causing
++ weird &quot;unable to import pubkey&quot; messages when a mirror contains different
++ pubkeys for the same key, fixes #50383
++
++Version 3.29 - 27 March 2009, by Christophe Fergeau
++
++- fix regression introduced by fix for bug #47803 (fix by Anssi Hannula).
++ Without this patch, urpmi got stuck in an infinite loop when trying
++ to upgrade from 2008.1.
++
++Version 3.28 - 25 March 2009, by Christophe Fergeau
++
++- postpone user choices as much as possible to avoid asking the user
++ unnecessary questions, (bug #48100, Anssi Hannula)
++
++Version 3.27 - 24 March 2009, by Christophe Fergeau
++
++- don't silently install suggests (bug #47934)
++- fix _handle_diff_provides in case of impossible-to-satisfy selected
++ packages (bug #48223, Anssi Hannula)
++- check rep for another pkg providing X if the prev pkg gets removed
++ due to a conflict (bug #47803, Anssi Hannula)
++
++Version 3.26 - 5 March 2009, by Thierry Vignaud
++
++- verify_signature: enable to check signatures against a chrooted rpmdb
++ (especially important for installer where there's no rpmdb in / and thus no
++ keys to check against)
++
++Version 3.25 - 16 January 2009, by Christophe Fergeau
++
++- previous fix for bug #46874 was bogus, really fix it this time
++
++Version 3.24 - 13 January 2009, by Christophe Fergeau
++
++- fix sorting choices on provided version (feature introduced in 3.08,
++ but was not working if packages were coming from different repository)
++- when a &quot;Requires:&quot; can be fullfilled by several different packages and
++ one of those packages is explicitly required by another package which
++ is also being installed, silently choose this package instead of letting
++ the choice up to perl-URPM user (fixes bug #46874)
++
++Version 3.23 - 12 December 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix bad free() (thanks to glibc for detecting it)
++
++Version 3.22 - 12 December 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix scriptlet failing:
++ adapt to librpm4.6, rpmtsSetRootDir(ts, &quot;&quot;) is forbidden
++
++Version 3.21 - 9 December 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- adapt to librpm4.6
++- drop list_rpm_tag()
++
++Version 3.20 - 14 October 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- $trans-&gt;run can now return both the translated errors, and some parsable
++ errors (useful for example to detect diskspace issues)
++
++Version 3.19 - 7 October 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- handle flag &quot;replacefiles&quot;
++
++Version 3.18 - 7 July 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- revert change introduced in 3.16 (it breaks too much, eg
++ superuser--priority-upgrade.t test case), and introduce
++ $state-&gt;{rejected_already_installed} instead
++
++Version 3.17 - 4 July 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- add traverse_tag_find(), removed_or_obsoleted_packages()
++- handle $state-&gt;{orphans_to_remove} in selected_size() and
++ build_transaction_set()
++
++Version 3.16 - 26 June 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- when not selecting a package because already installed,
++ put it in $state-&gt;{rejected} with flags {installed}
++
++Version 3.15 - 23 June 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix urpmi wrongly considering epochless conflicts to match any epoch in a
++ case when urpmi should upgrade a conflicting package to an actually
++ non-conflicting version (cf epochless-conflict-with-promotion urpmi test)
++ (Anssi)
++
++Version 3.14 - 23 May 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- add is_package_installed() in URPM/Resolve.pm
++ (to be used in urpmi 5.20)
++
++Version 3.13 - 20 May 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- do not ignore dropped provide from updated package (mdvbz#40842)
++
++Version 3.12 - 7 March 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- do allow to promoting a pkg even if it has unsatisfied require (since the
++ code will then fix the unsatisfied require). fixes &quot;big transaction&quot;
++ (cf urpmi split-transactions--strict-require.t test_efgh())
++- rpm5.org port done (by Per &#216;yvind Karlsen)
++
++Version 3.11 - 26 February 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- restore FILENAME_TAG in generated hdlist (to be compatible with older
++ distros where -&gt;filename can rely on it) (thanks to Nanar)
++
++Version 3.10 - 26 February 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- add filesize to synthesis, add -&gt;filesize to get it, and add
++ selected_size_filesize() to compute the sum
++- allow urpmi to know a package was not selected because a newer version is
++ installed (#29838)
++- handle new package providing xxx which conflicts with an installed package (#17106)
++- fix sort choices changed in perl-URPM 3.08
++- allow fixing &quot;using one big transaction&quot; that occurs when using --keep
++ (#30198)
++- do not add FILENAME_TAG and FILESIZE_TAG to hdlist anymore,
++ deprecate -&gt;header_filename,
++ deprecate URPM::Build::parse_rpms_build_headers
++
++Version 3.08 - 25 February 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- sort choices on virtual package by provided version (#12645)
++
++Version 3.07 - 11 January 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- add URPM::Package-&gt;changelogs, a wrapper around -&gt;changelog_time, -&gt;changelog_name, -&gt;changelog_text
++- resolve kmod requires even if first choice is a source dkms
++
++Version 3.05 - 8 January 2008, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix regression in -&gt;parse_rpm (introduced in 3.00)
++ (was breaking genhdlist2 and mkcd)
++
++Version 3.04 - 20 December 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix regression in parse_pubkeys() (introduced in 3.00) (#36121)
++
++Version 3.03 - 14 December 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- suggests:
++ handle both RPMTAG_SUGGESTSNAME (as done in SuSE and in Mandriva &gt; 2008.0)
++ and RPMTAG_REQUIRENAME + RPMSENSE_MISSINGOK (as done in Mandriva 2008.0)
++
++Version 3.02 - 14 December 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix &quot;make test&quot; on rpm 4.4.2.2
++- fix rpm 4.5 support
++
++Version 3.01 - 11 December 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- add URPM::DB::verify()
++
++Version 3.00 - 11 December 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- replace -&gt;import_needed_pubkeys and -&gt;import_pubkey in favor of
++ import_needed_pubkeys_from_file() and -&gt;import_pubkey_file
++ (! this breaks API !)
++- drop $package-&gt;upgrade_files() (unused for a long time afaik)
++- rpm.org HEAD support
++
++Version 2.10 - 22 November 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- much simpler --auto-select algorithm
++ (fixes #35718, ie auto-selecting with strict-arch)
++ (!! DANGEROUS CHANGE !!)
++- rpm 4.5 support (thanks to peroyvind) (#35323)
++
++Version 2.09 - 8 November 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- use a simple function to return simple string list from header
++ (fixes getting &gt;4096 long rpm changelogs)
++ (!! static buffer size limitation in callback_list_str_xpush() should be fixed !!)
++
++Version 2.08 - 24 October 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix build on rpm 4.4.2.2
++
++Version 2.07 - 1 October 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- prefer precompiled kmod packages corresponding to installed kernels
++- don't resolve suggested virtual packages if already installed (#34376)
++
++Version 2.06 - 28 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- also handle promotion via obsolete for conflicts
++
++Version 2.05 - 28 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- package promotion must respect strict_arch
++- enhance sorted graph by better taking into account conflicts from state-&gt;{rejected}
++ (fixes &quot;big transaction&quot; in urpmi split-transactions--strict-require.t test)
++
++Version 2.04 - 27 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- handle promotion via obsolete, not only provides
++
++Version 2.03 - 20 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix bug doing &quot;urpmi kernel-source&quot;
++
++Version 2.02 - 18 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- prefer every kernel-&lt;flavor&gt;-devel-&lt;version&gt; packages for which
++ kernel-&lt;flavor&gt;-&lt;version&gt; is selected
++- fix regression in 2.00: we can't cache the platform, cache the result of
++ is_arch_compat instead
++
++Version 2.01 - 14 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix bug occurring with --keep
++- fix regression in 2.00: keep_unrequested_dependencies is still used by
++ installer. restore it, but must now be set trough
++ $urpm-&gt;{keep_unrequested_dependencies}
++
++Version 2.00 - 13 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- speedup is_arch_compat (7 times faster) by keeping the platform in a cache
++- do not propose packages for non installed locales
++- pass the prefered choices to {callback_choices}: this allows urpmi to select
++ all the prefered packages according to installed locales
++- handle promote for conflict from installed package
++ (fixes test_gh() from urpmi split-transactions--promote test case)
++- handle promote from installed package which require a unselected package,
++ whereas new package does not require it anymore
++ (cf test_d &amp; test_e from split-transactions--conflict urpmi test case)
++
++Version 1.80 - 3 September 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix bug in sort_graph (used by build_transaction_set)
++
++Version 1.78 - 31 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix dead-loop in build_transaction_set (#33020)
++
++Version 1.77 - 29 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- disable &quot;dropping tags from rpm header&quot; until we can safely use it
++
++Version 1.76 - 28 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- build_transaction_set: new sort algorithm which allow returning sets of
++ circular dependent packages, taking into account obsoleted packages
++ (fixes #31969). It may still fail in presence of conflicts
++- allow running transaction with justdb option
++- fix split_length &gt; 1
++ (eg: &quot;urpmi --split-length 2 a b c&quot; will only install 2 pkgs)
++- spec2srcheader: workaround parseSpec returning a header where -&gt;arch is set
++ to %{_target_cpu} whereas we really want a header similar to .src.rpm
++ (see #32824)
++
++Version 1.75 - 12 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix dropping tags from rpm header.
++ it hasn't work since MDK8.1 and rpm 4.0.
++ it may break urpmi!! but potentially allows a much smaller hdlist.cz :)
++
++Version 1.74 - 12 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- sort choices per media, then per version
++
++Version 1.73 - 11 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- allow running transaction with replagekgs option
++
++Version 1.72 - 10 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- modify parse_hdlist so that partial hdlist reading can be used
++ (needed when some stuff is already done in the callback)
++
++Version 1.71 - 9 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- compilation fixes on rpm &lt; 4.4.8
++
++Version 1.69 - 9 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- &quot;suggests&quot; are no more handled as &quot;requires&quot;
++- resolve_requested support &quot;suggests&quot;: a newly suggested package is installed
++ as if required (can be disabled with option no_suggests)
++
++Version 1.68 - 3 August 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- add $trans-&gt;Element_version and $trans-&gt;Element_release
++
++Version 1.67 - 22 June 2007, by Olivier &quot;Nanar&quot; Thauvin
++
++- add osscore, archscore and platformscore function to URPM
++- is_platform_compat function to Pkg object
++- fix call to rpm function in spec2header()
++- fix some compilation warnings
++
++Version 1.66 - 2 July 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- fix --auto-select skipping some packages because of other packages providing
++ a more recent version, but no obsolete between those packages.
++ the fix is to revert commit from Aug 2002:
++ &quot;fixed propable old package (according provides) requested by
++ request_packages_to_upgrade.&quot;
++
++Version 1.65 - 22 June 2007, by Olivier Thauvin
++
++- really fix arch_score evaluation
++
++Version 1.64 - 12 June 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- hack on $pkg-&gt;is_arch_compat to make it return true for noarch packages
++ when using rpm 4.4.8 (#31314)
++
++Version 1.63 - 9 May 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- add $trans-&gt;Element_fullname
++
++Version 1.62 - 3 May 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- pass the virtual package name as a parameter to {callback_choices} in
++ -&gt;resolve_requested
++- add $trans-&gt;NElements and $trans-&gt;Element_name
++ to be able to display name of uninstalled package in callback_uninst
++- fix b--obsoletes--&gt;a and c--conflicts--&gt;a prompting for upgrading a
++ (need a fix in urpmi which rely on the $state-&gt;{rejected}
++ to upgrade (-U) b instead of installing (-i) it)
++
++Version 1.60 - 8 March 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- more debugging hooks
++- create $urpm-&gt;packages_providing($name) and use it
++- create $urpm-&gt;packages_by_name($name)
++
++Version 1.59 - 1 March 2007, by Olivier Thauvin
++
++- rpm 4.4.8 adaptions
++- load rpm config files at module load, improve the mechanism
++
++Version 1.58 - 14 February 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- don't check signature and digest in -&gt;traverse and -&gt;traverse_tag
++ (=&gt; x15 speedup, ie 2.5 speedup on urpmi --auto-select and rpmdrake)
++
++Version 1.57 - 9 February 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- allow upgrading from noarch to x86_64 even if strict-arch
++
++Version 1.56 - 19 January 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- tell perl that strings from rpm headers are utf8
++- add URPM::bind_rpm_textdomain_codeset() to set encoding of messages returned
++ by rpmlib, and tell perl that those strings are utf8
++- really use strict-arch by default on x86_64
++
++Version 1.55 - 10 January 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- bug fix release
++- fix &quot;not selecting foo-1 since the more recent foo-1 is installed&quot; causing
++ urpmi to try to remove the package it wants to install (#28076)
++
++Version 1.54 - 9 January 2007, by Pascal &quot;Pixel&quot; Rigaux
++
++- if we have a choice between foo-1 and bar-1 and foo-2 is installed,
++ prefering bar-1 instead of foo-1
++ (otherwise we can hit: &quot;the more recent foo-2 is installed, but does not
++ provide xxx whereas foo-1 does&quot;, cf bug #27991)
++- bar is needed, foo-1 does provide bar, installed foo-2 does not provide bar:
++ do not let the algorithm use foo-2 as if it also provides bar
++- allow understanding what -&gt;resolve_requested is doing through a callback ($urpm-&gt;{debug_URPM})
++- cleanup some code in -&gt;resolve_requested
++- make the documentation for -&gt;is_arch_compat more clear
+
+Added: rpm/perl-URPM/trunk/README
+===================================================================
+--- rpm/perl-URPM/trunk/README (rev 0)
++++ rpm/perl-URPM/trunk/README 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,7 @@
++The URPM module allows you to manipulate rpm files, rpm header files and
++hdlist files and manage them in memory.
++
++Copyright 2002-2007 Mandrakesoft
++
++This library is free software; you can redistribute it and/or
++modify it under the same terms as Perl itself.
+
+Added: rpm/perl-URPM/trunk/URPM/.perl_checker
+===================================================================
+--- rpm/perl-URPM/trunk/URPM/.perl_checker (rev 0)
++++ rpm/perl-URPM/trunk/URPM/.perl_checker 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1 @@
++Basedir ..
+
+Added: rpm/perl-URPM/trunk/URPM/Build.pm
+===================================================================
+--- rpm/perl-URPM/trunk/URPM/Build.pm (rev 0)
++++ rpm/perl-URPM/trunk/URPM/Build.pm 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,528 @@
++package URPM;
++
++# $Id: Build.pm 270395 2010-07-30 00:55:59Z nanardon $
++
++use strict;
++use warnings;
++
++sub _get_tmp_dir () {
++ my $t = $ENV{TMPDIR};
++ $t &amp;&amp; -w $t or $t = '/tmp';
++ &quot;$t/.build_hdlist&quot;;
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#
++#- prepare build of an hdlist from a list of files.
++#- it can be used to start computing depslist.
++#- parameters are :
++#- rpms : array of all rpm file name to parse (mandatory)
++#- dir : directory which will contain headers (defaults to /tmp/.build_hdlist)
++#- callback : perl code to be called for each package read (defaults pack_header)
++#- clean : bool to clean cache before (default no).
++#- packing : bool to create info (default is weird)
++#
++# deprecated
++sub parse_rpms_build_headers {
++ my ($urpm, %options) = @_;
++ my ($dir, %cache, @headers);
++
++ #- check for mandatory options.
++ if (@{$options{rpms} || []} &gt; 0) {
++ #- build a working directory which will hold rpm headers.
++ $dir = $options{dir} || _get_tmp_dir();
++ $options{clean} and system($ENV{LD_LOADER} ? $ENV{LD_LOADER} : @{[]}, &quot;rm&quot;, &quot;-rf&quot;, $dir);
++ -d $dir or mkdir $dir, 0755 or die &quot;cannot create directory $dir\n&quot;;
++
++ #- examine cache if it contains any headers which will be much faster to read
++ #- than parsing rpm file directly.
++ unless ($options{clean}) {
++ my $dirh;
++ opendir $dirh, $dir;
++ while (defined (my $file = readdir $dirh)) {
++ my ($fullname, $filename) = $file =~ /(.+?-[^:\-]+-[^:\-]+\.[^:\-\.]+)(?::(\S+))?$/ or next;
++ my @stat = stat &quot;$dir/$file&quot;;
++ $cache{$filename || $fullname} = {
++ file =&gt; $file,
++ size =&gt; $stat[7],
++ 'time' =&gt; $stat[9],
++ };
++ }
++ closedir $dirh;
++ }
++
++ foreach (@{$options{rpms}}) {
++ my ($key) = m!([^/]*)\.rpm$! or next; #- get rpm filename.
++ my ($id, $filename);
++
++ if ($cache{$key} &amp;&amp; $cache{$key}{time} &gt; 0 &amp;&amp; $cache{$key}{time} &gt;= (stat $_)[9]) {
++ ($id, undef) = $urpm-&gt;parse_hdlist(&quot;$dir/$cache{$key}{file}&quot;, packing =&gt; $options{packing}, keep_all_tags =&gt; $options{keep_all_tags});
++ unless (defined $id) {
++ if ($options{dontdie}) {
++ print STDERR &quot;bad header $dir/$cache{$key}{file}\n&quot;;
++ next;
++ } else {
++ die &quot;bad header $dir/$cache{$key}{file}\n&quot;;
++ }
++ }
++
++ $options{callback} and $options{callback}-&gt;($urpm, $id, %options, (file =&gt; $_));
++
++ $filename = $cache{$key}{file};
++ } else {
++ ($id, undef) = $urpm-&gt;parse_rpm($_, keep_all_tags =&gt; $options{keep_all_tags});
++ unless (defined $id) {
++ if ($options{dontdie}) {
++ print STDERR &quot;bad rpm $_\n&quot;;
++ next;
++ } else {
++ die &quot;bad rpm $_\n&quot;;
++ }
++ }
++
++ my $pkg = $urpm-&gt;{depslist}[$id];
++
++ $filename = $pkg-&gt;fullname;
++
++ unless (-s &quot;$dir/$filename&quot;) {
++ open my $fh, &quot;&gt;$dir/$filename&quot; or die &quot;unable to open $dir/$filename for writing\n&quot;;
++ $pkg-&gt;build_header(fileno $fh);
++ close $fh;
++ }
++ -s &quot;$dir/$filename&quot; or unlink(&quot;$dir/$filename&quot;), die &quot;can create header $dir/$filename\n&quot;;
++
++ #- make smart use of memory (no need to keep header in memory now).
++ if ($options{callback}) {
++ $options{callback}-&gt;($urpm, $id, %options, (file =&gt; $_));
++ } else {
++ $pkg-&gt;pack_header;
++ }
++
++ # Olivier Thauvin &lt;<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">thauvin at aerov.jussieu.fr</A>&gt;
++ # isn't this code better, but maybe it will break some tools:
++ # $options{callback}-&gt;($urpm, $id, %options, (file =&gt; $_)) if ($options{callback});
++ # $pkg-&gt;pack_header;
++ }
++
++ #- keep track of header associated (to avoid rereading rpm filename directly
++ #- if rereading has been made neccessary).
++ push @headers, $filename;
++ }
++ }
++ @headers;
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#
++#- allow rereading of hdlist and clean.
++sub unresolved_provides_clean {
++ my ($urpm) = @_;
++ $urpm-&gt;{depslist} = [];
++ $urpm-&gt;{provides}{$_} = undef foreach keys %{$urpm-&gt;{provides} || {}};
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#
++#- read a list of headers (typically when building an hdlist when provides have
++#- been cleaned).
++#- parameters are :
++#- headers : array containing all headers filenames to parse (mandatory)
++#- dir : directory which contains headers (defaults to /tmp/.build_hdlist)
++#- callback : perl code to be called for each package read (defaults to pack_header)
++sub parse_headers {
++ my ($urpm, %options) = @_;
++ my ($dir, $start, $id);
++
++ $dir = $options{dir} || _get_tmp_dir();
++ -d $dir or die &quot;no directory $dir\n&quot;;
++
++ $start = @{$urpm-&gt;{depslist} || []};
++ foreach (@{$options{headers} || []}) {
++ #- make smart use of memory (no need to keep header in memory now).
++ ($id, undef) = $urpm-&gt;parse_hdlist(&quot;$dir/$_&quot;, packing =&gt; !$options{callback});
++ defined $id or die &quot;bad header $dir/$_\n&quot;;
++ $options{callback} and $options{callback}-&gt;($urpm, $id, %options);
++ }
++ defined $id ? ($start, $id) : @{[]};
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#- compute dependencies, result in stored in info values of urpm.
++#- operations are incremental, it is possible to read just one hdlist, compute
++#- dependencies and read another hdlist, and again.
++#- parameters are :
++#- callback : callback to relocate reference to package id.
++sub compute_deps {
++ my ($urpm, %options) = @_;
++ my %propagated_weight = (
++ basesystem =&gt; 10000,
++ msec =&gt; 20000,
++ filesystem =&gt; 50000,
++ );
++ my ($locales_weight, $step_weight, $fixed_weight) = (-5000, 10000, $propagated_weight{basesystem});
++
++ #- avoid recomputing already present infos, take care not to modify
++ #- existing entries, as the array here is used instead of values of infos.
++ my $start = @{$urpm-&gt;{deps} ||= []};
++ my $end = $#{$urpm-&gt;{depslist} || []};
++
++ #- check if something has to be done.
++ $start &gt; $end and return;
++
++ #- keep track of prereqs.
++ my %prereqs;
++
++ #- take into account in which hdlist a package has been found.
++ #- this can be done by an incremental take into account generation
++ #- of depslist.ordered part corresponding to the hdlist.
++ #- compute closed requires, do not take into account choices.
++ foreach ($start .. $end) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++
++ my %required_packages;
++ my @required_packages;
++ my %requires;
++
++ foreach ($pkg-&gt;requires) {
++ my ($n, $prereq) = /^([^\s\[]*)(\[\*\])?/;
++ $requires{$n} = $prereq &amp;&amp; 1;
++ }
++ my @requires = keys %requires;
++
++ while (my $req = shift @requires) {
++ $req =~ /^basesystem/ and next; #- never need to requires basesystem directly as always required! what a speed up!
++ my $treq = (
++ $req =~ /^\d+$/ ? [ $req ]
++ : $urpm-&gt;{provides}{$req} ? [ keys %{$urpm-&gt;{provides}{$req}} ]
++ : [ ($req !~ /NOTFOUND_/ ? &quot;NOTFOUND_&quot; : &quot;&quot;) . $req ]
++ );
++ if (@$treq &gt; 1) {
++ #- this is a choice, no closure need to be done here.
++ push @required_packages, $treq;
++ } else {
++ #- this could be nothing if the provides is a file not found.
++ #- and this has been fixed above.
++ foreach (@$treq) {
++ my $pkg_ = /^\d+$/ &amp;&amp; $urpm-&gt;{depslist}[$_];
++ exists $required_packages{$_} and $pkg_ = undef;
++ $required_packages{$_} ||= $requires{$req}; $pkg_ or next;
++ foreach ($pkg_-&gt;requires_nosense) {
++ exists $requires{$_} or push @requires, $_;
++ $requires{$_} ||= $requires{$req};
++ }
++ }
++ }
++ }
++ #- examine choice to remove those which are not mandatory.
++ foreach (@required_packages) {
++ unless (grep { exists $required_packages{$_} } @$_) {
++ $required_packages{join '|', sort { $a &lt;=&gt; $b } @$_} = undef;
++ }
++ }
++
++ #- store a short representation of requires.
++ $urpm-&gt;{requires}[$_] = join ' ', keys %required_packages;
++ foreach my $d (keys %required_packages) {
++ $required_packages{$d} or next;
++ $prereqs{$d}{$_} = undef;
++ }
++ }
++
++ #- expand choices and closure again.
++ my %ordered;
++ foreach ($start .. $end) {
++ my @requires = $_;
++ my ($dep, %requires);
++ while (defined ($dep = shift @requires)) {
++ exists $requires{$dep} || /^[^\d\|]*$/ and next;
++ foreach ($dep, split ' ', (defined $urpm-&gt;{deps}[$dep] ? $urpm-&gt;{deps}[$dep] : $urpm-&gt;{requires}[$dep])) {
++ if (/\|/) {
++ push @requires, split /\|/, $_;
++ } else {
++ /^\d+$/ and $requires{$_} = undef;
++ }
++ }
++ }
++
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ my $delta = 1 + $propagated_weight{$pkg-&gt;name};
++ foreach (keys %requires) {
++ $ordered{$_} += $delta;
++ }
++ }
++
++ #- some package should be sorted at the beginning.
++ foreach (qw(basesystem msec rpm locales filesystem setup glibc sash bash libtermcap2 termcap readline ldconfig)) {
++ foreach (keys %{$urpm-&gt;{provides}{$_} || {}}) {
++ /^\d+$/ and $ordered{$_} = $fixed_weight;
++ }
++ /locales/ and $locales_weight += $fixed_weight;
++ $fixed_weight += $step_weight;
++ }
++ foreach ($start .. $end) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++
++ $pkg-&gt;name =~ /locales-[a-zA-Z]/ and $ordered{$_} = $locales_weight;
++ }
++
++ #- compute base flag, consists of packages which are required without
++ #- choices of basesystem and are ALWAYS installed. these packages can
++ #- safely be removed from requires of others packages.
++ foreach (qw(basesystem glibc kernel)) {
++ foreach (keys %{$urpm-&gt;{provides}{$_} || {}}) {
++ foreach ($_, split ' ', (defined $urpm-&gt;{deps}[$_] ? $urpm-&gt;{deps}[$_] : $urpm-&gt;{requires}[$_])) {
++ /^\d+$/ and $urpm-&gt;{depslist}[$_] and $urpm-&gt;{depslist}[$_]-&gt;set_flag_base(1);
++ }
++ }
++ }
++
++ #- give an id to each packages, start from number of package already
++ #- registered in depslist.
++ my %remap_ids; @remap_ids{sort {
++ exists $prereqs{$b}{$a} &amp;&amp; ! exists $prereqs{$a}{$b} ? 1 :
++ $ordered{$b} &lt;=&gt; $ordered{$a} or do {
++ my ($na, $nb) = map { $urpm-&gt;{depslist}[$_]-&gt;name } ($a, $b);
++ my ($sa, $sb) = map { /^lib(.*)/ ? $1 : '' } ($na, $nb);
++ $sa &amp;&amp; $sb ? $sa cmp $sb : $sa ? -1 : $sb ? 1 : $na cmp $nb;
++ } } ($start .. $end)} = ($start .. $end);
++
++ #- now it is possible to clean ordered and prereqs.
++ %ordered = %prereqs = ();
++
++ #- recompute requires to use packages id, drop any base packages or
++ #- reference of a package to itself.
++ my @depslist;
++ foreach ($start .. $end) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++
++ #- set new id.
++ $pkg-&gt;set_id($remap_ids{$_});
++
++ my ($id, $base, %requires_id, %not_founds);
++ foreach (split ' ', $urpm-&gt;{requires}[$_]) {
++ if (/\|/) {
++ #- all choices are grouped together at the end of requires,
++ #- this allow computation of dropable choices.
++ my ($to_drop, @choices_base_id, @choices_id);
++ foreach (split /\|/, $_) {
++ my ($id, $base) = (exists($remap_ids{$_}) ? $remap_ids{$_} : $_, $urpm-&gt;{depslist}[$_]-&gt;flag_base);
++ $base and push @choices_base_id, $id;
++ $base &amp;&amp;= ! $pkg-&gt;flag_base;
++ $to_drop ||= $id == $pkg-&gt;id || exists $requires_id{$id} || $base;
++ push @choices_id, $id;
++ }
++
++ #- package can safely be dropped as it will be selected in requires directly.
++ $to_drop and next;
++
++ #- if a base package is in a list, keep it instead of the choice.
++ if (@choices_base_id) {
++ @choices_id = @choices_base_id;
++ $base = 1;
++ }
++ if (@choices_id == 1) {
++ $id = $choices_id[0];
++ } else {
++ my $choices_key = join '|', sort { $a &lt;=&gt; $b } @choices_id;
++ $requires_id{$choices_key} = undef;
++ next;
++ }
++ } elsif (/^\d+$/) {
++ ($id, $base) = (exists($remap_ids{$_}) ? $remap_ids{$_} : $_, $urpm-&gt;{depslist}[$_]-&gt;flag_base);
++ } else {
++ $not_founds{$_} = undef;
++ next;
++ }
++
++ #- select individual package from choices or defined package.
++ $base &amp;&amp;= ! $pkg-&gt;flag_base;
++ $base || $id == $pkg-&gt;id or $requires_id{$id} = undef;
++ }
++ #- be smart with memory usage.
++ delete $urpm-&gt;{requires}[$_];
++ $urpm-&gt;{deps}[$remap_ids{$_}] = join ' ', ((sort { ($a =~ /^(\d+)/)[0] &lt;=&gt; ($b =~ /^(\d+)/)[0] } keys %requires_id),
++ keys %not_founds);
++ $depslist[$remap_ids{$_}-$start] = $pkg;
++ }
++
++ #- remap all provides ids for new package position and update depslist.
++ delete $urpm-&gt;{requires};
++ @{$urpm-&gt;{depslist}}[$start .. $end] = @depslist;
++ foreach my $h (values %{$urpm-&gt;{provides}}) {
++ my %provided;
++ foreach (keys %{$h || {}}) {
++ $provided{exists($remap_ids{$_}) ? $remap_ids{$_} : $_} = delete $h-&gt;{$_};
++ }
++ $h = \%provided;
++ }
++ $options{callback} and $options{callback}-&gt;($urpm, \%remap_ids, %options);
++
++ ($start, $end);
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#
++#- build an hdlist from existing depslist, from start to end inclusive.
++#- parameters are :
++#- hdlist : hdlist file to use.
++#- dir : directory which contains headers (defaults to /tmp/.build_hdlist)
++#- start : index of first package (defaults to first index of depslist).
++#- end : index of last package (defaults to last index of depslist).
++#- idlist : id list of rpm to compute (defaults is start .. end)
++#- ratio : compression ratio (default 4).
++#- split : split ratio (default 400kb, see MDV::Packdrakeng).
++sub build_hdlist {
++ my ($urpm, %options) = @_;
++ my ($dir, $ratio, @idlist);
++
++ $dir = $options{dir} || _get_tmp_dir();
++ -d $dir or die &quot;no directory $dir\n&quot;;
++
++ @idlist = $urpm-&gt;build_listid($options{start}, $options{end}, $options{idlist});
++
++ #- compression ratio are not very high, sample for cooker
++ #- gives the following (main only and cache fed up):
++ #- ratio compression_time size
++ #- 9 21.5 sec 8.10Mb -&gt; good for installation CD
++ #- 6 10.7 sec 8.15Mb
++ #- 5 9.5 sec 8.20Mb
++ #- 4 8.6 sec 8.30Mb -&gt; good for urpmi
++ #- 3 7.6 sec 8.60Mb
++ $ratio = $options{ratio} || 4;
++
++ require MDV::Packdrakeng;
++ my $pack = MDV::Packdrakeng-&gt;new(
++ archive =&gt; $options{hdlist},
++ compress =&gt; &quot;gzip&quot;,
++ uncompress =&gt; &quot;gzip -d&quot;,
++ block_size =&gt; $options{split},
++ comp_level =&gt; $ratio,
++ ) or die &quot;Can't create archive&quot;;
++ foreach my $pkg (@{$urpm-&gt;{depslist}}[@idlist]) {
++ my $filename = $pkg-&gt;fullname;
++ -s &quot;$dir/$filename&quot; or die &quot;bad header $dir/$filename\n&quot;;
++ $pack-&gt;add($dir, $filename);
++ }
++}
++
++#- build synthesis file.
++#- used by genhdlist2 and mkcd
++#-
++#- parameters are :
++#- synthesis : synthesis file to create (mandatory if fd not given).
++#- fd : file descriptor (mandatory if synthesis not given).
++#- start : index of first package (defaults to first index of depslist).
++#- end : index of last package (defaults to last index of depslist).
++#- idlist : id list of rpm to compute (defaults is start .. end)
++#- ratio : compression ratio (default 9).
++#- filter : program to filter through (default is 'gzip -$ratio').
++#- returns true on success
++sub build_synthesis {
++ my ($urpm, %options) = @_;
++ my ($ratio, $filter, @idlist);
++
++ @idlist = $urpm-&gt;build_listid($options{start}, $options{end}, $options{idlist});
++
++ $ratio = $options{ratio} || 9;
++ $filter = $options{filter} ? $options{filter} : &quot;gzip -$ratio&quot;;
++ $options{synthesis} || defined $options{fd} or die &quot;invalid parameters given&quot;;
++
++ #- first pass: traverse provides to find files provided.
++ my %provided_files;
++ foreach (keys %{$urpm-&gt;{provides}}) {
++ m!^/! or next;
++ foreach my $id (keys %{$urpm-&gt;{provides}{$_} || {}}) {
++ push @{$provided_files{$id} ||= []}, $_;
++ }
++ }
++
++
++ #- second pass: write each info including files provided.
++ $options{synthesis} and open my $fh, &quot;| &quot; . ($ENV{LD_LOADER} || '') . &quot; $filter &gt;'$options{synthesis}'&quot;;
++ foreach (@idlist) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ my %files;
++
++ if ($provided_files{$_}) {
++ @files{@{$provided_files{$_}}} = undef;
++ delete @files{$pkg-&gt;provides_nosense};
++ }
++
++ $pkg-&gt;build_info($options{synthesis} ? fileno $fh : $options{fd}, join('@', keys %files));
++ }
++ close $fh; # returns true on success
++}
++
++# DEPRECATED. ONLY USED BY MKCD
++#- write depslist.ordered file according to info in params.
++#- parameters are :
++#- depslist : depslist.ordered file to create.
++#- provides : provides file to create.
++#- compss : compss file to create.
++sub build_base_files {
++ my ($urpm, %options) = @_;
++
++ if ($options{depslist}) {
++ open my $fh, &quot;&gt;&quot;, $options{depslist} or die &quot;Can't write to $options{depslist}: $!\n&quot;;
++ foreach (0 .. $#{$urpm-&gt;{depslist}}) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++
++ printf $fh (&quot;%s-%s-%s.%s%s %s %s\n&quot;, $pkg-&gt;fullname,
++ ($pkg-&gt;epoch ? ':' . $pkg-&gt;epoch : ''), $pkg-&gt;size || 0, $urpm-&gt;{deps}[$_]);
++ }
++ close $fh;
++ }
++
++ if ($options{provides}) {
++ open my $fh, &quot;&gt;&quot;, $options{provides} or die &quot;Can't write to $options{provides}: $!\n&quot;;
++ while (my ($k, $v) = each %{$urpm-&gt;{provides}}) {
++ printf $fh &quot;%s\n&quot;, join '@', $k, map { scalar $urpm-&gt;{depslist}[$_]-&gt;fullname } keys %{$v || {}};
++ }
++ close $fh;
++ }
++
++ if ($options{compss}) {
++ my %p;
++
++ open my $fh, &quot;&gt;&quot;, $options{compss} or die &quot;Can't write to $options{compss}: $!\n&quot;;
++ foreach (@{$urpm-&gt;{depslist}}) {
++ $_-&gt;group or next;
++ push @{$p{$_-&gt;group} ||= []}, $_-&gt;name;
++ }
++ foreach (sort keys %p) {
++ print $fh $_, &quot;\n&quot;;
++ foreach (@{$p{$_}}) {
++ print $fh &quot;\t&quot;, $_, &quot;\n&quot;;
++ }
++ print $fh &quot;\n&quot;;
++ }
++ close $fh;
++ }
++
++ 1;
++}
++
++our $MAKEDELTARPM = '/usr/bin/makedeltarpm';
++
++#- make_delta_rpm($old_rpm_file, $new_rpm_file)
++# Creates a delta rpm in the current directory.
++
++# DEPRECATED. UNUSED
++sub make_delta_rpm ($$) {
++ @_ == 2 or return 0;
++ -e $_[0] &amp;&amp; -e $_[1] &amp;&amp; -x $MAKEDELTARPM or return 0;
++ my @id;
++ my $urpm = new URPM;
++ foreach my $i (0, 1) {
++ ($id[$i]) = $urpm-&gt;parse_rpm($_[$i]);
++ defined $id[$i] or return 0;
++ }
++ my $oldpkg = $urpm-&gt;{depslist}[$id[0]];
++ my $newpkg = $urpm-&gt;{depslist}[$id[1]];
++ $oldpkg-&gt;arch eq $newpkg-&gt;arch or return 0;
++ #- construct filename of the deltarpm
++ my $patchrpm = $oldpkg-&gt;name . '-' . $oldpkg-&gt;version . '-' . $oldpkg-&gt;release . '_' . $newpkg-&gt;version . '-' . $newpkg-&gt;release . '.' . $oldpkg-&gt;arch . '.delta.rpm';
++ !system($MAKEDELTARPM, @_, $patchrpm);
++}
++
++1;
+
+Added: rpm/perl-URPM/trunk/URPM/Query.pm
+===================================================================
+--- rpm/perl-URPM/trunk/URPM/Query.pm (rev 0)
++++ rpm/perl-URPM/trunk/URPM/Query.pm 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,40 @@
++package URPM;
++
++use strict;
++use warnings;
++
++# Olivier Thauvin &lt;<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">thauvin at aerov.jussieu.fr</A>&gt;
++# This package extend URPM functions to permit
++# URPM low level query on rpm header
++# $Id: Query.pm 270395 2010-07-30 00:55:59Z nanardon $
++
++# tag2id
++# INPUT array of rpm tag name
++# Return an array of ID tag
++
++sub tag2id {
++ my @l = @_;
++ my %taglist = URPM::list_rpm_tag();
++ map { $taglist{uc($_)} || undef } @l;
++}
++
++sub query_pkg {
++ my (undef, $pkg, $query) = @_;
++ my @tags = map {
++ [ $pkg-&gt;get_tag(tag2id($_)) ]
++ } $query =~ m/\%\{([^{}]*)\}*/g;
++
++ $query =~ s/\%\{[^{}]*\}/%s/g;
++ $query =~ s/\\n/\n/g;
++ $query =~ s/\\t/\t/g;
++ my ($max, @res) = 0;
++
++ foreach (@tags) { $max &lt; $#{$_} and $max = $#{$_} };
++
++ foreach my $i (0 .. $max) {
++ push(@res, sprintf($query, map { ${$_}[ $#{$_} &lt; $i ? $#{$_} : $i ] } @tags));
++ }
++ @res
++}
++
++1;
+
+Added: rpm/perl-URPM/trunk/URPM/Resolve.pm
+===================================================================
+--- rpm/perl-URPM/trunk/URPM/Resolve.pm (rev 0)
++++ rpm/perl-URPM/trunk/URPM/Resolve.pm 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,2003 @@
++package URPM;
++#package URPM::Resolve;
++#use URPM;
++
++# $Id: Resolve.pm 270395 2010-07-30 00:55:59Z nanardon $
++
++use strict;
++use warnings;
++use Config;
++
++
++#- a few functions from MDK::Common copied here:
++sub listlength { scalar @_ }
++sub min { my $n = shift; $_ &lt; $n and $n = $_ foreach @_; $n }
++sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ }
++sub find(&amp;@) {
++ my $f = shift;
++ $f-&gt;($_) and return $_ foreach @_;
++ undef;
++}
++
++#- property2name* functions below parse things like &quot;mageia-release[&gt;= 1]&quot;
++#- which is the format returned by URPM.xs for -&gt;requires, -&gt;provides, -&gt;conflicts...
++sub property2name {
++ $_[0] =~ /^([^\s\[]*)/ &amp;&amp; $1;
++}
++sub property2name_range {
++ $_[0] =~ /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/;
++}
++sub property2name_op_version {
++ $_[0] =~ /^([^\s\[]*)(?:\[\*\])?\s*\[?([^\s\]]*)\s*([^\s\]]*)/;
++}
++
++#- wrappers around $state (cf &quot;The $state object&quot; in &quot;perldoc URPM&quot;)
++sub packages_to_remove {
++ my ($state) = @_;
++ grep {
++ $state-&gt;{rejected}{$_}{removed} &amp;&amp; !$state-&gt;{rejected}{$_}{obsoleted};
++ } keys %{$state-&gt;{rejected} || {}};
++}
++sub removed_or_obsoleted_packages {
++ my ($state) = @_;
++ grep {
++ $state-&gt;{rejected}{$_}{removed} || $state-&gt;{rejected}{$_}{obsoleted};
++ } keys %{$state-&gt;{rejected} || {}};
++}
++
++#- Find candidates packages from a require string (or id).
++#- Takes care of choices using the '|' separator.
++#- (nb: see also find_required_package())
++#-
++#- side-effects: none
++sub find_candidate_packages_ {
++ my ($urpm, $id_prop, $o_rejected) = @_;
++ my @packages;
++
++ foreach (split /\|/, $id_prop) {
++ if (/^\d+$/) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ $pkg-&gt;flag_skip and next;
++ $pkg-&gt;arch eq 'src' || $pkg-&gt;is_arch_compat or next;
++ $o_rejected &amp;&amp; exists $o_rejected-&gt;{$pkg-&gt;fullname} and next;
++ push @packages, $pkg;
++ } elsif (my $name = property2name($_)) {
++ my $property = $_;
++ foreach (keys %{$urpm-&gt;{provides}{$name} || {}}) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ $pkg-&gt;flag_skip and next;
++ $pkg-&gt;is_arch_compat or next;
++ $o_rejected &amp;&amp; exists $o_rejected-&gt;{$pkg-&gt;fullname} and next;
++ #- check if at least one provide of the package overlap the property.
++ !$urpm-&gt;{provides}{$name}{$_} || $pkg-&gt;provides_overlap($property, 1)
++ and push @packages, $pkg;
++ }
++ }
++ }
++ @packages;
++}
++
++#- deprecated, use find_candidate_packages_() directly
++#-
++#- side-effects: none
++sub find_candidate_packages {
++ my ($urpm, $id_prop, $o_rejected) = @_;
++
++ my %packages;
++ foreach (find_candidate_packages_($urpm, $id_prop, $o_rejected)) {
++ push @{$packages{$_-&gt;name}}, $_;
++ }
++ \%packages;
++}
++
++#- returns the &quot;arch&quot; of package $n in rpm db
++sub get_installed_arch {
++ my ($db, $n) = @_;
++ my $arch;
++ $db-&gt;traverse_tag('name', [ $n ], sub { $arch = $_[0]-&gt;arch });
++ $arch;
++}
++
++#- is &quot;strict-arch&quot; wanted? (cf &quot;man urpmi&quot;)
++#- since it's slower we only force it on bi-arch
++sub strict_arch {
++ my ($urpm) = @_;
++ defined $urpm-&gt;{options}{'strict-arch'} ? $urpm-&gt;{options}{'strict-arch'} : $Config{archname} =~ /x86_64|sparc64|ppc64/;
++}
++my %installed_arch;
++
++#- checks wether $pkg could be installed under strict-arch policy
++#- (ie check wether $pkg-&gt;name with different arch is not installed)
++#-
++#- side-effects: none (but uses a cache)
++sub strict_arch_check_installed {
++ my ($db, $pkg) = @_;
++ if ($pkg-&gt;arch ne 'src' &amp;&amp; $pkg-&gt;arch ne 'noarch') {
++ my $n = $pkg-&gt;name;
++ defined $installed_arch{$n} or $installed_arch{$n} = get_installed_arch($db, $n);
++ if ($installed_arch{$n} &amp;&amp; $installed_arch{$n} ne 'noarch') {
++ $pkg-&gt;arch eq $installed_arch{$n} or return;
++ }
++ }
++ 1;
++}
++
++#- check wether $installed_pkg and $pkg have same arch
++#- (except for src/noarch of course)
++#-
++#- side-effects: none
++sub strict_arch_check {
++ my ($installed_pkg, $pkg) = @_;
++ if ($pkg-&gt;arch ne 'src' &amp;&amp; $pkg-&gt;arch ne 'noarch') {
++ if ($installed_pkg-&gt;arch ne 'noarch') {
++ $pkg-&gt;arch eq $installed_pkg-&gt;arch or return;
++ }
++ }
++ 1;
++}
++
++#- is $pkg-&gt;name installed?
++#-
++#- side-effects: none
++sub is_package_installed {
++ my ($db, $pkg) = @_;
++
++ my $found;
++ $db-&gt;traverse_tag('name', [ $pkg-&gt;name ], sub {
++ my ($p) = @_;
++ $found ||= $p-&gt;fullname eq $pkg-&gt;fullname;
++ });
++ $found;
++}
++
++sub _is_selected_or_installed {
++ my ($urpm, $db, $name) = @_;
++
++ (grep { $_-&gt;flag_available } $urpm-&gt;packages_providing($name)) &gt; 0 ||
++ $db-&gt;traverse_tag('name', [ $name ], undef) &gt; 0;
++}
++
++#- finds $pkg &quot;provides&quot; that matches $provide_name, and returns the version provided
++#- eg: $pkg provides &quot;a = 3&quot;, $provide_name is &quot;a &gt; 1&quot;, returns &quot;3&quot;
++sub provided_version_that_overlaps {
++ my ($pkg, $provide_name) = @_;
++
++ my $version;
++ foreach my $property ($pkg-&gt;provides) {
++ my ($n, undef, $v) = property2name_op_version($property) or next;
++ $n eq $provide_name or next;
++
++ if ($version) {
++ $version = $v if URPM::rpmvercmp($v, $version) &gt; 0;
++ } else {
++ $version = $v;
++ }
++ }
++ $version;
++}
++
++#- deprecated function, use find_required_package()
++sub find_chosen_packages { &amp;find_required_package }
++
++#- find the package (or packages) to install matching $id_prop
++#- returns (list ref of matches, list ref of preferred matches)
++#- (see also find_candidate_packages_())
++#-
++#- side-effects: flag_install, flag_upgrade (and strict_arch_check_installed cache)
++sub find_required_package {
++ my ($urpm, $db, $state, $id_prop) = @_;
++ my (%packages, %provided_version);
++ my $strict_arch = strict_arch($urpm);
++
++ my $may_add_to_packages = sub {
++ my ($pkg) = @_;
++
++ if (my $p = $packages{$pkg-&gt;name}) {
++ $pkg-&gt;flag_requested &gt; $p-&gt;flag_requested ||
++ $pkg-&gt;flag_requested == $p-&gt;flag_requested &amp;&amp; $pkg-&gt;compare_pkg($p) &gt; 0 and $packages{$pkg-&gt;name} = $pkg;
++ } else {
++ $packages{$pkg-&gt;name} = $pkg;
++ }
++ };
++
++ #- search for possible packages, try to be as fast as possible, backtrack can be longer.
++ foreach (split /\|/, $id_prop) {
++ if (/^\d+$/) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ $pkg-&gt;arch eq 'src' || $pkg-&gt;is_arch_compat or next;
++ $pkg-&gt;flag_skip || $state-&gt;{rejected}{$pkg-&gt;fullname} and next;
++ #- determine if this package is better than a possibly previously chosen package.
++ $pkg-&gt;flag_selected || exists $state-&gt;{selected}{$pkg-&gt;id} and return [$pkg];
++ !$strict_arch || strict_arch_check_installed($db, $pkg) or next;
++ $may_add_to_packages-&gt;($pkg);
++ } elsif (my $name = property2name($_)) {
++ my $property = $_;
++ foreach (keys %{$urpm-&gt;{provides}{$name} || {}}) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ $pkg-&gt;is_arch_compat or next;
++ $pkg-&gt;flag_skip || $state-&gt;{rejected}{$pkg-&gt;fullname} and next;
++ #- check if at least one provide of the package overlaps the property
++ if (!$urpm-&gt;{provides}{$name}{$_} || $pkg-&gt;provides_overlap($property)) {
++ #- determine if this package is better than a possibly previously chosen package.
++ $pkg-&gt;flag_selected || exists $state-&gt;{selected}{$pkg-&gt;id} and return [$pkg];
++ !$strict_arch || strict_arch_check_installed($db, $pkg) or next;
++ $provided_version{$pkg} = provided_version_that_overlaps($pkg, $name);
++ $may_add_to_packages-&gt;($pkg);
++ }
++ }
++ }
++ }
++ my @packages = values %packages;
++
++ if (@packages &gt; 1) {
++ #- packages should be preferred if one of their provides is referenced
++ #- in the &quot;requested&quot; hash, or if the package itself is requested (or
++ #- required).
++ #- If there is no preference, choose the first one by default (higher
++ #- probability of being chosen) and ask the user.
++ #- Packages with more compatibles architectures are always preferred.
++ #- Puts the results in @chosen. Other are left unordered.
++ foreach my $pkg (@packages) {
++ _set_flag_installed_and_upgrade_if_no_newer($db, $pkg);
++ }
++
++ if (my @kernel_source = _find_required_package__kernel_source($urpm, $db, \@packages)) {
++ $urpm-&gt;{debug_URPM}(&quot;packageCallbackChoices: kernel source chosen &quot; . join(&quot;,&quot;, map { $_-&gt;name } @kernel_source) . &quot; in &quot; . join(&quot;,&quot;, map { $_-&gt;name } @packages)) if $urpm-&gt;{debug_URPM};
++ return \@kernel_source, \@kernel_source;
++ }
++ if (my @kmod = _find_required_package__kmod($urpm, $db, \@packages)) {
++ $urpm-&gt;{debug_URPM}(&quot;packageCallbackChoices: kmod packages &quot; . join(&quot;,&quot;, map { $_-&gt;name } @kmod) . &quot; in &quot; . join(&quot;,&quot;, map { $_-&gt;name } @packages)) if $urpm-&gt;{debug_URPM};
++ return \@kmod, \@kmod;
++ }
++
++ _find_required_package__sort($urpm, $db, \@packages, \%provided_version);
++ } else {
++ \@packages;
++ }
++}
++
++# nb: _set_flag_installed_and_upgrade_if_no_newer must be done on $packages
++sub _find_required_package__sort {
++ my ($urpm, $db, $packages, $provided_version) = @_;
++
++ my ($best, @other) = sort {
++ $a-&gt;[1] &lt;=&gt; $b-&gt;[1] #- we want the lowest (ie preferred arch)
++ || $b-&gt;[2] &lt;=&gt; $a-&gt;[2]; #- and the higher score
++ } map {
++ my $score = 0;
++ $score += 2 if $_-&gt;flag_requested;
++ $score += $_-&gt;flag_upgrade ? 1 : -1 if $_-&gt;flag_installed;
++ [ $_, $_-&gt;is_arch_compat, $score ];
++ } @$packages;
++
++ my @chosen_with_score = ($best, grep { $_-&gt;[1] == $best-&gt;[1] &amp;&amp; $_-&gt;[2] == $best-&gt;[2] } @other);
++ my @chosen = map { $_-&gt;[0] } @chosen_with_score;
++
++ #- return immediately if there is only one chosen package
++ if (@chosen == 1) { return \@chosen }
++
++ #- if several packages were selected to match a requested installation,
++ #- and if --more-choices wasn't given, trim the choices to the first one.
++ if (!$urpm-&gt;{options}{morechoices} &amp;&amp; $chosen_with_score[0][2] == 3) {
++ return [ $chosen[0] ];
++ }
++
++ if ($urpm-&gt;{media}) {
++ @chosen_with_score = sort {
++ $a-&gt;[2] != $b-&gt;[2] ?
++ $a-&gt;[0]-&gt;id &lt;=&gt; $b-&gt;[0]-&gt;id :
++ $b-&gt;[1] &lt;=&gt; $a-&gt;[1] || $b-&gt;[0]-&gt;compare_pkg($a-&gt;[0]);
++ } map { [ $_, _score_for_locales($urpm, $db, $_), pkg2media($urpm-&gt;{media}, $_) ] } @chosen;
++ } else {
++ # obsolete code which should not happen, kept just in case
++ $urpm-&gt;{debug_URPM}(&quot;can't sort choices by media&quot;) if $urpm-&gt;{debug_URPM};
++ @chosen_with_score = sort {
++ $b-&gt;[1] &lt;=&gt; $a-&gt;[1] ||
++ $b-&gt;[0]-&gt;compare_pkg($a-&gt;[0]) || $a-&gt;[0]-&gt;id &lt;=&gt; $b-&gt;[0]-&gt;id;
++ } map { [ $_, _score_for_locales($urpm, $db, $_) ] } @chosen;
++ }
++ if (!$urpm-&gt;{options}{morechoices}) {
++ if (my @valid_locales = grep { $_-&gt;[1] } @chosen_with_score) {
++ #- get rid of invalid locales
++ @chosen_with_score = @valid_locales;
++ }
++ }
++ # propose to select all packages for installed locales
++ my @prefered = grep { $_-&gt;[1] == 3 } @chosen_with_score;
++
++ @chosen = map { $_-&gt;[0] } @chosen_with_score;
++ if (%$provided_version) {
++ # highest provided version first
++ # (nb: this sort overrules the sort on media (cf -&gt;id above))
++ @chosen = sort { URPM::rpmvercmp($provided_version-&gt;{$b} || 0, $provided_version-&gt;{$a} || 0) } @chosen;
++ }
++ \@chosen, [ map { $_-&gt;[0] } @prefered ];
++}
++
++#- prefer the pkgs corresponding to installed/selected kernels
++sub _find_required_package__kernel_source {
++ my ($urpm, $db, $choices) = @_;
++
++ $choices-&gt;[0]-&gt;name =~ /^kernel-(.*source-|.*-devel-)/ or return;
++
++ grep {
++ if ($_-&gt;name =~ /^kernel-.*source-stripped-(.*)/) {
++ my $version = quotemeta($1);
++ find {
++ $_-&gt;name =~ /-$version$/ &amp;&amp; ($_-&gt;flag_installed || $_-&gt;flag_selected);
++ } $urpm-&gt;packages_providing('kernel');
++ } elsif ($_-&gt;name =~ /(kernel-.*)-devel-(.*)/) {
++ my $kernel = &quot;$1-$2&quot;;
++ _is_selected_or_installed($urpm, $db, $kernel);
++ } elsif ($_-&gt;name =~ /^kernel-.*source-/) {
++ #- hopefully we don't have a media with kernel-source but not kernel-source-stripped nor kernel-.*-devel
++ 0;
++ } else {
++ $urpm-&gt;{debug_URPM}(&quot;unknown kernel-source package &quot; . $_-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ 0;
++ }
++ } @$choices;
++}
++
++#- prefer the pkgs corresponding to installed/selected kernels
++sub _find_required_package__kmod {
++ my ($urpm, $db, $choices) = @_;
++
++ $choices-&gt;[0]-&gt;name =~ /^dkms-|-kernel-2\./ or return;
++
++ grep {
++ if (my ($_name, $version, $flavor, $release) = $_-&gt;name =~ /(.*)-kernel-(2\..*)-(.*)-(.*)/) {
++ my $kernel = &quot;kernel-$flavor-$version-$release&quot;;
++ _is_selected_or_installed($urpm, $db, $kernel);
++ } elsif ($_-&gt;name =~ /^dkms-/) {
++ 0; # we prefer precompiled dkms
++ } else {
++ $urpm-&gt;{debug_URPM}(&quot;unknown kmod package &quot; . $_-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ 0;
++ }
++ } @$choices;
++}
++
++#- Packages that require locales-xxx when the corresponding locales are
++#- already installed should be preferred over packages that require locales
++#- which are not installed.
++#-
++#- eg: locales-fr &amp; locales-de are installed,
++#- prefer firefox-fr &amp; firefox-de which respectively require locales-fr &amp; locales-de
++sub _score_for_locales {
++ my ($urpm, $db, $pkg) = @_;
++
++ my @r = $pkg-&gt;requires_nosense;
++
++ if (my ($specific_locales) = grep { /locales-(?!en)/ } @r) {
++ if (_is_selected_or_installed($urpm, $db, $specific_locales)) {
++ 3; # good locale
++ } else {
++ 0; # bad locale
++ }
++ } elsif (grep { /locales-en/ } @r) {
++ 2; #
++ } else {
++ 1;
++ }
++}
++
++#- side-effects: $properties, $choices
++#- + those of backtrack_selected ($state-&gt;{backtrack}, $state-&gt;{rejected}, $state-&gt;{selected}, $state-&gt;{whatrequires}, flag_requested, flag_required)
++sub _choose_required {
++ my ($urpm, $db, $state, $dep, $properties, $choices, $diff_provides, %options) = @_;
++
++ #- take the best choice possible.
++ my ($chosen, $prefered) = find_required_package($urpm, $db, $state, $dep-&gt;{required});
++
++ #- If no choice is found, this means that nothing can be possibly selected
++ #- according to $dep, so we need to retry the selection, allowing all
++ #- packages that conflict or anything similar to see which strategy can be
++ #- tried. Backtracking is used to avoid trying multiple times the same
++ #- packages. If multiple packages are possible and properties is not
++ #- empty, postpone the choice for a later time as one of the packages
++ #- may be selected for another reason. Otherwise simply ask the user which
++ #- one to choose; else take the first one available.
++ if (!@$chosen) {
++ $urpm-&gt;{debug_URPM}(&quot;no packages match &quot; . _dep_to_name($urpm, $dep) . &quot; (it is either in skip.list or already rejected)&quot;) if $urpm-&gt;{debug_URPM};
++ unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, $diff_provides, %options);
++ return; #- backtrack code choose to continue with same package or completely new strategy.
++ } elsif (@$chosen &gt; 1) {
++ if (@$properties) {
++ unshift @$choices, $dep;
++ return;
++ } elsif ($options{callback_choices}) {
++ my @l = grep { ref $_ } $options{callback_choices}-&gt;($urpm, $db, $state, $chosen, _dep_to_name($urpm, $dep), $prefered);
++ $urpm-&gt;{debug_URPM}(&quot;replacing &quot; . _dep_to_name($urpm, $dep) . &quot; with &quot; .
++ join(' ', map { $_-&gt;name } @l)) if $urpm-&gt;{debug_URPM};
++ unshift @$properties, map {
++ +{
++ required =&gt; $_-&gt;id,
++ _choices =&gt; $dep-&gt;{required},
++ exists $dep-&gt;{from} ? (from =&gt; $dep-&gt;{from}) : @{[]},
++ exists $dep-&gt;{requested} ? (requested =&gt; $dep-&gt;{requested}) : @{[]},
++ };
++ } @l;
++ return; #- always redo according to choices.
++ }
++ }
++
++
++ #- now do the real work, select the package.
++ my $pkg = shift @$chosen;
++ if ($urpm-&gt;{debug_URPM} &amp;&amp; $pkg-&gt;name ne _dep_to_name($urpm, $dep)) {
++ $urpm-&gt;{debug_URPM}(&quot;chosen &quot; . $pkg-&gt;fullname . &quot; for &quot; . _dep_to_name($urpm, $dep));
++ @$chosen and $urpm-&gt;{debug_URPM}(&quot; (it could also have chosen &quot; . join(' ', map { scalar $_-&gt;fullname } @$chosen));
++ }
++
++ $pkg;
++}
++
++sub pkg2media {
++ my ($mediums, $p) = @_;
++ my $id = $p-&gt;id;
++ #- || 0 to avoid undef, but is it normal to have undef ?
++ find { $id &gt;= ($_-&gt;{start} || 0) &amp;&amp; $id &lt;= ($_-&gt;{end} || 0) } @$mediums;
++}
++
++sub whatrequires {
++ my ($urpm, $state, $property_name) = @_;
++
++ map { $urpm-&gt;{depslist}[$_] } whatrequires_id($state, $property_name);
++}
++sub whatrequires_id {
++ my ($state, $property_name) = @_;
++
++ keys %{$state-&gt;{whatrequires}{$property_name} || {}};
++}
++
++#- return unresolved requires of a package (a new one or an existing one).
++#-
++#- side-effects: none (but uses a $state-&gt;{cached_installed})
++sub unsatisfied_requires {
++ my ($urpm, $db, $state, $pkg, %options) = @_;
++ my %unsatisfied;
++
++ #- all requires should be satisfied according to selected packages or installed packages,
++ #- or the package itself.
++ REQUIRES: foreach my $prop ($pkg-&gt;requires) {
++ my ($n, $s) = property2name_range($prop) or next;
++
++ if (defined $options{name} &amp;&amp; $n ne $options{name}) {
++ #- allow filtering on a given name (to speed up some search).
++ } elsif (exists $unsatisfied{$prop}) {
++ #- avoid recomputing the same all the time.
++ } else {
++ #- check for installed packages in the installed cache.
++ foreach (keys %{$state-&gt;{cached_installed}{$n} || {}}) {
++ exists $state-&gt;{rejected}{$_} and next;
++ next REQUIRES;
++ }
++
++ #- check on the selected package if a provide is satisfying the resolution (need to do the ops).
++ foreach (grep { exists $state-&gt;{selected}{$_} } keys %{$urpm-&gt;{provides}{$n} || {}}) {
++ my $p = $urpm-&gt;{depslist}[$_];
++ !$urpm-&gt;{provides}{$n}{$_} || $p-&gt;provides_overlap($prop, 1) and next REQUIRES;
++ }
++
++ #- check if the package itself provides what is necessary.
++ $pkg-&gt;provides_overlap($prop) and next REQUIRES;
++
++ #- check on installed system if a package which is not obsoleted is satisfying the require.
++ my $satisfied = 0;
++ if ($n =~ m!^/!) {
++ $db-&gt;traverse_tag('path', [ $n ], sub {
++ my ($p) = @_;
++ exists $state-&gt;{rejected}{$p-&gt;fullname} and return;
++ $state-&gt;{cached_installed}{$n}{$p-&gt;fullname} = undef;
++ ++$satisfied;
++ });
++ } else {
++ $db-&gt;traverse_tag('whatprovides', [ $n ], sub {
++ my ($p) = @_;
++ exists $state-&gt;{rejected}{$p-&gt;fullname} and return;
++ foreach ($p-&gt;provides) {
++ if (my ($pn, $ps) = property2name_range($_)) {
++ $ps or $state-&gt;{cached_installed}{$pn}{$p-&gt;fullname} = undef;
++ $pn eq $n or next;
++ URPM::ranges_overlap($ps, $s, 1) and ++$satisfied;
++ }
++ }
++ });
++ }
++ #- if nothing can be done, the require should be resolved.
++ $satisfied or $unsatisfied{$prop} = undef;
++ }
++ }
++
++ keys %unsatisfied;
++}
++
++#- this function is &quot;suggests vs requires&quot; safe:
++#- 'whatrequires' will give both requires &amp; suggests, but unsatisfied_requires
++#- will check $p-&gt;requires and so filter out suggests
++
++#- side-effects: only those done by $do
++sub with_db_unsatisfied_requires {
++ my ($urpm, $db, $state, $name, $do) = @_;
++
++ $db-&gt;traverse_tag('whatrequires', [ $name ], sub {
++ my ($p) = @_;
++ if (my @l = unsatisfied_requires($urpm, $db, $state, $p, name =&gt; $name)) {
++ $urpm-&gt;{debug_URPM}(&quot;installed &quot; . $p-&gt;fullname . &quot; is conflicting because of unsatisfied @l&quot;) if $urpm-&gt;{debug_URPM};
++ $do-&gt;($p, @l);
++ }
++ });
++}
++
++#- side-effects: only those done by $do
++sub with_state_unsatisfied_requires {
++ my ($urpm, $db, $state, $name, $do) = @_;
++
++ foreach (whatrequires_id($state, $name)) {
++ $state-&gt;{selected}{$_} or next;
++ my $p = $urpm-&gt;{depslist}[$_];
++ if (my @l = unsatisfied_requires($urpm, $db, $state, $p, name =&gt; $name)) {
++ $urpm-&gt;{debug_URPM}(&quot;selected &quot; . $p-&gt;fullname . &quot; is conflicting because of unsatisfied @l&quot;) if $urpm-&gt;{debug_URPM};
++ $do-&gt;($p, @l);
++ }
++ }
++}
++
++sub with_any_unsatisfied_requires {
++ my ($urpm, $db, $state, $name, $do) = @_;
++ with_db_unsatisfied_requires($urpm, $db, $state, $name, sub { my ($p, @l) = @_; $do-&gt;($p, 0, @l)});
++ with_state_unsatisfied_requires($urpm, $db, $state, $name, sub { my ($p, @l) = @_; $do-&gt;($p, 1, @l)});
++}
++
++
++# used when a require is not available
++#
++#- side-effects: $state-&gt;{backtrack}, $state-&gt;{selected}
++#- + those of disable_selected_and_unrequested_dependencies ($state-&gt;{whatrequires}, flag_requested, flag_required)
++#- + those of _set_rejected_from ($state-&gt;{rejected})
++#- + those of set_rejected_and_compute_diff_provides ($state-&gt;{rejected}, $diff_provides_h)
++#- + those of _add_rejected_backtrack ($state-&gt;{rejected})
++sub backtrack_selected {
++ my ($urpm, $db, $state, $dep, $diff_provides, %options) = @_;
++
++ if (defined $dep-&gt;{required}) {
++ #- avoid deadlock here...
++ if (!exists $state-&gt;{backtrack}{deadlock}{$dep-&gt;{required}}) {
++ $state-&gt;{backtrack}{deadlock}{$dep-&gt;{required}} = undef;
++
++ #- search for all possible packages, first is to try the selection, then if it is
++ #- impossible, backtrack the origin.
++ my @packages = find_candidate_packages_($urpm, $dep-&gt;{required});
++
++ foreach (@packages) {
++ #- avoid dead loop.
++ exists $state-&gt;{backtrack}{selected}{$_-&gt;id} and next;
++ #- a package if found is problably rejected or there is a problem.
++ if ($state-&gt;{rejected}{$_-&gt;fullname}) {
++ #- keep in mind a backtrack has happening here...
++ exists $dep-&gt;{promote} and _add_rejected_backtrack($state, $_, { promote =&gt; [ $dep-&gt;{promote} ] });
++
++ my $closure = $state-&gt;{rejected}{$_-&gt;fullname}{closure} || {};
++ foreach my $p (grep { exists $closure-&gt;{$_}{avoid} } keys %$closure) {
++ _add_rejected_backtrack($state, $_, { conflicts =&gt; [ $p ] })
++ }
++ #- backtrack callback should return a strictly positive value if the selection of the new
++ #- package is prefered over the currently selected package.
++ next;
++ }
++ $state-&gt;{backtrack}{selected}{$_-&gt;id} = undef;
++
++ #- in such case, we need to drop the problem caused so that rejected condition is removed.
++ #- if this is not possible, the next backtrack on the same package will be refused above.
++ my @l = map { $urpm-&gt;search($_, strict_fullname =&gt; 1) }
++ keys %{($state-&gt;{rejected}{$_-&gt;fullname} || {})-&gt;{closure}};
++
++ disable_selected_and_unrequested_dependencies($urpm, $db, $state, @l);
++
++ return { required =&gt; $_-&gt;id,
++ exists $dep-&gt;{from} ? (from =&gt; $dep-&gt;{from}) : @{[]},
++ exists $dep-&gt;{requested} ? (requested =&gt; $dep-&gt;{requested}) : @{[]},
++ exists $dep-&gt;{promote} ? (promote =&gt; $dep-&gt;{promote}) : @{[]},
++ exists $dep-&gt;{psel} ? (psel =&gt; $dep-&gt;{psel}) : @{[]},
++ };
++ }
++ }
++ }
++
++ if (defined $dep-&gt;{from}) {
++ if ($options{nodeps}) {
++ #- try to keep unsatisfied dependencies in requested.
++ if ($dep-&gt;{required} &amp;&amp; exists $state-&gt;{selected}{$dep-&gt;{from}-&gt;id}) {
++ push @{$state-&gt;{selected}{$dep-&gt;{from}-&gt;id}{unsatisfied}}, $dep-&gt;{required};
++ }
++ } else {
++ #- at this point, dep cannot be resolved, this means we need to disable
++ #- all selection tree, re-enabling removed and obsoleted packages as well.
++ unless (exists $state-&gt;{rejected}{$dep-&gt;{from}-&gt;fullname}) {
++ #- package is not currently rejected, compute the closure now.
++ my @l = disable_selected_and_unrequested_dependencies($urpm, $db, $state, $dep-&gt;{from});
++ foreach (@l) {
++ #- disable all these packages in order to avoid selecting them again.
++ _set_rejected_from($state, $_, $dep-&gt;{from});
++ }
++ }
++ #- the package is already rejected, we assume we can add another reason here!
++ $urpm-&gt;{debug_URPM}(&quot;adding a reason to already rejected package &quot; . $dep-&gt;{from}-&gt;fullname . &quot;: unsatisfied &quot; . $dep-&gt;{required}) if $urpm-&gt;{debug_URPM};
++
++ _add_rejected_backtrack($state, $dep-&gt;{from}, { unsatisfied =&gt; [ $dep-&gt;{required} ] });
++ }
++ }
++
++ my @properties;
++ if (defined $dep-&gt;{psel}) {
++ if ($options{keep}) {
++ backtrack_selected_psel_keep($urpm, $db, $state, $dep-&gt;{psel}, $dep-&gt;{keep});
++
++ #- the package is already rejected, we assume we can add another reason here!
++ defined $dep-&gt;{promote} and _add_rejected_backtrack($state, $dep-&gt;{psel}, { promote =&gt; [ $dep-&gt;{promote} ] });
++ } else {
++ #- the backtrack need to examine diff_provides promotion on $n.
++ with_db_unsatisfied_requires($urpm, $db, $state, $dep-&gt;{promote}, sub {
++ my ($p, @unsatisfied) = @_;
++ my %diff_provides_h;
++ set_rejected_and_compute_diff_provides($urpm, $state, \%diff_provides_h, {
++ rejected_pkg =&gt; $p, removed =&gt; 1,
++ from =&gt; $dep-&gt;{psel},
++ why =&gt; { unsatisfied =&gt; \@unsatisfied }
++ });
++ push @$diff_provides, map { +{ name =&gt; $_, pkg =&gt; $dep-&gt;{psel} } } keys %diff_provides_h;
++ });
++ with_state_unsatisfied_requires($urpm, $db, $state, $dep-&gt;{promote}, sub {
++ my ($p) = @_;
++ _set_rejected_from($state, $p, $dep-&gt;{psel});
++ disable_selected_and_unrequested_dependencies($urpm, $db, $state, $p);
++ });
++ }
++ }
++
++ #- some packages may have been removed because of selection of this one.
++ #- the rejected flags should have been cleaned by disable_selected above.
++ @properties;
++}
++
++#- side-effects:
++#- + those of _set_rejected_from ($state-&gt;{rejected})
++#- + those of _add_rejected_backtrack ($state-&gt;{rejected})
++#- + those of disable_selected_and_unrequested_dependencies ($state-&gt;{selected}, $state-&gt;{whatrequires}, flag_requested, flag_required)
++sub backtrack_selected_psel_keep {
++ my ($urpm, $db, $state, $psel, $keep) = @_;
++
++ #- we shouldn't try to remove packages, so psel which leads to this need to be unselected.
++ unless (exists $state-&gt;{rejected}{$psel-&gt;fullname}) {
++ #- package is not currently rejected, compute the closure now.
++ my @l = disable_selected_and_unrequested_dependencies($urpm, $db, $state, $psel);
++ foreach (@l) {
++ #- disable all these packages in order to avoid selecting them again.
++ _set_rejected_from($state, $_, $psel);
++ }
++ }
++ #- to simplify, a reference to list or standalone elements may be set in keep.
++ $keep and _add_rejected_backtrack($state, $psel, { keep =&gt; $keep });
++}
++
++#- side-effects: $state-&gt;{rejected}
++sub _remove_all_rejected_from {
++ my ($state, $from_fullname) = @_;
++
++ grep {
++ _remove_rejected_from($state, $_, $from_fullname);
++ } keys %{$state-&gt;{rejected}};
++}
++
++#- side-effects: $state-&gt;{rejected}
++sub _remove_rejected_from {
++ my ($state, $fullname, $from_fullname) = @_;
++
++ my $rv = $state-&gt;{rejected}{$fullname} or return;
++
++ foreach (qw(removed obsoleted)) {
++ if (exists $rv-&gt;{$_} &amp;&amp; exists $rv-&gt;{$_}{$from_fullname}) {
++ delete $rv-&gt;{$_}{$from_fullname};
++ delete $rv-&gt;{$_} if !%{$rv-&gt;{$_}};
++ }
++ }
++
++ exists $rv-&gt;{closure}{$from_fullname} or return;
++ delete $rv-&gt;{closure}{$from_fullname};
++ if (%{$rv-&gt;{closure}}) {
++ 0;
++ } else {
++ delete $state-&gt;{rejected}{$fullname};
++ 1;
++ }
++}
++
++#- side-effects: $state-&gt;{rejected}
++sub _add_rejected_backtrack {
++ my ($state, $pkg, $backtrack) = @_;
++
++ my $bt = $state-&gt;{rejected}{$pkg-&gt;fullname}{backtrack} ||= {};
++
++ foreach (keys %$backtrack) {
++ push @{$bt-&gt;{$_}}, @{$backtrack-&gt;{$_}};
++ }
++}
++
++#- useful to reject packages in advance
++#- eg when selecting &quot;a&quot; which conflict with &quot;b&quot;, ensure we won't select &quot;b&quot;
++#- but it's somewhat dangerous because it's sometimes called on installed packages,
++#- and in that case, a real resolve_rejected_ must be done
++#- (that's why set_rejected ignores the effect of _set_rejected_from)
++#-
++#- side-effects: $state-&gt;{rejected}
++sub _set_rejected_from {
++ my ($state, $pkg, $from_pkg) = @_;
++
++ $pkg-&gt;fullname ne $from_pkg-&gt;fullname or return;
++
++ $state-&gt;{rejected}{$pkg-&gt;fullname}{closure}{$from_pkg-&gt;fullname}{avoid} ||= undef;
++}
++
++#- side-effects: $state-&gt;{rejected}
++sub _set_rejected_old_package {
++ my ($state, $pkg, $new_pkg) = @_;
++
++ if ($pkg-&gt;fullname eq $new_pkg-&gt;fullname) {
++ $state-&gt;{rejected_already_installed}{$pkg-&gt;id} = $pkg;
++ } else {
++ push @{$state-&gt;{rejected}{$pkg-&gt;fullname}{backtrack}{keep}}, scalar $new_pkg-&gt;fullname;
++ }
++}
++
++#- side-effects: $state-&gt;{rejected}
++sub set_rejected {
++ my ($urpm, $state, $rdep) = @_;
++
++ my $fullname = $rdep-&gt;{rejected_pkg}-&gt;fullname;
++ my $rv = $state-&gt;{rejected}{$fullname} ||= {};
++
++ my $newly_rejected = !exists $rv-&gt;{size};
++
++ if ($newly_rejected) {
++ $urpm-&gt;{debug_URPM}(&quot;set_rejected: $fullname&quot;) if $urpm-&gt;{debug_URPM};
++ #- keep track of size of package which are finally removed.
++ $rv-&gt;{size} = $rdep-&gt;{rejected_pkg}-&gt;size;
++ }
++
++ #- keep track of what causes closure.
++ if ($rdep-&gt;{from}) {
++ my $closure = $rv-&gt;{closure}{scalar $rdep-&gt;{from}-&gt;fullname} ||= {};
++ if (my $l = delete $rdep-&gt;{why}{unsatisfied}) {
++ my $unsatisfied = $closure-&gt;{unsatisfied} ||= [];
++ @$unsatisfied = uniq(@$unsatisfied, @$l);
++ }
++ $closure-&gt;{$_} = $rdep-&gt;{why}{$_} foreach keys %{$rdep-&gt;{why}};
++ }
++
++ #- set removed and obsoleted level.
++ foreach (qw(removed obsoleted)) {
++ if ($rdep-&gt;{$_}) {
++ if ($rdep-&gt;{from}) {
++ $rv-&gt;{$_}{scalar $rdep-&gt;{from}-&gt;fullname} = undef;
++ } else {
++ $rv-&gt;{$_}{asked} = undef;
++ }
++ }
++ }
++
++ $newly_rejected;
++}
++
++#- side-effects:
++#- + those of set_rejected ($state-&gt;{rejected})
++#- + those of _compute_diff_provides_of_removed_pkg ($diff_provides_h)
++sub set_rejected_and_compute_diff_provides {
++ my ($urpm, $state, $diff_provides_h, $rdep) = @_;
++
++ my $newly_rejected = set_rejected($urpm, $state, $rdep);
++
++ #- no need to compute diff_provides if package was already rejected
++ $newly_rejected or return;
++
++ _compute_diff_provides_of_removed_pkg($urpm, $state, $diff_provides_h, $rdep-&gt;{rejected_pkg});
++}
++
++#- see resolve_rejected_ below
++sub resolve_rejected {
++ my ($urpm, $db, $state, $pkg, %rdep) = @_;
++ $rdep{rejected_pkg} = $pkg;
++ resolve_rejected_($urpm, $db, $state, $rdep{unsatisfied}, \%rdep);
++}
++
++#- close rejected (as urpme previously) for package to be removable without error.
++#-
++#- side-effects: $properties
++#- + those of set_rejected ($state-&gt;{rejected})
++sub resolve_rejected_ {
++ my ($urpm, $db, $state, $properties, $rdep) = @_;
++
++ $urpm-&gt;{debug_URPM}(&quot;resolve_rejected: &quot; . $rdep-&gt;{rejected_pkg}-&gt;fullname) if $urpm-&gt;{debug_URPM};
++
++ #- check if the package has already been asked to be rejected (removed or obsoleted).
++ #- this means only add the new reason and return.
++ my $newly_rejected = set_rejected($urpm, $state, $rdep);
++
++ $newly_rejected or return;
++
++ my @pkgs_todo = $rdep-&gt;{rejected_pkg};
++
++ while (my $cp = shift @pkgs_todo) {
++ #- close what requires this property, but check with selected package requiring old properties.
++ foreach my $n ($cp-&gt;provides_nosense) {
++ foreach my $pkg (whatrequires($urpm, $state, $n)) {
++ if (my @l = unsatisfied_requires($urpm, $db, $state, $pkg, name =&gt; $n)) {
++ #- a selected package requires something that is no more available
++ #- and should be tried to be re-selected if possible.
++ if ($properties) {
++ push @$properties, map {
++ { required =&gt; $_, rejected =&gt; scalar $pkg-&gt;fullname }; # rejected is only there for debugging purpose (??)
++ } @l;
++ }
++ }
++ }
++ with_db_unsatisfied_requires($urpm, $db, $state, $n, sub {
++ my ($p, @unsatisfied) = @_;
++
++ my $newly_rejected = set_rejected($urpm, $state, {
++ rejected_pkg =&gt; $p,
++ from =&gt; $rdep-&gt;{rejected_pkg},
++ why =&gt; { unsatisfied =&gt; \@unsatisfied },
++ obsoleted =&gt; $rdep-&gt;{obsoleted},
++ removed =&gt; $rdep-&gt;{removed},
++ });
++
++ #- continue the closure unless already examined.
++ $newly_rejected or return;
++
++ $p-&gt;pack_header; #- need to pack else package is no longer visible...
++ push @pkgs_todo, $p;
++ });
++ }
++ }
++}
++
++# see resolve_requested__no_suggests below for information about usage
++sub resolve_requested {
++ my ($urpm, $db, $state, $requested, %options) = @_;
++
++ my @selected = resolve_requested__no_suggests($urpm, $db, $state, $requested, %options);
++
++ if (!$options{no_suggests}) {
++ my @todo = @selected;
++ while (@todo) {
++ my $pkg = shift @todo;
++ my %suggests = map { $_ =&gt; 1 } $pkg-&gt;suggests or next;
++
++ #- do not install a package that has already been suggested
++ $db-&gt;traverse_tag('name', [ $pkg-&gt;name ], sub {
++ my ($p) = @_;
++ delete $suggests{$_} foreach $p-&gt;suggests;
++ });
++
++ # workaround: if you do &quot;urpmi virtual_pkg&quot; and one virtual_pkg is already installed,
++ # it will ask anyway for the other choices
++ foreach my $suggest (keys %suggests) {
++ $db-&gt;traverse_tag('whatprovides', [ $suggest ], sub {
++ delete $suggests{$suggest};
++ });
++ }
++
++ %suggests or next;
++
++ $urpm-&gt;{debug_URPM}(&quot;requested &quot; . join(', ', keys %suggests) . &quot; suggested by &quot; . $pkg-&gt;fullname) if $urpm-&gt;{debug_URPM};
++
++ my %new_requested = map { $_ =&gt; undef } keys %suggests;
++ my @new_selected = resolve_requested__no_suggests_($urpm, $db, $state, \%new_requested, %options);
++ $state-&gt;{selected}{$_-&gt;id}{suggested} = 1 foreach @new_selected;
++ push @selected, @new_selected;
++ push @todo, @new_selected;
++ }
++ }
++ @selected;
++}
++
++#- Resolve dependencies of requested packages; keep resolution state to
++#- speed up process.
++#- A requested package is marked to be installed; once done, an upgrade flag or
++#- an installed flag is set according to the needs of the installation of this
++#- package.
++#- Other required packages will have a required flag set along with an upgrade
++#- flag or an installed flag.
++#- Base flag should always be &quot;installed&quot; or &quot;upgraded&quot;.
++#- The following options are recognized :
++#- callback_choices : subroutine to be called to ask the user to choose
++#- between several possible packages. Returns an array of URPM::Package
++#- objects, or an empty list eventually.
++#- keep :
++#- nodeps :
++#-
++#- side-effects: flag_requested
++#- + those of resolve_requested__no_suggests_
++sub resolve_requested__no_suggests {
++ my ($urpm, $db, $state, $requested, %options) = @_;
++
++ foreach (keys %$requested) {
++ #- keep track of requested packages by propating the flag.
++ foreach (find_candidate_packages_($urpm, $_)) {
++ $_-&gt;set_flag_requested;
++ }
++ }
++
++ resolve_requested__no_suggests_($urpm, $db, $state, $requested, %options);
++}
++
++# same as resolve_requested__no_suggests, but do not modify requested_flag
++#-
++#- side-effects: $state-&gt;{selected}, flag_required, flag_installed, flag_upgrade
++#- + those of backtrack_selected (flag_requested, $state-&gt;{rejected}, $state-&gt;{whatrequires}, $state-&gt;{backtrack})
++#- + those of _unselect_package_deprecated_by (flag_requested, $state-&gt;{rejected}, $state-&gt;{whatrequires}, $state-&gt;{oldpackage}, $state-&gt;{unselected_uninstalled})
++#- + those of _handle_conflicts ($state-&gt;{rejected})
++#- + those of _handle_conflict ($state-&gt;{rejected})
++#- + those of backtrack_selected_psel_keep (flag_requested, $state-&gt;{whatrequires})
++#- + those of _handle_diff_provides (flag_requested, $state-&gt;{rejected}, $state-&gt;{whatrequires})
++#- + those of _no_more_recent_installed_and_providing ($state-&gt;{rejected})
++sub resolve_requested__no_suggests_ {
++ my ($urpm, $db, $state, $requested, %options) = @_;
++
++ my @properties = map {
++ { required =&gt; $_, requested =&gt; $requested-&gt;{$_} };
++ } keys %$requested;
++
++ my (@diff_provides, @selected, @choices);
++
++ #- for each dep property evaluated, examine which package will be obsoleted on $db,
++ #- then examine provides that will be removed (which need to be satisfied by another
++ #- package present or by a new package to upgrade), then requires not satisfied and
++ #- finally conflicts that will force a new upgrade or a remove.
++ do {
++ while (my $dep = shift @properties) {
++ #- we need to avoid selecting packages if the source has been disabled.
++ if (exists $dep-&gt;{from} &amp;&amp; !$urpm-&gt;{keep_unrequested_dependencies}) {
++ exists $state-&gt;{selected}{$dep-&gt;{from}-&gt;id} or next;
++ }
++
++ my $pkg = _choose_required($urpm, $db, $state, $dep, \@properties, \@choices, \@diff_provides, %options) or next;
++
++ !$pkg || exists $state-&gt;{selected}{$pkg-&gt;id} and next;
++
++ if ($pkg-&gt;arch eq 'src') {
++ $pkg-&gt;set_flag_upgrade;
++ } else {
++ _set_flag_installed_and_upgrade_if_no_newer($db, $pkg);
++
++ if ($pkg-&gt;flag_installed &amp;&amp; !$pkg-&gt;flag_upgrade) {
++ _no_more_recent_installed_and_providing($urpm, $db, $state, $pkg, $dep-&gt;{required}) or next;
++ }
++ }
++
++ _handle_conflicts_with_selected($urpm, $db, $state, $pkg, $dep, \@properties, \@diff_provides, %options) or next;
++
++ $urpm-&gt;{debug_URPM}(&quot;selecting &quot; . $pkg-&gt;fullname) if $urpm-&gt;{debug_URPM};
++
++ #- keep in mind the package has be selected, remove the entry in requested input hash,
++ #- this means required dependencies have undef value in selected hash.
++ #- requested flag is set only for requested package where value is not false.
++ push @selected, $pkg;
++ $state-&gt;{selected}{$pkg-&gt;id} = { exists $dep-&gt;{requested} ? (requested =&gt; $dep-&gt;{requested}) : @{[]},
++ exists $dep-&gt;{from} ? (from =&gt; $dep-&gt;{from}) : @{[]},
++ exists $dep-&gt;{promote} ? (promote =&gt; $dep-&gt;{promote}) : @{[]},
++ exists $dep-&gt;{psel} ? (psel =&gt; $dep-&gt;{psel}) : @{[]},
++ $pkg-&gt;flag_disable_obsolete ? (install =&gt; 1) : @{[]},
++ };
++
++ $pkg-&gt;set_flag_required;
++
++ #- check if the package is not already installed before trying to use it, compute
++ #- obsoleted packages too. This is valable only for non source packages.
++ my %diff_provides_h;
++ if ($pkg-&gt;arch ne 'src' &amp;&amp; !$pkg-&gt;flag_disable_obsolete) {
++ _unselect_package_deprecated_by($urpm, $db, $state, \%diff_provides_h, $pkg);
++ }
++
++ #- all requires should be satisfied according to selected package, or installed packages.
++ if (my @l = unsatisfied_requires($urpm, $db, $state, $pkg)) {
++ $urpm-&gt;{debug_URPM}(&quot;requiring &quot; . join(',', sort @l) . &quot; for &quot; . $pkg-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ unshift @properties, map { +{ required =&gt; $_, from =&gt; $pkg,
++ exists $dep-&gt;{promote} ? (promote =&gt; $dep-&gt;{promote}) : @{[]},
++ exists $dep-&gt;{psel} ? (psel =&gt; $dep-&gt;{psel}) : @{[]},
++ } } @l;
++ }
++
++ #- keep in mind what is requiring each item (for unselect to work).
++ foreach ($pkg-&gt;requires_nosense) {
++ $state-&gt;{whatrequires}{$_}{$pkg-&gt;id} = undef;
++ }
++
++ #- cancel flag if this package should be cancelled but too late (typically keep options).
++ my @keep;
++
++ _handle_conflicts($urpm, $db, $state, $pkg, \@properties, \%diff_provides_h, $options{keep} &amp;&amp; \@keep);
++
++ #- examine if an existing package does not conflict with this one.
++ $db-&gt;traverse_tag('whatconflicts', [ $pkg-&gt;provides_nosense ], sub {
++ @keep and return;
++ my ($p) = @_;
++ foreach my $property ($p-&gt;conflicts) {
++ if ($pkg-&gt;provides_overlap($property)) {
++ _handle_conflict($urpm, $state, $pkg, $p, $property, $property, \@properties, \%diff_provides_h, $options{keep} &amp;&amp; \@keep);
++ }
++ }
++ });
++
++ #- keep existing package and therefore cancel current one.
++ if (@keep) {
++ backtrack_selected_psel_keep($urpm, $db, $state, $pkg, \@keep);
++ }
++
++ push @diff_provides, map { +{ name =&gt; $_, pkg =&gt; $pkg } } keys %diff_provides_h;
++ }
++ if (my $diff = shift @diff_provides) {
++ _handle_diff_provides($urpm, $db, $state, \@properties, \@diff_provides, $diff-&gt;{name}, $diff-&gt;{pkg}, %options);
++ } elsif (my $dep = shift @choices) {
++ push @properties, $dep;
++ }
++ } while @diff_provides || @properties || @choices;
++
++ #- return what has been selected by this call (not all selected hash which may be not empty
++ #- previously. avoid returning rejected packages which weren't selectable.
++ grep { exists $state-&gt;{selected}{$_-&gt;id} } @selected;
++}
++
++#- pre-disables packages that $pkg has conflict entries for, and
++#- unselects $pkg if such a package is already selected
++#- side-effects:
++#- + those of _set_rejected_from ($state-&gt;{rejected})
++#- + those of _remove_all_rejected_from ($state-&gt;{rejected})
++#- + those of backtrack_selected ($state-&gt;{backtrack}, $state-&gt;{rejected}, $state-&gt;{selected}, $state-&gt;{whatrequires}, flag_requested, flag_required)
++sub _handle_conflicts_with_selected {
++ my ($urpm, $db, $state, $pkg, $dep, $properties, $diff_provides, %options) = @_;
++ foreach ($pkg-&gt;conflicts) {
++ if (my ($n, $o, $v) = property2name_op_version($_)) {
++ foreach my $p ($urpm-&gt;packages_providing($n)) {
++ $pkg == $p and next;
++ $p-&gt;provides_overlap($_) or next;
++ if (exists $state-&gt;{selected}{$p-&gt;id}) {
++ $urpm-&gt;{debug_URPM}($pkg-&gt;fullname . &quot; conflicts with already selected package &quot; . $p-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ _remove_all_rejected_from($state, $pkg);
++ _set_rejected_from($state, $pkg, $p);
++ unshift @$properties, backtrack_selected($urpm, $db, $state, $dep, $diff_provides, %options);
++ return;
++ }
++ _set_rejected_from($state, $p, $pkg);
++ }
++ }
++ }
++ 1;
++}
++
++#- side-effects:
++#- + those of set_rejected_and_compute_diff_provides ($state-&gt;{rejected}, $diff_provides_h)
++#- + those of _handle_conflict ($properties, $keep, $diff_provides_h)
++sub _handle_conflicts {
++ my ($urpm, $db, $state, $pkg, $properties, $diff_provides_h, $keep) = @_;
++
++ #- examine conflicts, an existing package conflicting with this selection should
++ #- be upgraded to a new version which will be safe, else it should be removed.
++ foreach ($pkg-&gt;conflicts) {
++ $keep &amp;&amp; @$keep and last;
++ if (my ($file) = m!^(/[^\s\[]*)!) {
++ $db-&gt;traverse_tag('path', [ $file ], sub {
++ $keep &amp;&amp; @$keep and return;
++ my ($p) = @_;
++ if ($keep) {
++ push @$keep, scalar $p-&gt;fullname;
++ } else {
++ #- all these package should be removed.
++ set_rejected_and_compute_diff_provides($urpm, $state, $diff_provides_h, {
++ rejected_pkg =&gt; $p, removed =&gt; 1,
++ from =&gt; $pkg,
++ why =&gt; { conflicts =&gt; $file },
++ });
++ }
++ });
++ } elsif (my $name = property2name($_)) {
++ my $property = $_;
++ $db-&gt;traverse_tag('whatprovides', [ $name ], sub {
++ $keep &amp;&amp; @$keep and return;
++ my ($p) = @_;
++ if ($p-&gt;provides_overlap($property)) {
++ _handle_conflict($urpm, $state, $pkg, $p, $property, scalar($pkg-&gt;fullname), $properties, $diff_provides_h, $keep);
++ }
++ });
++ }
++ }
++}
++
++#- side-effects:
++#- + those of _unselect_package_deprecated_by_property (flag_requested, flag_required, $state-&gt;{selected}, $state-&gt;{rejected}, $state-&gt;{whatrequires}, $state-&gt;{oldpackage}, $state-&gt;{unselected_uninstalled})
++sub _unselect_package_deprecated_by {
++ my ($urpm, $db, $state, $diff_provides_h, $pkg) = @_;
++
++ _unselect_package_deprecated_by_property($urpm, $db, $state, $pkg, $diff_provides_h, $pkg-&gt;name, '&lt;', $pkg-&gt;epoch . &quot;:&quot; . $pkg-&gt;version . &quot;-&quot; . $pkg-&gt;release);
++
++ foreach ($pkg-&gt;obsoletes) {
++ my ($n, $o, $v) = property2name_op_version($_) or next;
++
++ #- ignore if this package obsoletes itself
++ #- otherwise this can cause havoc if: to_install=v3, installed=v2, v3 obsoletes &lt; v2
++ if ($n ne $pkg-&gt;name) {
++ _unselect_package_deprecated_by_property($urpm, $db, $state, $pkg, $diff_provides_h, $n, $o, $v);
++ }
++ }
++}
++
++#- side-effects: $state-&gt;{oldpackage}, $state-&gt;{unselected_uninstalled}
++#- + those of set_rejected ($state-&gt;{rejected})
++#- + those of _set_rejected_from ($state-&gt;{rejected})
++#- + those of disable_selected (flag_requested, flag_required, $state-&gt;{selected}, $state-&gt;{rejected}, $state-&gt;{whatrequires})
++sub _unselect_package_deprecated_by_property {
++ my ($urpm, $db, $state, $pkg, $diff_provides_h, $n, $o, $v) = @_;
++
++ #- populate avoided entries according to what is selected.
++ foreach my $p ($urpm-&gt;packages_providing($n)) {
++ if ($p-&gt;name eq $pkg-&gt;name) {
++ #- all packages with the same name should now be avoided except when chosen.
++ } else {
++ #- in case of obsoletes, keep track of what should be avoided
++ #- but only if package name equals the obsolete name.
++ $p-&gt;name eq $n &amp;&amp; (!$o || eval($p-&gt;compare($v) . $o . 0)) or next;
++ }
++ #- these packages are not yet selected, if they happen to be selected,
++ #- they must first be unselected.
++ _set_rejected_from($state, $p, $pkg);
++ }
++
++ #- examine rpm db too (but only according to package names as a fix in rpm itself)
++ $db-&gt;traverse_tag('name', [ $n ], sub {
++ my ($p) = @_;
++
++ #- without an operator, anything (with the same name) is matched.
++ #- with an operator, check package EVR with the obsoletes EVR.
++ #- $satisfied is true if installed package has version newer or equal.
++ my $comparison = $p-&gt;compare($v);
++ my $satisfied = !$o || eval($comparison . $o . 0);
++
++ my $obsoleted;
++ if ($p-&gt;name eq $pkg-&gt;name) {
++ #- all packages older than the current one are obsoleted,
++ #- the others are simply removed (the result is the same).
++ if ($o &amp;&amp; $comparison &gt; 0) {
++ #- installed package is newer
++ #- remove this package from the list of packages to install,
++ #- unless urpmi was invoked with --allow-force (in which
++ #- case rpm could be invoked with --oldpackage)
++ if (!$urpm-&gt;{options}{'allow-force'}) {
++ #- since the originally requested packages (or other
++ #- non-installed ones) could be unselected by the following
++ #- operation, remember them, to warn the user
++ $state-&gt;{unselected_uninstalled} = [ grep {
++ !$_-&gt;flag_installed;
++ } disable_selected($urpm, $db, $state, $pkg) ];
++
++ return;
++ }
++ } elsif ($satisfied) {
++ $obsoleted = 1;
++ }
++ } elsif ($satisfied) {
++ $obsoleted = 1;
++ } else {
++ return;
++ }
++
++ set_rejected_and_compute_diff_provides($urpm, $state, $diff_provides_h, {
++ rejected_pkg =&gt; $p,
++ obsoleted =&gt; $obsoleted, removed =&gt; !$obsoleted,
++ from =&gt; $pkg, why =&gt; $obsoleted ? undef : { old_requested =&gt; 1 },
++ });
++ $obsoleted or ++$state-&gt;{oldpackage};
++ });
++}
++
++#- side-effects: $diff_provides
++sub _compute_diff_provides_of_removed_pkg {
++ my ($urpm, $state, $diff_provides_h, $p) = @_;
++
++ foreach ($p-&gt;provides) {
++ #- check differential provides between obsoleted package and newer one.
++ my ($pn, $ps) = property2name_range($_) or next;
++
++ my $not_provided = 1;
++ foreach (grep { exists $state-&gt;{selected}{$_} }
++ keys %{$urpm-&gt;{provides}{$pn} || {}}) {
++ my $pp = $urpm-&gt;{depslist}[$_];
++ foreach ($pp-&gt;provides) {
++ my ($ppn, $pps) = property2name_range($_) or next;
++ $ppn eq $pn &amp;&amp; $pps eq $ps
++ and $not_provided = 0;
++ }
++ }
++ $not_provided and $diff_provides_h-&gt;{$pn} = undef;
++ }
++}
++
++#- side-effects: none
++sub _find_packages_obsoleting {
++ my ($urpm, $state, $p) = @_;
++
++ grep {
++ !$_-&gt;flag_skip
++ &amp;&amp; $_-&gt;is_arch_compat
++ &amp;&amp; !exists $state-&gt;{rejected}{$_-&gt;fullname}
++ &amp;&amp; $_-&gt;obsoletes_overlap($p-&gt;name . &quot; == &quot; . $p-&gt;epoch . &quot;:&quot; . $p-&gt;version . &quot;-&quot; . $p-&gt;release)
++ &amp;&amp; $_-&gt;fullname ne $p-&gt;fullname
++ &amp;&amp; (!strict_arch($urpm) || strict_arch_check($p, $_));
++ } $urpm-&gt;packages_obsoleting($p-&gt;name);
++}
++
++#- side-effects: $properties
++#- + those of backtrack_selected_psel_keep ($state-&gt;{rejected}, $state-&gt;{selected}, $state-&gt;{whatrequires}, flag_requested, flag_required)
++#- + those of resolve_rejected_ ($state-&gt;{rejected}, $properties)
++#- + those of disable_selected_and_unrequested_dependencies (flag_requested, flag_required, $state-&gt;{selected}, $state-&gt;{whatrequires}, $state-&gt;{rejected})
++#- + those of _set_rejected_from ($state-&gt;{rejected})
++sub _handle_diff_provides {
++ my ($urpm, $db, $state, $properties, $diff_provides, $n, $pkg, %options) = @_;
++
++ with_any_unsatisfied_requires($urpm, $db, $state, $n, sub {
++ my ($p, $from_state, @unsatisfied) = @_;
++
++ #- try if upgrading the package will be satisfying all the requires...
++ #- there is no need to avoid promoting epoch as the package examined is not
++ #- already installed.
++ my @packages = find_candidate_packages_($urpm, $p-&gt;name, $state-&gt;{rejected});
++ @packages =
++ grep { ($_-&gt;name eq $p-&gt;name ? $p-&gt;compare_pkg($_) &lt; 0 :
++ $_-&gt;obsoletes_overlap($p-&gt;name . &quot; == &quot; . $p-&gt;epoch . &quot;:&quot; . $p-&gt;version . &quot;-&quot; . $p-&gt;release))
++ &amp;&amp; (!strict_arch($urpm) || strict_arch_check($p, $_))
++ } @packages;
++
++ if (!@packages) {
++ @packages = _find_packages_obsoleting($urpm, $state, $p);
++ }
++
++ if (@packages) {
++ my $best = join('|', map { $_-&gt;id } @packages);
++ $urpm-&gt;{debug_URPM}(&quot;promoting &quot; . $urpm-&gt;{depslist}[$best]-&gt;fullname . &quot; because of conflict above&quot;) if $urpm-&gt;{debug_URPM};
++ push @$properties, { required =&gt; $best, promote =&gt; $n, psel =&gt; $pkg };
++ } else {
++ #- no package have been found, we may need to remove the package examined unless
++ #- there exists enough packages that provided the unsatisfied requires.
++ my @best;
++ foreach (@unsatisfied) {
++ my @packages = find_candidate_packages_($urpm, $_, $state-&gt;{rejected});
++ if (@packages = grep { $_-&gt;fullname ne $p-&gt;fullname } @packages) {
++ push @best, join('|', map { $_-&gt;id } @packages);
++ }
++ }
++
++ if (@best == @unsatisfied) {
++ $urpm-&gt;{debug_URPM}(&quot;promoting &quot; . join(' ', _ids_to_fullnames($urpm, @best)) . &quot; because of conflict above&quot;) if $urpm-&gt;{debug_URPM};
++ push @$properties, map { +{ required =&gt; $_, promote =&gt; $n, psel =&gt; $pkg } } @best;
++ } else {
++ if ($from_state) {
++ disable_selected_and_unrequested_dependencies($urpm, $db, $state, $p);
++ _set_rejected_from($state, $p, $pkg);
++ } elsif ($options{keep}) {
++ backtrack_selected_psel_keep($urpm, $db, $state, $pkg, [ scalar $p-&gt;fullname ]);
++ } else {
++ my %diff_provides_h;
++ set_rejected_and_compute_diff_provides($urpm, $state, \%diff_provides_h, {
++ rejected_pkg =&gt; $p, removed =&gt; 1,
++ from =&gt; $pkg,
++ why =&gt; { unsatisfied =&gt; \@unsatisfied },
++ });
++ push @$diff_provides, map { +{ name =&gt; $_, pkg =&gt; $pkg } } keys %diff_provides_h;
++ }
++ }
++ }
++ });
++}
++
++#- side-effects: $properties, $keep
++#- + those of set_rejected_and_compute_diff_provides ($state-&gt;{rejected}, $diff_provides_h)
++sub _handle_conflict {
++ my ($urpm, $state, $pkg, $p, $property, $reason, $properties, $diff_provides_h, $keep) = @_;
++
++ $urpm-&gt;{debug_URPM}(&quot;installed package &quot; . $p-&gt;fullname . &quot; is conflicting with &quot; . $pkg-&gt;fullname . &quot; (Conflicts: $property)&quot;) if $urpm-&gt;{debug_URPM};
++
++ #- the existing package will conflict with the selection; check
++ #- whether a newer version will be ok, else ask to remove the old.
++ my $need_deps = $p-&gt;name . &quot; &gt; &quot; . ($p-&gt;epoch ? $p-&gt;epoch . &quot;:&quot; : &quot;&quot;) .
++ $p-&gt;version . &quot;-&quot; . $p-&gt;release;
++ my @packages = grep { $_-&gt;name eq $p-&gt;name } find_candidate_packages_($urpm, $need_deps, $state-&gt;{rejected});
++ @packages = grep { ! $_-&gt;provides_overlap($property) } @packages;
++
++ if (!@packages) {
++ @packages = _find_packages_obsoleting($urpm, $state, $p);
++ @packages = grep { ! $_-&gt;provides_overlap($property) } @packages;
++ }
++
++ if (@packages) {
++ my $best = join('|', map { $_-&gt;id } @packages);
++ $urpm-&gt;{debug_URPM}(&quot;promoting &quot; . join('|', map { scalar $_-&gt;fullname } @packages) . &quot; because of conflict above&quot;) if $urpm-&gt;{debug_URPM};
++ unshift @$properties, { required =&gt; $best, promote_conflicts =&gt; $reason };
++ } else {
++ if ($keep) {
++ push @$keep, scalar $p-&gt;fullname;
++ } else {
++ #- no package has been found, we need to remove the package examined.
++ set_rejected_and_compute_diff_provides($urpm, $state, $diff_provides_h, {
++ rejected_pkg =&gt; $p, removed =&gt; 1,
++ from =&gt; $pkg,
++ why =&gt; { conflicts =&gt; $reason },
++ });
++ }
++ }
++}
++
++#- side-effects: none
++sub _dep_to_name {
++ my ($urpm, $dep) = @_;
++ join('|', map { _id_to_name($urpm, $_) } split('\|', $dep-&gt;{required}));
++}
++#- side-effects: none
++sub _id_to_name {
++ my ($urpm, $id_prop) = @_;
++ if ($id_prop =~ /^\d+/) {
++ my $pkg = $urpm-&gt;{depslist}[$id_prop];
++ $pkg &amp;&amp; $pkg-&gt;name;
++ } else {
++ $id_prop;
++ }
++}
++#- side-effects: none
++sub _ids_to_names {
++ my $urpm = shift;
++
++ map { $urpm-&gt;{depslist}[$_]-&gt;name } @_;
++}
++#- side-effects: none
++sub _ids_to_fullnames {
++ my $urpm = shift;
++
++ map { scalar $urpm-&gt;{depslist}[$_]-&gt;fullname } @_;
++}
++
++#- side-effects: flag_installed, flag_upgrade
++sub _set_flag_installed_and_upgrade_if_no_newer {
++ my ($db, $pkg) = @_;
++
++ !$pkg-&gt;flag_upgrade &amp;&amp; !$pkg-&gt;flag_installed or return;
++
++ my $upgrade = 1;
++ $db-&gt;traverse_tag('name', [ $pkg-&gt;name ], sub {
++ my ($p) = @_;
++ $pkg-&gt;set_flag_installed;
++ $upgrade &amp;&amp;= $pkg-&gt;compare_pkg($p) &gt; 0;
++ });
++ $pkg-&gt;set_flag_upgrade($upgrade);
++}
++
++#- side-effects:
++#- + those of _set_rejected_old_package ($state-&gt;{rejected})
++sub _no_more_recent_installed_and_providing {
++ my ($urpm, $db, $state, $pkg, $required) = @_;
++
++ my $allow = 1;
++ $db-&gt;traverse_tag('name', [ $pkg-&gt;name ], sub {
++ my ($p) = @_;
++ #- allow if a less recent package is installed,
++ if ($allow &amp;&amp; $pkg-&gt;compare_pkg($p) &lt;= 0) {
++ if ($required =~ /^\d+/ || $p-&gt;provides_overlap($required)) {
++ $urpm-&gt;{debug_URPM}(&quot;not selecting &quot; . $pkg-&gt;fullname . &quot; since the more recent &quot; . $p-&gt;fullname . &quot; is installed&quot;) if $urpm-&gt;{debug_URPM};
++ _set_rejected_old_package($state, $pkg, $p);
++ $allow = 0;
++ } else {
++ $urpm-&gt;{debug_URPM}(&quot;the more recent &quot; . $p-&gt;fullname .
++ &quot; is installed, but does not provide $required whereas &quot; .
++ $pkg-&gt;fullname . &quot; does&quot;) if $urpm-&gt;{debug_URPM};
++ }
++ }
++ });
++ $allow;
++}
++
++#- do the opposite of the resolve_requested:
++#- unselect a package and extend to any package not requested that is no
++#- longer needed by any other package.
++#- return the packages that have been deselected.
++#-
++#- side-effects: flag_requested, flag_required, $state-&gt;{selected}, $state-&gt;{whatrequires}
++#- + those of _remove_all_rejected_from ($state-&gt;{rejected})
++sub disable_selected {
++ my ($urpm, $db, $state, @pkgs_todo) = @_;
++ my @unselected;
++
++ #- iterate over package needing unrequested one.
++ while (my $pkg = shift @pkgs_todo) {
++ exists $state-&gt;{selected}{$pkg-&gt;id} or next;
++
++ #- keep a trace of what is deselected.
++ push @unselected, $pkg;
++
++ #- perform a closure on rejected packages (removed, obsoleted or avoided).
++ my @rejected_todo = scalar $pkg-&gt;fullname;
++ while (my $fullname = shift @rejected_todo) {
++ push @rejected_todo, _remove_all_rejected_from($state, $fullname);
++ }
++
++ #- the package being examined has to be unselected.
++ $urpm-&gt;{debug_URPM}(&quot;unselecting &quot; . $pkg-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ $pkg-&gt;set_flag_requested(0);
++ $pkg-&gt;set_flag_required(0);
++ delete $state-&gt;{selected}{$pkg-&gt;id};
++
++ #- determine package that requires properties no longer available, so that they need to be
++ #- unselected too.
++ foreach my $n ($pkg-&gt;provides_nosense) {
++ foreach my $p (whatrequires($urpm, $state, $n)) {
++ exists $state-&gt;{selected}{$p-&gt;id} or next;
++ if (unsatisfied_requires($urpm, $db, $state, $p, name =&gt; $n)) {
++ #- this package has broken dependencies and is selected.
++ push @pkgs_todo, $p;
++ }
++ }
++ }
++
++ #- clean whatrequires hash.
++ foreach ($pkg-&gt;requires_nosense) {
++ delete $state-&gt;{whatrequires}{$_}{$pkg-&gt;id};
++ %{$state-&gt;{whatrequires}{$_}} or delete $state-&gt;{whatrequires}{$_};
++ }
++ }
++
++ #- return all unselected packages.
++ @unselected;
++}
++
++#- determine dependencies that can safely been removed and are not requested
++#- return the packages that have been deselected.
++#-
++#- side-effects:
++#- + those of disable_selected (flag_requested, flag_required, $state-&gt;{selected}, $state-&gt;{whatrequires}, $state-&gt;{rejected})
++sub disable_selected_and_unrequested_dependencies {
++ my ($urpm, $db, $state, @pkgs_todo) = @_;
++ my @all_unselected;
++
++ #- disable selected packages, then extend unselection to all required packages
++ #- no longer needed and not requested.
++ while (my @unselected = disable_selected($urpm, $db, $state, @pkgs_todo)) {
++ my %required;
++
++ #- keep in the packages that had to be unselected.
++ @all_unselected or push @all_unselected, @unselected;
++
++ if ($urpm-&gt;{keep_unrequested_dependencies}) {
++ last;
++ }
++
++ #- search for unrequested required packages.
++ foreach (@unselected) {
++ foreach ($_-&gt;requires_nosense) {
++ foreach my $pkg (grep { $_ } $urpm-&gt;packages_providing($_)) {
++ $state-&gt;{selected}{$pkg-&gt;id} or next;
++ $state-&gt;{selected}{$pkg-&gt;id}{psel} &amp;&amp; $state-&gt;{selected}{$state-&gt;{selected}{$pkg-&gt;id}{psel}-&gt;id} and next;
++ $pkg-&gt;flag_requested and next;
++ $required{$pkg-&gt;id} = undef;
++ }
++ }
++ }
++
++ #- check required packages are not needed by another selected package.
++ foreach (keys %required) {
++ my $pkg = $urpm-&gt;{depslist}[$_] or next;
++ foreach ($pkg-&gt;provides_nosense) {
++ foreach my $p_id (whatrequires_id($state, $_)) {
++ exists $required{$p_id} and next;
++ $state-&gt;{selected}{$p_id} and $required{$pkg-&gt;id} = 1;
++ }
++ }
++ }
++
++ #- now required values still undefined indicates packages than can be removed.
++ @pkgs_todo = map { $urpm-&gt;{depslist}[$_] } grep { !$required{$_} } keys %required;
++ }
++
++ @all_unselected;
++}
++
++#- compute selected size by removing any removed or obsoleted package.
++#-
++#- side-effects: none
++sub selected_size {
++ my ($urpm, $state) = @_;
++ my ($size) = _selected_size_filesize($urpm, $state, 0);
++ $size;
++}
++#- side-effects: none
++sub selected_size_filesize {
++ my ($urpm, $state) = @_;
++ _selected_size_filesize($urpm, $state, 1);
++}
++#- side-effects: none
++sub _selected_size_filesize {
++ my ($urpm, $state, $compute_filesize) = @_;
++ my ($size, $filesize, $bad_filesize);
++
++ foreach (keys %{$state-&gt;{selected} || {}}) {
++ my $pkg = $urpm-&gt;{depslist}[$_];
++ $size += $pkg-&gt;size;
++ $compute_filesize or next;
++
++ if (my $n = $pkg-&gt;filesize) {
++ $filesize += $n;
++ } elsif (!$bad_filesize) {
++ $urpm-&gt;{debug} and $urpm-&gt;{debug}(&quot;no filesize for package &quot; . $pkg-&gt;fullname);
++ $bad_filesize = 1;
++ }
++ }
++
++ foreach (values %{$state-&gt;{rejected} || {}}) {
++ $_-&gt;{removed} || $_-&gt;{obsoleted} or next;
++ $size -= $_-&gt;{size};
++ }
++
++ foreach (@{$state-&gt;{orphans_to_remove} || []}) {
++ $size -= $_-&gt;size;
++ }
++
++ $size, $bad_filesize ? 0 : $filesize;
++}
++
++#- compute installed flags for all packages in depslist.
++#-
++#- side-effects: flag_upgrade, flag_installed
++sub compute_installed_flags {
++ my ($urpm, $db) = @_;
++
++ #- first pass to initialize flags installed and upgrade for all packages.
++ foreach (@{$urpm-&gt;{depslist}}) {
++ $_-&gt;is_arch_compat or next;
++ $_-&gt;flag_upgrade || $_-&gt;flag_installed or $_-&gt;set_flag_upgrade;
++ }
++
++ #- second pass to set installed flag and clean upgrade flag according to installed packages.
++ $db-&gt;traverse(sub {
++ my ($p) = @_;
++ #- compute flags.
++ foreach my $pkg ($urpm-&gt;packages_providing($p-&gt;name)) {
++ next if !defined $pkg;
++ $pkg-&gt;is_arch_compat &amp;&amp; $pkg-&gt;name eq $p-&gt;name or next;
++ #- compute only installed and upgrade flags.
++ $pkg-&gt;set_flag_installed; #- there is at least one package installed (whatever its version).
++ $pkg-&gt;flag_upgrade and $pkg-&gt;set_flag_upgrade($pkg-&gt;compare_pkg($p) &gt; 0);
++ }
++ });
++}
++
++#- side-effects: flag_skip, flag_disable_obsolete
++sub compute_flag {
++ my ($urpm, $pkg, %options) = @_;
++ foreach (qw(skip disable_obsolete)) {
++ if ($options{$_} &amp;&amp; !$pkg-&gt;flag($_)) {
++ $pkg-&gt;set_flag($_, 1);
++ $options{callback} and $options{callback}-&gt;($urpm, $pkg, %options);
++ }
++ }
++}
++
++#- Adds packages flags according to an array containing packages names.
++#- $val is an array reference (as returned by get_packages_list) containing
++#- package names, or a regular expression matching against the fullname, if
++#- enclosed in slashes.
++#- %options :
++#- callback : sub to be called for each package where the flag is set
++#- skip : if true, set the 'skip' flag
++#- disable_obsolete : if true, set the 'disable_obsolete' flag
++#-
++#- side-effects:
++#- + those of compute_flag (flag_skip, flag_disable_obsolete)
++sub compute_flags {
++ my ($urpm, $val, %options) = @_;
++ if (ref $val eq 'HASH') { $val = [ keys %$val ] } #- compatibility with urpmi &lt;= 4.5-13mdk
++ my @regex;
++
++ #- unless a regular expression is given, search in provides
++ foreach my $name (@$val) {
++ if ($name =~ m,^/(.*)/$,) {
++ push @regex, $1;
++ } else {
++ foreach my $pkg ($urpm-&gt;packages_providing($name)) {
++ compute_flag($urpm, $pkg, %options);
++ }
++ }
++ }
++
++ #- now search packages which fullname match given regexps
++ if (@regex) {
++ #- very costly :-(
++ foreach my $pkg (@{$urpm-&gt;{depslist}}) {
++ if (grep { $pkg-&gt;fullname =~ /$_/ } @regex) {
++ compute_flag($urpm, $pkg, %options);
++ }
++ }
++ }
++}
++
++#- side-effects: none
++sub _choose_best_pkg {
++ my ($urpm, $pkg_installed, @pkgs) = @_;
++
++ _choose_best_pkg_($urpm, $pkg_installed, grep {
++ $_-&gt;compare_pkg($pkg_installed) &gt; 0;
++ } @pkgs);
++}
++
++#- side-effects: none
++sub _choose_best_pkg_ {
++ my ($urpm, $pkg_installed, @pkgs) = @_;
++
++ my $best;
++ foreach my $pkg (grep {
++ !strict_arch($urpm) || strict_arch_check($pkg_installed, $_);
++ } @pkgs) {
++ if (!$best || ($pkg-&gt;compare_pkg($best) || $pkg-&gt;id &lt; $best-&gt;id) &gt; 0) {
++ $best = $pkg;
++ }
++ }
++ $best;
++}
++
++#- side-effects: none
++sub _choose_bests_obsolete {
++ my ($urpm, $db, $pkg_installed, @pkgs) = @_;
++
++ _set_flag_installed_and_upgrade_if_no_newer($db, $_) foreach @pkgs;
++
++ my %by_name;
++ push @{$by_name{$_-&gt;name}}, $_ foreach grep { $_-&gt;flag_upgrade } @pkgs;
++
++ map { _choose_best_pkg_($urpm, $pkg_installed, @$_) } values %by_name;
++}
++
++#- select packages to upgrade, according to package already registered.
++#- by default, only takes best package and its obsoleted and compute
++#- all installed or upgrade flag.
++#- (used for --auto-select)
++#-
++#- side-effects: $requisted, flag_installed, flag_upgrade
++sub request_packages_to_upgrade {
++ my ($urpm, $db, $state, $requested, %options) = @_;
++
++ my %by_name;
++
++ #- now we can examine all existing packages to find packages to upgrade.
++ $db-&gt;traverse(sub {
++ my ($pkg_installed) = @_;
++ my $name = $pkg_installed-&gt;name;
++ my $pkg;
++ if (exists $by_name{$name}) {
++ if (my $p = $by_name{$name}) {
++ #- here a pkg with the same name is installed twice
++ if ($p-&gt;compare_pkg($pkg_installed) &gt; 0) {
++ #- we selected $p, and it is still a valid choice
++ $pkg = $p;
++ } else {
++ #- $p is no good since $pkg_installed is higher version,
++ }
++ }
++ } elsif ($pkg = _choose_best_pkg($urpm, $pkg_installed, $urpm-&gt;packages_by_name($name))) {
++ #- first try with package using the same name.
++ $pkg-&gt;set_flag_installed;
++ $pkg-&gt;set_flag_upgrade;
++ }
++ if (my @pkgs = _choose_bests_obsolete($urpm, $db, $pkg_installed, _find_packages_obsoleting($urpm, $state, $pkg_installed))) {
++ if (@pkgs == 1) {
++ $pkg and $urpm-&gt;{debug_URPM}(&quot;auto-select: prefering &quot; . $pkgs[0]-&gt;fullname . &quot; obsoleting &quot; . $pkg_installed-&gt;fullname . &quot; over &quot; . $pkg-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ $pkg = $pkgs[0];
++ } elsif (@pkgs &gt; 1) {
++ $urpm-&gt;{debug_URPM}(&quot;auto-select: multiple packages (&quot; . join(' ', map { scalar $_-&gt;fullname } @pkgs) . &quot;) obsoleting &quot; . $pkg_installed-&gt;fullname) if $urpm-&gt;{debug_URPM};
++ $pkg = undef;
++ }
++ }
++ if ($pkg &amp;&amp; $options{idlist} &amp;&amp; !grep { $pkg-&gt;id == $_ } @{$options{idlist}}) {
++ $urpm-&gt;{debug_URPM}(&quot;not auto-selecting $pkg-&gt;fullname because it's not in search medias&quot;) if $urpm-&gt;{debug_URPM};
++ $pkg = undef;
++ }
++
++ $pkg and $urpm-&gt;{debug_URPM}(&quot;auto-select: adding &quot; . $pkg-&gt;fullname . &quot; replacing &quot; . $pkg_installed-&gt;fullname) if $urpm-&gt;{debug_URPM};
++
++ $by_name{$name} = $pkg;
++ });
++
++ foreach my $pkg (values %by_name) {
++ $pkg or next;
++ $pkg-&gt;set_flag_upgrade;
++ $requested-&gt;{$pkg-&gt;id} = $options{requested};
++ }
++
++ $requested;
++}
++
++#- side-effects: none
++sub _sort_by_dependencies_get_graph {
++ my ($urpm, $state, $l) = @_;
++ my %edges;
++ foreach my $id (@$l) {
++ my $pkg = $urpm-&gt;{depslist}[$id];
++ my @provides = map { whatrequires_id($state, $_) } $pkg-&gt;provides_nosense;
++ if (my $from = $state-&gt;{selected}{$id}{from}) {
++ unshift @provides, $from-&gt;id;
++ }
++ $edges{$id} = [ uniq(@provides) ];
++ }
++ \%edges;
++}
++
++#- side-effects: none
++sub reverse_multi_hash {
++ my ($h) = @_;
++ my %r;
++ my ($k, $v);
++ while (($k, $v) = each %$h) {
++ push @{$r{$_}}, $k foreach @$v;
++ }
++ \%r;
++}
++
++sub _merge_2_groups {
++ my ($groups, $l1, $l2) = @_;
++ my $l = [ @$l1, @$l2 ];
++ $groups-&gt;{$_} = $l foreach @$l;
++ $l;
++}
++sub _add_group {
++ my ($groups, $group) = @_;
++
++ my ($main, @other) = uniq(grep { $_ } map { $groups-&gt;{$_} } @$group);
++ $main ||= [];
++ if (@other) {
++ $main = _merge_2_groups($groups, $main, $_) foreach @other;
++ }
++ foreach (grep { !$groups-&gt;{$_} } @$group) {
++ $groups-&gt;{$_} ||= $main;
++ push @$main, $_;
++ my @l_ = uniq(@$main);
++ @l_ == @$main or die '';
++ }
++ # warn &quot;# groups: &quot;, join(' ', map { join('+', @$_) } uniq(values %$groups)), &quot;\n&quot;;
++}
++
++#- nb: this handles $nodes list not containing all $nodes that can be seen in $edges
++#-
++#- side-effects: none
++sub sort_graph {
++ my ($nodes, $edges) = @_;
++
++ #require Data::Dumper;
++ #warn Data::Dumper::Dumper($nodes, $edges);
++
++ my %nodes_h = map { $_ =&gt; 1 } @$nodes;
++ my (%loops, %added, @sorted);
++
++ my $recurse; $recurse = sub {
++ my ($id, @ids) = @_;
++# warn &quot;# recurse $id @ids\n&quot;;
++
++ my $loop_ahead;
++ foreach my $p_id (@{$edges-&gt;{$id}}) {
++ if ($p_id == $id) {
++ # don't care
++ } elsif (exists $added{$p_id}) {
++ # already done
++ } elsif (grep { $_ == $p_id } @ids) {
++ my $begin = 1;
++ my @l = grep { $begin &amp;&amp;= $_ != $p_id } @ids;
++ $loop_ahead = 1;
++ _add_group(\%loops, [ $p_id, $id, @l ]);
++ } elsif ($loops{$p_id}) {
++ my $take;
++ if (my @l = grep { $take ||= $loops{$_} &amp;&amp; $loops{$_} == $loops{$p_id} } reverse @ids) {
++ $loop_ahead = 1;
++# warn &quot;# loop to existing one $p_id, $id, @l\n&quot;;
++ _add_group(\%loops, [ $p_id, $id, @l ]);
++ }
++ } else {
++ $recurse-&gt;($p_id, $id, @ids);
++ #- we would need to compute loop_ahead. we will do it below only once, and if not already set
++ }
++ }
++ if (!$loop_ahead &amp;&amp; $loops{$id} &amp;&amp; grep { exists $loops{$_} &amp;&amp; $loops{$_} == $loops{$id} } @ids) {
++ $loop_ahead = 1;
++ }
++
++ if (!$loop_ahead) {
++ #- it's now a leaf or a loop we're done with
++ my @toadd = $loops{$id} ? @{$loops{$id}} : $id;
++ $added{$_} = undef foreach @toadd;
++# warn &quot;# adding &quot;, join('+', @toadd), &quot; for $id\n&quot;;
++ push @sorted, [ uniq(grep { $nodes_h{$_} } @toadd) ];
++ }
++ };
++ !exists $added{$_} and $recurse-&gt;($_) foreach @$nodes;
++
++# warn &quot;# result: &quot;, join(' ', map { join('+', @$_) } @sorted), &quot;\n&quot;;
++
++ check_graph_is_sorted(\@sorted, $nodes, $edges) or die &quot;sort_graph failed&quot;;
++
++ @sorted;
++}
++
++#- side-effects: none
++sub check_graph_is_sorted {
++ my ($sorted, $nodes, $edges) = @_;
++
++ my $i = 1;
++ my %nb;
++ foreach (@$sorted) {
++ $nb{$_} = $i foreach @$_;
++ $i++;
++ }
++ my $nb_errors = 0;
++ my $error = sub { $nb_errors++; warn &quot;error: $_[0]\n&quot; };
++
++ foreach my $id (@$nodes) {
++ $nb{$id} or $error-&gt;(&quot;missing $id in sort_graph list&quot;);
++ }
++ foreach my $id (keys %$edges) {
++ my $id_i = $nb{$id} or next;
++ foreach my $req (@{$edges-&gt;{$id}}) {
++ my $req_i = $nb{$req} or next;
++ $req_i &lt;= $id_i or $error-&gt;(&quot;$req should be before $id ($req_i $id_i)&quot;);
++ }
++ }
++ $nb_errors == 0;
++}
++
++
++#- side-effects: none
++sub _sort_by_dependencies__add_obsolete_edges {
++ my ($urpm, $state, $l, $requires) = @_;
++
++ my @obsoletes = grep { $_-&gt;{obsoleted} } values %{$state-&gt;{rejected}} or return;
++ my @groups = grep { @$_ &gt; 1 } map { [ keys %{$_-&gt;{closure}} ] } @obsoletes;
++ my %groups;
++ foreach my $group (@groups) {
++ _add_group(\%groups, $group);
++ foreach (@$group) {
++ my $rej = $state-&gt;{rejected}{$_} or next;
++ _add_group(\%groups, [ $_, keys %{$rej-&gt;{closure}} ]);
++ }
++ }
++
++ my %fullnames = map { scalar($urpm-&gt;{depslist}[$_]-&gt;fullname) =&gt; $_ } @$l;
++ foreach my $group (uniq(values %groups)) {
++ my @group = grep { defined $_ } map { $fullnames{$_} } @$group;
++ foreach (@group) {
++ @{$requires-&gt;{$_}} = uniq(@{$requires-&gt;{$_}}, @group);
++ }
++ }
++}
++
++#- side-effects: none
++sub sort_by_dependencies {
++ my ($urpm, $state, @list_unsorted) = @_;
++ @list_unsorted = sort { $a &lt;=&gt; $b } @list_unsorted; # sort by ids to be more reproductable
++ $urpm-&gt;{debug_URPM}(&quot;getting graph of dependencies for sorting&quot;) if $urpm-&gt;{debug_URPM};
++ my $edges = _sort_by_dependencies_get_graph($urpm, $state, \@list_unsorted);
++ my $requires = reverse_multi_hash($edges);
++
++ _sort_by_dependencies__add_obsolete_edges($urpm, $state, \@list_unsorted, $requires);
++
++ $urpm-&gt;{debug_URPM}(&quot;sorting graph of dependencies&quot;) if $urpm-&gt;{debug_URPM};
++ sort_graph(\@list_unsorted, $requires);
++}
++
++sub sorted_rpms_to_string {
++ my ($urpm, @sorted) = @_;
++
++ &quot;rpms sorted by dependencies:\n&quot; . join(&quot;\n&quot;, map {
++ join('+', _ids_to_names($urpm, @$_));
++ } @sorted);
++}
++
++#- build transaction set for given selection
++#- options: start, end, idlist, split_length, keep
++#-
++#- side-effects: $state-&gt;{transaction}, $state-&gt;{transaction_state}
++sub build_transaction_set {
++ my ($urpm, $db, $state, %options) = @_;
++
++ #- clean transaction set.
++ $state-&gt;{transaction} = [];
++
++ my %selected_id;
++ @selected_id{$urpm-&gt;build_listid($options{start}, $options{end}, $options{idlist})} = ();
++
++ if ($options{split_length}) {
++ #- first step consists of sorting packages according to dependencies.
++ my @sorted = sort_by_dependencies($urpm, $state,
++ keys(%selected_id) &gt; 0 ?
++ (grep { exists($selected_id{$_}) } keys %{$state-&gt;{selected}}) :
++ keys %{$state-&gt;{selected}});
++ $urpm-&gt;{debug_URPM}(sorted_rpms_to_string($urpm, @sorted)) if $urpm-&gt;{debug_URPM};
++
++ #- second step consists of re-applying resolve_requested in the same
++ #- order computed in first step and to update a list of packages to
++ #- install, to upgrade and to remove.
++ my %examined;
++ my @todo = @sorted;
++ while (@todo) {
++ my @ids;
++ while (@todo &amp;&amp; @ids &lt; $options{split_length}) {
++ my $l = shift @todo;
++ push @ids, @$l;
++ }
++ my %requested = map { $_ =&gt; undef } @ids;
++
++ resolve_requested__no_suggests_($urpm,
++ $db, $state-&gt;{transaction_state} ||= {},
++ \%requested,
++ defined $options{start} ? (start =&gt; $options{start}) : @{[]},
++ defined $options{end} ? (end =&gt; $options{end}) : @{[]},
++ keep =&gt; $options{keep},
++ );
++
++ my @upgrade = grep { ! exists $examined{$_} } keys %{$state-&gt;{transaction_state}{selected}};
++ my @remove = grep { ! exists $examined{$_} } packages_to_remove($state-&gt;{transaction_state});
++
++ @upgrade || @remove or next;
++
++ if (my @bad_remove = grep { !$state-&gt;{rejected}{$_}{removed} || $state-&gt;{rejected}{$_}{obsoleted} } @remove) {
++ $urpm-&gt;{error}(sorted_rpms_to_string($urpm, @sorted)) if $urpm-&gt;{error};
++ $urpm-&gt;{error}('transaction is too small: ' . join(' ', @bad_remove) . ' is rejected but it should not (current transaction: ' . join(' ', _ids_to_fullnames($urpm, @upgrade)) . ', requested: ' . join('+', _ids_to_fullnames($urpm, @ids)) . ')') if $urpm-&gt;{error};
++ $state-&gt;{transaction} = [];
++ last;
++ }
++
++ $urpm-&gt;{debug_URPM}(sprintf('transaction valid: remove=%s update=%s',
++ join(',', @remove),
++ join(',', _ids_to_names($urpm, @upgrade)))) if $urpm-&gt;{debug_URPM};
++
++ $examined{$_} = undef foreach @upgrade, @remove;
++ push @{$state-&gt;{transaction}}, { upgrade =&gt; \@upgrade, remove =&gt; \@remove };
++ }
++
++ #- check that the transaction set has been correctly created.
++ #- (ie that no other package was removed)
++ if (keys(%{$state-&gt;{selected}}) == keys(%{$state-&gt;{transaction_state}{selected}}) &amp;&amp;
++ listlength(packages_to_remove($state)) == listlength(packages_to_remove($state-&gt;{transaction_state}))
++ ) {
++ foreach (keys(%{$state-&gt;{selected}})) {
++ exists $state-&gt;{transaction_state}{selected}{$_} and next;
++ $urpm-&gt;{error}('using one big transaction') if $urpm-&gt;{error};
++ $state-&gt;{transaction} = []; last;
++ }
++ foreach (packages_to_remove($state)) {
++ $state-&gt;{transaction_state}{rejected}{$_}{removed} &amp;&amp;
++ !$state-&gt;{transaction_state}{rejected}{$_}{obsoleted} and next;
++ $urpm-&gt;{error}('using one big transaction') if $urpm-&gt;{error};
++ $state-&gt;{transaction} = []; last;
++ }
++ }
++ }
++
++ #- fallback if something can be selected but nothing has been allowed in transaction list.
++ if (%{$state-&gt;{selected} || {}} &amp;&amp; !@{$state-&gt;{transaction}}) {
++ $urpm-&gt;{debug_URPM}('using one big transaction') if $urpm-&gt;{debug_URPM};
++ push @{$state-&gt;{transaction}}, {
++ upgrade =&gt; [ keys %{$state-&gt;{selected}} ],
++ remove =&gt; [ packages_to_remove($state) ],
++ };
++ }
++
++ if ($state-&gt;{orphans_to_remove}) {
++ my @l = map { scalar $_-&gt;fullname } @{$state-&gt;{orphans_to_remove}};
++ push @{$state-&gt;{transaction}}, { remove =&gt; \@l };
++ }
++
++ $state-&gt;{transaction};
++}
++
++1;
+
+Added: rpm/perl-URPM/trunk/URPM/Signature.pm
+===================================================================
+--- rpm/perl-URPM/trunk/URPM/Signature.pm (rev 0)
++++ rpm/perl-URPM/trunk/URPM/Signature.pm 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,91 @@
++package URPM;
++
++use strict;
++use warnings;
++
++#- parse from rpmlib db.
++#-
++#- side-effects: $urpm
++sub parse_pubkeys {
++ my ($urpm, %options) = @_;
++
++ my $db = $options{db};
++ $db ||= URPM::DB::open($options{root}) or die &quot;Can't open RPM DB, aborting\n&quot;;
++ my @keys = parse_pubkeys_($db);
++
++ $urpm-&gt;{keys}{$_-&gt;{id}} = $_ foreach @keys;
++}
++
++#- side-effects: none
++sub parse_pubkeys_ {
++ my ($db) = @_;
++
++ my ($block, $content);
++ my %keys;
++
++ $db-&gt;traverse_tag('name', [ 'gpg-pubkey' ], sub {
++ my ($p) = @_;
++ # the first blank separates the PEM headers from key data, this
++ # flags we found it:
++ my $found_blank = 0;
++ foreach (split &quot;\n&quot;, $p-&gt;description) {
++ if ($block) {
++ if (/^$/ and not $found_blank) {
++ # All content until now were the encapsulated pem
++ # headers...
++ $content = '';
++ $found_blank = 1;
++ }
++ elsif (/^-----END PGP PUBLIC KEY BLOCK-----$/) {
++ $keys{$p-&gt;version} = {
++ $p-&gt;summary =~ /^gpg\((.*)\)$/ ? (name =&gt; $1) : @{[]},
++ id =&gt; $p-&gt;version,
++ content =&gt; $content,
++ block =&gt; $p-&gt;description,
++ };
++ $block = undef;
++ $content = '';
++ }
++ else {
++ $content .= $_;
++ }
++ }
++ $block ||= /^-----BEGIN PGP PUBLIC KEY BLOCK-----$/;
++ }
++ });
++
++ values %keys;
++}
++
++#- obsoleted
++sub import_needed_pubkeys {
++ warn &quot;import_needed_pubkeys prototype has changed, please give a file directly\n&quot;;
++ return;
++}
++
++#- import pubkeys only if it is needed.
++sub import_needed_pubkeys_from_file {
++ my ($db, $pubkey_file, $o_callback) = @_;
++
++ my @keys = parse_pubkeys_($db);
++
++ my $keyid = substr get_gpg_fingerprint($pubkey_file), 8;
++ my ($kv) = grep { (hex($keyid) == hex($_-&gt;{id})) } @keys;
++ my $imported;
++ if (!$kv) {
++ if (!import_pubkey_file($db, $pubkey_file)) {
++ #$urpm-&gt;{debug_URPM}(&quot;Couldn't import public key from &quot;.$pubkey_file) if $urpm-&gt;{debug_URPM};
++ $imported = 0;
++ } else {
++ $imported = 1;
++ }
++ @keys = parse_pubkeys_($db);
++ ($kv) = grep { (hex($keyid) == hex($_-&gt;{id})) } @keys;
++ }
++
++ #- let the caller know about what has been found.
++ #- this is an error if the key is not found.
++ $o_callback and $o_callback-&gt;($kv?$kv-&gt;{id}:undef, $imported);
++}
++
++1;
+
+Added: rpm/perl-URPM/trunk/URPM.pm
+===================================================================
+--- rpm/perl-URPM/trunk/URPM.pm (rev 0)
++++ rpm/perl-URPM/trunk/URPM.pm 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,879 @@
++package URPM;
++
++use strict;
++use warnings;
++use DynaLoader;
++
++# different files, but same package
++# require them here to avoid dependencies
++use URPM::Build;
++use URPM::Resolve;
++use URPM::Signature;
++
++our @ISA = qw(DynaLoader);
++our $VERSION = '3.38';
++
++URPM-&gt;bootstrap($VERSION);
++
++sub new {
++ my ($class, %options) = @_;
++ my $self = bless {
++ depslist =&gt; [],
++ provides =&gt; {},
++ obsoletes =&gt; {},
++ }, $class;
++ $self-&gt;{nofatal} = 1 if $options{nofatal};
++ $self;
++}
++
++sub set_nofatal { $_[0]{nofatal} = $_[1] }
++
++sub packages_providing {
++ my ($urpm, $name) = @_;
++ grep { $_ } map { $urpm-&gt;{depslist}[$_] } keys %{$urpm-&gt;{provides}{$name} || {}};
++}
++
++sub packages_obsoleting {
++ my ($urpm, $name) = @_;
++ map { $urpm-&gt;{depslist}[$_] } keys %{$urpm-&gt;{obsoletes}{$name} || {}};
++}
++
++sub packages_by_name {
++ my ($urpm, $name) = @_;
++ grep { $name eq $_-&gt;name } packages_providing($urpm, $name);
++}
++
++sub search {
++ my ($urpm, $name, %options) = @_;
++ my $best;
++
++ #- tries other alternative if no strict searching.
++ unless ($options{strict_name}) {
++ if ($name =~ /^(.*)-([^\-]*)-([^\-]*)\.([^\.\-]*)$/) {
++ foreach my $pkg (packages_providing($urpm, $1)) {
++ $pkg-&gt;fullname eq $name and return $pkg;
++ }
++ }
++ unless ($options{strict_fullname}) {
++ if ($name =~ /^(.*)-([^\-]*)-([^\-]*)$/) {
++ foreach my $pkg (packages_providing($urpm, $1)) {
++ my ($n, $v, $r, $a) = $pkg-&gt;fullname;
++ $options{src} &amp;&amp; $a eq 'src' || $pkg-&gt;is_arch_compat or next;
++ &quot;$n-$v-$r&quot; eq $name or next;
++ !$best || $pkg-&gt;compare_pkg($best) &gt; 0 and $best = $pkg;
++ }
++ $best and return $best;
++ }
++ if ($name =~ /^(.*)-([^\-]*)$/) {
++ foreach my $pkg (packages_providing($urpm, $1)) {
++ my ($n, $v, undef, $a) = $pkg-&gt;fullname;
++ $options{src} &amp;&amp; $a eq 'src' || $pkg-&gt;is_arch_compat or next;
++ &quot;$n-$v&quot; eq $name or next;
++ !$best || $pkg-&gt;compare_pkg($best) &gt; 0 and $best = $pkg;
++ }
++ $best and return $best;
++ }
++ }
++ }
++
++ unless ($options{strict_fullname}) {
++ foreach my $pkg (packages_providing($urpm, $name)) {
++ my ($n, undef, undef, $a) = $pkg-&gt;fullname;
++ $options{src} &amp;&amp; $a eq 'src' || $pkg-&gt;is_arch_compat or next;
++ $n eq $name or next;
++ !$best || $pkg-&gt;compare_pkg($best) &gt; 0 and $best = $pkg;
++ }
++ }
++
++ return $best;
++}
++
++#- Olivier Thauvin:
++#- Returns @$listid, $start .. $end or the whole deplist id
++#- according to the given args
++sub build_listid {
++ my ($urpm, $start, $end, $listid) = @_;
++
++ @{$listid || []} &gt; 0 ? @$listid :
++ (($start || 0) .. (defined($end) ? $end : $#{$urpm-&gt;{depslist}}));
++}
++
++#- this is used when faking a URPM::DB: $urpm can be used as-a $db
++#- (used for urpmi --env)
++sub traverse {
++ my ($urpm, $callback) = @_;
++
++ if ($callback) {
++ foreach my $p (@{$urpm-&gt;{depslist} || []}) {
++ $callback-&gt;($p);
++ }
++ }
++
++ scalar @{$urpm-&gt;{depslist} || []};
++}
++
++
++#- this is used when faking a URPM::DB: $urpm can be used as-a $db
++#- (used for urpmi --env)
++sub traverse_tag {
++ my ($urpm, $tag, $names, $callback) = @_;
++ my $count = 0;
++ my %names;
++
++ if (@{$names || []}) {
++ if ($tag eq 'name') {
++ foreach my $n (@$names) {
++ foreach my $p (packages_providing($urpm, $n)) {
++ $p-&gt;name eq $n or next;
++ $callback and $callback-&gt;($p);
++ ++$count;
++ }
++ }
++ } elsif ($tag eq 'whatprovides') {
++ foreach (@$names) {
++ foreach (keys %{$urpm-&gt;{provides}{$_} || {}}) {
++ $callback and $callback-&gt;($urpm-&gt;{depslist}[$_]);
++ ++$count;
++ }
++ }
++ } else {
++ @names{@$names} = ();
++ if ($tag eq 'whatrequires') {
++ foreach (@{$urpm-&gt;{depslist} || []}) {
++ if (grep { exists $names{$_} } $_-&gt;requires_nosense) {
++ $callback and $callback-&gt;($_);
++ ++$count;
++ }
++ }
++ } elsif ($tag eq 'whatconflicts') {
++ foreach (@{$urpm-&gt;{depslist} || []}) {
++ if (grep { exists $names{$_} } $_-&gt;conflicts_nosense) {
++ $callback and $callback-&gt;($_);
++ ++$count;
++ }
++ }
++ } elsif ($tag eq 'group') {
++ foreach (@{$urpm-&gt;{depslist} || []}) {
++ if (exists $names{$_-&gt;group}) {
++ $callback and $callback-&gt;($_);
++ ++$count;
++ }
++ }
++ } elsif ($tag eq 'triggeredby' || $tag eq 'path') {
++ foreach (@{$urpm-&gt;{depslist} || []}) {
++ if (grep { exists $names{$_} } $_-&gt;files, grep { m!^/! } $_-&gt;provides_nosense) {
++ $callback and $callback-&gt;($_);
++ ++$count;
++ }
++ }
++ } else {
++ die &quot;unknown tag&quot;;
++ }
++ }
++ }
++
++ $count;
++}
++
++# wrapper around XS functions
++# it handles error cases
++sub _parse_hdlist_or_synthesis {
++ my ($parse_func, $urpm, $file, %options) = @_;
++
++ my $previous_indice = @{$urpm-&gt;{depslist}};
++ if (my ($start, $end) = $parse_func-&gt;($urpm, $file, %options)) {
++ ($start, $end);
++ } elsif (!$options{callback}) {
++ #- parse_hdlist__XS may have added some pkgs to {depslist},
++ #- but we don't want those pkgs since reading hdlist failed later.
++ #- so we need to drop them
++ #- FIXME: {provides} would need to be reverted too!
++ splice(@{$urpm-&gt;{depslist}}, $previous_indice);
++ ();
++ } else {
++ #- we need to keep them since the callback has been used
++ #- and we can't pretend we didn't parse anything
++ #- (needed for genhdlist2)
++ ();
++ }
++}
++sub parse_synthesis { _parse_hdlist_or_synthesis(\&amp;parse_synthesis__XS, @_) }
++sub parse_hdlist { _parse_hdlist_or_synthesis(\&amp;parse_hdlist__XS, @_) }
++
++sub add_macro {
++ my ($s) = @_;
++ #- quote for rpmlib, *sigh*
++ $s =~ s/\n/\\\n/g;
++ add_macro_noexpand($s);
++}
++
++package URPM::Package;
++our @ISA = qw(); # help perl_checker
++
++#- debug help for urpmi
++sub dump_flags {
++ my ($pkg) = @_;
++ &lt;&lt;EODUMP;
++available: ${\($pkg-&gt;flag_available)}
++base: ${\($pkg-&gt;flag_base)}
++disable_obsolete: ${\($pkg-&gt;flag_disable_obsolete)}
++installed: ${\($pkg-&gt;flag_installed)}
++requested: ${\($pkg-&gt;flag_requested)}
++required: ${\($pkg-&gt;flag_required)}
++selected: ${\($pkg-&gt;flag_selected)}
++skip: ${\($pkg-&gt;flag_skip)}
++upgrade: ${\($pkg-&gt;flag_upgrade)}
++EODUMP
++}
++
++my %arch_cache;
++sub is_arch_compat {
++ my ($pkg) = @_;
++ my $arch = $pkg-&gt;arch;
++ exists $arch_cache{$arch} and return $arch_cache{$arch};
++
++ $arch_cache{$arch} = is_arch_compat__XS($pkg);
++}
++
++sub changelogs {
++ my ($pkg) = @_;
++
++ my @ti = $pkg-&gt;changelog_time or return;
++ my @na = $pkg-&gt;changelog_name or return;
++ my @tx = $pkg-&gt;changelog_text or return;
++ map {
++ { time =&gt; $ti[$_], name =&gt; $na[$_], text =&gt; $tx[$_] };
++ } 0 .. $#ti;
++}
++
++package URPM::Transaction;
++our @ISA = qw(); # help perl_checker
++
++package URPM::DB;
++our @ISA = qw(); # help perl_checker
++
++1;
++
++__END__
++
++=head1 NAME
++
++URPM - Manipulate RPM files and headers
++
++=head1 SYNOPSIS
++
++ use URPM;
++
++ # using the local RPM database
++ my $db = URPM::DB::open();
++ $db-&gt;traverse(sub {
++ my ($package) = @_; # this is a URPM::Package object
++ print $package-&gt;name, &quot;\n&quot;;
++ # ...
++ });
++
++ # loading and parsing a synthesis file
++ my $urpm = new URPM;
++ $urpm-&gt;parse_synthesis(&quot;synthesis.sample.cz&quot;);
++ $urpm-&gt;traverse(sub {
++ # retrieve all packages from the dependency list
++ # ...
++ });
++
++=head1 DESCRIPTION
++
++The URPM module allows you to manipulate RPM files, RPM header files and
++hdlist files and manage them in memory. It is notably used by the C&lt;urpmi&gt;
++utility. It provides four classes : C&lt;URPM&gt;, C&lt;URPM::DB&gt;, C&lt;URPM::Package&gt;,
++and C&lt;URPM::Transaction&gt;.
++
++=head2 The URPM class
++
++=over 4
++
++=item URPM-&gt;new()
++
++The constructor creates a new, empty URPM object. It's a blessed hash that
++contains two fields:
++
++B&lt;depslist&gt; is an arrayref containing the list of depending packages (which are
++C&lt;URPM::Package&gt; objects).
++
++B&lt;provides&gt; is an hashref containing as keys the list of property names
++provided by the URPM object. The associated value is true if the property is
++versioned.
++
++If the constructor is called with the arguments C&lt;&lt; nofatal =&gt; 1 &gt;&gt;, various
++fatal error messages are suppressed (file not found in parse_hdlist() and
++parse_synthesis()).
++
++=item URPM::read_config_files()
++
++Force the re-reading of the RPM configuration files.
++
++=item URPM::ranges_overlap($range1, $range2 [, $nopromoteepoch])
++
++This utility function compares two version ranges, in order to calculate
++dependencies properly. The ranges have roughly the form
++
++ [&lt;|&lt;=|==|=&gt;|&gt;] [epoch:]version[-release]
++
++where epoch, version and release are RPM-style version numbers.
++
++If the optional parameter $nopromoteepoch is true, and if the 2nd range has no
++epoch while the first one has one, then the 2nd range is assumed to have an
++epoch C&lt;== 0&gt;.
++
++B&lt;Warning&gt;: $nopromoteepoch actually defaults to 1, so if you're going to
++pass a variable, make sure undef is treated like 1, not 0.
++
++=item $urpm-&gt;parse_synthesis($file [, callback =&gt; sub {...} ])
++
++This method gets the B&lt;depslist&gt; and the B&lt;provides&gt; from a synthesis file
++and adds them to the URPM object.
++
++=item $urpm-&gt;parse_hdlist($file, %options)
++
++This method loads rpm informations from rpm headers contained in an hdlist
++file and adds them to the URPM object. Allowed options are
++
++ packing =&gt; 0 / 1
++ callback =&gt; sub { ... }
++ keep_all_tags =&gt; 0 / 1
++
++The return value is a two-element array containing the first and the last id
++parsed.
++
++=item $urpm-&gt;parse_rpm($file, %options)
++
++This method gets the B&lt;depslist&gt; and the B&lt;provides&gt; from an RPM file
++and adds them to the URPM object. Allowed options are
++
++ packing =&gt; 0 / 1
++ keep_all_tags =&gt; 0 / 1
++ callback =&gt; sub { ... }
++
++If C&lt;keep_all_tags&gt; isn't specified, URPM will drop all memory-consuming tags
++(notably changelogs, filelists, scriptlets).
++
++=item $urpm-&gt;packages_providing($name)
++
++Returns a list of C&lt;URPM::Package&gt; providing &lt;$name&gt;
++
++=item $urpm-&gt;packages_by_name($name)
++
++Returns a list of C&lt;URPM::Package&gt; corresponding to the wanted &lt;$name&gt;
++
++=item $urpm-&gt;search($name, %options)
++
++Search an RPM by name or by part of name in the list of RPMs represented by
++this $urpm. The behaviour of the search is influenced by several options:
++
++ strict_name =&gt; 0 / 1
++ strict_fullname =&gt; 0 / 1
++ src =&gt; 0 / 1
++
++=item $urpm-&gt;traverse($callback)
++
++Executes the callback for each package in the depslist, passing a
++C&lt;URPM::Package&gt; object as argument the callback.
++
++This is used when faking a URPM::DB: $urpm can be used as-a $db
++
++=item $urpm-&gt;traverse_tag($tag, $names, $callback)
++
++$tag may be one of C&lt;name&gt;, C&lt;whatprovides&gt;, C&lt;whatrequires&gt;, C&lt;whatconflicts&gt;,
++C&lt;group&gt;, C&lt;triggeredby&gt;, or C&lt;path&gt;.
++$names is a reference to an array, holding the acceptable values of the said
++tag for the searched variables.
++Then, $callback is called for each matching package in the depslist.
++
++This is used when faking a URPM::DB: $urpm can be used as-a $db
++
++=item URPM::verify_rpm($file, %options)
++
++Verifies an RPM file.
++Returns 0 on failure, 1 on success.
++Recognized options are:
++
++ nodigests =&gt; 0 / 1
++ nosignatures =&gt; 0 / 1
++
++=item URPM::verify_signature($file)
++
++Verifies the signature of an RPM file. Returns a string that will contain &quot;OK&quot;
++or &quot;NOT OK&quot; as well as a description of the found key (if successful) or of the
++error (if signature verification failed.)
++
++=item $urpm-&gt;import_pubkey(%options)
++
++Imports a key in the RPM database.
++
++ db =&gt; $urpm_db
++ root =&gt; '...'
++ block =&gt; '...'
++ filename =&gt; '...'
++
++=item URPM::spec2srcheader($specfile)
++
++Returns a URPM::Package object containing the header of the source rpm produced
++by the evaluation of the specfile whose path is given as argument. All
++dependencies stored in this header are exactly the one needed to build the
++specfile.
++
++=back
++
++=head2 The URPM::DB class
++
++=over 4
++
++=item open($prefix, $write_perm)
++
++Returns a new C&lt;URPM::DB&gt; object pointing on the local RPM database (or
++C&lt;undef&gt; on failure).
++
++$prefix defaults to C&lt;&quot;&quot;&gt; and indicates the RPM DB root directory prefix if
++any. (See the B&lt;--root&gt; option to rpm(1)).
++
++$write_perm is a boolean that defaults to false, and that indicates whether
++the RPM DB should be open in read/write mode.
++
++=item rebuild($prefix)
++
++Rebuilds the RPM database (like C&lt;rpm --rebuilddb&gt;). $prefix defaults to C&lt;&quot;&quot;&gt;.
++
++=item $db-&gt;traverse($callback)
++
++Executes the specified callback (a code reference) for each package
++in the DB, passing a C&lt;URPM::Package&gt; object as argument the callback.
++
++=item $db-&gt;traverse_tag($tag,$names,$callback)
++
++$tag may be one of C&lt;name&gt;, C&lt;whatprovides&gt;, C&lt;whatrequires&gt;, C&lt;whatconflicts&gt;,
++C&lt;group&gt;, C&lt;triggeredby&gt;, or C&lt;path&gt;.
++$names is a reference to an array, holding the acceptable values of the said
++tag for the searched variables.
++Then, $callback is called for each matching package in the DB.
++
++=item $db-&gt;traverse_tag_find($tag,$name,$callback)
++
++Quite similar to C&lt;traverse_tag&gt;, but stops when $callback returns true.
++
++(also note that only one $name is handled)
++
++=item $db-&gt;create_transaction($prefix)
++
++Creates and returns a new transaction (an C&lt;URPM::Transaction&gt; object) on the
++specified DB. For $prefix, cf L&lt;open&gt;.
++
++=back
++
++=head2 The URPM::Package class
++
++Most methods of C&lt;URPM::Package&gt; are accessors for the various properties
++of an RPM package.
++
++=over 4
++
++=item $package-&gt;arch()
++
++Gives the package architecture
++
++=item $package-&gt;build_header($fileno)
++
++Writes the rpm header to the specified file ($fileno being an integer).
++
++=item $package-&gt;build_info($fileno, [$provides_files])
++
++Writes a line of information in a synthesis file.
++
++=item $package-&gt;buildarchs()
++
++=item $package-&gt;buildhost()
++
++=item $package-&gt;buildtime()
++
++=item $package-&gt;changelog_name()
++
++=item $package-&gt;changelog_text()
++
++=item $package-&gt;changelog_time()
++
++=item $package-&gt;compare($evr)
++
++=item $package-&gt;compare_pkg($other_pkg)
++
++=item $package-&gt;conf_files()
++
++=item $package-&gt;conflicts()
++
++=item $package-&gt;conflicts_nosense()
++
++=item $package-&gt;description()
++
++=item $package-&gt;dirnames()
++
++=item $package-&gt;distribution()
++
++=item $package-&gt;epoch()
++
++=item $package-&gt;excludearchs()
++
++=item $package-&gt;exclusivearchs()
++
++=item $package-&gt;filelinktos()
++
++=item $package-&gt;files()
++
++List of files in this rpm.
++
++=item $package-&gt;files_flags()
++
++=item $package-&gt;files_gid()
++
++=item $package-&gt;files_group()
++
++=item $package-&gt;files_md5sum()
++
++=item $package-&gt;files_mode()
++
++=item $package-&gt;files_mtime()
++
++=item $package-&gt;files_owner()
++
++=item $package-&gt;files_size()
++
++=item $package-&gt;files_uid()
++
++=item $package-&gt;flag($name)
++
++=item $package-&gt;flag_available()
++
++=item $package-&gt;flag_base()
++
++=item $package-&gt;flag_disable_obsolete()
++
++=item $package-&gt;flag_installed()
++
++=item $package-&gt;flag_requested()
++
++=item $package-&gt;flag_required()
++
++=item $package-&gt;flag_selected()
++
++=item $package-&gt;flag_skip()
++
++=item $package-&gt;flag_upgrade()
++
++=item $package-&gt;free_header()
++
++=item $package-&gt;fullname()
++
++Returns a 4 element list: name, version, release and architecture in an array
++context. Returns a string NAME-VERSION-RELEASE.ARCH in scalar context.
++
++=item $package-&gt;get_tag($tagid)
++
++Returns an array containing values of $tagid. $tagid is the numerical value of
++rpm tags. See rpmlib.h.
++
++=item $package-&gt;queryformat($format)
++
++Querying the package like rpm --queryformat do.
++
++The function calls directly the rpmlib, then use header informations, so it
++silently failed if you use synthesis instead of hdlist/rpm/header files or rpmdb.
++
++=item $package-&gt;get_tag_modifiers($tagid)
++
++Return an array of human readable view of tag values. $tagid is the numerical value of rpm tags.
++
++=item $package-&gt;group()
++
++=item $package-&gt;id()
++
++=item $package-&gt;installtid()
++
++=item $package-&gt;is_arch_compat()
++
++Returns whether this package is compatible with the current machine's
++architecture. 0 means not compatible. The lower the result is, the preferred
++the package is.
++
++=item $package-&gt;is_platform_compat()
++
++Return whether this package is compatible with the current machine's
++platform configuration (/etc/rpm/platform). 0 mean not compatible.
++The lower the result is the preferred the package is.
++
++=item $package-&gt;license()
++
++=item $package-&gt;name()
++
++The rpm's bare name.
++
++=item $package-&gt;obsoletes()
++
++=item $package-&gt;obsoletes_nosense()
++
++=item $package-&gt;obsoletes_overlap($s, [$nopromoteepoch, [$direction] ])
++
++=item $package-&gt;os()
++
++=item $package-&gt;pack_header()
++
++=item $package-&gt;packager()
++
++=item $package-&gt;payload_format()
++
++=item $package-&gt;provides()
++
++=item $package-&gt;provides_nosense()
++
++=item $package-&gt;provides_overlap($s, [$nopromoteepoch,] [$direction])
++
++=item $package-&gt;rate()
++
++=item $package-&gt;release()
++
++=item $package-&gt;requires()
++
++=item $package-&gt;requires_nosense()
++
++=item $package-&gt;rflags()
++
++=item $package-&gt;filesize()
++
++Size of the rpm file (ie the rpm header + cpio body)
++
++=item $package-&gt;set_flag($name, $value)
++
++=item $package-&gt;set_flag_base($value)
++
++=item $package-&gt;set_flag_disable_obsolete($value)
++
++=item $package-&gt;set_flag_installed($value)
++
++=item $package-&gt;set_flag_requested($value)
++
++=item $package-&gt;set_flag_required($value)
++
++=item $package-&gt;set_flag_skip($value)
++
++=item $package-&gt;set_flag_upgrade($value)
++
++=item $package-&gt;set_id($id)
++
++=item $package-&gt;set_rate($rate)
++
++=item $package-&gt;set_rflags(...)
++
++=item $package-&gt;size()
++
++=item $package-&gt;sourcerpm()
++
++=item $package-&gt;summary()
++
++=item $package-&gt;update_header($filename, ...)
++
++=item $package-&gt;url()
++
++=item $package-&gt;vendor()
++
++=item $package-&gt;version()
++
++=back
++
++=head2 The URPM::Transaction class
++
++=over 4
++
++=item $trans-&gt;set_script_fd($fileno)
++
++Sets the transaction output filehandle.
++
++=item $trans-&gt;add($pkg, %options)
++
++Adds a package to be installed to the transaction represented by $trans.
++$pkg is an C&lt;URPM::Package&gt; object.
++
++Options are:
++
++ update =&gt; 0 / 1 : indicates whether this is an upgrade
++ excludepath =&gt; [ ... ]
++
++=item $trans-&gt;remove($name)
++
++Adds a package to be erased to the transaction represented by $trans.
++$name is the name of the package.
++
++=item $trans-&gt;check(%options)
++
++Checks that all dependencies can be resolved in this transaction.
++
++Options are:
++
++ translate_message =&gt; 0 / 1 (currently ignored.)
++
++In list context, returns an array of problems (an empty array indicates
++success).
++
++=item $trans-&gt;order()
++
++Determines package order in a transaction set according to dependencies. In
++list context, returns an array of problems (an empty array indicates success).
++
++=item $trans-&gt;run($data, %options)
++
++Runs the transaction.
++
++$data is an arbitrary user-provided piece of data to be passed to callbacks.
++
++Recognized options are:
++
++ callback_close =&gt; sub { ... }
++ callback_inst =&gt; sub { ... }
++ callback_open =&gt; sub { ... }
++ callback_trans =&gt; sub { ... }
++ callback_uninst =&gt; sub { ... }
++ delta =&gt; used for progress callbacks (trans, uninst, inst)
++ excludedocs =&gt; 0 / 1
++ force =&gt; 0 / 1
++ ignorearch =&gt; 0 / 1
++ nosize =&gt; 0 / 1
++ noscripts =&gt; 0 / 1
++ oldpackage =&gt; 0 / 1
++ repackage =&gt; 0 / 1
++ test =&gt; 0 / 1
++ translate_message =&gt; 1
++
++They roughly correspond to command-line options to rpm(1).
++
++=item $trans-&gt;traverse($callback)
++
++Executes the specified callback (a code reference) for each package in the
++transaction, passing a C&lt;URPM::Package&gt; object as argument the callback.
++
++=back
++
++=head2 Macro handling functions
++
++=over
++
++=item loadmacrosfile($filename)
++
++Load the specified macro file. Sets $! if the file can't be read.
++
++=item expand($name)
++
++Expands the specified macro.
++
++=item add_macro($macro_definition)
++
++=item add_macro_noexpand($macro_definition)
++
++Define a macro. For example,
++
++ URPM::add_macro(&quot;vendor Mageia&quot;);
++ my $vendor = URPM::expand(&quot;%vendor&quot;);
++
++The 'noexpand' version doesn't expand literal newline characters in the
++macro definition.
++
++=item del_macro($name)
++
++Delete a macro.
++
++=item resetmacros()
++
++Destroys macros.
++
++=item setVerbosity($level)
++
++Sets rpm verbosity level. $level is an integer between 2 (RPMMESS_CRIT) and 7
++(RPMMESS_DEBUG).
++
++=item rpmErrorString()
++
++=item rpmErrorWriteTo($fd)
++
++=item platformscore($platform)
++
++Return the score of $platform according computer's configuration.
++0 mean not compatible, lower is prefered.
++
++=item archscore($arch)
++
++Return the score of the given arch. 0 mean not compatible,
++lower is prefered.
++
++=item osscore($os)
++
++Return the score of the given os. 0 mean not compatible,
++lower is prefered.
++
++=back
++
++=head2 The $state object
++
++It has the following fields:
++
++B&lt;backtrack&gt;: {
++ selected =&gt; { id =&gt; undef },
++ deadlock =&gt; { id|property =&gt; undef },
++ }
++
++B&lt;cached_installed&gt;: { property_name =&gt; { fullname =&gt; undef } }
++
++B&lt;oldpackage&gt;: int
++ # will be passed to $trans-&gt;run to set RPMPROB_FILTER_OLDPACKAGE
++
++B&lt;selected&gt;: { id =&gt; {
++ requested =&gt; bool, install =&gt; bool,
++ from =&gt; pkg, psel =&gt; pkg,
++ promote =&gt; name, unsatisfied =&gt; [ id|property ]
++ } }
++
++B&lt;rejected&gt;: { fullname =&gt; {
++ size =&gt; int, removed =&gt; { fullname|&quot;asked&quot; =&gt; undef },
++ obsoleted =&gt; { fullname|&quot;asked&quot; =&gt; undef },
++ backtrack =&gt; { # those info are only used to display why package is unselected
++ promote =&gt; [ name ], keep =&gt; [ fullname ],
++ unsatisfied =&gt; [ id|property ],
++ conflicts =&gt; [ fullname ],
++ },
++ closure =&gt; { fullname =&gt; { old_requested =&gt; bool,
++ unsatisfied =&gt; [ id|property ],
++ conflicts =&gt; property },
++ avoid =&gt; bool },
++ },
++ } }
++
++B&lt;rejected_already_installed&gt;: { id =&gt; pkg }
++
++B&lt;orphans_to_remove&gt;: [ pkg ]
++
++B&lt;whatrequires&gt;: { name =&gt; { id =&gt; undef } }
++ # reversed requires_nosense for selected packages
++
++B&lt;unselected_uninstalled&gt;: [ pkg ]
++ # (old) packages which are needed, but installed package is newer
++
++more fields only used in build_transaction_set and its callers):
++
++B&lt;transaction&gt;: [ { upgrade =&gt; [ id ], remove =&gt; [ fullname ] } ]
++
++B&lt;transaction_state&gt;: $state object
++
++=head1 COPYRIGHT
++
++Copyright 2002, 2003, 2004, 2005 MandrakeSoft SA
++
++Copyright 2005, 2006, 2007, 2008 Mandriva SA
++
++FranE&lt;ccedil&gt;ois Pons (original author), Rafael Garcia-Suarez, Pixel &lt;<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">pixel at mandriva.com</A>&gt; (current maintainer)
++
++This library is free software; you can redistribute it and/or modify it under
++the same terms as Perl itself.
++
++=cut
+
+Added: rpm/perl-URPM/trunk/URPM.xs
+===================================================================
+--- rpm/perl-URPM/trunk/URPM.xs (rev 0)
++++ rpm/perl-URPM/trunk/URPM.xs 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,3995 @@
++/* Copyright (c) 2002, 2003, 2004, 2005 MandrakeSoft SA
++ * Copyright (c) 2005, 2006, 2007, 2008 Mandriva SA
++ *
++ * All rights reserved.
++ * This program is free software; you can redistribute it and/or
++ * modify it under the same terms as Perl itself.
++ *
++ * $Id: URPM.xs 259125 2009-08-10 14:37:07Z cfergeau $
++ *
++ */
++#include &quot;EXTERN.h&quot;
++#include &quot;perl.h&quot;
++#include &quot;XSUB.h&quot;
++
++#include &lt;sys/utsname.h&gt;
++#include &lt;sys/select.h&gt;
++#include &lt;sys/time.h&gt;
++#include &lt;sys/types.h&gt;
++#include &lt;sys/stat.h&gt;
++#include &lt;sys/wait.h&gt;
++#include &lt;fcntl.h&gt;
++#include &lt;unistd.h&gt;
++#include &lt;zlib.h&gt;
++#include &lt;libintl.h&gt;
++
++#undef Fflush
++#undef Mkdir
++#undef Stat
++#undef Fstat
++
++#ifdef RPM_ORG
++static inline void *_free(const void * p) {
++ if (p != NULL) free((void *)p);
++ return NULL;
++}
++typedef struct rpmSpec_s * Spec;
++#else
++#include &lt;rpm/rpm46compat.h&gt;
++#endif
++
++#include &lt;rpm/rpmio.h&gt;
++#include &lt;rpm/rpmdb.h&gt;
++#include &lt;rpm/rpmts.h&gt;
++#include &lt;rpm/rpmte.h&gt;
++#include &lt;rpm/rpmps.h&gt;
++#include &lt;rpm/rpmpgp.h&gt;
++#include &lt;rpm/rpmcli.h&gt;
++#include &lt;rpm/rpmbuild.h&gt;
++#include &lt;rpm/rpmlog.h&gt;
++
++struct s_Package {
++ char *info;
++ int filesize;
++ char *requires;
++ char *suggests;
++ char *obsoletes;
++ char *conflicts;
++ char *provides;
++ char *rflags;
++ char *summary;
++ unsigned flag;
++ Header h;
++};
++
++struct s_Transaction {
++ rpmts ts;
++ int count;
++};
++
++struct s_TransactionData {
++ SV* callback_open;
++ SV* callback_close;
++ SV* callback_trans;
++ SV* callback_uninst;
++ SV* callback_inst;
++ long min_delta;
++ SV *data; /* chain with another data user provided */
++};
++
++typedef struct s_Transaction* URPM__DB;
++typedef struct s_Transaction* URPM__Transaction;
++typedef struct s_Package* URPM__Package;
++
++#define FLAG_ID 0x001fffffU
++#define FLAG_RATE 0x00e00000U
++#define FLAG_BASE 0x01000000U
++#define FLAG_SKIP 0x02000000U
++#define FLAG_DISABLE_OBSOLETE 0x04000000U
++#define FLAG_INSTALLED 0x08000000U
++#define FLAG_REQUESTED 0x10000000U
++#define FLAG_REQUIRED 0x20000000U
++#define FLAG_UPGRADE 0x40000000U
++#define FLAG_NO_HEADER_FREE 0x80000000U
++
++#define FLAG_ID_MAX 0x001ffffe
++#define FLAG_ID_INVALID 0x001fffff
++
++#define FLAG_RATE_POS 21
++#define FLAG_RATE_MAX 5
++#define FLAG_RATE_INVALID 0
++
++
++#define FILENAME_TAG 1000000
++#define FILESIZE_TAG 1000001
++
++#define FILTER_MODE_ALL_FILES 0
++#define FILTER_MODE_CONF_FILES 2
++
++/* promote epoch sense should be :
++ 0 for compability with old packages
++ 1 for rpm 4.2 and better new approach. */
++#define PROMOTE_EPOCH_SENSE 1
++
++static ssize_t write_nocheck(int fd, const void *buf, size_t count) {
++ return write(fd, buf, count);
++}
++static const void* unused_variable(const void *p) {
++ return p;
++}
++
++static int rpmError_callback_data;
++
++int rpmError_callback() {
++ write_nocheck(rpmError_callback_data, rpmlogMessage(), strlen(rpmlogMessage()));
++ return RPMLOG_DEFAULT;
++}
++
++static int rpm_codeset_is_utf8 = 0;
++
++static SV*
++newSVpv_utf8(const char *s, STRLEN len)
++{
++ SV *sv = newSVpv(s, len);
++ SvUTF8_on(sv);
++ return sv;
++}
++
++static void
++get_fullname_parts(URPM__Package pkg, char **name, char **version, char **release, char **arch, char **eos) {
++ char *_version = NULL, *_release = NULL, *_arch = NULL, *_eos = NULL;
++
++ if ((_eos = strchr(pkg-&gt;info, '@')) != NULL) {
++ *_eos = 0; /* mark end of string to enable searching backwards */
++ if ((_arch = strrchr(pkg-&gt;info, '.')) != NULL) {
++ *_arch = 0;
++ if ((release != NULL || version != NULL || name != NULL) &amp;&amp; (_release = strrchr(pkg-&gt;info, '-')) != NULL) {
++ *_release = 0;
++ if ((version != NULL || name != NULL) &amp;&amp; (_version = strrchr(pkg-&gt;info, '-')) != NULL) {
++ if (name != NULL) *name = pkg-&gt;info;
++ if (version != NULL) *version = _version + 1;
++ }
++ if (release != NULL) *release = _release + 1;
++ *_release = '-';
++ }
++ if (arch != NULL) *arch = _arch + 1;
++ *_arch = '.';
++ }
++ if (eos != NULL) *eos = _eos;
++ *_eos = '@';
++ }
++}
++
++static char *
++get_name(Header header, int32_t tag) {
++ struct rpmtd_s val;
++
++ headerGet(header, tag, &amp;val, HEADERGET_MINMEM);
++ char *name = (char *) rpmtdGetString(&amp;val);
++ return name ? name : &quot;&quot;;
++}
++
++static int
++get_int(Header header, int32_t tag) {
++ struct rpmtd_s val;
++
++ headerGet(header, tag, &amp;val, HEADERGET_DEFAULT);
++ uint32_t *ep = rpmtdGetUint32(&amp;val);
++ return ep ? *ep : 0;
++}
++
++static int
++sigsize_to_filesize(int sigsize) {
++ return sigsize + 440; /* 440 is the rpm header size (?) empirical, but works */
++}
++
++static int
++print_list_entry(char *buff, int sz, const char *name, uint32_t flags, const char *evr) {
++ int len = strlen(name);
++ char *p = buff;
++
++ if (len &gt;= sz || !strncmp(name, &quot;rpmlib(&quot;, 7)) return -1;
++ memcpy(p, name, len); p += len;
++
++ if (flags &amp; (RPMSENSE_PREREQ|RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POSTUN|RPMSENSE_SCRIPT_POST)) {
++ if (p - buff + 3 &gt;= sz) return -1;
++ memcpy(p, &quot;[*]&quot;, 4); p += 3;
++ }
++ if (evr != NULL) {
++ len = strlen(evr);
++ if (len &gt; 0) {
++ if (p - buff + 6 + len &gt;= sz) return -1;
++ *p++ = '[';
++ if (flags &amp; RPMSENSE_LESS) *p++ = '&lt;';
++ if (flags &amp; RPMSENSE_GREATER) *p++ = '&gt;';
++ if (flags &amp; RPMSENSE_EQUAL) *p++ = '=';
++ if ((flags &amp; (RPMSENSE_LESS|RPMSENSE_EQUAL|RPMSENSE_GREATER)) == RPMSENSE_EQUAL) *p++ = '=';
++ *p++ = ' ';
++ memcpy(p, evr, len); p+= len;
++ *p++ = ']';
++ }
++ }
++ *p = 0; /* make sure to mark null char, Is it really necessary ? */
++
++ return p - buff;
++}
++
++static int
++ranges_overlap(uint32_t aflags, char *sa, uint32_t bflags, char *sb, int b_nopromote) {
++ if (!aflags || !bflags)
++ return 1; /* really faster to test it there instead of later */
++ else {
++ int sense = 0;
++ char *eosa = strchr(sa, ']');
++ char *eosb = strchr(sb, ']');
++ char *ea, *va, *ra, *eb, *vb, *rb;
++
++ if (eosa) *eosa = 0;
++ if (eosb) *eosb = 0;
++ /* parse sa as an [epoch:]version[-release] */
++ for (ea = sa; *sa &gt;= '0' &amp;&amp; *sa &lt;= '9'; ++sa);
++ if (*sa == ':') {
++ *sa++ = 0; /* ea could be an empty string (should be interpreted as 0) */
++ va = sa;
++ } else {
++ va = ea; /* no epoch */
++ ea = NULL;
++ }
++ if ((ra = strrchr(sa, '-'))) *ra++ = 0;
++ /* parse sb as an [epoch:]version[-release] */
++ for (eb = sb; *sb &gt;= '0' &amp;&amp; *sb &lt;= '9'; ++sb);
++ if (*sb == ':') {
++ *sb++ = 0; /* ea could be an empty string (should be interpreted as 0) */
++ vb = sb;
++ } else {
++ vb = eb; /* no epoch */
++ eb = NULL;
++ }
++ if ((rb = strrchr(sb, '-'))) *rb++ = 0;
++ /* now compare epoch */
++ if (ea &amp;&amp; eb)
++ sense = rpmvercmp(*ea ? ea : &quot;0&quot;, *eb ? eb : &quot;0&quot;);
++ else if (ea &amp;&amp; *ea &amp;&amp; atol(ea) &gt; 0)
++ sense = b_nopromote ? 1 : 0;
++ else if (eb &amp;&amp; *eb &amp;&amp; atol(eb) &gt; 0)
++ sense = -1;
++ /* now compare version and release if epoch has not been enough */
++ if (sense == 0) {
++ sense = rpmvercmp(va, vb);
++ if (sense == 0 &amp;&amp; ra &amp;&amp; *ra &amp;&amp; rb &amp;&amp; *rb)
++ sense = rpmvercmp(ra, rb);
++ }
++ /* restore all character that have been modified inline */
++ if (rb) rb[-1] = '-';
++ if (ra) ra[-1] = '-';
++ if (eb) vb[-1] = ':';
++ if (ea) va[-1] = ':';
++ if (eosb) *eosb = ']';
++ if (eosa) *eosa = ']';
++ /* finish the overlap computation */
++ if (sense &lt; 0 &amp;&amp; ((aflags &amp; RPMSENSE_GREATER) || (bflags &amp; RPMSENSE_LESS)))
++ return 1;
++ else if (sense &gt; 0 &amp;&amp; ((aflags &amp; RPMSENSE_LESS) || (bflags &amp; RPMSENSE_GREATER)))
++ return 1;
++ else if (sense == 0 &amp;&amp; (((aflags &amp; RPMSENSE_EQUAL) &amp;&amp; (bflags &amp; RPMSENSE_EQUAL)) ||
++ ((aflags &amp; RPMSENSE_LESS) &amp;&amp; (bflags &amp; RPMSENSE_LESS)) ||
++ ((aflags &amp; RPMSENSE_GREATER) &amp;&amp; (bflags &amp; RPMSENSE_GREATER))))
++ return 1;
++ else
++ return 0;
++ }
++}
++
++static int has_old_suggests;
++int32_t is_old_suggests(int32_t flags) {
++ int is = flags &amp; RPMSENSE_MISSINGOK;
++ if (is) has_old_suggests = is;
++ return is;
++}
++int32_t is_not_old_suggests(int32_t flags) {
++ return !is_old_suggests(flags);
++}
++
++typedef int (*callback_list_str)(char *s, int slen, const char *name, const uint32_t flags, const char *evr, void *param);
++
++static int
++callback_list_str_xpush(char *s, int slen, const char *name, uint32_t flags, const char *evr, __attribute__((unused)) void *param) {
++ dSP;
++ if (s) {
++ XPUSHs(sv_2mortal(newSVpv(s, slen)));
++ } else {
++ char buff[4096];
++ int len = print_list_entry(buff, sizeof(buff)-1, name, flags, evr);
++ if (len &gt;= 0)
++ XPUSHs(sv_2mortal(newSVpv(buff, len)));
++ }
++ PUTBACK;
++ /* returning zero indicates to continue processing */
++ return 0;
++}
++static int
++callback_list_str_xpush_requires(char *s, int slen, const char *name, const uint32_t flags, const char *evr, __attribute__((unused)) void *param) {
++ dSP;
++ if (s) {
++ XPUSHs(sv_2mortal(newSVpv(s, slen)));
++ } else if (is_not_old_suggests(flags)) {
++ char buff[4096];
++ int len = print_list_entry(buff, sizeof(buff)-1, name, flags, evr);
++ if (len &gt;= 0)
++ XPUSHs(sv_2mortal(newSVpv(buff, len)));
++ }
++ PUTBACK;
++ /* returning zero indicates to continue processing */
++ return 0;
++}
++static int
++callback_list_str_xpush_old_suggests(char *s, int slen, const char *name, uint32_t flags, const char *evr, __attribute__((unused)) void *param) {
++ dSP;
++ if (s) {
++ XPUSHs(sv_2mortal(newSVpv(s, slen)));
++ } else if (is_old_suggests(flags)) {
++ char buff[4096];
++ int len = print_list_entry(buff, sizeof(buff)-1, name, flags, evr);
++ if (len &gt;= 0)
++ XPUSHs(sv_2mortal(newSVpv(buff, len)));
++ }
++ PUTBACK;
++ /* returning zero indicates to continue processing */
++ return 0;
++}
++
++struct cb_overlap_s {
++ char *name;
++ int32_t flags;
++ char *evr;
++ int direction; /* indicate to compare the above at left or right to the iteration element */
++ int b_nopromote;
++};
++
++static int
++callback_list_str_overlap(char *s, int slen, const char *name, uint32_t flags, const char *evr, void *param) {
++ struct cb_overlap_s *os = (struct cb_overlap_s *)param;
++ int result = 0;
++ char *eos = NULL;
++ char *eon = NULL;
++ char eosc = '\0';
++ char eonc = '\0';
++
++ /* we need to extract name, flags and evr from a full sense information, store result in local copy */
++ if (s) {
++ if (slen) { eos = s + slen; eosc = *eos; *eos = 0; }
++ name = s;
++ while (*s &amp;&amp; *s != ' ' &amp;&amp; *s != '[' &amp;&amp; *s != '&lt;' &amp;&amp; *s != '&gt;' &amp;&amp; *s != '=') ++s;
++ if (*s) {
++ eon = s;
++ while (*s) {
++ if (*s == ' ' || *s == '[' || *s == '*' || *s == ']');
++ else if (*s == '&lt;') flags |= RPMSENSE_LESS;
++ else if (*s == '&gt;') flags |= RPMSENSE_GREATER;
++ else if (*s == '=') flags |= RPMSENSE_EQUAL;
++ else break;
++ ++s;
++ }
++ evr = s;
++ } else
++ evr = &quot;&quot;;
++ }
++
++ /* mark end of name */
++ if (eon) { eonc = *eon; *eon = 0; }
++ /* names should be equal, else it will not overlap */
++ if (!strcmp(name, os-&gt;name)) {
++ /* perform overlap according to direction needed, negative for left */
++ if (os-&gt;direction &lt; 0)
++ result = ranges_overlap(os-&gt;flags, os-&gt;evr, flags, (char *) evr, os-&gt;b_nopromote);
++ else
++ result = ranges_overlap(flags, (char *) evr, os-&gt;flags, os-&gt;evr, os-&gt;b_nopromote);
++ }
++
++ /* fprintf(stderr, &quot;cb_list_str_overlap result=%d, os-&gt;direction=%d, os-&gt;name=%s, os-&gt;evr=%s, name=%s, evr=%s\n&quot;,
++ result, os-&gt;direction, os-&gt;name, os-&gt;evr, name, evr); */
++
++ /* restore s if needed */
++ if (eon) *eon = eonc;
++ if (eos) *eos = eosc;
++
++ return result;
++}
++
++static int
++return_list_str(char *s, Header header, int32_t tag_name, int32_t tag_flags, int32_t tag_version, callback_list_str f, void *param) {
++ int count = 0;
++
++ if (s != NULL) {
++ char *ps = strchr(s, '@');
++ if (tag_flags &amp;&amp; tag_version) {
++ while(ps != NULL) {
++ ++count;
++ if (f(s, ps-s, NULL, 0, NULL, param)) return -count;
++ s = ps + 1; ps = strchr(s, '@');
++ }
++ ++count;
++ if (f(s, 0, NULL, 0, NULL, param)) return -count;
++ } else {
++ char *eos;
++ while(ps != NULL) {
++ *ps = 0; eos = strchr(s, '['); if (!eos) eos = strchr(s, ' ');
++ ++count;
++ if (f(s, eos ? eos-s : ps-s, NULL, 0, NULL, param)) { *ps = '@'; return -count; }
++ *ps = '@'; /* restore in memory modified char */
++ s = ps + 1; ps = strchr(s, '@');
++ }
++ eos = strchr(s, '['); if (!eos) eos = strchr(s, ' ');
++ ++count;
++ if (f(s, eos ? eos-s : 0, NULL, 0, NULL, param)) return -count;
++ }
++ } else if (header) {
++ struct rpmtd_s list, flags, list_evr;
++
++ if (headerGet(header, tag_name, &amp;list, HEADERGET_DEFAULT)) {
++ if (tag_flags) headerGet(header, tag_flags, &amp;flags, HEADERGET_DEFAULT);
++ if (tag_version) headerGet(header, tag_version, &amp;list_evr, HEADERGET_DEFAULT);
++ while (rpmtdNext(&amp;list) &gt;= 0) {
++ ++count;
++ uint32_t *flag = rpmtdNextUint32(&amp;flags);
++ if (f(NULL, 0, rpmtdGetString(&amp;list), flag ? *flag : 0,
++ rpmtdNextString(&amp;list_evr), param)) {
++ rpmtdFreeData(&amp;list);
++ if (tag_flags) rpmtdFreeData(&amp;flags);
++ if (tag_version) rpmtdFreeData(&amp;list_evr);
++ return -count;
++ }
++ }
++ rpmtdFreeData(&amp;list);
++ if (tag_flags) rpmtdFreeData(&amp;flags);
++ if (tag_version) rpmtdFreeData(&amp;list_evr);
++ }
++ }
++ return count;
++}
++
++static int
++xpush_simple_list_str(Header header, int32_t tag_name) {
++ dSP;
++ if (header) {
++ struct rpmtd_s list;
++ const char *val;
++ int size;
++
++ if (!headerGet(header, tag_name, &amp;list, HEADERGET_DEFAULT)) return 0;
++ size = rpmtdCount(&amp;list);
++
++ while ((val = rpmtdNextString(&amp;list))) {
++ XPUSHs(sv_2mortal(newSVpv(val, 0)));
++ }
++ rpmtdFreeData(&amp;list);
++ PUTBACK;
++ return size;
++ } else return 0;
++}
++
++void
++return_list_int32_t(Header header, int32_t tag_name) {
++ dSP;
++ if (header) {
++ struct rpmtd_s list;
++
++ if (headerGet(header, tag_name, &amp;list, HEADERGET_DEFAULT)) {
++ uint32_t *val;
++ while ((val = rpmtdNextUint32(&amp;list)))
++ XPUSHs(sv_2mortal(newSViv(*val)));
++ rpmtdFreeData(&amp;list);
++ }
++ }
++ PUTBACK;
++}
++
++void
++return_list_uint_16(Header header, int32_t tag_name) {
++ dSP;
++ if (header) {
++ struct rpmtd_s list;
++ if (headerGet(header, tag_name, &amp;list, HEADERGET_DEFAULT)) {
++ int count = rpmtdCount(&amp;list);
++ int i;
++ uint16_t *list_ = list.data;
++ for(i = 0; i &lt; count; i++) {
++ XPUSHs(sv_2mortal(newSViv(list_[i])));
++ }
++ rpmtdFreeData(&amp;list);
++ }
++ }
++ PUTBACK;
++}
++
++void
++return_list_tag_modifier(Header header, int32_t tag_name) {
++ dSP;
++ int i;
++ struct rpmtd_s td;
++ if (!headerGet(header, tag_name, &amp;td, HEADERGET_DEFAULT)) return;
++ int count = rpmtdCount(&amp;td);
++ int32_t *list = td.data;
++
++ for (i = 0; i &lt; count; i++) {
++ char buff[15];
++ char *s = buff;
++ switch (tag_name) {
++ case RPMTAG_FILEFLAGS:
++ if (list[i] &amp; RPMFILE_CONFIG) *s++ = 'c';
++ if (list[i] &amp; RPMFILE_DOC) *s++ = 'd';
++ if (list[i] &amp; RPMFILE_GHOST) *s++ = 'g';
++ if (list[i] &amp; RPMFILE_LICENSE) *s++ = 'l';
++ if (list[i] &amp; RPMFILE_MISSINGOK) *s++ = 'm';
++ if (list[i] &amp; RPMFILE_NOREPLACE) *s++ = 'n';
++ if (list[i] &amp; RPMFILE_SPECFILE) *s++ = 'S';
++ if (list[i] &amp; RPMFILE_README) *s++ = 'R';
++ if (list[i] &amp; RPMFILE_EXCLUDE) *s++ = 'e';
++ if (list[i] &amp; RPMFILE_ICON) *s++ = 'i';
++ if (list[i] &amp; RPMFILE_UNPATCHED) *s++ = 'u';
++ if (list[i] &amp; RPMFILE_PUBKEY) *s++ = 'p';
++ break;
++ default:
++ rpmtdFreeData(&amp;td);
++ return;
++ }
++ *s = '\0';
++ XPUSHs(sv_2mortal(newSVpv(buff, strlen(buff))));
++ }
++ rpmtdFreeData(&amp;td);
++ PUTBACK;
++}
++
++void
++return_list_tag(URPM__Package pkg, int32_t tag_name) {
++ dSP;
++ if (pkg-&gt;h != NULL) {
++ struct rpmtd_s td;
++ if (headerGet(pkg-&gt;h, tag_name, &amp;td, HEADERGET_DEFAULT)) {
++ void *list = td.data;
++ int32_t count = rpmtdCount(&amp;td);
++ if (tag_name == RPMTAG_ARCH) {
++ XPUSHs(sv_2mortal(newSVpv(headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? (char *) list : &quot;src&quot;, 0)));
++ } else
++ switch (rpmtdType(&amp;td)) {
++ case RPM_NULL_TYPE:
++ break;
++#ifdef RPM_ORG
++ case RPM_CHAR_TYPE:
++#endif
++ case RPM_INT8_TYPE:
++ case RPM_INT16_TYPE:
++ case RPM_INT32_TYPE:
++ {
++ int i;
++ int *r;
++ r = (int *)list;
++ for (i=0; i &lt; count; i++) {
++ XPUSHs(sv_2mortal(newSViv(r[i])));
++ }
++ }
++ break;
++ case RPM_STRING_TYPE:
++ XPUSHs(sv_2mortal(newSVpv((char *) list, 0)));
++ break;
++ case RPM_BIN_TYPE:
++ break;
++ case RPM_STRING_ARRAY_TYPE:
++ {
++ int i;
++ char **s;
++
++ s = (char **)list;
++ for (i = 0; i &lt; count; i++) {
++ XPUSHs(sv_2mortal(newSVpv(s[i], 0)));
++ }
++ }
++ break;
++ case RPM_I18NSTRING_TYPE:
++ break;
++ case RPM_INT64_TYPE:
++ break;
++ }
++ }
++ } else {
++ char *name;
++ char *version;
++ char *release;
++ char *arch;
++ char *eos;
++ switch (tag_name) {
++ case RPMTAG_NAME:
++ {
++ get_fullname_parts(pkg, &amp;name, &amp;version, &amp;release, &amp;arch, &amp;eos);
++ if (version - name &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(name, version-name - 1)));
++ }
++ break;
++ case RPMTAG_VERSION:
++ {
++ get_fullname_parts(pkg, &amp;name, &amp;version, &amp;release, &amp;arch, &amp;eos);
++ if (release - version &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(version, release-version - 1)));
++ }
++ break;
++ case RPMTAG_RELEASE:
++ {
++ get_fullname_parts(pkg, &amp;name, &amp;version, &amp;release, &amp;arch, &amp;eos);
++ if (arch - release &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(release, arch-release - 1)));
++ }
++ break;
++ case RPMTAG_ARCH:
++ {
++ get_fullname_parts(pkg, &amp;name, &amp;version, &amp;release, &amp;arch, &amp;eos);
++ XPUSHs(sv_2mortal(newSVpv(arch, eos-arch)));
++ }
++ break;
++ case RPMTAG_SUMMARY:
++ XPUSHs(sv_2mortal(newSVpv(pkg-&gt;summary, 0)));
++ break;
++ }
++ }
++ PUTBACK;
++}
++
++
++void
++return_files(Header header, int filter_mode) {
++ dSP;
++ if (header) {
++ char buff[4096];
++ char *p, *s;
++ STRLEN len;
++ unsigned int i;
++
++ struct rpmtd_s td_flags, td_fmodes;
++ int32_t *flags = NULL;
++ uint16_t *fmodes = NULL;
++ if (filter_mode) {
++ headerGet(header, RPMTAG_FILEFLAGS, &amp;td_flags, HEADERGET_DEFAULT);
++ headerGet(header, RPMTAG_FILEMODES, &amp;td_fmodes, HEADERGET_DEFAULT);
++ flags = td_flags.data;
++ fmodes = td_fmodes.data;
++ }
++
++ struct rpmtd_s td_baseNames, td_dirIndexes, td_dirNames, td_list;
++ headerGet(header, RPMTAG_BASENAMES, &amp;td_baseNames, HEADERGET_DEFAULT);
++ headerGet(header, RPMTAG_DIRINDEXES, &amp;td_dirIndexes, HEADERGET_DEFAULT);
++ headerGet(header, RPMTAG_DIRNAMES, &amp;td_dirNames, HEADERGET_DEFAULT);
++
++ char **baseNames = td_baseNames.data;
++ char **dirNames = td_dirNames.data;
++ int32_t *dirIndexes = td_dirIndexes.data;
++
++ char **list = NULL;
++ if (!baseNames || !dirNames || !dirIndexes) {
++ if (!headerGet(header, RPMTAG_OLDFILENAMES, &amp;td_list, HEADERGET_DEFAULT)) return;
++ list = td_list.data;
++ }
++
++ for(i = 0; i &lt; rpmtdCount(&amp;td_baseNames); i++) {
++ if (list) {
++ s = list[i];
++ len = strlen(list[i]);
++ } else {
++ len = strlen(dirNames[dirIndexes[i]]);
++ if (len &gt;= sizeof(buff)) continue;
++ memcpy(p = buff, dirNames[dirIndexes[i]], len + 1); p += len;
++ len = strlen(baseNames[i]);
++ if (p - buff + len &gt;= sizeof(buff)) continue;
++ memcpy(p, baseNames[i], len + 1); p += len;
++ s = buff;
++ len = p-buff;
++ }
++
++ if (filter_mode) {
++ if ((filter_mode &amp; FILTER_MODE_CONF_FILES) &amp;&amp; flags &amp;&amp; (flags[i] &amp; RPMFILE_CONFIG) == 0) continue;
++ }
++
++ XPUSHs(sv_2mortal(newSVpv(s, len)));
++ }
++
++ free(baseNames);
++ free(dirNames);
++ free(list);
++ }
++ PUTBACK;
++}
++
++void
++return_problems(rpmps ps, int translate_message, int raw_message) {
++ dSP;
++ if (ps &amp;&amp; rpmpsNumProblems(ps) &gt; 0) {
++ rpmpsi iterator = rpmpsInitIterator(ps);
++ while (rpmpsNextIterator(iterator) &gt;= 0) {
++ rpmProblem p = rpmpsGetProblem(iterator);
++
++ if (translate_message) {
++ /* translate error using rpm localization */
++ const char *buf = rpmProblemString(p);
++ SV *sv = newSVpv(buf, 0);
++ if (rpm_codeset_is_utf8) SvUTF8_on(sv);
++ XPUSHs(sv_2mortal(sv));
++ _free(buf);
++ }
++ if (raw_message) {
++ const char *pkgNEVR = rpmProblemGetPkgNEVR(p) ? rpmProblemGetPkgNEVR(p) : &quot;&quot;;
++ const char *altNEVR = rpmProblemGetAltNEVR(p) ? rpmProblemGetAltNEVR(p) : &quot;&quot;;
++ const char *s = rpmProblemGetStr(p) ? rpmProblemGetStr(p) : &quot;&quot;;
++ SV *sv;
++
++ switch (rpmProblemGetType(p)) {
++ case RPMPROB_BADARCH:
++ sv = newSVpvf(&quot;badarch@%s&quot;, pkgNEVR); break;
++
++ case RPMPROB_BADOS:
++ sv = newSVpvf(&quot;bados@%s&quot;, pkgNEVR); break;
++
++ case RPMPROB_PKG_INSTALLED:
++ sv = newSVpvf(&quot;installed@%s&quot;, pkgNEVR); break;
++
++ case RPMPROB_BADRELOCATE:
++ sv = newSVpvf(&quot;badrelocate@%s@%s&quot;, pkgNEVR, s); break;
++
++ case RPMPROB_NEW_FILE_CONFLICT:
++ case RPMPROB_FILE_CONFLICT:
++ sv = newSVpvf(&quot;conflicts@%s@%s@%s&quot;, pkgNEVR, altNEVR, s); break;
++
++ case RPMPROB_OLDPACKAGE:
++ sv = newSVpvf(&quot;installed@%s@%s&quot;, pkgNEVR, altNEVR); break;
++
++ case RPMPROB_DISKSPACE:
++ sv = newSVpvf(&quot;diskspace@%s@%s@%lld&quot;, pkgNEVR, s, (long long)rpmProblemGetDiskNeed(p)); break;
++ case RPMPROB_DISKNODES:
++ sv = newSVpvf(&quot;disknodes@%s@%s@%lld&quot;, pkgNEVR, s, (long long)rpmProblemGetDiskNeed(p)); break;
++ case RPMPROB_REQUIRES:
++ sv = newSVpvf(&quot;requires@%s@%s&quot;, pkgNEVR, altNEVR+2); break;
++
++ case RPMPROB_CONFLICT:
++ sv = newSVpvf(&quot;conflicts@%s@%s&quot;, pkgNEVR, altNEVR+2); break;
++
++ default:
++ sv = newSVpvf(&quot;unknown@%s&quot;, pkgNEVR); break;
++ }
++ XPUSHs(sv_2mortal(sv));
++ }
++ }
++ rpmpsFreeIterator(iterator);
++ }
++ PUTBACK;
++}
++
++static char *
++pack_list(Header header, int32_t tag_name, int32_t tag_flags, int32_t tag_version, int32_t (*check_flag)(int32_t)) {
++ char buff[65536];
++ int32_t *flags = NULL;
++ char **list_evr = NULL;
++ unsigned int i;
++ char *p = buff;
++
++ struct rpmtd_s td;
++ if (headerGet(header, tag_name, &amp;td, HEADERGET_DEFAULT)) {
++ char **list = td.data;
++
++ struct rpmtd_s td_flags, td_list_evr;
++ if (tag_flags &amp;&amp; headerGet(header, tag_flags, &amp;td_flags, HEADERGET_DEFAULT)) flags = td_flags.data;
++ if (tag_version &amp;&amp; headerGet(header, tag_version, &amp;td_list_evr, HEADERGET_DEFAULT)) list_evr = td_list_evr.data;
++ for(i = 0; i &lt; rpmtdCount(&amp;td); i++) {
++ if (check_flag &amp;&amp; !check_flag(flags[i])) continue;
++ int len = print_list_entry(p, sizeof(buff)-(p-buff)-1, list[i], flags ? flags[i] : 0, list_evr ? list_evr[i] : NULL);
++ if (len &lt; 0) continue;
++ p += len;
++ *p++ = '@';
++ }
++ if (p &gt; buff) p[-1] = 0;
++
++ free(list);
++ free(list_evr);
++ }
++
++ return p &gt; buff ? memcpy(malloc(p-buff), buff, p-buff) : NULL;
++}
++
++static void
++pack_header(URPM__Package pkg) {
++ if (pkg-&gt;h) {
++ if (pkg-&gt;info == NULL) {
++ char buff[1024];
++ char *p = buff;
++ char *name = get_name(pkg-&gt;h, RPMTAG_NAME);
++ char *version = get_name(pkg-&gt;h, RPMTAG_VERSION);
++ char *release = get_name(pkg-&gt;h, RPMTAG_RELEASE);
++ char *arch = headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(pkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++
++ p += 1 + snprintf(buff, sizeof(buff), &quot;%s-%s-%s.%s@%d@%d@%s&quot;, name, version, release, arch,
++ get_int(pkg-&gt;h, RPMTAG_EPOCH), get_int(pkg-&gt;h, RPMTAG_SIZE),
++ get_name(pkg-&gt;h, RPMTAG_GROUP));
++ pkg-&gt;info = memcpy(malloc(p-buff), buff, p-buff);
++ }
++ if (pkg-&gt;filesize == 0) pkg-&gt;filesize = sigsize_to_filesize(get_int(pkg-&gt;h, RPMTAG_SIGSIZE));
++ if (pkg-&gt;requires == NULL &amp;&amp; pkg-&gt;suggests == NULL)
++ has_old_suggests = 0;
++ pkg-&gt;requires = pack_list(pkg-&gt;h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION, is_not_old_suggests);
++ if (has_old_suggests)
++ pkg-&gt;suggests = pack_list(pkg-&gt;h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION, is_old_suggests);
++ else
++ pkg-&gt;suggests = pack_list(pkg-&gt;h, RPMTAG_SUGGESTSNAME, 0, 0, NULL);
++ if (pkg-&gt;obsoletes == NULL)
++ pkg-&gt;obsoletes = pack_list(pkg-&gt;h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION, NULL);
++ if (pkg-&gt;conflicts == NULL)
++ pkg-&gt;conflicts = pack_list(pkg-&gt;h, RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTFLAGS, RPMTAG_CONFLICTVERSION, NULL);
++ if (pkg-&gt;provides == NULL)
++ pkg-&gt;provides = pack_list(pkg-&gt;h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION, NULL);
++ if (pkg-&gt;summary == NULL) {
++ char *summary = get_name(pkg-&gt;h, RPMTAG_SUMMARY);
++ int len = 1 + strlen(summary);
++
++ pkg-&gt;summary = memcpy(malloc(len), summary, len);
++ }
++
++ if (!(pkg-&gt;flag &amp; FLAG_NO_HEADER_FREE)) pkg-&gt;h =headerFree(pkg-&gt;h);
++ pkg-&gt;h = 0;
++ }
++}
++
++static void
++update_hash_entry(HV *hash, char *name, STRLEN len, int force, IV use_sense, URPM__Package pkg) {
++ SV** isv;
++
++ if (!len) len = strlen(name);
++ if ((isv = hv_fetch(hash, name, len, force))) {
++ /* check if an entry has been found or created, it should so be updated */
++ if (!SvROK(*isv) || SvTYPE(SvRV(*isv)) != SVt_PVHV) {
++ SV* choice_set = (SV*)newHV();
++ if (choice_set) {
++ SvREFCNT_dec(*isv); /* drop the old as we are changing it */
++ if (!(*isv = newRV_noinc(choice_set))) {
++ SvREFCNT_dec(choice_set);
++ *isv = &amp;PL_sv_undef;
++ }
++ }
++ }
++ if (isv &amp;&amp; *isv != &amp;PL_sv_undef) {
++ char id[8];
++ STRLEN id_len = snprintf(id, sizeof(id), &quot;%d&quot;, pkg-&gt;flag &amp; FLAG_ID);
++ SV **sense = hv_fetch((HV*)SvRV(*isv), id, id_len, 1);
++ if (sense &amp;&amp; use_sense) sv_setiv(*sense, use_sense);
++ }
++ }
++}
++
++static void
++update_provide_entry(char *name, STRLEN len, int force, IV use_sense, URPM__Package pkg, HV *provides) {
++ update_hash_entry(provides, name, len, force, use_sense, pkg);
++}
++
++static void
++update_provides(URPM__Package pkg, HV *provides) {
++ if (pkg-&gt;h) {
++ int len;
++ struct rpmtd_s td, td_flags;
++ int32_t *flags = NULL;
++ unsigned int i;
++
++ /* examine requires for files which need to be marked in provides */
++ if (headerGet(pkg-&gt;h, RPMTAG_REQUIRENAME, &amp;td, HEADERGET_DEFAULT)) {
++ char **list = td.data;
++ for (i = 0; i &lt; rpmtdCount(&amp;td); ++i) {
++ len = strlen(list[i]);
++ if (list[i][0] == '/') (void)hv_fetch(provides, list[i], len, 1);
++ }
++ }
++
++ /* update all provides */
++ if (headerGet(pkg-&gt;h, RPMTAG_PROVIDENAME, &amp;td, HEADERGET_DEFAULT)) {
++ char **list = td.data;
++ if (headerGet(pkg-&gt;h, RPMTAG_PROVIDEFLAGS, &amp;td_flags, HEADERGET_DEFAULT))
++ flags = td_flags.data;
++ for (i = 0; i &lt; rpmtdCount(&amp;td); ++i) {
++ len = strlen(list[i]);
++ if (!strncmp(list[i], &quot;rpmlib(&quot;, 7)) continue;
++ update_provide_entry(list[i], len, 1, flags &amp;&amp; flags[i] &amp; (RPMSENSE_PREREQ|RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POSTUN|RPMSENSE_SCRIPT_POST|RPMSENSE_LESS|RPMSENSE_EQUAL|RPMSENSE_GREATER),
++ pkg, provides);
++ }
++ }
++ } else {
++ char *ps, *s, *es;
++
++ if ((s = pkg-&gt;requires) != NULL &amp;&amp; *s != 0) {
++ ps = strchr(s, '@');
++ while(ps != NULL) {
++ if (s[0] == '/') {
++ *ps = 0; es = strchr(s, '['); if (!es) es = strchr(s, ' '); *ps = '@';
++ (void)hv_fetch(provides, s, es != NULL ? es-s : ps-s, 1);
++ }
++ s = ps + 1; ps = strchr(s, '@');
++ }
++ if (s[0] == '/') {
++ es = strchr(s, '['); if (!es) es = strchr(s, ' ');
++ (void)hv_fetch(provides, s, es != NULL ? (U32)(es-s) : strlen(s), 1);
++ }
++ }
++
++ if ((s = pkg-&gt;provides) != NULL &amp;&amp; *s != 0) {
++ char *es;
++
++ ps = strchr(s, '@');
++ while(ps != NULL) {
++ *ps = 0; es = strchr(s, '['); if (!es) es = strchr(s, ' '); *ps = '@';
++ update_provide_entry(s, es != NULL ? es-s : ps-s, 1, es != NULL, pkg, provides);
++ s = ps + 1; ps = strchr(s, '@');
++ }
++ es = strchr(s, '['); if (!es) es = strchr(s, ' ');
++ update_provide_entry(s, es != NULL ? es-s : 0, 1, es != NULL, pkg, provides);
++ }
++ }
++}
++
++static void
++update_obsoletes(URPM__Package pkg, HV *obsoletes) {
++ if (pkg-&gt;h) {
++ struct rpmtd_s td;
++
++ /* update all provides */
++ if (headerGet(pkg-&gt;h, RPMTAG_OBSOLETENAME, &amp;td, HEADERGET_DEFAULT)) {
++ char **list = td.data;
++ unsigned int i;
++ for (i = 0; i &lt; rpmtdCount(&amp;td); ++i)
++ update_hash_entry(obsoletes, list[i], 0, 1, 0, pkg);
++ }
++ } else {
++ char *ps, *s;
++
++ if ((s = pkg-&gt;obsoletes) != NULL &amp;&amp; *s != 0) {
++ char *es;
++
++ ps = strchr(s, '@');
++ while(ps != NULL) {
++ *ps = 0; es = strchr(s, '['); if (!es) es = strchr(s, ' '); *ps = '@';
++ update_hash_entry(obsoletes, s, es != NULL ? es-s : ps-s, 1, 0, pkg);
++ s = ps + 1; ps = strchr(s, '@');
++ }
++ es = strchr(s, '['); if (!es) es = strchr(s, ' ');
++ update_hash_entry(obsoletes, s, es != NULL ? es-s : 0, 1, 0, pkg);
++ }
++ }
++}
++
++static void
++update_provides_files(URPM__Package pkg, HV *provides) {
++ if (pkg-&gt;h) {
++ STRLEN len;
++ char **list = NULL;
++ unsigned int i;
++
++ struct rpmtd_s td_baseNames, td_dirIndexes, td_dirNames;
++ if (headerGet(pkg-&gt;h, RPMTAG_BASENAMES, &amp;td_baseNames, HEADERGET_DEFAULT) &amp;&amp;
++ headerGet(pkg-&gt;h, RPMTAG_DIRINDEXES, &amp;td_dirIndexes, HEADERGET_DEFAULT) &amp;&amp;
++ headerGet(pkg-&gt;h, RPMTAG_DIRNAMES, &amp;td_dirNames, HEADERGET_DEFAULT)) {
++
++ char **baseNames = td_baseNames.data;
++ char **dirNames = td_dirNames.data;
++ int32_t *dirIndexes = td_dirIndexes.data;
++
++ char buff[4096];
++ char *p;
++
++ for(i = 0; i &lt; rpmtdCount(&amp;td_baseNames); i++) {
++ len = strlen(dirNames[dirIndexes[i]]);
++ if (len &gt;= sizeof(buff)) continue;
++ memcpy(p = buff, dirNames[dirIndexes[i]], len + 1); p += len;
++ len = strlen(baseNames[i]);
++ if (p - buff + len &gt;= sizeof(buff)) continue;
++ memcpy(p, baseNames[i], len + 1); p += len;
++
++ update_provide_entry(buff, p-buff, 0, 0, pkg, provides);
++ }
++
++ free(baseNames);
++ free(dirNames);
++ } else {
++ struct rpmtd_s td;
++ headerGet(pkg-&gt;h, RPMTAG_OLDFILENAMES, &amp;td, HEADERGET_DEFAULT);
++ if (list) {
++ for (i = 0; i &lt; rpmtdCount(&amp;td); i++) {
++ len = strlen(list[i]);
++
++ update_provide_entry(list[i], len, 0, 0, pkg, provides);
++ }
++
++ free(list);
++ }
++ }
++ }
++}
++
++int
++open_archive(char *filename, pid_t *pid, int *empty_archive) {
++ int fd;
++ struct {
++ char header[4];
++ char toc_d_count[4];
++ char toc_l_count[4];
++ char toc_f_count[4];
++ char toc_str_size[4];
++ char uncompress[40];
++ char trailer[4];
++ } buf;
++
++ fd = open(filename, O_RDONLY);
++ if (fd &gt;= 0) {
++ int pos = lseek(fd, -(int)sizeof(buf), SEEK_END);
++ if (read(fd, &amp;buf, sizeof(buf)) != sizeof(buf) || strncmp(buf.header, &quot;cz[0&quot;, 4) || strncmp(buf.trailer, &quot;0]cz&quot;, 4)) {
++ /* this is not an archive, open it without magic, but first rewind at begin of file */
++ lseek(fd, 0, SEEK_SET);
++ } else if (pos == 0) {
++ *empty_archive = 1;
++ fd = -1;
++ } else {
++ /* this is an archive, create a pipe and fork for reading with uncompress defined inside */
++ int fdno[2];
++
++ if (!pipe(fdno)) {
++ if ((*pid = fork()) != 0) {
++ fd_set readfds;
++ struct timeval timeout;
++
++ FD_ZERO(&amp;readfds);
++ FD_SET(fdno[0], &amp;readfds);
++ timeout.tv_sec = 1;
++ timeout.tv_usec = 0;
++ select(fdno[0]+1, &amp;readfds, NULL, NULL, &amp;timeout);
++
++ close(fd);
++ fd = fdno[0];
++ close(fdno[1]);
++ } else {
++ char *unpacker[22]; /* enough for 40 bytes in uncompress to never overbuf */
++ char *p = buf.uncompress;
++ int ip = 0;
++ char *ld_loader = getenv(&quot;LD_LOADER&quot;);
++
++ if (ld_loader &amp;&amp; *ld_loader) {
++ unpacker[ip++] = ld_loader;
++ }
++
++ buf.trailer[0] = 0; /* make sure end-of-string is right */
++ while (*p) {
++ if (*p == ' ' || *p == '\t') *p++ = 0;
++ else {
++ unpacker[ip++] = p;
++ while (*p &amp;&amp; *p != ' ' &amp;&amp; *p != '\t') ++p;
++ }
++ }
++ unpacker[ip] = NULL; /* needed for execlp */
++
++ lseek(fd, 0, SEEK_SET);
++ dup2(fd, STDIN_FILENO); close(fd);
++ dup2(fdno[1], STDOUT_FILENO); close(fdno[1]);
++
++ /* get rid of &quot;decompression OK, trailing garbage ignored&quot; */
++ fd = open(&quot;/dev/null&quot;, O_WRONLY);
++ dup2(fd, STDERR_FILENO); close(fd);
++
++ execvp(unpacker[0], unpacker);
++ exit(1);
++ }
++ } else {
++ close(fd);
++ fd = -1;
++ }
++ }
++ }
++ return fd;
++}
++
++static int
++call_package_callback(SV *urpm, SV *sv_pkg, SV *callback) {
++ if (sv_pkg != NULL &amp;&amp; callback != NULL) {
++ int count;
++
++ /* now, a callback will be called for sure */
++ dSP;
++ PUSHMARK(SP);
++ XPUSHs(urpm);
++ XPUSHs(sv_pkg);
++ PUTBACK;
++ count = call_sv(callback, G_SCALAR);
++ SPAGAIN;
++ if (count == 1 &amp;&amp; !POPi) {
++ /* package should not be added in depslist, so we free it */
++ SvREFCNT_dec(sv_pkg);
++ sv_pkg = NULL;
++ }
++ PUTBACK;
++ }
++
++ return sv_pkg != NULL;
++}
++
++static int
++parse_line(AV *depslist, HV *provides, HV *obsoletes, URPM__Package pkg, char *buff, SV *urpm, SV *callback) {
++ SV *sv_pkg;
++ URPM__Package _pkg;
++ char *tag, *data;
++ int data_len;
++
++ if (buff[0] == 0) {
++ return 1;
++ } else if ((tag = buff)[0] == '@' &amp;&amp; (data = strchr(tag+1, '@')) != NULL) {
++ *tag++ = *data++ = 0;
++ data_len = 1+strlen(data);
++ if (!strcmp(tag, &quot;info&quot;)) {
++ pkg-&gt;info = memcpy(malloc(data_len), data, data_len);
++ pkg-&gt;flag &amp;= ~FLAG_ID;
++ pkg-&gt;flag |= 1 + av_len(depslist);
++ sv_pkg = sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;,
++ _pkg = memcpy(malloc(sizeof(struct s_Package)), pkg, sizeof(struct s_Package)));
++ if (call_package_callback(urpm, sv_pkg, callback)) {
++ if (provides) update_provides(_pkg, provides);
++ if (obsoletes) update_obsoletes(_pkg, obsoletes);
++ av_push(depslist, sv_pkg);
++ }
++ memset(pkg, 0, sizeof(struct s_Package));
++ } else if (!strcmp(tag, &quot;filesize&quot;)) {
++ pkg-&gt;filesize = atoi(data);
++ } else if (!strcmp(tag, &quot;requires&quot;)) {
++ free(pkg-&gt;requires); pkg-&gt;requires = memcpy(malloc(data_len), data, data_len);
++ } else if (!strcmp(tag, &quot;suggests&quot;)) {
++ free(pkg-&gt;suggests); pkg-&gt;suggests = memcpy(malloc(data_len), data, data_len);
++ } else if (!strcmp(tag, &quot;obsoletes&quot;)) {
++ free(pkg-&gt;obsoletes); pkg-&gt;obsoletes = memcpy(malloc(data_len), data, data_len);
++ } else if (!strcmp(tag, &quot;conflicts&quot;)) {
++ free(pkg-&gt;conflicts); pkg-&gt;conflicts = memcpy(malloc(data_len), data, data_len);
++ } else if (!strcmp(tag, &quot;provides&quot;)) {
++ free(pkg-&gt;provides); pkg-&gt;provides = memcpy(malloc(data_len), data, data_len);
++ } else if (!strcmp(tag, &quot;summary&quot;)) {
++ free(pkg-&gt;summary); pkg-&gt;summary = memcpy(malloc(data_len), data, data_len);
++ }
++ return 1;
++ } else {
++ fprintf(stderr, &quot;bad line &lt;%s&gt;\n&quot;, buff);
++ return 0;
++ }
++}
++
++#if 0
++static void pack_rpm_header(Header *h) {
++ Header packed = headerNew();
++
++ HeaderIterator hi = headerInitIterator(*h);
++ struct rpmtd_s td;
++ while (headerNext(hi, &amp;td)) {
++ // fprintf(stderr, &quot;adding %s %d\n&quot;, tagname(tag), c);
++ headerPut(packed, &amp;td, HEADERPUT_DEFAULT);
++ rpmtdFreeData(&amp;td);
++ }
++
++ headerFreeIterator(hi);
++ *h = headerFree(*h);
++
++ *h = packed;
++}
++
++static void drop_tags(Header *h) {
++ headerDel(*h, RPMTAG_FILEUSERNAME); /* user ownership is correct */
++ headerDel(*h, RPMTAG_FILEGROUPNAME); /* group ownership is correct */
++ headerDel(*h, RPMTAG_FILEMTIMES); /* correct time without it */
++ headerDel(*h, RPMTAG_FILEINODES); /* hardlinks work without it */
++ headerDel(*h, RPMTAG_FILEDEVICES); /* it is the same number for every file */
++ headerDel(*h, RPMTAG_FILESIZES); /* ? */
++ headerDel(*h, RPMTAG_FILERDEVS); /* it seems unused. always empty */
++ headerDel(*h, RPMTAG_FILEVERIFYFLAGS); /* only used for -V */
++#ifndef RPM_ORG
++ headerDel(*h, RPMTAG_FILEDIGESTALGOS); /* only used for -V */
++ headerDel(*h, RPMTAG_FILEDIGESTS); /* only used for -V */ /* alias: RPMTAG_FILEMD5S */
++#endif
++ /* keep RPMTAG_FILEFLAGS for %config (rpmnew) to work */
++ /* keep RPMTAG_FILELANGS for %lang (_install_langs) to work */
++ /* keep RPMTAG_FILELINKTOS for checking conflicts between symlinks */
++ /* keep RPMTAG_FILEMODES otherwise it segfaults with excludepath */
++
++ /* keep RPMTAG_POSTIN RPMTAG_POSTUN RPMTAG_PREIN RPMTAG_PREUN */
++ /* keep RPMTAG_TRIGGERSCRIPTS RPMTAG_TRIGGERVERSION RPMTAG_TRIGGERFLAGS RPMTAG_TRIGGERNAME */
++ /* small enough, and only in some packages. not needed per se */
++
++ headerDel(*h, RPMTAG_ICON);
++ headerDel(*h, RPMTAG_GIF);
++ headerDel(*h, RPMTAG_EXCLUDE);
++ headerDel(*h, RPMTAG_EXCLUSIVE);
++ headerDel(*h, RPMTAG_COOKIE);
++ headerDel(*h, RPMTAG_VERIFYSCRIPT);
++
++ /* always the same for our packages */
++ headerDel(*h, RPMTAG_VENDOR);
++ headerDel(*h, RPMTAG_DISTRIBUTION);
++
++ /* keep RPMTAG_SIGSIZE, useful to tell the size of the rpm file (+440) */
++
++ headerDel(*h, RPMTAG_DSAHEADER);
++ headerDel(*h, RPMTAG_SHA1HEADER);
++ headerDel(*h, RPMTAG_SIGMD5);
++ headerDel(*h, RPMTAG_SIGGPG);
++
++ pack_rpm_header(h);
++}
++#endif
++
++static int
++update_header(char *filename, URPM__Package pkg, __attribute__((unused)) int keep_all_tags, int vsflags) {
++ int d = open(filename, O_RDONLY);
++
++ if (d &gt;= 0) {
++ unsigned char sig[4];
++
++ if (read(d, &amp;sig, sizeof(sig)) == sizeof(sig)) {
++ lseek(d, 0, SEEK_SET);
++ if (sig[0] == 0xed &amp;&amp; sig[1] == 0xab &amp;&amp; sig[2] == 0xee &amp;&amp; sig[3] == 0xdb) {
++ FD_t fd = fdDup(d);
++ Header header;
++ rpmts ts;
++
++ close(d);
++ ts = rpmtsCreate();
++ rpmtsSetVSFlags(ts, _RPMVSF_NOSIGNATURES | vsflags);
++ if (fd != NULL &amp;&amp; rpmReadPackageFile(ts, fd, filename, &amp;header) == 0 &amp;&amp; header) {
++ char *basename;
++#ifndef RPM_ORG
++ struct stat sb;
++#else
++ int32_t size;
++#endif
++
++ basename = strrchr(filename, '/');
++#ifndef RPM_ORG
++ Fstat(fd, &amp;sb);
++#else
++ size = fdSize(fd);
++#endif
++ Fclose(fd);
++
++ /* this is only kept for compatibility with older distros
++ (where -&gt;filename on &quot;unpacked&quot; URPM::Package rely on FILENAME_TAG) */
++ headerPutString(header, FILENAME_TAG, basename != NULL ? basename + 1 : filename);
++
++ if (pkg-&gt;h &amp;&amp; !(pkg-&gt;flag &amp; FLAG_NO_HEADER_FREE)) pkg-&gt;h = headerFree(pkg-&gt;h);
++ pkg-&gt;h = header;
++ pkg-&gt;flag &amp;= ~FLAG_NO_HEADER_FREE;
++
++ /*if (!keep_all_tags) drop_tags(&amp;pkg-&gt;h);*/
++ (void)rpmtsFree(ts);
++ return 1;
++ }
++ (void)rpmtsFree(ts);
++ } else if (sig[0] == 0x8e &amp;&amp; sig[1] == 0xad &amp;&amp; sig[2] == 0xe8 &amp;&amp; sig[3] == 0x01) {
++ FD_t fd = fdDup(d);
++
++ close(d);
++ if (fd != NULL) {
++ if (pkg-&gt;h &amp;&amp; !(pkg-&gt;flag &amp; FLAG_NO_HEADER_FREE)) pkg-&gt;h = headerFree(pkg-&gt;h);
++ pkg-&gt;h = headerRead(fd, HEADER_MAGIC_YES);
++ pkg-&gt;flag &amp;= ~FLAG_NO_HEADER_FREE;
++ Fclose(fd);
++ return 1;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
++static int
++read_config_files(int force) {
++ static int already = 0;
++ int rc = 0;
++
++ if (!already || force) {
++ rc = rpmReadConfigFiles(NULL, NULL);
++ already = (rc == 0); /* set config as load only if it succeed */
++ }
++ return rc;
++}
++
++static void
++ts_nosignature(rpmts ts) {
++ rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES);
++}
++
++static void *rpmRunTransactions_callback(__attribute__((unused)) const void *h,
++ const rpmCallbackType what,
++ const rpm_loff_t amount,
++ const rpm_loff_t total,
++ fnpyKey pkgKey,
++ rpmCallbackData data) {
++ static struct timeval tprev;
++ static struct timeval tcurr;
++ static FD_t fd = NULL;
++ long delta;
++ int i;
++ struct s_TransactionData *td = data;
++ SV *callback = NULL;
++ char *callback_type = NULL;
++ char *callback_subtype = NULL;
++
++ if (!td)
++ return NULL;
++
++ switch (what) {
++ case RPMCALLBACK_INST_OPEN_FILE:
++ callback = td-&gt;callback_open;
++ callback_type = &quot;open&quot;;
++ break;
++ case RPMCALLBACK_INST_CLOSE_FILE:
++ callback = td-&gt;callback_close;
++ callback_type = &quot;close&quot;;
++ break;
++ case RPMCALLBACK_TRANS_START:
++ case RPMCALLBACK_TRANS_PROGRESS:
++ case RPMCALLBACK_TRANS_STOP:
++ callback = td-&gt;callback_trans;
++ callback_type = &quot;trans&quot;;
++ break;
++ case RPMCALLBACK_UNINST_START:
++ case RPMCALLBACK_UNINST_PROGRESS:
++ case RPMCALLBACK_UNINST_STOP:
++ callback = td-&gt;callback_uninst;
++ callback_type = &quot;uninst&quot;;
++ break;
++ case RPMCALLBACK_INST_START:
++ case RPMCALLBACK_INST_PROGRESS:
++ callback = td-&gt;callback_inst;
++ callback_type = &quot;inst&quot;;
++ break;
++ default:
++ break;
++ }
++
++ if (callback != NULL) {
++ switch (what) {
++ case RPMCALLBACK_TRANS_START:
++ case RPMCALLBACK_UNINST_START:
++ case RPMCALLBACK_INST_START:
++ callback_subtype = &quot;start&quot;;
++ gettimeofday(&amp;tprev, NULL);
++ break;
++ case RPMCALLBACK_TRANS_PROGRESS:
++ case RPMCALLBACK_UNINST_PROGRESS:
++ case RPMCALLBACK_INST_PROGRESS:
++ callback_subtype = &quot;progress&quot;;
++ gettimeofday(&amp;tcurr, NULL);
++ delta = 1000000 * (tcurr.tv_sec - tprev.tv_sec) + (tcurr.tv_usec - tprev.tv_usec);
++ if (delta &lt; td-&gt;min_delta &amp;&amp; amount &lt; total - 1)
++ callback = NULL; /* avoid calling too often a given callback */
++ else
++ tprev = tcurr;
++ break;
++ case RPMCALLBACK_TRANS_STOP:
++ case RPMCALLBACK_UNINST_STOP:
++ callback_subtype = &quot;stop&quot;;
++ break;
++ default:
++ break;
++ }
++
++ if (callback != NULL) {
++ /* now, a callback will be called for sure */
++ dSP;
++ ENTER;
++ SAVETMPS;
++ PUSHMARK(SP);
++ XPUSHs(td-&gt;data);
++ XPUSHs(sv_2mortal(newSVpv(callback_type, 0)));
++ XPUSHs(pkgKey != NULL ? sv_2mortal(newSViv((long)pkgKey - 1)) : &amp;PL_sv_undef);
++ if (callback_subtype != NULL) {
++ XPUSHs(sv_2mortal(newSVpv(callback_subtype, 0)));
++ XPUSHs(sv_2mortal(newSViv(amount)));
++ XPUSHs(sv_2mortal(newSViv(total)));
++ }
++ PUTBACK;
++ i = call_sv(callback, callback == td-&gt;callback_open ? G_SCALAR : G_DISCARD);
++ SPAGAIN;
++ if (callback == td-&gt;callback_open) {
++ if (i != 1) croak(&quot;callback_open should return a file handle&quot;);
++ i = POPi;
++ fd = fdDup(i);
++ if (fd) {
++ fd = fdLink(fd, &quot;persist perl-URPM&quot;);
++ Fcntl(fd, F_SETFD, (void *)1); /* necessary to avoid forked/execed process to lock removable */
++ }
++ PUTBACK;
++ } else if (callback == td-&gt;callback_close) {
++ fd = fdFree(fd, &quot;persist perl-URPM&quot;);
++ if (fd) {
++ Fclose(fd);
++ fd = NULL;
++ }
++ }
++ FREETMPS;
++ LEAVE;
++ }
++ }
++ return callback == td-&gt;callback_open ? fd : NULL;
++}
++
++int rpmtag_from_string(char *tag)
++{
++ if (!strcmp(tag, &quot;name&quot;))
++ return RPMTAG_NAME;
++ else if (!strcmp(tag, &quot;whatprovides&quot;))
++ return RPMTAG_PROVIDENAME;
++ else if (!strcmp(tag, &quot;whatrequires&quot;))
++ return RPMTAG_REQUIRENAME;
++ else if (!strcmp(tag, &quot;whatconflicts&quot;))
++ return RPMTAG_CONFLICTNAME;
++ else if (!strcmp(tag, &quot;group&quot;))
++ return RPMTAG_GROUP;
++ else if (!strcmp(tag, &quot;triggeredby&quot;))
++ return RPMTAG_TRIGGERNAME;
++ else if (!strcmp(tag, &quot;path&quot;))
++ return RPMTAG_BASENAMES;
++ else croak(&quot;unknown tag [%s]&quot;, tag);
++}
++
++MODULE = URPM PACKAGE = URPM::Package PREFIX = Pkg_
++
++void
++Pkg_DESTROY(pkg)
++ URPM::Package pkg
++ CODE:
++ free(pkg-&gt;info);
++ free(pkg-&gt;requires);
++ free(pkg-&gt;suggests);
++ free(pkg-&gt;obsoletes);
++ free(pkg-&gt;conflicts);
++ free(pkg-&gt;provides);
++ free(pkg-&gt;rflags);
++ free(pkg-&gt;summary);
++ if (pkg-&gt;h &amp;&amp; !(pkg-&gt;flag &amp; FLAG_NO_HEADER_FREE)) pkg-&gt;h = headerFree(pkg-&gt;h);
++ free(pkg);
++
++void
++Pkg_name(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *name;
++ char *version;
++
++ get_fullname_parts(pkg, &amp;name, &amp;version, NULL, NULL, NULL);
++ if (version - name &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(name, version-name-1)));
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_NAME), 0)));
++ }
++
++void
++Pkg_version(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *version;
++ char *release;
++
++ get_fullname_parts(pkg, NULL, &amp;version, &amp;release, NULL, NULL);
++ if (release - version &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(version, release-version-1)));
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_VERSION), 0)));
++ }
++
++void
++Pkg_release(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *release;
++ char *arch;
++
++ get_fullname_parts(pkg, NULL, NULL, &amp;release, &amp;arch, NULL);
++ if (arch - release &lt; 1) croak(&quot;invalid fullname&quot;);
++ XPUSHs(sv_2mortal(newSVpv(release, arch-release-1)));
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_RELEASE), 0)));
++ }
++
++void
++Pkg_arch(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *arch;
++ char *eos;
++
++ get_fullname_parts(pkg, NULL, NULL, NULL, &amp;arch, &amp;eos);
++ XPUSHs(sv_2mortal(newSVpv(arch, eos-arch)));
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(pkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;, 0)));
++ }
++
++int
++Pkg_is_arch_compat__XS(pkg)
++ URPM::Package pkg
++ INIT:
++#ifndef RPM_ORG
++ char * platform;
++#endif
++ CODE:
++ read_config_files(0);
++ if (pkg-&gt;info) {
++ char *arch;
++ char *eos;
++
++ get_fullname_parts(pkg, NULL, NULL, NULL, &amp;arch, &amp;eos);
++ *eos = 0;
++#ifndef RPM_ORG
++ platform = rpmExpand(arch, &quot;-%{_target_vendor}-%{_target_os}%{?_gnu}&quot;, NULL);
++ RETVAL = rpmPlatformScore(platform, NULL, 0);
++ _free(platform);
++#else
++ RETVAL = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
++#endif
++ *eos = '@';
++ } else if (pkg-&gt;h &amp;&amp; headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM)) {
++ char *arch = get_name(pkg-&gt;h, RPMTAG_ARCH);
++#ifndef RPM_ORG
++ platform = rpmExpand(arch, &quot;-%{_target_vendor}-%{_target_os}%{?_gnu}&quot;, NULL);
++ RETVAL = rpmPlatformScore(platform, NULL, 0);
++ _free(platform);
++#else
++ RETVAL = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
++#endif
++ } else {
++ RETVAL = 0;
++ }
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_is_platform_compat(pkg)
++ URPM::Package pkg
++ INIT:
++#ifndef RPM_ORG
++ char * platform = NULL;
++ struct rpmtd_s val;
++#endif
++ CODE:
++#ifndef RPM_ORG
++ read_config_files(0);
++ if (pkg-&gt;h &amp;&amp; headerIsEntry(pkg-&gt;h, RPMTAG_PLATFORM)) {
++ (void) headerGet(pkg-&gt;h, RPMTAG_PLATFORM, &amp;val, HEADERGET_DEFAULT);
++ platform = (char *) rpmtdGetString(&amp;val);
++ RETVAL = rpmPlatformScore(platform, NULL, 0);
++ platform = headerFreeData(platform, val.type);
++ } else if (pkg-&gt;info) {
++ char *arch;
++ char *eos;
++
++ get_fullname_parts(pkg, NULL, NULL, NULL, &amp;arch, &amp;eos);
++ *eos = 0;
++ platform = rpmExpand(arch, &quot;-%{_target_vendor}-&quot;, eos, &quot;%{?_gnu}&quot;, NULL);
++ RETVAL = rpmPlatformScore(platform, NULL, 0);
++ *eos = '@';
++ _free(platform);
++ } else {
++#else
++ croak(&quot;is_platform_compat() is available only since rpm 4.4.8&quot;);
++ { /* to match last } and avoid another #ifdef for it */
++#endif
++ RETVAL = 0;
++ }
++
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_summary(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;summary) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(pkg-&gt;summary, 0)));
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(get_name(pkg-&gt;h, RPMTAG_SUMMARY), 0)));
++ }
++
++void
++Pkg_description(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(get_name(pkg-&gt;h, RPMTAG_DESCRIPTION), 0)));
++ }
++
++void
++Pkg_sourcerpm(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_SOURCERPM), 0)));
++ }
++
++void
++Pkg_packager(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(get_name(pkg-&gt;h, RPMTAG_PACKAGER), 0)));
++ }
++
++void
++Pkg_buildhost(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_BUILDHOST), 0)));
++ }
++
++int
++Pkg_buildtime(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;h) {
++ RETVAL = get_int(pkg-&gt;h, RPMTAG_BUILDTIME);
++ } else {
++ RETVAL = 0;
++ }
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_installtid(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;h) {
++ RETVAL = get_int(pkg-&gt;h, RPMTAG_INSTALLTID);
++ } else {
++ RETVAL = 0;
++ }
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_url(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_URL), 0)));
++ }
++
++void
++Pkg_license(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_LICENSE), 0)));
++ }
++
++void
++Pkg_distribution(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_DISTRIBUTION), 0)));
++ }
++
++void
++Pkg_vendor(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_VENDOR), 0)));
++ }
++
++void
++Pkg_os(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_OS), 0)));
++ }
++
++void
++Pkg_payload_format(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_PAYLOADFORMAT), 0)));
++ }
++
++void
++Pkg_fullname(pkg)
++ URPM::Package pkg
++ PREINIT:
++ I32 gimme = GIMME_V;
++ PPCODE:
++ if (pkg-&gt;info) {
++ if (gimme == G_SCALAR) {
++ char *eos;
++ if ((eos = strchr(pkg-&gt;info, '@')) != NULL) {
++ XPUSHs(sv_2mortal(newSVpv(pkg-&gt;info, eos-pkg-&gt;info)));
++ }
++ } else if (gimme == G_ARRAY) {
++ char *name, *version, *release, *arch, *eos;
++ get_fullname_parts(pkg, &amp;name, &amp;version, &amp;release, &amp;arch, &amp;eos);
++ if (version - name &lt; 1 || release - version &lt; 1 || arch - release &lt; 1)
++ croak(&quot;invalid fullname&quot;);
++ EXTEND(SP, 4);
++ PUSHs(sv_2mortal(newSVpv(name, version-name-1)));
++ PUSHs(sv_2mortal(newSVpv(version, release-version-1)));
++ PUSHs(sv_2mortal(newSVpv(release, arch-release-1)));
++ PUSHs(sv_2mortal(newSVpv(arch, eos-arch)));
++ }
++ } else if (pkg-&gt;h) {
++ char *name = get_name(pkg-&gt;h, RPMTAG_NAME);
++ char *version = get_name(pkg-&gt;h, RPMTAG_VERSION);
++ char *release = get_name(pkg-&gt;h, RPMTAG_RELEASE);
++ char *arch = headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(pkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++
++ if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSVpvf(&quot;%s-%s-%s.%s&quot;, name, version, release, arch)));
++ } else if (gimme == G_ARRAY) {
++ EXTEND(SP, 4);
++ PUSHs(sv_2mortal(newSVpv(name, 0)));
++ PUSHs(sv_2mortal(newSVpv(version, 0)));
++ PUSHs(sv_2mortal(newSVpv(release, 0)));
++ PUSHs(sv_2mortal(newSVpv(arch, 0)));
++ }
++ }
++
++int
++Pkg_epoch(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;info) {
++ char *s, *eos;
++
++ if ((s = strchr(pkg-&gt;info, '@')) != NULL) {
++ if ((eos = strchr(s+1, '@')) != NULL) *eos = 0; /* mark end of string to enable searching backwards */
++ RETVAL = atoi(s+1);
++ if (eos != NULL) *eos = '@';
++ } else {
++ RETVAL = 0;
++ }
++ } else if (pkg-&gt;h) {
++ RETVAL = get_int(pkg-&gt;h, RPMTAG_EPOCH);
++ } else RETVAL = 0;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_compare_pkg(lpkg, rpkg)
++ URPM::Package lpkg
++ URPM::Package rpkg
++ PREINIT:
++ int compare = 0;
++ int lepoch;
++ char *lversion;
++ char *lrelease;
++ char *larch;
++ char *leos;
++ int repoch;
++ char *rversion;
++ char *rrelease;
++ char *rarch;
++ char *reos;
++ CODE:
++ if (lpkg == rpkg) RETVAL = 0;
++ else {
++ if (lpkg-&gt;info) {
++ char *s;
++
++ if ((s = strchr(lpkg-&gt;info, '@')) != NULL) {
++ if ((leos = strchr(s+1, '@')) != NULL) *leos = 0; /* mark end of string to enable searching backwards */
++ lepoch = atoi(s+1);
++ if (leos != NULL) *leos = '@';
++ } else {
++ lepoch = 0;
++ }
++ get_fullname_parts(lpkg, NULL, &amp;lversion, &amp;lrelease, &amp;larch, &amp;leos);
++ /* temporarily mark end of each substring */
++ lrelease[-1] = 0;
++ larch[-1] = 0;
++ } else if (lpkg-&gt;h) {
++ lepoch = get_int(lpkg-&gt;h, RPMTAG_EPOCH);
++ lversion = get_name(lpkg-&gt;h, RPMTAG_VERSION);
++ lrelease = get_name(lpkg-&gt;h, RPMTAG_RELEASE);
++ larch = headerIsEntry(lpkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(lpkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++ } else croak(&quot;undefined package&quot;);
++ if (rpkg-&gt;info) {
++ char *s;
++
++ if ((s = strchr(rpkg-&gt;info, '@')) != NULL) {
++ if ((reos = strchr(s+1, '@')) != NULL) *reos = 0; /* mark end of string to enable searching backwards */
++ repoch = atoi(s+1);
++ if (reos != NULL) *reos = '@';
++ } else {
++ repoch = 0;
++ }
++ get_fullname_parts(rpkg, NULL, &amp;rversion, &amp;rrelease, &amp;rarch, &amp;reos);
++ /* temporarily mark end of each substring */
++ rrelease[-1] = 0;
++ rarch[-1] = 0;
++ } else if (rpkg-&gt;h) {
++ repoch = get_int(rpkg-&gt;h, RPMTAG_EPOCH);
++ rversion = get_name(rpkg-&gt;h, RPMTAG_VERSION);
++ rrelease = get_name(rpkg-&gt;h, RPMTAG_RELEASE);
++ rarch = headerIsEntry(rpkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(rpkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++ } else {
++ /* restore info string modified */
++ if (lpkg-&gt;info) {
++ lrelease[-1] = '-';
++ larch[-1] = '.';
++ }
++ croak(&quot;undefined package&quot;);
++ }
++ compare = lepoch - repoch;
++ if (!compare) {
++ compare = rpmvercmp(lversion, rversion);
++ if (!compare) {
++ compare = rpmvercmp(lrelease, rrelease);
++ if (!compare) {
++ int lscore, rscore;
++ char *eolarch = strchr(larch, '@');
++ char *eorarch = strchr(rarch, '@');
++
++ read_config_files(0);
++ if (eolarch) *eolarch = 0; lscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, larch);
++ if (eorarch) *eorarch = 0; rscore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, rarch);
++ if (lscore == 0) {
++ if (rscore == 0)
++#if 0
++ /* Nanar: TODO check this
++ * hu ?? what is the goal of strcmp, some of arch are equivalent */
++ compare = 0
++#endif
++ compare = strcmp(larch, rarch);
++ else
++ compare = -1;
++ } else {
++ if (rscore == 0)
++ compare = 1;
++ else
++ compare = rscore - lscore; /* score are lower for better */
++ }
++ if (eolarch) *eolarch = '@';
++ if (eorarch) *eorarch = '@';
++ }
++ }
++ }
++ /* restore info string modified */
++ if (lpkg-&gt;info) {
++ lrelease[-1] = '-';
++ larch[-1] = '.';
++ }
++ if (rpkg-&gt;info) {
++ rrelease[-1] = '-';
++ rarch[-1] = '.';
++ }
++ RETVAL = compare;
++ }
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_compare(pkg, evr)
++ URPM::Package pkg
++ char *evr
++ PREINIT:
++ int compare = 0;
++ int _epoch;
++ char *_version;
++ char *_release;
++ char *_eos;
++ CODE:
++ if (pkg-&gt;info) {
++ char *s;
++
++ if ((s = strchr(pkg-&gt;info, '@')) != NULL) {
++ if ((_eos = strchr(s+1, '@')) != NULL) *_eos = 0; /* mark end of string to enable searching backwards */
++ _epoch = atoi(s+1);
++ if (_eos != NULL) *_eos = '@';
++ } else {
++ _epoch = 0;
++ }
++ get_fullname_parts(pkg, NULL, &amp;_version, &amp;_release, &amp;_eos, NULL);
++ /* temporarily mark end of each substring */
++ _release[-1] = 0;
++ _eos[-1] = 0;
++ } else if (pkg-&gt;h) {
++ _epoch = get_int(pkg-&gt;h, RPMTAG_EPOCH);
++ } else croak(&quot;undefined package&quot;);
++ if (!compare) {
++ char *epoch, *version, *release;
++
++ /* extract epoch and version from evr */
++ version = evr;
++ while (*version &amp;&amp; isdigit(*version)) version++;
++ if (*version == ':') {
++ epoch = evr;
++ *version++ = 0;
++ if (!*epoch) epoch = &quot;0&quot;;
++ compare = _epoch - (*epoch ? atoi(epoch) : 0);
++ version[-1] = ':'; /* restore in memory modification */
++ } else {
++ /* there is no epoch defined, so assume epoch = 0 */
++ version = evr;
++ compare = _epoch;
++ }
++ if (!compare) {
++ if (!pkg-&gt;info)
++ _version = get_name(pkg-&gt;h, RPMTAG_VERSION);
++ /* continue extracting release if any */
++ if ((release = strrchr(version, '-')) != NULL) {
++ *release++ = 0;
++ compare = rpmvercmp(_version, version);
++ if (!compare) {
++ /* need to compare with release here */
++ if (!pkg-&gt;info)
++ _release = get_name(pkg-&gt;h, RPMTAG_RELEASE);
++ compare = rpmvercmp(_release, release);
++ }
++ release[-1] = '-'; /* restore in memory modification */
++ } else {
++ compare = rpmvercmp(_version, version);
++ }
++ }
++ }
++ /* restore info string modified */
++ if (pkg-&gt;info) {
++ _release[-1] = '-';
++ _eos[-1] = '.';
++ }
++ RETVAL = compare;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_size(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;info) {
++ char *s, *eos;
++
++ if ((s = strchr(pkg-&gt;info, '@')) != NULL &amp;&amp; (s = strchr(s+1, '@')) != NULL) {
++ if ((eos = strchr(s+1, '@')) != NULL) *eos = 0; /* mark end of string to enable searching backwards */
++ RETVAL = atoi(s+1);
++ if (eos != NULL) *eos = '@';
++ } else {
++ RETVAL = 0;
++ }
++ } else if (pkg-&gt;h) {
++ RETVAL = get_int(pkg-&gt;h, RPMTAG_SIZE);
++ } else RETVAL = 0;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_filesize(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;filesize) {
++ RETVAL = pkg-&gt;filesize;
++ } else if (pkg-&gt;h) {
++ RETVAL = sigsize_to_filesize(get_int(pkg-&gt;h, RPMTAG_SIGSIZE));
++ } else RETVAL = 0;
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_group(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *s;
++
++ if ((s = strchr(pkg-&gt;info, '@')) != NULL &amp;&amp; (s = strchr(s+1, '@')) != NULL &amp;&amp; (s = strchr(s+1, '@')) != NULL) {
++ char *eos = strchr(s+1, '@');
++ XPUSHs(sv_2mortal(newSVpv_utf8(s+1, eos != NULL ? eos-s-1 : 0)));
++ }
++ } else if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(get_name(pkg-&gt;h, RPMTAG_GROUP), 0)));
++ }
++
++void
++Pkg_filename(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *eon;
++
++ if ((eon = strchr(pkg-&gt;info, '@')) != NULL) {
++ char savbuf[4];
++ memcpy(savbuf, eon, 4); /* there should be at least epoch and size described so (@<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">0 at 0</A> minimum) */
++ memcpy(eon, &quot;.rpm&quot;, 4);
++ XPUSHs(sv_2mortal(newSVpv(pkg-&gt;info, eon-pkg-&gt;info+4)));
++ memcpy(eon, savbuf, 4);
++ }
++ } else if (pkg-&gt;h) {
++ char *name = get_name(pkg-&gt;h, RPMTAG_NAME);
++ char *version = get_name(pkg-&gt;h, RPMTAG_VERSION);
++ char *release = get_name(pkg-&gt;h, RPMTAG_RELEASE);
++ char *arch = headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(pkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++
++ XPUSHs(sv_2mortal(newSVpvf(&quot;%s-%s-%s.%s.rpm&quot;, name, version, release, arch)));
++ }
++
++# deprecated
++void
++Pkg_header_filename(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;info) {
++ char *eon;
++
++ if ((eon = strchr(pkg-&gt;info, '@')) != NULL) {
++ XPUSHs(sv_2mortal(newSVpv(pkg-&gt;info, eon-pkg-&gt;info)));
++ }
++ } else if (pkg-&gt;h) {
++ char buff[1024];
++ char *p = buff;
++ char *name = get_name(pkg-&gt;h, RPMTAG_NAME);
++ char *version = get_name(pkg-&gt;h, RPMTAG_VERSION);
++ char *release = get_name(pkg-&gt;h, RPMTAG_RELEASE);
++ char *arch = headerIsEntry(pkg-&gt;h, RPMTAG_SOURCERPM) ? get_name(pkg-&gt;h, RPMTAG_ARCH) : &quot;src&quot;;
++
++ p += snprintf(buff, sizeof(buff), &quot;%s-%s-%s.%s&quot;, name, version, release, arch);
++ XPUSHs(sv_2mortal(newSVpv(buff, p-buff)));
++ }
++
++void
++Pkg_id(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if ((pkg-&gt;flag &amp; FLAG_ID) &lt;= FLAG_ID_MAX) {
++ XPUSHs(sv_2mortal(newSViv(pkg-&gt;flag &amp; FLAG_ID)));
++ }
++
++void
++Pkg_set_id(pkg, id=-1)
++ URPM::Package pkg
++ int id
++ PPCODE:
++ if ((pkg-&gt;flag &amp; FLAG_ID) &lt;= FLAG_ID_MAX) {
++ XPUSHs(sv_2mortal(newSViv(pkg-&gt;flag &amp; FLAG_ID)));
++ }
++ pkg-&gt;flag &amp;= ~FLAG_ID;
++ pkg-&gt;flag |= id &gt;= 0 &amp;&amp; id &lt;= FLAG_ID_MAX ? id : FLAG_ID_INVALID;
++
++void
++Pkg_requires(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;requires, pkg-&gt;h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION,
++ callback_list_str_xpush_requires, NULL);
++ SPAGAIN;
++
++void
++Pkg_requires_nosense(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;requires, pkg-&gt;h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, 0,
++ callback_list_str_xpush_requires, NULL);
++ SPAGAIN;
++
++void
++Pkg_suggests(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ int count = return_list_str(pkg-&gt;suggests, pkg-&gt;h, RPMTAG_SUGGESTSNAME, 0, 0, callback_list_str_xpush, NULL);
++ if (count == 0)
++ return_list_str(pkg-&gt;suggests, pkg-&gt;h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, 0,
++ callback_list_str_xpush_old_suggests, NULL);
++ SPAGAIN;
++
++void
++Pkg_obsoletes(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;obsoletes, pkg-&gt;h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION,
++ callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++void
++Pkg_obsoletes_nosense(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;obsoletes, pkg-&gt;h, RPMTAG_OBSOLETENAME, 0, 0, callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++int
++Pkg_obsoletes_overlap(pkg, s, b_nopromote=1, direction=-1)
++ URPM::Package pkg
++ char *s
++ int b_nopromote
++ int direction
++ PREINIT:
++ struct cb_overlap_s os;
++ char *eon = NULL;
++ char eonc = '\0';
++ CODE:
++ os.name = s;
++ os.flags = 0;
++ while (*s &amp;&amp; *s != ' ' &amp;&amp; *s != '[' &amp;&amp; *s != '&lt;' &amp;&amp; *s != '&gt;' &amp;&amp; *s != '=') ++s;
++ if (*s) {
++ eon = s;
++ while (*s) {
++ if (*s == ' ' || *s == '[' || *s == '*' || *s == ']');
++ else if (*s == '&lt;') os.flags |= RPMSENSE_LESS;
++ else if (*s == '&gt;') os.flags |= RPMSENSE_GREATER;
++ else if (*s == '=') os.flags |= RPMSENSE_EQUAL;
++ else break;
++ ++s;
++ }
++ os.evr = s;
++ } else
++ os.evr = &quot;&quot;;
++ os.direction = direction;
++ os.b_nopromote = b_nopromote;
++ /* mark end of name */
++ if (eon) { eonc = *eon; *eon = 0; }
++ /* return_list_str returns a negative value is the callback has returned non-zero */
++ RETVAL = return_list_str(pkg-&gt;obsoletes, pkg-&gt;h, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEFLAGS, RPMTAG_OBSOLETEVERSION,
++ callback_list_str_overlap, &amp;os) &lt; 0;
++ /* restore end of name */
++ if (eon) *eon = eonc;
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_conflicts(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;conflicts, pkg-&gt;h, RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTFLAGS, RPMTAG_CONFLICTVERSION,
++ callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++void
++Pkg_conflicts_nosense(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;conflicts, pkg-&gt;h, RPMTAG_CONFLICTNAME, 0, 0, callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++void
++Pkg_provides(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;provides, pkg-&gt;h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION,
++ callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++void
++Pkg_provides_nosense(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_str(pkg-&gt;provides, pkg-&gt;h, RPMTAG_PROVIDENAME, 0, 0, callback_list_str_xpush, NULL);
++ SPAGAIN;
++
++int
++Pkg_provides_overlap(pkg, s, b_nopromote=1, direction=1)
++ URPM::Package pkg
++ char *s
++ int b_nopromote
++ int direction
++ PREINIT:
++ struct cb_overlap_s os;
++ char *eon = NULL;
++ char eonc = '\0';
++ CODE:
++ os.name = s;
++ os.flags = 0;
++ while (*s &amp;&amp; *s != ' ' &amp;&amp; *s != '[' &amp;&amp; *s != '&lt;' &amp;&amp; *s != '&gt;' &amp;&amp; *s != '=') ++s;
++ if (*s) {
++ eon = s;
++ while (*s) {
++ if (*s == ' ' || *s == '[' || *s == '*' || *s == ']');
++ else if (*s == '&lt;') os.flags |= RPMSENSE_LESS;
++ else if (*s == '&gt;') os.flags |= RPMSENSE_GREATER;
++ else if (*s == '=') os.flags |= RPMSENSE_EQUAL;
++ else break;
++ ++s;
++ }
++ os.evr = s;
++ } else
++ os.evr = &quot;&quot;;
++ os.direction = direction;
++ os.b_nopromote = b_nopromote;
++ /* mark end of name */
++ if (eon) { eonc = *eon; *eon = 0; }
++ /* return_list_str returns a negative value is the callback has returned non-zero */
++ RETVAL = return_list_str(pkg-&gt;provides, pkg-&gt;h, RPMTAG_PROVIDENAME, RPMTAG_PROVIDEFLAGS, RPMTAG_PROVIDEVERSION,
++ callback_list_str_overlap, &amp;os) &lt; 0;
++ /* restore end of name */
++ if (eon) *eon = eonc;
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_buildarchs(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_BUILDARCHS);
++ SPAGAIN;
++
++void
++Pkg_excludearchs(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_EXCLUDEARCH);
++ SPAGAIN;
++
++void
++Pkg_exclusivearchs(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_EXCLUSIVEARCH);
++ SPAGAIN;
++
++void
++Pkg_dirnames(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_DIRNAMES);
++ SPAGAIN;
++
++void Pkg_distepoch(pkg)
++ URPM::Package pkg
++ PPCODE:
++#ifdef RPMTAG_DISTEPOCH
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_DISTEPOCH), 0)));
++ }
++#else
++ croak(&quot;distepoch isn't available with this rpm version&quot;);
++#endif
++
++void Pkg_disttag(pkg)
++ URPM::Package pkg
++ PPCODE:
++ if (pkg-&gt;h) {
++ XPUSHs(sv_2mortal(newSVpv(get_name(pkg-&gt;h, RPMTAG_DISTTAG), 0)));
++ }
++
++void
++Pkg_filelinktos(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_FILELINKTOS);
++ SPAGAIN;
++
++void
++Pkg_files(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_files(pkg-&gt;h, 0);
++ SPAGAIN;
++
++void
++Pkg_files_md5sum(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_FILEMD5S);
++ SPAGAIN;
++
++void
++Pkg_files_owner(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_FILEUSERNAME);
++ SPAGAIN;
++
++void
++Pkg_files_group(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_FILEGROUPNAME);
++ SPAGAIN;
++
++void
++Pkg_files_mtime(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_FILEMTIMES);
++ SPAGAIN;
++
++void
++Pkg_files_size(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_FILESIZES);
++ SPAGAIN;
++
++void
++Pkg_files_uid(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_FILEUIDS);
++ SPAGAIN;
++
++void
++Pkg_files_gid(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_FILEGIDS);
++ SPAGAIN;
++
++void
++Pkg_files_mode(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_uint_16(pkg-&gt;h, RPMTAG_FILEMODES);
++ SPAGAIN;
++
++void
++Pkg_files_flags(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_FILEFLAGS);
++ SPAGAIN;
++
++void
++Pkg_conf_files(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_files(pkg-&gt;h, FILTER_MODE_CONF_FILES);
++ SPAGAIN;
++
++void
++Pkg_changelog_time(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ return_list_int32_t(pkg-&gt;h, RPMTAG_CHANGELOGTIME);
++ SPAGAIN;
++
++void
++Pkg_changelog_name(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_CHANGELOGNAME);
++ SPAGAIN;
++
++void
++Pkg_changelog_text(pkg)
++ URPM::Package pkg
++ PPCODE:
++ PUTBACK;
++ xpush_simple_list_str(pkg-&gt;h, RPMTAG_CHANGELOGTEXT);
++ SPAGAIN;
++
++void
++Pkg_queryformat(pkg, fmt)
++ URPM::Package pkg
++ char *fmt
++ PREINIT:
++ char *s;
++ PPCODE:
++ if (pkg-&gt;h) {
++ s = headerFormat(pkg-&gt;h, fmt, NULL);
++ if (s) {
++ XPUSHs(sv_2mortal(newSVpv_utf8(s,0)));
++ }
++ }
++
++void
++Pkg_get_tag(pkg, tagname)
++ URPM::Package pkg
++ int tagname;
++ PPCODE:
++ PUTBACK;
++ return_list_tag(pkg, tagname);
++ SPAGAIN;
++
++void
++Pkg_get_tag_modifiers(pkg, tagname)
++ URPM::Package pkg
++ int tagname;
++ PPCODE:
++ PUTBACK;
++ return_list_tag_modifier(pkg-&gt;h, tagname);
++ SPAGAIN;
++
++void
++Pkg_pack_header(pkg)
++ URPM::Package pkg
++ CODE:
++ pack_header(pkg);
++
++int
++Pkg_update_header(pkg, filename, ...)
++ URPM::Package pkg
++ char *filename
++ PREINIT:
++ int packing = 0;
++ int keep_all_tags = 0;
++ CODE:
++ /* compability mode with older interface of parse_hdlist */
++ if (items == 3) {
++ packing = SvIV(ST(2));
++ } else if (items &gt; 3) {
++ int i;
++ for (i = 2; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 7 &amp;&amp; !memcmp(s, &quot;packing&quot;, 7)) {
++ packing = SvTRUE(ST(i + 1));
++ } else if (len == 13 &amp;&amp; !memcmp(s, &quot;keep_all_tags&quot;, 13)) {
++ keep_all_tags = SvTRUE(ST(i+1));
++ }
++ }
++ }
++ RETVAL = update_header(filename, pkg, !packing &amp;&amp; keep_all_tags, RPMVSF_DEFAULT);
++ if (RETVAL &amp;&amp; packing) pack_header(pkg);
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_free_header(pkg)
++ URPM::Package pkg
++ CODE:
++ if (pkg-&gt;h &amp;&amp; !(pkg-&gt;flag &amp; FLAG_NO_HEADER_FREE)) pkg-&gt;h = headerFree(pkg-&gt;h);
++ pkg-&gt;h = NULL;
++
++void
++Pkg_build_info(pkg, fileno, provides_files=NULL)
++ URPM::Package pkg
++ int fileno
++ char *provides_files
++ CODE:
++ if (pkg-&gt;info) {
++ char buff[65536];
++ size_t size;
++
++ /* info line should be the last to be written */
++ if (pkg-&gt;provides &amp;&amp; *pkg-&gt;provides) {
++ size = snprintf(buff, sizeof(buff), &quot;@provides@%s\n&quot;, pkg-&gt;provides);
++ if (size &lt; sizeof(buff)) {
++ if (provides_files &amp;&amp; *provides_files) {
++ --size;
++ size += snprintf(buff+size, sizeof(buff)-size, &quot;@%s\n&quot;, provides_files);
++ }
++ write_nocheck(fileno, buff, size);
++ }
++ }
++ if (pkg-&gt;conflicts &amp;&amp; *pkg-&gt;conflicts) {
++ size = snprintf(buff, sizeof(buff), &quot;@conflicts@%s\n&quot;, pkg-&gt;conflicts);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ if (pkg-&gt;obsoletes &amp;&amp; *pkg-&gt;obsoletes) {
++ size = snprintf(buff, sizeof(buff), &quot;@obsoletes@%s\n&quot;, pkg-&gt;obsoletes);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ if (pkg-&gt;requires &amp;&amp; *pkg-&gt;requires) {
++ size = snprintf(buff, sizeof(buff), &quot;@requires@%s\n&quot;, pkg-&gt;requires);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ if (pkg-&gt;suggests &amp;&amp; *pkg-&gt;suggests) {
++ size = snprintf(buff, sizeof(buff), &quot;@suggests@%s\n&quot;, pkg-&gt;suggests);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ if (pkg-&gt;summary &amp;&amp; *pkg-&gt;summary) {
++ size = snprintf(buff, sizeof(buff), &quot;@summary@%s\n&quot;, pkg-&gt;summary);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ if (pkg-&gt;filesize) {
++ size = snprintf(buff, sizeof(buff), &quot;@filesize@%d\n&quot;, pkg-&gt;filesize);
++ if (size &lt; sizeof(buff)) write_nocheck(fileno, buff, size);
++ }
++ size = snprintf(buff, sizeof(buff), &quot;@info@%s\n&quot;, pkg-&gt;info);
++ write_nocheck(fileno, buff, size);
++ } else croak(&quot;no info available for package %s&quot;,
++ pkg-&gt;h ? get_name(pkg-&gt;h, RPMTAG_NAME) : &quot;-&quot;);
++
++void
++Pkg_build_header(pkg, fileno)
++ URPM::Package pkg
++ int fileno
++ CODE:
++ if (pkg-&gt;h) {
++ FD_t fd;
++
++ if ((fd = fdDup(fileno)) != NULL) {
++ headerWrite(fd, pkg-&gt;h, HEADER_MAGIC_YES);
++ Fclose(fd);
++ } else croak(&quot;unable to get rpmio handle on fileno %d&quot;, fileno);
++ } else croak(&quot;no header available for package&quot;);
++
++int
++Pkg_flag(pkg, name)
++ URPM::Package pkg
++ char *name
++ PREINIT:
++ unsigned mask;
++ CODE:
++ if (!strcmp(name, &quot;skip&quot;)) mask = FLAG_SKIP;
++ else if (!strcmp(name, &quot;disable_obsolete&quot;)) mask = FLAG_DISABLE_OBSOLETE;
++ else if (!strcmp(name, &quot;installed&quot;)) mask = FLAG_INSTALLED;
++ else if (!strcmp(name, &quot;requested&quot;)) mask = FLAG_REQUESTED;
++ else if (!strcmp(name, &quot;required&quot;)) mask = FLAG_REQUIRED;
++ else if (!strcmp(name, &quot;upgrade&quot;)) mask = FLAG_UPGRADE;
++ else croak(&quot;unknown flag: %s&quot;, name);
++ RETVAL = pkg-&gt;flag &amp; mask;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag(pkg, name, value=1)
++ URPM::Package pkg
++ char *name
++ int value
++ PREINIT:
++ unsigned mask;
++ CODE:
++ if (!strcmp(name, &quot;skip&quot;)) mask = FLAG_SKIP;
++ else if (!strcmp(name, &quot;disable_obsolete&quot;)) mask = FLAG_DISABLE_OBSOLETE;
++ else if (!strcmp(name, &quot;installed&quot;)) mask = FLAG_INSTALLED;
++ else if (!strcmp(name, &quot;requested&quot;)) mask = FLAG_REQUESTED;
++ else if (!strcmp(name, &quot;required&quot;)) mask = FLAG_REQUIRED;
++ else if (!strcmp(name, &quot;upgrade&quot;)) mask = FLAG_UPGRADE;
++ else croak(&quot;unknown flag: %s&quot;, name);
++ RETVAL = pkg-&gt;flag &amp; mask;
++ if (value) pkg-&gt;flag |= mask;
++ else pkg-&gt;flag &amp;= ~mask;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_skip(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_SKIP;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_skip(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_SKIP;
++ if (value) pkg-&gt;flag |= FLAG_SKIP;
++ else pkg-&gt;flag &amp;= ~FLAG_SKIP;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_base(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_BASE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_base(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_BASE;
++ if (value) pkg-&gt;flag |= FLAG_BASE;
++ else pkg-&gt;flag &amp;= ~FLAG_BASE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_disable_obsolete(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_DISABLE_OBSOLETE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_disable_obsolete(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_DISABLE_OBSOLETE;
++ if (value) pkg-&gt;flag |= FLAG_DISABLE_OBSOLETE;
++ else pkg-&gt;flag &amp;= ~FLAG_DISABLE_OBSOLETE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_installed(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_INSTALLED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_installed(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_INSTALLED;
++ if (value) pkg-&gt;flag |= FLAG_INSTALLED;
++ else pkg-&gt;flag &amp;= ~FLAG_INSTALLED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_requested(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_REQUESTED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_requested(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_REQUESTED;
++ if (value) pkg-&gt;flag |= FLAG_REQUESTED;
++ else pkg-&gt;flag &amp;= ~FLAG_REQUESTED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_required(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_REQUIRED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_required(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_REQUIRED;
++ if (value) pkg-&gt;flag |= FLAG_REQUIRED;
++ else pkg-&gt;flag &amp;= ~FLAG_REQUIRED;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_upgrade(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_UPGRADE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_flag_upgrade(pkg, value=1)
++ URPM::Package pkg
++ int value
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_UPGRADE;
++ if (value) pkg-&gt;flag |= FLAG_UPGRADE;
++ else pkg-&gt;flag &amp;= ~FLAG_UPGRADE;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_selected(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = pkg-&gt;flag &amp; FLAG_UPGRADE ? pkg-&gt;flag &amp; (FLAG_BASE | FLAG_REQUIRED) : 0;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_flag_available(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = (pkg-&gt;flag &amp; FLAG_INSTALLED &amp;&amp; !(pkg-&gt;flag &amp; FLAG_UPGRADE)) ||
++ (pkg-&gt;flag &amp; FLAG_UPGRADE ? pkg-&gt;flag &amp; (FLAG_BASE | FLAG_REQUIRED) : 0);
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_rate(pkg)
++ URPM::Package pkg
++ CODE:
++ RETVAL = (pkg-&gt;flag &amp; FLAG_RATE) &gt;&gt; FLAG_RATE_POS;
++ OUTPUT:
++ RETVAL
++
++int
++Pkg_set_rate(pkg, rate)
++ URPM::Package pkg
++ int rate
++ CODE:
++ RETVAL = (pkg-&gt;flag &amp; FLAG_RATE) &gt;&gt; FLAG_RATE_POS;
++ pkg-&gt;flag &amp;= ~FLAG_RATE;
++ pkg-&gt;flag |= (rate &gt;= 0 &amp;&amp; rate &lt;= FLAG_RATE_MAX ? rate : FLAG_RATE_INVALID) &lt;&lt; FLAG_RATE_POS;
++ OUTPUT:
++ RETVAL
++
++void
++Pkg_rflags(pkg)
++ URPM::Package pkg
++ PREINIT:
++ I32 gimme = GIMME_V;
++ PPCODE:
++ if (gimme == G_ARRAY &amp;&amp; pkg-&gt;rflags != NULL) {
++ char *s = pkg-&gt;rflags;
++ char *eos;
++ while ((eos = strchr(s, '\t')) != NULL) {
++ XPUSHs(sv_2mortal(newSVpv(s, eos-s)));
++ s = eos + 1;
++ }
++ XPUSHs(sv_2mortal(newSVpv(s, 0)));
++ }
++
++void
++Pkg_set_rflags(pkg, ...)
++ URPM::Package pkg
++ PREINIT:
++ I32 gimme = GIMME_V;
++ char *new_rflags;
++ STRLEN total_len;
++ int i;
++ PPCODE:
++ total_len = 0;
++ for (i = 1; i &lt; items; ++i)
++ total_len += SvCUR(ST(i)) + 1;
++
++ new_rflags = malloc(total_len);
++ total_len = 0;
++ for (i = 1; i &lt; items; ++i) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++ memcpy(new_rflags + total_len, s, len);
++ new_rflags[total_len + len] = '\t';
++ total_len += len + 1;
++ }
++ new_rflags[total_len - 1] = 0; /* but mark end-of-string correctly */
++
++ if (gimme == G_ARRAY &amp;&amp; pkg-&gt;rflags != NULL) {
++ char *s = pkg-&gt;rflags;
++ char *eos;
++ while ((eos = strchr(s, '\t')) != NULL) {
++ XPUSHs(sv_2mortal(newSVpv(s, eos-s)));
++ s = eos + 1;
++ }
++ XPUSHs(sv_2mortal(newSVpv(s, 0)));
++ }
++
++ free(pkg-&gt;rflags);
++ pkg-&gt;rflags = new_rflags;
++
++
++MODULE = URPM PACKAGE = URPM::DB PREFIX = Db_
++
++URPM::DB
++Db_open(prefix=NULL, write_perm=0)
++ char *prefix
++ int write_perm
++ PREINIT:
++ URPM__DB db;
++ CODE:
++ read_config_files(0);
++ db = malloc(sizeof(struct s_Transaction));
++ db-&gt;count = 1;
++ db-&gt;ts = rpmtsCreate();
++ rpmtsSetRootDir(db-&gt;ts, prefix &amp;&amp; prefix[0] ? prefix : NULL);
++ if (rpmtsOpenDB(db-&gt;ts, write_perm ? O_RDWR | O_CREAT : O_RDONLY) == 0) {
++ RETVAL = db;
++ } else {
++ RETVAL = NULL;
++ (void)rpmtsFree(db-&gt;ts);
++ free(db);
++ }
++ OUTPUT:
++ RETVAL
++
++int
++Db_rebuild(prefix=&quot;&quot;)
++ char *prefix
++ PREINIT:
++ rpmts ts;
++ CODE:
++ read_config_files(0);
++ ts = rpmtsCreate();
++ rpmtsSetRootDir(ts, prefix);
++ RETVAL = rpmtsRebuildDB(ts) == 0;
++ (void)rpmtsFree(ts);
++ OUTPUT:
++ RETVAL
++
++int
++Db_verify(prefix=&quot;&quot;)
++ char *prefix
++ PREINIT:
++ rpmts ts;
++ CODE:
++ ts = rpmtsCreate();
++ rpmtsSetRootDir(ts, prefix);
++ RETVAL = rpmtsVerifyDB(ts) == 0;
++ ts = rpmtsFree(ts);
++ OUTPUT:
++ RETVAL
++
++void
++Db_DESTROY(db)
++ URPM::DB db
++ CODE:
++ (void)rpmtsFree(db-&gt;ts);
++ if (!--db-&gt;count) free(db);
++
++int
++Db_traverse(db,callback)
++ URPM::DB db
++ SV *callback
++ PREINIT:
++ Header header;
++ rpmdbMatchIterator mi;
++ int count = 0;
++ CODE:
++ db-&gt;ts = rpmtsLink(db-&gt;ts, &quot;URPM::DB::traverse&quot;);
++ ts_nosignature(db-&gt;ts);
++ mi = rpmtsInitIterator(db-&gt;ts, RPMDBI_PACKAGES, NULL, 0);
++ while ((header = rpmdbNextIterator(mi))) {
++ if (SvROK(callback)) {
++ dSP;
++ URPM__Package pkg = calloc(1, sizeof(struct s_Package));
++
++ pkg-&gt;flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE;
++ pkg-&gt;h = header;
++
++ PUSHMARK(SP);
++ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;, pkg)));
++ PUTBACK;
++
++ call_sv(callback, G_DISCARD | G_SCALAR);
++
++ SPAGAIN;
++ pkg-&gt;h = 0; /* avoid using it anymore, in case it has been copied inside callback */
++ }
++ ++count;
++ }
++ rpmdbFreeIterator(mi);
++ (void)rpmtsFree(db-&gt;ts);
++ RETVAL = count;
++ OUTPUT:
++ RETVAL
++
++int
++Db_traverse_tag(db,tag,names,callback)
++ URPM::DB db
++ char *tag
++ SV *names
++ SV *callback
++ PREINIT:
++ Header header;
++ rpmdbMatchIterator mi;
++ int count = 0;
++ CODE:
++ if (SvROK(names) &amp;&amp; SvTYPE(SvRV(names)) == SVt_PVAV) {
++ AV* names_av = (AV*)SvRV(names);
++ int len = av_len(names_av);
++ int i, rpmtag;
++
++ rpmtag = rpmtag_from_string(tag);
++
++ for (i = 0; i &lt;= len; ++i) {
++ STRLEN str_len;
++ SV **isv = av_fetch(names_av, i, 0);
++ char *name = SvPV(*isv, str_len);
++ db-&gt;ts = rpmtsLink(db-&gt;ts, &quot;URPM::DB::traverse_tag&quot;);
++ ts_nosignature(db-&gt;ts);
++ mi = rpmtsInitIterator(db-&gt;ts, rpmtag, name, str_len);
++ while ((header = rpmdbNextIterator(mi))) {
++ if (SvROK(callback)) {
++ dSP;
++ URPM__Package pkg = calloc(1, sizeof(struct s_Package));
++
++ pkg-&gt;flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE;
++ pkg-&gt;h = header;
++
++ PUSHMARK(SP);
++ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;, pkg)));
++ PUTBACK;
++
++ call_sv(callback, G_DISCARD | G_SCALAR);
++
++ SPAGAIN;
++ pkg-&gt;h = 0; /* avoid using it anymore, in case it has been copied inside callback */
++ }
++ ++count;
++ }
++ (void)rpmdbFreeIterator(mi);
++ (void)rpmtsFree(db-&gt;ts);
++ }
++ } else croak(&quot;bad arguments list&quot;);
++ RETVAL = count;
++ OUTPUT:
++ RETVAL
++
++int
++Db_traverse_tag_find(db,tag,name,callback)
++ URPM::DB db
++ char *tag
++ char *name
++ SV *callback
++ PREINIT:
++ Header header;
++ rpmdbMatchIterator mi;
++ CODE:
++ int rpmtag = rpmtag_from_string(tag);
++ int found = 0;
++
++ db-&gt;ts = rpmtsLink(db-&gt;ts, &quot;URPM::DB::traverse_tag&quot;);
++ ts_nosignature(db-&gt;ts);
++ mi = rpmtsInitIterator(db-&gt;ts, rpmtag, name, 0);
++ while ((header = rpmdbNextIterator(mi))) {
++ dSP;
++ URPM__Package pkg = calloc(1, sizeof(struct s_Package));
++
++ pkg-&gt;flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE;
++ pkg-&gt;h = header;
++
++ PUSHMARK(SP);
++ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;, pkg)));
++ PUTBACK;
++
++ int count = call_sv(callback, G_SCALAR);
++
++ SPAGAIN;
++ pkg-&gt;h = 0; /* avoid using it anymore, in case it has been copied inside callback */
++
++ if (count == 1 &amp;&amp; POPi) {
++ found = 1;
++ break;
++ }
++ }
++ (void)rpmdbFreeIterator(mi);
++ (void)rpmtsFree(db-&gt;ts);
++ RETVAL = found;
++ OUTPUT:
++ RETVAL
++
++URPM::Transaction
++Db_create_transaction(db, prefix=&quot;/&quot;)
++ URPM::DB db
++ char *prefix
++ CODE:
++ /* this is *REALLY* dangerous to create a new transaction while another is open,
++ so use the db transaction instead. */
++ db-&gt;ts = rpmtsLink(db-&gt;ts, &quot;URPM::DB::create_transaction&quot;);
++ ++db-&gt;count;
++ RETVAL = db;
++ OUTPUT:
++ RETVAL
++
++
++MODULE = URPM PACKAGE = URPM::Transaction PREFIX = Trans_
++
++void
++Trans_DESTROY(trans)
++ URPM::Transaction trans
++ CODE:
++ (void)rpmtsFree(trans-&gt;ts);
++ if (!--trans-&gt;count) free(trans);
++
++void
++Trans_set_script_fd(trans, fdno)
++ URPM::Transaction trans
++ int fdno
++ CODE:
++ rpmtsSetScriptFd(trans-&gt;ts, fdDup(fdno));
++
++int
++Trans_add(trans, pkg, ...)
++ URPM::Transaction trans
++ URPM::Package pkg
++ CODE:
++ if ((pkg-&gt;flag &amp; FLAG_ID) &lt;= FLAG_ID_MAX &amp;&amp; pkg-&gt;h != NULL) {
++ int update = 0;
++#ifndef RPM_ORG
++ rpmRelocation relocations = NULL;
++#else
++ rpmRelocation *relocations = NULL;
++#endif
++ /* compability mode with older interface of add */
++ if (items == 3) {
++ update = SvIV(ST(2));
++ } else if (items &gt; 3) {
++ int i;
++ for (i = 2; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 6 &amp;&amp; !memcmp(s, &quot;update&quot;, 6)) {
++ update = SvIV(ST(i+1));
++ } else if (len == 11 &amp;&amp; !memcmp(s, &quot;excludepath&quot;, 11)) {
++ if (SvROK(ST(i+1)) &amp;&amp; SvTYPE(SvRV(ST(i+1))) == SVt_PVAV) {
++ AV *excludepath = (AV*)SvRV(ST(i+1));
++ I32 j = 1 + av_len(excludepath);
++#ifndef RPM_ORG
++ int relno = 0;
++ relocations = malloc(sizeof(rpmRelocation));
++#else
++ relocations = calloc(j + 1, sizeof(rpmRelocation));
++#endif
++ while (--j &gt;= 0) {
++ SV **e = av_fetch(excludepath, j, 0);
++ if (e != NULL &amp;&amp; *e != NULL) {
++#ifndef RPM_ORG
++ rpmfiAddRelocation(&amp;relocations, &amp;relno, SvPV_nolen(*e), NULL);
++#else
++ relocations[j].oldPath = SvPV_nolen(*e);
++#endif
++ }
++ }
++ }
++ }
++ }
++ }
++ RETVAL = rpmtsAddInstallElement(trans-&gt;ts, pkg-&gt;h, (fnpyKey)(1+(long)(pkg-&gt;flag &amp; FLAG_ID)), update, relocations) == 0;
++ /* free allocated memory, check rpm is copying it just above, at least in 4.0.4 */
++#ifndef RPM_ORG
++ rpmfiFreeRelocations(relocations);
++#else
++ free(relocations);
++#endif
++ } else RETVAL = 0;
++ OUTPUT:
++ RETVAL
++
++int
++Trans_remove(trans, name)
++ URPM::Transaction trans
++ char *name
++ PREINIT:
++ Header h;
++ rpmdbMatchIterator mi;
++ int count = 0;
++ char *boa = NULL, *bor = NULL;
++ CODE:
++ /* hide arch in name if present */
++ if ((boa = strrchr(name, '.'))) {
++ *boa = 0;
++ if ((bor = strrchr(name, '-'))) {
++ *bor = 0;
++ if (!strrchr(name, '-')) {
++ *boa = '.'; boa = NULL;
++ }
++ *bor = '-'; bor = NULL;
++ } else {
++ *boa = '.'; boa = NULL;
++ }
++ }
++ mi = rpmtsInitIterator(trans-&gt;ts, RPMDBI_LABEL, name, 0);
++ while ((h = rpmdbNextIterator(mi))) {
++ unsigned int recOffset = rpmdbGetIteratorOffset(mi);
++ if (recOffset != 0) {
++ rpmtsAddEraseElement(trans-&gt;ts, h, recOffset);
++ ++count;
++ }
++ }
++ rpmdbFreeIterator(mi);
++ if (boa) *boa = '.';
++ RETVAL=count;
++ OUTPUT:
++ RETVAL
++
++int
++Trans_traverse(trans, callback)
++ URPM::Transaction trans
++ SV *callback
++ PREINIT:
++ rpmdbMatchIterator mi;
++ Header h;
++ int c = 0;
++ CODE:
++ mi = rpmtsInitIterator(trans-&gt;ts, RPMDBI_PACKAGES, NULL, 0);
++ while ((h = rpmdbNextIterator(mi))) {
++ if (SvROK(callback)) {
++ dSP;
++ URPM__Package pkg = calloc(1, sizeof(struct s_Package));
++ pkg-&gt;flag = FLAG_ID_INVALID | FLAG_NO_HEADER_FREE;
++ pkg-&gt;h = h;
++ PUSHMARK(SP);
++ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;, pkg)));
++ PUTBACK;
++ call_sv(callback, G_DISCARD | G_SCALAR);
++ SPAGAIN;
++ pkg-&gt;h = 0; /* avoid using it anymore, in case it has been copied inside callback */
++ }
++ ++c;
++ }
++ rpmdbFreeIterator(mi);
++ RETVAL = c;
++ OUTPUT:
++ RETVAL
++
++void
++Trans_check(trans, ...)
++ URPM::Transaction trans
++ PREINIT:
++ I32 gimme = GIMME_V;
++ int translate_message = 0;
++ int i;
++ PPCODE:
++ for (i = 1; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 17 &amp;&amp; !memcmp(s, &quot;translate_message&quot;, 17)) {
++ translate_message = SvIV(ST(i+1));
++ }
++ }
++ if (rpmtsCheck(trans-&gt;ts)) {
++ if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSViv(0)));
++ } else if (gimme == G_ARRAY) {
++ XPUSHs(sv_2mortal(newSVpv(&quot;error while checking dependencies&quot;, 0)));
++ }
++ } else {
++ rpmps ps = rpmtsProblems(trans-&gt;ts);
++ if (rpmpsNumProblems(ps) &gt; 0) {
++ if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSViv(0)));
++ } else if (gimme == G_ARRAY) {
++ /* now translation is handled by rpmlib, but only for version 4.2 and above */
++ PUTBACK;
++ return_problems(ps, 1, 0);
++ SPAGAIN;
++ }
++ } else if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSViv(1)));
++ }
++ ps = rpmpsFree(ps);
++ }
++
++void
++Trans_order(trans)
++ URPM::Transaction trans
++ PREINIT:
++ I32 gimme = GIMME_V;
++ PPCODE:
++ if (rpmtsOrder(trans-&gt;ts) == 0) {
++ if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSViv(1)));
++ }
++ } else {
++ if (gimme == G_SCALAR) {
++ XPUSHs(sv_2mortal(newSViv(0)));
++ } else if (gimme == G_ARRAY) {
++ XPUSHs(sv_2mortal(newSVpv(&quot;error while ordering dependencies&quot;, 0)));
++ }
++ }
++
++int
++Trans_NElements(trans)
++ URPM::Transaction trans
++ CODE:
++ RETVAL = rpmtsNElements(trans-&gt;ts);
++ OUTPUT:
++ RETVAL
++
++char *
++Trans_Element_name(trans, index)
++ URPM::Transaction trans
++ int index
++ CODE:
++ rpmte te = rpmtsElement(trans-&gt;ts, index);
++ RETVAL = te ? (char *) rpmteN(te) : NULL;
++ OUTPUT:
++ RETVAL
++
++char *
++Trans_Element_version(trans, index)
++ URPM::Transaction trans
++ int index
++ CODE:
++ rpmte te = rpmtsElement(trans-&gt;ts, index);
++ RETVAL = te ? (char *) rpmteV(te) : NULL;
++ OUTPUT:
++ RETVAL
++
++char *
++Trans_Element_release(trans, index)
++ URPM::Transaction trans
++ int index
++ CODE:
++ rpmte te = rpmtsElement(trans-&gt;ts, index);
++ RETVAL = te ? (char *) rpmteR(te) : NULL;
++ OUTPUT:
++ RETVAL
++
++char *
++Trans_Element_fullname(trans, index)
++ URPM::Transaction trans
++ int index
++ CODE:
++ rpmte te = rpmtsElement(trans-&gt;ts, index);
++ RETVAL = te ? (char *) rpmteNEVRA(te) : NULL;
++ OUTPUT:
++ RETVAL
++
++void
++Trans_run(trans, data, ...)
++ URPM::Transaction trans
++ SV *data
++ PREINIT:
++ struct s_TransactionData td = { NULL, NULL, NULL, NULL, NULL, 100000, data };
++ rpmtransFlags transFlags = RPMTRANS_FLAG_NONE;
++ int probFilter = 0;
++ int translate_message = 0, raw_message = 0;
++ int i;
++ PPCODE:
++ for (i = 2 ; i &lt; items - 1 ; i += 2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 4 &amp;&amp; !memcmp(s, &quot;test&quot;, 4)) {
++ if (SvIV(ST(i+1))) transFlags |= RPMTRANS_FLAG_TEST;
++ } else if (len == 11 &amp;&amp; !memcmp(s, &quot;excludedocs&quot;, 11)) {
++ if (SvIV(ST(i+1))) transFlags |= RPMTRANS_FLAG_NODOCS;
++ } else if (len == 5) {
++ if (!memcmp(s, &quot;force&quot;, 5)) {
++ if (SvIV(ST(i+1))) probFilter |= (RPMPROB_FILTER_REPLACEPKG |
++ RPMPROB_FILTER_REPLACEOLDFILES |
++ RPMPROB_FILTER_REPLACENEWFILES |
++ RPMPROB_FILTER_OLDPACKAGE);
++ } else if (!memcmp(s, &quot;delta&quot;, 5))
++ td.min_delta = SvIV(ST(i+1));
++ } else if (len == 6 &amp;&amp; !memcmp(s, &quot;nosize&quot;, 6)) {
++ if (SvIV(ST(i+1))) probFilter |= (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES);
++ } else if (len == 9 &amp;&amp; !memcmp(s, &quot;noscripts&quot;, 9)) {
++ if (SvIV(ST(i+1))) transFlags |= (RPMTRANS_FLAG_NOSCRIPTS |
++ RPMTRANS_FLAG_NOPRE |
++ RPMTRANS_FLAG_NOPREUN |
++ RPMTRANS_FLAG_NOPOST |
++ RPMTRANS_FLAG_NOPOSTUN );
++ } else if (len == 10 &amp;&amp; !memcmp(s, &quot;oldpackage&quot;, 10)) {
++ if (SvIV(ST(i+1))) probFilter |= RPMPROB_FILTER_OLDPACKAGE;
++ } else if (len == 11 &amp;&amp; !memcmp(s, &quot;replacepkgs&quot;, 11)) {
++ if (SvIV(ST(i+1))) probFilter |= RPMPROB_FILTER_REPLACEPKG;
++ } else if (len == 11 &amp;&amp; !memcmp(s, &quot;raw_message&quot;, 11)) {
++ raw_message = 1;
++ } else if (len == 12 &amp;&amp; !memcmp(s, &quot;replacefiles&quot;, 12)) {
++ if (SvIV(ST(i+1))) probFilter |= RPMPROB_FILTER_REPLACEOLDFILES | RPMPROB_FILTER_REPLACENEWFILES;
++ } else if (len == 9 &amp;&amp; !memcmp(s, &quot;repackage&quot;, 9)) {
++ if (SvIV(ST(i+1))) transFlags |= RPMTRANS_FLAG_REPACKAGE;
++ } else if (len == 6 &amp;&amp; !memcmp(s, &quot;justdb&quot;, 6)) {
++ if (SvIV(ST(i+1))) transFlags |= RPMTRANS_FLAG_JUSTDB;
++ } else if (len == 10 &amp;&amp; !memcmp(s, &quot;ignorearch&quot;, 10)) {
++ if (SvIV(ST(i+1))) probFilter |= RPMPROB_FILTER_IGNOREARCH;
++ } else if (len == 17 &amp;&amp; !memcmp(s, &quot;translate_message&quot;, 17))
++ translate_message = 1;
++ else if (len &gt;= 9 &amp;&amp; !memcmp(s, &quot;callback_&quot;, 9)) {
++ if (len == 9+4 &amp;&amp; !memcmp(s+9, &quot;open&quot;, 4)) {
++ if (SvROK(ST(i+1))) td.callback_open = ST(i+1);
++ } else if (len == 9+5 &amp;&amp; !memcmp(s+9, &quot;close&quot;, 5)) {
++ if (SvROK(ST(i+1))) td.callback_close = ST(i+1);
++ } else if (len == 9+5 &amp;&amp; !memcmp(s+9, &quot;trans&quot;, 5)) {
++ if (SvROK(ST(i+1))) td.callback_trans = ST(i+1);
++ } else if (len == 9+6 &amp;&amp; !memcmp(s+9, &quot;uninst&quot;, 6)) {
++ if (SvROK(ST(i+1))) td.callback_uninst = ST(i+1);
++ } else if (len == 9+4 &amp;&amp; !memcmp(s+9, &quot;inst&quot;, 4)) {
++ if (SvROK(ST(i+1))) td.callback_inst = ST(i+1);
++ }
++ }
++ }
++ /* check macros */
++ {
++ char *repa = rpmExpand(&quot;%_repackage_all_erasures&quot;, NULL);
++ if (repa &amp;&amp; *repa &amp;&amp; *repa != '0')
++ transFlags |= RPMTRANS_FLAG_REPACKAGE;
++ if (repa) free(repa);
++ }
++ rpmtsSetFlags(trans-&gt;ts, transFlags);
++ trans-&gt;ts = rpmtsLink(trans-&gt;ts, &quot;URPM::Transaction::run&quot;);
++ rpmtsSetNotifyCallback(trans-&gt;ts, rpmRunTransactions_callback, &amp;td);
++ if (rpmtsRun(trans-&gt;ts, NULL, probFilter) &gt; 0) {
++ rpmps ps = rpmtsProblems(trans-&gt;ts);
++ PUTBACK;
++ return_problems(ps, translate_message, raw_message || !translate_message);
++ SPAGAIN;
++ ps = rpmpsFree(ps);
++ }
++ rpmtsEmpty(trans-&gt;ts);
++ (void)rpmtsFree(trans-&gt;ts);
++
++MODULE = URPM PACKAGE = URPM PREFIX = Urpm_
++
++BOOT:
++(void) read_config_files(0);
++
++void
++Urpm_bind_rpm_textdomain_codeset()
++ CODE:
++ rpm_codeset_is_utf8 = 1;
++ bind_textdomain_codeset(&quot;rpm&quot;, &quot;UTF-8&quot;);
++
++int
++Urpm_read_config_files()
++ CODE:
++ RETVAL = (read_config_files(1) == 0); /* force re-read of configuration files */
++ OUTPUT:
++ RETVAL
++
++void
++Urpm_list_rpm_tag(urpm=Nullsv)
++ SV *urpm
++ CODE:
++ croak(&quot;list_rpm_tag() has been removed from perl-URPM. please report if you need it back&quot;);
++
++int
++rpmvercmp(one, two)
++ char *one
++ char *two
++
++int
++Urpm_ranges_overlap(a, b, b_nopromote=1)
++ char *a
++ char *b
++ int b_nopromote
++ PREINIT:
++ char *sa = a, *sb = b;
++ int aflags = 0, bflags = 0;
++ CODE:
++ while (*sa &amp;&amp; *sa != ' ' &amp;&amp; *sa != '[' &amp;&amp; *sa != '&lt;' &amp;&amp; *sa != '&gt;' &amp;&amp; *sa != '=' &amp;&amp; *sa == *sb) {
++ ++sa;
++ ++sb;
++ }
++ if ((*sa &amp;&amp; *sa != ' ' &amp;&amp; *sa != '[' &amp;&amp; *sa != '&lt;' &amp;&amp; *sa != '&gt;' &amp;&amp; *sa != '=') ||
++ (*sb &amp;&amp; *sb != ' ' &amp;&amp; *sb != '[' &amp;&amp; *sb != '&lt;' &amp;&amp; *sb != '&gt;' &amp;&amp; *sb != '=')) {
++ /* the strings are sure to be different */
++ RETVAL = 0;
++ } else {
++ while (*sa) {
++ if (*sa == ' ' || *sa == '[' || *sa == '*' || *sa == ']');
++ else if (*sa == '&lt;') aflags |= RPMSENSE_LESS;
++ else if (*sa == '&gt;') aflags |= RPMSENSE_GREATER;
++ else if (*sa == '=') aflags |= RPMSENSE_EQUAL;
++ else break;
++ ++sa;
++ }
++ while (*sb) {
++ if (*sb == ' ' || *sb == '[' || *sb == '*' || *sb == ']');
++ else if (*sb == '&lt;') bflags |= RPMSENSE_LESS;
++ else if (*sb == '&gt;') bflags |= RPMSENSE_GREATER;
++ else if (*sb == '=') bflags |= RPMSENSE_EQUAL;
++ else break;
++ ++sb;
++ }
++ RETVAL = ranges_overlap(aflags, sa, bflags, sb, b_nopromote);
++ }
++ OUTPUT:
++ RETVAL
++
++void
++Urpm_parse_synthesis__XS(urpm, filename, ...)
++ SV *urpm
++ char *filename
++ PPCODE:
++ if (SvROK(urpm) &amp;&amp; SvTYPE(SvRV(urpm)) == SVt_PVHV) {
++ SV **fdepslist = hv_fetch((HV*)SvRV(urpm), &quot;depslist&quot;, 8, 0);
++ AV *depslist = fdepslist &amp;&amp; SvROK(*fdepslist) &amp;&amp; SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
++ SV **fprovides = hv_fetch((HV*)SvRV(urpm), &quot;provides&quot;, 8, 0);
++ HV *provides = fprovides &amp;&amp; SvROK(*fprovides) &amp;&amp; SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
++ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), &quot;obsoletes&quot;, 9, 0);
++ HV *obsoletes = fobsoletes &amp;&amp; SvROK(*fobsoletes) &amp;&amp; SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
++
++ if (depslist != NULL) {
++ char buff[65536];
++ char *p, *eol;
++ int buff_len;
++ struct s_Package pkg;
++ gzFile f;
++ int start_id = 1 + av_len(depslist);
++ SV *callback = NULL;
++
++ if (items &gt; 2) {
++ int i;
++ for (i = 2; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 8 &amp;&amp; !memcmp(s, &quot;callback&quot;, 8)) {
++ if (SvROK(ST(i+1))) callback = ST(i+1);
++ }
++ }
++ }
++
++ PUTBACK;
++ if ((f = gzopen(filename, &quot;rb&quot;)) != NULL) {
++ memset(&amp;pkg, 0, sizeof(struct s_Package));
++ buff[sizeof(buff)-1] = 0;
++ p = buff;
++ int ok = 1;
++ while ((buff_len = gzread(f, p, sizeof(buff)-1-(p-buff))) &gt;= 0 &amp;&amp;
++ (buff_len += p-buff)) {
++ buff[buff_len] = 0;
++ p = buff;
++ if ((eol = strchr(p, '\n')) != NULL) {
++ do {
++ *eol++ = 0;
++ if (!parse_line(depslist, provides, obsoletes, &amp;pkg, p, urpm, callback)) { ok = 0; break; }
++ p = eol;
++ } while ((eol = strchr(p, '\n')) != NULL);
++ } else {
++ /* a line larger than sizeof(buff) has been encountered, bad file problably */
++ fprintf(stderr, &quot;invalid line &lt;%s&gt;\n&quot;, p);
++ ok = 0;
++ break;
++ }
++ if (gzeof(f)) {
++ if (!parse_line(depslist, provides, obsoletes, &amp;pkg, p, urpm, callback)) ok = 0;
++ break;
++ } else {
++ /* move the remaining non-complete-line at beginning */
++ memmove(buff, p, buff_len-(p-buff));
++ /* point to the end of the non-complete-line */
++ p = &amp;buff[buff_len-(p-buff)];
++ }
++ }
++ if (gzclose(f) != 0) ok = 0;
++ SPAGAIN;
++ if (ok) {
++ XPUSHs(sv_2mortal(newSViv(start_id)));
++ XPUSHs(sv_2mortal(newSViv(av_len(depslist))));
++ }
++ } else {
++ SV **nofatal = hv_fetch((HV*)SvRV(urpm), &quot;nofatal&quot;, 7, 0);
++ if (!errno) errno = EINVAL; /* zlib error */
++ if (!nofatal || !SvIV(*nofatal))
++ croak(errno == ENOENT
++ ? &quot;unable to read synthesis file %s&quot;
++ : &quot;unable to uncompress synthesis file %s&quot;, filename);
++ }
++ } else croak(&quot;first argument should contain a depslist ARRAY reference&quot;);
++ } else croak(&quot;first argument should be a reference to a HASH&quot;);
++
++void
++Urpm_parse_hdlist__XS(urpm, filename, ...)
++ SV *urpm
++ char *filename
++ PPCODE:
++ if (SvROK(urpm) &amp;&amp; SvTYPE(SvRV(urpm)) == SVt_PVHV) {
++ SV **fdepslist = hv_fetch((HV*)SvRV(urpm), &quot;depslist&quot;, 8, 0);
++ AV *depslist = fdepslist &amp;&amp; SvROK(*fdepslist) &amp;&amp; SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
++ SV **fprovides = hv_fetch((HV*)SvRV(urpm), &quot;provides&quot;, 8, 0);
++ HV *provides = fprovides &amp;&amp; SvROK(*fprovides) &amp;&amp; SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
++ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), &quot;obsoletes&quot;, 9, 0);
++ HV *obsoletes = fobsoletes &amp;&amp; SvROK(*fobsoletes) &amp;&amp; SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
++
++ if (depslist != NULL) {
++ pid_t pid = 0;
++ int d;
++ int empty_archive = 0;
++ FD_t fd;
++
++ d = open_archive(filename, &amp;pid, &amp;empty_archive);
++ fd = fdDup(d);
++ close(d);
++
++ if (empty_archive) {
++ XPUSHs(sv_2mortal(newSViv(1 + av_len(depslist))));
++ XPUSHs(sv_2mortal(newSViv(av_len(depslist))));
++ } else if (d &gt;= 0 &amp;&amp; fd) {
++ Header header;
++ int start_id = 1 + av_len(depslist);
++ int packing = 0;
++ SV *callback = NULL;
++
++ /* compability mode with older interface of parse_hdlist */
++ if (items == 3) {
++ packing = SvTRUE(ST(2));
++ } else if (items &gt; 3) {
++ int i;
++ for (i = 2; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 7 &amp;&amp; !memcmp(s, &quot;packing&quot;, 7)) {
++ packing = SvTRUE(ST(i+1));
++ } else if (len == 8 &amp;&amp; !memcmp(s, &quot;callback&quot;, 8)) {
++ if (SvROK(ST(i+1))) callback = ST(i+1);
++ }
++ }
++ }
++
++ PUTBACK;
++ do {
++ header=headerRead(fd, HEADER_MAGIC_YES);
++ if (header != NULL) {
++ struct s_Package pkg, *_pkg;
++ SV *sv_pkg;
++
++ memset(&amp;pkg, 0, sizeof(struct s_Package));
++ pkg.flag = 1 + av_len(depslist);
++ pkg.h = header;
++ sv_pkg = sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;,
++ _pkg = memcpy(malloc(sizeof(struct s_Package)), &amp;pkg, sizeof(struct s_Package)));
++ if (call_package_callback(urpm, sv_pkg, callback)) {
++ if (provides) {
++ update_provides(_pkg, provides);
++ update_provides_files(_pkg, provides);
++ }
++ if (obsoletes) update_obsoletes(_pkg, obsoletes);
++ if (packing) pack_header(_pkg);
++ av_push(depslist, sv_pkg);
++ }
++ }
++ } while (header != NULL);
++
++ int ok = Fclose(fd) == 0;
++
++ if (pid) {
++ kill(pid, SIGTERM);
++ int status;
++ int rc = waitpid(pid, &amp;status, 0);
++ ok = rc != -1 &amp;&amp; WEXITSTATUS(status) != 1; /* in our standard case, gzip will exit with status code 2, meaning &quot;decompression OK, trailing garbage ignored&quot; */
++ pid = 0;
++ } else if (!empty_archive) {
++ ok = av_len(depslist) &gt;= start_id;
++ }
++ SPAGAIN;
++ if (ok) {
++ XPUSHs(sv_2mortal(newSViv(start_id)));
++ XPUSHs(sv_2mortal(newSViv(av_len(depslist))));
++ }
++ } else {
++ SV **nofatal = hv_fetch((HV*)SvRV(urpm), &quot;nofatal&quot;, 7, 0);
++ if (!nofatal || !SvIV(*nofatal))
++ croak(&quot;cannot open hdlist file %s&quot;, filename);
++ }
++ } else croak(&quot;first argument should contain a depslist ARRAY reference&quot;);
++ } else croak(&quot;first argument should be a reference to a HASH&quot;);
++
++void
++Urpm_parse_rpm(urpm, filename, ...)
++ SV *urpm
++ char *filename
++ PPCODE:
++ if (SvROK(urpm) &amp;&amp; SvTYPE(SvRV(urpm)) == SVt_PVHV) {
++ SV **fdepslist = hv_fetch((HV*)SvRV(urpm), &quot;depslist&quot;, 8, 0);
++ AV *depslist = fdepslist &amp;&amp; SvROK(*fdepslist) &amp;&amp; SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
++ SV **fprovides = hv_fetch((HV*)SvRV(urpm), &quot;provides&quot;, 8, 0);
++ HV *provides = fprovides &amp;&amp; SvROK(*fprovides) &amp;&amp; SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
++ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), &quot;obsoletes&quot;, 8, 0);
++ HV *obsoletes = fobsoletes &amp;&amp; SvROK(*fobsoletes) &amp;&amp; SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
++
++ if (depslist != NULL) {
++ struct s_Package pkg, *_pkg;
++ SV *sv_pkg;
++ int packing = 0;
++ int keep_all_tags = 0;
++ SV *callback = NULL;
++ rpmVSFlags vsflags = RPMVSF_DEFAULT;
++
++ /* compability mode with older interface of parse_hdlist */
++ if (items == 3) {
++ packing = SvTRUE(ST(2));
++ } else if (items &gt; 3) {
++ int i;
++ for (i = 2; i &lt; items-1; i+=2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++
++ if (len == 7 &amp;&amp; !memcmp(s, &quot;packing&quot;, 7)) {
++ packing = SvTRUE(ST(i + 1));
++ } else if (len == 13 &amp;&amp; !memcmp(s, &quot;keep_all_tags&quot;, 13)) {
++ keep_all_tags = SvTRUE(ST(i+1));
++ } else if (len == 8 &amp;&amp; !memcmp(s, &quot;callback&quot;, 8)) {
++ if (SvROK(ST(i+1))) callback = ST(i+1);
++ } else if (len == 5) {
++ if (!memcmp(s, &quot;nopgp&quot;, 5)) {
++ if (SvIV(ST(i+1))) vsflags |= (RPMVSF_NOSHA1 | RPMVSF_NOSHA1HEADER);
++ }
++ else if (!memcmp(s, &quot;nogpg&quot;, 5)) {
++ if (SvIV(ST(i+1))) vsflags |= (RPMVSF_NOSHA1 | RPMVSF_NOSHA1HEADER);
++ }
++ else if (!memcmp(s, &quot;nomd5&quot;, 5)) {
++ if (SvIV(ST(i+1))) vsflags |= (RPMVSF_NOMD5 | RPMVSF_NOMD5HEADER);
++ }
++ else if (!memcmp(s, &quot;norsa&quot;, 5)) {
++ if (SvIV(ST(i+1))) vsflags |= (RPMVSF_NORSA | RPMVSF_NORSAHEADER);
++ }
++ else if (!memcmp(s, &quot;nodsa&quot;, 5)) {
++ if (SvIV(ST(i+1))) vsflags |= (RPMVSF_NODSA | RPMVSF_NODSAHEADER);
++ }
++ } else if (len == 9) {
++ if (!memcmp(s, &quot;nodigests&quot;, 9)) {
++ if (SvIV(ST(i+1))) vsflags |= _RPMVSF_NODIGESTS;
++ } else
++ if (!memcmp(s, &quot;nopayload&quot;, 9)) {
++ if (SvIV(ST(i+1))) vsflags |= _RPMVSF_NOPAYLOAD;
++ }
++ }
++ }
++ }
++ PUTBACK;
++ memset(&amp;pkg, 0, sizeof(struct s_Package));
++ pkg.flag = 1 + av_len(depslist);
++ _pkg = memcpy(malloc(sizeof(struct s_Package)), &amp;pkg, sizeof(struct s_Package));
++
++ if (update_header(filename, _pkg, keep_all_tags, vsflags)) {
++ sv_pkg = sv_setref_pv(newSVpv(&quot;&quot;, 0), &quot;URPM::Package&quot;, _pkg);
++ if (call_package_callback(urpm, sv_pkg, callback)) {
++ if (provides) {
++ update_provides(_pkg, provides);
++ update_provides_files(_pkg, provides);
++ }
++ if (obsoletes) update_obsoletes(_pkg, obsoletes);
++ if (packing) pack_header(_pkg);
++ av_push(depslist, sv_pkg);
++ }
++ SPAGAIN;
++ /* only one element read */
++ XPUSHs(sv_2mortal(newSViv(av_len(depslist))));
++ XPUSHs(sv_2mortal(newSViv(av_len(depslist))));
++ } else free(_pkg);
++ } else croak(&quot;first argument should contain a depslist ARRAY reference&quot;);
++ } else croak(&quot;first argument should be a reference to a HASH&quot;);
++
++int
++Urpm_verify_rpm(filename, ...)
++ char *filename
++ PREINIT:
++ FD_t fd;
++ int i, oldlogmask;
++ rpmts ts = NULL;
++ struct rpmQVKArguments_s qva;
++ CODE:
++ /* Don't display error messages */
++ oldlogmask = rpmlogSetMask(RPMLOG_UPTO(RPMLOG_PRI(4)));
++ memset(&amp;qva, 0, sizeof(struct rpmQVKArguments_s));
++ qva.qva_source = RPMQV_RPM;
++ qva.qva_flags = VERIFY_ALL;
++ for (i = 1 ; i &lt; items - 1 ; i += 2) {
++ STRLEN len;
++ char *s = SvPV(ST(i), len);
++ if (len == 9 &amp;&amp; !strncmp(s, &quot;nodigests&quot;, 9)) {
++ if (SvIV(ST(i+1))) qva.qva_flags &amp;= ~VERIFY_DIGEST;
++ } else if (len == 12 &amp;&amp; !strncmp(s, &quot;nosignatures&quot;, 12)) {
++ if (SvIV(ST(i+1))) qva.qva_flags &amp;= ~VERIFY_SIGNATURE;
++ }
++ }
++ fd = Fopen(filename, &quot;r&quot;);
++ if (fd == NULL) {
++ RETVAL = 0;
++ } else {
++ read_config_files(0);
++ ts = rpmtsCreate();
++ rpmtsSetRootDir(ts, &quot;/&quot;);
++ rpmtsOpenDB(ts, O_RDONLY);
++ if (rpmVerifySignatures(&amp;qva, ts, fd, filename)) {
++ RETVAL = 0;
++ } else {
++ RETVAL = 1;
++ }
++ Fclose(fd);
++ (void)rpmtsFree(ts);
++ }
++ rpmlogSetMask(oldlogmask);
++
++ OUTPUT:
++ RETVAL
++
++
++char *
++Urpm_get_gpg_fingerprint(filename)
++ char * filename
++ PREINIT:
++ uint8_t fingerprint[sizeof(pgpKeyID_t)];
++ char fingerprint_str[sizeof(pgpKeyID_t) * 2 + 1];
++ const uint8_t *pkt = NULL;
++ size_t pktlen = 0;
++ int rc;
++
++ CODE:
++ memset (fingerprint, 0, sizeof (fingerprint));
++ if ((rc = pgpReadPkts(filename, (uint8_t ** ) &amp;pkt, &amp;pktlen)) &lt;= 0) {
++ pktlen = 0;
++ } else if (rc != PGPARMOR_PUBKEY) {
++ pktlen = 0;
++ } else {
++ unsigned int i;
++ pgpPubkeyFingerprint (pkt, pktlen, fingerprint);
++ for (i = 0; i &lt; sizeof (pgpKeyID_t); i++) {
++ sprintf(&amp;fingerprint_str[i*2], &quot;%02x&quot;, fingerprint[i]);
++ }
++ }
++ _free(pkt);
++ RETVAL = fingerprint_str;
++ OUTPUT:
++ RETVAL
++
++
++char *
++Urpm_verify_signature(filename, prefix=&quot;/&quot;)
++ char *filename
++ char *prefix
++ PREINIT:
++ rpmts ts = NULL;
++ char result[1024];
++ rpmRC rc;
++ FD_t fd;
++ Header h;
++ CODE:
++ fd = Fopen(filename, &quot;r&quot;);
++ if (fd == NULL) {
++ RETVAL = &quot;NOT OK (could not read file)&quot;;
++ } else {
++ read_config_files(0);
++ ts = rpmtsCreate();
++ rpmtsSetRootDir(ts, prefix);
++ rpmtsOpenDB(ts, O_RDONLY);
++ rpmtsSetVSFlags(ts, RPMVSF_DEFAULT);
++ rc = rpmReadPackageFile(ts, fd, filename, &amp;h);
++ Fclose(fd);
++ *result = '\0';
++ switch(rc) {
++ case RPMRC_OK:
++ if (h) {
++ char *fmtsig = headerFormat(
++ h,
++ &quot;%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:&quot;
++ &quot;{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|&quot;,
++ NULL);
++ snprintf(result, sizeof(result), &quot;OK (%s)&quot;, fmtsig);
++ free(fmtsig);
++ } else snprintf(result, sizeof(result), &quot;NOT OK (bad rpm): %s&quot;, rpmlogMessage());
++ break;
++ case RPMRC_NOTFOUND:
++ snprintf(result, sizeof(result), &quot;NOT OK (signature not found): %s&quot;, rpmlogMessage());
++ break;
++ case RPMRC_FAIL:
++ snprintf(result, sizeof(result), &quot;NOT OK (fail): %s&quot;, rpmlogMessage());
++ break;
++ case RPMRC_NOTTRUSTED:
++ snprintf(result, sizeof(result), &quot;NOT OK (key not trusted): %s&quot;, rpmlogMessage());
++ break;
++ case RPMRC_NOKEY:
++ snprintf(result, sizeof(result), &quot;NOT OK (no key): %s&quot;, rpmlogMessage());
++ break;
++ }
++ RETVAL = result;
++ if (h) h = headerFree(h);
++ (void)rpmtsFree(ts);
++ }
++
++ OUTPUT:
++ RETVAL
++
++
++int
++Urpm_import_pubkey_file(db, filename)
++ URPM::DB db
++ char * filename
++ PREINIT:
++ const uint8_t *pkt = NULL;
++ size_t pktlen = 0;
++ int rc;
++ CODE:
++
++ rpmts ts = rpmtsLink(db-&gt;ts, &quot;URPM::import_pubkey_file&quot;);
++ rpmtsClean(ts);
++
++ if ((rc = pgpReadPkts(filename, (uint8_t ** ) &amp;pkt, &amp;pktlen)) &lt;= 0) {
++ RETVAL = 0;
++ } else if (rc != PGPARMOR_PUBKEY) {
++ RETVAL = 0;
++ } else if (rpmtsImportPubkey(ts, pkt, pktlen) != RPMRC_OK) {
++ RETVAL = 0;
++ } else {
++ RETVAL = 1;
++ }
++ pkt = _free(pkt);
++ (void)rpmtsFree(ts);
++ OUTPUT:
++ RETVAL
++
++int
++Urpm_import_pubkey(...)
++ CODE:
++ unused_variable(&amp;items);
++ croak(&quot;import_pubkey() is dead. use import_pubkey_file() instead&quot;);
++ RETVAL = 1;
++ OUTPUT:
++ RETVAL
++
++int
++Urpm_archscore(arch)
++ const char * arch
++ PREINIT:
++#ifndef RPM_ORG
++ char * platform = NULL;
++#endif
++ CODE:
++ read_config_files(0);
++#ifndef RPM_ORG
++ platform = rpmExpand(arch, &quot;-%{_target_vendor}-%{_target_os}%{?_gnu}&quot;, NULL);
++ RETVAL=rpmPlatformScore(platform, NULL, 0);
++ _free(platform);
++#else
++ RETVAL=rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
++#endif
++ OUTPUT:
++ RETVAL
++
++int
++Urpm_osscore(os)
++ const char * os
++ PREINIT:
++#ifndef RPM_ORG
++ char * platform = NULL;
++#endif
++ CODE:
++ read_config_files(0);
++#ifndef RPM_ORG
++ platform = rpmExpand(&quot;%{_target_cpu}-%{_target_vendor}-&quot;, os, &quot;%{?_gnu}&quot;, NULL);
++ RETVAL=rpmPlatformScore(platform, NULL, 0);
++ _free(platform);
++#else
++ RETVAL=rpmMachineScore(RPM_MACHTABLE_INSTOS, os);
++#endif
++ OUTPUT:
++ RETVAL
++
++int
++Urpm_platformscore(platform)
++ const char * platform
++ CODE:
++ read_config_files(0);
++#ifndef RPM_ORG
++ RETVAL=rpmPlatformScore(platform, NULL, 0);
++#else
++ unused_variable(platform);
++ croak(&quot;platformscore() is available only since rpm 4.4.8&quot;);
++ RETVAL=0;
++#endif
++ OUTPUT:
++ RETVAL
++
++void
++Urpm_stream2header(fp)
++ FILE *fp
++ PREINIT:
++ FD_t fd;
++ URPM__Package pkg;
++ PPCODE:
++ if ((fd = fdDup(fileno(fp)))) {
++ pkg = (URPM__Package)malloc(sizeof(struct s_Package));
++ memset(pkg, 0, sizeof(struct s_Package));
++ pkg-&gt;h = headerRead(fd, HEADER_MAGIC_YES);
++ if (pkg-&gt;h) {
++ SV *sv_pkg;
++ EXTEND(SP, 1);
++ sv_pkg = sv_newmortal();
++ sv_setref_pv(sv_pkg, &quot;URPM::Package&quot;, (void*)pkg);
++ PUSHs(sv_pkg);
++ }
++ Fclose(fd);
++ }
++
++void
++Urpm_spec2srcheader(specfile)
++ char *specfile
++ PREINIT:
++ rpmts ts = rpmtsCreate();
++ URPM__Package pkg;
++ Spec spec = NULL;
++ PPCODE:
++/* ensure the config is in memory with all macro */
++ read_config_files(0);
++/* Do not verify architecture */
++#define SPEC_ANYARCH 1
++/* Do not verify whether sources exist */
++#define SPEC_FORCE 1
++ if (!parseSpec(ts, specfile, &quot;/&quot;, NULL, 0, NULL, NULL, SPEC_ANYARCH, SPEC_FORCE)) {
++ SV *sv_pkg;
++ spec = rpmtsSetSpec(ts, NULL);
++#ifdef RPM_ORG
++ if (! spec-&gt;sourceHeader)
++#endif
++ initSourceHeader(spec);
++ pkg = (URPM__Package)malloc(sizeof(struct s_Package));
++ memset(pkg, 0, sizeof(struct s_Package));
++ headerPutString(spec-&gt;sourceHeader, RPMTAG_SOURCERPM, &quot;&quot;);
++
++ {
++ struct rpmtd_s td = {
++ .tag = RPMTAG_ARCH,
++ .type = RPM_STRING_TYPE,
++ .data = (void *) &quot;src&quot;,
++ .count = 1,
++ };
++ /* parseSpec() sets RPMTAG_ARCH to %{_target_cpu} whereas we really a header similar to .src.rpm header */
++ headerMod(spec-&gt;sourceHeader, &amp;td);
++ }
++
++ pkg-&gt;h = headerLink(spec-&gt;sourceHeader);
++ sv_pkg = sv_newmortal();
++ sv_setref_pv(sv_pkg, &quot;URPM::Package&quot;, (void*)pkg);
++ XPUSHs(sv_pkg);
++ spec = freeSpec(spec);
++ } else {
++ XPUSHs(&amp;PL_sv_undef);
++ /* apparently rpmlib sets errno this when given a bad spec. */
++ if (errno == EBADF)
++ errno = 0;
++ }
++ ts = rpmtsFree(ts);
++
++void
++expand(name)
++ char * name
++ PPCODE:
++ const char * value = rpmExpand(name, NULL);
++ XPUSHs(sv_2mortal(newSVpv(value, 0)));
++
++void
++add_macro_noexpand(macro)
++ char * macro
++ CODE:
++ rpmDefineMacro(NULL, macro, RMIL_DEFAULT);
++
++void
++del_macro(name)
++ char * name
++ CODE:
++ delMacro(NULL, name);
++
++void
++loadmacrosfile(filename)
++ char * filename
++ PPCODE:
++ rpmInitMacros(NULL, filename);
++
++void
++resetmacros()
++ PPCODE:
++ rpmFreeMacros(NULL);
++
++void
++setVerbosity(level)
++ int level
++ PPCODE:
++ rpmSetVerbosity(level);
++
++const char *
++rpmErrorString()
++ CODE:
++ RETVAL = rpmlogMessage();
++ OUTPUT:
++ RETVAL
++
++void
++rpmErrorWriteTo(fd)
++ int fd
++ CODE:
++ rpmError_callback_data = fd;
++ rpmlogSetCallback(rpmError_callback, NULL);
++
++ /* vim:set ts=8 sts=2 sw=2: */
+
+Added: rpm/perl-URPM/trunk/t/00prepare.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/00prepare.t (rev 0)
++++ rpm/perl-URPM/trunk/t/00prepare.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,16 @@
++#!/usr/bin/perl
++
++use strict;
++use warnings;
++use Test::More tests =&gt; 1;
++use Cwd;
++
++chdir 't' if -d 't';
++mkdir &quot;tmp&quot;;
++for (qw(BUILD SOURCES RPMS RPMS/noarch)) {
++ mkdir &quot;tmp/&quot;.$_;
++}
++# locally build a test rpm
++system(rpmbuild =&gt; '--define', '_topdir '. Cwd::cwd() . &quot;/tmp/&quot;, '-bb', 'test-rpm.spec');
++ok( -f 'tmp/RPMS/noarch/test-rpm-1.0-1mdk.noarch.rpm', 'rpm created' );
++
+
+Added: rpm/perl-URPM/trunk/t/buggy_synthesis.cz
+===================================================================
+(Binary files differ)
+
+
+Property changes on: rpm/perl-URPM/trunk/t/buggy_synthesis.cz
+___________________________________________________________________
+Added: svn:mime-type
+ + application/octet-stream
+
+Added: rpm/perl-URPM/trunk/t/empty_synthesis.cz
+===================================================================
+(Binary files differ)
+
+
+Property changes on: rpm/perl-URPM/trunk/t/empty_synthesis.cz
+___________________________________________________________________
+Added: svn:mime-type
+ + application/octet-stream
+
+Added: rpm/perl-URPM/trunk/t/fatal.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/fatal.t (rev 0)
++++ rpm/perl-URPM/trunk/t/fatal.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,23 @@
++#!/usr/bin/perl
++
++use strict;
++use Test::More tests =&gt; 8;
++use URPM;
++
++my $u = new URPM;
++
++eval { $u-&gt;parse_hdlist('non-existent'); };
++like( $@, qr/^cannot open hdlist file non-existent/, 'fatal error on hdlist not found' );
++is( $! + 0, $!{EBADF}, '$! is EBADF' );
++eval { $u-&gt;parse_synthesis('non-existent'); };
++like( $@, qr/^unable to read synthesis file non-existent/, 'fatal error on synthesis not found' );
++is( $! + 0, $!{ENOENT}, '$! is ENOENT' );
++
++my $v = new URPM( nofatal =&gt; 1 );
++
++eval { $v-&gt;parse_hdlist('non-existent'); };
++is( $@, '', 'no error on hdlist not found' );
++is( $! + 0, $!{EBADF}, '$! is EBADF' );
++eval { $v-&gt;parse_synthesis('non-existent'); };
++is( $@, '', 'no error on synthesis not found' );
++is( $! + 0, $!{ENOENT}, '$! is ENOENT' );
+
+Added: rpm/perl-URPM/trunk/t/parse.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/parse.t (rev 0)
++++ rpm/perl-URPM/trunk/t/parse.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,119 @@
++#!/usr/bin/perl
++
++# $Id: parse.t 258553 2009-07-22 18:21:30Z peroyvind $
++
++use strict;
++use warnings;
++use Test::More tests =&gt; 39;
++use MDV::Packdrakeng;
++use URPM;
++use URPM::Build;
++use URPM::Query;
++
++chdir 't' if -d 't';
++
++# shut up
++URPM::setVerbosity(2);
++
++my $a = new URPM;
++ok($a);
++
++END { system('rm -rf hdlist.cz empty_hdlist.cz headers tmp') }
++
++my ($start, $end) = $a-&gt;parse_rpms_build_headers(rpms =&gt; [ &quot;tmp/RPMS/noarch/test-rpm-1.0-1mdk.noarch.rpm&quot; ], keep_all_tags =&gt; 1);
++ok(@{$a-&gt;{depslist}} == 1);
++my $pkg = $a-&gt;{depslist}[0];
++ok($pkg);
++is($pkg-&gt;get_tag(1000), 'test-rpm', 'name');
++is($pkg-&gt;get_tag(1001), '1.0', 'version');
++is($pkg-&gt;get_tag(1002), '1mdk', 'release');
++
++mkdir 'headers';
++system('touch headers/empty');
++is(URPM-&gt;new-&gt;parse_hdlist('headers/empty'), undef, 'empty header');
++system('echo FOO &gt; headers/bad');
++is(URPM-&gt;new-&gt;parse_hdlist('headers/bad'), undef, 'bad rpm header');
++
++$a-&gt;build_hdlist(
++ start =&gt; 0,
++ end =&gt; -1,
++ hdlist =&gt; 'empty_hdlist.cz',
++);
++ok(-f 'empty_hdlist.cz');
++
++($start, $end) = URPM-&gt;new-&gt;parse_hdlist('empty_hdlist.cz');
++is(&quot;$start $end&quot;, &quot;0 -1&quot;, 'empty hdlist');
++
++
++$a-&gt;build_hdlist(
++ start =&gt; 0,
++ end =&gt; $#{$a-&gt;{depslist}},
++ hdlist =&gt; 'hdlist.cz',
++ ratio =&gt; 9,
++);
++
++ok(-f 'hdlist.cz');
++
++my $b = new URPM;
++($start, $end) = $b-&gt;parse_hdlist('hdlist.cz', keep_all_tags =&gt; 1);
++is(&quot;$start $end&quot;, &quot;0 0&quot;, 'parse_hdlist');
++ok(@{$b-&gt;{depslist}} == 1);
++$pkg = $b-&gt;{depslist}[0];
++ok($pkg);
++is($pkg-&gt;get_tag(1000), 'test-rpm', 'name');
++is($pkg-&gt;get_tag(1001), '1.0', 'version');
++is($pkg-&gt;get_tag(1002), '1mdk', 'release');
++is($pkg-&gt;queryformat(&quot;%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}&quot;), &quot;test-rpm-1.0-1mdk.noarch&quot;,
++ q/get headers from hdlist/);
++rpm_is_jbj_version() ?
++ ok($pkg-&gt;is_platform_compat() &gt; 0, &quot;can evaluate platform score&quot;) :
++ pass('no platform compat');
++
++my $headers = eval { [ $b-&gt;parse_rpms_build_headers(rpms =&gt; [ &quot;tmp/RPMS/noarch/test-rpm-1.0-1mdk.noarch.rpm&quot; ],
++ dir =&gt; 'headers') ] };
++is($@, '', 'parse_rpms_build_headers');
++is(int @$headers, 1, 'parse_rpms_build_headers');
++ok(@{$b-&gt;{depslist}} == 2);
++($start, $end) = eval { $b-&gt;parse_headers(dir =&gt; &quot;headers&quot;, headers =&gt; $headers) };
++is($@, '', 'parse_headers');
++is(&quot;$start $end&quot;, &quot;2 2&quot;, 'parse_headers');
++
++
++
++# Version comparison
++ok(URPM::rpmvercmp(&quot;1-1mdk&quot;, &quot;1-1mdk&quot;) == 0, &quot;Same value = 0&quot;);
++ok(URPM::rpmvercmp(&quot;0:1-1mdk&quot;, &quot;1-1mdk&quot;) == -1, &quot;Same value, epoch 0 on left = 1&quot;);
++ok(URPM::rpmvercmp(&quot;1-1mdk&quot;, &quot;1-2mdk&quot;) == -1, &quot;Right value win = -1&quot;);
++ok(URPM::rpmvercmp(&quot;1-2mdk&quot;, &quot;1-1mdk&quot;) == 1, &quot;Left value win = 1&quot;);
++ok(URPM::rpmvercmp(&quot;1:1-1mdk&quot;, &quot;2:1-1mdk&quot;) == -1, &quot;epoch 1 vs 2 = -1&quot;);
++
++{
++ open(my $hdfh, &quot;zcat hdlist.cz 2&gt;/dev/null |&quot;) or die $!;
++ my $pkg = URPM::stream2header($hdfh);
++ ok(defined $pkg, &quot;Reading a header works&quot;);
++ is($pkg-&gt;get_tag(1000), 'test-rpm');
++ is($pkg-&gt;get_tag(1001), '1.0');
++ is($pkg-&gt;get_tag(1002), '1mdk');
++ is($pkg-&gt;queryformat(&quot;%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}&quot;), &quot;test-rpm-1.0-1mdk.noarch&quot;);
++ ok($pkg-&gt;is_arch_compat(), &quot;Arch compat works&quot;);
++ close $hdfh;
++}
++
++{
++ my $pkg = URPM::spec2srcheader(&quot;test-rpm.spec&quot;);
++ ok(defined $pkg, &quot;Parsing a spec works&quot;);
++ is($pkg-&gt;get_tag(1000), 'test-rpm', 'parsed correctly');
++ $pkg = URPM::spec2srcheader(&quot;doesnotexist.spec&quot;);
++ ok(!defined $pkg, &quot;non-existent spec&quot;);
++ open my $f, '&gt;', 'bad.spec' or die &quot;Can't write bad.spec: $!\n&quot;;
++ print $f &quot;Name: foo\nVerssion: 2\n&quot;;
++ close $f;
++ $pkg = URPM::spec2srcheader(&quot;bad.spec&quot;);
++ ok(!defined $pkg, &quot;bad spec&quot;);
++ END { unlink &quot;bad.spec&quot; }
++}
++
++sub rpm_is_jbj_version {
++ # checking for --yaml support
++ `rpm --help` =~ /yaml/;
++}
+
+Added: rpm/perl-URPM/trunk/t/pod.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/pod.t (rev 0)
++++ rpm/perl-URPM/trunk/t/pod.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,5 @@
++#!perl
++use Test::More;
++eval &quot;use Test::Pod 1.14&quot;;
++plan skip_all =&gt; &quot;Test::Pod 1.14 required for testing POD&quot; if $@;
++all_pod_files_ok();
+
+Added: rpm/perl-URPM/trunk/t/rpmdb.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/rpmdb.t (rev 0)
++++ rpm/perl-URPM/trunk/t/rpmdb.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,46 @@
++#!/usr/bin/perl
++
++use strict ;
++use warnings ;
++use Test::More tests =&gt; 7;
++use URPM;
++
++my ($count, @all_pkgs_extern, @all_pkgs);
++my ($pkg_perl, $count_perl, $pkg_perl_extern);
++{
++ my $db;
++ ok($db = URPM::DB::open, 'DB opened');
++
++ @all_pkgs_extern = sort { $a cmp $b } split /\n/ =&gt; qx(rpm -qa --nosignature --qf '%{name}-%{version}-%{release}\n');
++ ok(@all_pkgs_extern &gt; 0, 'There are RPMs');
++
++ $count = $db-&gt;traverse(sub {
++ my ($pkg) = @_;
++ my ($name, $version, $release, $arch) = $pkg-&gt;fullname;
++ #- arch is void for -pubkey- package.
++ my $fullname = &quot;$name-$version-$release&quot;;
++ push @all_pkgs, $fullname;
++ if ($name eq 'perl') { $pkg_perl_extern = $fullname }
++ });
++
++ $count_perl = $db-&gt;traverse_tag('name', ['perl'], sub {
++ my ($pkg) = @_;
++ my ($name, $version, $release) = $pkg-&gt;fullname;
++ $pkg_perl = &quot;$name-$version-$release&quot;;
++ });
++}
++is($count, @all_pkgs_extern,
++ 'traversed same num of packages than given by rpm -qa');
++is($count, @all_pkgs,
++ 'traversed each package once');
++is($count_perl, 1, q(there's exactly 1 &quot;perl&quot; package));
++is($pkg_perl, $pkg_perl_extern, '... with the correct fullname');
++
++my @all_pkgs_sorted = sort { $a cmp $b } @all_pkgs;
++my $bad_pkgs = 0;
++foreach (0..$#all_pkgs_sorted) {
++ $all_pkgs_sorted[$_] eq $all_pkgs_extern[$_] and next;
++ diag($all_pkgs_extern[$_] . &quot; vs &quot; . $all_pkgs_sorted[$_]);
++ ++$bad_pkgs;
++}
++is($bad_pkgs, 0, 'no mismatch between package lists');
+
+Added: rpm/perl-URPM/trunk/t/sort_graph.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/sort_graph.t (rev 0)
++++ rpm/perl-URPM/trunk/t/sort_graph.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,76 @@
++#!/usr/bin/perl
++
++use strict;
++use Test::More 'no_plan';
++use URPM;
++
++
++my ($list_unsorted, $requires);
++
++$list_unsorted = [ 0, 1, 2 ];
++$requires = { 2 =&gt; [ 1 ], 1 =&gt; [ 0 ], 0 =&gt; [ 1, 2 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0, 1, 2, 3, 4 ];
++$requires = { '0' =&gt; [], '1' =&gt; [ 2, 3 ], '2' =&gt; [ 4 ], '3' =&gt; [ 4 ], '4' =&gt; [ 1, 0 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0, 3, 4, 5, 6, 10 ];
++$requires = { '0' =&gt; [ 4 ], '3' =&gt; [ 5 ], '4' =&gt; [ 6, 5 ], '5' =&gt; [ 10 ], '6' =&gt; [ 10, 3 ], '10' =&gt; [ 6 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0, 1, 2, 3, 4 ];
++$requires = { '0' =&gt; [ 0 ], '1' =&gt; [ 4 ], '2' =&gt; [], '3' =&gt; [ 3 ], '4' =&gt; [ 0, 2 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0, 1, 2, 3, 4 ];
++$requires = { '0' =&gt; [], '1' =&gt; [ 3, 1 ], '2' =&gt; [ 2 ], '3' =&gt; [ 3 ], '4' =&gt; [ 1, 2 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0, 1, 2, 3, 4 ];
++$requires = { '0' =&gt; [ 3, 4 ], '1' =&gt; [ 0, 3 ], '2' =&gt; [], '3' =&gt; [ 4 ], '4' =&gt; [ 0, 3 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 92, 94, 133, 137, 5826, 5828, 5830, 5831, 5836, 5839, 5842, 5844, 5845, 5848, 5849, 5851, 5856, 5859, 5864, 5873, 5882, 5883, 5890, 5892, 5894, 5895, 5897, 5900, 5913, 5915, 5916, 5917, 5924, 5925, 5926, 5928, 5929, 5932, 5936, 5937, 5938, 5943, 5948, 5953, 5955, 5956, 5959, 5960, 5961, 5962, 5964, 5968, 5969, 5970, 5974, 6008, 6009, 6010, 6012, 6110, 6115, 6119, 6120, 6127, 6129, 6132, 6135, 6164, 6165, 6166, 16841, 16842, 16844, 16845, 16890, 17009, 17011, 17013, 17156, 17157, 17169 ];
++$requires = { '17011' =&gt; [], '5883' =&gt; [], '5956' =&gt; [ 5955, 5839, 5959, 5964 ], '5897' =&gt; [], '5953' =&gt; [ 5936, 5943 ], '5894' =&gt; [ 5839 ], '17013' =&gt; [ 6135 ], '5936' =&gt; [ 5943 ], '5826' =&gt; [], '6135' =&gt; [ 5839 ], '16845' =&gt; [ 5839 ], '5974' =&gt; [ 5974, 5839, 5964 ], '5851' =&gt; [ 5856, 5849 ], '6115' =&gt; [], '92' =&gt; [ 5839, 5925, 94 ], '6010' =&gt; [ 6008, 6009, 6010 ], '5882' =&gt; [], '5970' =&gt; [ 5955, 5839, 5969 ], '16841' =&gt; [], '5926' =&gt; [ 5953, 5936, 5926, 6009, 5943, 5928 ], '17156' =&gt; [ 17157, 17156 ], '5848' =&gt; [ 5856 ], '6008' =&gt; [ 6009, 5839, 6008, 6010 ], '5842' =&gt; [ 5839, 5844 ], '16844' =&gt; [ 16845, 16841, 16842, 5839 ], '16842' =&gt; [], '5955' =&gt; [ 5970 ], '6119' =&gt; [ 6119 ], '133' =&gt; [ 5839 ], '6009' =&gt; [ 6008, 6009, 6010 ], '5831' =&gt; [], '5839' =&gt; [ 5839 ], '6165' =&gt; [ 5839 ], '5830' =&gt; [], '5960' =&gt; [ 5839, 5962 ], '5932' =&gt; [ 5953, 5936, 6009, 5932, 5938, 5943, 5928 ], '5924' =&gt; [ 5839 ], '5828' =&gt; [], '5959' =&gt; [ 5969 ], '5890' =&gt; [ 5897 ], '17169' =&gt; [ 17157 ], '5
+ 937' =&gt; [ 5936, 5943 ], '137' =&gt; [ 133, 5839, 5925 ], '5895' =&gt; [], '5892' =&gt; [], '6110' =&gt; [ 5839 ], '6127' =&gt; [], '5900' =&gt; [], '5948' =&gt; [ 5953, 5936, 6009, 5932, 5937, 5948, 5929, 5938, 5943, 5928 ], '6120' =&gt; [], '5929' =&gt; [ 5936, 5943 ], '5961' =&gt; [ 5839 ], '5964' =&gt; [ 5956, 5970, 5839 ], '6164' =&gt; [ 6119, 6120, 6164 ], '5925' =&gt; [ 5924 ], '5844' =&gt; [ 5842, 5844 ], '5864' =&gt; [], '17157' =&gt; [ 5839, 17156, 17157 ], '5969' =&gt; [], '5962' =&gt; [ 6009, 5839, 5962 ], '5913' =&gt; [ 6115, 5839, 5917 ], '5968' =&gt; [ 5970, 5839, 5959 ], '5915' =&gt; [], '6166' =&gt; [ 5839, 6165 ], '6132' =&gt; [ 5839, 6129 ], '6129' =&gt; [ 5839, 6127, 6132 ], '5938' =&gt; [ 5936, 5943 ], '5836' =&gt; [], '5943' =&gt; [ 5953, 5936, 6009, 5937, 5948, 5929, 5928 ], '5856' =&gt; [ 5897 ], '5873' =&gt; [], '5917' =&gt; [ 5839, 5856, 5917, 5849 ], '17009' =&gt; [], '94' =&gt; [ 5839 ], '5859' =&gt; [ 5856 ], '16890' =&gt; [], '5845' =&gt; [ 5851, 5848, 5856, 5849 ], '5928' =&gt; [ 5953, 5936, 5926, 6009, 5943, 5928 ], '5916' =&gt; [ 5915 ], '5849' =&gt; [ 58
+ 56 ], '6012' =&gt; [ 6012 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 53, 56, 118, 189, 223, 284, 286, 304, 396, 397, 403, 442, 480, 544, 556, 596, 607, 692, 729, 758, 764, 772, 778, 798, 829, 838, 840, 865, 917, 1019, 1112, 1149, 1191, 1192, 1232, 1275, 1292, 1316, 1319, 1364, 1411, 1415, 1422, 1487, 1508, 1583, 1719, 1769, 1787, 1827, 1855, 1884, 1894, 2001, 2136, 2139, 2243, 2244, 2355, 2387, 2516, 2597, 2603, 2669, 2694, 2727, 2746, 2818, 2820, 2826, 2845, 2861, 2869, 2932, 2992, 3002, 3016, 3037, 3069, 3079, 3151, 3173, 3272, 3273, 3275, 3280, 3289, 3293, 3314, 3327, 3568, 3569, 3602, 3659, 3662, 3665, 3667, 3669, 3672, 3675, 3682, 3934, 3935, 3936, 3971, 3973, 3980, 4053, 4060, 4150, 4161, 4350, 4400, 4402, 4426, 4428, 4430, 4438, 4439, 4444, 4446, 4635, 4636, 4637, 4638, 4639, 4640, 4656, 4657, 4673, 4681, 4685, 4686, 4687, 4691, 4715, 4793, 5060, 5070, 5079, 5198, 5199, 5250, 5327, 5329, 5330, 5331, 5333, 5334, 5342, 5401, 5404, 5407, 5409, 5423, 5442, 5486, 5487, 5494, 5499, 5501, 5616, 5618, 5664, 5685, 5688, 5775,
+ 5777, 5778, 6166, 6178, 6305, 8295, 9859, 10199, 10649, 10651, 10659, 11879, 22012 ];
++$requires = { '5423' =&gt; [ 5442 ], '118' =&gt; [ 5060 ], '3934' =&gt; [ 764 ], '5250' =&gt; [], '2818' =&gt; [], '2746' =&gt; [ 1019, 764 ], '2992' =&gt; [ 5327, 1884, 4636, 917, 2603, 56, 5334 ], '3002' =&gt; [ 3069 ], '5327' =&gt; [ 3934, 2746, 5327, 1884, 4636, 1019, 397, 764, 758, 829, 2603, 4681, 5331, 1232, 5777, 5334, 1719 ], '798' =&gt; [ 3273, 2861 ], '3037' =&gt; [ 3037, 2820, 838 ], '5688' =&gt; [ 5327, 1884, 4636, 2603, 5334 ], '1884' =&gt; [ 3934, 764, 4402, 5777, 2861 ], '2516' =&gt; [ 917, 596, 2826, 56, 607, 1112, 4444 ], '2001' =&gt; [ 4060, 442, 284, 5333, 1894, 396, 5329, 4640 ], '5664' =&gt; [], '1364' =&gt; [ 5250, 1364, 4060, 917, 5401, 2243, 5407, 1411 ], '5494' =&gt; [ 480, 5501 ], '4715' =&gt; [ 3151 ], '5499' =&gt; [ 764, 865, 2387, 1232, 3973 ], '3273' =&gt; [], '4636' =&gt; [ 3934, 1884, 4636, 764, 5198, 4638, 4639, 5777, 2861, 5775 ], '1019' =&gt; [ 764 ], '4060' =&gt; [ 4060, 4053 ], '4439' =&gt; [ 1364, 4060, 3682, 2932, 729, 3665, 403, 2845, 3672, 3327, 3569, 4444 ], '397' =&gt; [ 764, 1232 ], '764' =&gt; [ 5501, 5486 ],
+ '865' =&gt; [ 764, 2387, 3973 ], '5342' =&gt; [ 4715, 11879, 4635, 4673, 53 ], '5060' =&gt; [], '3936' =&gt; [], '3314' =&gt; [], '8295' =&gt; [], '3682' =&gt; [ 3665, 3662, 3569 ], '5198' =&gt; [ 3934, 764, 5777, 2861 ], '10649' =&gt; [ 5331, 6166 ], '4685' =&gt; [ 4687, 4686 ], '3272' =&gt; [], '11879' =&gt; [], '442' =&gt; [ 798, 1884, 3273, 442, 5778, 3935, 396, 4400 ], '4638' =&gt; [], '5778' =&gt; [ 798, 3273, 5777, 3327, 5775 ], '2932' =&gt; [ 2932 ], '1855' =&gt; [ 607, 1112 ], '2387' =&gt; [ 3973 ], '1191' =&gt; [ 5494, 1019, 5487, 480, 396 ], '3016' =&gt; [ 2746, 1191, 480, 396 ], '5404' =&gt; [ 5409 ], '284' =&gt; [ 4060, 2603 ], '5442' =&gt; [], '2136' =&gt; [ 5327, 1884, 2516, 4636, 764, 2387, 917, 596, 2603, 5409, 3293, 3973, 56, 5334, 1415, 4444 ], '2869' =&gt; [ 5494, 1232, 5487, 480, 396 ], '5070' =&gt; [ 5060 ], '4402' =&gt; [], '729' =&gt; [ 1364, 4060, 56 ], '917' =&gt; [ 917, 5401, 1411 ], '3568' =&gt; [ 764, 2387, 3973, 5501, 5486 ], '3980' =&gt; [ 5327, 1884, 4636, 4635, 2603, 5334 ], '4635' =&gt; [], '3675' =&gt; [], '758' =&gt; [ 3934, 764, 1232 ],
+ '829' =&gt; [ 764, 1232 ], '4687' =&gt; [ 1192, 6305 ], '596' =&gt; [ 917, 596, 544 ], '5330' =&gt; [ 5423, 3934, 2746, 5327, 1884, 4636, 1019, 397, 764, 5442, 4402, 758, 829, 2603, 4681, 1232, 1319, 5777, 5334, 5501, 5486, 4161, 2861, 1719 ], '223' =&gt; [ 1855, 223, 2727, 1112 ], '772' =&gt; [], '5401' =&gt; [], '4657' =&gt; [ 4657 ], '3289' =&gt; [ 2001, 4060, 442, 5404, 284, 3293, 5333, 5329, 4640 ], '4350' =&gt; [], '5685' =&gt; [ 5688, 10649 ], '3151' =&gt; [ 5499, 764 ], '3069' =&gt; [], '3667' =&gt; [ 3675, 3659, 3662 ], '1149' =&gt; [ 2869, 829, 480, 396 ], '3935' =&gt; [ 3934, 480, 396 ], '4673' =&gt; [ 10659, 4150, 10651 ], '2603' =&gt; [ 772 ], '2243' =&gt; [], '4053' =&gt; [], '1487' =&gt; [ 5327, 1884, 2516, 4636, 764, 5060, 2387, 2136, 917, 596, 2603, 2355, 5409, 3293, 3973, 56, 4426, 5334, 4444 ], '3659' =&gt; [ 3675 ], '2694' =&gt; [ 764, 2387, 3973 ], '4681' =&gt; [ 3934, 1019, 764 ], '1769' =&gt; [ 118, 764, 865, 5060, 2387, 4402, 1769, 1232, 3602, 5777, 3973, 3173, 5079, 2861 ], '2826' =&gt; [ 2516, 5342, 917, 596, 56, 607, 1112, 4
+ 444 ], '778' =&gt; [ 397, 2869, 480, 396 ], '4639' =&gt; [ 3934, 5664, 4636, 764, 5198, 5777, 4656, 5501, 5486, 2861 ], '4430' =&gt; [ 5423, 5327, 1884, 4636, 5442, 2603, 5334, 5618 ], '5407' =&gt; [ 4060, 5401 ], '2355' =&gt; [ 5327, 1884, 2516, 4636, 10649, 2136, 917, 596, 2603, 1487, 5409, 3293, 56, 4426, 5334, 3280, 4444 ], '5409' =&gt; [], '5331' =&gt; [ 5330, 5334 ], '10199' =&gt; [], '3293' =&gt; [ 5327, 1884, 4636, 3314, 5330, 2603, 5409, 3293, 1894, 5334, 3280 ], '4446' =&gt; [], '1232' =&gt; [ 764, 5501 ], '2820' =&gt; [ 2820 ], '4637' =&gt; [], '3602' =&gt; [ 5060 ], '1192' =&gt; [ 5775 ], '1275' =&gt; [ 2820 ], '4438' =&gt; [ 2992, 5342, 917, 3568, 3675, 4446, 3669, 56, 1827, 3662, 4444 ], '556' =&gt; [ 5060, 3173 ], '22012' =&gt; [ 8295, 442, 5407, 1275, 1787, 189, 1292, 5333, 1422, 1508, 4400, 1316, 4640, 840, 4793 ], '1787' =&gt; [ 3037, 1275, 1292 ], '1319' =&gt; [ 5423, 5442, 1319, 286, 3275 ], '189' =&gt; [ 5494, 865, 5487, 480, 692, 396, 3971 ], '2597' =&gt; [ 5250, 1364, 4060, 4439, 442, 5404, 284, 2136, 729, 3289, 5333, 6
+ 92, 396, 3971, 1415, 2845, 5329, 1316, 3327, 4640 ], '1292' =&gt; [ 3037, 1275 ], '5487' =&gt; [ 480, 5486 ], '5333' =&gt; [ 3934, 2746, 5327, 1884, 4636, 4060, 1019, 397, 764, 442, 5778, 1191, 3016, 284, 2869, 4402, 758, 829, 5330, 1149, 3935, 2603, 4681, 778, 1232, 5333, 5777, 4691, 3079, 396, 5334, 5501, 5486, 5329, 2861, 4640, 1719, 2669 ], '5777' =&gt; [ 2861, 5775 ], '480' =&gt; [ 5494, 189 ], '1894' =&gt; [ 5327, 1884, 4636, 764, 2603, 1894, 1583, 5334 ], '4691' =&gt; [ 1191, 3935, 4681, 480, 396 ], '3079' =&gt; [ 2869, 758, 3935, 480, 396 ], '692' =&gt; [ 2387, 480, 3971 ], '3973' =&gt; [], '5199' =&gt; [ 798, 3273, 5198, 5778, 3935, 480, 396 ], '3669' =&gt; [ 3675 ], '304' =&gt; [ 4636, 2603, 304, 5334, 2861 ], '1583' =&gt; [], '396' =&gt; [ 5494, 764, 5487, 480 ], '3173' =&gt; [], '1422' =&gt; [ 2694, 692, 396, 3971 ], '3665' =&gt; [ 3675 ], '56' =&gt; [ 2992, 917 ], '2139' =&gt; [ 2139 ], '9859' =&gt; [ 9859 ], '5616' =&gt; [ 2818, 3936, 3272, 10199, 2139, 5618 ], '4426' =&gt; [ 4430 ], '5334' =&gt; [ 764, 5060, 4402, 5334, 5079 ], '6
+ 178' =&gt; [], '10659' =&gt; [], '4656' =&gt; [ 5664, 4657 ], '1508' =&gt; [ 5250, 1364, 4060, 4439, 442, 5404, 284, 5070, 729, 3289, 1487, 2355, 2597, 5333, 692, 396, 3971, 2845, 4428, 5329, 1316, 3327, 4640 ], '4400' =&gt; [ 3273, 4402 ], '1827' =&gt; [], '6305' =&gt; [ 5775 ], '5501' =&gt; [], '838' =&gt; [ 3037, 2820 ], '5486' =&gt; [], '403' =&gt; [ 4060, 3569 ], '3971' =&gt; [ 480, 3973 ], '3662' =&gt; [ 3675, 3667 ], '286' =&gt; [ 5423, 5442 ], '2845' =&gt; [ 1364, 4060, 596, 2845, 544, 3327 ], '1415' =&gt; [ 5327, 1884, 2516, 4636, 2136, 917, 596, 2603, 5409, 5331, 3293, 56, 5334, 3280, 4444 ], '5618' =&gt; [ 5616, 5618 ], '2727' =&gt; [ 607 ], '3672' =&gt; [ 4060, 3669, 3665 ], '544' =&gt; [ 917, 596 ], '4150' =&gt; [ 4350, 556, 304, 9859, 2861, 2244 ], '4161' =&gt; [ 5423, 5060, 5442, 4402, 1319, 4161, 5079 ], '10651' =&gt; [], '5079' =&gt; [ 5060, 5079 ], '3280' =&gt; [ 5327, 1884, 4636, 2603, 5334 ], '53' =&gt; [], '6166' =&gt; [], '4428' =&gt; [ 4060, 4426, 3569 ], '607' =&gt; [], '5329' =&gt; [ 4060, 396, 5334, 5329 ], '1112' =&gt; [ 1855, 607, 1112 ],
+ '3275' =&gt; [], '1316' =&gt; [ 5250, 2516, 1364, 4060, 4439, 729, 223, 2826, 2845, 2727 ], '2861' =&gt; [], '3327' =&gt; [ 3273 ], '4640' =&gt; [ 3934, 798, 1884, 3273, 4636, 4060, 764, 5198, 442, 4638, 5778, 4402, 3935, 4637, 5777, 5199, 396, 5501, 5486, 2861, 3327, 4640 ], '4686' =&gt; [ 5423, 5060, 5442, 4402, 1319, 5777, 4161, 5079 ], '840' =&gt; [ 118, 764, 865, 5060, 4685, 2387, 4402, 1769, 1232, 3602, 5777, 3973, 3173, 5501, 5486, 5079, 2861 ], '3569' =&gt; [], '4444' =&gt; [ 3002, 917, 3675, 4446, 4438, 3669, 56, 6178, 3662, 5618, 4444 ], '1719' =&gt; [ 1019, 764, 1232 ], '1411' =&gt; [ 917, 5401 ], '5775' =&gt; [ 5777, 2861 ], '2244' =&gt; [ 4402 ], '4793' =&gt; [], '2669' =&gt; [ 1191, 2869, 480, 396, 1719 ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 5625, 6155, 6156, 6157, 6158, 6172, 6180, 6186, 6190, 6192, 6199, 6201, 6202, 6204, 6206, 6210, 6215, 6221, 6222, 6223, 6224, 6226, 6229, 6233, 6234, 6236, 6238, 6239, 6243, 6244, 6250, 6254, 6255, 6256, 6257, 6258, 6259, 6261, 6263, 6265, 6266, 6267, 6269, 6270, 6271, 6272, 6273, 6274, 6275, 6278, 6279, 6284, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6296, 6298, 6299, 6300, 6301, 6302, 6303, 6304, 6305, 6306, 6307, 6309, 6310, 6311, 6312, 6314, 6315, 6316, 6317, 6318, 6319, 6320, 6321, 6322, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6333, 6334, 6335, 6336, 6337, 6338, 6339, 6341, 6342, 6343, 6344, 6346, 6347, 6348, 6349, 6350, 6376, 6377, 6379, 6380, 6385, 6387, 6388, 6390, 6394, 6400, 6402, 6403, 6404, 6405, 6412, 6414, 6416, 6417, 6418, 6419, 6420, 6426, 6427, 6429, 6430, 6436, 6439, 6444, 6451, 6454, 6459, 6462, 6464, 6466, 6469, 6472, 6477, 6478, 6479, 6480, 6481, 6483, 6484, 6485, 6489, 6491, 6493, 6495, 6497, 6500, 6501
+ , 6502, 6518, 6519, 6521, 6522, 6523, 6524, 6527, 6528, 6530, 6531, 6533, 6534, 6535, 6536, 6537, 6538, 6540, 6541, 6542, 6546, 6547, 6548, 16770, 16772, 16774, 16775, 16779, 16780, 16783, 16786, 16788, 16789, 16790, 16793, 16794, 16795, 16799, 16802, 16803, 16804, 16805, 16864, 16869, 16871, 16873, 16874, 16875, 16878, 16879, 16913, 16927, 16928, 16957, 16958, 16959, 16960, 16961, 16962, 16963, 16964, 16965, 16966, 16967, 16968, 16969, 16970, 16971, 16972, 16974, 16975, 16976, 16977, 16978, 16979, 16980, 16981, 16982, 16983, 16984, 16985, 16986, 16987, 16988, 16989, 16990, 16992 ];
++$requires = { '16977' =&gt; [ '16972', '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6261' =&gt; [ '6500', '6481' ], '16775' =&gt; [ '16774', '16979', '16970', '16969', '16976', '16803', '6500', '16981', '16986', '6481' ], '6347' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6256' =&gt; [ '6287', '6284', '6274', '6273', '6257', '6278', '6271', '6269', '6288', '6286', '6275', '6289', '6272', '6254' ], '16873' =&gt; [ '16873' ], '16965' =&gt; [ '16969' ], '6535' =&gt; [ '6377', '6500', '6524', '6481' ], '6270' =&gt; [ '6279', '6548', '6519' ], '6497' =&gt; [ '6481' ], '16967' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '16774' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '16799' =&gt; [ '16783', '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6501' =&gt; [ '6484' ], '16793' =&gt; [ '16969', '16981', '16790' ], '16783' =&gt; [ '16969' ], '6518' =&gt; [ '6489', '6481' ], '6293' =
+ &gt; [ '6293', '6300' ], '6333' =&gt; [ '6342', '6346', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 6349, 6347, 6344, 6334, 6328, 6332 ], '16794' =&gt; [ '16979', '16989', '16970', '16969', '6500', '16981', '16986', '6481' ], '6222' =&gt; [ '6292', '6223', '6377', '6300' ], '16984' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '16927' =&gt; [ '16928', '6377', '6500', '6481' ], '6531' =&gt; [ '6535', '6306', '6480', '6527', '6158', '6377', '6500', '6521', '6524', '6481' ], '6405' =&gt; [ '6416' ], '16786' =&gt; [ '16979', '16795', '16970', '16969', '16976', '6500', '16981', '16986', '6481' ], '6541' =&gt; [ '6541', '6390', '6426' ], '6263' =&gt; [ '6292', '6267', '6342', '6266', '6300' ], '6341' =&gt; [ '6347', '6333', '6341', '6334', '6332', '6342', '6329', '6344', '6337', '6348', '6328', '6339', '6346', '6343', '6330', '6335', '6349' ], '16802' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6334' =&gt; [ '6334', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 63
+ 46, 6349, 6347, 6344, 6342, 6328, 6332 ], '6290' =&gt; [ '6292', '6390', '6426', '6500', '6300', '6481' ], '6522' =&gt; [ '6531', '6527', '6537', '6536', '6523', '6534' ], '6527' =&gt; [ '6377', '6500', '6524', '6481' ], '16789' =&gt; [ '16969' ], '16982' =&gt; [ '16979', '16989', '16970', '16969', '6500', '16981', '16986', '6481' ], '6495' =&gt; [ '6489' ], '16804' =&gt; [ '16969', '6500', '6481' ], '16980' =&gt; [ '16979', '16989', '16970', '16969', '16976', '6500', '16981', '16986', '6481', '16961' ], '16928' =&gt; [ '16927' ], '16989' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6332' =&gt; [ '6342', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6190' =&gt; [ '6192' ], '6292' =&gt; [ '6292', '6298', '6300' ], '6298' =&gt; [ '6290', '6300' ], '6239' =&gt; [ '6484', '6501', '6483', '6480', '6489', '6158', '6416', '6462', '6500', '6155', '6481', '6417' ], '6267' =&gt; [ '6292', '6267', '6342', '6266', '6300' ], '6186' =&gt; [ '6376', '6292', '6298', '
+ 6186', '6300' ], '16958' =&gt; [ '16979', '16969', '6500', '16986', '6481' ], '6419' =&gt; [ '6342', '6339' ], '6394' =&gt; [ '6306', '6292', '6298', '6394', '6300', '6387' ], '6412' =&gt; [ '6430', '6390' ], '6204' =&gt; [ '6306', '6292', '6377', '6500', '6300', '6202', '6481' ], '6229' =&gt; [ '6233' ], '6342' =&gt; [ '6261', '6334', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 6346, 6349, 6347, 6344, 6342, 6328, 6332 ], '6430' =&gt; [ '6426' ], '16795' =&gt; [ '16979', '16970', '16969', '16976', '6500', '16981', '16986', '6481' ], '6390' =&gt; [ '6426' ], '16779' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6533' =&gt; [ '6377', '6500', '6481' ], '6478' =&gt; [ '6500' ], '16970' =&gt; [ '16979', '16969', '6500', '16981', '16986', '6481' ], '16987' =&gt; [ '16969' ], '6329' =&gt; [ '6342', '6346', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6349, 6347, 6344, 6334, 6328, 6332 ], '6530' =&gt; [ '6377', '6500', '6481' ], '16869' =&gt; [ '16869' ], '16974' =&gt; [ '16979', '16989', '16970', '16969
+ ', '16976', '6500', '16981', '16986', '6481' ], '6226' =&gt; [ '5625' ], '6528' =&gt; [ '6377', '6500', '6481' ], '6344' =&gt; [ '6333', '6342', 6335, 6348, 6330, 6337, 6343, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6444' =&gt; [ '6292', '6300' ], '6156' =&gt; [ '6155' ], '6491' =&gt; [ '6484' ], '6337' =&gt; [ '6342', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6477' =&gt; [ '6485' ], '16957' =&gt; [ '16969' ], '6519' =&gt; [ '6489' ], '6348' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6328' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6266' =&gt; [ '6342' ], '16976' =&gt; [ '16979', '16989', '16970', '16969', '6500', '16981', '16986', '6481' ], '16990' =&gt; [ '16969' ], '6547' =&gt; [ '6489', '6481' ], '6537' =&gt; [ '6535', '6531', '6528', '6377', '6500', '6481' ], '6404' =&gt; [ '6403' ], '6388' =&gt; [ '6377' ], '6310' =&gt; [ '6320'
+ ], '6466' =&gt; [ '6462' ], '16803' =&gt; [ '16774', '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '16983' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '6454' =&gt; [ '6439', '6292', '6377', '6300' ], '16874' =&gt; [ '6206' ], '6540' =&gt; [ '6541' ], '6244' =&gt; [ '6270', '6311', '5625', '6310', '6259', '6255' ], '16879' =&gt; [ '16869', '16879', '16864' ], '6299' =&gt; [ '6293', '6290', '6292', '6299', '6500', '6300', '6481' ], '16805' =&gt; [ '16965', '16972', '16979', '16989', '16970', '16969', '16976', '6500', '16981', '16986', '6481' ], '6339' =&gt; [ '6342', '6346', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6349, 6347, 6344, 6334, 6328, 6332 ], '6400' =&gt; [ '6394' ], '6221' =&gt; [ '6292', '6300', '6224' ], '16966' =&gt; [ '16979', '16969', '6500', '16986', '6481' ], '16964' =&gt; [ '16972' ], '16971' =&gt; [ '16979', '16969', '16990', '6500', '16986', '6481' ], '6300' =&gt; [ '6300' ], '6346' =&gt; [ '6342', '6339', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6346,
+ 6349, 6347, 6344, 6334, 6328, 6332 ], '6202' =&gt; [ '6292', '6377', '6300', '6481' ], '6536' =&gt; [ '6535', '6531', '6377', '6500', '6521', '6481' ], '16975' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481' ], '16986' =&gt; [ '16979', '16969', '6500', '6481' ], '6385' =&gt; [ '6376' ], '16992' =&gt; [ '16972', '16979', '16982', '16989', '16970', '16969', '16976', '16985', '6500', '16981', '16986', '6481', '16961' ], '6538' =&gt; [ '6535', '6530', '6377', '6500', '6481' ], '6479' =&gt; [ '6483' ], '6343' =&gt; [ '6342', 6335, 6348, 6330, 6333, 6337, 6343, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6414' =&gt; [ '6417' ], '6523' =&gt; [ '6533', '6377', '6500', '6481' ], '6534' =&gt; [ '6535', '6531', '6377', '6500', '6481' ], '6234' =&gt; [ '6236' ], '6330' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6493' =&gt; [ '6480' ], '6521' =&gt; [ '6377', '6500', '6521', '6481' ], '6335' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333,
+ 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '6524' =&gt; [ '6480', '6530', '6377', '6500', '6521', '6524', '6199', '6481' ], '16772' =&gt; [ '16775', '16774', '16979', '16970', '16969', '16976', '16803', '16983', '6500', '16981', '16986', '6481' ], '6349' =&gt; [ '6342', '6343', 6335, 6348, 6330, 6333, 6337, 6329, 6339, 6346, 6349, 6347, 6344, 6334, 6328, 6332 ], '16864' =&gt; [ '16871' ], '6258' =&gt; [ '6258' ], '16968' =&gt; [ '16977', '16960', '16972', '16979', '16982', '16980', '16989', '16958', '16970', '16987', '16974', '16969', '16957', '16976', '16983', '16985', '6500', '16964', '16981', '16986', '16992', '16968', '6481', '16961', '16988', '16963', '16959' ], '16878' =&gt; [ '16878' ], '16978' =&gt; [ '16979', '16989', '16970', '16969', '6500', '16981', '16986', '6481' ], '6502' =&gt; [ '6501', '6491' ], '6157' =&gt; [ '6158' ], '16788' =&gt; [ '16979', '16969', '6500', '16986', '6481' ], '16790' =&gt; [ '16969' ], '16770' =&gt; [ '16965', '16979', '16989', '16970', '16974', '16969', '1
+ 6990', '16976', '16805', '6500', '16971', '16981', '16986', '6481' ], '6210' =&gt; [ '6306', '6210' ], '6379' =&gt; [ '6387' ], '6469' =&gt; [ '6427' ], '6259' =&gt; [ '6518', '6547' ], '6206' =&gt; [ '6206' ], '16961' =&gt; [ '16979', '16989', '16970', '16969', '6500', '16981', '16986', '6481' ], '16963' =&gt; [ '16979', '16969', '6500', '16986', '6481' ], '6250' =&gt; [ '6256', '6244' ], '16988' =&gt; [ '16969', '16985' ], '16959' =&gt; [ '16979', '16970', '16969', '6500', '16981', '16986', '6481', '16963' ] };
++check_it($list_unsorted, $requires, 0);
++
++$list_unsorted = [ 0 .. 10 ];
++check_it($list_unsorted, create_random($list_unsorted), 1) foreach 1 .. 10000;
++
++
++sub check_it {
++ my ($list_unsorted, $requires, $dump_it) = @_;
++
++ my @sorted = eval { URPM::sort_graph($list_unsorted, $requires) };
++ ok(@sorted &gt; 0);
++
++ if (!@sorted &amp;&amp; $dump_it) {
++ require Data::Dumper;
++ $Data::Dumper::Sortkeys = 1;
++ warn Data::Dumper::Dumper($list_unsorted, $requires);
++ warn &quot;$@\n&quot;;
++ exit 1;
++ }
++}
++
++
++sub create_random {
++ my ($list_unsorted) = @_;
++ my %requires;
++
++ foreach my $i (@$list_unsorted) {
++ my $nb = int(rand(1) * 2.8);
++ push @{$requires{$i}}, grep { $_ != $i } uniq(map { int(rand @$list_unsorted) } 1 .. $nb);
++ }
++ \%requires;
++}
++sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ }
+
+Added: rpm/perl-URPM/trunk/t/synthesis.t
+===================================================================
+--- rpm/perl-URPM/trunk/t/synthesis.t (rev 0)
++++ rpm/perl-URPM/trunk/t/synthesis.t 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,151 @@
++#!/usr/bin/perl
++
++use strict ;
++use warnings ;
++use Test::More tests =&gt; 94;
++use URPM;
++
++chdir 't' if -d 't';
++my $file1 = 'synthesis.sample.cz';
++
++open my $f, &quot;| gzip -9 &gt;$file1&quot;;
++print $f &lt;&lt;'EOF';
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at provides</A>@glibc-devel == 6:2.2.4-25mdk
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at requires</A>@/sbin/<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">install-info at glibc</A> == <A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">2.2.4 at kernel-headers</A>@kernel-headers &gt;= 2.2.1@/bin/sh@/bin/sh@/bin/<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">sh at rpmlib</A>(PayloadFilesHavePrefix) &lt;= <A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">4.0-1 at rpmlib</A>(CompressedFileNames) &lt;= 3.0.4-1
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at conflicts</A>@texinfo &lt; <A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">3.11 at gcc</A> &lt; 2.96-0.50mdk
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at obsoletes</A>@<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">libc-debug at libc-headers</A>@<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">libc-devel at linuxthreads-devel</A>@glibc-debug
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at info</A>@<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">glibc-devel-2.2.4-25mdk.i586 at 6</A>@<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">45692097 at Development</A>/C
++EOF
++close $f;
++
++END { unlink $file1 }
++
++my $a = new URPM;
++ok($a);
++
++my ($first, $end);
++
++($first, $end) = URPM-&gt;new-&gt;parse_synthesis('empty_synthesis.cz');
++is(&quot;$first $end&quot;, &quot;0 -1&quot;, 'parse empty synthesis');
++
++is(URPM-&gt;new-&gt;parse_synthesis('buggy_synthesis.cz'), undef, 'parse buggy synthesis');
++
++($first, $end) = $a-&gt;parse_synthesis($file1);
++ok($first == 0 &amp;&amp; $end == 0);
++is(int @{$a-&gt;{depslist}}, 1);
++ok(keys(%{$a-&gt;{provides}}) == 3);
++ok(defined $a-&gt;{provides}{'glibc-devel'});
++ok(exists $a-&gt;{provides}{'/bin/sh'});
++ok(! defined $a-&gt;{provides}{'/bin/sh'});
++ok(exists $a-&gt;{provides}{'/sbin/install-info'});
++ok(! defined $a-&gt;{provides}{'/sbin/install-info'});
++
++my $pkg = $a-&gt;{depslist}[0];
++ok($pkg);
++ok($pkg-&gt;name eq 'glibc-devel');
++ok($pkg-&gt;version eq '2.2.4');
++ok($pkg-&gt;release eq '25mdk');
++ok($pkg-&gt;arch eq 'i586');
++ok($pkg-&gt;fullname eq 'glibc-devel-2.2.4-25mdk.i586');
++ok(!defined $pkg-&gt;buildarchs);
++ok(!defined $pkg-&gt;buildhost);
++is($pkg-&gt;buildtime,0);
++ok(!defined $pkg-&gt;changelog_name);
++ok(!defined $pkg-&gt;changelog_text);
++ok(!defined $pkg-&gt;changelog_time);
++
++my ($name, $version, $release, $arch, @l) = $pkg-&gt;fullname;
++ok(@l == 0);
++ok($name eq 'glibc-devel');
++ok($version eq '2.2.4');
++ok($release eq '25mdk');
++ok($arch eq 'i586');
++
++ok($pkg-&gt;epoch == 6);
++ok($pkg-&gt;size == 45692097);
++ok($pkg-&gt;group eq 'Development/C');
++ok($pkg-&gt;filename eq 'glibc-devel-2.2.4-25mdk.i586.rpm');
++ok(defined $pkg-&gt;id);
++ok($pkg-&gt;id == 0);
++ok($pkg-&gt;set_id(6) == 0);
++ok($pkg-&gt;id == 6);
++ok($pkg-&gt;set_id == 6);
++ok(! defined $pkg-&gt;id);
++ok(! defined $pkg-&gt;set_id(0));
++ok(defined $pkg-&gt;id);
++ok($pkg-&gt;id == 0);
++
++my @obsoletes = $pkg-&gt;obsoletes;
++ok(@obsoletes == 5);
++ok($obsoletes[0] eq 'libc-debug');
++ok($obsoletes[4] eq 'glibc-debug');
++
++my @conflicts = $pkg-&gt;conflicts;
++ok(@conflicts == 2);
++ok($conflicts[0] eq 'texinfo &lt; 3.11');
++ok($conflicts[1] eq 'gcc &lt; 2.96-0.50mdk');
++
++my @requires = $pkg-&gt;requires;
++ok(@requires == 9);
++ok($requires[0] eq '/sbin/install-info');
++ok($requires[8] eq 'rpmlib(CompressedFileNames) &lt;= 3.0.4-1');
++
++my @provides = $pkg-&gt;provides;
++ok(@provides == 1);
++ok($provides[0] eq 'glibc-devel == 6:2.2.4-25mdk');
++
++my @files = $pkg-&gt;files;
++ok(@files == 0);
++
++ok($pkg-&gt;compare(&quot;6:2.2.4-25mdk&quot;) == 0);
++ok($pkg-&gt;compare(&quot;2.2.4-25mdk&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.4&quot;) == 0);
++ok($pkg-&gt;compare(&quot;2.2.3&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.4.0&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.5&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.1.7&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.3.1&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.31&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.4-25&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.4-25.1mdk&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.4-24mdk&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;2.2.4-26mdk&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.4-25.1mdk&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.4.0&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.5&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.31&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;6:2.3.1&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.4-24mdk&quot;) &gt; 0);
++ok($pkg-&gt;compare(&quot;6:2.2.4-26mdk&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;7:2.2.4-26mdk&quot;) &lt; 0);
++ok($pkg-&gt;compare(&quot;7:2.2.4-24mdk&quot;) &lt; 0);
++
++ok($a-&gt;traverse() == 1);
++
++my $test = 0;
++ok($a-&gt;traverse(sub { my ($pkg) = @_; $test = $pkg-&gt;name eq 'glibc-devel' }) == 1);
++ok($test);
++ok($a-&gt;traverse_tag('name', [ 'glibc-devel' ]) == 1);
++ok($a-&gt;traverse_tag('name', [ 'glibc' ]) == 0);
++
++$test = 0;
++ok($a-&gt;traverse_tag('name', [ 'glibc-devel' ], sub { my ($pkg) = @_; $test = $pkg-&gt;name eq 'glibc-devel' }) == 1);
++ok($test);
++
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at conflicts</A> = $pkg-&gt;conflicts_nosense;
++ok(@conflicts == 2);
++ok($conflicts[0] eq 'texinfo');
++ok($conflicts[1] eq 'gcc');
++
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at requires</A> = $pkg-&gt;requires_nosense;
++ok(@requires == 9);
++ok($requires[0] eq '/sbin/install-info');
++ok($requires[1] eq 'glibc');
++ok($requires[3] eq 'kernel-headers');
++ok($requires[8] eq 'rpmlib(CompressedFileNames)');
++
+<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">+ at provides</A> = $pkg-&gt;provides_nosense;
++ok(@provides == 1);
++ok($provides[0] eq 'glibc-devel');
+
+Added: rpm/perl-URPM/trunk/t/test-rpm.spec
+===================================================================
+--- rpm/perl-URPM/trunk/t/test-rpm.spec (rev 0)
++++ rpm/perl-URPM/trunk/t/test-rpm.spec 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,40 @@
++# $Id: test-rpm.spec 258552 2009-07-22 18:19:56Z peroyvind $
++
++# prevent distepoch &amp; disttag to be added and appended to package filename
++%undefine distepoch
++%undefine disttag
++
++Summary: test rpm for perl-URPM test suite
++BuildArch: noarch
++Name: test-rpm
++Version: 1.0
++Release: 1mdk
++License: GPL
++Group: Application/Development
++BuildRoot: %{_tmppath}/%{name}-root
++
++%description
++test rpm
++
++%prep
++
++%build
++
++%install
++rm -rf $RPM_BUILD_ROOT
++mkdir -p $RPM_BUILD_ROOT%_sysconfdir
++
++date &gt;&gt; $RPM_BUILD_ROOT%_sysconfdir/%name
++
++%clean
++rm -rf $RPM_BUILD_ROOT
++
++%files
++%defattr(-,root,root)
++%config(noreplace) %_sysconfdir/%name
++
++%changelog
++* Thu Apr 22 2004 Olivier Thauvin &lt;<A HREF="https://www.mageia.org/mailman/listinfo/mageia-sysadm">thauvin at aerov.jussieu.fr</A>&gt; 1-1mdk
++- initial build
++
++
+
+Added: rpm/perl-URPM/trunk/typemap
+===================================================================
+--- rpm/perl-URPM/trunk/typemap (rev 0)
++++ rpm/perl-URPM/trunk/typemap 2011-02-04 13:41:50 UTC (rev 419)
+@@ -0,0 +1,3 @@
++URPM::DB T_PTROBJ
++URPM::Transaction T_PTROBJ
++URPM::Package T_PTROBJ
+-------------- next part --------------
+An HTML attachment was scrubbed...
+URL: &lt;/pipermail/mageia-sysadm/attachments/20110204/fb8a6b76/attachment-0001.html&gt;
+</PRE>
+
+<!--endarticle-->
+ <HR>
+ <P><UL>
+ <!--threads-->
+ <LI>Previous message: <A HREF="002554.html">[Mageia-sysadm] [418] add README file
+</A></li>
+ <LI>Next message: <A HREF="002555.html">[Mageia-sysadm] [420] - import cleaned mageia-lxde-config
+</A></li>
+ <LI> <B>Messages sorted by:</B>
+ <a href="date.html#2825">[ date ]</a>
+ <a href="thread.html#2825">[ thread ]</a>
+ <a href="subject.html#2825">[ subject ]</a>
+ <a href="author.html#2825">[ author ]</a>
+ </LI>
+ </UL>
+
+<hr>
+<a href="https://www.mageia.org/mailman/listinfo/mageia-sysadm">More information about the Mageia-sysadm
+mailing list</a><br>
+</body></html>