mercurial/hgweb/hgweb_mod.py
changeset 4462 12e4d9524951
parent 4458 e19d9b1223ee
child 4469 8af65bc092b0
equal deleted inserted replaced
4461:3e679426dd7f 4462:12e4d9524951
    10 import tempfile, urllib, bz2
    10 import tempfile, urllib, bz2
    11 from mercurial.node import *
    11 from mercurial.node import *
    12 from mercurial.i18n import gettext as _
    12 from mercurial.i18n import gettext as _
    13 from mercurial import mdiff, ui, hg, util, archival, streamclone, patch
    13 from mercurial import mdiff, ui, hg, util, archival, streamclone, patch
    14 from mercurial import revlog, templater
    14 from mercurial import revlog, templater
    15 from common import get_mtime, staticfile, style_map
    15 from common import get_mtime, staticfile, style_map, paritygen
    16 
    16 
    17 def _up(p):
    17 def _up(p):
    18     if p[0] != "/":
    18     if p[0] != "/":
    19         p = "/" + p
    19         p = "/" + p
    20     if p[-1] == "/":
    20     if p[-1] == "/":
   145                 if t and t[-1] != os.sep:
   145                 if t and t[-1] != os.sep:
   146                     t += os.sep
   146                     t += os.sep
   147                 l += [x for x in files if x.startswith(t)]
   147                 l += [x for x in files if x.startswith(t)]
   148             return l
   148             return l
   149 
   149 
   150         parity = [0]
   150         parity = paritygen(self.stripecount)
   151         def diffblock(diff, f, fn):
   151         def diffblock(diff, f, fn):
   152             yield self.t("diffblock",
   152             yield self.t("diffblock",
   153                          lines=prettyprintlines(diff),
   153                          lines=prettyprintlines(diff),
   154                          parity=parity[0],
   154                          parity=parity.next(),
   155                          file=f,
   155                          file=f,
   156                          filenode=hex(fn or nullid))
   156                          filenode=hex(fn or nullid))
   157             parity[0] = 1 - parity[0]
       
   158 
   157 
   159         def prettyprintlines(diff):
   158         def prettyprintlines(diff):
   160             for l in diff.splitlines(1):
   159             for l in diff.splitlines(1):
   161                 if l.startswith('+'):
   160                 if l.startswith('+'):
   162                     yield self.t("difflineplus", line=l)
   161                     yield self.t("difflineplus", line=l)
   195             yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
   194             yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
   196                                           opts=diffopts), f, tn)
   195                                           opts=diffopts), f, tn)
   197 
   196 
   198     def changelog(self, ctx, shortlog=False):
   197     def changelog(self, ctx, shortlog=False):
   199         def changelist(**map):
   198         def changelist(**map):
   200             parity = (start - end) & 1
       
   201             cl = self.repo.changelog
   199             cl = self.repo.changelog
   202             l = [] # build a list in forward order for efficiency
   200             l = [] # build a list in forward order for efficiency
   203             for i in xrange(start, end):
   201             for i in xrange(start, end):
   204                 ctx = self.repo.changectx(i)
   202                 ctx = self.repo.changectx(i)
   205                 n = ctx.node()
   203                 n = ctx.node()
   206 
   204 
   207                 l.insert(0, {"parity": parity,
   205                 l.insert(0, {"parity": parity.next(),
   208                              "author": ctx.user(),
   206                              "author": ctx.user(),
   209                              "parent": self.siblings(ctx.parents(), i - 1),
   207                              "parent": self.siblings(ctx.parents(), i - 1),
   210                              "child": self.siblings(ctx.children(), i + 1),
   208                              "child": self.siblings(ctx.children(), i + 1),
   211                              "changelogtag": self.showtag("changelogtag",n),
   209                              "changelogtag": self.showtag("changelogtag",n),
   212                              "desc": ctx.description(),
   210                              "desc": ctx.description(),
   213                              "date": ctx.date(),
   211                              "date": ctx.date(),
   214                              "files": self.listfilediffs(ctx.files(), n),
   212                              "files": self.listfilediffs(ctx.files(), n),
   215                              "rev": i,
   213                              "rev": i,
   216                              "node": hex(n)})
   214                              "node": hex(n)})
   217                 parity = 1 - parity
       
   218 
   215 
   219             for e in l:
   216             for e in l:
   220                 yield e
   217                 yield e
   221 
   218 
   222         maxchanges = shortlog and self.maxshortchanges or self.maxchanges
   219         maxchanges = shortlog and self.maxshortchanges or self.maxchanges
   224         count = cl.count()
   221         count = cl.count()
   225         pos = ctx.rev()
   222         pos = ctx.rev()
   226         start = max(0, pos - maxchanges + 1)
   223         start = max(0, pos - maxchanges + 1)
   227         end = min(count, start + maxchanges)
   224         end = min(count, start + maxchanges)
   228         pos = end - 1
   225         pos = end - 1
       
   226         parity = paritygen(self.stripecount, offset=start-end)
   229 
   227 
   230         changenav = revnavgen(pos, maxchanges, count, self.repo.changectx)
   228         changenav = revnavgen(pos, maxchanges, count, self.repo.changectx)
   231 
   229 
   232         yield self.t(shortlog and 'shortlog' or 'changelog',
   230         yield self.t(shortlog and 'shortlog' or 'changelog',
   233                      changenav=changenav,
   231                      changenav=changenav,
   265 
   263 
   266                 count += 1
   264                 count += 1
   267                 n = ctx.node()
   265                 n = ctx.node()
   268 
   266 
   269                 yield self.t('searchentry',
   267                 yield self.t('searchentry',
   270                              parity=self.stripes(count),
   268                              parity=parity.next(),
   271                              author=ctx.user(),
   269                              author=ctx.user(),
   272                              parent=self.siblings(ctx.parents()),
   270                              parent=self.siblings(ctx.parents()),
   273                              child=self.siblings(ctx.children()),
   271                              child=self.siblings(ctx.children()),
   274                              changelogtag=self.showtag("changelogtag",n),
   272                              changelogtag=self.showtag("changelogtag",n),
   275                              desc=ctx.description(),
   273                              desc=ctx.description(),
   280 
   278 
   281                 if count >= self.maxchanges:
   279                 if count >= self.maxchanges:
   282                     break
   280                     break
   283 
   281 
   284         cl = self.repo.changelog
   282         cl = self.repo.changelog
       
   283         parity = paritygen(self.stripecount)
   285 
   284 
   286         yield self.t('search',
   285         yield self.t('search',
   287                      query=query,
   286                      query=query,
   288                      node=hex(cl.tip()),
   287                      node=hex(cl.tip()),
   289                      entries=changelist)
   288                      entries=changelist)
   292         n = ctx.node()
   291         n = ctx.node()
   293         parents = ctx.parents()
   292         parents = ctx.parents()
   294         p1 = parents[0].node()
   293         p1 = parents[0].node()
   295 
   294 
   296         files = []
   295         files = []
   297         parity = 0
   296         parity = paritygen(self.stripecount)
   298         for f in ctx.files():
   297         for f in ctx.files():
   299             files.append(self.t("filenodelink",
   298             files.append(self.t("filenodelink",
   300                                 node=hex(n), file=f,
   299                                 node=hex(n), file=f,
   301                                 parity=parity))
   300                                 parity=parity.next()))
   302             parity = 1 - parity
       
   303 
   301 
   304         def diff(**map):
   302         def diff(**map):
   305             yield self.diff(p1, n, None)
   303             yield self.diff(p1, n, None)
   306 
   304 
   307         yield self.t('changeset',
   305         yield self.t('changeset',
   324         pagelen = self.maxshortchanges
   322         pagelen = self.maxshortchanges
   325         pos = fctx.filerev()
   323         pos = fctx.filerev()
   326         start = max(0, pos - pagelen + 1)
   324         start = max(0, pos - pagelen + 1)
   327         end = min(count, start + pagelen)
   325         end = min(count, start + pagelen)
   328         pos = end - 1
   326         pos = end - 1
       
   327         parity = paritygen(self.stripecount, offset=start-end)
   329 
   328 
   330         def entries(**map):
   329         def entries(**map):
   331             l = []
   330             l = []
   332             parity = (count - 1) & 1
       
   333 
   331 
   334             for i in xrange(start, end):
   332             for i in xrange(start, end):
   335                 ctx = fctx.filectx(i)
   333                 ctx = fctx.filectx(i)
   336                 n = fl.node(i)
   334                 n = fl.node(i)
   337 
   335 
   338                 l.insert(0, {"parity": parity,
   336                 l.insert(0, {"parity": parity.next(),
   339                              "filerev": i,
   337                              "filerev": i,
   340                              "file": f,
   338                              "file": f,
   341                              "node": hex(ctx.node()),
   339                              "node": hex(ctx.node()),
   342                              "author": ctx.user(),
   340                              "author": ctx.user(),
   343                              "date": ctx.date(),
   341                              "date": ctx.date(),
   344                              "rename": self.renamelink(fl, n),
   342                              "rename": self.renamelink(fl, n),
   345                              "parent": self.siblings(fctx.parents()),
   343                              "parent": self.siblings(fctx.parents()),
   346                              "child": self.siblings(fctx.children()),
   344                              "child": self.siblings(fctx.children()),
   347                              "desc": ctx.description()})
   345                              "desc": ctx.description()})
   348                 parity = 1 - parity
       
   349 
   346 
   350             for e in l:
   347             for e in l:
   351                 yield e
   348                 yield e
   352 
   349 
   353         nodefunc = lambda x: fctx.filectx(fileid=x)
   350         nodefunc = lambda x: fctx.filectx(fileid=x)
   358     def filerevision(self, fctx):
   355     def filerevision(self, fctx):
   359         f = fctx.path()
   356         f = fctx.path()
   360         text = fctx.data()
   357         text = fctx.data()
   361         fl = fctx.filelog()
   358         fl = fctx.filelog()
   362         n = fctx.filenode()
   359         n = fctx.filenode()
       
   360         parity = paritygen(self.stripecount)
   363 
   361 
   364         mt = mimetypes.guess_type(f)[0]
   362         mt = mimetypes.guess_type(f)[0]
   365         rawtext = text
   363         rawtext = text
   366         if util.binary(text):
   364         if util.binary(text):
   367             mt = mt or 'application/octet-stream'
   365             mt = mt or 'application/octet-stream'
   370 
   368 
   371         def lines():
   369         def lines():
   372             for l, t in enumerate(text.splitlines(1)):
   370             for l, t in enumerate(text.splitlines(1)):
   373                 yield {"line": t,
   371                 yield {"line": t,
   374                        "linenumber": "% 6d" % (l + 1),
   372                        "linenumber": "% 6d" % (l + 1),
   375                        "parity": self.stripes(l)}
   373                        "parity": parity.next()}
   376 
   374 
   377         yield self.t("filerevision",
   375         yield self.t("filerevision",
   378                      file=f,
   376                      file=f,
   379                      path=_up(f),
   377                      path=_up(f),
   380                      text=lines(),
   378                      text=lines(),
   392 
   390 
   393     def fileannotate(self, fctx):
   391     def fileannotate(self, fctx):
   394         f = fctx.path()
   392         f = fctx.path()
   395         n = fctx.filenode()
   393         n = fctx.filenode()
   396         fl = fctx.filelog()
   394         fl = fctx.filelog()
       
   395         parity = paritygen(self.stripecount)
   397 
   396 
   398         def annotate(**map):
   397         def annotate(**map):
   399             parity = 0
       
   400             last = None
   398             last = None
   401             for f, l in fctx.annotate(follow=True):
   399             for f, l in fctx.annotate(follow=True):
   402                 fnode = f.filenode()
   400                 fnode = f.filenode()
   403                 name = self.repo.ui.shortuser(f.user())
   401                 name = self.repo.ui.shortuser(f.user())
   404 
   402 
   405                 if last != fnode:
   403                 if last != fnode:
   406                     parity = 1 - parity
       
   407                     last = fnode
   404                     last = fnode
   408 
   405 
   409                 yield {"parity": parity,
   406                 yield {"parity": parity.next(),
   410                        "node": hex(f.node()),
   407                        "node": hex(f.node()),
   411                        "rev": f.rev(),
   408                        "rev": f.rev(),
   412                        "author": name,
   409                        "author": name,
   413                        "file": f.path(),
   410                        "file": f.path(),
   414                        "line": l}
   411                        "line": l}
   430     def manifest(self, ctx, path):
   427     def manifest(self, ctx, path):
   431         mf = ctx.manifest()
   428         mf = ctx.manifest()
   432         node = ctx.node()
   429         node = ctx.node()
   433 
   430 
   434         files = {}
   431         files = {}
       
   432         parity = paritygen(self.stripecount)
   435 
   433 
   436         if path and path[-1] != "/":
   434         if path and path[-1] != "/":
   437             path += "/"
   435             path += "/"
   438         l = len(path)
   436         l = len(path)
   439         abspath = "/" + path
   437         abspath = "/" + path
   448             else:
   446             else:
   449                 short = os.path.basename(remain)
   447                 short = os.path.basename(remain)
   450                 files[short] = (f, n)
   448                 files[short] = (f, n)
   451 
   449 
   452         def filelist(**map):
   450         def filelist(**map):
   453             parity = 0
       
   454             fl = files.keys()
   451             fl = files.keys()
   455             fl.sort()
   452             fl.sort()
   456             for f in fl:
   453             for f in fl:
   457                 full, fnode = files[f]
   454                 full, fnode = files[f]
   458                 if not fnode:
   455                 if not fnode:
   459                     continue
   456                     continue
   460 
   457 
   461                 yield {"file": full,
   458                 yield {"file": full,
   462                        "parity": self.stripes(parity),
   459                        "parity": parity.next(),
   463                        "basename": f,
   460                        "basename": f,
   464                        "size": ctx.filectx(full).size(),
   461                        "size": ctx.filectx(full).size(),
   465                        "permissions": mf.execf(full)}
   462                        "permissions": mf.execf(full)}
   466                 parity += 1
       
   467 
   463 
   468         def dirlist(**map):
   464         def dirlist(**map):
   469             parity = 0
       
   470             fl = files.keys()
   465             fl = files.keys()
   471             fl.sort()
   466             fl.sort()
   472             for f in fl:
   467             for f in fl:
   473                 full, fnode = files[f]
   468                 full, fnode = files[f]
   474                 if fnode:
   469                 if fnode:
   475                     continue
   470                     continue
   476 
   471 
   477                 yield {"parity": self.stripes(parity),
   472                 yield {"parity": parity.next(),
   478                        "path": os.path.join(abspath, f),
   473                        "path": os.path.join(abspath, f),
   479                        "basename": f[:-1]}
   474                        "basename": f[:-1]}
   480                 parity += 1
       
   481 
   475 
   482         yield self.t("manifest",
   476         yield self.t("manifest",
   483                      rev=ctx.rev(),
   477                      rev=ctx.rev(),
   484                      node=hex(node),
   478                      node=hex(node),
   485                      path=abspath,
   479                      path=abspath,
   486                      up=_up(abspath),
   480                      up=_up(abspath),
   487                      upparity=self.stripes(0),
   481                      upparity=parity.next(),
   488                      fentries=filelist,
   482                      fentries=filelist,
   489                      dentries=dirlist,
   483                      dentries=dirlist,
   490                      archives=self.archivelist(hex(node)))
   484                      archives=self.archivelist(hex(node)))
   491 
   485 
   492     def tags(self):
   486     def tags(self):
   493         i = self.repo.tagslist()
   487         i = self.repo.tagslist()
   494         i.reverse()
   488         i.reverse()
       
   489         parity = paritygen(self.stripecount)
   495 
   490 
   496         def entries(notip=False, **map):
   491         def entries(notip=False, **map):
   497             parity = 0
       
   498             for k, n in i:
   492             for k, n in i:
   499                 if notip and k == "tip":
   493                 if notip and k == "tip":
   500                     continue
   494                     continue
   501                 yield {"parity": self.stripes(parity),
   495                 yield {"parity": parity.next(),
   502                        "tag": k,
   496                        "tag": k,
   503                        "date": self.repo.changectx(n).date(),
   497                        "date": self.repo.changectx(n).date(),
   504                        "node": hex(n)}
   498                        "node": hex(n)}
   505                 parity += 1
       
   506 
   499 
   507         yield self.t("tags",
   500         yield self.t("tags",
   508                      node=hex(self.repo.changelog.tip()),
   501                      node=hex(self.repo.changelog.tip()),
   509                      entries=lambda **x: entries(False, **x),
   502                      entries=lambda **x: entries(False, **x),
   510                      entriesnotip=lambda **x: entries(True, **x))
   503                      entriesnotip=lambda **x: entries(True, **x))
   512     def summary(self):
   505     def summary(self):
   513         i = self.repo.tagslist()
   506         i = self.repo.tagslist()
   514         i.reverse()
   507         i.reverse()
   515 
   508 
   516         def tagentries(**map):
   509         def tagentries(**map):
   517             parity = 0
   510             parity = paritygen(self.stripecount)
   518             count = 0
   511             count = 0
   519             for k, n in i:
   512             for k, n in i:
   520                 if k == "tip": # skip tip
   513                 if k == "tip": # skip tip
   521                     continue;
   514                     continue;
   522 
   515 
   523                 count += 1
   516                 count += 1
   524                 if count > 10: # limit to 10 tags
   517                 if count > 10: # limit to 10 tags
   525                     break;
   518                     break;
   526 
   519 
   527                 yield self.t("tagentry",
   520                 yield self.t("tagentry",
   528                              parity=self.stripes(parity),
   521                              parity=parity.next(),
   529                              tag=k,
   522                              tag=k,
   530                              node=hex(n),
   523                              node=hex(n),
   531                              date=self.repo.changectx(n).date())
   524                              date=self.repo.changectx(n).date())
   532                 parity += 1
       
   533 
   525 
   534 
   526 
   535         def branches(**map):
   527         def branches(**map):
   536             parity = 0
   528             parity = paritygen(self.stripecount)
   537 
   529 
   538             b = self.repo.branchtags()
   530             b = self.repo.branchtags()
   539             l = [(-self.repo.changelog.rev(n), n, t) for t, n in b.items()]
   531             l = [(-self.repo.changelog.rev(n), n, t) for t, n in b.items()]
   540             l.sort()
   532             l.sort()
   541 
   533 
   542             for r,n,t in l:
   534             for r,n,t in l:
   543                 ctx = self.repo.changectx(n)
   535                 ctx = self.repo.changectx(n)
   544 
   536 
   545                 yield {'parity': self.stripes(parity),
   537                 yield {'parity': parity.next(),
   546                        'branch': t,
   538                        'branch': t,
   547                        'node': hex(n),
   539                        'node': hex(n),
   548                        'date': ctx.date()}
   540                        'date': ctx.date()}
   549                 parity += 1
       
   550 
   541 
   551         def changelist(**map):
   542         def changelist(**map):
   552             parity = 0
   543             parity = paritygen(self.stripecount, offset=start-end)
   553             l = [] # build a list in forward order for efficiency
   544             l = [] # build a list in forward order for efficiency
   554             for i in xrange(start, end):
   545             for i in xrange(start, end):
   555                 ctx = self.repo.changectx(i)
   546                 ctx = self.repo.changectx(i)
   556                 hn = hex(ctx.node())
   547                 hn = hex(ctx.node())
   557 
   548 
   558                 l.insert(0, self.t(
   549                 l.insert(0, self.t(
   559                     'shortlogentry',
   550                     'shortlogentry',
   560                     parity=parity,
   551                     parity=parity.next(),
   561                     author=ctx.user(),
   552                     author=ctx.user(),
   562                     desc=ctx.description(),
   553                     desc=ctx.description(),
   563                     date=ctx.date(),
   554                     date=ctx.date(),
   564                     rev=i,
   555                     rev=i,
   565                     node=hn))
   556                     node=hn))
   566                 parity = 1 - parity
       
   567 
   557 
   568             yield l
   558             yield l
   569 
   559 
   570         cl = self.repo.changelog
   560         cl = self.repo.changelog
   571         count = cl.count()
   561         count = cl.count()
   843             fctx = ctx.filectx(path)
   833             fctx = ctx.filectx(path)
   844         except hg.RepoError:
   834         except hg.RepoError:
   845             fctx = self.repo.filectx(path, fileid=changeid)
   835             fctx = self.repo.filectx(path, fileid=changeid)
   846 
   836 
   847         return fctx
   837         return fctx
   848 
       
   849     def stripes(self, parity):
       
   850         "make horizontal stripes for easier reading"
       
   851         if self.stripecount:
       
   852             return (1 + parity / self.stripecount) & 1
       
   853         else:
       
   854             return 0
       
   855 
   838 
   856     def do_log(self, req):
   839     def do_log(self, req):
   857         if req.form.has_key('file') and req.form['file'][0]:
   840         if req.form.has_key('file') and req.form['file'][0]:
   858             self.do_filelog(req)
   841             self.do_filelog(req)
   859         else:
   842         else: