/stdhome

To get this branch, use:
bzr branch http://bzr.ed.am/stdhome

« back to all changes in this revision

Viewing changes to lib/stdhome/program.py

  • Committer: Tim Marston
  • Date: 2014-01-05 11:51:35 UTC
  • Revision ID: tim@ed.am-20140105115135-6ses87ggwyjrxzfj
added global objects (the.repo, the.program), deployment object and implemented
init command

Show diffs side-by-side

added added

removed removed

1
 
# stdhome.py
 
1
# program.py
2
2
#
3
3
# Copyright (C) 2013 Tim Marston <tim@edm.am>
4
4
#
19
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
20
 
21
21
 
22
 
import sys, os
23
 
import getopt
24
 
 
25
 
 
26
 
class Stdhome:
 
22
import os, sys, getopt
 
23
import the
 
24
 
 
25
 
 
26
class Program:
27
27
 
28
28
 
29
29
        def __init__( self, version ):
 
30
                self.name = os.path.basename( sys.argv[ 0 ] )
30
31
                self.version = version
31
 
                self.program = os.path.basename( sys.argv[ 0 ] )
 
32
 
 
33
 
 
34
        def die( self, error_message ):
 
35
                prefix = self.name + ( ' ' + the.command if the.command else '' )
 
36
                print >> sys.stderr, '%s: %s' % ( prefix, error_message )
 
37
                exit( 1 )
32
38
 
33
39
 
34
40
        def print_usage( self, error_message ):
35
 
                print >> sys.stderr, self.program + ": " + error_message
36
 
                print >> sys.stderr, "Try '" + self.program + " --help' for more information."
37
 
                exit( 1 )
 
41
                suffix = ' ' + the.command if the.command else ''
 
42
                self.die( error_message + \
 
43
                                  "\nTry '%s%s --help' for more information." % \
 
44
                                  ( self.name, suffix ) )
38
45
 
39
46
 
40
47
        def print_help( self ):
41
 
                print "Usage: " + self.program + " COMMAND [OPTION]..."
 
48
                print "Usage: " + self.name + " COMMAND [OPTION]..."
42
49
                print
43
50
                #      01234567890123456789012345678901234567890123456789012345678901234567890123456789
44
51
                print "Manage your home directories, across multiple computers, similar to how you"
63
70
                print
64
71
                print "For help about a particular command (including the additional options that the"
65
72
                print "command accepts) try typing:"
66
 
                print "  $ " + self.program + " COMMAND --help"
 
73
                print "  $ " + self.name + " COMMAND --help"
67
74
                exit( 0 )
68
75
 
69
76
 
97
104
                         'stage-commit' ].count( command ) == 1:
98
105
                        return command
99
106
 
100
 
                # aliases
 
107
                # resolve aliases
101
108
                elif command == 'up':
102
109
                        return 'update'
103
110
                elif command == 'rm':
123
130
                        args = args[ 1 : ]
124
131
                return None
125
132
 
 
133
 
126
134
        def run( self ):
127
135
                # make an initial attempt to parse the command line, looking only for
128
136
                # --help and --version, so that they have the chance to run without a
132
140
                                sys.argv[ 1: ], "",
133
141
                                [ "help", "version" ] )
134
142
 
135
 
                        for opt, optargs in opts:
 
143
                        for opt, optarg in opts:
136
144
                                # we only show help if there are no non-option arguments (e.g.,
137
145
                                # a command) specified.  If a command has been specified it will
138
146
                                # have to be parsed and --help will be handled by it, instead)
142
150
                                        self.print_version()
143
151
 
144
152
                except getopt.GetoptError as e:
145
 
                        # ignore any errors -- we aren't parsing the command line properly
 
153
                        # ignore errors -- we aren't parsing the command line properly yet
146
154
                        pass
147
155
 
148
156
                # find the first non-option argument (the command)
149
 
                self.command = self.get_command_argument( sys.argv[ 1: ] )
150
 
                if self.command == None:
 
157
                the.command = self.get_command_argument( sys.argv[ 1: ] )
 
158
                if the.command == None:
151
159
                        self.print_usage( "missing command" )
152
160
 
153
161
                # check command is valid
154
 
                self.command = self.check_command( self.command )
155
 
                if self.command == None:
 
162
                the.command = self.check_command( the.command )
 
163
                if the.command == None:
156
164
                        self.print_usage( "bad command" )
157
165
 
158
166
                # calculate class name
159
 
                bits = self.command.split( '-' )
 
167
                bits = the.command.split( '-' )
160
168
                class_name = 'Command'
161
169
                for bit in bits:
162
170
                        class_name += bit[ 0 ].upper() + bit[ 1 : ]
163
171
 
164
 
                # instantiate and run the command class
165
 
                module = __import__( 'stdhome.command_' + self.command )
166
 
                the_class = getattr( module, class_name )
167
 
                instance = the_class()
168
 
                instance.run( self )
 
172
                # instantiate the command class
 
173
                module = __import__( 'stdhome.command_' + the.command,
 
174
                                                         fromlist = [ class_name ] )
 
175
                instance = getattr( module, class_name )()
 
176
 
 
177
                # run it
 
178
                try:
 
179
                        instance.parse_command_line()
 
180
                        instance.run()
 
181
                except ( getopt.GetoptError, self.UsageError ) as e:
 
182
                        self.print_usage( e.msg )
 
183
                except self.FatalError as e:
 
184
                        message = e.msg
 
185
                        if the.verbose and e.output:
 
186
                                message += '\n\nOUTPUT:\n' + e.output
 
187
                        self.die( message )
 
188
 
 
189
 
 
190
        class UsageError( Exception ):
 
191
 
 
192
                def __init__( self, error_message ):
 
193
                        self.msg = error_message
 
194
 
 
195
 
 
196
        class FatalError( Exception ):
 
197
 
 
198
                def __init__( self, message, output = None ):
 
199
                        self.msg = message
 
200
                        self.output = output