--- /dev/null
+Index: main.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/main.c,v
+retrieving revision 1.110.4.14
+retrieving revision 1.110.4.15
+diff -u -r1.110.4.14 -r1.110.4.15
+--- main.c 6 Jun 2004 20:47:51 -0000 1.110.4.14
++++ main.c 2 Jul 2004 17:42:39 -0000 1.110.4.15
+@@ -11,7 +11,7 @@
+ */
+
+ /*
+- $Id$
++ $Id$
+ */
+
+ #ifdef HAVE_CONFIG_H
+@@ -223,8 +223,10 @@
+ #define OPT_INST_DOWNGRADE 1058
+ #define OPT_INST_UNIQNAMES 'Q'
+
+-#define OPT_RPMONLY_FORCE 1059
+-#define OPT_RPMONLY_NODEPS 1060
++#define OPT_CAPLOOKUP 1059
++#define OPT_RPMONLY_FORCE 1070
++#define OPT_RPMONLY_NODEPS 1071
++
+
+ #define OPT_UNINSTALL 'e'
+
+@@ -327,6 +329,9 @@
+ {0,0,0,0, N_("Packages spec:"), 65},
+ {"pset", OPT_PKGSET, "FILE", 0, N_("Take package set definition from FILE"), 65 },
+ {"pkgset", 0, 0, OPTION_ALIAS | OPTION_HIDDEN, 0, 65 }, /* backward compat */
++{"caplookup", OPT_CAPLOOKUP, 0, 0,
++ N_("Look into package capabilities & files to resolve packages"), 65 },
++
+
+ // obsoleted by '#'
+ {"nevr", OPT_NEVR, "\"NAME [[E:][V[-R]]]\"", OPTION_HIDDEN,
+@@ -385,7 +390,7 @@
+
+ {"nodeps", OPT_INST_NODEPS, 0, 0,
+ N_("Install packages with broken dependencies"), 71 },
+-
++
+ {"force", OPT_INST_FORCE, 0, 0,
+ N_("Be unconcerned"), 71 },
+
+@@ -560,6 +565,10 @@
+ case OPT_PKGSET:
+ n_array_push(argsp->pkgdef_sets, arg);
+ break;
++
++ case OPT_CAPLOOKUP:
++ argsp->inst.flags |= INSTS_CAPLOOKUP;
++ break;
+
+ case 'l':
+ if (argsp->mjrmode != MODE_SRCLIST)
+Index: pkgset-install.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/pkgset-install.c,v
+retrieving revision 1.82.4.10
+retrieving revision 1.82.4.11
+diff -u -r1.82.4.10 -r1.82.4.11
+--- pkgset-install.c 22 Jun 2004 17:13:35 -0000 1.82.4.10
++++ pkgset-install.c 2 Jul 2004 17:42:39 -0000 1.82.4.11
+@@ -11,7 +11,7 @@
+ */
+
+ /*
+- $Id$
++ $Id$
+ */
+
+ #ifdef HAVE_CONFIG_H
+@@ -171,9 +171,11 @@
+ logn(LOGERR, msg, pkg_snprintf_s(pkg), eqs, giveup);
+ install = -1;
+
+- } else if (is_hand_marked && !freshen) { /* msg without "freshen" */
+- msgn(0, msg, pkg_snprintf_s(pkg), eqs, skiped);
+-
++ } else if (is_hand_marked) {
++ int vl = 0;
++ if (freshen)
++ vl = 3;
++ msgn(vl, msg, pkg_snprintf_s(pkg), eqs, skiped);
+ }
+ }
+ }
+@@ -2331,11 +2333,10 @@
+ }
+ }
+
+-static
+-int unmark_name_dups(tn_array *pkgs)
++static int unmark_name_dups(tn_array *pkgs)
+ {
+ struct pkg *pkg, *pkg2;
+- int i, n;
++ int i, n, nmarked;
+
+ if (n_array_size(pkgs) < 2)
+ return 0;
+@@ -2349,7 +2350,8 @@
+
+ if (!pkg_is_marked(pkg))
+ continue;
+-
++
++ nmarked++;
+ DBGF("%s\n", pkg_snprintf_s(pkg));
+
+
+@@ -2360,6 +2362,7 @@
+
+ i++;
+ n++;
++ //nmarked--;
+ if (i == n_array_size(pkgs))
+ break;
+ pkg2 = n_array_nth(pkgs, i);
+@@ -2367,9 +2370,100 @@
+ }
+ }
+
+- return n;
++ return nmarked;
++}
++
++static
++int prepare_icap(struct upgrade_s *upg, const char *capname, tn_array *pkgs)
++{
++ int i, found = 0;
++ tn_array *dbpkgs;
++ struct capreq *cap = capreq_new_name_a(capname);
++
++ dbpkgs = rpm_get_provides_dbpkgs(upg->inst->db->dbh, cap, NULL, 0);
++ if (dbpkgs == NULL) {
++ struct pkg *pkg;
++ if (upg->inst->flags & INSTS_FRESHEN)
++ return 0;
++
++ pkg = n_array_nth(pkgs, 0);
++ pkg_hand_mark(pkg);
++ return 1;
++ }
++
++ n_array_sort_ex(pkgs, (tn_fn_cmp)pkg_cmp_name_evr_rev);
++
++ for (i=0; i < n_array_size(dbpkgs); i++) {
++ struct dbpkg *dbpkg = n_array_nth(dbpkgs, i);
++ int n = n_array_bsearch_idx_ex(pkgs, dbpkg->pkg,
++ (tn_fn_cmp)pkg_cmp_name);
++
++ DBGF("%s: %s\n", capname, pkg_snprintf_s0(dbpkg->pkg));
++
++ if (n < 0)
++ continue;
++
++ for (; n < n_array_size(pkgs); n++) {
++ struct pkg *pkg = n_array_nth(pkgs, n);
++ int cmprc, mark = 0;
++
++ DBGF("%s: %s cmp %s\n", capname, pkg_snprintf_s(pkg),
++ pkg_snprintf_s0(dbpkg->pkg));
++ if (pkg_cmp_name(pkg, dbpkg->pkg) != 0)
++ break;
++
++ cmprc = pkg_cmp_name_evr(pkg, dbpkg->pkg);
++ if (cmprc > 0)
++ mark = 1;
++
++ else if (cmprc == 0 && upg->inst->flags & INSTS_REINSTALL)
++ mark = 1;
++
++ else if (cmprc < 0 && upg->inst->flags & INSTS_DOWNGRADE)
++ mark = 1;
++
++ if (mark) {
++ found = 1;
++ msgn(1, "%s: marked as %s provider", pkg_snprintf_s(pkg),
++ capname);
++
++ pkg_hand_mark(pkg);
++ goto l_end;
++
++ } else if (cmprc <= 0) {
++ char *eqs = cmprc == 0 ? "equal" : "newer";
++ msgn(1, "%s: %s version of %s is installed (%s), skipped",
++ capname, eqs, pkg_snprintf_s0(dbpkg->pkg),
++ pkg_snprintf_s(pkg));
++
++ } else {
++ n_assert(0);
++
++ }
++ }
++ }
++l_end:
++ if (dbpkgs)
++ n_array_free(dbpkgs);
++
++ return found;
+ }
+
++static
++int prepare_icaps(struct upgrade_s *upg)
++{
++ tn_array *keys;
++ int i;
++
++ keys = n_hash_keys_cp(upg->inst->icaps);
++ for (i=0; i < n_array_size(keys); i++) {
++ const char *cap = n_array_nth(keys, i);
++ tn_array *pkgs = n_hash_get(upg->inst->icaps, cap);
++ prepare_icap(upg, cap, pkgs);
++ }
++ n_array_free(keys);
++ return 1;
++}
+
+ int pkgset_install(struct pkgset *ps, struct inst_s *inst,
+ struct install_info *iinf)
+@@ -2381,13 +2475,15 @@
+ if (inst->flags & INSTS_INSTALL)
+ n_assert((inst->flags & INSTS_UPGRADE) == 0);
+
+-
+ packages_mark(ps->pkgs, 0, PKG_INTERNALMARK | PKG_INDIRMARK);
+
+- unmark_name_dups(ps->pkgs);
+-
+- mem_info(1, "ENTER pkgset_install:");
++ mem_info(2, "ENTER pkgset_install:");
+ init_upgrade_s(&upg, ps, inst);
++ prepare_icaps(&upg);
++ if (unmark_name_dups(ps->pkgs) == 0) {
++ msgn(1, _("Nothing to do"));
++ return 1;
++ }
+
+ is_particle = inst->flags & INSTS_PARTICLE;
+
+@@ -2421,8 +2517,11 @@
+ }
+ }
+
+- if (nmarked == 0)
++ if (nmarked == 0) {
++ msgn(1, _("Nothing to do"));
+ goto l_end;
++ }
++
+
+ if (nmarked == 1)
+ inst->flags &= ~INSTS_PARTICLE;
+Index: pkgset.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/pkgset.c,v
+retrieving revision 1.55.4.3
+retrieving revision 1.55.4.4
+diff -u -r1.55.4.3 -r1.55.4.4
+--- pkgset.c 6 Jun 2004 20:47:51 -0000 1.55.4.3
++++ pkgset.c 2 Jul 2004 17:42:40 -0000 1.55.4.4
+@@ -11,7 +11,7 @@
+ */
+
+ /*
+- $Id$
++ $Id$
+ */
+
+ #include <limits.h>
+@@ -150,6 +150,7 @@
+ inst->rpmopts = n_array_new(4, free, (tn_fn_cmp)strcmp);
+ inst->hold_patterns = n_array_new(4, free, (tn_fn_cmp)strcmp);
+ inst->ign_patterns = n_array_new(4, free, (tn_fn_cmp)strcmp);
++ inst->icaps = n_hash_new(21, (tn_fn_free)n_array_free);
+ }
+
+ struct pkgset *pkgset_new(unsigned optflags)
+@@ -836,9 +837,40 @@
+ return rc;
+ }
+
++static int pkgset_mark_bycap(struct pkgset *ps, struct inst_s *inst,
++ const struct pkgdef *pdef)
++{
++ tn_array *pkgs;
++
++ n_assert(inst->flags & INSTS_CAPLOOKUP);
++
++ pkgs = pkgset_lookup_cap(ps, pdef->pkg->name);
++ if (pkgs == NULL || n_array_size(pkgs) == 0) {
++ logn(LOGERR, _("mark: %s not found"), pdef->pkg->name);
++ if (pkgs)
++ n_array_free(pkgs);
++ return 0;
++ }
++
++ if (verbose > 1) {
++ int i;
++
++ msgn(2, "%s: %d package(s) found:", pdef->pkg->name,
++ n_array_size(pkgs));
++ for (i=0; i<n_array_size(pkgs); i++)
++ msgn(2, " - %s", pkg_snprintf_s(n_array_nth(pkgs, i)));
++
++ }
++
++ n_hash_insert(inst->icaps, pdef->pkg->name, pkgs);
++ return n_array_size(pkgs);
++}
++
++
++
+ static
+-int pkgset_mark_pkgdef_exact(struct pkgset *ps, const struct pkgdef *pdef,
+- int nodeps)
++int pkgset_mark_pkgdef_exact(struct pkgset *ps, struct inst_s *inst,
++ const struct pkgdef *pdef, int nodeps)
+ {
+ int i, marked = 0, matched = 0;
+ struct pkg *pkg, tmpkg, *findedpkg;
+@@ -851,10 +883,13 @@
+
+ i = n_array_bsearch_idx_ex(ps->pkgs, pdef->pkg, (tn_fn_cmp)pkg_cmp_name);
+ if (i < 0) {
++ if (inst->flags & INSTS_CAPLOOKUP)
++ return pkgset_mark_bycap(ps, inst, pdef);
+ logn(LOGERR, _("mark: %s not found"), pdef->pkg->name);
+ return 0;
+ }
+
++
+ findedpkg = pkg = n_array_nth(ps->pkgs, i);
+
+ if (pkg_match_pkgdef(pkg, pdef)) {
+@@ -877,9 +912,10 @@
+ }
+ }
+
++#if 0
+ if (!marked && !matched)
+ logn(LOGERR, _("mark: %s: versions not match"), pdef->pkg->name);
+-
++#endif
+ return marked;
+ }
+
+@@ -924,6 +960,29 @@
+ return nerr;
+ }
+
++static int pkgset_mark_verify_icaps(struct inst_s *inst)
++{
++ tn_array *keys;
++ int i, j;
++
++ keys = n_hash_keys_cp(inst->icaps);
++ for (i=0; i<n_array_size(keys); i++) {
++ const char *cap = n_array_nth(keys, i);
++ tn_array *pkgs = n_hash_get(inst->icaps, cap);
++
++ for (j=0; j < n_array_size(pkgs); j++) {
++ struct pkg *pkg = n_array_nth(pkgs, j);
++ if (pkg_is_marked(pkg)) {
++ logn(LOGNOTICE, "%s: removed cap due to %s is marked",
++ cap, pkg_snprintf_s0(pkg));
++ n_hash_remove(inst->icaps, cap);
++ break;
++ }
++ }
++ }
++ n_array_free(keys);
++ return n_hash_size(inst->icaps);
++}
+
+
+ int pkgset_mark_usrset(struct pkgset *ps, struct usrpkgset *ups,
+@@ -931,6 +990,7 @@
+ {
+ int i, nerr = 0, nodeps = 0, npatterns = 0;
+
++ n_hash_clean(inst->icaps);
+ packages_mark(ps->pkgs, 0, PKG_INDIRMARK | PKG_DIRMARK);
+ //pkgset_mark(ps, PS_MARK_OFF_ALL);
+
+@@ -942,7 +1002,7 @@
+ for (i=0; i<n_array_size(ups->pkgdefs); i++) {
+ struct pkgdef *pdef = n_array_nth(ups->pkgdefs, i);
+ if (pdef->tflags & (PKGDEF_REGNAME | PKGDEF_PKGFILE)) {
+- if (!pkgset_mark_pkgdef_exact(ps, pdef, nodeps))
++ if (!pkgset_mark_pkgdef_exact(ps, inst, pdef, nodeps))
+ nerr++;
+
+ } else if (pdef->tflags & PKGDEF_PATTERN) {
+@@ -950,6 +1010,7 @@
+
+ } else if (pdef->tflags & PKGDEF_VIRTUAL) { /* VIRTUAL implies OPTIONAL */
+ tn_array *avpkgs;
++
+
+ #if 0
+ if (pdef->pkg == NULL) {
+@@ -1010,7 +1071,7 @@
+ if ((inst->flags & INSTS_CONFIRM_INST) && inst->ask_fn &&
+ inst->ask_fn(0, "Install %s? [y/N]", pdef->pkg->name));
+ #endif
+- if (!pkgset_mark_pkgdef_exact(ps, pdef, nodeps))
++ if (!pkgset_mark_pkgdef_exact(ps, inst, pdef, nodeps))
+ nerr++;
+
+ } else {
+@@ -1036,7 +1097,8 @@
+ logn(LOGERR, _("Buggy package set."));
+ }
+ }
+-
++
++ pkgset_mark_verify_icaps(inst);
+ return nerr == 0;
+ }
+
+@@ -1056,8 +1118,40 @@
+ return n_array_nth(ps->pkgs, i);
+ }
+
++tn_array *pkgset_lookup_cap(struct pkgset *ps, const char *capname)
++{
++ struct pkg **suspkgs, pkgsbuf[1024];
++ int i, nsuspkgs = 0, found = 0;
++ tn_array *pkgs = NULL;
++ struct capreq *cap = capreq_new_name_a(capname);
++
++ DBGF("%s\n", capname);
++
++ found = psreq_lookup(ps, cap, &suspkgs, (struct pkg **)pkgsbuf, &nsuspkgs);
++ if (found && nsuspkgs) {
++ struct pkg **matches;
++ int nmatches = 0, strict;
++
++ found = 0;
++ matches = alloca(sizeof(*matches) * nsuspkgs);
++ strict = ps->flags & PSVERIFY_MERCY ? 0 : 1;
++ if (psreq_match_pkgs(NULL, cap, strict, suspkgs,
++ nsuspkgs, matches, &nmatches)) {
++ found = 1;
++ pkgs = n_array_new(nmatches, NULL,
++ (tn_fn_cmp)pkg_cmp_name_evr_rev);
++
++ if (nmatches > 0) {
++ for (i=0; i < nmatches; i++)
++ n_array_push(pkgs, matches[i]);
++ }
++ }
++ }
++ return pkgs;
++}
++
+
+-tn_array *pkgset_lookup_cap(struct pkgset *ps, const char *capname)
++tn_array *pkgset_lookup_cap_OLD(struct pkgset *ps, const char *capname)
+ {
+ const struct capreq_idx_ent *ent;
+ tn_array *pkgs = NULL;
+Index: pkgset.h
+===================================================================
+RCS file: /cvsroot/installer/poldek/pkgset.h,v
+retrieving revision 1.37.4.2
+retrieving revision 1.37.4.3
+diff -u -r1.37.4.2 -r1.37.4.3
+--- pkgset.h 16 Feb 2004 19:39:57 -0000 1.37.4.2
++++ pkgset.h 2 Jul 2004 17:42:40 -0000 1.37.4.3
+@@ -1,4 +1,4 @@
+-/* $Id$ */
++/* $Id$ */
+ #ifndef POLDEK_PKGSET_H
+ #define POLDEK_PKGSET_H
+
+@@ -53,8 +53,8 @@
+ #define INSTS_JUSTFETCH (1 << 10)
+ #define INSTS_JUSTPRINT (1 << 11)
+ #define INSTS_JUSTPRINT_N (1 << 12) /* names, not filenames */
+-
+ #define INSTS_JUSTPRINTS (INSTS_JUSTPRINT | INSTS_JUSTPRINT_N)
++#define INSTS_CAPLOOKUP (1 << 13)
+
+
+ #define INSTS_MKDBDIR (1 << 15) /* --mkdir */
+@@ -86,7 +86,8 @@
+ tn_array *rpmopts; /* rpm cmdline opts (char *opts[]) */
+ tn_array *rpmacros; /* rpm macros to pass to cmdline (char *opts[]) */
+ tn_array *hold_patterns;
+- tn_array *ign_patterns;
++ tn_array *ign_patterns;
++ tn_hash *icaps;
+
+ int (*askpkg_fn)(const char *, struct pkg **pkgs, struct pkg *deflt);
+ int (*ask_fn)(int default_a, const char *, ...);
+Index: rpm.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/Attic/rpm.c,v
+retrieving revision 1.41.4.4
+retrieving revision 1.41.4.5
+diff -u -r1.41.4.4 -r1.41.4.5
+--- rpm.c 28 Jun 2004 20:18:39 -0000 1.41.4.4
++++ rpm.c 2 Jul 2004 17:42:40 -0000 1.41.4.5
+@@ -11,7 +11,7 @@
+ */
+
+ /*
+- $Id$
++ $Id$
+ */
+
+ #ifdef HAVE_CONFIG_H
+@@ -614,7 +614,7 @@
+
+ rpmdb_it_init(db, &it, RPMITER_CAP, capreq_name(cap));
+ while ((dbrec = rpmdb_it_get(&it))) {
+- if (dbpkg_array_has(unistdbpkgs, dbrec->recno))
++ if (unistdbpkgs && dbpkg_array_has(unistdbpkgs, dbrec->recno))
+ continue;
+
+ if (dbpkgs == NULL)
+Index: usrset.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/Attic/usrset.c,v
+retrieving revision 1.12.6.1
+retrieving revision 1.12.6.2
+diff -u -r1.12.6.1 -r1.12.6.2
+--- usrset.c 30 Dec 2003 18:19:52 -0000 1.12.6.1
++++ usrset.c 2 Jul 2004 17:42:40 -0000 1.12.6.2
+@@ -7,7 +7,7 @@
+ */
+
+ /*
+- $Id$
++ $Id$
+ */
+
+ #include <ctype.h>
+@@ -108,7 +108,7 @@
+ if (*p == '\0' || *p == '#')
+ return 0;
+
+- while (*p && !isalnum(*p)) {
++ while (*p && !isalnum(*p) && *p != '/') {
+ switch (*p) {
+ case '~':
+ case '!': /* for backward compatybility */
+@@ -125,7 +125,7 @@
+ p++;
+ }
+
+- if (!isalnum(*p)) {
++ if (!isalnum(*p) && *p != '/') {
+ if (nline > 0)
+ logn(LOGERR, _("%s:%d: syntax error"), fpath, nline);
+ else
+@@ -168,7 +168,7 @@
+
+
+ pdef = n_malloc(sizeof(*pdef) +
+- (virtname ? strlen(virtname) + 1 : 0));
++ (virtname ? strlen(virtname) + 1 : 0));
+ pdef->tflags = tflags | deftyp;
+
+ if (name == NULL) {
--- /dev/null
+Index: pkgset-order.c
+===================================================================
+RCS file: /cvsroot/installer/poldek/pkgset-order.c,v
+retrieving revision 1.16
+diff -u -r1.16 pkgset-order.c
+--- pkgset-order.c 24 Oct 2002 16:41:04 -0000 1.16
++++ pkgset-order.c 2 Jul 2004 17:07:02 -0000
+@@ -36,6 +36,7 @@
+ static void mapfn_clean_pkg_color(struct pkg *pkg)
+ {
+ pkg_set_color(pkg, PKG_COLOR_WHITE);
++ pkg_clr_prereqed(pkg);
+ }
+
+ /*
+@@ -45,11 +46,13 @@
+ tn_array *ordered_pkgs;
+ tn_array *stack;
+ int nerrors;
++ int prereq_only;
+ };
+
+
+ static
+-int visit_install_order(struct visit_install_order_s *vs, struct pkg *pkg, int deep)
++int visit_install_order(struct visit_install_order_s *vs, struct pkg *pkg,
++ int deep)
+ {
+ int i, last_stack_i = -1;
+
+@@ -68,7 +71,7 @@
+ if (verbose > 2) {
+ msg(4, "_\n");
+ msg_i(4, deep, "_ visit %s -> (", pkg->name);
+- for (i=0; i<n_array_size(pkg->reqpkgs); i++) {
++ for (i=0; i < n_array_size(pkg->reqpkgs); i++) {
+ struct reqpkg *rp;
+
+ rp = n_array_nth(pkg->reqpkgs, i);
+@@ -102,7 +105,9 @@
+ pkg_set_prereqed(rp->pkg);
+ else
+ pkg_clr_prereqed(rp->pkg);
+- visit_install_order(vs, rp->pkg, deep);
++
++ if (!vs->prereq_only || (rp->flags & REQPKG_PREREQ))
++ visit_install_order(vs, rp->pkg, deep);
+
+ } else if (pkg_is_color(rp->pkg, PKG_COLOR_BLACK)) {
+ msg(4, "_\n");
+@@ -178,10 +183,11 @@
+ }
+ }
+ msg(4, "_\n");
+-
++
+ l_end:
+ pkg_set_color(pkg, PKG_COLOR_BLACK);
+ pkg_clr_prereqed(pkg);
++ msgn(4, "push %s", pkg_snprintf_s(pkg));
+ n_array_push(vs->ordered_pkgs, pkg_link(pkg));
+ if (last_stack_i != -1)
+ for (i=last_stack_i; i < n_array_size(vs->stack); i++) {
+@@ -192,9 +198,7 @@
+ return 0;
+ }
+
+-
+-/* RET: number of detected loops */
+-int packages_order(tn_array *pkgs, tn_array **ordered_pkgs)
++static int do_order(tn_array *pkgs, tn_array **ordered_pkgs, int prereq_only)
+ {
+ struct pkg *pkg;
+ struct visit_install_order_s vs;
+@@ -204,15 +208,14 @@
+ (tn_fn_free)pkg_free, NULL);
+ vs.nerrors = 0;
+ vs.stack = n_array_new(128, NULL, NULL);
++ vs.prereq_only = prereq_only;
+
+ n_array_map(pkgs, (tn_fn_map1)mapfn_clean_pkg_color);
+- n_array_isort_ex(pkgs, (tn_fn_cmp)pkg_cmp_pri);
+-
++
+ for (i=0; i<n_array_size(pkgs); i++) {
+ pkg = n_array_nth(pkgs, i);
+- //printf("V %d %s\n", i, pkg_snprintf_s(pkg));
+ if (pkg_is_color(pkg, PKG_COLOR_WHITE)) {
+- visit_install_order(&vs, pkg, 1);
++ visit_install_order(&vs, pkg, 1);
+ n_array_clean(vs.stack);
+ }
+ }
+@@ -222,8 +225,30 @@
+ n_assert(*ordered_pkgs == NULL);
+ n_array_free(vs.stack);
+ *ordered_pkgs = vs.ordered_pkgs;
+- n_array_isort(pkgs);
+ return vs.nerrors;
++}
++
++
++/* RET: number of detected loops */
++int packages_order(tn_array *pkgs, tn_array **ordered_pkgs)
++{
++ tn_array *ordered = NULL;
++ int nloops, verbose_;
++
++ n_array_isort_ex(pkgs, (tn_fn_cmp)pkg_cmp_pri);
++
++ verbose_ = verbose;
++ verbose = -10;
++ do_order(pkgs, &ordered, 0);
++
++ verbose = verbose_;
++ *ordered_pkgs = NULL;
++ nloops = do_order(ordered, ordered_pkgs, 1);
++
++ n_array_free(ordered);
++ n_array_isort(pkgs);
++
++ return nloops;
+ }
+
+ int pkgset_order(struct pkgset *ps)
--- /dev/null
+--- poldek-0.18.6/vfile/vfprogress.c 2004-06-08 15:57:03.000000000 +0200
++++ poldek-0.18.6-patrys/vfile/vfprogress.c 2004-07-07 18:36:25.262259864 +0200
+@@ -60,14 +60,15 @@
+
+ static int eta2str(char *buf, int bufsize, struct vf_progress_bar *bar)
+ {
+- int mm, ss, n = 0;
++ int hh, mm, ss, n = 0;
+ float eta = bar->eta + 0.5;
+
+
+- mm = (int)(eta / 60.0);
++ hh = (int)(eta / 60.0 / 60.00);
++ mm = (int)(eta / 60.0) % 60;
+ ss = (int)eta % 60;
+ if (mm || ss)
+- n = n_snprintf(&buf[n], bufsize - n, "%.2d:%.2d ETA", mm, ss);
++ n = n_snprintf(&buf[n], bufsize - n, "%.2d:%.2d:%.2d", hh, mm, ss);
+ return n;
+ }
+
+@@ -84,8 +85,6 @@
+ bar->transfer_rate = (float)amount / (current_time - bar->time_base);
+ if (bar->transfer_rate > 0)
+ bar->eta = (total - amount) / bar->transfer_rate;
+-
+- bar->transfer_rate /= 1024.0;
+ }
+
+
+@@ -95,6 +94,7 @@
+ char line[256], outline[256], fmt[40];
+ float frac, percent;
+ long n;
++ int screen_width = term_get_width();
+
+
+ if (bar->state == VF_PROGRESS_DISABLED)
+@@ -107,8 +107,18 @@
+ bar->state = VF_PROGRESS_DISABLED;
+ return;
+ }
++
++ if (screen_width < 50) /* what kind of terminal is this?! */
++ {
++ screen_width = 50;
++ }
++ if (screen_width > 255) /* this might cause problems */
++ {
++ screen_width = 255;
++ }
+
+ if (bar->state == VF_PROGRESS_VIRGIN) {
++ bar->width = screen_width - 49; /* calculate bar width = screen width - 8 - unit_line*/
+ if (total > 0) {
+ if (total == amount || /* downloaded before progress() call */
+ total < 1024) { /* too small to show to */
+@@ -142,7 +152,7 @@
+ return;
+ }
+ calculate_tt(total, amount, bar);
+- n_assert(bar->prev_n < 100);
++// n_assert(bar->prev_n < 100);
+ if (!bar->is_tty) {
+ int k;
+
+@@ -159,18 +169,19 @@
+ }
+
+ } else {
+- char unit_line[45], amount_str[16], total_str[16];
++ char unit_line[42], amount_str[16], total_str[16], transfer_str[16];
+ int nn;
+
+ nbytes2str(total_str, sizeof(total_str), total);
+ nbytes2str(amount_str, sizeof(amount_str), amount);
++ nbytes2str(transfer_str, sizeof(transfer_str), bar->transfer_rate);
+
+ if (total == amount) {
+ if (bar->time_base == bar->time_last) /* fetched in less than 1s */
+ bar->transfer_rate = total / 1024.0;
+
+- nn = n_snprintf(unit_line, sizeof(unit_line), "[%s (%.1fK/s)]",
+- total_str, bar->transfer_rate);
++ nn = n_snprintf(unit_line, sizeof(unit_line), "[ %7s] [%7s/s]",
++ total_str, transfer_str);
+ } else {
+ int n = 0;
+ char eta_str[64];
+@@ -178,10 +189,9 @@
+ n = eta2str(eta_str, sizeof(eta_str), bar);
+
+ nn = n_snprintf(unit_line, sizeof(unit_line),
+- "[%s of %s (%.1fK/s)%s%s]",
+- amount_str, total_str, bar->transfer_rate,
+- n ? ", ": "",
+- n ? eta_str : "");
++ "[%7s/%7s] [%7s/s] [%8s]",
++ amount_str, total_str, transfer_str,
++ n ? eta_str : "--:--:--");
+ }
+ if (nn > bar->maxlen)
+ bar->maxlen = nn;