aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPer Øyvind Karlsen <peroyvind@mandriva.org>2011-06-28 14:43:01 +0000
committerPer Øyvind Karlsen <peroyvind@mandriva.org>2011-06-28 14:43:01 +0000
commit2ab1c41aa1c488c9942fde9f793ac59b3d1c6706 (patch)
tree4e20aec8d34c4d5c68304c1a8ac0a017ebb71e4e
parent3864ff992fb4437f41269246ba61496f1511880f (diff)
downloadperl-URPM-2ab1c41aa1c488c9942fde9f793ac59b3d1c6706.tar
perl-URPM-2ab1c41aa1c488c9942fde9f793ac59b3d1c6706.tar.gz
perl-URPM-2ab1c41aa1c488c9942fde9f793ac59b3d1c6706.tar.bz2
perl-URPM-2ab1c41aa1c488c9942fde9f793ac59b3d1c6706.tar.xz
perl-URPM-2ab1c41aa1c488c9942fde9f793ac59b3d1c6706.zip
* merge changes from 3.37.2 (distepoch & disttag support for upgrades) and retrofit it to rpm 4.4 API
-rw-r--r--NEWS12
-rw-r--r--URPM.xs364
2 files changed, 348 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index 0b44e5f..4795c52 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+Version 3.18.2 - 28 June 2011, by Per Øyvind Karlsen
+
+- support getting disttag & distepoch from synthesis
+- fix URPM::Package->distepoch to actually work
+- add disttag & distepoch at end of @
+- add support for doing comparision against provides with distepoch to allow
+ fresh install of newer releases into chroots
+- convert suggests to compatible tags when loading package headers
+- fix incorrect arch returned for packages without any (ie. public keys)
+- eliminate disttag & distepoch when extracting name, version, release to
+ handle upgrade
+
Version 3.18.1 - 14 October 2008, by Pascal "Pixel" Rigaux
- $trans->run can now return both the translated errors, and some parsable
diff --git a/URPM.xs b/URPM.xs
index 40a3d6f..b82fc3c 100644
--- a/URPM.xs
+++ b/URPM.xs
@@ -127,6 +127,7 @@ typedef struct s_Package* URPM__Package;
#define FILENAME_TAG 1000000
#define FILESIZE_TAG 1000001
+#define RPMTAG_DISTEPOCH 1218
#define FILTER_MODE_ALL_FILES 0
#define FILTER_MODE_CONF_FILES 2
@@ -136,6 +137,8 @@ typedef struct s_Package* URPM__Package;
1 for rpm 4.2 and better new approach. */
#define PROMOTE_EPOCH_SENSE 1
+static struct headerTagTableEntry_s *ourTagTable = NULL;
+
static ssize_t write_nocheck(int fd, const void *buf, size_t count) {
return write(fd, buf, count);
}
@@ -159,6 +162,25 @@ void rpmError_callback() {
static int rpm_codeset_is_utf8 = 0;
+static struct s_backup {
+ char *ptr;
+ char chr;
+} char_backups[32];
+
+static int BI = 0;
+
+static void
+backup_char(char *c) {
+ char_backups[BI].chr = *c,
+ *(char_backups[BI++].ptr = &(*c)) = 0; /* mark end of string to enable searching backwards */
+}
+
+static void
+restore_chars() {
+ for(; BI > 0; char_backups[BI].ptr = NULL)
+ BI--, *char_backups[BI].ptr = char_backups[BI].chr;
+}
+
static SV*
newSVpv_utf8(const char *s, STRLEN len)
{
@@ -170,12 +192,35 @@ newSVpv_utf8(const char *s, STRLEN len)
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;
+ int i, disttag = 0;
+ char *tmp = pkg->info;
+ for (i = 0; i < 4 && tmp != NULL; i++)
+ tmp = strchr(++tmp, '@');
+ if (tmp++ != NULL && *tmp != '@')
+ disttag = 1;
+ /* XXX: filename at end of line, don't bother to support it, just make sure
+ * for it not to cause crash...
+ */
+ if ((tmp = strrchr(pkg->info, '.')) && !strcmp(tmp, ".rpm"))
+ disttag = 0;
if ((_eos = strchr(pkg->info, '@')) != NULL) {
*_eos = 0; /* mark end of string to enable searching backwards */
if ((_arch = strrchr(pkg->info, '.')) != NULL) {
*_arch = 0;
if ((release != NULL || version != NULL || name != NULL) && (_release = strrchr(pkg->info, '-')) != NULL) {
+ if (disttag) {
+ tmp = _release;
+ while(tmp != _arch) {
+ backup_char(tmp++);
+ }
+ if((tmp = strrchr(pkg->info, '-'))) {
+ _release = tmp;
+ } else {
+ restore_chars();
+ croak("failed while eliminating distepoch, this should never happen! :(");
+ }
+ }
*_release = 0;
if ((version != NULL || name != NULL) && (_version = strrchr(pkg->info, '-')) != NULL) {
if (name != NULL) *name = pkg->info;
@@ -210,6 +255,136 @@ get_int(Header header, int_32 tag) {
return i ? *i : 0;
}
+static void
+strip_distepoch(Header header, int_32 tag) {
+ int_32 type, count;
+ char **list;
+ int ix;
+
+ headerGetEntry(header, tag, &type, (void **) &list, &count);
+ for (ix = 0; ix < count; ix++) {
+ char *tmp = strchr(list[ix], '-');
+ if(tmp) {
+ tmp = strchr(tmp, ':');
+ if(tmp) {
+ memset(tmp, 0, strlen(tmp));
+ }
+ }
+ }
+ headerModifyEntry(header, tag, RPM_STRING_ARRAY_TYPE, list, 1);
+}
+
+static void
+pretend_distepoch(Header header, int_32 names_tag, int_32 flags_tag, int_32 versions_tag) {
+ char **name = NULL, **name2 = NULL;
+ int_32 *flag, *flag2;
+ int_32 type, type2;
+ int_32 count, count2;
+ int_32 ix;
+ char **version = NULL, **version2 = NULL;
+ char *EVR = headerSprintf(header, "%|EPOCH?{%{EPOCH}:}|%{VERSION}-%{RELEASE}", ourTagTable, headerDefaultFormats, NULL);
+
+ headerGetEntry(header, flags_tag, &type, (void **) &flag, &count);
+ headerGetEntry(header, versions_tag, &type2, (void **) &version, &count2);
+
+ for (ix = 0; ix < (int)count; ix++) {
+ if(!(flag[ix] & ((RPMSENSE_LESS|RPMSENSE_GREATER|~RPMSENSE_EQUAL))) && version[ix] && *version[ix] && !strcmp(EVR, version[ix])) {
+ if(!name) {
+ int_32 count3, type3;
+ headerGetEntry(header, names_tag, &type3, (void **) &name, &count3);
+
+ name2 = malloc(++count * sizeof(*name));
+ memcpy(name2, name, sizeof(*name)*count);
+ flag2 = malloc(count * sizeof(flag));
+ memcpy(flag2, flag, sizeof(flag)*count);
+ version2 = malloc(count * sizeof(*version));
+ memcpy(version2, version, sizeof(*version)*count);
+ } else {
+ name2 = realloc(name2, sizeof(*name) * ++count);
+ flag2 = realloc(flag2, sizeof(flag) * count);
+ version2 = realloc(version2, sizeof(*version) * count);
+ }
+ name2[count-1] = name[ix];
+ flag2[count-1] = (flag[ix] | RPMSENSE_LESS) & ~RPMSENSE_EQUAL;
+ flag2[ix] |= RPMSENSE_GREATER;
+ version2[count-1] = strdup(version[ix]);
+ char *v = version2[count-1];
+ (*(&v[strlen(v)-1]))++;
+ }
+ }
+ if(name) {
+ headerModifyEntry(header, names_tag, RPM_STRING_ARRAY_TYPE, name, count);
+ headerModifyEntry(header, flags_tag, RPM_INT32_TYPE, flag, count);
+ headerModifyEntry(header, versions_tag, RPM_STRING_ARRAY_TYPE, version, count);
+ }
+}
+
+static void
+remap_suggests(Header header) {
+ char **list, **list_evr;
+ int_32 *flags;
+ int_32 type, count, ix;
+
+ if (headerGetEntry(header, RPMTAG_REQUIREFLAGS, &type, (void **) &flags, &count)) {
+ int_32 count_sug = 0;
+ for(ix = 0; ix < count_sug; ix++)
+ if(flags[ix] & RPMSENSE_MISSINGOK)
+ count_sug++;
+
+ if(count_sug) {
+ if(headerGetEntry(header, RPMTAG_REQUIRENAME, &type, (void **) &list, &count)) {
+ headerGetEntry(header, RPMTAG_REQUIREVERSION, &type, (void **) &list_evr, &count);
+ char **list_sug, **list_evr_sug;
+ int_32 *flags_sug;
+ int_32 ix_sug, ix_list;
+
+ list_sug = malloc(count_sug * sizeof(char*));
+ flags_sug = malloc(count_sug * sizeof(int_32));
+ list_evr_sug = malloc(count_sug * sizeof(char*));
+
+ for(ix_sug = ix_list = ix = 0; ix < count; ix++) {
+ if(flags[ix] & RPMSENSE_MISSINGOK) {
+ list_sug[ix_sug] = list[ix];
+ flags_sug[ix_sug] = flags[ix];
+ list_evr_sug[ix_sug] = list_evr[ix];
+
+ ix_sug++;
+ count--;
+ }
+ else {
+ list[ix_list] = list[ix];
+ flags[ix_list] = flags[ix];
+ list_evr[ix_list] = list_evr[ix];
+ ix_list++;
+ }
+ }
+ headerModifyEntry(header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE, list, count);
+ headerModifyEntry(header, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE, flags, count);
+ headerModifyEntry(header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE, list_evr, count);
+
+ headerAddEntry(header, RPMTAG_SUGGESTSNAME, RPM_STRING_ARRAY_TYPE, list_sug, count_sug);
+ /* XXX: unused
+ headerAddEntry(header, RPMTAG_SUGGESTSFLAGS, RPM_INT32_TYPE, flags_sug, count_sug);
+ headerAddEntry(header, RPMTAG_SUGGESTSVERSION, RPM_STRING_ARRAY_TYPE, list_evr_sug, count_sug);
+ */
+ }
+ }
+ }
+}
+
+static void
+convert_header(Header header) {
+ if (header) {
+ if (headerIsEntry(header, RPMTAG_DISTEPOCH)) {
+ strip_distepoch(header, RPMTAG_PROVIDEVERSION);
+ strip_distepoch(header, RPMTAG_REQUIREVERSION);
+ strip_distepoch(header, RPMTAG_OBSOLETEVERSION);
+ strip_distepoch(header, RPMTAG_CONFLICTVERSION);
+ }
+ remap_suggests(header);
+ }
+}
+
static int
sigsize_to_filesize(int sigsize) {
return sigsize + 440; /* 440 is the rpm header size (?) empirical, but works */
@@ -254,7 +429,7 @@ ranges_overlap(int_32 aflags, char *sa, int_32 bflags, char *sb, int b_nopromote
int sense = 0;
char *eosa = strchr(sa, ']');
char *eosb = strchr(sb, ']');
- char *ea, *va, *ra, *eb, *vb, *rb;
+ char *ea, *va, *ra, *da, *eb, *vb, *rb, *db;
if (eosa) *eosa = 0;
if (eosb) *eosb = 0;
@@ -268,6 +443,9 @@ ranges_overlap(int_32 aflags, char *sa, int_32 bflags, char *sb, int b_nopromote
ea = NULL;
}
if ((ra = strrchr(sa, '-'))) *ra++ = 0;
+ if (ra && (da = strchr(ra, ':'))) *da++ = 0;
+ else da = NULL;
+
/* parse sb as an [epoch:]version[-release] */
for (eb = sb; *sb >= '0' && *sb <= '9'; ++sb);
if (*sb == ':') {
@@ -278,6 +456,8 @@ ranges_overlap(int_32 aflags, char *sa, int_32 bflags, char *sb, int b_nopromote
eb = NULL;
}
if ((rb = strrchr(sb, '-'))) *rb++ = 0;
+ if (rb && (db = strchr(rb, ':'))) *db++ = 0;
+ else db = NULL;
/* now compare epoch */
if (ea && eb)
sense = rpmvercmp(*ea ? ea : "0", *eb ? eb : "0");
@@ -292,6 +472,8 @@ ranges_overlap(int_32 aflags, char *sa, int_32 bflags, char *sb, int b_nopromote
sense = rpmvercmp(ra, rb);
}
/* restore all character that have been modified inline */
+ if (db) db[-1] = ':';
+ if (da) da[-1] = ':';
if (rb) rb[-1] = '-';
if (ra) ra[-1] = '-';
if (eb) vb[-1] = ':';
@@ -437,11 +619,28 @@ return_list_str(char *s, Header header, int_32 tag_name, int_32 tag_flags, int_3
if (tag_flags && tag_version) {
while(ps != NULL) {
++count;
- if (f(s, ps-s, NULL, 0, NULL, param)) return -count;
+ char *tmp, *ps2 = NULL;
+ if((tmp = strchr(s, '[')) &&
+ (tmp = strchr(tmp, '-')) &&
+ (tmp = strchr(tmp, ':')) &&
+ tmp < ps) {
+ backup_char(tmp);
+ *tmp = ']';
+ ps2 = ++tmp;
+ }
+ if (f(s, ps2 ? ps2-s : ps-s, NULL, 0, NULL, param)) { restore_chars(); return -count; }
+ restore_chars();
s = ps + 1; ps = strchr(s, '@');
}
++count;
- if (f(s, 0, NULL, 0, NULL, param)) return -count;
+ if((ps = strchr(s, '[')) &&
+ (ps = strchr(ps, '-')) &&
+ (ps = strchr(ps, ':'))) {
+ backup_char(ps);
+ *ps++ = ']';
+ }
+ if (f(s, ps ? ps-s : 0, NULL, 0, NULL, param)) { restore_chars(); return -count; }
+ restore_chars();
} else {
char *eos;
while(ps != NULL) {
@@ -652,13 +851,14 @@ return_list_tag(URPM__Package pkg, int_32 tag_name) {
case RPMTAG_ARCH:
{
get_fullname_parts(pkg, &name, &version, &release, &arch, &eos);
- XPUSHs(sv_2mortal(newSVpv(arch, eos-arch)));
+ XPUSHs(sv_2mortal(newSVpv(arch == eos ? "" : arch, eos-arch)));
}
break;
case RPMTAG_SUMMARY:
XPUSHs(sv_2mortal(newSVpv(pkg->summary, 0)));
break;
}
+ restore_chars();
}
PUTBACK;
}
@@ -828,15 +1028,28 @@ pack_header(URPM__Package pkg) {
if (pkg->info == NULL) {
char buff[1024];
char *p = buff;
- char *name = get_name(pkg->h, RPMTAG_NAME);
- char *version = get_name(pkg->h, RPMTAG_VERSION);
- char *release = get_name(pkg->h, RPMTAG_RELEASE);
- char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src";
-
- p += 1 + snprintf(buff, sizeof(buff), "%s-%s-%s.%s@%d@%d@%s", name, version, release, arch,
+ const char *group = get_name(pkg->h, RPMTAG_GROUP);
+ const char *disttag = get_name(pkg->h, RPMTAG_DISTTAG);
+ const char *distepoch = get_name(pkg->h, RPMTAG_DISTEPOCH);
+ const char *nvra = headerSprintf(pkg->h,
+ "%{NAME}-%{VERSION}-%{RELEASE}%|DISTTAG?{-%{DISTTAG}%|DISTEPOCH?"
+ "{%{DISTEPOCH}}|}|.%|ARCH?{%|SOURCERPM?{%{ARCH}}:{src}|}:{}|",
+ ourTagTable, headerDefaultFormats, NULL
+ );
+ p += snprintf(buff, sizeof(buff), "%s@%d@%d@%s", nvra,
get_int(pkg->h, RPMTAG_EPOCH), get_int(pkg->h, RPMTAG_SIZE),
- get_name(pkg->h, RPMTAG_GROUP));
+ group);
+ if (*disttag || *distepoch) {
+ p = stpcpy(p, "@");
+ if (*disttag)
+ p = stpcpy(p, disttag);
+ p = stpcpy(p, "@");
+ if (*distepoch)
+ p = stpcpy(p, distepoch);
+ }
+ *++p = '\0';
pkg->info = memcpy(malloc(p-buff), buff, p-buff);
+ _free(nvra);
}
if (pkg->filesize == 0) pkg->filesize = sigsize_to_filesize(get_int(pkg->h, RPMTAG_SIGSIZE));
if (pkg->requires == NULL && pkg->suggests == NULL)
@@ -1298,6 +1511,7 @@ update_header(char *filename, URPM__Package pkg, int keep_all_tags, int vsflags)
if (fd != NULL) {
if (pkg->h && !(pkg->flag & FLAG_NO_HEADER_FREE)) headerFree(pkg->h);
pkg->h = headerRead(fd, HEADER_MAGIC_YES);
+
pkg->flag &= ~FLAG_NO_HEADER_FREE;
Fclose(fd);
return 1;
@@ -1494,6 +1708,7 @@ Pkg_name(pkg)
get_fullname_parts(pkg, &name, &version, NULL, NULL, NULL);
if (version - name < 1) croak("invalid fullname");
XPUSHs(sv_2mortal(newSVpv(name, version-name-1)));
+ restore_chars();
} else if (pkg->h) {
XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_NAME), 0)));
}
@@ -1509,6 +1724,7 @@ Pkg_version(pkg)
get_fullname_parts(pkg, NULL, &version, &release, NULL, NULL);
if (release - version < 1) croak("invalid fullname");
XPUSHs(sv_2mortal(newSVpv(version, release-version-1)));
+ restore_chars();
} else if (pkg->h) {
XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_VERSION), 0)));
}
@@ -1523,7 +1739,8 @@ Pkg_release(pkg)
get_fullname_parts(pkg, NULL, NULL, &release, &arch, NULL);
if (arch - release < 1) croak("invalid fullname");
- XPUSHs(sv_2mortal(newSVpv(release, arch-release-1)));
+ XPUSHs(sv_2mortal(newSVpv(release, arch[-2] ? arch-release-1 : 0)));
+ restore_chars();
} else if (pkg->h) {
XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_RELEASE), 0)));
}
@@ -1537,7 +1754,8 @@ Pkg_arch(pkg)
char *eos;
get_fullname_parts(pkg, NULL, NULL, NULL, &arch, &eos);
- XPUSHs(sv_2mortal(newSVpv(arch, eos-arch)));
+ XPUSHs(sv_2mortal(newSVpv(arch == eos ? "" : arch, eos-arch)));
+ restore_chars();
} else if (pkg->h) {
XPUSHs(sv_2mortal(newSVpv(headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src", 0)));
}
@@ -1574,6 +1792,7 @@ Pkg_is_arch_compat__XS(pkg)
#else
RETVAL = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
#endif
+ restore_chars();
} else {
RETVAL = 0;
}
@@ -1605,6 +1824,7 @@ Pkg_is_platform_compat(pkg)
RETVAL = rpmPlatformScore(platform, NULL, 0);
*eos = '@';
_free(platform);
+ restore_chars();
} else {
#else
croak("is_platform_compat() is available only since rpm 4.4.8");
@@ -1750,8 +1970,9 @@ Pkg_fullname(pkg)
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)));
+ PUSHs(sv_2mortal(newSVpv(release, arch[-2] ? arch-release-1 : 0)));
+ PUSHs(sv_2mortal(newSVpv(arch == eos ? "" : arch, eos-arch)));
+ restore_chars();
}
} else if (pkg->h) {
char *name = get_name(pkg->h, RPMTAG_NAME);
@@ -1760,7 +1981,13 @@ Pkg_fullname(pkg)
char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src";
if (gimme == G_SCALAR) {
- XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s", name, version, release, arch)));
+ const char *nvra = headerSprintf(pkg->h,
+ "%{NAME}-%{VERSION}-%{RELEASE}%|DISTTAG?{-%{DISTTAG}%|DISTEPOCH?"
+ "{%{DISTEPOCH}}|}|.%|ARCH?{%|SOURCERPM?{%{ARCH}}:{src}|}:{}|",
+ ourTagTable, headerDefaultFormats, NULL
+ );
+ XPUSHs(sv_2mortal(newSVpvf("%s", nvra)));
+ _free(nvra);
} else if (gimme == G_ARRAY) {
EXTEND(SP, 4);
PUSHs(sv_2mortal(newSVpv(name, 0)));
@@ -1854,6 +2081,7 @@ Pkg_compare_pkg(lpkg, rpkg)
lrelease[-1] = '-';
larch[-1] = '.';
}
+ restore_chars();
croak("undefined package");
}
compare = lepoch - repoch;
@@ -1899,6 +2127,7 @@ Pkg_compare_pkg(lpkg, rpkg)
rrelease[-1] = '-';
rarch[-1] = '.';
}
+ restore_chars();
RETVAL = compare;
}
OUTPUT:
@@ -1933,7 +2162,7 @@ Pkg_compare(pkg, evr)
_epoch = get_int(pkg->h, RPMTAG_EPOCH);
} else croak("undefined package");
if (!compare) {
- char *epoch, *version, *release;
+ char *epoch, *version, *release, *distepoch;
/* extract epoch and version from evr */
version = evr;
@@ -1955,6 +2184,10 @@ Pkg_compare(pkg, evr)
/* continue extracting release if any */
if ((release = strrchr(version, '-')) != NULL) {
*release++ = 0;
+ /* XXX: compare distepoch rather than just ignoring? */
+ if ((distepoch = strrchr(release, ':')) != NULL)
+ *distepoch++ = 0;
+
compare = rpmvercmp(_version, version);
if (!compare) {
/* need to compare with release here */
@@ -1963,6 +2196,8 @@ Pkg_compare(pkg, evr)
compare = rpmvercmp(_release, release);
}
release[-1] = '-'; /* restore in memory modification */
+ if (distepoch != NULL)
+ distepoch[-1] = ':';
} else {
compare = rpmvercmp(_version, version);
}
@@ -1972,6 +2207,7 @@ Pkg_compare(pkg, evr)
if (pkg->info) {
_release[-1] = '-';
_eos[-1] = '.';
+ restore_chars();
}
RETVAL = compare;
OUTPUT:
@@ -2039,12 +2275,14 @@ Pkg_filename(pkg)
memcpy(eon, savbuf, 4);
}
} else if (pkg->h) {
- char *name = get_name(pkg->h, RPMTAG_NAME);
- char *version = get_name(pkg->h, RPMTAG_VERSION);
- char *release = get_name(pkg->h, RPMTAG_RELEASE);
- char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src";
-
- XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s.rpm", name, version, release, arch)));
+ const char *nvra = headerSprintf(pkg->h,
+ "%{NAME}-%{VERSION}-%{RELEASE}%|DISTTAG?{-%{DISTTAG}%|DISTEPOCH?"
+ "{%{DISTEPOCH}}|}|.%|ARCH?{%|SOURCERPM?{%{ARCH}}:{src}|}:{}|",
+ ourTagTable, headerDefaultFormats, NULL
+ );
+
+ XPUSHs(sv_2mortal(newSVpvf("%s.rpm", nvra)));
+ _free(nvra);
}
# deprecated
@@ -2061,13 +2299,17 @@ Pkg_header_filename(pkg)
} else if (pkg->h) {
char buff[1024];
char *p = buff;
- char *name = get_name(pkg->h, RPMTAG_NAME);
- char *version = get_name(pkg->h, RPMTAG_VERSION);
- char *release = get_name(pkg->h, RPMTAG_RELEASE);
- char *arch = headerIsEntry(pkg->h, RPMTAG_SOURCERPM) ? get_name(pkg->h, RPMTAG_ARCH) : "src";
- p += snprintf(buff, sizeof(buff), "%s-%s-%s.%s", name, version, release, arch);
+ const char *nvra = headerSprintf(pkg->h,
+ "%{NAME}-%{VERSION}-%{RELEASE}%|DISTTAG?{-%{DISTTAG}%|DISTEPOCH?"
+ "{%{DISTEPOCH}}|}|.%|ARCH?{%|SOURCERPM?{%{ARCH}}:{src}|}:{}|",
+ ourTagTable, headerDefaultFormats, NULL
+ );
+
+ p += snprintf(buff, sizeof(buff), "%s", nvra);
XPUSHs(sv_2mortal(newSVpv(buff, p-buff)));
+ _free(nvra);
+
}
void
@@ -2279,6 +2521,36 @@ Pkg_dirnames(pkg)
xpush_simple_list_str(pkg->h, RPMTAG_DIRNAMES);
SPAGAIN;
+void Pkg_distepoch(pkg)
+ URPM::Package pkg
+ PPCODE:
+ if (pkg->info) {
+ int i;
+ char *tmp = pkg->info, *eos = NULL;
+ for (i = 0; i < 5 && tmp != NULL; i++)
+ tmp = strchr(++tmp, '@');
+ if (tmp != NULL && *tmp)
+ eos = strchr(++tmp, '@');
+ XPUSHs(sv_2mortal(newSVpv((tmp && *tmp != '@') ? tmp : "", eos ? eos-tmp : 0)));
+ } else if (pkg->h) {
+ XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_DISTEPOCH), 0)));
+ }
+
+void Pkg_disttag(pkg)
+ URPM::Package pkg
+ PPCODE:
+ if (pkg->info) {
+ int i;
+ char *tmp = pkg->info, *eos = NULL;
+ for (i = 0; i < 4 && tmp != NULL; i++)
+ tmp = strchr(++tmp, '@');
+ if (tmp != NULL && *tmp)
+ eos = strchr(++tmp, '@');
+ XPUSHs(sv_2mortal(newSVpv((tmp && *tmp != '@') ? tmp : "", eos ? eos-tmp : 0)));
+ } else if (pkg->h) {
+ XPUSHs(sv_2mortal(newSVpv(get_name(pkg->h, RPMTAG_DISTTAG), 0)));
+ }
+
void
Pkg_filelinktos(pkg)
URPM::Package pkg
@@ -3062,7 +3334,35 @@ Trans_add(trans, pkg, ...)
}
}
}
+
+ if(headerIsEntry(pkg->h, RPMTAG_DISTEPOCH)) {
+ pretend_distepoch(pkg->h, RPMTAG_REQUIRENAME, RPMTAG_REQUIREFLAGS, RPMTAG_REQUIREVERSION);
+ }
+ remap_suggests(pkg->h);
+ /* If we're going to update to rpm 5.3, we'll create an empty DB_CONFIG
+ * first iff there's no existing DB_CONFIG in place. This will prevent
+ * switching to possibly incompatible configurations during upgrade.
+ */
+ if (!strcmp(get_name(pkg->h, RPMTAG_NAME), "rpm")) {
+ const char *version = get_name(pkg->h, RPMTAG_VERSION);
+ if (rpmvercmp(version, "5.3") >= 0) {
+ const char *fn = rpmGetPath("%{_dbpath}", "/DB_CONFIG", NULL);
+ struct stat st;
+ if (stat(fn, &st)) {
+ FD_t fd = Fopen(fn, "w");
+ Fclose(fd);
+ }
+ fn = _free(fn);
+ }
+ }
+
RETVAL = rpmtsAddInstallElement(trans->ts, pkg->h, (fnpyKey)(1+(long)(pkg->flag & FLAG_ID)), update, relocations) == 0;
+
+ rpmte te = rpmtsElement(trans->ts, 0);
+ headerLink(pkg->h);
+ rpmteSetHeader(te, pkg->h);
+ headerUnlink(pkg->h);
+
/* free allocated memory, check rpm is copying it just above, at least in 4.0.4 */
free(relocations);
} else RETVAL = 0;
@@ -3328,6 +3628,9 @@ MODULE = URPM PACKAGE = URPM PREFIX = Urpm_
BOOT:
(void) read_config_files(0);
+ourTagTable = malloc((sizeof(rpmTagTable[0])*rpmTagTableSize)+sizeof(rpmTagTable[0]));
+memcpy(ourTagTable, rpmTagTable, sizeof(rpmTagTable[0])*rpmTagTableSize);
+ourTagTable[rpmTagTableSize] = (struct headerTagTableEntry_s){ "RPMTAG_DISTEPOCH", RPMTAG_DISTEPOCH, RPM_STRING_TYPE };
void
Urpm_bind_rpm_textdomain_codeset()
@@ -3559,6 +3862,8 @@ Urpm_parse_hdlist__XS(urpm, filename, ...)
struct s_Package pkg, *_pkg;
SV *sv_pkg;
+ convert_header(header);
+
memset(&pkg, 0, sizeof(struct s_Package));
pkg.flag = 1 + av_len(depslist);
pkg.h = header;
@@ -3888,6 +4193,9 @@ Urpm_stream2header(fp)
pkg->h = headerRead(fd, HEADER_MAGIC_YES);
if (pkg->h) {
SV *sv_pkg;
+
+ convert_header(pkg->h);
+
EXTEND(SP, 1);
sv_pkg = sv_newmortal();
sv_setref_pv(sv_pkg, "URPM::Package", (void*)pkg);