registry.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/env python
  2. # Licensed to Cloudera, Inc. under one
  3. # or more contributor license agreements. See the NOTICE file
  4. # distributed with this work for additional information
  5. # regarding copyright ownership. Cloudera, Inc. licenses this file
  6. # to you under the Apache License, Version 2.0 (the
  7. # "License"); you may not use this file except in compliance
  8. # with the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. """
  18. Registry for the applications
  19. """
  20. import glob
  21. import logging
  22. import os
  23. import simplejson
  24. import common
  25. LOG = logging.getLogger(__name__)
  26. class AppRegistry(object):
  27. """
  28. Represents a registry.
  29. """
  30. def __init__(self):
  31. """Open the existing registry"""
  32. self._reg_path = os.path.join(common.INSTALL_ROOT, 'app.reg')
  33. self._initialized = False
  34. self._apps = { } # Map of name -> DesktopApp
  35. self._open()
  36. def _open(self):
  37. """Open the registry file. May raise OSError"""
  38. if os.path.exists(self._reg_path):
  39. reg_file = file(self._reg_path)
  40. app_list = simplejson.load(reg_file)
  41. reg_file.close()
  42. for app_json in app_list:
  43. app_json.setdefault('author', 'Unknown') # Added after 0.9
  44. app = DesktopApp.create(app_json)
  45. self._apps[app.name] = app
  46. self._initialized = True
  47. def _write(self, path):
  48. """Write out the registry to the given path"""
  49. outfile = file(path, 'w')
  50. simplejson.dump(self._apps.values(), outfile, cls=AppJsonEncoder, indent=2)
  51. outfile.close()
  52. def contains(self, app):
  53. """Returns whether the app (of the same version) is in the registry"""
  54. try:
  55. existing = self._apps[app.name]
  56. return existing.version == app.version
  57. except KeyError:
  58. return False
  59. def register(self, app):
  60. """register(app) -> True/False"""
  61. assert self._initialized, "Registry not yet initialized"
  62. try:
  63. existing = self._apps[app.name]
  64. version_diff = common.cmp_version(existing.version, app.version)
  65. if version_diff == 0:
  66. LOG.warn('%s is already registered' % (app,))
  67. return False
  68. elif version_diff < 0:
  69. LOG.info('Upgrading %s from version %s' % (app, existing.version))
  70. elif version_diff > 0:
  71. LOG.error('A newer version of %s is already installed' % (app,))
  72. return False
  73. except KeyError:
  74. pass
  75. LOG.info('Updating registry with %s' % (app,))
  76. self._apps[app.name] = app
  77. return True
  78. def unregister(self, app_name):
  79. """unregister(app_Name) -> DesktopApp. May raise KeyError"""
  80. assert self._initialized, "Registry not yet initialized"
  81. app = self._apps[app_name]
  82. del self._apps[app_name]
  83. return app
  84. def get_all_apps(self):
  85. """get_all_apps() -> List of DesktopApp"""
  86. return self._apps.values()
  87. def save(self):
  88. """Save and write out the registry"""
  89. assert self._initialized, "Registry not yet initialized"
  90. tmp_path = self._reg_path + '.new'
  91. self._write(tmp_path)
  92. os.rename(tmp_path, self._reg_path)
  93. LOG.info('=== Saved registry at %s' % (self._reg_path,))
  94. class DesktopApp(object):
  95. """
  96. Represents an app.
  97. """
  98. @staticmethod
  99. def create(json):
  100. return DesktopApp(json['name'], json['version'], json['path'], json['desc'], json['author'])
  101. def __init__(self, name, version, path, desc, author):
  102. self.name = name
  103. self.version = version
  104. self.path = path
  105. self.desc = desc
  106. self.author = author
  107. def __str__(self):
  108. return "%s (version %s)" % (self.name, self.version)
  109. def __cmp__(self, other):
  110. if not isinstance(other, DesktopApp):
  111. raise TypeError
  112. return cmp((self.name, self.version), (other.name, other.version))
  113. def jsonable(self):
  114. return dict(name=self.name, version=self.version, path=self.path,
  115. desc=self.desc, author=self.author)
  116. def find_ext_pys(self):
  117. """find_ext_pys() -> A list of paths for all ext-py packages"""
  118. return glob.glob(os.path.join(self.path, 'ext-py', '*'))
  119. class AppJsonEncoder(simplejson.JSONEncoder):
  120. def __init__(self, **kwargs):
  121. simplejson.JSONEncoder.__init__(self, **kwargs)
  122. def default(self, obj):
  123. if isinstance(obj, DesktopApp):
  124. return obj.jsonable()
  125. return simplejson.JSONEncoder.default(self, obj)