/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-02-26 19:10:31 UTC
  • Revision ID: tim@ed.am-20140226191031-elcqy5j09h2syn2j
moved copy-in, copy-out and deployment conflict checking to a set of "walkers";
bzr vcs back-end now parses affected files during update; deployment state now
includes affected files

Show diffs side-by-side

added added

removed removed

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