/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_in.py

  • Committer: Tim Marston
  • Date: 2016-12-13 21:40:34 UTC
  • Revision ID: tim@ed.am-20161213214034-nd5t7ztnlrjd627i
fix add command and generic filename expansion/resolution to expend to
homedir-relative filename and absolute filename based on original filename, as
specified, rather than a fully, symlink-resolved filename.  So, e.g., if ~/bob
was a symlink to ~/fred, then ~/bob/a would resolve to the relative filename
bob/a, becuase it is inside the homedir (it would resolve to fred/a otherwise)

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
from copy_base import CopyBaseWalker
24
23
import stdhome.the as the
25
 
 
26
 
 
27
 
class CopyInWalker( Walker ):
 
24
from stdhome.file_matcher import FileMatcher
 
25
 
 
26
 
 
27
class CopyInWalker( CopyBaseWalker ):
28
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.
 
29
        home directory.
31
30
 
32
31
        Walker source:       home dir
33
32
        Walker destination:  repo
34
33
        Walker traversing:   repo
35
34
        """
36
35
 
37
 
        def __init__( self ):
 
36
        def __init__( self, walk_files = None, report = False ):
 
37
                CopyBaseWalker.__init__( self )
38
38
                self.src_dir = the.full_home_dir
39
39
                self.dst_dir = the.repo.full_dir
40
 
                self.walk_list = self.generate_walk_list( the.repo.full_dir )
41
 
 
42
 
                self.changed = list()
43
 
 
44
 
 
45
 
        def process( self, rel_file, src, dst ):
46
 
 
47
 
                # directory (in repo)
48
 
                if dst.type == 'd':
49
 
 
50
 
                        # if entity doesn't exist in home dir, delete directory in repo (and
51
 
                        # don't recurse, obviously!)
52
 
                        if src.type == '_':
53
 
                                if the.verbose > 1: print "  _>d " + rel_file
54
 
                                shutil.rmtree( dst.file )
55
 
                                return False
56
 
 
57
 
                        # if entity is a directory in home dir, copy permissions to
58
 
                        # diurectory in repo, as necessary, and recurse
59
 
                        elif src.type == 'd':
60
 
                                # TODO: should check permissions and only do as necessary
61
 
                                if the.verbose > 1: print "  d>d " + rel_file
62
 
                                shutil.copystat( src.file, dst.file )
63
 
                                return True
64
 
 
65
 
                        # TODO: if entity is a directory symlink in the home direcotry,
66
 
                        # silently accept it if it is explicitly matched by the accept list.
67
 
                        # In which case, we'll also need to add this rel_file to a
68
 
                        # not_deployed file list so that, after this walk, we can remove it
69
 
                        # from the deployment's deploy_list.  If we don't, the directory in
70
 
                        # the repo will get copied-out.
71
 
#                       elif src.link_type == 'd' and self.accept_list.matches( rel_file ):
72
 
#                               if the.verbose > 1: print "  d@d " + rel_file
73
 
#                               return True
74
 
 
75
 
                        # TODO: serious differences between ~/ and repo (e.g., files in one
76
 
                        # that are directories in the other) should be ignored (e.g., not
77
 
                        # copied-in).  And the stuff that is ignored during copy-in should
78
 
                        # also be ignored during copy-out and must not be added to the
79
 
                        # deployment's deploy_files list.  Since these ignored files and
80
 
                        # directories are transparent to the user, they must be explicitly
81
 
                        # permitted via an "ignore list" in ~/.stdhomerc.  If these serious
82
 
                        # differences are not matched by the ignore list, an error should be
83
 
                        # shown (which will require a separate "check" walk of the repo, as
84
 
                        # is done in copy_out).
85
 
                        else:
86
 
                                self.changed.append( "%s (%s => %s)" % ( rel_file,
87
 
                                        dst.get_type_name(), src.get_type_name() ) )
88
 
                                return False
89
 
 
90
 
                # file (in repo)
91
 
                elif dst.type == 'f':
92
 
 
93
 
                        # if entity doesn't exist in home dir, delete file in repo
94
 
                        if src.type == '_':
95
 
                                if the.verbose > 1: print "  _>f " + rel_file
96
 
                                os.unlink( dst.file )
97
 
 
98
 
                        # if entity in home dir is a symlink, replace file in repo
99
 
                        elif src.type == 'l':
100
 
                                if the.verbose > 1: print "  l>f " + rel_file
101
 
                                os.unlink( dst.file )
102
 
                                os.symlink( os.readlink( src.file ), dst.file )
103
 
 
104
 
                        # if entity in home dir is a file, replace file in repo only if it
105
 
                        # differs
106
 
                        elif src.type == 'f':
107
 
                                if not filecmp.cmp( src.file, dst.file ):
108
 
                                        if the.verbose > 1: print "  f>f " + rel_file
109
 
                                        os.unlink( dst.file )
110
 
                                        shutil.copy( src.file, dst.file )
111
 
                                        shutil.copystat( src.file, dst.file )
112
 
                                else:
113
 
                                        if the.verbose > 1: print "  f=f " + rel_file
114
 
 
115
 
                        # TODO: serious differences between ~/ and repo (e.g., files in one
116
 
                        # that are directories in the other) should be ignored (e.g., not
117
 
                        # copied-in).  And the stuff that is ignored during copy-in should
118
 
                        # also be ignored during copy-out and must not be added to the
119
 
                        # deployment's deploy_files list.  Since these ignored files and
120
 
                        # directories are transparent to the user, they must be explicitly
121
 
                        # permitted via an "ignore list" in ~/.stdhomerc.  If these serious
122
 
                        # differences are not matched by the ignore list, an error should be
123
 
                        # show (which will require a separate "check" walk of the repo, as
124
 
                        # is done in copy_out).
125
 
                        else:
126
 
                                self.changed.append( "%s (%s => %s)" % ( rel_file,
127
 
                                        dst.get_type_name(), src.get_type_name() ) )
128
 
 
129
 
                # symlink (in repo)
130
 
                elif dst.type == 'l':
131
 
 
132
 
                        # if entity doesn't exist in home dir, delete symlink in repo
133
 
                        if src.type == '_':
134
 
                                if the.verbose > 1: print "  _>l " + rel_file
135
 
                                os.unlink( dst.file )
136
 
 
137
 
                        # if entity in home dir is a symlink, replace symlink in repo only
138
 
                        # if it differs
139
 
                        elif src.type == 'l':
140
 
                                if os.readlink( src.file ) != os.readlink( dst.file ):
141
 
                                        if the.verbose > 1: print "  l>l " + rel_file
142
 
                                        os.unlink( dst.file )
143
 
                                        os.symlink( os.readlink( src.file ), dst.file )
144
 
                                else:
145
 
                                        if the.verbose > 1: print "  l=l " + rel_file
146
 
 
147
 
                        # if entity in home dir is a file, replace symlink in repo
148
 
                        elif src.type == 'f':
149
 
                                if the.verbose > 1: print "  f>l " + rel_file
150
 
                                os.unlink( dst.file )
151
 
                                shutil.copy( src.file, dst.file )
152
 
                                shutil.copystat( src.file, dst.file )
153
 
 
154
 
                        # TODO: serious differences between ~/ and repo (e.g., files in one
155
 
                        # that are directories in the other) should be ignored (e.g., not
156
 
                        # copied-in).  And the stuff that is ignored during copy-in should
157
 
                        # also be ignored during copy-out and must not be added to the
158
 
                        # deployment's deploy_files list.  Since these ignored files and
159
 
                        # directories are transparent to the user, they must be explicitly
160
 
                        # permitted via an "ignore list" in ~/.stdhomerc.  If these serious
161
 
                        # differences are not matched by the ignore list, an error should be
162
 
                        # show (which will require a separate "check" walk of the repo, as
163
 
                        # is done in copy_out).
164
 
                        else:
165
 
                                self.changed.append( "%s (%s => %s)" % ( rel_file,
166
 
                                        dst.get_type_name(). src.get_type_name() ) )
167
 
 
168
 
                # can not recurse on a non-directory
169
 
                return False
 
40
                self.walk_list = walk_files if walk_files is not None else \
 
41
                                                 self.generate_walk_list( the.repo.full_dir )
 
42
                self.check_src_symlinks = True
 
43
                self.report = report
 
44
 
 
45
 
 
46
        def print_op( self, rel_file, src, op, dst ):
 
47
 
 
48
                CopyBaseWalker.print_op( self, rel_file, src, op, dst )
 
49
 
 
50
                # verbose reporting
 
51
                if the.verbose >= 2:
 
52
                        if op == '*': op = '>'
 
53
                        print "  %s%s%s %s" % ( src, op, dst, rel_file )