List:Commits« Previous MessageNext Message »
From:Mike Lischke Date:March 21 2011 4:38pm
Subject:bzr commit into wex-installer-1.0 branch (mike.lischke:376)
View as plain text  
#At file:///D:/Work/MySQL/installer/ based on revid:iggy@stripped

  376 Mike Lischke	2011-03-21
      - ManifestUpdater: improved RE to search files.
      . Manfiest template: changed mysql documentation to match our current file name (this is temporary anyway).
      - Re-enabled OS architecture check.
      - FeatureBox: fixed display and handling for (partially) installed products (i.e. you cannot uncheck a product with installed features). Set and unset hidden features if at least one or no feature of a product is installed.
      - InstallProgress: fixed counting of remaining products, it is now also correct when re-entering the page.

    modified:
      ManifestUpdater/Program.cs
      Setup/manifest-base.xml
      WexInstaller.Core/Win32.cs
      WexInstaller/Controls/FeatureBox.cs
      WexInstaller/Controls/FeatureTreeView.cs
      WexInstaller/InstallWizard/InstallProgressPanel.cs
=== modified file 'ManifestUpdater/Program.cs'
=== modified file 'ManifestUpdater/Program.cs'
--- a/ManifestUpdater/Program.cs	2011-03-18 10:29:04 +0000
+++ b/ManifestUpdater/Program.cs	2011-03-21 16:38:32 +0000
@@ -69,10 +69,17 @@
     /// <returns>The found file with the latest version or null if none could be found.</returns>
     static string FindLatestVersion(string fileName)
     {
-      // Names adhere to the pattern mysql-([a-zA-Z\+]+-)*[0-9]\.[0-9]\.[0-9][0-9]-win(32|x64)\.msi
-      // e.g. mysql-5.5.9-win32.msi, or mysql-connector-odbc-5.1.8-winx64.msi.
+      // Package names consist of 4 parts:
+      // 1) starting with the literal mysql-
+      // 2) an optional sequence of words and a dash
+      // 3) a version number (separated by a dot) consisting of at least 2 numbers and at most 4 numbers, where
+      //    the 3. and 4. number (if they exist) can have any number of digits.
+      // 4) an ending consisting of an option part for the architecture and the msi extension.
+      // e.g. mysql-5.1.59-win32.msi, or mysql-connector-odbc-5.1.8-winx64.msi, or
+      //      mysql-universal-installer-document-bundle-1.0.0.0.msi
+      // 
       // Extract the architecture and extension part, which forms the end of our search pattern.
-      Regex filePattern = new Regex(@"(?<baseName>mysql-([a-zA-Z\+]+-)*\d\.\d\.)(\d)+(?<ending>-win(32|x64)\.msi)$");
+      Regex filePattern = new Regex(@"(?<baseName>mysql-([a-zA-Z\+]+-)*\d\.\d)(\.\d+)*[a-z]?(?<ending>(-win(32|x64))?\.msi)$");
       Match match = filePattern.Match(fileName);
       string newestFile = null;
       if (match.Success)
@@ -86,7 +93,8 @@
         foreach (string file in files)
         {
           Version v = new Version(GetProperty(file, "ProductVersion"));
-          if (v <= newestVersion) continue;
+          if (v <= newestVersion)
+            continue;
           newestVersion = v;
           newestFile = file;
         }
@@ -107,6 +115,9 @@
       package.FileName = Path.GetFileName(msiFile);
       package.ThisVersion = GetProperty(msiFile, "ProductVersion");
       package.Id = GetProperty(msiFile, "ProductCode");
+      if (String.IsNullOrEmpty(package.Id))
+        Console.WriteLine(String.Format("Warning: {0} doesn't have a product code",
+          package.FileName));
       package.Features.Clear();
       SetFeatures(msiFile, package);
     }

=== modified file 'Setup/manifest-base.xml'
--- a/Setup/manifest-base.xml	2011-03-18 10:29:04 +0000
+++ b/Setup/manifest-base.xml	2011-03-21 16:38:32 +0000
@@ -19,7 +19,7 @@
         <CatalogProduct productId="connector-c-win32" setupTypeFlags="5" />
         <CatalogProduct productId="connector-cpp-win32" setupTypeFlags="5" />
         <CatalogProduct productId="examples-5.5" setupTypeFlags="5"/>
-        <CatalogProduct productId="mysql-documentation-5.5" setupTypeFlags="5"/>
+        <CatalogProduct productId="mysql-universal-installer-document-bundle-1.0.0.0" setupTypeFlags="5"/>
       </CatalogProducts>
     </ProductCatalog>
     <ProductCatalog id="mysql-5.5-winx64-gpl" name="MySQL 5.5" description="MySQL 5.5 Community Edition" commercial="false">
@@ -37,7 +37,7 @@
         <CatalogProduct productId="connector-c-winx64" setupTypeFlags="5" />
         <CatalogProduct productId="connector-cpp-winx64" setupTypeFlags="5" />
         <CatalogProduct productId="examples-5.5" setupTypeFlags="5"/>
-        <CatalogProduct productId="mysql-documentation-5.5" setupTypeFlags="5"/>
+        <CatalogProduct productId="mysql-universal-installer-document-bundle-1.0.0.0" setupTypeFlags="5"/>
       </CatalogProducts>
     </ProductCatalog>
     <ProductCatalog id="mysql-5.1-win32-gpl" name="MySQL 5.1" description="MySQL 5.1 Community Edition" commercial="false">
@@ -55,7 +55,7 @@
         <CatalogProduct productId="connector-c-win32" setupTypeFlags="5" />
         <CatalogProduct productId="connector-cpp-win32" setupTypeFlags="5" />
         <CatalogProduct productId="examples-5.1" setupTypeFlags="5"/>
-        <CatalogProduct productId="mysql-documentation-5.1" setupTypeFlags="5"/>
+        <CatalogProduct productId="mysql-universal-installer-document-bundle-1.0.0.0" setupTypeFlags="5"/>
       </CatalogProducts>
     </ProductCatalog>
     <ProductCatalog id="mysql-5.1-winx64-gpl" name="MySQL 5.1" description="MySQL 5.1 Community Edition" commercial="false">
@@ -73,7 +73,7 @@
         <CatalogProduct productId="connector-c-winx64" setupTypeFlags="5" />
         <CatalogProduct productId="connector-cpp-winx64" setupTypeFlags="5" />
         <CatalogProduct productId="examples-5.1" setupTypeFlags="5"/>
-        <CatalogProduct productId="mysql-documentation-5.1" setupTypeFlags="5"/>
+        <CatalogProduct productId="mysql-universal-installer-document-bundle-1.0.0.0" setupTypeFlags="5"/>
       </CatalogProducts>
     </ProductCatalog>
   </ProductCatalogs>
@@ -150,25 +150,19 @@
       </Product>
     </ProductCategory>
     <ProductCategory name="Documentation" title="Documentation" description="">
-      <Product name="mysql-documentation-5.5" title="MySQL Documentation 5.5" description="A collection of popular MySQL Documents" upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
-        <Packages>
-          <Package type="MSI" arch="Any" filename="mysql-documentation-5.5.msi" id="" thisVersion="">
-          </Package>
-        </Packages>
-      </Product>
-      <Product name="mysql-documentation-5.1" title="MySQL Documentation 5.1" description="A collection of popular MySQL Documents" upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
-        <Packages>
-          <Package type="MSI" arch="Any" filename="mysql-documentation-5.1.msi" id="" thisVersion="">
-          </Package>
-        </Packages>
-      </Product>
-      <Product name="examples-5.5" title="Samples and Examples 5.5" description="A collection of examples and sample databases to help a developer get started." upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
+      <Product name="mysql-universal-installer-document-bundle-1.0.0.0" title="MySQL Documentation" description="A collection of popular MySQL Documents" upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
+        <Packages>
+          <Package type="MSI" arch="Any" filename="mysql-universal-installer-document-bundle-1.0.0.0.msi" id="" thisVersion="">
+          </Package>
+        </Packages>
+      </Product>
+      <Product name="examples-5.5" title="Samples and Examples" description="A collection of examples and sample databases to help a developer get started." upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
         <Packages>
           <Package type="MSI" arch="Any" filename="mysql-examples-5.5.0.msi" id="" thisVersion="">
           </Package>
         </Packages>
       </Product>
-      <Product name="examples-5.1" title="Samples and Examples 5.1" description="A collection of examples and sample databases to help a developer get started." upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
+      <Product name="examples-5.1" title="Samples and Examples" description="A collection of examples and sample databases to help a developer get started." upgradeId="" urlBaseDir="http://wb.mysql.com/installer">
         <Packages>
           <Package type="MSI" arch="Any" filename="mysql-examples-5.1.0.msi" id="" thisVersion="">
           </Package>

=== modified file 'WexInstaller.Core/Win32.cs'
--- a/WexInstaller.Core/Win32.cs	2011-03-18 19:10:58 +0000
+++ b/WexInstaller.Core/Win32.cs	2011-03-21 16:38:32 +0000
@@ -3098,7 +3098,6 @@
     /// </summary>
     public static bool Is64BitOS()
     {
-      /*
       ManagementObjectSearcher searcher =
         new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_OperatingSystem");
       foreach (ManagementObject wmi in searcher.Get())
@@ -3111,7 +3110,7 @@
 
         return "64-bit".Equals(architecture);
       }
-      */
+      
       return false;
     }
 

=== modified file 'WexInstaller/Controls/FeatureBox.cs'
--- a/WexInstaller/Controls/FeatureBox.cs	2011-03-21 10:02:47 +0000
+++ b/WexInstaller/Controls/FeatureBox.cs	2011-03-21 16:38:32 +0000
@@ -263,9 +263,9 @@
       }
       else
       {
-        ProductFeature pf = (e.Node.Tag as ProductFeature);
-        if (pf.ProposedInstalled)
-          state = CheckBoxState.CheckedNormal;
+        ProductFeature feature = (e.Node.Tag as ProductFeature);
+        state = feature.Installed ? CheckBoxState.CheckedDisabled :
+          feature.ProposedInstalled ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal;
       }
 
       if (CBGlyphSize.IsEmpty)
@@ -303,13 +303,16 @@
       }
       else
       {
-        ProductFeature pf = e.Node.Tag as ProductFeature;
-        pf.ProposedInstalled = !pf.ProposedInstalled;
+        ProductFeature feature = e.Node.Tag as ProductFeature;
+        if (feature.Installed)
+          return;
+
+        feature.ProposedInstalled = !feature.ProposedInstalled;
 
         // Check if at least one (visible) product feature for the owning product is proposed for installation.
         // If so set also all invisible features too. Otherwise remove invisible features from the 
         // installation list so that the entire product is set to no-installation.
-        ProductElement element = pf;
+        ProductElement element = feature;
         do
         {
           element = element.Parent;
@@ -321,9 +324,9 @@
           bool anyFeatureInstalled = false;
           foreach (TreeNode node in featureList.Nodes)
             anyFeatureInstalled |= (node.Tag as ProductFeature).ProposedInstalled;
-          foreach (ProductFeature feature in product.GetProductFeatures())
-            if (feature.Display == "0") // Invisible feature.
-              feature.ProposedInstalled = anyFeatureInstalled;
+          foreach (ProductFeature childFeature in product.GetProductFeatures())
+            if (childFeature.Display == "0") // Invisible feature.
+              childFeature.ProposedInstalled = anyFeatureInstalled;
         }
 
         featureList.Invalidate(); // There can be sub features that changed state too, so redraw everything.

=== modified file 'WexInstaller/Controls/FeatureTreeView.cs'
--- a/WexInstaller/Controls/FeatureTreeView.cs	2011-03-21 10:34:56 +0000
+++ b/WexInstaller/Controls/FeatureTreeView.cs	2011-03-21 16:38:32 +0000
@@ -82,7 +82,9 @@
     /// <summary>
     /// Switches to the next valid check state for the given node applying the state to the
     /// represented products and features on the way.
-    /// The next valid state for an unchecked or mixed node is checked, otherwise unchecked.
+    /// The next valid state for an unchecked or mixed node is checked, otherwise unchecked (for enabled states).
+    /// If the check state is disabled then it can only be checked (when mixed), though not changed
+    /// if already checked.
     /// </summary>
     private void SwitchStateForNode(TreeNode node)
     {
@@ -112,11 +114,11 @@
     ///  Switches between the check states that represent the installation proposal.
     ///  Keep in mind we have 3 states (no installation, partial installation, full installation).
     ///  If nothing or only a part is proposed for installation yet for that product set all to install.
-    ///  Otherwise set all to not-install.
+    ///  Otherwise set all to not-install, if not already installed.
     /// </summary>
     private void SwitchStateForProduct(Product p, bool forceInstall)
     {
-      List<ProductFeature> productFeatures = p.GetProductFeatures();
+      List<ProductFeature> productFeatures = p.GetAllProductFeatures();
       bool doInstall;
 
       // Installation is forced if the category to which this product belongs has a mixed
@@ -129,42 +131,74 @@
           doInstall = !p.ProposedInstalled;
         else
         {
-          CheckBoxState state = GetStateFromFeatureList(p.GetProductFeatures());
+          CheckBoxState state = GetEnabledEquivalent(GetStateFromFeatureList(productFeatures));
           doInstall = (state == CheckBoxState.UncheckedNormal) || (state == CheckBoxState.MixedNormal);
         }
       }
       if (!p.Installed)
         p.ProposedInstalled = doInstall;
 
-      foreach (ProductFeature pf in productFeatures)
-        pf.ProposedInstalled = doInstall;
+      foreach (ProductFeature feature in productFeatures)
+        if (!feature.Installed)
+          feature.ProposedInstalled = doInstall;
 
       OnProductInstallationProposalChanged(p);
     }
 
+    /// <summary>
+    /// Returns the enabled variant of the given state (if that is disabled).
+    /// </summary>
+    /// <param name="state"></param>
+    /// <returns></returns>
+    private CheckBoxState GetEnabledEquivalent(CheckBoxState state)
+    {
+      switch (state)
+      {
+        case CheckBoxState.CheckedDisabled:
+          return CheckBoxState.CheckedNormal;
+        case CheckBoxState.MixedDisabled:
+          return CheckBoxState.MixedNormal;
+        case CheckBoxState.UncheckedDisabled:
+          return CheckBoxState.UncheckedNormal;
+        default:
+          return state;
+      }
+    }
+
+    /// <summary>
+    /// Used to determine if a given state is one of the disabled states.
+    /// </summary>
+    private bool IsDisabled(CheckBoxState state)
+    {
+      return (state == CheckBoxState.CheckedDisabled || state == CheckBoxState.MixedDisabled ||
+        state == CheckBoxState.UncheckedDisabled);
+    }
+
+    /// <summary>
+    /// Determines and returns the checkbox state for a given node.
+    /// Both product and category nodes are handled here.
+    /// </summary>
     private CheckBoxState GetNodeCheckboxState(TreeNode node)
     {
-      CheckBoxState result = CheckBoxState.MixedHot; // A state we don't use in the UI.
+      CheckBoxState result = CheckBoxState.UncheckedDisabled;
 
       if (node.Tag is Product)
-      {
         result = GetStateForProduct(node.Tag as Product);
-        // If the product is already installed convert the state to its disabled equivalent.
-        if ((node.Tag as Product).Installed)
-          result = (CheckBoxState)((int)result + 3);
-      }
       else
       {
         List<ProductFeature> featureList = new List<ProductFeature>();
+        bool hasInstalledParts = false;
         foreach (TreeNode child in node.Nodes)
         {
           CheckBoxState childState = GetStateForProduct(child.Tag as Product);
-          if (result == CheckBoxState.MixedHot)
+          if (childState == CheckBoxState.CheckedDisabled || childState == CheckBoxState.MixedDisabled)
+            hasInstalledParts = true;
+          if (result == CheckBoxState.UncheckedDisabled)
             result = childState;
           else
-            if (result != childState)
+            if (GetEnabledEquivalent(result) != GetEnabledEquivalent(childState))
             {
-              result = CheckBoxState.MixedNormal;
+              result = hasInstalledParts ? CheckBoxState.MixedDisabled : CheckBoxState.MixedNormal;
               break;
             }
         }
@@ -181,7 +215,7 @@
         state = GetStateFromFeatureList(productFeatures);
       else
         if (p.ProposedInstalled || p.Installed)
-          state = CheckBoxState.CheckedNormal;
+          state = p.Installed ? CheckBoxState.CheckedDisabled : CheckBoxState.CheckedNormal;
         else
           state = CheckBoxState.UncheckedNormal;
 
@@ -190,19 +224,26 @@
 
     private CheckBoxState GetStateFromFeatureList(List<ProductFeature> featureList)
     {
-      bool allInstalled = true;
+      bool allToBeInstalled = true;
+      bool anyToBeInstalled = false;
       bool anyInstalled = false;
-      foreach (ProductFeature f in featureList)
+      foreach (ProductFeature feature in featureList)
       {
-        allInstalled &= f.ProposedInstalled;
-        anyInstalled |= f.ProposedInstalled;
+        allToBeInstalled &= feature.ProposedInstalled;
+        anyToBeInstalled |= feature.ProposedInstalled;
+        anyInstalled |= feature.Installed;
       }
-      if (allInstalled)
-        return CheckBoxState.CheckedNormal;
+      CheckBoxState result = CheckBoxState.UncheckedNormal;
+      if (allToBeInstalled)
+        result = CheckBoxState.CheckedNormal;
+      else
+        if (anyToBeInstalled)
+          result = CheckBoxState.MixedNormal;
+
+      // If any feature is already installed convert the state to its disabled equivalent.
       if (anyInstalled)
-        return CheckBoxState.MixedNormal;
-
-      return CheckBoxState.UncheckedNormal;
+        result = (CheckBoxState)((int)result + 3);
+      return result;
     }
 
     private int GetOffset(TreeNode node)

=== modified file 'WexInstaller/InstallWizard/InstallProgressPanel.cs'
--- a/WexInstaller/InstallWizard/InstallProgressPanel.cs	2011-03-21 12:59:48 +0000
+++ b/WexInstaller/InstallWizard/InstallProgressPanel.cs	2011-03-21 16:38:32 +0000
@@ -59,6 +59,7 @@
       if (!finished)
       {
         started = false;
+        nextOk = true;
         progressLevels.Clear();
         NextButton.Text = Properties.Resources.NextButtonExecuteText;
       }
@@ -67,6 +68,7 @@
       // installations we have on the way.
       productList.Items.Clear();
       leftToDownload = 0;
+      leftToInstall = 0;
       foreach (ProductCategory pc in ProductManager.ProductCategories)
       {
         foreach (Product p in pc.Products)
@@ -77,6 +79,9 @@
             if (!p.FoundLocal)
               leftToDownload++;
 
+            if (p.CurrentState != ProductState.InstallSuccess && p.CurrentState != ProductState.UpdateSuccess)
+              leftToInstall++;
+
             ListViewItem item = new ListViewItem(String.Empty);
             item.Name = p.Name;
             item.Tag = p;
@@ -93,9 +98,10 @@
           }
         }
       }
-      leftToInstall = productList.Items.Count;
 
-      nextOk = leftToInstall > 0;
+      finished = (leftToInstall == 0);
+      if (finished)
+        NextButton.Text = Properties.Resources.NextButtonDefaultText;
 
       base.Activate();
     }
@@ -299,6 +305,7 @@
         (p.CurrentState == ProductState.DownloadNoMirror))
       {
         downloadErrorCount++;
+        leftToInstall--;
         currentItem.SubItems[4].Text = e.Error.Message;
         currentItem.SubItems[3].Text = ListViewWex.LinkMarker + Resources.TryAgainLink + ListViewWex.LinkMarker;
       }
@@ -375,29 +382,16 @@
       foreach (ListViewItem item in productList.Items)
       {
         Product p = (Product)item.Tag;
-        if (p.CurrentState == ProductState.WebRemote ||
-          p.CurrentState == ProductState.DownloadStarted ||
-          p.CurrentState == ProductState.DownloadMirrorSelection ||
-          p.CurrentState == ProductState.DownloadInProgress ||
-          p.CurrentState == ProductState.InstallInProgress ||
-          p.CurrentState == ProductState.UpdateInProgress ||
-          p.CurrentState == ProductState.RemoveInProgress)
-        {
-          continue;
-        }
-        if (p.CurrentState != ProductState.DownloadSuccess &&
-          p.CurrentState != ProductState.FoundLocal &&
-          p.CurrentState != ProductState.WillPerformUpgrade &&
-          p.CurrentState != ProductState.CurrentlyInstalled)
-        {
-          leftToInstall--;
-          continue;
-        }
-        installingItem = item;
-        p.ProductMSIActionProgressChanged += new ProductMSIActionProgressHandler(ProductMSIActionProgressChanged);
-        p.ProductMSIActionCompleted += new ProductMSIActionCompleteHandler(ProductMSIActionCompleted);
-        p.MakeChanges();
-        break;
+        if ((p.CurrentState == ProductState.FoundLocal) ||
+          (p.CurrentState == ProductState.WillPerformUpgrade) ||
+          (p.CurrentState == ProductState.CurrentlyInstalled))
+        {
+          installingItem = item;
+          p.ProductMSIActionProgressChanged += new ProductMSIActionProgressHandler(ProductMSIActionProgressChanged);
+          p.ProductMSIActionCompleted += new ProductMSIActionCompleteHandler(ProductMSIActionCompleted);
+          p.MakeChanges();
+          break;
+        }
       }
     }
 
@@ -409,9 +403,8 @@
       if (installedProductsNeedConfig == false)
         (ParentControl as InstallWizardControl).RemoveConfigPages("Configuration");
       nextOk = true;
-      NextButton.Enabled = true;
-
       finished = true;
+      SignalChange();
     }
 
     private void ProductMSIActionProgressChanged(object sender, ProductMSIActionProgressEventArgs pe)


Attachment: [text/bzr-bundle] bzr/mike.lischke@oracle.com-20110321163832-tmecgh0rmce8sbac.bundle
Thread
bzr commit into wex-installer-1.0 branch (mike.lischke:376) Mike Lischke21 Mar