19
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
import filecmp, os, shutil
23
from walker import Walker
23
from copy_base import CopyBaseWalker
24
24
import stdhome.the as the
27
class CopyOutWalker( Walker ):
25
from stdhome.file_matcher import FileMatcher
28
class CopyOutWalker( CopyBaseWalker ):
28
29
"""The copy-out walker traverses the repo, copying its content to the home
29
directory. It is run *after* checking for conflicts that might occur during
30
copy-out, so any conflicts that exist can be assumed to be unimportant and
31
disposable. In other words, this will happily overwrite stuff in the home
32
directory, without regard to its content.
30
directory. During an update, it is run *after* checking for conflicts that
31
might occur during copy-out, so any conflicts that exist can be assumed to
32
be unimportant and disposable. In other words, this will happily overwrite
33
stuff in the home directory, without regard to its content.
34
35
Walker source: repo
35
36
Walker destination: home dir
36
37
Walker traversing: repo (or a provided file list, which may include stuff
37
38
that no longer exists in the repo
40
def __init__( self, updated_files = None ):
42
def __init__( self, walk_files = None ):
41
43
self.src_dir = the.repo.full_dir
42
44
self.dst_dir = the.full_home_dir
43
self.walk_list = updated_files if updated_files is not None else \
45
self.walk_list = walk_files if walk_files is not None else \
44
46
self.generate_walk_list( the.repo.full_dir )
46
self.accept_symlinks = list()
49
def process( self, rel_file, src, dst ):
54
# if entity doesn't exist in home dir, create directory (no need to
55
# recurse, since we're copying the whole directory)
57
if the.verbose > 1: print " _<d " + rel_file
59
shutil.copystat( src.file, dst.file )
62
# if entity is a directory in home dir, copy permissions, as
63
# required (and recurse)
65
# TODO: should check permission and only do as necessary
66
if the.verbose > 1: print " d<d " + rel_file
67
shutil.copystat( src.file, dst.file )
70
# TODO: if entity is a symlink to a directory, and this is
71
# acceptable, just recurse
72
# elif dst.link_type == 'd' and self.accept_list.match( rel_file ):
73
# if the.verbose > 1: print " d@=d " + rel_file
76
# if entity is a file or symlink in home dir, replace it with
77
# directory (no need to recurse, since we're copying the whole
79
elif dst.type == 'f' or dst.type == 'l':
80
if the.verbose > 1: print " %s<d %s" % ( dst.type, rel_file )
83
shutil.copystat( src.file, dst.file )
87
raise NotImplementedError()
92
# if entity doesn't exist in home dir, copy file
94
if the.verbose > 1: print " _<f " + rel_file
95
shutil.copy( src.file, dst.file )
96
shutil.copystat( src.file, dst.file )
98
# if entity is a file in home dir, replace it only if it differs
100
if not filecmp.cmp( src.file, dst.file ):
101
if the.verbose > 1: print " f<f " + rel_file
102
os.unlink( dst.file )
103
shutil.copy( src.file, dst.file )
104
shutil.copystat( src.file, dst.file )
106
if the.verbose > 1: print " f=f " + rel_file
108
# if entity is a directory in home dir, replace it with file
109
elif dst.type == 'd':
110
if the.verbose > 1: print " d<f " + rel_file
111
shutil.rmtree( dst.file )
112
shutil.copy( src.file, dst.file )
113
shutil.copystat( src.file, dst.file )
115
# if entity is a symlink in home dir, replace it with file
116
elif dst.type == 'l':
117
if the.verbose > 1: print " l<f " + rel_file
118
os.unlink( dst.file )
119
shutil.copy( src.file, dst.file )
120
shutil.copystat( src.file, dst.file )
123
raise NotImplementedError()
128
# if entity doesn't exist in home dir, copy symlink
130
if the.verbose > 1: print " _<l " + rel_file
131
os.symlink( os.readlink( src.file ), dst.file )
133
# if entity is a symlink in home dir, replace it only if it differs
134
elif dst.type == 'l':
135
if os.readlink( src.file ) != os.readlink( dst.file ):
136
if the.verbose > 1: print " l<l " + rel_file
137
os.unlink( dst.file )
138
os.symlink( os.readlink( src.file ), dst.file )
140
if the.verbose > 1: print " l=l " + rel_file
142
# if entity is a file in home dir, replace it with file
143
elif dst.type == 'f':
144
if the.verbose > 1: print " f<l " + rel_file
145
os.unlink( dst.file )
146
os.symlink( os.readlink( src.file ), dst.file )
148
# if entity is a directory in home dir, replace it with file
149
elif dst.type == 'd':
150
if the.verbose > 1: print " d<l " + rel_file
151
shutil.rmtree( dst.file )
152
os.symlink( os.readlink( src.file ), dst.file )
155
raise NotImplementedError()
157
# deleted file (in repo)
160
# if entity doesn't exist in home dir, we're good
164
# if entity is a file or symlink in home dir, delete it
165
if dst.type == 'f' or dst.type == 'l':
166
if the.verbose > 1: print " %s<_ %s" % ( dst.type, rel_file )
167
os.unlink( dst.file )
169
# if entity is a directory in home dir, delete it
170
elif dst.type == 'd':
171
if the.verbose > 1: print " d<_ " + rel_file
172
shutil.rmtree( dst.file )
175
raise NotImplementedError()
177
# non-directories can not be recursed in to
48
self.accept_list = FileMatcher( the.config_file, 'symlink' )
51
def print_op( self, rel_file, operation ):
52
operation = re.sub( r'(.)(.)(.)', r'\3\2\1', operation )
53
operation = re.sub( r'\>', r'<', operation )
54
print " %s %s" % ( operation, rel_file )