blob: 6026a7c2ede54cd0bbba32c60bfe316630adcd0a [file] [log] [blame]
Phillip J. Eby069159b2006-04-18 04:05:34 +00001from distutils.command.sdist import sdist as _sdist
2from distutils.util import convert_path
3import os, re, sys, pkg_resources
4
5entities = [
6 ("&lt;","<"), ("&gt;", ">"), ("&quot;", '"'), ("&apos;", "'"),
7 ("&amp;", "&")
8]
9
10def unescape(data):
11 for old,new in entities:
12 data = data.replace(old,new)
13 return data
14
15def re_finder(pattern, postproc=None):
16 def find(dirname, filename):
17 f = open(filename,'rU')
18 data = f.read()
19 f.close()
20 for match in pattern.finditer(data):
21 path = match.group(1)
22 if postproc:
23 path = postproc(path)
24 yield joinpath(dirname,path)
25 return find
26
27def joinpath(prefix,suffix):
28 if not prefix:
29 return suffix
30 return os.path.join(prefix,suffix)
31
32
33
34
35
36
37
38
39
40
41
42def walk_revctrl(dirname=''):
43 """Find all files under revision control"""
44 for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):
45 for item in ep.load()(dirname):
46 yield item
47
48def _default_revctrl(dirname=''):
49 for path, finder in finders:
50 path = joinpath(dirname,path)
51 if os.path.isfile(path):
52 for path in finder(dirname,path):
53 if os.path.isfile(path):
54 yield path
55 elif os.path.isdir(path):
56 for item in _default_revctrl(path):
57 yield item
58
59def externals_finder(dirname, filename):
60 """Find any 'svn:externals' directories"""
61 found = False
62 f = open(filename,'rb')
63 for line in iter(f.readline, ''): # can't use direct iter!
64 parts = line.split()
65 if len(parts)==2:
66 kind,length = parts
67 data = f.read(int(length))
68 if kind=='K' and data=='svn:externals':
69 found = True
70 elif kind=='V' and found:
71 f.close()
72 break
73 else:
74 f.close()
75 return
76
77 for line in data.splitlines():
78 parts = line.split()
79 if parts:
80 yield joinpath(dirname, parts[0])
81
82
83finders = [
84 (convert_path('CVS/Entries'),
85 re_finder(re.compile(r"^\w?/([^/]+)/", re.M))),
86 (convert_path('.svn/entries'),
87 re_finder(
88 re.compile(r'name="([^"]+)"(?![^>]+deleted="true")', re.I),
89 unescape
90 )
91 ),
92 (convert_path('.svn/dir-props'), externals_finder),
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
124class sdist(_sdist):
125 """Smart sdist that finds anything supported by revision control"""
126
127 user_options = [
128 ('formats=', None,
129 "formats for source distribution (comma-separated list)"),
130 ('keep-temp', 'k',
131 "keep the distribution tree around after creating " +
132 "archive file(s)"),
133 ('dist-dir=', 'd',
134 "directory to put the source distribution archive(s) in "
135 "[default: dist]"),
136 ]
137
138 negative_opt = {}
139
140 def run(self):
141 self.run_command('egg_info')
142 ei_cmd = self.get_finalized_command('egg_info')
143 self.filelist = ei_cmd.filelist
144 self.filelist.append(os.path.join(ei_cmd.egg_info,'SOURCES.txt'))
145
146 self.check_metadata()
147 self.make_distribution()
148
149 dist_files = getattr(self.distribution,'dist_files',[])
150 for file in self.archive_files:
151 data = ('sdist', '', file)
152 if data not in dist_files:
153 dist_files.append(data)
154
155 def read_template(self):
156 try:
157 _sdist.read_template(self)
158 except:
159 # grody hack to close the template file (MANIFEST.in)
160 # this prevents easy_install's attempt at deleting the file from
161 # dying and thus masking the real error
162 sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close()
163 raise
164