From a0d18a5d17229928e6db1d451b36f9300be020e6 Mon Sep 17 00:00:00 2001
From: Seblu <sebastien.luttringer@smartjog.com>
Date: Fri, 24 Jun 2011 15:00:29 +0200
Subject: [PATCH] Improve script execution

Script is now compiled before execution to have a better debugging features.
local directory is no more given for each scripts
global directory is new to each script execution
only namespace object must be used to share data across scripts
---
 bin/isinstall              | 17 ++++++-----------
 installsystems/image.py    | 33 ++++++++++++++++++++++-----------
 installsystems/template.py | 22 +++++++++++++++++++---
 installsystems/tools.py    |  6 +-----
 4 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/bin/isinstall b/bin/isinstall
index b1878a7..84a74e0 100755
--- a/bin/isinstall
+++ b/bin/isinstall
@@ -52,10 +52,9 @@ try:
     # load config
     config = ConfigFile("isinstall", args.config)
     # looks if arguments is a file or image name
-    image_name_type = istools.pathtype(args.image_name)
-    if image_name_type == "file":
+    if istools.pathtype(args.image_name) == "file" and os.path.isfile(args.image_name):
         pkg = PackageImage(istools.abspath(args.image_name))
-    elif image_name_type == "name":
+    elif PackageImage.check_image_name(args.image_name):
         # remove cache is asked
         if args.no_cache:
             config.cache = None
@@ -74,17 +73,13 @@ try:
         exit(1)
     # install start time
     t0 = time.time()
-    # global dict of execution context
-    gl_exec = { "parser": p_main }
-    # run parser scripts
-    pkg.run_parser(gl_exec)
+    # run parser scripts with parser parser argument
+    pkg.run_parser(parser=p_main)
     # call parser again, with extended attributes
-    arrow("Run parser", 1, args.verbose)
+    arrow("Parsing arguments", 1, args.verbose)
     args = p_main.parse_args()
-    # add parser result to global dict
-    gl_exec["args"] = args
     # run setup scripts
-    pkg.run_setup(gl_exec)
+    pkg.run_setup(namespace = args)
     # compute building time
     t1 = time.time()
     dt = int(t1 - t0)
diff --git a/installsystems/image.py b/installsystems/image.py
index 5ddcb2d..fdead34 100644
--- a/installsystems/image.py
+++ b/installsystems/image.py
@@ -375,21 +375,19 @@ class PackageImage(Image):
             arrow(pay_name, 2, self.verbose)
             pay_obj.check()
 
-    def run_parser(self, gl):
+    def run_parser(self, **kwargs):
         '''
         Run parser scripts
         '''
-        gl["image"] = self
-        self._run_scripts(gl, "parser")
+        self._run_scripts("parser", **kwargs)
 
-    def run_setup(self, gl):
+    def run_setup(self, **kwargs):
         '''
         Run setup scripts
         '''
-        gl["image"] = self
-        self._run_scripts(gl, "setup")
+        self._run_scripts("setup", **kwargs)
 
-    def _run_scripts(self, gl, directory):
+    def _run_scripts(self, directory, **kwargs):
         '''
         Run scripts in a tarball directory
         '''
@@ -401,16 +399,29 @@ class PackageImage(Image):
         # run scripts
         for n_scripts in l_scripts:
             arrow(os.path.basename(n_scripts), 2, self.verbose)
+            # extract source code
             try:
                 s_scripts = self._tarball.get_str(n_scripts)
             except Exception as e:
                 raise Exception("Extracting script %s fail: %s" %
-                                (os.path.basename(n_scripts), e))
+                                (n_scripts, e))
+            # compile source code
             try:
-                exec(s_scripts, gl, dict())
+                o_scripts = compile(s_scripts, n_scripts, "exec")
+            except Exception as e:
+                raise Exception("Unable to compile %s fail: %s" %
+                                (n_scripts, e))
+            # define execution context
+            gl = {}
+            for k in kwargs:
+                gl[k] = kwargs[k]
+            gl["image"] = self
+            # execute source code
+            try:
+                exec o_scripts in gl
             except Exception as e:
                 raise Exception("Execution script %s fail: %s" %
-                                (os.path.basename(n_scripts), e))
+                                (n_scripts, e))
 
 
 class Payload(object):
@@ -438,7 +449,7 @@ class Payload(object):
         raise AttributeError
 
     def __setattr__(self, name, value):
-        # set all value which exists have no underscore, but undesrcore exists
+        # set all value which exists have no underscore, but where undesrcore exists
         if name in self.legit_attr:
             object.__setattr__(self, "_%s" % name, value)
         else:
diff --git a/installsystems/template.py b/installsystems/template.py
index af960e5..f24bd7e 100644
--- a/installsystems/template.py
+++ b/installsystems/template.py
@@ -12,8 +12,20 @@ author =
 parser = """# -*- python -*-
 # -*- coding: utf-8 -*-
 
+# image object is a reference to current image
+# parser object is installsystems argument parser
+
+import os
+import installsystems.argparse as argparse
+
+class TargetAction(argparse.Action):
+  def __call__(self, parser, namespace, values, option_string=None):
+    if not os.path.isdir(values):
+      raise Exception("Invalid target directory %s" % values)
+    namespace.target = values
+
 parser.add_argument("-n", "--hostname", dest="hostname", type=str, required=True)
-parser.add_argument("target", type=str,
+parser.add_argument("target", type=str, action=TargetAction,
   help="target installation directory")
 
 # vim:set ts=2 sw=2 noet:
@@ -22,9 +34,13 @@ parser.add_argument("target", type=str,
 setup = """# -*- python -*-
 # -*- coding: utf-8 -*-
 
-print "hostname: %s" % args.hostname
+# image object is a reference to current image
+# namespace object is the persistant, it can be used to store data accross scripts
+
+print "hostname: %s" % namespace.hostname
 
-image.payload["rootfs"].extract(args.target)
+# uncomment to extract payload named root in namespace.target directory
+#image.payload["rootfs"].extract(namespace.target)
 
 # vim:set ts=2 sw=2 noet:
 """
diff --git a/installsystems/tools.py b/installsystems/tools.py
index d45d042..1f3e9f8 100644
--- a/installsystems/tools.py
+++ b/installsystems/tools.py
@@ -81,18 +81,14 @@ def chrights(path, uid=None, gid=None, mode=None, mtime=None):
 
 def pathtype(path):
     '''Return path type. This is usefull to know what kind of path is given'''
-    from installsystems.image import Image
     if path.startswith("http://") or path.startswith("https://"):
         return "http"
     if path.startswith("ftp://") or path.startswith("ftps://"):
         return "ftp"
     elif path.startswith("ssh://"):
         return "ssh"
-    elif path.startswith("file://") or path.startswith("/") or os.path.exists(path):
+    else:
         return "file"
-    elif Image.check_image_name(path):
-        return "name"
-    return None
 
 def abspath(path):
     '''Format a path to be absolute'''
-- 
GitLab