Diff of /src/pkgbind.cpp [2facf8] .. [b70b9b] Maximize Restore

  Switch to side-by-side view

--- a/src/pkgbind.cpp
+++ b/src/pkgbind.cpp
@@ -4,7 +4,7 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009, 2010, 2011, MinGW Project
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
  *
  *
  * Implementation of repository binding for the pkgXmlDocument class.
@@ -40,6 +40,9 @@
    * of package lists, from any specified repository.
    */
   public:
+    static void Reset( void ){ count = total = 0; }
+    static void IncrementTotal( void ){ ++total; }
+
     pkgRepository( pkgXmlDocument*, pkgXmlNode*, pkgXmlNode*, bool );
     ~pkgRepository(){};
 
@@ -50,8 +53,15 @@
     pkgXmlNode *dbase;
     pkgXmlNode *repository;
     pkgXmlDocument *owner;
+    static int count, total;
     bool force_update;
 };
+
+/* Don't forget that we MUST explicitly allocate static storage for
+ * static property values declared within the pkgRepository class.
+ */
+int pkgRepository::count;
+int pkgRepository::total;
 
 pkgRepository::pkgRepository
 /*
@@ -74,16 +84,57 @@
     const char *dfile;
     if( (dfile = xmlfile( dname )) != NULL )
     {
+      /* We've identified a further "package-list" file; update the
+       * count of such files processed, to include this one.
+       */
+      ++count;
+
       /* Check for a locally cached copy of the "package-list" file...
        */
+      const char *mode = "Loading";
+      const char *fmt = "%s catalogue: %s.xml; (item %d of %d)\n";
       if( force_update || (access( dfile, F_OK ) != 0) )
       {
 	/* When performing an "update", or if no local copy is available...
 	 * Force a "sync", to fetch a copy from the public host.
 	 */
-	dmh_printf( "Update catalogue: %s.xml\n", dname );
+	const char *mode = force_update ? "Updating" : "Downloading";
+	if( owner->ProgressMeter() != NULL )
+	  /*
+	   * Progress of the "update" is being metered; annotate the
+	   * metering display accordingly...
+	   */
+	  owner->ProgressMeter()->Annotate( fmt, mode, dname, count, total );
+
+	else
+	  /* Progress is not being explicitly metered, but the user
+	   * may still appreciate a minimal progress report...
+	   */
+	  dmh_printf( fmt, mode, dname, count, total );
+
+	/* During the actual fetch, collect any generated diagnostics
+	 * for the current catalogue file into a message digest, so
+	 * that the GUI may present them in a single message box.
+	 */
+	dmh_control( DMH_BEGIN_DIGEST );
 	owner->SyncRepository( dname, repository );
       }
+      else if( owner->ProgressMeter() != NULL )
+	/*
+	 * This is a simple request to load a local copy of the
+	 * catalogue file; progress metering is in effect, so we
+	 * annotate the metering display accordingly...
+	 */
+	owner->ProgressMeter()->Annotate( fmt, mode, dname, count, total );
+
+      else if( pkgOptions()->Test( OPTION_VERBOSE ) > 1 )
+	/*
+	 * Similarly, this is a request to load a local copy of
+	 * the catalogue; progress metering is not in effect, but
+	 * the user has requested verbose diagnostics, so issue
+	 * a diagnostic progress report.
+	 */
+	dmh_printf( fmt, mode, dname, count, total );
 
       /* We SHOULD now have a locally cached copy of the package-list;
        * attempt to merge it into the active profile database...
@@ -94,8 +145,6 @@
 	/* We successfully loaded the XML catalogue; refer to its
 	 * root element...
 	 */
-	if( pkgOptions()->Test( OPTION_VERBOSE ) > 1 )
-	  dmh_printf( "Load catalogue: %s.xml\n", dname );
 	pkgXmlNode *catalogue, *pkglist;
 	if( (catalogue = merge.GetRoot()) != NULL )
 	{
@@ -118,7 +167,31 @@
 	  /* Recursively incorporate any additional package lists,
 	   * which may be specified within the current catalogue...
 	   */
-	  GetPackageList( catalogue->FindFirstAssociate( package_list_key ) );
+	  catalogue = catalogue->FindFirstAssociate( package_list_key );
+	  if( (pkglist = catalogue) != NULL )
+	    do {
+		 /* ...updating the total catalogue reference count,
+		  * to include all extra catalogue files specified.
+		  */
+		 ++total;
+		 pkglist = pkglist->FindNextAssociate( package_list_key );
+	       } while( pkglist != NULL );
+
+	  /* Flush any message digest which has been accumulated
+	   * for the last catalogue processed...
+	   */
+	  dmh_control( DMH_END_DIGEST );
+	  if( owner->ProgressMeter() != NULL )
+	  {
+	    /* ...and update the progress meter display, if any,
+	     * to reflect current progress.
+	     */
+	    owner->ProgressMeter()->SetRange( 0, total );
+	    owner->ProgressMeter()->SetValue( count );
+	  }
+	  /* Proceed to process the embedded catalogues.
+	   */
+	  GetPackageList( catalogue );
 	}
       }
       else
@@ -135,6 +208,10 @@
       free( (void *)(dfile) );
     }
   }
+  /* Ensure that any accumulated diagnostics, pertaining to catalogue
+   * processing, have been displayed before wrapping up.
+   */
+  dmh_control( DMH_END_DIGEST );
 }
 
 void pkgRepository::GetPackageList( pkgXmlNode *catalogue )
@@ -182,6 +259,7 @@
     /* Sanity check passed...
      * Walk the XML data tree, selecting "repository" specifications...
      */
+    pkgRepository::Reset();
     pkgXmlNode *repository = dbase->FindFirstAssociate( repository_key );
     while( repository != NULL )
     {
@@ -190,18 +268,25 @@
       pkgRepository client( this, dbase, repository, force_update );
       pkgXmlNode *catalogue = repository->FindFirstAssociate( package_list_key );
       if( catalogue == NULL )
-	/*
-	 * This repository specification doesn't identify any named
+      {
+	/* This repository specification doesn't identify any named
 	 * package list, so try the default, (which is named to match
 	 * the XML key name for the "package-list" element)...
 	 */
+	pkgRepository::IncrementTotal();
 	client.GetPackageList( package_list_key );
-
+      }
       else
-	/* At least one package list catalogue is specified; load it,
+      { /* At least one package list catalogue is specified; load it,
 	 * and any others which are explicitly identified...
 	 */
+	pkgXmlNode *ref = catalogue;
+	do { pkgRepository::IncrementTotal();
+	     ref = ref->FindNextAssociate( package_list_key );
+	   } while( ref != NULL );
+
 	client.GetPackageList( catalogue );
+      }
 
       /* Similarly, a complete distribution may draw from an arbitrary set
        * of distinct repositories; move on, to process the next repository