/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/deployment.py

  • Committer: Tim Marston
  • Date: 2014-04-06 14:04:12 UTC
  • Revision ID: tim@ed.am-20140406140412-jucgusrltzf8vyz5
during `stdhome status`, announce if a deployment is ongoing

Show diffs side-by-side

added added

removed removed

21
21
 
22
22
import os, re, shutil, filecmp, json
23
23
import the, util
24
 
from walker.copy_in_walker import CopyInWalker
25
 
from walker.conflict_walker import ConflictWalker
26
 
from walker.copy_out_walker import CopyOutWalker
 
24
from walker.copy_in import CopyInWalker
 
25
from walker.conflict import ConflictWalker
 
26
from walker.copy_out import CopyOutWalker
 
27
 
27
28
 
28
29
class Deployment:
29
30
 
30
31
 
31
32
        def __init__( self ):
 
33
                if the.repo is None:
 
34
                        raise RuntimeError( 'logic error: Deployment initialised when '
 
35
                                                                'the.repo is unset' )
32
36
                self.load_deployment_state()
33
37
                self.conflicts_checked = False
34
38
 
35
39
 
36
40
        def load_deployment_state( self ):
 
41
                """Load any deployment state.  If one is found then a deployment will be
 
42
                considered to be ongoing.
 
43
                """
37
44
 
38
45
                # list of files that were copied-in (or at least given the opportunity
39
46
        # to be) and updated through the vcs update.  This means that, while
40
 
        # there may have been conflicts during the update (which will be dealt
41
 
        # with in the repo), any arising conflicts with the filesystem are now
42
 
        # assumed to be because of the vcs update and can be ignored (that is to
43
 
        # say, we no longer care about the file in the home directory).  In
44
 
        # short, this is a list of files that it is safe to deploy, regardless
45
 
        # of the state of the filesystem.
 
47
        # there may have been conflicts during the update (which the user will
 
48
        # have to deal with in the repo), any conflicts arising with these files
 
49
        # in the home directory are no longer important and can be ignored.  In
 
50
        # short, this is a list of files that can safely be deployed, regardless
 
51
        # of the state of the home directory.
46
52
                self.deploy_files = None
47
53
 
48
54
                # list of files that were affected by a recent vcs update (so only these
49
 
                # need to be checked for deployment conflicts or copied-out)
 
55
                # files need to be checked for deployment conflicts or copied-out)
50
56
                self.affected_files = None
51
57
 
 
58
                # the revno that the repo was as prior to a recent update
 
59
                self.initial_revno = None
 
60
 
52
61
                # do we have a repo?
53
62
                if not os.path.exists( the.repo.full_dir ): return
54
63
 
58
67
                        return
59
68
 
60
69
                # read the file list
61
 
                if the.verbose: print "loading deployment state"
 
70
                if the.verbose: print "deployment state found; loading"
62
71
                f = open( file, 'r' )
63
72
                state = json.loads( f.read() )
64
73
 
65
74
                # unpack deployment state
66
75
                self.deploy_files = state['deploy_files'];
 
76
                self.initial_revno = state['initial_revno'];
67
77
                self.affected_files = state['affected_files'];
68
78
 
69
79
 
70
80
        def save_deployment_state( self ):
 
81
                """Save the current deployment state (so there will be a deployment ongoing).
 
82
                """
 
83
 
71
84
                if the.verbose: print "saving deployment state"
72
85
 
73
86
                # create metadata directory, as necessary
77
90
                # pack deployment state
78
91
                state = {
79
92
                        'deploy_files': self.deploy_files,
 
93
                        'initial_revno': self.initial_revno,
80
94
                        'affected_files': self.affected_files,
81
95
                }
82
96
 
87
101
 
88
102
 
89
103
        def remove_deployment_state( self ):
 
104
                """Remove the current deployment state (so no deployment will be ongoing).
 
105
                """
90
106
 
91
107
                # check it exists
92
108
                file = os.path.join( the.full_mddir, "deploy.%s" % the.repo.name )
98
114
 
99
115
 
100
116
        def is_ongoing( self ):
 
117
                """Is there a deployment currently ongoing?
 
118
                """
 
119
 
101
120
                return False if self.deploy_files is None else True
102
121
 
103
122
 
104
123
        def check_ongoing( self, ongoing = True ):
 
124
                """Check that a deployment either is or is not ongoing and raise an error if
 
125
                not.
 
126
                """
 
127
 
105
128
                if( ongoing ):
106
129
                        if self.deploy_files is None:
107
130
                                raise self.DeploymentOngoing( False )
110
133
                                raise self.DeploymentOngoing( True )
111
134
 
112
135
 
113
 
        def copy_in( self ):
 
136
        def get_initial_revno( self ):
 
137
                """Get the initial revision identifier from the deployment state.
 
138
                """
 
139
 
 
140
                return self.initial_revno
 
141
 
 
142
 
 
143
        def copy_in( self, initial_revno = None ):
 
144
                """Copy-in changes from the home directory to the repository.  When finished,
 
145
                the state of deployment is saved, meaning that a deployment is ongoing.
 
146
                """
114
147
 
115
148
                # check we don't already have a file list
116
149
                self.check_ongoing( False )
123
156
                        if the.verbose: print "importing files..."
124
157
                        walker = CopyInWalker()
125
158
                        walker.walk()
126
 
                        if( walker.changed ):
127
 
                                raise self.CopyInConflicts( walker.changed )
128
159
                        self.deploy_files = walker.walk_list
129
160
 
 
161
                        # obtain initial revno
 
162
                        self.initial_revno = the.repo.vcs.get_revno()
 
163
 
130
164
                # save state
131
165
                self.save_deployment_state()
132
166
 
133
167
 
134
168
        def get_conflicts( self, affected_files = None ):
 
169
                """Check to see if there are any delpoyment conflicts.  If a list of affected
 
170
                files is supplied, then only those files are checked (and they are also
 
171
                saved with the deployment state).  Otherwise, all files in the
 
172
                repository are checked.
 
173
                """
135
174
 
136
175
                # check we have a file list
137
176
                self.check_ongoing( True )
146
185
                walker.walk()
147
186
 
148
187
                self.conflicts_checked = True
149
 
                return walker.changed
 
188
                return walker.changed + walker.obstructed
150
189
 
151
190
 
152
191
        def copy_out( self ):
 
192
                """Copy-out changed files frmo the repository to the home directory.  If the
 
193
                deployment state incudes a list of affected files, then only those fiels
 
194
                are copied-out.
 
195
                """
153
196
 
154
197
                # check we have a file list
155
198
                self.check_ongoing( True )