# HG changeset patch # User John Schneiderman # Date 1426011863 -3600 # Node ID 3a0242e260ab39264ef299d446054936cf30bd27 # Parent 5ef160e59286fbbf3b7bac421ac3c5c4326d960c Ability to add a repository plug-in. IN: - diff -r 5ef160e59286 -r 3a0242e260ab doc/ChangeLog --- 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 . *** ******************************************************************************** 2015-00-00 John Schneiderman 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 0.3.0 diff -r 5ef160e59286 -r 3a0242e260ab doc/TODO --- 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. diff -r 5ef160e59286 -r 3a0242e260ab src/hwm.py --- 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 diff -r 5ef160e59286 -r 3a0242e260ab src/manager.py --- 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): diff -r 5ef160e59286 -r 3a0242e260ab src/manrepo.py --- 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