##// END OF EJS Templates
hgwebdir: try to get web.style and web.motd from the ui.config system...
Alexis S. L. Carvalho -
r4080:ef14fdb6 default
parent child Browse files
Show More
@@ -1,216 +1,224
1 1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 9 import os
10 10 from mercurial.demandload import demandload
11 11 demandload(globals(), "mimetools cStringIO")
12 12 demandload(globals(), "mercurial:ui,hg,util,templater")
13 13 demandload(globals(), "mercurial.hgweb.hgweb_mod:hgweb")
14 14 demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile,style_map")
15 15 from mercurial.i18n import gettext as _
16 16
17 17 # This is a stopgap
18 18 class hgwebdir(object):
19 19 def __init__(self, config, parentui=None):
20 20 def cleannames(items):
21 21 return [(name.strip(os.sep), path) for name, path in items]
22 22
23 23 self.parentui = parentui
24 self.motd = ""
25 self.style = ""
24 self.motd = None
25 self.style = None
26 26 self.repos_sorted = ('name', False)
27 27 if isinstance(config, (list, tuple)):
28 28 self.repos = cleannames(config)
29 29 self.repos_sorted = ('', False)
30 30 elif isinstance(config, dict):
31 31 self.repos = cleannames(config.items())
32 32 self.repos.sort()
33 33 else:
34 34 cp = util.configparser()
35 35 cp.read(config)
36 36 self.repos = []
37 37 if cp.has_section('web'):
38 38 if cp.has_option('web', 'motd'):
39 39 self.motd = cp.get('web', 'motd')
40 40 if cp.has_option('web', 'style'):
41 41 self.style = cp.get('web', 'style')
42 42 if cp.has_section('paths'):
43 43 self.repos.extend(cleannames(cp.items('paths')))
44 44 if cp.has_section('collections'):
45 45 for prefix, root in cp.items('collections'):
46 46 for path in util.walkrepos(root):
47 47 repo = os.path.normpath(path)
48 48 name = repo
49 49 if name.startswith(prefix):
50 50 name = name[len(prefix):]
51 51 self.repos.append((name.lstrip(os.sep), repo))
52 52 self.repos.sort()
53 53
54 54 def run(self):
55 55 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
56 56 raise RuntimeError("This function is only intended to be called while running as a CGI script.")
57 57 import mercurial.hgweb.wsgicgi as wsgicgi
58 58 from request import wsgiapplication
59 59 def make_web_app():
60 60 return self
61 61 wsgicgi.launch(wsgiapplication(make_web_app))
62 62
63 63 def run_wsgi(self, req):
64 64 def header(**map):
65 65 header_file = cStringIO.StringIO(
66 66 ''.join(tmpl("header", encoding=util._encoding, **map)))
67 67 msg = mimetools.Message(header_file, 0)
68 68 req.header(msg.items())
69 69 yield header_file.read()
70 70
71 71 def footer(**map):
72 72 yield tmpl("footer", **map)
73 73
74 74 def motd(**map):
75 yield self.motd
75 if self.motd is not None:
76 yield self.motd
77 else:
78 yield config('web', 'motd', '')
76 79
77 80 parentui = self.parentui or ui.ui(report_untrusted=False)
78 81
82 def config(section, name, default=None, untrusted=True):
83 return parentui.config(section, name, default, untrusted)
84
79 85 url = req.env['REQUEST_URI'].split('?')[0]
80 86 if not url.endswith('/'):
81 87 url += '/'
82 88
83 89 style = self.style
90 if style is None:
91 style = config('web', 'style', '')
84 92 if req.form.has_key('style'):
85 93 style = req.form['style'][0]
86 94 mapfile = style_map(templater.templatepath(), style)
87 95 tmpl = templater.templater(mapfile, templater.common_filters,
88 96 defaults={"header": header,
89 97 "footer": footer,
90 98 "motd": motd,
91 99 "url": url})
92 100
93 101 def archivelist(ui, nodeid, url):
94 102 allowed = ui.configlist("web", "allow_archive", untrusted=True)
95 103 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
96 104 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
97 105 untrusted=True):
98 106 yield {"type" : i[0], "extension": i[1],
99 107 "node": nodeid, "url": url}
100 108
101 109 def entries(sortcolumn="", descending=False, **map):
102 110 def sessionvars(**map):
103 111 fields = []
104 112 if req.form.has_key('style'):
105 113 style = req.form['style'][0]
106 114 if style != get('web', 'style', ''):
107 115 fields.append(('style', style))
108 116
109 117 separator = url[-1] == '?' and ';' or '?'
110 118 for name, value in fields:
111 119 yield dict(name=name, value=value, separator=separator)
112 120 separator = ';'
113 121
114 122 rows = []
115 123 parity = 0
116 124 for name, path in self.repos:
117 125 u = ui.ui(parentui=parentui)
118 126 try:
119 127 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
120 128 except IOError:
121 129 pass
122 130 def get(section, name, default=None):
123 131 return u.config(section, name, default, untrusted=True)
124 132
125 133 url = ('/'.join([req.env["REQUEST_URI"].split('?')[0], name])
126 134 .replace("//", "/")) + '/'
127 135
128 136 # update time with local timezone
129 137 try:
130 138 d = (get_mtime(path), util.makedate()[1])
131 139 except OSError:
132 140 continue
133 141
134 142 contact = (get("ui", "username") or # preferred
135 143 get("web", "contact") or # deprecated
136 144 get("web", "author", "")) # also
137 145 description = get("web", "description", "")
138 146 name = get("web", "name", name)
139 147 row = dict(contact=contact or "unknown",
140 148 contact_sort=contact.upper() or "unknown",
141 149 name=name,
142 150 name_sort=name,
143 151 url=url,
144 152 description=description or "unknown",
145 153 description_sort=description.upper() or "unknown",
146 154 lastchange=d,
147 155 lastchange_sort=d[1]-d[0],
148 156 sessionvars=sessionvars,
149 157 archives=archivelist(u, "tip", url))
150 158 if (not sortcolumn
151 159 or (sortcolumn, descending) == self.repos_sorted):
152 160 # fast path for unsorted output
153 161 row['parity'] = parity
154 162 parity = 1 - parity
155 163 yield row
156 164 else:
157 165 rows.append((row["%s_sort" % sortcolumn], row))
158 166 if rows:
159 167 rows.sort()
160 168 if descending:
161 169 rows.reverse()
162 170 for key, row in rows:
163 171 row['parity'] = parity
164 172 parity = 1 - parity
165 173 yield row
166 174
167 175 virtual = req.env.get("PATH_INFO", "").strip('/')
168 176 if virtual.startswith('static/'):
169 177 static = os.path.join(templater.templatepath(), 'static')
170 178 fname = virtual[7:]
171 179 req.write(staticfile(static, fname, req) or
172 180 tmpl('error', error='%r not found' % fname))
173 181 elif virtual:
174 182 while virtual:
175 183 real = dict(self.repos).get(virtual)
176 184 if real:
177 185 break
178 186 up = virtual.rfind('/')
179 187 if up < 0:
180 188 break
181 189 virtual = virtual[:up]
182 190 if real:
183 191 req.env['REPO_NAME'] = virtual
184 192 try:
185 193 repo = hg.repository(parentui, real)
186 194 hgweb(repo).run_wsgi(req)
187 195 except IOError, inst:
188 196 req.write(tmpl("error", error=inst.strerror))
189 197 except hg.RepoError, inst:
190 198 req.write(tmpl("error", error=str(inst)))
191 199 else:
192 200 req.write(tmpl("notfound", repo=virtual))
193 201 else:
194 202 if req.form.has_key('static'):
195 203 static = os.path.join(templater.templatepath(), "static")
196 204 fname = req.form['static'][0]
197 205 req.write(staticfile(static, fname, req)
198 206 or tmpl("error", error="%r not found" % fname))
199 207 else:
200 208 sortable = ["name", "description", "contact", "lastchange"]
201 209 sortcolumn, descending = self.repos_sorted
202 210 if req.form.has_key('sort'):
203 211 sortcolumn = req.form['sort'][0]
204 212 descending = sortcolumn.startswith('-')
205 213 if descending:
206 214 sortcolumn = sortcolumn[1:]
207 215 if sortcolumn not in sortable:
208 216 sortcolumn = ""
209 217
210 218 sort = [("sort_%s" % column,
211 219 "%s%s" % ((not descending and column == sortcolumn)
212 220 and "-" or "", column))
213 221 for column in sortable]
214 222 req.write(tmpl("index", entries=entries,
215 223 sortcolumn=sortcolumn, descending=descending,
216 224 **dict(sort)))
General Comments 0
You need to be logged in to leave comments. Login now