summaryrefslogtreecommitdiff
path: root/avfs.py
blob: fda6c72634c281a14f0aeebf80b1f1b49a2c4b85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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)