/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-05 17:30:19 UTC
  • Revision ID: tim@ed.am-20140405173019-5eoi82r8i3etgn4j
added file matcher (for symlink accept and/or ignore lists)

Show diffs side-by-side

added added

removed removed

19
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
20
 
21
21
 
22
 
import re
23
 
from copy_base import CopyBaseWalker
 
22
import filecmp, os, shutil
 
23
from walker import Walker
24
24
import stdhome.the as the
25
 
from stdhome.file_matcher import FileMatcher
26
 
 
27
 
 
28
 
class CopyOutWalker( CopyBaseWalker ):
 
25
 
 
26
 
 
27
class CopyOutWalker( Walker ):
29
28
        """The copy-out walker traverses the repo, copying its content to the home
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.
 
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.
34
33
 
35
34
        Walker source:       repo
36
35
        Walker destination:  home dir
38
37
                                                        that no longer exists in the repo
39
38
        """
40
39
 
41
 
        def __init__( self, walk_files = None, quiet = False ):
42
 
                CopyBaseWalker.__init__( self )
 
40
        def __init__( self, updated_files = None ):
43
41
                self.src_dir = the.repo.full_dir
44
42
                self.dst_dir = the.full_home_dir
45
 
                self.walk_list = walk_files if walk_files is not None else \
46
 
                                                 self.generate_walk_list()
47
 
                self.check_dst_symlinks = True
48
 
                self.check_dst_ignores = True
49
 
                self.quiet = quiet
50
 
 
51
 
 
52
 
        def print_op( self, rel_file, src, op, dst ):
53
 
 
54
 
                # report changes
55
 
                if not self.quiet and the.verbose < 2 and op == '*':
56
 
                        if dst == '_':
57
 
                                print " N  %s" % ( rel_file )
58
 
                        elif src == '_':
59
 
                                print " D  %s" % ( rel_file )
60
 
                        elif src == dst:
61
 
                                print " M  %s" % ( rel_file )
62
 
                        else:
63
 
                                print " K  %s" % ( rel_file )
64
 
 
65
 
                # verbose reporting
66
 
                if the.verbose >= 2:
67
 
                        if op == '*': op = '<'
68
 
                        print "  %s%s%s %s" % ( src, op, dst, rel_file )
 
43
                self.walk_list = updated_files if updated_files is not None else \
 
44
                                                 self.generate_walk_list( the.repo.full_dir )
 
45
 
 
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