/stdhome

To get this branch, use:
bzr branch http://bzr.ed.am/stdhome

« back to all changes in this revision

Viewing changes to lib/stdhome/walker/copy_out.py

  • Committer: Tim Marston
  • Date: 2014-04-18 14:42:00 UTC
  • Revision ID: tim@ed.am-20140418144200-ksbr3l58p2v3jhy2
fixed bugs in command.expand_files, where results could be not unique, nor
sorted, and make sure the last component of the files is not resolved if it is a
symlink

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
20
 
21
21
 
22
 
import filecmp, os, shutil
23
 
from walker import Walker
 
22
import re
 
23
from copy_base import CopyBaseWalker
24
24
import stdhome.the as the
25
 
 
26
 
 
27
 
class CopyOutWalker( Walker ):
 
25
from stdhome.file_matcher import FileMatcher
 
26
 
 
27
 
 
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.
33
34
 
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
 
39
 
38
40
        """
39
41
 
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 )
45
47
 
46
 
                self.accept_symlinks = list()
47
 
 
48
 
 
49
 
        def process( self, rel_file, src, dst ):
50
 
 
51
 
                # directory (in repo)
52
 
                if src.type == 'd':
53
 
 
54
 
                        # if entity doesn't exist in home dir, create directory (no need to
55
 
                        # recurse, since we're copying the whole directory)
56
 
                        if dst.type == '_':
57
 
                                if the.verbose > 1: print "  _<d " + rel_file
58
 
                                os.mkdir( dst.file )
59
 
                                shutil.copystat( src.file, dst.file )
60
 
                                return False
61
 
 
62
 
                        # if entity is a directory in home dir, copy permissions, as
63
 
                        # required (and recurse)
64
 
                        elif dst.type == 'd':
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 )
68
 
                                return True
69
 
 
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
74
 
#                               return True
75
 
 
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
78
 
                        # directory)
79
 
                        elif dst.type == 'f' or dst.type == 'l':
80
 
                                if the.verbose > 1: print "  %s<d %s" % ( dst.type, rel_file )
81
 
                                os.unlink( dst.file )
82
 
                                os.mkdir( dst.file )
83
 
                                shutil.copystat( src.file, dst.file )
84
 
                                return False
85
 
 
86
 
                        else:
87
 
                                raise NotImplementedError()
88
 
 
89
 
                # file (in repo)
90
 
                if src.type == 'f':
91
 
 
92
 
                        # if entity doesn't exist in home dir, copy file
93
 
                        if dst.type == '_':
94
 
                                if the.verbose > 1: print "  _<f " + rel_file
95
 
                                shutil.copy( src.file, dst.file )
96
 
                                shutil.copystat( src.file, dst.file )
97
 
 
98
 
                        # if entity is a file in home dir, replace it only if it differs
99
 
                        elif dst.type == 'f':
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 )
105
 
                                else:
106
 
                                        if the.verbose > 1: print "  f=f " + rel_file
107
 
 
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 )
114
 
 
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 )
121
 
 
122
 
                        else:
123
 
                                raise NotImplementedError()
124
 
 
125
 
                # link (in repo)
126
 
                if src.type == 'l':
127
 
 
128
 
                        # if entity doesn't exist in home dir, copy symlink
129
 
                        if dst.type == '_':
130
 
                                if the.verbose > 1: print "  _<l " + rel_file
131
 
                                os.symlink( os.readlink( src.file ), dst.file )
132
 
 
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 )
139
 
                                else:
140
 
                                        if the.verbose > 1: print "  l=l " + rel_file
141
 
 
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 )
147
 
 
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 )
153
 
 
154
 
                        else:
155
 
                                raise NotImplementedError()
156
 
 
157
 
                # deleted file (in repo)
158
 
                if src.type == '_':
159
 
 
160
 
                        # if entity doesn't exist in home dir, we're good
161
 
                        if dst.type == '_':
162
 
                                pass;
163
 
 
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 )
168
 
 
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 )
173
 
 
174
 
                        else:
175
 
                                raise NotImplementedError()
176
 
 
177
 
                # non-directories can not be recursed in to
178
 
                return False
 
48
                self.accept_list = FileMatcher( the.config_file, 'symlink' )
 
49
 
 
50
 
 
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 )