changeset 58:4f4599ea035b

Ability to manage all basic aspects of plug-in configuration in a repository. IN: -
author John Schneiderman
date Wed, 11 Mar 2015 21:37:53 +0100
parents d9170c4ce812
children 813025a65bf1
files doc/ChangeLog src/hwm.py src/manager.py src/manrepo.py
diffstat 4 files changed, 185 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/doc/ChangeLog	Wed Mar 11 20:40:37 2015 +0100
+++ b/doc/ChangeLog	Wed Mar 11 21:37:53 2015 +0100
@@ -20,6 +20,7 @@
 2015-00-00 John Schneiderman <Licensing _AT_ CodeGNU _DOT_ com> 0.4.0
 - Ability to add a plug-in to a managed repository.
 - Ability to remove a plug-in from a managed repository.
+- Ability to manage a plug-in's setting for a managed repository.
 - No longer dependant upon third-party general file locker for repositories.
 - Manager functions use exceptions for error handling.
 2014-08-21 John Schneiderman <Licensing _AT_ CodeGNU _DOT_ com> 0.3.0
--- a/src/hwm.py	Wed Mar 11 20:40:37 2015 +0100
+++ b/src/hwm.py	Wed Mar 11 21:37:53 2015 +0100
@@ -97,16 +97,18 @@
 		parser = argparse.ArgumentParser(description=_app_info.DESCRIPTION)
 		parser.add_argument('-l', '--list', action='store_true', help='Outputs a list of all the managed repositories.')
 
-		plgInGrp = parser.add_argument_group('Manage Plug-Ins', 'Options that operate upon managed repository\'s plug-ins.')
-		plgInGrp.add_argument('-e', '--enable-plugin', action='store', nargs='?', type=str, default=None, help='Enable a plug-in in a repository.')
-		plgInGrp.add_argument('-f', '--plugin-file', action='store', nargs='?', type=str, default=None, help='The path to the plug-in script.')
-		plgInGrp.add_argument('-x', '--disable-plugin', action='store', nargs='?', type=str, default=None, help='Disable a plug-in in a repository.')
+		plgInGrp = parser.add_argument_group('Manage Plug-Ins', 'Options that operate upon a managed repository\'s plug-ins.')
+		plgInGrp.add_argument('-p', '--plugin', action='store', nargs=1, type=str, default=None, help='The name of a plug-in for a repository.')
+		plgInGrp.add_argument('-e', '--enable', action='store_true', help='Enable a plug-in in a repository.')
+		plgInGrp.add_argument('-f', '--script-path', action='store', nargs='?', type=str, default=None, help='The path to the plug-in script.')
+		plgInGrp.add_argument('-x', '--disable', action='store_true', help='Disable a plug-in in a repository.')
+		plgInGrp.add_argument('-s', '--setting', action='store', nargs=2, type=str, default=None, help='Sets a setting name/value pair for a plug-in.')
 
 		manGrp = parser.add_argument_group('Manage Repositories', 'Options that operate upon managed repositories.')
 		manGrp.add_argument('storage', action='store', nargs='?', help='The storage-name of the repository to perform an action upon.')
 		manGrp.add_argument('-a', '--action', action='store', nargs=1, type=str, choices=['c', 'create', 'm', 'modify', 'd', 'delete', 'r', 'register'], help='Performs an action upon a managed repository.')
 		manGrp.add_argument('-i', '--ignore', action='store', nargs='+', default=None, help='The groups to place in an ignore file.')
-		manGrp.add_argument('-s', '--skip-common', action='store_true', help='The common ignore group is not added by default.')
+		manGrp.add_argument('-k', '--skip-common', action='store_true', help='The common ignore group is not added by default.')
 		manGrp.add_argument('-n', '--name', action='store', nargs='?', default=None, help='The display name of the repository.')
 		manGrp.add_argument('-d', '--description', action='store', nargs='?', default=None, help='The description of the repository.')
 		manGrp.add_argument('-c', '--contact', action='store', nargs='?', default=None, help='The contact point of a repository.')
@@ -118,12 +120,21 @@
 
 		if args.list:
 			manager.list()
-		elif args.enable_plugin is not None:
-			manager.plugInEnable(repo, args.enable_plugin, args.plugin_file)
-		elif args.disable_plugin is not None:
-			manager.plugInDisable(repo, args.disable_plugin)
+		elif args.plugin is not None:
+			if args.enable:
+				manager.plugInEnable(repo, args.plugin[0], args.script_path)
+			elif args.disable:
+				manager.plugInDisable(repo, args.plugin[0])
+			elif args.setting is not None:
+				if len(args.setting[1]) > 0:
+					manager.setPlugInSetting(repo, args.plugin[0], args.setting[0], args.setting[1])
+				else:
+					manager.setPlugInSetting(repo, args.plugin[0], args.setting[0], None)
+			else:
+				print >>sys.stderr, "Failure determine requested plug-in '%s' option." % args.plugin[0]
+				exit(1)
 		elif args.action is None:
-			print >>sys.stderr, "No actionable arguments supplied."
+			print >>sys.stderr, "No repository operation argument supplied."
 			exit(1)
 		elif ('create' == args.action[0]) or ('c' == args.action[0]):
 			manager.create(repo, args.ignore, args.skip_common)
@@ -134,7 +145,7 @@
 		elif ('register' == args.action[0]) or ('r' == args.action[0]):
 			manager.register(repo)
 		else:
-			print >>sys.stderr, "Failure determine requested action '%s'." % args.action[0]
+			print >>sys.stderr, "Unknown repository action supplied '%s'." % args.action[0]
 			exit(1)
 		exit(0)
 	except (ValueError, RuntimeError) as error:
--- a/src/manager.py	Wed Mar 11 20:40:37 2015 +0100
+++ b/src/manager.py	Wed Mar 11 21:37:53 2015 +0100
@@ -76,6 +76,17 @@
 		__writeRepositoryDetails(repository)
 
 
+def setPlugInSetting(repository, plugIn, named, value):
+	with RepositoryManagerLock():
+		print "\t Setting repository %s's '%s' plug-in setting '%s' to %s" % (repository.StorageName, plugIn, named, value)
+		if not __doesRepositoryStorageNameExist(repository):
+			raise ValueError("The repository '%s' does not exist." % repository.StorageName)
+
+		print 'Modifying plug-in setting ...'
+		repository.setSetting(plugIn, named, value)
+		__writeRepositoryDetails(repository)
+
+
 def create(repository, ignoreGroups, skipCommon):
 	""" Creates a new repository under HgWeb.
 
--- a/src/manrepo.py	Wed Mar 11 20:40:37 2015 +0100
+++ b/src/manrepo.py	Wed Mar 11 21:37:53 2015 +0100
@@ -38,7 +38,7 @@
 	# The Mercurial repository interface.
 	__repo = None
 	# The collection of plug-ins enabled for a repository.
-	__plugIns = []
+	__plugIns = None
 
 	@property
 	def StorageName(self):
@@ -97,8 +97,9 @@
 				self.__description = self.__repo.ui.config('web', 'description', default=None)
 				self.__contact = self.__repo.ui.config('web', 'contact', default=None)
 				plugInList = self.__repo.ui.configitems('extensions')
+				self.__plugIns = []
 				for plugIn in plugInList:
-					self.__plugIns.append(RepositoryPlugin(plugIn[0], plugIn[1]))
+					self.__plugIns.append(RepositoryPlugin(plugIn[0], plugIn[1], self.__repo.ui.configitems(plugIn[0])))
 			except error.RepoError:
 				pass
 
@@ -123,14 +124,9 @@
 		import os
 
 		with open(settings.RepositoryPath + os.sep + self.__storageName + os.sep + '.hg' + os.sep + 'hgrc', 'w') as hgrc:
-			hgrc.write('[extensions]\n')
-			for plugIn in self.PlugIns:
-				if plugIn.scriptFile is None:
-					hgrc.write(plugIn.name + ' =\n')
-				else:
-					hgrc.write(plugIn.name + ' = ' + plugIn.scriptFile + '\n')
+			#{ Repository Information Section
 
-			hgrc.write('\n[web]\n')
+			hgrc.write('[web]\n')
 			if self.DisplayName is None:
 				hgrc.write('name = ' + self.StorageName + '\n')
 			else:
@@ -141,8 +137,32 @@
 
 			if self.Contact is not None:
 				hgrc.write('contact = ' + self.Contact + '\n')
-		# Needed for when repositories are re-named.
-		self = Repository(self.StorageName)
+
+			#} Repository Information Section
+
+			#{ Plug-in Section
+
+			if len(self.PlugIns) > 0:
+				hgrc.write('\n[extensions]\n')
+				for plugIn in self.PlugIns:
+					if plugIn.scriptFile is None:
+						hgrc.write(plugIn.name + ' =\n')
+					else:
+						hgrc.write(plugIn.name + ' = ' + plugIn.scriptFile + '\n')
+
+			#} Plug-in Section
+
+			#{ Plug-in Settings Section
+
+			for plugIn in self.PlugIns:
+				if len(plugIn.settings) > 0:
+					hgrc.write("\n[%s]" % plugIn.name)
+					for setting in plugIn.settings:
+						hgrc.write("\n%s = %s" % (setting.name, setting.value))
+
+			#} Plug-in Settings Section
+
+		self = Repository(self.StorageName)  # Needed for when repositories are re-named.
 
 	def __str__(self):
 		""" Converts the object contents into a human-friendly string. """
@@ -182,20 +202,107 @@
 				return
 		raise ValueError("The plug-in '%s' is already disabled." % named)
 
+	def setSetting(self, plugInName, name, value):
+		""" Set's the setting of a plug-in
+		@details When the supplied value is None, the setting is removed.
+
+		@param[in] plugInName		The name of the plug-in whose setting is
+									being set.
+		@param[in] name				The name of the setting being set.
+		@param[in] value			The value for the setting.
+
+		@post The setting for the plug-in is modified to the supplied value.
+
+		@throws ValueError	When the supplied plug-in name is not enabled.
+		"""
+		for plugIn in self.PlugIns:
+			if plugInName == plugIn.name:
+				plugInIndex = self.PlugIns.index(plugIn)
+				self.__plugIns[plugInIndex].setPlugInSetting(name, value)
+				return
+		raise ValueError("The plug-in '%s' is not enabled." % plugInName)
+
 
 class RepositoryPlugin(object):
+	""" Manages a plug-in for a repository. """
+	class PluginSetting(object):
+		""" Manages a plug-in setting found inside a repository. """
+
+		# The name of the plug-in setting.
+		__name = None
+		# The setting value for the of the plug-in option.
+		__value = None
+
+		@property
+		def name(self):
+			""" Accessor to the option name for a plug-in. """
+			return self.__name
+
+		@property
+		def value(self):
+			""" Accessor to the option value for a plug-in option. """
+			return self.__value
+
+		@value.setter
+		def value(self, value):
+			""" Mutator to the option value for a plug-in option. """
+			self.__value = value
+
+		def __init__(self, name, value=None):
+			""" Initialises a plug-in setting.
+
+			@param[in] name		The name of the plug-in setting option.
+			@param[in] name		The value for the plug-in setting option.
+
+			@post The object is ready for use.
+			"""
+			self.__name = name
+			self.__value = value
+
+		def __str__(self):
+			""" Constructs a string representation of the object and it's values.
+
+			@return The representation in the form name => value
+			"""
+			return "%s => %s" % (self.name, self.value)
+	# The name of a repository plug-in.
 	__name = None
+	# The path and file-name of the script for the repository plug-in.
 	__scriptFile = None
+	# The supplied option settings for the repository plug-in.
+	__settings = None
 
 	@property
 	def name(self):
+		""" The accessor to the name of a repository plug-in. """
 		return self.__name
 
 	@property
 	def scriptFile(self):
+		""" The accessor to the path and file-name of the script for the
+		repository plug-in.
+		"""
 		return self.__scriptFile
 
-	def __init__(self, name, scriptFile=None):
+	@property
+	def settings(self):
+		""" The accessor to the supplied option settings for the repository
+		plug-in.
+		"""
+		return self.__settings
+
+	def __init__(self, name, scriptFile=None, plugInSettings=[]):
+		""" Initialises a plug-in.
+		@details The supplied plug-in setting must be a key-value pair
+		co-responding to the plug-in option name and it's value respectively.
+
+		@param[in] name				The name of the plug-in.
+		@param[in] scriptFile		The path and file name of the script which
+									runs the plug-in.
+		@param[in] plugInSettings	A list of settings for the plug-in.
+
+		@post The object is ready for use.
+		"""
 		import os
 
 		self.__name = name
@@ -205,6 +312,10 @@
 			else:
 				raise ValueError("The plug-in file '%s' was not found." % scriptFile)
 
+		self.__settings = []
+		for plugInSetting in plugInSettings:
+			self.__settings.append(RepositoryPlugin.PluginSetting(plugInSetting[0], plugInSetting[1]))
+
 	def __eq__(self, other):
 		""" Determines if two repository plug-ins are the same.
 
@@ -218,10 +329,36 @@
 
 	def __str__(self):
 		""" Converts the object contents into a human-friendly string. """
+		plugIn = ""
 		if self.scriptFile is None:
-			return self.name
+			plugIn = plugIn + self.name
 		else:
-			return "%s -> %s" % (self.name, self.scriptFile)
+			plugIn = plugIn + "%s -> %s" % (self.name, self.scriptFile)
+		for setting in self.settings:
+			plugIn = plugIn + "\n\t%s" % setting
+		return plugIn
+
+	def setPlugInSetting(self, name, value):
+		""" Set's the plug-in setting.
+		@details When the plug-in setting already exists the supplied value
+		overwrites the existing one. When the setting does not exist, a new
+		entry is created. When the supplied value is None, the setting is
+		removed from the plug-in.
+
+		@param[in] name				The name of the setting being set.
+		@param[in] value			The value for the setting.
+
+		@post The setting for the plug-in is modified to the supplied value.
+		"""
+		for setting in self.settings:
+			if name == setting.name:
+				if value is None:
+					self.__settings.remove(setting)
+				else:
+					settingIndex = self.settings.index(setting)
+					self.__settings[settingIndex].value = value
+				return
+		self.__settings.append(RepositoryPlugin.PluginSetting(name, value))
 
 
 class ManagedCollection(object):