From 4c86254bd0af752727e56ff984d189064ccf2a88 Mon Sep 17 00:00:00 2001 From: Daniel Gnoutcheff Date: Wed, 29 Jun 2016 16:36:14 -0400 Subject: Split AVFS stuff into its own module. --- avfs.py | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 avfs.py (limited to 'avfs.py') diff --git a/avfs.py b/avfs.py new file mode 100644 index 0000000..fda6c72 --- /dev/null +++ b/avfs.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +""" +Traversing directories and archives with AVFS/fuse +""" + +import os +import os.path +import subprocess + +avfs_sys_mount = os.environ['HOME'] + '/.avfs' +avfs_started = False + +def sys_name(fpath): + global avfs_started + if not avfs_started: + subprocess.check_call(['mountavfs']) + avfs_started = True + return avfs_sys_mount + os.path.abspath(fpath) + +def exists(fpath): + return os.path.exists(sys_name(fpath)) + +def isdir(fpath): + return os.path.isdir(sys_name(fpath)) + +orig_open = open +def open(fpath, *pargs, **kwargs): + return orig_open(sys_name(fpath), *pargs, **kwargs) + +# AVFS has its own automatic view selection using file extensions, but it +# includes plugins (like #patch) that will lead us into an infinite loop +# if we try to do a directory traversal. Also, there are a few +# extensions we want to add. + +avfscmds = { + ('.gz', '#ugz'), + ('.tgz', '#ugz#utar'), + ('.tar.bz2', '#ubz2#utar'), + ('.bz2', '#ubz2'), + ('.bz', '#ubz2'), + ('.tbz2', '#ubz2#utar'), + ('.tbz', '#ubz2#utar'), + ('.Z', '#uz'), + ('.tpz', '#uz#utar'), + ('.tz', '#uz#utar'), + ('.taz', '#uz#utar'), + ('.a', '#uar'), + ('.deb', '#uar'), + ('.tar', '#utar'), + ('.gem', '#utar'), # Add upstream + ('.rar', '#urar'), + ('.sfx', '#urar'), + ('.zip', '#uzip'), + ('.jar', '#uzip'), + ('.ear', '#uzip'), + ('.war', '#uzip'), + ('.nupkg', '#uzip'), # Add upstream + ('.whl', '#uzip'), # Add upstream + ('.7z', '#u7z'), + ('.zoo', '#uzoo'), + ('.lha', '#ulha'), + ('.lhz', '#ulha'), + ('.arj', '#uarj'), + ('.cpio', '#ucpio'), + ('.rpm', '#rpm'), + ('.tar.xz', '#uxze#utar'), + ('.txz', '#uxze#utar'), + ('.xz', '#uxze'), + ('.lzma', '#uxze'), +} + +def guesscmd(filename): + for ext, cmd in avfscmds: + if filename.endswith(ext): + return cmd + guesscmd(filename[:-len(ext)]) + return '' + +def find(rootdir, prunedirs): + """ + Recursively list all files under rootdir, including files in archives + supported by AVFS. + """ + + sys_rootdir = sys_name(rootdir) + + for name in os.listdir(sys_rootdir): + path = rootdir + '/' + name + sys_path = sys_rootdir + '/' + name + + if os.path.isdir(sys_path): + if name not in prunedirs: + yield from find(path, prunedirs) + else: + cmd = guesscmd(name) + filtered_path = path + cmd + sys_filtered_path = sys_path + cmd + + if cmd and os.path.exists(sys_filtered_path): + if os.path.isdir(sys_filtered_path): + yield from find(filtered_path, prunedirs) + else: + yield filtered_path + else: + yield path + +if __name__ == "__main__": + import sys + for f in find(sys.argv[1], {'.git'}): + print(f) -- cgit v1.2.1