aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--URPM.pm6
-rw-r--r--URPM.xs45
-rw-r--r--URPM/Resolve.pm12
4 files changed, 62 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index e4c1745..c136498 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+- handle promotion via obsolete, not only provides
+
Version 2.03 - 20 September 2007, by Pascal "Pixel" Rigaux
- fix bug doing "urpmi kernel-source"
diff --git a/URPM.pm b/URPM.pm
index e2bf32a..11629f9 100644
--- a/URPM.pm
+++ b/URPM.pm
@@ -19,6 +19,7 @@ sub new {
my $self = bless {
depslist => [],
provides => {},
+ obsoletes => {},
}, $class;
$self->{nofatal} = 1 if $options{nofatal};
$self;
@@ -31,6 +32,11 @@ sub packages_providing {
map { $urpm->{depslist}[$_] } keys %{$urpm->{provides}{$name} || {}};
}
+sub packages_obsoleting {
+ my ($urpm, $name) = @_;
+ map { $urpm->{depslist}[$_] } keys %{$urpm->{obsoletes}{$name} || {}};
+}
+
sub packages_by_name {
my ($urpm, $name) = @_;
grep { $name eq $_->name } packages_providing($urpm, $name);
diff --git a/URPM.xs b/URPM.xs
index 188065e..9eb3c1b 100644
--- a/URPM.xs
+++ b/URPM.xs
@@ -897,6 +897,36 @@ update_provides(URPM__Package pkg, HV *provides) {
}
static void
+update_obsoletes(URPM__Package pkg, HV *obsoletes) {
+ if (pkg->h) {
+ int_32 type, count;
+ char **list = NULL;
+ int i;
+
+ /* update all provides */
+ headerGetEntry(pkg->h, RPMTAG_OBSOLETENAME, &type, (void **) &list, &count);
+ if (list)
+ for (i = 0; i < count; ++i)
+ update_hash_entry(obsoletes, list[i], 0, 1, 0, pkg);
+ } else {
+ char *ps, *s;
+
+ if ((s = pkg->obsoletes) != NULL && *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->h) {
STRLEN len;
@@ -1047,7 +1077,7 @@ call_package_callback(SV *urpm, SV *sv_pkg, SV *callback) {
}
static int
-parse_line(AV *depslist, HV *provides, URPM__Package pkg, char *buff, SV *urpm, SV *callback) {
+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;
@@ -1066,6 +1096,7 @@ parse_line(AV *depslist, HV *provides, URPM__Package pkg, char *buff, SV *urpm,
_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));
@@ -3250,6 +3281,8 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
AV *depslist = fdepslist && SvROK(*fdepslist) && SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
SV **fprovides = hv_fetch((HV*)SvRV(urpm), "provides", 8, 0);
HV *provides = fprovides && SvROK(*fprovides) && SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
+ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), "obsoletes", 9, 0);
+ HV *obsoletes = fobsoletes && SvROK(*fobsoletes) && SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
if (depslist != NULL) {
char buff[65536];
@@ -3285,7 +3318,7 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
if ((eol = strchr(p, '\n')) != NULL) {
do {
*eol++ = 0;
- if (!parse_line(depslist, provides, &pkg, p, urpm, callback)) { ok = 0; break; }
+ if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) { ok = 0; break; }
p = eol;
} while ((eol = strchr(p, '\n')) != NULL);
} else {
@@ -3295,7 +3328,7 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
break;
}
if (gzeof(f)) {
- if (!parse_line(depslist, provides, &pkg, p, urpm, callback)) ok = 0;
+ if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) ok = 0;
break;
} else {
/* move the remaining non-complete-line at beginning */
@@ -3331,6 +3364,8 @@ Urpm_parse_hdlist__XS(urpm, filename, ...)
AV *depslist = fdepslist && SvROK(*fdepslist) && SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
SV **fprovides = hv_fetch((HV*)SvRV(urpm), "provides", 8, 0);
HV *provides = fprovides && SvROK(*fprovides) && SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
+ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), "obsoletes", 9, 0);
+ HV *obsoletes = fobsoletes && SvROK(*fobsoletes) && SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
if (depslist != NULL) {
pid_t pid = 0;
@@ -3385,6 +3420,7 @@ Urpm_parse_hdlist__XS(urpm, filename, ...)
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);
}
@@ -3425,6 +3461,8 @@ Urpm_parse_rpm(urpm, filename, ...)
AV *depslist = fdepslist && SvROK(*fdepslist) && SvTYPE(SvRV(*fdepslist)) == SVt_PVAV ? (AV*)SvRV(*fdepslist) : NULL;
SV **fprovides = hv_fetch((HV*)SvRV(urpm), "provides", 8, 0);
HV *provides = fprovides && SvROK(*fprovides) && SvTYPE(SvRV(*fprovides)) == SVt_PVHV ? (HV*)SvRV(*fprovides) : NULL;
+ SV **fobsoletes = hv_fetch((HV*)SvRV(urpm), "obsoletes", 8, 0);
+ HV *obsoletes = fobsoletes && SvROK(*fobsoletes) && SvTYPE(SvRV(*fobsoletes)) == SVt_PVHV ? (HV*)SvRV(*fobsoletes) : NULL;
if (depslist != NULL) {
struct s_Package pkg, *_pkg;
@@ -3487,6 +3525,7 @@ Urpm_parse_rpm(urpm, filename, ...)
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);
}
diff --git a/URPM/Resolve.pm b/URPM/Resolve.pm
index d8eca12..f47b562 100644
--- a/URPM/Resolve.pm
+++ b/URPM/Resolve.pm
@@ -1018,6 +1018,18 @@ sub _handle_diff_provides {
unsatisfied_requires($urpm, $db, $state, $_, name => $n) == 0 }
@packages;
+ if (!@packages) {
+ @packages = packages_obsoleting($urpm, $p->name);
+ @packages = grep {
+ !$_->flag_skip
+ && $_->is_arch_compat
+ && !exists $state->{rejected}->{$_->fullname}
+ && $_->obsoletes_overlap($p->name . " == " . $p->epoch . ":" . $p->version . "-" . $p->release)
+ && $_->fullname ne $p->fullname &&
+ unsatisfied_requires($urpm, $db, $state, $_, name => $n) == 0;
+ } @packages;
+ }
+
if (@packages) {
my $best = join('|', map { $_->id } @packages);
$urpm->{debug_URPM}("promoting " . $urpm->{depslist}[$best]->fullname . " because of conflict above") if $urpm->{debug_URPM};