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
111
112
113
114
115
116
117
118
119
120
121
122
123
|
from distutils.command.sdist import sdist as _sdist
from distutils.util import convert_path
import os,re
entities = [
("<","<"), (">", ">"), (""", '"'), ("'", "'"),
("&", "&")
]
def unescape(data):
for old,new in entities:
data = data.replace(old,new)
return data
def re_finder(pattern, postproc=None):
def find(dirname, filename):
f = open(filename,'rU')
data = f.read()
f.close()
for match in pattern.finditer(data):
path = match.group(1)
if postproc:
path = postproc(path)
yield joinpath(dirname,path)
return find
def joinpath(prefix,suffix):
if not prefix:
return suffix
return os.path.join(prefix,suffix)
def walk_revctrl(dirname='', memo=None):
"""Find all files under revision control"""
if memo is None:
memo = {}
if dirname in memo:
# Don't rescan a scanned directory
return
for path, finder in finders:
path = joinpath(dirname,path)
if os.path.isfile(path):
for path in finder(dirname,path):
if os.path.isfile(path):
yield path
elif os.path.isdir(path):
for item in walk_revctrl(path, memo):
yield item
def externals_finder(dirname, filename):
"""Find any 'svn:externals' directories"""
found = False
f = open(filename,'rb')
for line in iter(f.readline, ''): # can't use direct iter!
parts = line.split()
if len(parts)==2:
kind,length = parts
data = f.read(int(length))
if kind=='K' and data=='svn:externals':
found = True
elif kind=='V' and found:
f.close()
break
else:
f.close()
return
for line in data.splitlines():
parts = line.split()
if parts:
yield joinpath(dirname, parts[0])
finders = [
(convert_path('CVS/Entries'),
re_finder(re.compile(r"^\w?/([^/]+)/", re.M))),
(convert_path('.svn/entries'),
re_finder(
re.compile(r'name="([^"]+)"(?![^>]+deleted="true")', re.I),
unescape
)
),
(convert_path('.svn/dir-props'), externals_finder),
]
class sdist(_sdist):
"""Smart sdist that finds anything supported by revision control"""
def run(self):
self.run_command('egg_info')
_sdist.run(self)
dist_files = getattr(self.distribution,'dist_files',[])
for file in self.archive_files:
data = ('sdist', '', file)
if data not in dist_files:
dist_files.append(data)
def finalize_options(self):
_sdist.finalize_options(self)
if not os.path.isfile(self.template):
self.force_manifest = 1 # always regen if no template
def add_defaults(self):
_sdist.add_defaults(self)
self.filelist.extend(walk_revctrl())
|