OSDN Git Service

Add support for non-specific upgrade of all installed packages.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Fri, 7 Oct 2011 20:58:57 +0000 (20:58 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Fri, 7 Oct 2011 20:58:57 +0000 (20:58 +0000)
ChangeLog
src/climain.cpp
src/pkgbase.h
src/pkgdeps.cpp

index 39675f4..11f8aa9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-10-07  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Add support for non-specific upgrade of all installed packages.
+
+       * src/pkgbase.h (pkgXmlDocument::RescheduleInstalledPackages):
+       New public method; declare it.
+
+       * src/pkgdeps.cpp (pkgXmlDocument::RescheduleInstalledPackages):
+       Implement it.
+
+       * src/climain.cpp (climain) [ACTION_UPGRADE && argc < 2]: Invoke
+       pkgXmlDocument::RescheduleInstalledPackages() to schedule the upgrade
+       request for all packages currently registered as installed.
+
 2011-10-06  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Implement "source" and "licence" operations.
index b335d71..72cf516 100644 (file)
@@ -261,11 +261,29 @@ EXTERN_C int climain( int argc, char **argv )
            delete pkgProcessedArchives;
            break;
 
+         case ACTION_UPGRADE:
+           if( argc < 2 )
+             /*
+              * This is a special case of the upgrade request, for which
+              * no explicit package names have been specified; in this case
+              * we retrieve the list of all installed packages, scheduling
+              * each of them for upgrade...
+              */
+             dbase.RescheduleInstalledPackages( ACTION_UPGRADE );
+
+           /* ...subsequently falling through to complete the action,
+            * using the default processing mechanism; (note that in this
+            * case no further scheduling will be performed, because there
+            * are no additional package names specified in the argv list).
+            */
          default:
            /* ...schedule the specified action for each additional command line
             * argument, (each of which is assumed to represent a package name)...
             */
            while( --argc )
+             /*
+              * (Skipped if argv < 2 on entry).
+              */
              dbase.Schedule( (unsigned long)(action), *++argv );
 
            /* ...finally, execute all scheduled actions, and update the
@@ -275,7 +293,6 @@ EXTERN_C int climain( int argc, char **argv )
            dbase.UpdateSystemMap();
        }
       }
-
       /* If we get this far, then all actions completed successfully;
        * we are done.
        */
index 68db994..6c2ff1d 100644 (file)
@@ -395,6 +395,7 @@ class pkgXmlDocument : public TiXmlDocument
      */
     void Schedule( unsigned long, const char* );
     pkgActionItem* Schedule( unsigned long, pkgActionItem&, pkgActionItem* = NULL );
+    void RescheduleInstalledPackages( unsigned long );
 
     /* Method to execute a sequence of scheduled actions.
      */
index d885e55..2146f2b 100644 (file)
@@ -643,4 +643,82 @@ void pkgXmlDocument::Schedule( unsigned long action, const char* name )
     dmh_notify( DMH_ERROR, pkgMsgUnknownPackage(), name );
 }
 
+void pkgXmlDocument::RescheduleInstalledPackages( unsigned long action )
+{
+  /* Wrapper function to retrieve the list of all installed packages,
+   * passing each entry in turn to the standard task scheduler.  We
+   * begin by locating the first sysroot entry in the XML database...
+   */
+  pkgXmlNode *sysroot = GetRoot()->FindFirstAssociate( sysroot_key );
+
+  /* ...then, while we have sysroots to examine...
+   */
+  while( sysroot != NULL )
+  {
+    /* ...we retrieve the first package installation record within
+     * the current sysroot data set.
+     */
+    pkgXmlNode *package = sysroot->FindFirstAssociate( installed_key );
+
+    /* Within each sysroot, until we've retrieved all embedded
+     * installation records...
+     */
+    while( package != NULL )
+    {
+      /* ...we read the canonical tarname for the package,
+       * and when it is appropriately specified...
+       */
+      const char *tarname = package->GetPropVal( tarname_key, NULL );
+      if( tarname != NULL )
+      {
+       /* ...we decode it, to determine the package name,
+        * subsystem name and component class.
+        */
+       pkgSpecs decode( tarname );
+       const char *pkgname = decode.GetPackageName();
+       const char *sysname = decode.GetSubSystemName();
+       const char *cptname = decode.GetComponentClass();
+
+       /* From these three, we need to reconstruct an effective
+        * package name for the scheduler look-up; this reconstruction
+        * is performed using the following formatted buffer.
+        */
+       const char *fmt = "%s-%s";
+       char refname[3 + strlen( sysname ) + strlen( pkgname ) + strlen( cptname )];
+       if( FindPackageByName( pkgname, sysname ) == NULL )
+       {
+         /* The package name alone is insufficient for a successful
+          * look-up; assume that the effective package name has been
+          * defined by prefixing the sysroot name.
+          */
+         sprintf( refname, fmt, sysname, pkgname );
+         pkgname = refname;
+       }
+       if( cptname != NULL )
+       {
+         /* A fully qualified logical package name should include
+          * the component class name, abstracted from the canonical
+          * tarname, and appended to the package name.
+          */
+         sprintf( refname, fmt, pkgname, cptname );
+         pkgname = refname;
+       }
+
+       /* Having constructed the effective logical package name,
+        * we schedule the requested action on the package...
+        */
+       Schedule( action, pkgname );
+      }
+      /* ...then move on to the next installed package, if any,
+       * within the current sysroot data set...
+       */
+      package = package->FindNextAssociate( installed_key );
+    }
+    /* ...and ultimately, to the next sysroot, if any, in the
+     * XML database.
+     */
+    sysroot = sysroot->FindNextAssociate( sysroot_key );
+  }
+}
+
 /* $RCSfile$: end of file */