1
#! /usr/bin/env python3
3
"""Script to synchronize two source trees.
5
Invoke with two arguments:
7
python treesync.py slave master
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:
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
21
normalizing the slave means replacing CRLF with LF when the master
26
import os, sys, stat, getopt
28
# Interactivity options
29
default_answer = "ask"
31
create_directories = "no"
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:")
41
default_answer = "yes"
49
create_directories = a
53
create_files = create_directories = write_slave = write_master = a
55
[slave, master] = args
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")
61
process(slave, master)
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")
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)
78
print("creating slave directory", slave)
81
except OSError as msg:
82
print("can't make slave directory", slave, ":", msg)
85
print("made slave directory", slave)
88
names = os.listdir(master)
90
mastername = os.path.join(master, name)
91
slavename = os.path.join(slave, name)
95
if os.path.isdir(mastername) and not os.path.islink(mastername):
96
subdirs.append((slavename, mastername))
98
entries = os.path.join(cvsdir, "Entries")
99
for e in open(entries).readlines():
101
if words[0] == '' and words[1:]:
103
s = os.path.join(slave, name)
104
m = os.path.join(master, name)
106
for (s, m) in subdirs:
109
def compare(slave, master):
111
sf = open(slave, 'r')
115
mf = open(master, 'rb')
120
print("Neither master nor slave exists", master)
122
print("Creating missing slave", slave)
123
copy(master, slave, answer=create_files)
126
print("Not updating missing master", master)
129
if identical(sf, mf):
134
# Master is newer -- copy master to slave
137
print("Master ", master)
138
print("is newer than slave", slave)
139
copy(master, slave, answer=write_slave)
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
149
print("***UPDATING MASTER (BINARY COPY)***")
150
copy(slave, master, "rb", answer=write_master)
152
print("***UPDATING MASTER***")
153
copy(slave, master, "r", answer=write_master)
157
def identical(sf, mf):
159
sd = sf.read(BUFSIZE)
160
md = mf.read(BUFSIZE)
161
if sd != md: return 0
166
st = os.fstat(f.fileno())
167
return st[stat.ST_MTIME]
171
buf = f.read(BUFSIZE)
173
if '\r' in buf or '\0' in buf: return 1
176
def copy(src, dst, rmode="rb", wmode="wb", answer='ask'):
177
print("copying", src)
179
if not okay("okay to copy? ", answer):
184
buf = f.read(BUFSIZE)
190
def raw_input(prompt):
191
sys.stdout.write(prompt)
193
return sys.stdin.readline()
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()
201
answer = default_answer
202
if answer[:1] == 'y':
204
if answer[:1] == 'n':
206
print("Yes or No please -- try again:")
209
if __name__ == '__main__':