Advertisement
nux95

tree

Jan 15th, 2013
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.22 KB | None | 0 0
  1. # coding: utf-8
  2. #
  3. # Copyright (C) 2012, Niklas Rosenstein
  4. #
  5. # Render *.tree file to HD:
  6. #
  7. #   python tree -o out.tree
  8. #   python tree -o out.tree -s /
  9. #   python tree -o out.tree -s /usr/bin/
  10. #
  11. # Read *.tree file and format to human readable text
  12. #
  13. #   python tree -o out-formatted.txt -i out.tree
  14. #
  15. #
  16.  
  17. import os
  18. import sys
  19. import struct
  20. import argparse
  21. import cStringIO
  22.  
  23. struct_i = struct.Struct('<i')
  24. pack_i = struct_i.pack
  25. unpack_i = lambda x: struct_i.unpack(x)[0]
  26.  
  27. struct_b = struct.Struct('<?')
  28. pack_b = struct_b.pack
  29. unpack_b = lambda x: struct_b.unpack(x)[0]
  30.  
  31. class ReadError(object):
  32.  
  33.     def format(self):
  34.         return "<ReadError>"
  35.  
  36. class UnkownParentNodeError(ReadError):
  37.  
  38.     def __init__(self, id, name, isdir, parent):
  39.         self.id = id
  40.         self.name = name
  41.         self.isdir = isdir
  42.         self.parent = parent
  43.  
  44.     def format(self):
  45.         return ("Node (id:%d,name:%s,isdir:%s) points to a parent (id:%d) that "
  46.                 "could not be found") % (self.id, self.name, bool(self.isdir),
  47.                                          self.parent)
  48.  
  49. class Node(object):
  50.  
  51.     def __init__(self, name):
  52.         super(Node, self).__init__()
  53.         self.name = os.path.basename(name)
  54.         self.files = []
  55.         self.folders = []
  56.  
  57.     def add_folder(self, node):
  58.         if not isinstance(node, Node):
  59.             raise TypeError
  60.         self.folders.append(node)
  61.  
  62.     def add_file(self, filename):
  63.         filename = os.path.basename(filename)
  64.         self.files.append(filename)
  65.  
  66.     def format(self, dest, i=0, t='    '):
  67.         dest.write(i * t + self.name + '/\n')
  68.         i += 1
  69.         for filename in self.files:
  70.             dest.write(i * t + filename + '/\n')
  71.         for child in self.folders:
  72.             child.format(dest, i, t)
  73.  
  74. class Base(object):
  75.  
  76.     def __init__(self):
  77.         super(Base, self).__init__()
  78.         self.fp = None
  79.  
  80.     def init(self, fp):
  81.         self.fp = fp
  82.  
  83.     def free(self):
  84.         self.fp = None
  85.  
  86.     def close(self):
  87.         self.fp.close()
  88.         self.free()
  89.  
  90. class Reader(Base):
  91.  
  92.     def __init__(self):
  93.         super(Reader, self).__init__()
  94.  
  95.     def init(self, fp):
  96.         super(Reader, self).init(fp)
  97.         self.dirs = {}
  98.         self.files = {}
  99.  
  100.     def free(self):
  101.         super(Reader, self).free()
  102.         self.dirs = None
  103.         self.files = None
  104.  
  105.     def read(self, fp):
  106.         self.init(fp)
  107.  
  108.         errors = []
  109.         root = Node('<root>')
  110.  
  111.         for name, isdir, id, parent_id in self.iter_nodes():
  112.             if isdir:
  113.                 self.dirs[id] = Node(name), parent_id
  114.             else:
  115.                 self.files[id] = (name, parent_id)
  116.  
  117.         for id, (filename, parent_id) in self.files.iteritems():
  118.             parent = None
  119.             if parent_id <= 0:
  120.                 parent = root
  121.             elif parent_id in self.dirs:
  122.                 parent = self.dirs[parent_id][0]
  123.             else:
  124.                 errors.append(UnkownParentNodeError(id, filename, True, parent_id))
  125.  
  126.             if parent:
  127.                 parent.add_file(filename)
  128.  
  129.         for id, (node, parent_id) in self.dirs.iteritems():
  130.             parent = None
  131.             if parent_id <= 0:
  132.                 parent = root
  133.             elif parent_id in self.dirs:
  134.                 parent = self.dirs[parent_id][0]
  135.             else:
  136.                 errors.append(UnkownParentNodeError(id, node.name, False, parent_id))
  137.  
  138.             if parent:
  139.                 parent.add_folder(node)
  140.  
  141.         self.free()
  142.         return root, errors
  143.  
  144.     def read_node(self):
  145.         length = self.fp.read(4)
  146.         if len(length) != 4:
  147.             return None
  148.  
  149.         length = unpack_i(length)
  150.         name = self.fp.read(length)
  151.         is_dir = unpack_b(self.fp.read(1))
  152.         id = unpack_i(self.fp.read(4))
  153.         parent_id = unpack_i(self.fp.read(4))
  154.  
  155.         return name, is_dir, id, parent_id
  156.  
  157.     def iter_nodes(self):
  158.         while True:
  159.             data = self.read_node()
  160.             if not data:
  161.                 break
  162.             else:
  163.                 yield data
  164.  
  165. class Writer(Base):
  166.  
  167.     def write(self, fp, node):
  168.         self.init(fp)
  169.         self.write_hierarchy(node)
  170.         self.free()
  171.  
  172.     def write_hierarchy(self, node, id=1, parent_id=0):
  173.         for child in node.folders:
  174.             self.write_node(child.name, True, id, parent_id)
  175.             curr_id = id
  176.             id += 1
  177.  
  178.             for filename in child.files:
  179.                 self.write_node(filename, False, id, curr_id)
  180.                 id += 1
  181.  
  182.             self.write_hierarchy(child, id, curr_id)
  183.  
  184.     def write_node(self, name, isdir, id, parent_id):
  185.         self.fp.write(pack_i(len(name)))
  186.         self.fp.write(name)
  187.         self.fp.write(pack_b(isdir))
  188.         self.fp.write(pack_i(id))
  189.         self.fp.write(pack_i(parent_id))
  190.  
  191. def collect_nodes(dirname, dest_node=None):
  192.     if not dest_node:
  193.         dest_node = Node('<root>')
  194.  
  195.     for name in os.listdir(dirname):
  196.         name = os.path.join(dirname, name)
  197.         if os.path.isdir(name):
  198.             node = Node(name)
  199.             collect_nodes(name, node)
  200.             dest_node.add_folder(node)
  201.         else:
  202.             dest_node.add_file(name)
  203.  
  204.     return dest_node
  205.  
  206. def main():
  207.     parser = argparse.ArgumentParser()
  208.     parser.add_argument('-i', '--input', nargs='?', default=None)
  209.     parser.add_argument('-s', '--source', nargs='?', default=os.getcwd())
  210.     parser.add_argument('-o', '--output', nargs='?', default='<out>')
  211.     args = parser.parse_args()
  212.  
  213.     if args.output == '<out>':
  214.         out = sys.stdout
  215.     else:
  216.         out = open(args.output, 'wb')
  217.  
  218.     if args.input:
  219.         fp = open(args.input, 'rb')
  220.         reader = Reader()
  221.         root, errors = reader.read(fp)
  222.         root.format(out)
  223.  
  224.         if not errors:
  225.             print "No errors in file", args.input
  226.         else:
  227.             for error in errors:
  228.                 print error.format()
  229.  
  230.     else:
  231.         if not os.path.isdir(args.source):
  232.             parser.error("path is not a directory")
  233.  
  234.  
  235.  
  236.         node = collect_nodes(args.source)
  237.         writer = Writer()
  238.         writer.write(out, node)
  239.  
  240. if __name__ == '__main__':
  241.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement