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 CopyInWalker( Walker ):
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
Walker source: home dir
33
Walker destination: repo
34
Walker traversing: repo
38
self.src_dir = the.full_fsdir
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_file, src_type, dst_file, dst_type ):
50
# if entity doesn't exist in home dir, delete directory in repo (and
51
# don't recurse, obviously!)
53
if the.verbose: 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: print " d>d " + rel_file
62
shutil.copystat( src_file, dst_file )
65
# TODO: serious differences in between ~/ and repo (e.g., files in
66
# one that are directories in the other) should be ignored (e.g.,
67
# not copied-in). And the stuff that is ignored during copy-in
68
# should also be ignored during copy-out and must not be added to
69
# the deploy_files list. Since these ignored files/directories are
70
# transparent to the user, they should have to explicitly permit
71
# them via an ignore file (e.g., ~/.stdhome/.ignore, akin to bzr's
72
# .bzrignore file). If these serious differences are not matched by
73
# the ignore file, an error should show (which will requie a
74
# separate "check" walk of the repo, as is done in copy_out).
76
self.changed.append( "%s (now %s)" % (
77
rel_file, self.name_of_type( src_type ) ) )
83
# if entity doesn't exist in home dir, delete file in repo
85
if the.verbose: print " _>f " + rel_file
88
# if entity in home dir is a symlink, replace file in repo
90
if the.verbose: print " l>f " + rel_file
92
os.symlink( os.readlink( src_file ), dst_file )
94
# if entity in home dir is a file, replace file in repo only if it
97
if not filecmp.cmp( src_file, dst_file ):
98
if the.verbose: print " f>f " + rel_file
100
shutil.copy( src_file, dst_file )
101
shutil.copystat( src_file, dst_file )
103
if the.verbose: print " f=f " + rel_file
105
# TODO: serious differences in between ~/ and repo (e.g., files in
106
# one that are directories in the other) should be ignored (e.g.,
107
# not copied-in). And the stuff that is ignored during copy-in
108
# should also be ignored during copy-out and must not be added to
109
# the deploy_files list. Since these ignored files/directories are
110
# transparent to the user, they should have to explicitly permit
111
# them via an ignore file (e.g., ~/.stdhome/.ignore, akin to bzr's
112
# .bzrignore file). If these serious differences are not matched by
113
# the ignore file, an error should show (which will requie a
114
# separate "check" walk of the repo, as is done in copy_out).
116
self.changed.append( "%s (now %s)" % (
117
rel_file, self.name_of_type( src_type ) ) )
120
elif dst_type == 'l':
122
# if entity doesn't exist in home dir, delete symlink in repo
124
if the.verbose: print " _>l " + rel_file
125
os.unlink( dst_file )
127
# if entity in home dir is a symlink, replace symlink in repo only
129
elif src_type == 'l':
130
if os.readlink( src_file ) != os.readlink( dst_file ):
131
if the.verbose: print " l>l " + rel_file
132
os.unlink( dst_file )
133
os.symlink( os.readlink( src_file ), dst_file )
135
if the.verbose: print " l=l " + rel_file
137
# if entity in home dir is a file, replace symlink in repo
138
elif src_type == 'f':
139
if the.verbose: print " f>l " + rel_file
140
os.unlink( dst_file )
141
shutil.copy( src_file, dst_file )
142
shutil.copystat( src_file, dst_file )
144
# TODO: serious differences in between ~/ and repo (e.g., files in
145
# one that are directories in the other) should be ignored (e.g.,
146
# not copied-in). And the stuff that is ignored during copy-in
147
# should also be ignored during copy-out and must not be added to
148
# the deploy_files list. Since these ignored files/directories are
149
# transparent to the user, they should have to explicitly permit
150
# them via an ignore file (e.g., ~/.stdhome/.ignore, akin to bzr's
151
# .bzrignore file). If these serious differences are not matched by
152
# the ignore file, an error should show (which will requie a
153
# separate "check" walk of the repo, as is done in copy_out).
155
self.changed.append( "%s (now %s)" % (
156
rel_file, self.name_of_type( src_type ) ) )
157
# can not recurse on a non-directory