comparison mercurial/hgweb/webutil.py @ 17991:d605a82cf189

hgweb: display diff for a changeset against any parents (issue2810) During merge of branches, it is useful to compare merge results against the two parents. This change adds this support to hgweb. To specify which parent to compare to, use rev/12300:12345 where 12300 is a parent changeset number. Two links are added to changeset web page so that one can choose which parent to compare to.
author Weiwen <weiwen@fb.com>
date Mon, 12 Nov 2012 14:05:39 -0800
parents 5c64ce6168da
children 60680d691a0b
comparison
equal deleted inserted replaced
17990:8216eb592dcd 17991:d605a82cf189
138 138
139 def cleanpath(repo, path): 139 def cleanpath(repo, path):
140 path = path.lstrip('/') 140 path = path.lstrip('/')
141 return scmutil.canonpath(repo.root, '', path) 141 return scmutil.canonpath(repo.root, '', path)
142 142
143 def changectx(repo, req): 143 def changeidctx (repo, changeid):
144 changeid = "tip"
145 if 'node' in req.form:
146 changeid = req.form['node'][0]
147 elif 'manifest' in req.form:
148 changeid = req.form['manifest'][0]
149
150 try: 144 try:
151 ctx = repo[changeid] 145 ctx = repo[changeid]
152 except error.RepoError: 146 except error.RepoError:
153 man = repo.manifest 147 man = repo.manifest
154 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))] 148 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
155 149
156 return ctx 150 return ctx
151
152 def changectx (repo, req):
153 changeid = "tip"
154 if 'node' in req.form:
155 changeid = req.form['node'][0]
156 ipos=changeid.find(':')
157 if ipos != -1:
158 changeid = changeid[(ipos + 1):]
159 elif 'manifest' in req.form:
160 changeid = req.form['manifest'][0]
161
162 return changeidctx(repo, changeid)
163
164 def basechangectx(repo, req):
165 if 'node' in req.form:
166 changeid = req.form['node'][0]
167 ipos=changeid.find(':')
168 if ipos != -1:
169 changeid = changeid[:ipos]
170 return changeidctx(repo, changeid)
171
172 return None
157 173
158 def filectx(repo, req): 174 def filectx(repo, req):
159 if 'file' not in req.form: 175 if 'file' not in req.form:
160 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given') 176 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
161 path = cleanpath(repo, req.form['file'][0]) 177 path = cleanpath(repo, req.form['file'][0])
176 for f in files[:max]: 192 for f in files[:max]:
177 yield tmpl('filedifflink', node=hex(node), file=f) 193 yield tmpl('filedifflink', node=hex(node), file=f)
178 if len(files) > max: 194 if len(files) > max:
179 yield tmpl('fileellipses') 195 yield tmpl('fileellipses')
180 196
181 def diffs(repo, tmpl, ctx, files, parity, style): 197 def diffs(repo, tmpl, ctx, basectx, files, parity, style):
182 198
183 def countgen(): 199 def countgen():
184 start = 1 200 start = 1
185 while True: 201 while True:
186 yield start 202 yield start
207 m = match.exact(repo.root, repo.getcwd(), files) 223 m = match.exact(repo.root, repo.getcwd(), files)
208 else: 224 else:
209 m = match.always(repo.root, repo.getcwd()) 225 m = match.always(repo.root, repo.getcwd())
210 226
211 diffopts = patch.diffopts(repo.ui, untrusted=True) 227 diffopts = patch.diffopts(repo.ui, untrusted=True)
212 parents = ctx.parents() 228 if basectx is None:
213 node1 = parents and parents[0].node() or nullid 229 parents = ctx.parents()
230 node1 = parents and parents[0].node() or nullid
231 else:
232 node1 = basectx.node()
214 node2 = ctx.node() 233 node2 = ctx.node()
215 234
216 block = [] 235 block = []
217 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts): 236 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
218 if chunk.startswith('diff') and block: 237 if chunk.startswith('diff') and block:
272 yield tmpl('comparisonblock', lines=getblock(s.get_opcodes())) 291 yield tmpl('comparisonblock', lines=getblock(s.get_opcodes()))
273 else: 292 else:
274 for oc in s.get_grouped_opcodes(n=context): 293 for oc in s.get_grouped_opcodes(n=context):
275 yield tmpl('comparisonblock', lines=getblock(oc)) 294 yield tmpl('comparisonblock', lines=getblock(oc))
276 295
277 def diffstatgen(ctx): 296 def diffstatgen(ctx, basectx):
278 '''Generator function that provides the diffstat data.''' 297 '''Generator function that provides the diffstat data.'''
279 298
280 stats = patch.diffstatdata(util.iterlines(ctx.diff())) 299 stats = patch.diffstatdata(util.iterlines(ctx.diff(basectx)))
281 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats) 300 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
282 while True: 301 while True:
283 yield stats, maxname, maxtotal, addtotal, removetotal, binary 302 yield stats, maxname, maxtotal, addtotal, removetotal, binary
284 303
285 def diffsummary(statgen): 304 def diffsummary(statgen):