~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Tools/scripts/treesync.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python3
 
2
 
 
3
"""Script to synchronize two source trees.
 
4
 
 
5
Invoke with two arguments:
 
6
 
 
7
python treesync.py slave master
 
8
 
 
9
The assumption is that "master" contains CVS administration while
 
10
slave doesn't.  All files in the slave tree that have a CVS/Entries
 
11
entry in the master tree are synchronized.  This means:
 
12
 
 
13
    If the files differ:
 
14
        if the slave file is newer:
 
15
            normalize the slave file
 
16
            if the files still differ:
 
17
                copy the slave to the master
 
18
        else (the master is newer):
 
19
            copy the master to the slave
 
20
 
 
21
    normalizing the slave means replacing CRLF with LF when the master
 
22
    doesn't use CRLF
 
23
 
 
24
"""
 
25
 
 
26
import os, sys, stat, getopt
 
27
 
 
28
# Interactivity options
 
29
default_answer = "ask"
 
30
create_files = "yes"
 
31
create_directories = "no"
 
32
write_slave = "ask"
 
33
write_master = "ask"
 
34
 
 
35
def main():
 
36
    global always_no, always_yes
 
37
    global create_directories, write_master, write_slave
 
38
    opts, args = getopt.getopt(sys.argv[1:], "nym:s:d:f:a:")
 
39
    for o, a in opts:
 
40
        if o == '-y':
 
41
            default_answer = "yes"
 
42
        if o == '-n':
 
43
            default_answer = "no"
 
44
        if o == '-s':
 
45
            write_slave = a
 
46
        if o == '-m':
 
47
            write_master = a
 
48
        if o == '-d':
 
49
            create_directories = a
 
50
        if o == '-f':
 
51
            create_files = a
 
52
        if o == '-a':
 
53
            create_files = create_directories = write_slave = write_master = a
 
54
    try:
 
55
        [slave, master] = args
 
56
    except ValueError:
 
57
        print("usage: python", sys.argv[0] or "treesync.py", end=' ')
 
58
        print("[-n] [-y] [-m y|n|a] [-s y|n|a] [-d y|n|a] [-f n|y|a]", end=' ')
 
59
        print("slavedir masterdir")
 
60
        return
 
61
    process(slave, master)
 
62
 
 
63
def process(slave, master):
 
64
    cvsdir = os.path.join(master, "CVS")
 
65
    if not os.path.isdir(cvsdir):
 
66
        print("skipping master subdirectory", master)
 
67
        print("-- not under CVS")
 
68
        return
 
69
    print("-"*40)
 
70
    print("slave ", slave)
 
71
    print("master", master)
 
72
    if not os.path.isdir(slave):
 
73
        if not okay("create slave directory %s?" % slave,
 
74
                    answer=create_directories):
 
75
            print("skipping master subdirectory", master)
 
76
            print("-- no corresponding slave", slave)
 
77
            return
 
78
        print("creating slave directory", slave)
 
79
        try:
 
80
            os.mkdir(slave)
 
81
        except OSError as msg:
 
82
            print("can't make slave directory", slave, ":", msg)
 
83
            return
 
84
        else:
 
85
            print("made slave directory", slave)
 
86
    cvsdir = None
 
87
    subdirs = []
 
88
    names = os.listdir(master)
 
89
    for name in names:
 
90
        mastername = os.path.join(master, name)
 
91
        slavename = os.path.join(slave, name)
 
92
        if name == "CVS":
 
93
            cvsdir = mastername
 
94
        else:
 
95
            if os.path.isdir(mastername) and not os.path.islink(mastername):
 
96
                subdirs.append((slavename, mastername))
 
97
    if cvsdir:
 
98
        entries = os.path.join(cvsdir, "Entries")
 
99
        for e in open(entries).readlines():
 
100
            words = e.split('/')
 
101
            if words[0] == '' and words[1:]:
 
102
                name = words[1]
 
103
                s = os.path.join(slave, name)
 
104
                m = os.path.join(master, name)
 
105
                compare(s, m)
 
106
    for (s, m) in subdirs:
 
107
        process(s, m)
 
108
 
 
109
def compare(slave, master):
 
110
    try:
 
111
        sf = open(slave, 'r')
 
112
    except IOError:
 
113
        sf = None
 
114
    try:
 
115
        mf = open(master, 'rb')
 
116
    except IOError:
 
117
        mf = None
 
118
    if not sf:
 
119
        if not mf:
 
120
            print("Neither master nor slave exists", master)
 
121
            return
 
122
        print("Creating missing slave", slave)
 
123
        copy(master, slave, answer=create_files)
 
124
        return
 
125
    if not mf:
 
126
        print("Not updating missing master", master)
 
127
        return
 
128
    if sf and mf:
 
129
        if identical(sf, mf):
 
130
            return
 
131
    sft = mtime(sf)
 
132
    mft = mtime(mf)
 
133
    if mft > sft:
 
134
        # Master is newer -- copy master to slave
 
135
        sf.close()
 
136
        mf.close()
 
137
        print("Master             ", master)
 
138
        print("is newer than slave", slave)
 
139
        copy(master, slave, answer=write_slave)
 
140
        return
 
141
    # Slave is newer -- copy slave to master
 
142
    print("Slave is", sft-mft, "seconds newer than master")
 
143
    # But first check what to do about CRLF
 
144
    mf.seek(0)
 
145
    fun = funnychars(mf)
 
146
    mf.close()
 
147
    sf.close()
 
148
    if fun:
 
149
        print("***UPDATING MASTER (BINARY COPY)***")
 
150
        copy(slave, master, "rb", answer=write_master)
 
151
    else:
 
152
        print("***UPDATING MASTER***")
 
153
        copy(slave, master, "r", answer=write_master)
 
154
 
 
155
BUFSIZE = 16*1024
 
156
 
 
157
def identical(sf, mf):
 
158
    while 1:
 
159
        sd = sf.read(BUFSIZE)
 
160
        md = mf.read(BUFSIZE)
 
161
        if sd != md: return 0
 
162
        if not sd: break
 
163
    return 1
 
164
 
 
165
def mtime(f):
 
166
    st = os.fstat(f.fileno())
 
167
    return st[stat.ST_MTIME]
 
168
 
 
169
def funnychars(f):
 
170
    while 1:
 
171
        buf = f.read(BUFSIZE)
 
172
        if not buf: break
 
173
        if '\r' in buf or '\0' in buf: return 1
 
174
    return 0
 
175
 
 
176
def copy(src, dst, rmode="rb", wmode="wb", answer='ask'):
 
177
    print("copying", src)
 
178
    print("     to", dst)
 
179
    if not okay("okay to copy? ", answer):
 
180
        return
 
181
    f = open(src, rmode)
 
182
    g = open(dst, wmode)
 
183
    while 1:
 
184
        buf = f.read(BUFSIZE)
 
185
        if not buf: break
 
186
        g.write(buf)
 
187
    f.close()
 
188
    g.close()
 
189
 
 
190
def raw_input(prompt):
 
191
    sys.stdout.write(prompt)
 
192
    sys.stdout.flush()
 
193
    return sys.stdin.readline()
 
194
 
 
195
def okay(prompt, answer='ask'):
 
196
    answer = answer.strip().lower()
 
197
    if not answer or answer[0] not in 'ny':
 
198
        answer = input(prompt)
 
199
        answer = answer.strip().lower()
 
200
        if not answer:
 
201
            answer = default_answer
 
202
    if answer[:1] == 'y':
 
203
        return 1
 
204
    if answer[:1] == 'n':
 
205
        return 0
 
206
    print("Yes or No please -- try again:")
 
207
    return okay(prompt)
 
208
 
 
209
if __name__ == '__main__':
 
210
    main()