Procházet zdrojové kódy

HUE-2. app_reg does not install conf/*.ini

Install symlink from desktop/conf to app's *.ini.
Also changed the make target 'install-bdist' to not worry about
conf files, since app_reg is taking care of them.
bc Wong před 15 roky
rodič
revize
b0d2c68614
4 změnil soubory, kde provedl 83 přidání a 28 odebrání
  1. 5 15
      Makefile.sdk
  2. 5 4
      tools/app_reg/app_reg.py
  3. 4 1
      tools/app_reg/common.py
  4. 69 8
      tools/app_reg/registry.py

+ 5 - 15
Makefile.sdk

@@ -232,20 +232,10 @@ bdist: ext-eggs compile
 .PHONY: install-bdist
 install-bdist: bdist
 	@echo "--- Install built distribution for $(APP_NAME) at $(INSTALL_DIR)"
+	@# Check that INSTALL_DIR is empty
+	@if [ -n '$(wildcard $(INSTALL_DIR)/*)' ] ; then \
+	  echo 'ERROR: $(INSTALL_DIR) not empty. Cowardly refusing to continue.' ; \
+	  false ; \
+	fi
 	@mkdir -p $(INSTALL_DIR)
 	@rsync -a $(BDIST_DIR)/ $(INSTALL_DIR)
-ifneq ($(wildcard conf),) # if there are conf files
-	@echo "--- Installing $(APP_NAME) configuration into $(INSTALL_CONF_DIR)"
-	@mkdir -p $(INSTALL_CONF_DIR)
-	for conffile in $(INSTALL_DIR)/conf/* ; do \
-	  filename=$$(basename $$conffile) ; \
-	  if [ -f $(INSTALL_CONF_DIR)/$$filename ]; then \
-	    echo "Moving aside old config $(INSTALL_CONF_DIR)/$$filename" ; \
-	    mv $(INSTALL_CONF_DIR)/$$filename{,.save.$(shell date +"%Y%m%d.%H%M%S")} ; \
-	  fi ; \
-	  mv $$conffile $(INSTALL_CONF_DIR)/$$filename ; \
-	done
-	@# Remove the conf dir from the install location since we've placed the confs in the
-	@# right spot
-	@rmdir $(INSTALL_DIR)/conf
-endif

+ 5 - 4
tools/app_reg/app_reg.py

@@ -17,7 +17,7 @@
 
 """
 A tool to manage Hue applications. This does not stop/restart a
-running Desktop instance.
+running Hue instance.
 
 Usage:
     %(PROG_NAME)s [flags] --install <path_to_app> [<path_to_app> ...]
@@ -30,7 +30,7 @@ Usage:
         To list all registered applications.
 
     %(PROG_NAME)s [flags] --sync
-        Synchronize all registered applications with the Desktop environment.
+        Synchronize all registered applications with the Hue environment.
         Useful after a `make clean'.
 
 Optional flags:
@@ -111,11 +111,11 @@ def _do_install_one(reg, app_loc):
     LOG.error(ex)
     return False
 
-  app = registry.DesktopApp(app_name, version, app_loc, desc, author)
+  app = registry.HueApp(app_name, version, app_loc, desc, author)
   if reg.contains(app):
     LOG.warn("=== %s is already installed" % (app,))
     return True
-  return reg.register(app) and build.make_app(app)
+  return reg.register(app) and build.make_app(app) and app.install_conf()
 
 
 def do_install(app_loc_list):
@@ -148,6 +148,7 @@ def do_remove(app_name):
   reg = registry.AppRegistry()
   try:
     app = reg.unregister(app_name)
+    app.uninstall_conf()
   except KeyError:
     LOG.error("%s is not installed" % (app_name,))
     return False

+ 4 - 1
tools/app_reg/common.py

@@ -17,9 +17,12 @@
 
 import os.path
 
-# The root of the Desktop installation
+# The root of the Hue installation
 INSTALL_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..'))
 
+# The Hue config directory
+HUE_CONF_DIR = os.path.join(INSTALL_ROOT, 'desktop', 'conf')
+
 # Virtual env
 VIRTUAL_ENV = os.path.join(INSTALL_ROOT, 'build', 'env')
 

+ 69 - 8
tools/app_reg/registry.py

@@ -19,6 +19,7 @@
 Registry for the applications
 """
 
+import errno
 import glob
 import logging
 import os
@@ -36,7 +37,7 @@ class AppRegistry(object):
     """Open the existing registry"""
     self._reg_path = os.path.join(common.INSTALL_ROOT, 'app.reg')
     self._initialized = False
-    self._apps = { }    # Map of name -> DesktopApp
+    self._apps = { }    # Map of name -> HueApp
     self._open()
 
 
@@ -49,7 +50,7 @@ class AppRegistry(object):
 
       for app_json in app_list:
         app_json.setdefault('author', 'Unknown')        # Added after 0.9
-        app = DesktopApp.create(app_json)
+        app = HueApp.create(app_json)
         self._apps[app.name] = app
 
     self._initialized = True
@@ -94,7 +95,7 @@ class AppRegistry(object):
 
 
   def unregister(self, app_name):
-    """unregister(app_Name) -> DesktopApp. May raise KeyError"""
+    """unregister(app_Name) -> HueApp. May raise KeyError"""
     assert self._initialized, "Registry not yet initialized"
 
     app = self._apps[app_name]
@@ -103,7 +104,7 @@ class AppRegistry(object):
 
 
   def get_all_apps(self):
-    """get_all_apps() -> List of DesktopApp"""
+    """get_all_apps() -> List of HueApp"""
     return self._apps.values()
 
 
@@ -117,13 +118,13 @@ class AppRegistry(object):
     LOG.info('=== Saved registry at %s' % (self._reg_path,))
 
 
-class DesktopApp(object):
+class HueApp(object):
   """
   Represents an app.
   """
   @staticmethod
   def create(json):
-    return DesktopApp(json['name'], json['version'], json['path'], json['desc'], json['author'])
+    return HueApp(json['name'], json['version'], json['path'], json['desc'], json['author'])
 
   def __init__(self, name, version, path, desc, author):
     self.name = name
@@ -136,7 +137,7 @@ class DesktopApp(object):
     return "%s (version %s)" % (self.name, self.version)
 
   def __cmp__(self, other):
-    if not isinstance(other, DesktopApp):
+    if not isinstance(other, HueApp):
       raise TypeError
     return cmp((self.name, self.version), (other.name, other.version))
 
@@ -148,12 +149,72 @@ class DesktopApp(object):
     """find_ext_pys() -> A list of paths for all ext-py packages"""
     return glob.glob(os.path.join(self.path, 'ext-py', '*'))
 
+  def get_conffiles(self):
+    """get_conffiles() -> A list of config (.ini) files"""
+    ini_files = glob.glob(os.path.join(self.path, 'conf', '*.ini'))
+    return [ os.path.abspath(ini) for ini in ini_files ]
+
+
+  def install_conf(self):
+    """
+    install_conf() -> True/False
+
+    Symlink the app's conf/*.ini files into the conf directory.
+    """
+    installed = [ ]
+
+    for target in self.get_conffiles():
+      link_name = os.path.join(common.HUE_CONF_DIR, os.path.basename(target))
+      try:
+        os.symlink(target, link_name)
+        LOG.info('Symlink config %s -> %s' % (link_name, target))
+        installed.append(link_name)
+      except OSError, ex:
+        # Does the link already exists?
+        if ex.errno == errno.EEXIST and os.path.islink(link_name):
+          try:
+            cur = os.readlink(link_name)
+            if cur == target:
+              LOG.warn("Symlink for configuration already exists: %s" % (link_name,))
+              continue
+          except:
+            pass
+        # Nope. True error. Cleanup.
+        LOG.error("Failed to symlink %s to %s: %s" % (target, link_name, ex))
+        for lnk in installed:
+          try:
+            os.unlink(lnk)
+          except:
+            LOG.error("Failed to cleanup link %s" % (link_name,))
+        return False
+    return True
+
+
+  def uninstall_conf(self):
+    """uninstall_conf() -> True/False"""
+    app_conf_dir = os.path.join(self.path, 'conf')
+
+    # Check all symlink in the conf dir and remove any that point to this app
+    for name in os.listdir(common.HUE_CONF_DIR):
+      path = os.path.join(common.HUE_CONF_DIR, name)
+      if not os.path.islink(path):
+        continue
+      target = os.readlink(path)
+      if os.path.samefile(os.path.dirname(target), app_conf_dir):
+        try:
+          os.unlink(path)
+          LOG.info('Remove config symlink %s -> %s' % (path, target))
+        except OSError, ex:
+          LOG.error("Failed to remove configuration link %s: %s" % (path, ex))
+          return False
+    return True
+
 
 class AppJsonEncoder(simplejson.JSONEncoder):
   def __init__(self, **kwargs):
     simplejson.JSONEncoder.__init__(self, **kwargs)
 
   def default(self, obj):
-    if isinstance(obj, DesktopApp):
+    if isinstance(obj, HueApp):
       return obj.jsonable()
     return simplejson.JSONEncoder.default(self, obj)