3
# Copyright (C) 2013 to 2014 Tim Marston <tim@edm.am>
5
# This file is part of stdhome (hereafter referred to as "this program").
6
# See http://ed.am/dev/stdhome for more information.
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
import filecmp, os, shutil
23
from walker import Walker
24
import stdhome.the as the
27
class CopyOutWalker( Walker ):
28
"""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.
35
Walker destination: home dir
36
Walker traversing: repo (or a provided file list, which may include stuff
37
that no longer exists in the repo
40
def __init__( self, updated_files = None ):
41
self.src_dir = the.repo.full_dir
42
self.dst_dir = the.full_home_dir
43
self.walk_list = updated_files if updated_files is not None else \
44
self.generate_walk_list( the.repo.full_dir )
47
def process( self, rel_file, src_file, src_type, dst_file, dst_type ):
52
# if entity doesn't exist in home dir, create directory (no need to
53
# recurse, since we're copying the whole directory)
55
if the.verbose > 1: print " _<d " + rel_file
57
shutil.copystat( src_file, dst_file )
60
# if entity is a file or symlink in home dir, replace it with
61
# directory (no need to recurse, since we're copying the whole
63
elif dst_type == 'f' or dst_type == 'l':
64
if the.verbose > 1: print " %s<d %s" % ( dst_type, rel_file )
67
shutil.copystat( src_file, dst_file )
70
# if entity is a directory in home dir, copy permissions, as
71
# required (and recurse)
73
# TODO: should check permission and only do as necessary
74
if the.verbose > 1: print " d<d " + rel_file
75
shutil.copystat( src_file, dst_file )
79
raise NotImplementedError()
84
# if entity doesn't exist in home dir, copy file
86
if the.verbose > 1: print " _<f " + rel_file
87
shutil.copy( src_file, dst_file )
88
shutil.copystat( src_file, dst_file )
90
# if entity is a symlink in home dir, replace it with file
92
if the.verbose > 1: print " l<f " + rel_file
94
shutil.copy( src_file, dst_file )
95
shutil.copystat( src_file, dst_file )
97
# if entity is a file in home dir, replace it only if it differs
99
if not filecmp.cmp( src_file, dst_file ):
100
if the.verbose > 1: print " f<f " + rel_file
101
os.unlink( dst_file )
102
shutil.copy( src_file, dst_file )
103
shutil.copystat( src_file, dst_file )
105
if the.verbose > 1: print " f=f " + rel_file
107
# if entity is a directory in home dir, replace it with file
108
elif dst_type == 'd':
109
if the.verbose > 1: print " d<f " + rel_file
110
shutil.rmtree( dst_file )
111
shutil.copy( src_file, dst_file )
112
shutil.copystat( src_file, dst_file )
115
raise NotImplementedError()
120
# if entity doesn't exist in home dir, copy symlink
122
if the.verbose > 1: print " _<l " + rel_file
123
os.symlink( os.readlink( src_file ), dst_file )
125
# if entity is a symlink in home dir, replace it only if it differs
126
elif dst_type == 'l':
127
if os.readlink( src_file ) != os.readlink( dst_file ):
128
if the.verbose > 1: print " l<l " + rel_file
129
os.unlink( dst_file )
130
os.symlink( os.readlink( src_file ), dst_file )
132
if the.verbose > 1: print " l=l " + rel_file
134
# if entity is a file in home dir, replace it with file
135
elif dst_type == 'f':
136
if the.verbose > 1: print " f<l " + rel_file
137
os.unlink( dst_file )
138
os.symlink( os.readlink( src_file ), dst_file )
140
# if entity is a directory in home dir, replace it with file
141
elif dst_type == 'd':
142
if the.verbose > 1: print " d<l " + rel_file
143
shutil.rmtree( dst_file )
144
os.symlink( os.readlink( src_file ), dst_file )
147
raise NotImplementedError()
152
# if entity doesn't exist in home dir, we're good
156
# if entity is a file or symlink in home dir, delete it
157
if dst_type == 'f' or dst_type == 'l':
158
if the.verbose > 1: print " %s<_ %s" % ( dst_type, rel_file )
159
os.unlink( dst_file )
161
# if entity is a directory in home dir, delete it
162
elif dst_type == 'd':
163
if the.verbose > 1: print " d<_ " + rel_file
164
shutil.rmtree( dst_file )
167
raise NotImplementedError()
169
# non-directories can not be recursed in to