IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.7KB

  1. from tarfile import TarFile, \
  2. TarInfo
  3. import os
  4. import stat
  5. from itertools import chain
  6. from .misc import filehash
  7. def normalized_recursive_directory_iterator(path):
  8. Q = iter([ path ])
  9. name = next(Q, None)
  10. while name:
  11. st = os.lstat(name)
  12. if stat.S_ISDIR(st.st_mode):
  13. L = sorted(os.listdir(name))
  14. def create_map(name, L):
  15. return map(lambda x: os.path.join(name, x), L)
  16. L = create_map(name, L)
  17. yield (os.path.relpath(name, path), name, st.st_mode, st.st_uid, st.st_gid, st.st_size, st.st_mtime)
  18. Q = chain(L, Q)
  19. else: # file
  20. yield (os.path.relpath(name, path), name, st.st_mode, st.st_uid, st.st_gid, st.st_size, st.st_mtime)
  21. name = next(Q, None)
  22. def _export_diff(mountpoint, origin_mountpoint, output_directory):
  23. mit = normalized_recursive_directory_iterator(mountpoint)
  24. oit = normalized_recursive_directory_iterator(origin_mountpoint)
  25. def emit_removal(o):
  26. print('Removal:', o[0])
  27. def emit_creation(m):
  28. print('Creation:', m[0])
  29. def emit_compare(m, o):
  30. if m[2] != o[2] or m[3] != o[3] or m[4] != o[4]:
  31. print('Metadata change:', o[0])
  32. elif stat.S_ISREG(m[2]) and m[5] != o[5]:
  33. print('Size change:', o[0])
  34. elif stat.S_ISREG(m[2]) and m[6] != o[6] and filehash(m[1]) != filehash(o[1]):
  35. print('Content change:', o[0])
  36. else: # no change
  37. pass # print('Compare:', m[0])
  38. m = next(mit, None)
  39. o = next(oit, None)
  40. while True:
  41. if m is None and o is None:
  42. break
  43. elif m is None and o is not None:
  44. emit_removal(o)
  45. elif m is not None and o is None:
  46. emit_creation(m)
  47. elif m[0] < o[0]:
  48. emit_creation(m)
  49. m = next(mit, None)
  50. elif m[0] > o[0]:
  51. emit_removal(o)
  52. o = next(oit, None)
  53. elif stat.S_ISDIR(m[2]) != stat.S_ISDIR(o[2]):
  54. emit_creation(m)
  55. m = next(mit, None)
  56. o = next(oit, None)
  57. else:
  58. emit_compare(m, o)
  59. m = next(mit, None)
  60. o = next(oit, None)
  61. #for root, dirs, files in os.walk(path):
  62. # dirs.sort()
  63. # for dirname in dirs:
  64. # print(os.path.join(root, dirname))
  65. def command_export(args):
  66. name, _ = zfs_find(args.reference, focker_type='image')
  67. mountpoint = zfs_mountpoint(name)
  68. origin = zfs_parse_output(['zfs', 'get', '-H', 'origin', name])
  69. origin = origin[2].split('@')[0]
  70. origin_mountpoint = zfs_mountpoint(origin)
  71. Q = [ zfs_mountpoint(name) ]
  72. while len(Q) > 0:
  73. el = Q.pop()