changeset 55:3a0242e260ab

Ability to add a repository plug-in. IN: -
author John Schneiderman
date Tue, 10 Mar 2015 19:24:23 +0100
parents 5ef160e59286
children 8b9816c1b322
files doc/ChangeLog doc/TODO src/hwm.py src/manager.py src/manrepo.py
diffstat 5 files changed, 134 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/doc/ChangeLog	Mon Mar 09 21:24:51 2015 +0100
+++ b/doc/ChangeLog	Tue Mar 10 19:24:23 2015 +0100
@@ -18,6 +18,7 @@
 ***  along with this program. If not, see <http://www.gnu.org/licenses/>.    ***
 ********************************************************************************
 2015-00-00 John Schneiderman <Licensing _AT_ CodeGNU _DOT_ com> 0.4.0
+- Ability to add a plug-in to 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/doc/TODO	Mon Mar 09 21:24:51 2015 +0100
+++ b/doc/TODO	Tue Mar 10 19:24:23 2015 +0100
@@ -27,7 +27,7 @@
 ***                                                                          ***
 ***                              Feature Goals                               ***
 ***                                                                          ***
-- Allow plug-ins addition and removal from repositories.
+- Allow plug-ins removal from repositories.
 - Installation tutorial.
 - User tutorials.
 - Manager functions should take both an output and error device instead of defaulting to std.
--- a/src/hwm.py	Mon Mar 09 21:24:51 2015 +0100
+++ b/src/hwm.py	Tue Mar 10 19:24:23 2015 +0100
@@ -97,7 +97,11 @@
 		parser = argparse.ArgumentParser(description=_app_info.DESCRIPTION)
 		parser.add_argument('-l', '--list', action='store_true', help='Outputs a list of all the managed repositories.')
 
-		manGrp = parser.add_argument_group('Manage', 'Options that operate upon 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=1, 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.')
+
+		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.')
@@ -113,6 +117,8 @@
 
 		if args.list:
 			manager.list()
+		elif args.enable_plugin is not None:
+			manager.plugInEnable(repo, args.enable_plugin[0], args.plugin_file)
 		elif args.action is None:
 			print >>sys.stderr, "No actionable arguments supplied."
 			exit(1)
@@ -129,7 +135,7 @@
 			exit(1)
 		exit(0)
 	except (ValueError, RuntimeError) as error:
-		print >>sys.stderr, "Issue Discovered: %s" % error
+		print >>sys.stderr, "Execution Failed: %s" % error
 		exit(2)
 	except Exception as error:
 		import traceback
--- a/src/manager.py	Mon Mar 09 21:24:51 2015 +0100
+++ b/src/manager.py	Tue Mar 10 19:24:23 2015 +0100
@@ -26,6 +26,33 @@
 settings = config.Manager()
 
 
+def plugInEnable(repository, plugInName, scriptFile):
+	""" Enables a plug-in to a managed repository.
+
+	@pre The repository must already exist.
+
+	@param[in] repository		The targeted repository to add a plug-in to.
+	@param[in] plugInName		The name of the plug-in to add.
+	@param[in] scriptFile		The file path location of the plug-in script.
+
+	@post The managed repository has it's configuration file enabling the
+	supplied plug-in.
+
+	@throws ValueError		When the repository storage name does not exist.
+	"""
+	from manrepo import RepositoryPlugin
+
+	with RepositoryManagerLock():
+		print "\tEnable plug-in %s for %s" % (plugInName, repository.StorageName)
+		if not __doesRepositoryStorageNameExist(repository):
+			raise ValueError("The repository '%s' does not exist." % repository.StorageName)
+
+		print 'Creating plug-in information ...'
+		plugIn = RepositoryPlugin(plugInName, scriptFile)
+		repository.addPlugIn(plugIn)
+		__writeRepositoryDetails(repository)
+
+
 def create(repository, ignoreGroups, skipCommon):
 	""" Creates a new repository under HgWeb.
 
@@ -450,7 +477,7 @@
 	import stat
 	import sys
 
-	print "Saving display details ..."
+	print "Saving repository configuration details ..."
 	config = settings.RepositoryPath + os.sep + repo.StorageName + os.sep + '.hg' + os.sep + 'hgrc'
 
 	if os.path.exists(config):
--- a/src/manrepo.py	Mon Mar 09 21:24:51 2015 +0100
+++ b/src/manrepo.py	Tue Mar 10 19:24:23 2015 +0100
@@ -37,6 +37,8 @@
 	__contact = None
 	# The Mercurial repository interface.
 	__repo = None
+	# The collection of plug-ins enabled for a repository.
+	__plugIns = []
 
 	@property
 	def StorageName(self):
@@ -73,6 +75,11 @@
 		""" Sets the contact point for the managed repository. """
 		self.__contact = value
 
+	@property
+	def PlugIns(self):
+		""" Gets the collection of enabled plug-ins for the managed repository. """
+		return self.__plugIns
+
 	def __init__(self, repoName=None):
 		""" Initialises the object with the values from a managed repository
 
@@ -89,6 +96,9 @@
 				self.__displayName = self.__repo.ui.config('web', 'name', default=None)
 				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')
+				for plugIn in plugInList:
+					self.__plugIns.append(RepositoryPlugin(plugIn[0], plugIn[1]))
 			except error.RepoError:
 				pass
 
@@ -113,27 +123,90 @@
 		import os
 
 		with open(settings.RepositoryPath + os.sep + self.__storageName + os.sep + '.hg' + os.sep + 'hgrc', 'w') as hgrc:
-			hgrc.write('[web]\n')
+			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')
 
-			if self.__displayName is None:
-				hgrc.write('name = ' + self.__storageName + '\n')
+			hgrc.write('\n[web]\n')
+			if self.DisplayName is None:
+				hgrc.write('name = ' + self.StorageName + '\n')
 			else:
-				hgrc.write('name = ' + self.__displayName + '\n')
+				hgrc.write('name = ' + self.DisplayName + '\n')
+
+			if self.Description is not None:
+				hgrc.write('description = ' + self.Description + '\n')
+
+			if self.Contact is not None:
+				hgrc.write('contact = ' + self.Contact + '\n')
+		# Needed for when repositories are re-named.
+		self = Repository(self.StorageName)
 
-			if self.__description is not None:
-				hgrc.write('description = ' + self.__description + '\n')
+	def __str__(self):
+		""" Converts the object contents into a human-friendly string. """
+		repo = "%s\n\tDisplay: %s\n\tDescription: %s\n\tContact: %s" % (self.StorageName, self.DisplayName, self.Description, self.Contact)
+		if len(self.PlugIns) > 0:
+			repo = repo + "\n\tPlug-ins:"
+			for plugIn in self.PlugIns:
+				repo = repo + "\n\t\t%s" % plugIn
+		return repo
+
+	def addPlugIn(self, plugIn):
+		""" Adds a plug-in to enable in a repository.
+
+		@param[in] plugIn	The plug-in that is to be enabled.
+
+		@post The object now has the supplied plug-in as being enabled.
 
-			if self.__contact is not None:
-				hgrc.write('contact = ' + self.__contact + '\n')
+		@throws ValueError		When the supplied plug-in is already enabled.
+		"""
+		if plugIn not in self.PlugIns:
+			self.__plugIns.append(plugIn)
+		else:
+			raise ValueError("The plug-in '%s' is already enabled." % plugIn.name)
+
+
+class RepositoryPlugin(object):
+	__name = None
+	__scriptFile = None
+
+	@property
+	def name(self):
+		return self.__name
+
+	@property
+	def scriptFile(self):
+		return self.__scriptFile
+
+	def __init__(self, name, scriptFile=None):
+		import os
 
-		if self.__repo is None:
-			from mercurial import ui, hg
-			import os
+		self.__name = name
+		if (scriptFile is not None and len(scriptFile) > 0):
+			if os.path.exists(scriptFile):
+				self.__scriptFile = scriptFile
+			else:
+				raise ValueError("The plug-in file '%s' was not found." % scriptFile)
+
+	def __eq__(self, other):
+		""" Determines if two repository plug-ins are the same.
 
-			self.__repo = hg.repository(ui.ui(), settings.RepositoryPath + os.sep + self.__storageName)
-		self.__displayName = self.__repo.ui.config('web', 'name', default=None)
-		self.__description = self.__repo.ui.config('web', 'description', default=None)
-		self.__contact = self.__repo.ui.config('web', 'contact', default=None)
+		@param[in] other	The plug-in on the right-hand-side of the
+							equality operator to compare against.
+
+		@return Gives true when both plug-ins represent the same one,
+		else-wise gives false.
+		"""
+		return self.name == other.name
+
+	def __str__(self):
+		""" Converts the object contents into a human-friendly string. """
+		if self.scriptFile is None:
+			return self.name
+		else:
+			return "%s -> %s" % (self.name, self.scriptFile)
 
 
 class ManagedCollection(object):
@@ -164,3 +237,11 @@
 
 		for name, path in parser.items('paths'):
 			self.__repositories.append(Repository(name))
+
+	def __str__(self):
+		""" Converts the object contents into a human-friendly string. """
+		collection = ""
+		for repository in self.Repositories:
+			collection = collection + str(repository) + '\n'
+		collection.rstrip('\n')
+		return collection