This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] setup: implement "perpetual" postinstall scripts


This is another patch against setup (on top of my earlier series,
although I think it'd also apply against the current CVS head).  The
objective is to provide postinstall scripts that are never marked
".done" and hence will run at each installation without having to
re-install the package that provided them.  I intend to use this for the
incremental autorebase, which is why these scripts has been arranged to
run before any other postinstall scripts (this ensures that the system
is already properly rebased when these are finally run).  I expect that
some other housekeeping tasks (like updating the info directory) could
benefit some a similar arrangement.

The patch implements these scripts by using an "_always" suffix before
the file extension.  It would actually be easier to implement and
require less changes if the perpetual scripts would be separated into
their own directory.  I'd implement this if consensus could be reached
where this directory should be located.  I'm not sure a subdirectory
under /etc/postinstall would work, but if it does this seems the most
straightforward.  If so, it would likely also make sense to have another
directory for such scripts to be run _after_ all normal postinstalls.

>From 155955b92498f95631d683c2bbc1d93d6b27ddda Mon Sep 17 00:00:00 2001
From: Achim Gratz
Date: Wed, 6 Feb 2013 12:37:17 +0100
Subject: [PATCH 5] implement perpetual scripts and run them before all other
 postinstall scripts

* postinstall.cc (RunFindVisitor): Exclude perpetual scripts (having suffix
  "_always" before the extension) from being returned.
* postinstall.cc (PerpetualFindVisitor): New helper class, returns perpetual
  scripts (having suffix "_always" before the extension).
* postinstall.cc (do_postinstall_thread): Search for perpetual scripts
  and run them before all other postinstall scripts.
* script.h (perpetual): New helper function, returns true if the
  script is a perpetual one.
* script.cc (perpetual): If the script name has suffix "_always"
  before the extension, then assume it is a perpetual one.
* setup/script.cc (run): Do not append suffix ".done" to perpetual
  scripts.
---
 setup/postinstall.cc | 58 +++++++++++++++++++++++++++++++++++++++++++++++-----
 setup/script.cc      | 10 +++++++--
 setup/script.h       |  1 +
 3 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/setup/postinstall.cc b/setup/postinstall.cc
index fe58b06..9beea86 100755
--- a/setup/postinstall.cc
+++ b/setup/postinstall.cc
@@ -54,8 +54,8 @@ public:
                          const WIN32_FIND_DATA *theFile)
     {
       std::string fileName(theFile->cFileName);
-      if (fileName.size() >= 5 &&
-          fileName.substr(fileName.size() - 5) == ".done")
+      if (  (fileName.size() >= 5 && (fileName.size() - 5) == fileName.find(".done"))
+	  || (std::string::npos != fileName.rfind("_always.")))
         return;
       std::string fn = std::string("/etc/postinstall/") + theFile->cFileName;
       _scripts->push_back(Script (fn));
@@ -68,6 +68,28 @@ private:
   vector<Script> *_scripts;
 };
 
+class PerpetualFindVisitor : public FindVisitor
+{
+public:
+  PerpetualFindVisitor (vector<Script> *scripts) : _scripts(scripts) {}
+  virtual void visitFile(const std::string& basePath,
+                         const WIN32_FIND_DATA *theFile)
+    {
+      std::string fileName(theFile->cFileName);
+      if (  (fileName.size() >= 5 && (fileName.size() - 5) == fileName.find(".done"))
+	  || !(std::string::npos != fileName.rfind("_always.")))
+        return;
+      std::string fn = std::string("/etc/postinstall/") + theFile->cFileName;
+      _scripts->push_back(Script (fn));
+    }
+  virtual ~ PerpetualFindVisitor () {}
+protected:
+  PerpetualFindVisitor (PerpetualFindVisitor const &);
+  PerpetualFindVisitor & operator= (PerpetualFindVisitor const &);
+private:
+  vector<Script> *_scripts;
+};
+
 // ---------------------------------------------------------------------------
 //
 // ---------------------------------------------------------------------------
@@ -147,6 +169,18 @@ do_postinstall_thread (HINSTANCE h, HWND owner)
 
   std::string s = "";
 
+  // Look for any scripts in /etc/postinstall which should always be run
+  std::string postinst = cygpath ("/etc/postinstall");
+  vector<Script> perpetual;
+  PerpetualFindVisitor myPerpetualVisitor (&perpetual);
+  Find (postinst).accept (myPerpetualVisitor);
+
+  // and try to run what we've found
+  {
+    RunScript scriptRunner("Perpetual", perpetual);
+    scriptRunner.run_all(s);
+  }
+
   // For each package we installed, we noted anything installed into /etc/postinstall.
   // run those scripts now
   int numpkg = packages.size() + 1;
@@ -155,7 +189,21 @@ do_postinstall_thread (HINSTANCE h, HWND owner)
     {
       packagemeta & pkg = **i;
 
-      RunScript scriptRunner(pkg.name, pkg.installed.scripts());
+      vector<Script> installed = pkg.installed.scripts();
+      // Remove any perpetual scripts that have just been installed
+      // (we've already run them)
+      for (std::vector<Script>::const_iterator j = perpetual.begin();
+	   j != perpetual.end();
+	   j++)
+	{
+	  std::vector<Script>::iterator p = find(installed.begin(), installed.end(), *j);
+	  if (p != installed.end())
+	    {
+	      installed.erase(p);
+	    }
+	}
+
+      RunScript scriptRunner(pkg.name, installed);
       scriptRunner.run_all(s);
 
       ++k;
@@ -163,7 +211,7 @@ do_postinstall_thread (HINSTANCE h, HWND owner)
     }
 
   // Look for any scripts in /etc/postinstall which haven't been renamed .done
-  std::string postinst = cygpath ("/etc/postinstall");
+  // (perpetual scripts are not renamed .done, but will not be returned either)
   vector<Script> scripts;
   RunFindVisitor myVisitor (&scripts);
   Find (postinst).accept (myVisitor);
@@ -179,7 +227,7 @@ do_postinstall_thread (HINSTANCE h, HWND owner)
            std::vector<Script>::iterator p = find(scripts.begin(), scripts.end(), *j);
            if (p != scripts.end())
              {
-               scripts.erase(p);
+	       scripts.erase(p);
              }
          }
     }
diff --git a/setup/script.cc b/setup/script.cc
index 6663e8c..6741af4 100755
--- a/setup/script.cc
+++ b/setup/script.cc
@@ -247,6 +247,11 @@ Script::extension() const
 {
   return strrchr (scriptName.c_str(), '.');
 }
+bool
+Script::perpetual() const
+{
+  return (!strncasecmp ("_always.", strrchr (scriptName.c_str(), '_') , 8));
+}
 
 int
 Script::run() const
@@ -292,8 +297,9 @@ Script::run() const
   /* if .done file exists then delete it otherwise just ignore no file error */
   io_stream::remove ("cygfile://" + scriptName + ".done");
 
-  /* don't rename the script as .done if it didn't run successfully */
-  if (!retval)
+  /* don't rename the script as .done if it didn't run successfully or
+     if this script is marked to be always run */
+  if (!retval && !perpetual())
     io_stream::move ("cygfile://" + scriptName,
                      "cygfile://" + scriptName + ".done");
 
diff --git a/setup/script.h b/setup/script.h
index 144fd71..cb69692 100755
--- a/setup/script.h
+++ b/setup/script.h
@@ -40,6 +40,7 @@ private:
   std::string scriptName;
   static char const ETCPostinstall[];
   char const * extension() const;
+  bool perpetual() const;
 };
 
 #endif /* SETUP_SCRIPT_H */
-- 
1.8.1.2



Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

Factory and User Sound Singles for Waldorf rackAttack:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]