Here's a small patch for setup.exe which causes setup to indicate if a postinstall script didn't run successfully.

This should help avoid the situation where the postinstall scripts fail to run and the user has a broken installation, but they don't notice until they try to run something which relies on postinstall scripts, e.g [1] and I'm sure there are other examples.

[1] http://cygwin.com/ml/cygwin-xfree/2010-07/msg00084.html

ChangeLog:

        * postinstall.cc : Note if any postinstall script fails and tell
        the user with an error messagebox
        * script.cc (run): Don't rename script as .done if it didn't run
        successfully
Index: postinstall.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/postinstall.cc,v
retrieving revision 2.23
diff -u -p -r2.23 postinstall.cc
--- postinstall.cc      11 May 2009 10:49:15 -0000      2.23
+++ postinstall.cc      23 Jul 2010 17:34:30 -0000
@@ -64,7 +64,7 @@ private:
 class RunScript : public unary_function<Script const &, int>
 {
 public:
-  RunScript(const std::string& name, int num) : _num(num), _cnt(0)
+  RunScript(const std::string& name, int num) : _num(num), _cnt(0), 
_no_errors(TRUE)
     {
       Progress.SetText2 (name.c_str());
       Progress.SetBar1 (_cnt, _num);
@@ -80,16 +80,26 @@ public:
       retval = aScript.run();
       ++_cnt;
       Progress.SetBar1 (_cnt, _num);
+
+      if ((retval != 0) && (retval != -ERROR_INVALID_DATA))
+        _no_errors = FALSE;
+
       return retval;
     }
+  bool success(void)
+  {
+    return _no_errors;
+  }
 private:
   int _num;
   int _cnt;
+  bool _no_errors;
 };
 
-static void
+static bool
 do_postinstall_thread (HINSTANCE h, HWND owner)
 {
+  bool success = TRUE;
   Progress.SetText1 ("Running...");
   Progress.SetText2 ("");
   Progress.SetText3 ("");
@@ -114,8 +124,8 @@ do_postinstall_thread (HINSTANCE h, HWND
     {
       packagemeta & pkg = **i;
 
-      for_each (pkg.installed.scripts().begin(), pkg.installed.scripts().end(),
-               RunScript(pkg.name, pkg.installed.scripts().size()));
+      success &= for_each (pkg.installed.scripts().begin(), 
pkg.installed.scripts().end(),
+                           RunScript(pkg.name, 
pkg.installed.scripts().size())).success();
 
       ++k;
       Progress.SetBar2 (k, numpkg);
@@ -125,9 +135,10 @@ do_postinstall_thread (HINSTANCE h, HWND
   RunFindVisitor myVisitor (&scripts);
   Progress.SetBar1 (0, 1);
   Find (postinst).accept (myVisitor);
-  for_each (scripts.begin(), scripts.end(),
-           RunScript("No package", scripts.size()));
+  success &= for_each (scripts.begin(), scripts.end(),
+                       RunScript("No package", scripts.size())).success();
   Progress.SetBar2 (numpkg, numpkg);
+  return success;
 }
 
 static DWORD WINAPI
@@ -138,7 +149,17 @@ do_postinstall_reflector (void *p)
 
   try
   {
-    do_postinstall_thread ((HINSTANCE) context[0], (HWND) context[1]);
+    if (!do_postinstall_thread ((HINSTANCE) context[0], (HWND) context[1]))
+      {
+        // one or more postinstall scripts failed to run successfully
+        // installation may be broken
+        MessageBox (NULL,
+                    "You will need to investigate and correct these errors "
+                    "before your Cygwin installation will function properly.\n"
+                    "Check setup.log for details.",
+                    "ERROR - postinstall scripts failed",
+                    MB_OK | MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
+      }
 
     // Tell the progress page that we're done running scripts
     Progress.PostMessage (WM_APP_POSTINSTALL_THREAD_COMPLETE);
Index: script.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/script.cc,v
retrieving revision 2.35
diff -u -p -r2.35 script.cc
--- script.cc   26 Jun 2009 12:08:54 -0000      2.35
+++ script.cc   23 Jul 2010 17:34:30 -0000
@@ -285,11 +285,13 @@ Script::run() const
   if (retval)
     log(LOG_PLAIN) << "abnormal exit: exit code=" << retval << endLog;
 
-  /* if file exists then delete it otherwise just ignore no file error */
+  /* if .done file exists then delete it otherwise just ignore no file error */
   io_stream::remove ("cygfile://" + scriptName + ".done");
 
-  io_stream::move ("cygfile://" + scriptName,
-                   "cygfile://" + scriptName + ".done");
+  /* don't rename the script as .done if it didn't run successfully */
+  if (!retval)
+    io_stream::move ("cygfile://" + scriptName,
+                     "cygfile://" + scriptName + ".done");
 
   return retval;
 }

Reply via email to