commit -- why not
diff --git a/Demo/pdist/cmptree.py b/Demo/pdist/cmptree.py
new file mode 100755
index 0000000..84ed3f0
--- /dev/null
+++ b/Demo/pdist/cmptree.py
@@ -0,0 +1,185 @@
+"""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)
+	print mins, "minutes and", secs, "seconds"
+	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"
+	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
+	print len(data), "bytes in", t2-t1, "seconds",
+	if dt:
+		print "i.e.", len(data)/dt, "bytes/sec",
+	print
+
+def recvfile(local, remote, name):
+	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
+	print size, "bytes in", dt, "seconds",
+	if dt:
+		print "i.e.", int(size/dt), "bytes/sec",
+	print
+	remote._recv(id) # ignored
+
+def fl():
+	sys.stdout.flush()
+
+if __name__ == '__main__':
+	main()