cmptree.py 4.65 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
"""Compare local and remote dictionaries and transfer differing files -- like rdist."""

import sys
from repr import repr
import FSProxy
import time
import os

def main():
	pwd = os.getcwd()
	s = raw_input("chdir [%s] " % pwd)
	if s:
		os.chdir(s)
		pwd = os.getcwd()
	host = ask("host", 'voorn.cwi.nl')
	port = 4127
	verbose = 1
	mode = ''
	print """\
Mode should be a string of characters, indicating what to do with differences.
r - read different files to local file system
w - write different files to remote file system
c - create new files, either remote or local
d - delete disappearing files, either remote or local
"""
	s = raw_input("mode [%s] " % mode)
	if s: mode = s
	address = (host, port)
	t1 = time.time()
	local = FSProxy.FSProxyLocal()
	remote = FSProxy.FSProxyClient(address, verbose)
	compare(local, remote, mode)
	remote._close()
	local._close()
	t2 = time.time()
	dt = t2-t1
	mins, secs = divmod(dt, 60)
38
	print mins, "minutes and", round(secs), "seconds"
Guido van Rossum's avatar
Guido van Rossum committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
	raw_input("[Return to exit] ")

def ask(prompt, default):
	s = raw_input("%s [%s] " % (prompt, default))
	return s or default

def askint(prompt, default):
	s = raw_input("%s [%s] " % (prompt, str(default)))
	if s: return string.atoi(s)
	return default

def compare(local, remote, mode):
	print
	print "PWD =", `os.getcwd()`
	sums_id = remote._send('sumlist')
	subdirs_id = remote._send('listsubdirs')
	remote._flush()
	print "calculating local sums ..."
	lsumdict = {}
	for name, info in local.sumlist():
		lsumdict[name] = info
	print "getting remote sums ..."
	sums = remote._recv(sums_id)
	print "got", len(sums)
	rsumdict = {}
	for name, rsum in sums:
		rsumdict[name] = rsum
		if not lsumdict.has_key(name):
			print `name`, "only remote"
			if 'r' in mode and 'c' in mode:
				recvfile(local, remote, name)
		else:
			lsum = lsumdict[name]
			if lsum != rsum:
				print `name`,
				rmtime = remote.mtime(name)
				lmtime = local.mtime(name)
				if rmtime > lmtime:
					print "remote newer",
					if 'r' in mode:
						recvfile(local, remote, name)
				elif lmtime > rmtime:
					print "local newer",
					if 'w' in mode:
						sendfile(local, remote, name)
				else:
					print "same mtime but different sum?!?!",
				print
	for name in lsumdict.keys():
		if not rsumdict.keys():
			print `name`, "only locally",
			fl()
			if 'w' in mode and 'c' in mode:
				sendfile(local, remote, name)
			elif 'r' in mode and 'd' in mode:
				os.unlink(name)
				print "removed."
			print
	print "gettin subdirs ..."
	subdirs = remote._recv(subdirs_id)
	common = []
	for name in subdirs:
		if local.isdir(name):
			print "Common subdirectory", repr(name)
			common.append(name)
		else:
			print "Remote subdirectory", repr(name), "not found locally"
106 107 108 109 110 111 112 113 114 115 116 117
			if 'r' in mode and 'c' in mode:
				pr = "Create local subdirectory %s? [y] " % \
				     repr(name)
				if 'y' in mode:
					ok = 'y'
				else:
					ok = ask(pr, "y")
				if ok[:1] in ('y', 'Y'):
					local.mkdir(name)
					print "Subdirectory %s made" % \
						repr(name)
					common.append(name)
Guido van Rossum's avatar
Guido van Rossum committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	lsubdirs = local.listsubdirs()
	for name in lsubdirs:
		if name not in subdirs:
			print "Local subdirectory", repr(name), "not found remotely"
	for name in common:
		print "Entering subdirectory", repr(name)
		local.cd(name)
		remote.cd(name)
		compare(local, remote, mode)
		remote.back()
		local.back()

def sendfile(local, remote, name):
	try:
		remote.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "sending ...",
	fl()
	
	data = open(name).read()
	
	t1 = time.time()
	
	remote._send_noreply('write', name, data)
	remote._flush()
	
	t2 = time.time()
	
	dt = t2-t1
150
	print len(data), "bytes in", round(dt), "seconds",
Guido van Rossum's avatar
Guido van Rossum committed
151
	if dt:
152
		print "i.e.", round(len(data)/dt), "bytes/sec",
Guido van Rossum's avatar
Guido van Rossum committed
153 154 155
	print

def recvfile(local, remote, name):
156 157 158 159 160 161 162 163 164 165 166
	ok = 0
	try:
		rv = recvfile_real(local, remote, name)
		ok = 1
		return rv
	finally:
		if not ok:
			print "*** recvfile of %s failed, deleting" % `name`
			local.delete(name)

def recvfile_real(local, remote, name):
Guido van Rossum's avatar
Guido van Rossum committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
	try:
		local.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "receiving ...",
	fl()
	
	f = open(name, 'w')
	t1 = time.time()
	
	length = 4*1024
	offset = 0
	id = remote._send('read', name, offset, length)
	remote._flush()
	while 1:
		newoffset = offset + length
		newid = remote._send('read', name, newoffset, length)
		data = remote._recv(id)
		id = newid
		if not data: break
		f.seek(offset)
		f.write(data)
		offset = newoffset
	size = f.tell()
	
	t2 = time.time()
	f.close()
	
	dt = t2-t1
198
	print size, "bytes in", round(dt), "seconds",
Guido van Rossum's avatar
Guido van Rossum committed
199 200 201 202 203 204 205 206 207 208
	if dt:
		print "i.e.", int(size/dt), "bytes/sec",
	print
	remote._recv(id) # ignored

def fl():
	sys.stdout.flush()

if __name__ == '__main__':
	main()