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]

[RFC] incremental rebase


As discussed on the main list, here's the incremental autorebase package
as well as the patched setup.exe to implement perpetual postinstall
scripts.

$cygwin=http://cygwin.stromeko.net/
wget $cygwin/noarch/release/_incautorebase/_incautorebase-00006-1.tar.bz2
wget $cygwin/x86/setup-x86.exe
wget $cygwin/x86_64/setup-x86_64.exe

As briefly mentioned, the implementation was done to minimize the
changes to both the infrastructure and the size of the patch to setup.
This could be implemented differently, for instance based on the
directory the script is in, rather than its name.  Also, in the same way
one could look at the name of the script and have certain scripts run
before or after the others, or use hidden groups (like _PostInstallLast
and have it actually do what that name suggests).

Another obvious extension would be triggers, i.e. the installation of
one (or multiple) packages will result in the execution of the triggered
postinstall script.  This is useful if the same postinstall action can
be used by many packages (texlive would benefit enormously from that).
This would require changes to the packaging, upset, setup or all of
them, of course.

I suggest to start with this and take it from there.

The patch to setup is this:

Subject: [PATCH 1/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.
---
 postinstall.cc | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 script.cc      | 11 +++++++++--
 script.h       |  1 +
 3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/postinstall.cc b/postinstall.cc
index 6f6502d..cca741a 100644
--- a/postinstall.cc
+++ b/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;
+};
+
 // ---------------------------------------------------------------------------
 //
 // ---------------------------------------------------------------------------
@@ -146,6 +168,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;
@@ -154,7 +188,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;
@@ -162,7 +210,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);
diff --git a/script.cc b/script.cc
index cb1b6b0..8214618 100644
--- a/script.cc
+++ b/script.cc
@@ -255,6 +255,12 @@ Script::extension() const
 {
   return strrchr (scriptName.c_str(), '.');
 }
+bool
+Script::perpetual() const
+{
+  char *suffix = strrchr (scriptName.c_str(), '_');
+  return (!strncasecmp ("_always.", (suffix ? suffix : ""), 8));
+}
 
 int
 Script::run() const
@@ -297,8 +303,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/script.h b/script.h
index abdd43e..2d3aaf8 100644
--- a/script.h
+++ b/script.h
@@ -43,6 +43,7 @@ private:
   std::string scriptName;
   static char const ETCPostinstall[];
   char const * extension() const;
+  bool perpetual() const;
 };
 
 #endif /* SETUP_SCRIPT_H */
-- 
2.1.3


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

Wavetables for the Terratec KOMPLEXER:
http://Synth.Stromeko.net/Downloads.html#KomplexerWaves

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