5523e9
This patchset consists of following upstream commits:
5523e9
- 1f3164ae6975747e72af383f2d74c27245e6fe36
5523e9
- fd40d58efa0fbff535f273e5ae5c200d43d28aef
5523e9
- bfa76529864b9dfb29258f4dedc3fa9de9c5aeca
5523e9
- 6665503ec6fb6430ecaafb3e318a4730f146efa9
5523e9
- bf856744f2820a1625ef9428284b5788d18103f3
5523e9
- c5200145fa08da884ce2c1ed85941363eeae6407
5523e9
- 80dee39fb1f97ab3927c10bdd13c7c438b5677be
5523e9
5523e9
with some changes to make RPM to compile.
5523e9
5523e9
diff -uNr rpm-4.11.3/doc/rpm.8 rpm-4.11.3.reinstall/doc/rpm.8
5523e9
--- rpm-4.11.3/doc/rpm.8	2017-07-12 16:57:41.711722771 +0200
5523e9
+++ rpm-4.11.3.reinstall/doc/rpm.8	2017-07-12 16:14:26.842680581 +0200
5523e9
@@ -110,7 +110,7 @@
5523e9
 One of the following basic modes must be selected:
5523e9
 \fBQuery\fR,
5523e9
 \fBVerify\fR,
5523e9
-\fBInstall/Upgrade/Freshen\fR,
5523e9
+\fBInstall/Upgrade/Freshen/Reinstall\fR,
5523e9
 \fBUninstall\fR,
5523e9
 \fBSet Owners/Groups\fR,
5523e9
 \fBShow Querytags\fR, and
5523e9
@@ -206,6 +206,13 @@
5523e9
 This will upgrade packages, but only ones for which an earlier version is
5523e9
 installed.
5523e9
 .PP
5523e9
+The general form of an rpm reinstall command is 
5523e9
+.PP
5523e9
+\fBrpm\fR {\fB--reinstall\fR} [\fBinstall-options\fR] \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
5523e9
+.PP
5523e9
+This reinstalls a previously installed package.
5523e9
+.PP
5523e9
+.PP
5523e9
 .TP
5523e9
 \fB--allfiles\fR
5523e9
 Installs or upgrades all the missingok files in the package,
5523e9
diff -uNr rpm-4.11.3/lib/depends.c rpm-4.11.3.reinstall/lib/depends.c
5523e9
--- rpm-4.11.3/lib/depends.c	2017-07-12 16:57:41.742723041 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/depends.c	2017-07-12 16:14:12.203550634 +0200
5523e9
@@ -54,6 +54,12 @@
5523e9
 #undef HASHTYPE
5523e9
 #undef HTKEYTYPE
5523e9
 
5523e9
+enum addOp_e {
5523e9
+    RPMTE_INSTALL	= 0,
5523e9
+    RPMTE_UPGRADE	= 1,
5523e9
+    RPMTE_REINSTALL	= 2,
5523e9
+};
5523e9
+
5523e9
 /**
5523e9
  * Check for supported payload format in header.
5523e9
  * @param h		header to check
5523e9
@@ -126,7 +132,7 @@
5523e9
 }
5523e9
 
5523e9
 /* Return rpmdb iterator with removals optionally pruned out */
5523e9
-static rpmdbMatchIterator rpmtsPrunedIterator(rpmts ts, rpmDbiTagVal tag,
5523e9
+rpmdbMatchIterator rpmtsPrunedIterator(rpmts ts, rpmDbiTagVal tag,
5523e9
 					      const char * key, int prune)
5523e9
 {
5523e9
     rpmdbMatchIterator mi = rpmtsInitIterator(ts, tag, key, 0);
5523e9
@@ -152,22 +158,29 @@
5523e9
 }
5523e9
 
5523e9
 /* Add erase elements for older packages of same color (if any). */
5523e9
-static int addUpgradeErasures(rpmts ts, rpm_color_t tscolor,
5523e9
+static int addSelfErasures(rpmts ts, rpm_color_t tscolor, int op,
5523e9
 				rpmte p, rpm_color_t hcolor, Header h)
5523e9
 {
5523e9
     Header oh;
5523e9
     rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0);
5523e9
     int rc = 0;
5523e9
+    int cmp;
5523e9
 
5523e9
     while((oh = rpmdbNextIterator(mi)) != NULL) {
5523e9
 	/* Ignore colored packages not in our rainbow. */
5523e9
 	if (skipColor(tscolor, hcolor, headerGetNumber(oh, RPMTAG_HEADERCOLOR)))
5523e9
 	    continue;
5523e9
 
5523e9
-	/* Skip packages that contain identical NEVR. */
5523e9
-	if (rpmVersionCompare(h, oh) == 0)
5523e9
+	cmp = rpmVersionCompare(h, oh);
5523e9
+
5523e9
+	/* On upgrade, skip packages that contain identical NEVR. */
5523e9
+	if ((op == RPMTE_UPGRADE) && (cmp == 0))
5523e9
 	    continue;
5523e9
 
5523e9
+	/* On reinstall, skip packages with differing NEVR. */
5523e9
+	if ((op == RPMTE_REINSTALL) && (cmp != 0))
5523e9
+	    continue;
5523e9
+	
5523e9
 	if (removePackage(ts, oh, p)) {
5523e9
 	    rc = 1;
5523e9
 	    break;
5523e9
@@ -385,8 +398,8 @@
5523e9
     return al;
5523e9
 }
5523e9
 
5523e9
-int rpmtsAddInstallElement(rpmts ts, Header h,
5523e9
-			fnpyKey key, int upgrade, rpmRelocation * relocs)
5523e9
+static int addPackage(rpmts ts, Header h,
5523e9
+		    fnpyKey key, int op, rpmRelocation * relocs)
5523e9
 {
5523e9
     tsMembers tsmem = rpmtsMembers(ts);
5523e9
     rpm_color_t tscolor = rpmtsColor(ts);
5523e9
@@ -403,10 +416,10 @@
5523e9
 
5523e9
     /* Source packages are never "upgraded" */
5523e9
     if (isSource)
5523e9
-	upgrade = 0;
5523e9
+	op = RPMTE_INSTALL;
5523e9
 
5523e9
     /* Do lazy (readonly?) open of rpm database for upgrades. */
5523e9
-    if (upgrade && rpmtsGetRdb(ts) == NULL && rpmtsGetDBMode(ts) != -1) {
5523e9
+    if (op != RPMTE_INSTALL && rpmtsGetRdb(ts) == NULL && rpmtsGetDBMode(ts) != -1) {
5523e9
 	if ((ec = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0)
5523e9
 	    goto exit;
5523e9
     }
5523e9
@@ -419,7 +432,7 @@
5523e9
 
5523e9
     /* Check binary packages for redundancies in the set */
5523e9
     if (!isSource) {
5523e9
-	oc = findPos(ts, tscolor, p, upgrade);
5523e9
+	oc = findPos(ts, tscolor, p, (op == RPMTE_UPGRADE));
5523e9
 	/* If we're replacing a previously added element, free the old one */
5523e9
 	if (oc >= 0 && oc < tsmem->orderCount) {
5523e9
 	    rpmalDel(tsmem->addedPackages, tsmem->order[oc]);
5523e9
@@ -451,15 +464,33 @@
5523e9
 
5523e9
     /* Add erasure elements for old versions and obsoletions on upgrades */
5523e9
     /* XXX TODO: If either of these fails, we'd need to undo all additions */
5523e9
-    if (upgrade) {
5523e9
-	addUpgradeErasures(ts, tscolor, p, rpmteColor(p), h);
5523e9
+    if (op != RPMTE_INSTALL)
5523e9
+	addSelfErasures(ts, tscolor, op, p, rpmteColor(p), h);
5523e9
+    if (op == RPMTE_UPGRADE)
5523e9
 	addObsoleteErasures(ts, tscolor, p);
5523e9
-    }
5523e9
 
5523e9
 exit:
5523e9
     return ec;
5523e9
 }
5523e9
 
5523e9
+int rpmtsAddInstallElement(rpmts ts, Header h,
5523e9
+			fnpyKey key, int upgrade, rpmRelocation * relocs)
5523e9
+{
5523e9
+    int op = (upgrade == 0) ? RPMTE_INSTALL : RPMTE_UPGRADE;
5523e9
+    if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL)
5523e9
+	return 1;
5523e9
+    return addPackage(ts, h, key, op, relocs);
5523e9
+}
5523e9
+
5523e9
+int rpmtsAddReinstallElement(rpmts ts, Header h, fnpyKey key)
5523e9
+{
5523e9
+    if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL)
5523e9
+	return 1;
5523e9
+    /* TODO: pull relocations from installed package */
5523e9
+    /* TODO: should reinstall of non-installed package fail? */
5523e9
+    return addPackage(ts, h, key, RPMTE_REINSTALL, NULL);
5523e9
+}
5523e9
+
5523e9
 int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
5523e9
 {
5523e9
     return removePackage(ts, h, NULL);
5523e9
diff -uNr rpm-4.11.3/lib/poptI.c rpm-4.11.3.reinstall/lib/poptI.c
5523e9
--- rpm-4.11.3/lib/poptI.c	2013-06-07 09:37:21.000000000 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/poptI.c	2017-07-12 16:14:26.842680581 +0200
5523e9
@@ -247,6 +247,10 @@
5523e9
 	&rpmIArgs.installInterfaceFlags, (INSTALL_UPGRADE|INSTALL_INSTALL),
5523e9
 	N_("upgrade package(s)"),
5523e9
 	N_("<packagefile>+") },
5523e9
+ { "reinstall", '\0', POPT_BIT_SET,
5523e9
+	&rpmIArgs.installInterfaceFlags, (INSTALL_REINSTALL|INSTALL_INSTALL),
5523e9
+	N_("reinstall package(s)"),
5523e9
+	N_("<packagefile>+") },
5523e9
 
5523e9
    POPT_TABLEEND
5523e9
 };
5523e9
diff -uNr rpm-4.11.3/lib/rpmcli.h rpm-4.11.3.reinstall/lib/rpmcli.h
5523e9
--- rpm-4.11.3/lib/rpmcli.h	2017-07-12 16:57:41.741723032 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/rpmcli.h	2017-07-12 16:14:26.842680581 +0200
5523e9
@@ -293,7 +293,8 @@
5523e9
     INSTALL_FRESHEN	= (1 << 6),	/*!< from --freshen */
5523e9
     INSTALL_INSTALL	= (1 << 7),	/*!< from --install */
5523e9
     INSTALL_ERASE	= (1 << 8),	/*!< from --erase */
5523e9
-    INSTALL_ALLMATCHES	= (1 << 9)	/*!< from --allmatches */
5523e9
+    INSTALL_ALLMATCHES	= (1 << 9),	/*!< from --allmatches */
5523e9
+    INSTALL_REINSTALL	= (1 << 10),	/*!< from --reinstall */
5523e9
 };
5523e9
 
5523e9
 typedef rpmFlags rpmInstallFlags;
5523e9
@@ -354,7 +355,7 @@
5523e9
 };
5523e9
 
5523e9
 /** \ingroup rpmcli
5523e9
- * Install/upgrade/freshen binary rpm package.
5523e9
+ * Install/upgrade/freshen/reinstall binary rpm package.
5523e9
  * @param ts		transaction set
5523e9
  * @param ia		mode flags and parameters
5523e9
  * @param fileArgv	array of package file names (NULL terminated)
5523e9
diff -uNr rpm-4.11.3/lib/rpminstall.c rpm-4.11.3.reinstall/lib/rpminstall.c
5523e9
--- rpm-4.11.3/lib/rpminstall.c	2014-09-05 13:48:07.000000000 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/rpminstall.c	2017-07-12 16:14:26.843680590 +0200
5523e9
@@ -552,7 +552,10 @@
5523e9
 	        continue;
5523e9
 	    }
5523e9
 
5523e9
-	rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName,
5523e9
+	if (ia->installInterfaceFlags & INSTALL_REINSTALL)
5523e9
+	    rc = rpmtsAddReinstallElement(ts, h, (fnpyKey)fileName);
5523e9
+	else
5523e9
+	    rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName,
5523e9
 			(ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
5523e9
 			relocations);
5523e9
 
5523e9
diff -uNr rpm-4.11.3/lib/rpmts.h rpm-4.11.3.reinstall/lib/rpmts.h
5523e9
--- rpm-4.11.3/lib/rpmts.h	2017-07-12 16:57:41.710722762 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/rpmts.h	2017-07-12 16:14:12.203550634 +0200
5523e9
@@ -544,6 +544,16 @@
5523e9
 		rpmRelocation * relocs);
5523e9
 
5523e9
 /** \ingroup rpmts
5523e9
+ * Add package to be reinstalled to transaction set.
5523e9
+ *
5523e9
+ * @param ts		transaction set
5523e9
+ * @param h		header
5523e9
+ * @param key		package retrieval key (e.g. file name)
5523e9
+ * @return		0 on success
5523e9
+ */
5523e9
+int rpmtsAddReinstallElement(rpmts ts, Header h, const fnpyKey key);
5523e9
+
5523e9
+/** \ingroup rpmts
5523e9
  * Add package to be erased to transaction set.
5523e9
  * @param ts		transaction set
5523e9
  * @param h		header
5523e9
diff -uNr rpm-4.11.3/lib/rpmts_internal.h rpm-4.11.3.reinstall/lib/rpmts_internal.h
5523e9
--- rpm-4.11.3/lib/rpmts_internal.h	2014-06-04 11:25:23.000000000 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/rpmts_internal.h	2017-07-12 16:44:18.613959252 +0200
5523e9
@@ -86,6 +86,11 @@
5523e9
 RPM_GNUC_INTERNAL
5523e9
 tsMembers rpmtsMembers(rpmts ts);
5523e9
 
5523e9
+/* Return rpmdb iterator with removals optionally pruned out */
5523e9
+RPM_GNUC_INTERNAL
5523e9
+rpmdbMatchIterator rpmtsPrunedIterator(rpmts ts, rpmDbiTagVal tag,
5523e9
+					      const char * key, int prune);
5523e9
+
5523e9
 RPM_GNUC_INTERNAL
5523e9
 rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types);
5523e9
 
5523e9
@@ -118,6 +123,9 @@
5523e9
  */
5523e9
 void rpmtsSELabelFini(rpmts ts, int close_status);
5523e9
 
5523e9
+RPM_GNUC_INTERNAL
5523e9
+rpmRC rpmtsSetupTransactionPlugins(rpmts ts);
5523e9
+
5523e9
 #ifdef __cplusplus
5523e9
 }
5523e9
 #endif
5523e9
diff -uNr rpm-4.11.3/lib/transaction.c rpm-4.11.3.reinstall/lib/transaction.c
5523e9
--- rpm-4.11.3/lib/transaction.c	2017-07-12 16:57:41.747723085 +0200
5523e9
+++ rpm-4.11.3.reinstall/lib/transaction.c	2017-07-12 16:43:59.563741144 +0200
5523e9
@@ -1138,7 +1138,7 @@
5523e9
 	if (!(probFilter & RPMPROB_FILTER_REPLACEPKG)) {
5523e9
 	    Header h;
5523e9
 	    rpmdbMatchIterator mi;
5523e9
-	    mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0);
5523e9
+	    mi = rpmtsPrunedIterator(ts, RPMDBI_NAME, rpmteN(p), 1);
5523e9
 	    rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p));
5523e9
 	    rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p));
5523e9
 	    rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p));
5523e9
@@ -1444,7 +1444,7 @@
5523e9
     return rc;
5523e9
 }
5523e9
 
5523e9
-static rpmRC rpmtsSetupTransactionPlugins(rpmts ts)
5523e9
+rpmRC rpmtsSetupTransactionPlugins(rpmts ts)
5523e9
 {
5523e9
     rpmRC rc = RPMRC_OK;
5523e9
     ARGV_t files = NULL;
5523e9
diff -uNr rpm-4.11.3/python/rpm/transaction.py rpm-4.11.3.reinstall/python/rpm/transaction.py
5523e9
--- rpm-4.11.3/python/rpm/transaction.py	2014-02-05 14:04:02.000000000 +0100
5523e9
+++ rpm-4.11.3.reinstall/python/rpm/transaction.py	2017-07-12 16:14:22.573642686 +0200
5523e9
@@ -50,7 +50,7 @@
5523e9
         else:
5523e9
             return tuple(keys)
5523e9
 
5523e9
-    def addInstall(self, item, key, how="u"):
5523e9
+    def _f2hdr(self, item):
5523e9
         if isinstance(item, _string_types):
5523e9
             f = open(item)
5523e9
             header = self.hdrFromFdno(f)
5523e9
@@ -59,6 +59,10 @@
5523e9
             header = item
5523e9
         else:
5523e9
             header = self.hdrFromFdno(item)
5523e9
+        return header
5523e9
+
5523e9
+    def addInstall(self, item, key, how="u"):
5523e9
+        header = self._f2hdr(item)
5523e9
 
5523e9
         if not how in ['u', 'i']:
5523e9
             raise ValueError('how argument must be "u" or "i"')
5523e9
@@ -67,6 +71,12 @@
5523e9
         if not TransactionSetCore.addInstall(self, header, key, upgrade):
5523e9
             raise rpm.error("adding package to transaction failed")
5523e9
 
5523e9
+    def addReinstall(self, item, key):
5523e9
+        header = self._f2hdr(item)
5523e9
+
5523e9
+        if not TransactionSetCore.addReinstall(self, header, key):
5523e9
+            raise rpm.error("adding package to transaction failed")
5523e9
+
5523e9
     def addErase(self, item):
5523e9
         hdrs = []
5523e9
         if isinstance(item, rpm.hdr):
5523e9
diff -uNr rpm-4.11.3/python/rpmts-py.c rpm-4.11.3.reinstall/python/rpmts-py.c
5523e9
--- rpm-4.11.3/python/rpmts-py.c	2017-07-12 16:57:41.741723032 +0200
5523e9
+++ rpm-4.11.3.reinstall/python/rpmts-py.c	2017-07-12 16:14:18.800609194 +0200
5523e9
@@ -190,6 +190,24 @@
5523e9
 }
5523e9
 
5523e9
 static PyObject *
5523e9
+rpmts_AddReinstall(rpmtsObject * s, PyObject * args)
5523e9
+{
5523e9
+    Header h = NULL;
5523e9
+    PyObject * key;
5523e9
+    int rc;
5523e9
+
5523e9
+    if (!PyArg_ParseTuple(args, "O&O:AddReinstall", 
5523e9
+			  hdrFromPyObject, &h, &key))
5523e9
+	return NULL;
5523e9
+
5523e9
+    rc = rpmtsAddReinstallElement(s->ts, h, key);
5523e9
+    if (key && rc == 0) {
5523e9
+	PyList_Append(s->keyList, key);
5523e9
+    }
5523e9
+    return PyBool_FromLong((rc == 0));
5523e9
+}
5523e9
+
5523e9
+static PyObject *
5523e9
 rpmts_AddErase(rpmtsObject * s, PyObject * args)
5523e9
 {
5523e9
     Header h;
5523e9
@@ -693,6 +711,8 @@
5523e9
 static struct PyMethodDef rpmts_methods[] = {
5523e9
  {"addInstall",	(PyCFunction) rpmts_AddInstall,	METH_VARARGS,
5523e9
 	NULL },
5523e9
+ {"addReinstall",	(PyCFunction) rpmts_AddReinstall,	METH_VARARGS,
5523e9
+	NULL },
5523e9
  {"addErase",	(PyCFunction) rpmts_AddErase,	METH_VARARGS|METH_KEYWORDS,
5523e9
 	NULL },
5523e9
  {"check",	(PyCFunction) rpmts_Check,	METH_VARARGS|METH_KEYWORDS,
5523e9
diff -uNr rpm-4.11.3/rpmqv.c rpm-4.11.3.reinstall/rpmqv.c
5523e9
--- rpm-4.11.3/rpmqv.c	2012-11-07 13:55:24.000000000 +0100
5523e9
+++ rpm-4.11.3.reinstall/rpmqv.c	2017-07-12 16:14:26.843680590 +0200
5523e9
@@ -135,7 +135,8 @@
5523e9
 #ifdef	IAM_RPMEIU
5523e9
   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
5523e9
     {	int iflags = (ia->installInterfaceFlags &
5523e9
-		(INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
5523e9
+			(INSTALL_UPGRADE|INSTALL_FRESHEN|
5523e9
+			 INSTALL_INSTALL|INSTALL_REINSTALL));
5523e9
 	int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
5523e9
 
5523e9
 	if (iflags & eflags)