Mercurial > p > roundup > code
comparison roundup/admin.py @ 1098:c5819344714c
more doc
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Tue, 10 Sep 2002 07:07:16 +0000 |
| parents | fa7df238e2d4 |
| children | db787cef1385 |
comparison
equal
deleted
inserted
replaced
| 1097:98f3d41f41d9 | 1098:c5819344714c |
|---|---|
| 14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" | 15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" |
| 16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
| 17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 18 # | 18 # |
| 19 # $Id: admin.py,v 1.26 2002-09-10 03:01:18 richard Exp $ | 19 # $Id: admin.py,v 1.27 2002-09-10 07:07:16 richard Exp $ |
| 20 | 20 |
| 21 import sys, os, getpass, getopt, re, UserDict, shlex, shutil | 21 import sys, os, getpass, getopt, re, UserDict, shlex, shutil |
| 22 try: | 22 try: |
| 23 import csv | 23 import csv |
| 24 except ImportError: | 24 except ImportError: |
| 59 self.commands[k[3:]] = getattr(self, k) | 59 self.commands[k[3:]] = getattr(self, k) |
| 60 self.help = {} | 60 self.help = {} |
| 61 for k in AdminTool.__dict__.keys(): | 61 for k in AdminTool.__dict__.keys(): |
| 62 if k[:5] == 'help_': | 62 if k[:5] == 'help_': |
| 63 self.help[k[5:]] = getattr(self, k) | 63 self.help[k[5:]] = getattr(self, k) |
| 64 self.instance_home = '' | 64 self.tracker_home = '' |
| 65 self.db = None | 65 self.db = None |
| 66 | 66 |
| 67 def get_class(self, classname): | 67 def get_class(self, classname): |
| 68 '''Get the class - raise an exception if it doesn't exist. | 68 '''Get the class - raise an exception if it doesn't exist. |
| 69 ''' | 69 ''' |
| 85 return props | 85 return props |
| 86 | 86 |
| 87 def usage(self, message=''): | 87 def usage(self, message=''): |
| 88 if message: | 88 if message: |
| 89 message = _('Problem: %(message)s)\n\n')%locals() | 89 message = _('Problem: %(message)s)\n\n')%locals() |
| 90 print _('''%(message)sUsage: roundup-admin [-i instance home] [-u login] [-c] <command> <arguments> | 90 print _('''%(message)sUsage: roundup-admin [options] <command> <arguments> |
| 91 | |
| 92 Options: | |
| 93 -i instance home -- specify the issue tracker "home directory" to administer | |
| 94 -u -- the user[:password] to use for commands | |
| 95 -c -- when outputting lists of data, just comma-separate them | |
| 91 | 96 |
| 92 Help: | 97 Help: |
| 93 roundup-admin -h | 98 roundup-admin -h |
| 94 roundup-admin help -- this help | 99 roundup-admin help -- this help |
| 95 roundup-admin help <command> -- command-specific help | 100 roundup-admin help <command> -- command-specific help |
| 96 roundup-admin help all -- all available help | 101 roundup-admin help all -- all available help |
| 97 Options: | 102 ''')%locals() |
| 98 -i instance home -- specify the issue tracker "home directory" to administer | |
| 99 -u -- the user[:password] to use for commands | |
| 100 -c -- when outputting lists of data, just comma-separate them''')%locals() | |
| 101 self.help_commands() | 103 self.help_commands() |
| 102 | 104 |
| 103 def help_commands(self): | 105 def help_commands(self): |
| 104 print _('Commands:'), | 106 print _('Commands:'), |
| 105 commands = [''] | 107 commands = [''] |
| 134 print line | 136 print line |
| 135 print _('</pre></td></tr>\n') | 137 print _('</pre></td></tr>\n') |
| 136 | 138 |
| 137 def help_all(self): | 139 def help_all(self): |
| 138 print _(''' | 140 print _(''' |
| 139 All commands (except help) require an instance specifier. This is just the path | 141 All commands (except help) require a tracker specifier. This is just the path |
| 140 to the roundup instance you're working with. A roundup instance is where | 142 to the roundup tracker you're working with. A roundup tracker is where |
| 141 roundup keeps the database and configuration file that defines an issue | 143 roundup keeps the database and configuration file that defines an issue |
| 142 tracker. It may be thought of as the issue tracker's "home directory". It may | 144 tracker. It may be thought of as the issue tracker's "home directory". It may |
| 143 be specified in the environment variable TRACKER_HOME or on the command | 145 be specified in the environment variable TRACKER_HOME or on the command |
| 144 line as "-i instance". | 146 line as "-i tracker". |
| 145 | 147 |
| 146 A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... | 148 A designator is a classname and a nodeid concatenated, eg. bug1, user10, ... |
| 147 | 149 |
| 148 Property values are represented as strings in command arguments and in the | 150 Property values are represented as strings in command arguments and in the |
| 149 printed results: | 151 printed results: |
| 247 print _('Templates:'), ', '.join(templates) | 249 print _('Templates:'), ', '.join(templates) |
| 248 import roundup.backends | 250 import roundup.backends |
| 249 backends = roundup.backends.__all__ | 251 backends = roundup.backends.__all__ |
| 250 print _('Back ends:'), ', '.join(backends) | 252 print _('Back ends:'), ', '.join(backends) |
| 251 | 253 |
| 252 def do_install(self, instance_home, args): | 254 def do_install(self, tracker_home, args): |
| 253 '''Usage: install [template [backend [admin password]]] | 255 '''Usage: install [template [backend [admin password]]] |
| 254 Install a new Roundup instance. | 256 Install a new Roundup tracker. |
| 255 | 257 |
| 256 The command will prompt for the instance home directory (if not supplied | 258 The command will prompt for the tracker home directory (if not supplied |
| 257 through TRACKER_HOME or the -i option). The template, backend and admin | 259 through TRACKER_HOME or the -i option). The template, backend and admin |
| 258 password may be specified on the command-line as arguments, in that | 260 password may be specified on the command-line as arguments, in that |
| 259 order. | 261 order. |
| 260 | 262 |
| 261 The initialise command must be called after this command in order | 263 The initialise command must be called after this command in order |
| 262 to initialise the instance's database. You may edit the instance's | 264 to initialise the tracker's database. You may edit the tracker's |
| 263 initial database contents before running that command by editing | 265 initial database contents before running that command by editing |
| 264 the instance's dbinit.py module init() function. | 266 the tracker's dbinit.py module init() function. |
| 265 | 267 |
| 266 See also initopts help. | 268 See also initopts help. |
| 267 ''' | 269 ''' |
| 268 if len(args) < 1: | 270 if len(args) < 1: |
| 269 raise UsageError, _('Not enough arguments supplied') | 271 raise UsageError, _('Not enough arguments supplied') |
| 270 | 272 |
| 271 # make sure the instance home can be created | 273 # make sure the tracker home can be created |
| 272 parent = os.path.split(instance_home)[0] | 274 parent = os.path.split(tracker_home)[0] |
| 273 if not os.path.exists(parent): | 275 if not os.path.exists(parent): |
| 274 raise UsageError, _('Instance home parent directory "%(parent)s"' | 276 raise UsageError, _('Instance home parent directory "%(parent)s"' |
| 275 ' does not exist')%locals() | 277 ' does not exist')%locals() |
| 276 | 278 |
| 277 # select template | 279 # select template |
| 295 backend = raw_input(_('Select backend [anydbm]: ')).strip() | 297 backend = raw_input(_('Select backend [anydbm]: ')).strip() |
| 296 if not backend: | 298 if not backend: |
| 297 backend = 'anydbm' | 299 backend = 'anydbm' |
| 298 | 300 |
| 299 # install! | 301 # install! |
| 300 init.install(instance_home, template, backend) | 302 init.install(tracker_home, template, backend) |
| 301 | 303 |
| 302 print _(''' | 304 print _(''' |
| 303 You should now edit the instance configuration file: | 305 You should now edit the tracker configuration file: |
| 304 %(config_file)s | 306 %(config_file)s |
| 305 ... at a minimum, you must set MAILHOST, MAIL_DOMAIN and ADMIN_EMAIL. | 307 ... at a minimum, you must set MAILHOST, MAIL_DOMAIN and ADMIN_EMAIL. |
| 306 | 308 |
| 307 If you wish to modify the default schema, you should also edit the database | 309 If you wish to modify the default schema, you should also edit the database |
| 308 initialisation file: | 310 initialisation file: |
| 309 %(database_config_file)s | 311 %(database_config_file)s |
| 310 ... see the documentation on customizing for more information. | 312 ... see the documentation on customizing for more information. |
| 311 ''')%{ | 313 ''')%{ |
| 312 'config_file': os.path.join(instance_home, 'config.py'), | 314 'config_file': os.path.join(tracker_home, 'config.py'), |
| 313 'database_config_file': os.path.join(instance_home, 'dbinit.py') | 315 'database_config_file': os.path.join(tracker_home, 'dbinit.py') |
| 314 } | 316 } |
| 315 return 0 | 317 return 0 |
| 316 | 318 |
| 317 | 319 |
| 318 def do_initialise(self, instance_home, args): | 320 def do_initialise(self, tracker_home, args): |
| 319 '''Usage: initialise [adminpw] | 321 '''Usage: initialise [adminpw] |
| 320 Initialise a new Roundup instance. | 322 Initialise a new Roundup tracker. |
| 321 | 323 |
| 322 The administrator details will be set at this step. | 324 The administrator details will be set at this step. |
| 323 | 325 |
| 324 Execute the instance's initialisation function dbinit.init() | 326 Execute the tracker's initialisation function dbinit.init() |
| 325 ''' | 327 ''' |
| 326 # password | 328 # password |
| 327 if len(args) > 1: | 329 if len(args) > 1: |
| 328 adminpw = args[1] | 330 adminpw = args[1] |
| 329 else: | 331 else: |
| 331 confirm = 'x' | 333 confirm = 'x' |
| 332 while adminpw != confirm: | 334 while adminpw != confirm: |
| 333 adminpw = getpass.getpass(_('Admin Password: ')) | 335 adminpw = getpass.getpass(_('Admin Password: ')) |
| 334 confirm = getpass.getpass(_(' Confirm: ')) | 336 confirm = getpass.getpass(_(' Confirm: ')) |
| 335 | 337 |
| 336 # make sure the instance home is installed | 338 # make sure the tracker home is installed |
| 337 if not os.path.exists(instance_home): | 339 if not os.path.exists(tracker_home): |
| 338 raise UsageError, _('Instance home does not exist')%locals() | 340 raise UsageError, _('Instance home does not exist')%locals() |
| 339 if not os.path.exists(os.path.join(instance_home, 'html')): | 341 if not os.path.exists(os.path.join(tracker_home, 'html')): |
| 340 raise UsageError, _('Instance has not been installed')%locals() | 342 raise UsageError, _('Instance has not been installed')%locals() |
| 341 | 343 |
| 342 # is there already a database? | 344 # is there already a database? |
| 343 if os.path.exists(os.path.join(instance_home, 'db')): | 345 if os.path.exists(os.path.join(tracker_home, 'db')): |
| 344 print _('WARNING: The database is already initialised!') | 346 print _('WARNING: The database is already initialised!') |
| 345 print _('If you re-initialise it, you will lose all the data!') | 347 print _('If you re-initialise it, you will lose all the data!') |
| 346 ok = raw_input(_('Erase it? Y/[N]: ')).strip() | 348 ok = raw_input(_('Erase it? Y/[N]: ')).strip() |
| 347 if ok.lower() != 'y': | 349 if ok.lower() != 'y': |
| 348 return 0 | 350 return 0 |
| 349 | 351 |
| 350 # nuke it | 352 # nuke it |
| 351 shutil.rmtree(os.path.join(instance_home, 'db')) | 353 shutil.rmtree(os.path.join(tracker_home, 'db')) |
| 352 | 354 |
| 353 # GO | 355 # GO |
| 354 init.initialise(instance_home, adminpw) | 356 init.initialise(tracker_home, adminpw) |
| 355 | 357 |
| 356 return 0 | 358 return 0 |
| 357 | 359 |
| 358 | 360 |
| 359 def do_get(self, args): | 361 def do_get(self, args): |
| 951 self.db.pack(pack_before) | 953 self.db.pack(pack_before) |
| 952 return 0 | 954 return 0 |
| 953 | 955 |
| 954 def do_reindex(self, args): | 956 def do_reindex(self, args): |
| 955 '''Usage: reindex | 957 '''Usage: reindex |
| 956 Re-generate an instance's search indexes. | 958 Re-generate a tracker's search indexes. |
| 957 | 959 |
| 958 This will re-generate the search indexes for an instance. This will | 960 This will re-generate the search indexes for a tracker. This will |
| 959 typically happen automatically. | 961 typically happen automatically. |
| 960 ''' | 962 ''' |
| 961 self.db.indexer.force_reindex() | 963 self.db.indexer.force_reindex() |
| 962 self.db.reindex() | 964 self.db.reindex() |
| 963 return 0 | 965 return 0 |
| 1028 print _('Multiple commands match "%(command)s": %(list)s')%{'command': | 1030 print _('Multiple commands match "%(command)s": %(list)s')%{'command': |
| 1029 command, 'list': ', '.join([i[0] for i in functions])} | 1031 command, 'list': ', '.join([i[0] for i in functions])} |
| 1030 return 1 | 1032 return 1 |
| 1031 command, function = functions[0] | 1033 command, function = functions[0] |
| 1032 | 1034 |
| 1033 # make sure we have an instance_home | 1035 # make sure we have a tracker_home |
| 1034 while not self.instance_home: | 1036 while not self.tracker_home: |
| 1035 self.instance_home = raw_input(_('Enter instance home: ')).strip() | 1037 self.tracker_home = raw_input(_('Enter tracker home: ')).strip() |
| 1036 | 1038 |
| 1037 # before we open the db, we may be doing an install or init | 1039 # before we open the db, we may be doing an install or init |
| 1038 if command == 'initialise': | 1040 if command == 'initialise': |
| 1039 try: | 1041 try: |
| 1040 return self.do_initialise(self.instance_home, args) | 1042 return self.do_initialise(self.tracker_home, args) |
| 1041 except UsageError, message: | 1043 except UsageError, message: |
| 1042 print _('Error: %(message)s')%locals() | 1044 print _('Error: %(message)s')%locals() |
| 1043 return 1 | 1045 return 1 |
| 1044 elif command == 'install': | 1046 elif command == 'install': |
| 1045 try: | 1047 try: |
| 1046 return self.do_install(self.instance_home, args) | 1048 return self.do_install(self.tracker_home, args) |
| 1047 except UsageError, message: | 1049 except UsageError, message: |
| 1048 print _('Error: %(message)s')%locals() | 1050 print _('Error: %(message)s')%locals() |
| 1049 return 1 | 1051 return 1 |
| 1050 | 1052 |
| 1051 # get the instance | 1053 # get the tracker |
| 1052 try: | 1054 try: |
| 1053 instance = roundup.instance.open(self.instance_home) | 1055 tracker = roundup.instance.open(self.tracker_home) |
| 1054 except ValueError, message: | 1056 except ValueError, message: |
| 1055 self.instance_home = '' | 1057 self.tracker_home = '' |
| 1056 print _("Error: Couldn't open instance: %(message)s")%locals() | 1058 print _("Error: Couldn't open tracker: %(message)s")%locals() |
| 1057 return 1 | 1059 return 1 |
| 1058 | 1060 |
| 1059 # only open the database once! | 1061 # only open the database once! |
| 1060 if not self.db: | 1062 if not self.db: |
| 1061 self.db = instance.open('admin') | 1063 self.db = tracker.open('admin') |
| 1062 | 1064 |
| 1063 # do the command | 1065 # do the command |
| 1064 ret = 0 | 1066 ret = 0 |
| 1065 try: | 1067 try: |
| 1066 ret = function(args[1:]) | 1068 ret = function(args[1:]) |
| 1110 except getopt.GetoptError, e: | 1112 except getopt.GetoptError, e: |
| 1111 self.usage(str(e)) | 1113 self.usage(str(e)) |
| 1112 return 1 | 1114 return 1 |
| 1113 | 1115 |
| 1114 # handle command-line args | 1116 # handle command-line args |
| 1115 self.instance_home = os.environ.get('TRACKER_HOME', '') | 1117 self.tracker_home = os.environ.get('TRACKER_HOME', '') |
| 1116 # TODO: reinstate the user/password stuff (-u arg too) | 1118 # TODO: reinstate the user/password stuff (-u arg too) |
| 1117 name = password = '' | 1119 name = password = '' |
| 1118 if os.environ.has_key('ROUNDUP_LOGIN'): | 1120 if os.environ.has_key('ROUNDUP_LOGIN'): |
| 1119 l = os.environ['ROUNDUP_LOGIN'].split(':') | 1121 l = os.environ['ROUNDUP_LOGIN'].split(':') |
| 1120 name = l[0] | 1122 name = l[0] |
| 1124 for opt, arg in opts: | 1126 for opt, arg in opts: |
| 1125 if opt == '-h': | 1127 if opt == '-h': |
| 1126 self.usage() | 1128 self.usage() |
| 1127 return 0 | 1129 return 0 |
| 1128 if opt == '-i': | 1130 if opt == '-i': |
| 1129 self.instance_home = arg | 1131 self.tracker_home = arg |
| 1130 if opt == '-c': | 1132 if opt == '-c': |
| 1131 self.comma_sep = 1 | 1133 self.comma_sep = 1 |
| 1132 | 1134 |
| 1133 # if no command - go interactive | 1135 # if no command - go interactive |
| 1134 ret = 0 | 1136 ret = 0 |
