/Demo/pdist/cmptree.py

http://unladen-swallow.googlecode.com/ · Python · 208 lines · 186 code · 21 blank · 1 comment · 45 complexity · 3436a17bd9b1eaaede8f6d94a3a49d61 MD5 · raw file

  1. """Compare local and remote dictionaries and transfer differing files -- like rdist."""
  2. import sys
  3. from repr import repr
  4. import FSProxy
  5. import time
  6. import os
  7. def main():
  8. pwd = os.getcwd()
  9. s = raw_input("chdir [%s] " % pwd)
  10. if s:
  11. os.chdir(s)
  12. pwd = os.getcwd()
  13. host = ask("host", 'voorn.cwi.nl')
  14. port = 4127
  15. verbose = 1
  16. mode = ''
  17. print """\
  18. Mode should be a string of characters, indicating what to do with differences.
  19. r - read different files to local file system
  20. w - write different files to remote file system
  21. c - create new files, either remote or local
  22. d - delete disappearing files, either remote or local
  23. """
  24. s = raw_input("mode [%s] " % mode)
  25. if s: mode = s
  26. address = (host, port)
  27. t1 = time.time()
  28. local = FSProxy.FSProxyLocal()
  29. remote = FSProxy.FSProxyClient(address, verbose)
  30. compare(local, remote, mode)
  31. remote._close()
  32. local._close()
  33. t2 = time.time()
  34. dt = t2-t1
  35. mins, secs = divmod(dt, 60)
  36. print mins, "minutes and", round(secs), "seconds"
  37. raw_input("[Return to exit] ")
  38. def ask(prompt, default):
  39. s = raw_input("%s [%s] " % (prompt, default))
  40. return s or default
  41. def askint(prompt, default):
  42. s = raw_input("%s [%s] " % (prompt, str(default)))
  43. if s: return string.atoi(s)
  44. return default
  45. def compare(local, remote, mode):
  46. print
  47. print "PWD =", repr(os.getcwd())
  48. sums_id = remote._send('sumlist')
  49. subdirs_id = remote._send('listsubdirs')
  50. remote._flush()
  51. print "calculating local sums ..."
  52. lsumdict = {}
  53. for name, info in local.sumlist():
  54. lsumdict[name] = info
  55. print "getting remote sums ..."
  56. sums = remote._recv(sums_id)
  57. print "got", len(sums)
  58. rsumdict = {}
  59. for name, rsum in sums:
  60. rsumdict[name] = rsum
  61. if not lsumdict.has_key(name):
  62. print repr(name), "only remote"
  63. if 'r' in mode and 'c' in mode:
  64. recvfile(local, remote, name)
  65. else:
  66. lsum = lsumdict[name]
  67. if lsum != rsum:
  68. print repr(name),
  69. rmtime = remote.mtime(name)
  70. lmtime = local.mtime(name)
  71. if rmtime > lmtime:
  72. print "remote newer",
  73. if 'r' in mode:
  74. recvfile(local, remote, name)
  75. elif lmtime > rmtime:
  76. print "local newer",
  77. if 'w' in mode:
  78. sendfile(local, remote, name)
  79. else:
  80. print "same mtime but different sum?!?!",
  81. print
  82. for name in lsumdict.keys():
  83. if not rsumdict.keys():
  84. print repr(name), "only locally",
  85. fl()
  86. if 'w' in mode and 'c' in mode:
  87. sendfile(local, remote, name)
  88. elif 'r' in mode and 'd' in mode:
  89. os.unlink(name)
  90. print "removed."
  91. print
  92. print "gettin subdirs ..."
  93. subdirs = remote._recv(subdirs_id)
  94. common = []
  95. for name in subdirs:
  96. if local.isdir(name):
  97. print "Common subdirectory", repr(name)
  98. common.append(name)
  99. else:
  100. print "Remote subdirectory", repr(name), "not found locally"
  101. if 'r' in mode and 'c' in mode:
  102. pr = "Create local subdirectory %s? [y] " % \
  103. repr(name)
  104. if 'y' in mode:
  105. ok = 'y'
  106. else:
  107. ok = ask(pr, "y")
  108. if ok[:1] in ('y', 'Y'):
  109. local.mkdir(name)
  110. print "Subdirectory %s made" % \
  111. repr(name)
  112. common.append(name)
  113. lsubdirs = local.listsubdirs()
  114. for name in lsubdirs:
  115. if name not in subdirs:
  116. print "Local subdirectory", repr(name), "not found remotely"
  117. for name in common:
  118. print "Entering subdirectory", repr(name)
  119. local.cd(name)
  120. remote.cd(name)
  121. compare(local, remote, mode)
  122. remote.back()
  123. local.back()
  124. def sendfile(local, remote, name):
  125. try:
  126. remote.create(name)
  127. except (IOError, os.error), msg:
  128. print "cannot create:", msg
  129. return
  130. print "sending ...",
  131. fl()
  132. data = open(name).read()
  133. t1 = time.time()
  134. remote._send_noreply('write', name, data)
  135. remote._flush()
  136. t2 = time.time()
  137. dt = t2-t1
  138. print len(data), "bytes in", round(dt), "seconds",
  139. if dt:
  140. print "i.e.", round(len(data)/dt), "bytes/sec",
  141. print
  142. def recvfile(local, remote, name):
  143. ok = 0
  144. try:
  145. rv = recvfile_real(local, remote, name)
  146. ok = 1
  147. return rv
  148. finally:
  149. if not ok:
  150. print "*** recvfile of %r failed, deleting" % (name,)
  151. local.delete(name)
  152. def recvfile_real(local, remote, name):
  153. try:
  154. local.create(name)
  155. except (IOError, os.error), msg:
  156. print "cannot create:", msg
  157. return
  158. print "receiving ...",
  159. fl()
  160. f = open(name, 'w')
  161. t1 = time.time()
  162. length = 4*1024
  163. offset = 0
  164. id = remote._send('read', name, offset, length)
  165. remote._flush()
  166. while 1:
  167. newoffset = offset + length
  168. newid = remote._send('read', name, newoffset, length)
  169. data = remote._recv(id)
  170. id = newid
  171. if not data: break
  172. f.seek(offset)
  173. f.write(data)
  174. offset = newoffset
  175. size = f.tell()
  176. t2 = time.time()
  177. f.close()
  178. dt = t2-t1
  179. print size, "bytes in", round(dt), "seconds",
  180. if dt:
  181. print "i.e.", size//dt, "bytes/sec",
  182. print
  183. remote._recv(id) # ignored
  184. def fl():
  185. sys.stdout.flush()
  186. if __name__ == '__main__':
  187. main()