22
22
import os, re, shutil, filecmp, json
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
31
32
def __init__( self ):
34
raise RuntimeError( 'logic error: Deployment initialised when '
32
36
self.load_deployment_state()
33
37
self.conflicts_checked = False
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.
38
45
# list of files that were copied-in (or at least given the opportunity
39
# 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.
46
self.deploy_files = None
46
# 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 have dealt with in the repo), any conflicts arising with these
49
# files in the home directory are no longer important and can be
50
# ignored. In short, this is a list of files that can safely be
51
# deployed, regardless of the state of the home directory.
52
self.imported_files = None
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
58
# the revno that the repo was as prior to a recent update
59
self.initial_revno = None
52
61
# do we have a repo?
53
62
if not os.path.exists( the.repo.full_dir ): return
60
69
# read the file list
61
if the.verbose: print "loading deployment state"
70
if the.verbose >= 1: print "deployment state found; loading"
62
71
f = open( file, 'r' )
63
72
state = json.loads( f.read() )
65
74
# unpack deployment state
66
self.deploy_files = state['deploy_files'];
67
self.affected_files = state['affected_files'];
75
if 'imported_files' in state:
76
self.imported_files = state['imported_files'];
77
if 'initial_revno' in state:
78
self.initial_revno = state['initial_revno'];
79
if 'affected_files' in state:
80
self.affected_files = state['affected_files'];
70
83
def save_deployment_state( self ):
71
if the.verbose: print "saving deployment state"
84
"""Save the current deployment state (so there will be a deployment ongoing).
87
if the.verbose >= 1: print "saving deployment state"
73
89
# create metadata directory, as necessary
74
90
if not os.path.isdir( the.full_mddir ):
89
106
def remove_deployment_state( self ):
107
"""Remove the current deployment state (so no deployment will be ongoing).
92
111
file = os.path.join( the.full_mddir, "deploy.%s" % the.repo.name )
93
112
if( os.path.isfile( file ) ):
96
if the.verbose: print "removing deployment state"
115
if the.verbose >= 1: print "removing deployment state"
100
119
def is_ongoing( self ):
101
return False if self.deploy_files is None else True
120
"""Is there a deployment currently ongoing?
123
return False if self.imported_files is None else True
104
126
def check_ongoing( self, ongoing = True ):
127
"""Check that a deployment either is or is not ongoing and raise an error if
106
if self.deploy_files is None:
132
if self.imported_files is None:
107
133
raise self.DeploymentOngoing( False )
109
if self.deploy_files is not None:
135
if self.imported_files is not None:
110
136
raise self.DeploymentOngoing( True )
139
def get_initial_revno( self ):
140
"""Get the initial revision identifier from the deployment state.
143
return self.initial_revno
146
def copy_in( self, initial_revno = None ):
147
"""Copy-in changes from the home directory to the repository. When finished,
148
the state of deployment is saved, meaning that a deployment is ongoing.
115
151
# check we don't already have a file list
116
152
self.check_ongoing( False )
118
154
# if the repo doesn't exist, we have an empty file list
119
155
if not os.path.exists( the.repo.full_dir ):
120
self.deploy_files = list()
156
self.imported_files = list()
123
if the.verbose: print "importing files..."
159
if the.verbose >= 1: print "importing files..."
124
160
walker = CopyInWalker()
126
if( walker.changed ):
127
raise self.CopyInConflicts( walker.changed )
128
self.deploy_files = walker.walk_list
162
self.imported_files = walker.walk_list
164
# obtain initial revno
165
self.initial_revno = the.repo.vcs.get_revno()
131
168
self.save_deployment_state()
134
171
def get_conflicts( self, affected_files = None ):
172
"""Check to see if there are any deployment conflicts. If a list of affected
173
files is supplied, then only those files are checked (and they are also
174
saved with the deployment state). Otherwise, all files in the
175
repository are checked.
136
178
# check we have a file list
137
179
self.check_ongoing( True )
142
184
self.save_deployment_state()
144
186
# check for deployment conflicts
145
walker = ConflictWalker( self.deploy_files, self.affected_files )
187
walker = ConflictWalker( self.imported_files, self.affected_files )
148
190
self.conflicts_checked = True
149
return walker.changed
152
def copy_out( self ):
191
return walker.changed + walker.obstructed
194
def copy_out( self, quiet ):
195
"""Copy-out changed files from the repository to the home directory. If the
196
deployment state includes a list of affected files, then only those
197
files are copied-out.
154
200
# check we have a file list
155
201
self.check_ongoing( True )