19
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
import filecmp, os, shutil
23
from walker import Walker
22
from copy_base import CopyBaseWalker
24
23
import stdhome.the as the
27
class CopyInWalker( Walker ):
24
from stdhome.file_matcher import FileMatcher
27
class CopyInWalker( CopyBaseWalker ):
28
28
"""The copy-in walker traverses the repo, copying-in matching files from the
29
home directory. It will overwrite certin changes (modified files, files
30
that have changed to symlinks), but barf at others.
32
31
Walker source: home dir
33
32
Walker destination: repo
34
33
Walker traversing: repo
36
def __init__( self, walk_files = None, report = False ):
37
CopyBaseWalker.__init__( self )
38
38
self.src_dir = the.full_home_dir
39
39
self.dst_dir = the.repo.full_dir
40
self.walk_list = self.generate_walk_list( the.repo.full_dir )
45
def process( self, rel_file, src, dst ):
50
# if entity doesn't exist in home dir, delete directory in repo (and
51
# don't recurse, obviously!)
53
if the.verbose > 1: print " _>d " + rel_file
54
shutil.rmtree( dst.file )
57
# if entity is a directory in home dir, copy permissions to
58
# diurectory in repo, as necessary, and recurse
60
# TODO: should check permissions and only do as necessary
61
if the.verbose > 1: print " d>d " + rel_file
62
shutil.copystat( src.file, dst.file )
65
# TODO: if entity is a directory symlink in the home direcotry,
66
# silently accept it if it is explicitly matched by the accept list.
67
# In which case, we'll also need to add this rel_file to a
68
# not_deployed file list so that, after this walk, we can remove it
69
# from the deployment's deploy_list. If we don't, the directory in
70
# the repo will get copied-out.
71
# elif src.link_type == 'd' and self.accept_list.matches( rel_file ):
72
# if the.verbose > 1: print " d@d " + rel_file
75
# TODO: serious differences between ~/ and repo (e.g., files in one
76
# that are directories in the other) should be ignored (e.g., not
77
# copied-in). And the stuff that is ignored during copy-in should
78
# also be ignored during copy-out and must not be added to the
79
# deployment's deploy_files list. Since these ignored files and
80
# directories are transparent to the user, they must be explicitly
81
# permitted via an "ignore list" in ~/.stdhomerc. If these serious
82
# differences are not matched by the ignore list, an error should be
83
# shown (which will require a separate "check" walk of the repo, as
84
# is done in copy_out).
86
self.changed.append( "%s (%s => %s)" % ( rel_file,
87
dst.get_type_name(), src.get_type_name() ) )
93
# if entity doesn't exist in home dir, delete file in repo
95
if the.verbose > 1: print " _>f " + rel_file
98
# if entity in home dir is a symlink, replace file in repo
100
if the.verbose > 1: print " l>f " + rel_file
101
os.unlink( dst.file )
102
os.symlink( os.readlink( src.file ), dst.file )
104
# if entity in home dir is a file, replace file in repo only if it
106
elif src.type == 'f':
107
if not filecmp.cmp( src.file, dst.file ):
108
if the.verbose > 1: print " f>f " + rel_file
109
os.unlink( dst.file )
110
shutil.copy( src.file, dst.file )
111
shutil.copystat( src.file, dst.file )
113
if the.verbose > 1: print " f=f " + rel_file
115
# TODO: serious differences between ~/ and repo (e.g., files in one
116
# that are directories in the other) should be ignored (e.g., not
117
# copied-in). And the stuff that is ignored during copy-in should
118
# also be ignored during copy-out and must not be added to the
119
# deployment's deploy_files list. Since these ignored files and
120
# directories are transparent to the user, they must be explicitly
121
# permitted via an "ignore list" in ~/.stdhomerc. If these serious
122
# differences are not matched by the ignore list, an error should be
123
# show (which will require a separate "check" walk of the repo, as
124
# is done in copy_out).
126
self.changed.append( "%s (%s => %s)" % ( rel_file,
127
dst.get_type_name(), src.get_type_name() ) )
130
elif dst.type == 'l':
132
# if entity doesn't exist in home dir, delete symlink in repo
134
if the.verbose > 1: print " _>l " + rel_file
135
os.unlink( dst.file )
137
# if entity in home dir is a symlink, replace symlink in repo only
139
elif src.type == 'l':
140
if os.readlink( src.file ) != os.readlink( dst.file ):
141
if the.verbose > 1: print " l>l " + rel_file
142
os.unlink( dst.file )
143
os.symlink( os.readlink( src.file ), dst.file )
145
if the.verbose > 1: print " l=l " + rel_file
147
# if entity in home dir is a file, replace symlink in repo
148
elif src.type == 'f':
149
if the.verbose > 1: print " f>l " + rel_file
150
os.unlink( dst.file )
151
shutil.copy( src.file, dst.file )
152
shutil.copystat( src.file, dst.file )
154
# TODO: serious differences between ~/ and repo (e.g., files in one
155
# that are directories in the other) should be ignored (e.g., not
156
# copied-in). And the stuff that is ignored during copy-in should
157
# also be ignored during copy-out and must not be added to the
158
# deployment's deploy_files list. Since these ignored files and
159
# directories are transparent to the user, they must be explicitly
160
# permitted via an "ignore list" in ~/.stdhomerc. If these serious
161
# differences are not matched by the ignore list, an error should be
162
# show (which will require a separate "check" walk of the repo, as
163
# is done in copy_out).
165
self.changed.append( "%s (%s => %s)" % ( rel_file,
166
dst.get_type_name(). src.get_type_name() ) )
168
# can not recurse on a non-directory
40
self.walk_list = walk_files if walk_files is not None else \
41
self.generate_walk_list( the.repo.full_dir )
42
self.check_src_symlinks = True
46
def print_op( self, rel_file, src, op, dst ):
48
CopyBaseWalker.print_op( self, rel_file, src, op, dst )
52
if op == '*': op = '>'
53
print " %s%s%s %s" % ( src, op, dst, rel_file )