Advertisement
Guest User

Trac #10640 patch

a guest
Mar 24th, 2012
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 23.81 KB | None | 0 0
  1. diff -urN -x '*.pyc' -x '*.svn*' -x '*.egg*' mercurial-plugin/setup.py mercurial-plugin-aliaspatch/setup.py
  2. --- mercurial-plugin/setup.py   2012-03-24 15:43:07.602219567 +0100
  3. +++ mercurial-plugin-aliaspatch/setup.py    2012-03-24 16:25:03.821921368 +0100
  4. @@ -32,7 +32,7 @@
  5.  
  6.  except ImportError:
  7.      pass
  8. -    
  9. +
  10.  TracMercurial = 'http://trac.edgewall.org/wiki/TracMercurial'
  11.  
  12.  setup(name='TracMercurial',
  13. @@ -55,5 +55,10 @@
  14.            '': ['COPYING', 'README'],
  15.            'tracext.hg': ['locale/*.*', 'locale/*/LC_MESSAGES/*.*'],
  16.            },
  17. -      entry_points={'trac.plugins': 'hg = tracext.hg.backend'},
  18. +      entry_points={
  19. +          'trac.plugins': [
  20. +              'tracext.hg.admin = tracext.hg.admin',
  21. +              'tracext.hg.backend = tracext.hg.backend',
  22. +          ]
  23. +      },
  24.        **extra)
  25. diff -urN -x '*.pyc' -x '*.svn*' -x '*.egg*' mercurial-plugin/tracext/hg/admin.py mercurial-plugin-aliaspatch/tracext/hg/admin.py
  26. --- mercurial-plugin/tracext/hg/admin.py    1970-01-01 01:00:00.000000000 +0100
  27. +++ mercurial-plugin-aliaspatch/tracext/hg/admin.py 2012-03-24 16:34:28.045531375 +0100
  28. @@ -0,0 +1,102 @@
  29. +from trac.core import Component, implements
  30. +from trac.perm import IPermissionRequestor
  31. +from trac.admin import IAdminPanelProvider
  32. +from trac.web.chrome import ITemplateProvider
  33. +from trac.util.translation import gettext as _
  34. +from pkg_resources import resource_filename
  35. +
  36. +try:
  37. +    from hashlib import sha1
  38. +except ImportError:
  39. +    from sha import new as sha1
  40. +
  41. +u = unicode
  42. +
  43. +class MercurialAliasAdminPage(Component):
  44. +
  45. +    implements(IAdminPanelProvider, IPermissionRequestor, ITemplateProvider)
  46. +
  47. +    def __init__(self):
  48. +        self.db = self.env.get_db_cnx()
  49. +
  50. +    # IPermissionRequestor
  51. +    def get_permission_actions(self):
  52. +        return ['HG_ALIAS_ADMIN']
  53. +
  54. +    # IAdminPanelProvider
  55. +    def get_admin_panels(self, req):
  56. +        #if req.perm.has_permission('HG_ALIAS_ADMIN'):
  57. +        yield ('versioncontrol', _("Version Control"), 'mercurialalias', _("Mercurial Aliases"))
  58. +
  59. +    # IAdminPanelProvider
  60. +    def render_admin_panel(self, req, cat, page, path_info):
  61. +        req.perm.require('HG_ALIAS_ADMIN')
  62. +
  63. +        if req.method == 'POST':
  64. +            if req.args.get('add'):
  65. +                self._add_alias(u(req.args.get('user')), u(req.args.get('alias')))
  66. +            elif req.args.get('remove') and req.args.get('sel'):
  67. +                sel = req.args.get('sel')
  68. +                sel = isinstance(sel, list) and sel or [sel]
  69. +                for r in sel:
  70. +                    user, key = r.rsplit('.', 1)
  71. +                    self._delete_alias_by_key(user, key)
  72. +
  73. +        data = {
  74. +            'aliases': self._list_aliases(),
  75. +        }
  76. +
  77. +        return 'admin_mercurialalias.html', data
  78. +
  79. +    def _list_aliases(self):
  80. +        cursor = self.db.cursor()
  81. +        cursor.execute("SELECT sid, name, value "
  82. +            "FROM session_attribute "
  83. +            "WHERE authenticated = 1 "
  84. +            "AND name LIKE 'mercurialalias.%' "
  85. +            "ORDER BY sid, value")
  86. +        for user, key, alias in cursor:
  87. +            yield dict(user=user, key=key.split('.', 1)[1], alias=alias)
  88. +
  89. +    def _get_alias(self, alias):
  90. +        cursor = self.db.cursor()
  91. +        cursor.execute("SELECT sid "
  92. +            "FROM session_attribute "
  93. +            "WHERE authenticated = 1 "
  94. +            "AND name LIKE 'mercurialalias.%' "
  95. +            "AND value = %s", (alias,))
  96. +        for sid, in cursor:
  97. +            return sid
  98. +
  99. +    def _add_alias(self, user, alias):
  100. +        if self._get_alias(alias):
  101. +            return False
  102. +        cursor = self.db.cursor()
  103. +        cursor.execute("INSERT INTO session_attribute (sid, authenticated, name, value) "
  104. +            "VALUES (%s, 1, %s, %s)", (user, self._gen_key(alias), alias))
  105. +        return True
  106. +
  107. +    def _delete_alias_by_key(self, user, key):
  108. +        cursor = self.db.cursor()
  109. +        cursor.execute("DELETE FROM session_attribute "
  110. +            "WHERE authenticated = 1 "
  111. +            "AND sid = %s "
  112. +            "AND name = %s", (user, 'mercurialalias.%s' % key))
  113. +
  114. +    def _delete_alias(self, alias):
  115. +        cursor = self.db.cursor()
  116. +        cursor.execute("DELETE FROM session_attribute "
  117. +            "WHERE authenticated = 1 "
  118. +            "AND name LIKE 'mercurialalias.%' "
  119. +            "AND value = %s", (alias,))
  120. +
  121. +    def _gen_key(self, alias):
  122. +        return u'mercurialalias.%s' % sha1(alias.encode('utf-8')).hexdigest()[:16]
  123. +
  124. +    # ITemplateProvider
  125. +    def get_htdocs_dirs(self):
  126. +        return []
  127. +
  128. +    # ITemplateProvider
  129. +    def get_templates_dirs(self):
  130. +        return [resource_filename(__name__, 'templates')]
  131. diff -urN -x '*.pyc' -x '*.svn*' -x '*.egg*' mercurial-plugin/tracext/hg/backend.py mercurial-plugin-aliaspatch/tracext/hg/backend.py
  132. --- mercurial-plugin/tracext/hg/backend.py  2012-03-24 15:43:07.662219243 +0100
  133. +++ mercurial-plugin-aliaspatch/tracext/hg/backend.py   2012-03-24 16:25:03.835254629 +0100
  134. @@ -57,7 +57,7 @@
  135.      # before loading mercurial modules, and desactivate it afterwards.
  136.      #
  137.      # See http://www.selenic.com/mercurial/bts/issue605
  138. -    
  139. +
  140.      try:
  141.          from mercurial import demandimport
  142.          demandimport.enable();
  143. @@ -93,7 +93,7 @@
  144.      # Force local encoding to be non-lossy (#7217)
  145.      os.environ['HGENCODING'] = 'utf-8'
  146.      encoding.tolocal = str
  147. -    
  148. +
  149.      if demandimport:
  150.          demandimport.disable()
  151.  
  152. @@ -105,7 +105,7 @@
  153.      else:
  154.          from mercurial.scmutil import match
  155.  
  156. -    
  157. +
  158.  except ImportError, e:
  159.      hg_import_error = e
  160.      ui = object
  161. @@ -140,14 +140,14 @@
  162.      if check(s):
  163.          return s
  164.  
  165. -        
  166. +
  167.  class trac_ui(ui):
  168.      # Note: will be dropped in 0.13, see MercurialConnector._setup_ui
  169.      def __init__(self, *args, **kwargs):
  170.          ui.__init__(self, *args)
  171.          self.setconfig('ui', 'interactive', 'off')
  172.          self.log = kwargs.get('log', args and args[0].log or None)
  173. -        
  174. +
  175.      def write(self, *args, **opts):
  176.          for a in args:
  177.              self.log.info('(mercurial status) %s', a)
  178. @@ -159,7 +159,7 @@
  179.      def plain(self, *args, **kw):
  180.          return False # so that '[hg] hgrc' file can specify [ui] options
  181.  
  182. -    def interactive(self):
  183. +    def interactive(self):
  184.          return False
  185.  
  186.      def readline(self):
  187. @@ -176,26 +176,26 @@
  188.          return (name.startswith('hg-') and
  189.                  name[3:] in ('Parents', 'Children', 'Tags', 'Branch') and
  190.                  mode == 'revprop') and 4 or 0
  191. -    
  192. +
  193.      def render_property(self, name, mode, context, props):
  194. -        return RenderedProperty(name=gettext(name[3:] + ':'),
  195. +        return RenderedProperty(name=gettext(name[3:] + ':'),
  196.                  name_attributes=[("class", "property")],
  197.                  content=self._render_property(name, mode, context, props))
  198.  
  199.      def _render_property(self, name, mode, context, props):
  200.          repos, revs = props[name]
  201. -        
  202. +
  203.          if name in ('hg-Parents', 'hg-Children'):
  204.              label = repos.display_rev
  205.          else:
  206.              label = lambda rev: rev
  207. -        
  208. +
  209.          def link(rev):
  210.              chgset = repos.get_changeset(rev)
  211.              return tag.a(label(rev), class_="changeset",
  212.                           title=shorten_line(chgset.message),
  213.                           href=context.href.changeset(rev, repos.reponame))
  214. -        
  215. +
  216.          if name == 'hg-Parents' and len(revs) == 2: # merge
  217.              new = context.resource.id
  218.              parent_links = [
  219. @@ -231,7 +231,7 @@
  220.      def match_property(self, name, mode):
  221.         return name in ('hg-transplant_source', 'hg-convert_revision') and \
  222.             mode == 'revprop' and 4 or 0
  223. -    
  224. +
  225.      def render_property(self, name, mode, context, props):
  226.          repos, value = props[name]
  227.          if name == 'hg-transplant_source':
  228. @@ -246,7 +246,7 @@
  229.                               title=_("no such changeset"), rel="nofollow")
  230.              return RenderedProperty(name=_("Transplant:"), content=link,
  231.                                      name_attributes=[("class", "property")])
  232. -        
  233. +
  234.          elif name == 'hg-convert_revision':
  235.              text = repos.to_u(value)
  236.              if value.startswith('svn:'):
  237. @@ -271,11 +271,11 @@
  238.  
  239.      def match_property(self, name, mode):
  240.         return name.startswith('hg-') and mode == 'revprop' and 1 or 0
  241. -    
  242. +
  243.      def render_property(self, name, mode, context, props):
  244. -        return RenderedProperty(name=name[3:] + ':',
  245. +        return RenderedProperty(name=name[3:] + ':',
  246.                                  name_attributes=[("class", "property")],
  247. -                                content=self._render_property(name, mode,
  248. +                                content=self._render_property(name, mode,
  249.                                                                context, props))
  250.  
  251.      def _render_property(self, name, mode, context, props):
  252. @@ -335,7 +335,7 @@
  253.                  self._version = version()
  254.              # development version assumed to be always the ''newest'' one,
  255.              # i.e. old development version won't be supported
  256. -            self._version_info = (999, 0, 0)
  257. +            self._version_info = (999, 0, 0)
  258.              m = re.match(r'(\d+)\.(\d+)(?:\.(\d+))?', self._version or '')
  259.              if m:
  260.                  self._version_info = tuple([int(n or 0) for n in m.groups()])
  261. @@ -359,7 +359,7 @@
  262.                  self.ui.check_trusted = False
  263.                  self.ui.readconfig(hgrc_path)
  264.              except IOError, e:
  265. -                self.log.warn("'[hg] hgrc' file (%s) can't be read: %s",
  266. +                self.log.warn("'[hg] hgrc' file (%s) can't be read: %s",
  267.                                hgrc_path, e)
  268.  
  269.          extensions.loadall(self.ui)
  270. @@ -380,7 +380,7 @@
  271.              yield 'Mercurial', self._version
  272.  
  273.      # IRepositoryConnector methods
  274. -    
  275. +
  276.      def get_supported_types(self):
  277.          """Support for `repository_type = hg`"""
  278.          if hg_import_error:
  279. @@ -398,7 +398,7 @@
  280.          return repos
  281.  
  282.      # IWikiSyntaxProvider methods
  283. -    
  284. +
  285.      def get_wiki_syntax(self):
  286.          yield (r'!?(?P<hgrev>[0-9a-f]{12,40})(?P<hgpath>/\S+\b)?',
  287.                 lambda formatter, label, match:
  288. @@ -454,7 +454,7 @@
  289.  
  290.  
  291.  ### Version Control API
  292. -    
  293. +
  294.  class MercurialRepository(Repository):
  295.      """Repository implementation based on the mercurial API.
  296.  
  297. @@ -466,6 +466,7 @@
  298.  
  299.      def __init__(self, path, params, log, connector):
  300.          self.ui = connector.ui
  301. +        self.env = connector.env
  302.          self._show_rev = connector.show_rev
  303.          self._node_fmt = connector.node_format
  304.          # TODO 0.13: per repository ui and options
  305. @@ -513,7 +514,7 @@
  306.          fsencoding = [sys.getfilesystemencoding() or 'utf-8'] + encoding
  307.          str_path = checked_encode(path, fsencoding, os.path.exists)
  308.          if str_path is None:
  309. -            raise TracError(_("Repository path '%(path)s' does not exist.",
  310. +            raise TracError(_("Repository path '%(path)s' does not exist.",
  311.                                path=path))
  312.          try:
  313.              self.repo = hg.repository(ui=self.ui, path=str_path)
  314. @@ -534,7 +535,20 @@
  315.  
  316.      def changectx(self, rev=None):
  317.          """Produce a Mercurial `context.changectx` from given Trac revision."""
  318. -        return self.repo[self.short_rev(rev)]
  319. +        return self._changectx_resolve_alias(self.repo[self.short_rev(rev)])
  320. +
  321. +    def _changectx_resolve_alias(self, ctx):
  322. +        db = self.env.get_db_cnx()
  323. +        cursor = db.cursor()
  324. +        cursor.execute("SELECT sid "
  325. +            "FROM session_attribute "
  326. +            "WHERE authenticated = 1 "
  327. +            "AND name LIKE 'mercurialalias.%' "
  328. +            "AND value = %s", (self.to_u(ctx.user()),))
  329. +        for sid, in cursor:
  330. +            ctx.user = lambda: self.to_u(sid)
  331. +            break
  332. +        return ctx
  333.  
  334.      def close(self):
  335.          self.repo = None
  336. @@ -614,7 +628,7 @@
  337.              else:
  338.                  return ''
  339.          # branches
  340. -        for ctx, b in sorted(branches.items(), reverse=True,
  341. +        for ctx, b in sorted(branches.items(), reverse=True,
  342.                               key=lambda (ctx, b): ctx.rev()):
  343.              yield ('branches', b + taginfo(ctx), '/', self._display(ctx))
  344.          # heads
  345. @@ -631,7 +645,7 @@
  346.              except (KeyError, RepoLookupError):
  347.                  pass
  348.          # closed branches
  349. -        for ctx, b in sorted(closed_branches.items(), reverse=True,
  350. +        for ctx, b in sorted(closed_branches.items(), reverse=True,
  351.                               key=lambda (ctx, b): ctx.rev()):
  352.              yield ('closed branches', b + taginfo(ctx), '/', self._display(ctx))
  353.  
  354. @@ -648,7 +662,7 @@
  355.              # Note: link to matching location in Mercurial's file browser
  356.              #rev = rev is not None and short(n) or 'tip'
  357.              #return '/'.join([url, 'file', rev, path])
  358. -  
  359. +
  360.      def get_changeset(self, rev):
  361.          return MercurialChangeset(self, self.changectx(rev))
  362.  
  363. @@ -660,7 +674,7 @@
  364.  
  365.          FIXME: this can only be handled correctly and efficiently by
  366.          using the db repository cache.
  367. -        
  368. +
  369.          The code below is only an heuristic, and doesn't work in the
  370.          general case. E.g. look at the mercurial repository timeline
  371.          for 2006-10-18, you need to give ''38'' daysback in order to
  372. @@ -686,14 +700,14 @@
  373.                  continue # assume no ancestor is younger and use next seed
  374.                  # (and that assumption is wrong for 3448 in the example above)
  375.              elif time < stop:
  376. -                yield MercurialChangeset(self, ctx)
  377. +                yield MercurialChangeset(self, self._changectx_resolve_alias(ctx))
  378.              for p in ctx.parents():
  379.                  if p.rev() not in seen:
  380.                      seen[p.rev()] = 1
  381.                      seeds.append(p)
  382.  
  383.      def get_node(self, path, rev=None):
  384. -        return MercurialNode(self, self.normalize_path(path),
  385. +        return MercurialNode(self, self.normalize_path(path),
  386.                               self.changectx(rev))
  387.  
  388.      def get_oldest_rev(self):
  389. @@ -701,12 +715,12 @@
  390.  
  391.      def get_youngest_rev(self):
  392.          return self.changectx().hex()
  393. -    
  394. +
  395.      def previous_rev(self, rev, path=''): # FIXME: path ignored for now
  396.          for p in self.changectx(rev).parents():
  397.              if p:
  398.                  return p.hex() # always follow first parent
  399. -    
  400. +
  401.      def next_rev(self, rev, path=''):
  402.          ctx = self.changectx(rev)
  403.          if path: # might be a file
  404. @@ -721,7 +735,7 @@
  405.          # it might be a directory (not supported for now) FIXME
  406.          for c in ctx.children():
  407.              return c.hex() # always follow first child
  408. -  
  409. +
  410.      def rev_older_than(self, rev1, rev2):
  411.          # FIXME use == and ancestors?
  412.          return self.short_rev(rev1) < self.short_rev(rev2)
  413. @@ -732,7 +746,7 @@
  414.      def get_changes(self, old_path, old_rev, new_path, new_rev,
  415.                      ignore_ancestry=1):
  416.          """Generates changes corresponding to generalized diffs.
  417. -        
  418. +
  419.          Generator that yields change tuples (old_node, new_node, kind,
  420.          change) for each node change between the two arbitrary
  421.          (path,rev) pairs.
  422. @@ -755,7 +769,7 @@
  423.          # Correct change info from changelog(revlog)
  424.          # Finding changes between two revs requires tracking back
  425.          # several routes.
  426. -                              
  427. +
  428.          if new_node.isdir:
  429.              # TODO: Should we follow rename and copy?
  430.              # As temporary workaround, simply compare entry names.
  431. @@ -793,7 +807,7 @@
  432.              if old_node.manifest[old_node.str_path] != \
  433.                     new_node.manifest[new_node.str_path]:
  434.                  yield(old_node, new_node, Node.FILE, Changeset.EDIT)
  435. -            
  436. +
  437.  
  438.  class MercurialNode(Node):
  439.      """A path in the repository, at a given revision.
  440. @@ -805,10 +819,10 @@
  441.      than for files, except when created as a `subnode()` of an
  442.      existing MercurialNode.
  443.      """
  444. -    
  445. +
  446.      filectx = dirnode = None
  447.  
  448. -    def __init__(self, repos, path, changectx,
  449. +    def __init__(self, repos, path, changectx,
  450.                   manifest=None, dirctx=None, str_entry=None):
  451.          """
  452.          :param repos: the `MercurialRepository`
  453. @@ -836,7 +850,7 @@
  454.              str_path = str_entry
  455.          else:
  456.              # Fast path: check for existing file
  457. -            str_path = checked_encode(path, repos.encoding,
  458. +            str_path = checked_encode(path, repos.encoding,
  459.                                        lambda s: s in self.manifest)
  460.              if str_path is None:
  461.                  # Slow path: this might be a directory node
  462. @@ -905,9 +919,9 @@
  463.  
  464.      def find_dirctx(self, max_rev, str_dirnames, str_entries):
  465.          """Find most recent modification for each given directory path.
  466. -        
  467. +
  468.          :param max_rev: find no revision more recent than this one
  469. -        :param str_dirnames: directory paths to consider
  470. +        :param str_dirnames: directory paths to consider
  471.                               (as `str` ending with '/')
  472.          :param str_entries: optionally maps directories to their file content
  473.  
  474. @@ -925,7 +939,7 @@
  475.             changelog and detect the first occurrence of a change in
  476.             each directory; this is much faster but can still be slow
  477.             if some folders are only modified in the distant past
  478. -          
  479. +
  480.          It is possible to combine both approach, and this can yield
  481.          excellent results in some cases (e.g. browsing the Linux repos
  482.          @ 118733 takes several minutes with the first approach, 11s
  483. @@ -970,8 +984,8 @@
  484.                          str_dirnames.remove(str_dir)
  485.                          if not str_dirnames:
  486.                              return str_dirctxs
  487. -                        
  488. -                
  489. +
  490. +
  491.      def subnode(self, str_path, subctx=None):
  492.          """Return a node with the same revision information but for
  493.          another path
  494. @@ -989,7 +1003,7 @@
  495.  
  496.      def read(self, size=None):
  497.          if self.isdir:
  498. -            return TracError(_("Can't read from directory %(path)s",
  499. +            return TracError(_("Can't read from directory %(path)s",
  500.                                 path=self.path))
  501.          if self.data is None:
  502.              self.data = self.filectx.data()
  503. @@ -1003,7 +1017,7 @@
  504.      def get_entries(self):
  505.          if self.isfile:
  506.              return
  507. -      
  508. +
  509.          # dirnames are entries which are sub-directories
  510.          str_entries = {}
  511.          str_dirnames = []
  512. @@ -1029,7 +1043,7 @@
  513.  
  514.          # pre-computing the changectx for the last change in each sub-directory
  515.          if str_dirnames:
  516. -            dirctxs = self.find_dirctx(self.created_rev, str_dirnames,
  517. +            dirctxs = self.find_dirctx(self.created_rev, str_dirnames,
  518.                                         str_entries)
  519.          else:
  520.              dirctxs = {}
  521. @@ -1090,7 +1104,7 @@
  522.          get = cachefunc(changefn)
  523.          if self.isfile:
  524.              fncache = {}
  525. -        chgiter, matchfn = cmdutil.walkchangerevs(self.repos.ui, repo, pats,
  526. +        chgiter, matchfn = cmdutil.walkchangerevs(self.repos.ui, repo, pats,
  527.                                                    get, opts)
  528.          # keep one lookahead entry so that we can detect renames
  529.          path = self.path
  530. @@ -1122,7 +1136,7 @@
  531.              for fc, line in self.filectx.annotate(follow=True):
  532.                  annotations.append(fc.rev() or '0')
  533.          return annotations
  534. -        
  535. +
  536.      def get_properties(self):
  537.          if self.isfile and 'x' in self.manifest.flags(self.str_path):
  538.              return {'exe': '*'}
  539. @@ -1153,7 +1167,7 @@
  540.      files changes are obtained by comparing the current manifest to
  541.      the parent manifest(s).
  542.      """
  543. -    
  544. +
  545.      def __init__(self, repos, ctx):
  546.          self.repos = repos
  547.          self.ctx = ctx
  548. @@ -1165,6 +1179,7 @@
  549.          desc = repos.to_u(ctx.description())
  550.          user = repos.to_u(ctx.user())
  551.          time = repos.from_hg_time(ctx.date())
  552. +
  553.          Changeset.__init__(self, repos, ctx.hex(), desc, user, time)
  554.  
  555.      hg_properties = [
  556. @@ -1175,7 +1190,7 @@
  557.          properties = {}
  558.          parents = self.ctx.parents()
  559.          if len(parents) > 1:
  560. -            properties['hg-Parents'] = (self.repos,
  561. +            properties['hg-Parents'] = (self.repos,
  562.                                          [p.hex() for p in parents if p])
  563.          children = self.ctx.children()
  564.          if len(children) > 1:
  565. @@ -1185,7 +1200,7 @@
  566.              properties['hg-Branch'] = (self.repos, [self.branch])
  567.          tags = self.ctx.tags()
  568.          if len(tags):
  569. -            properties['hg-Tags'] = (self.repos,
  570. +            properties['hg-Tags'] = (self.repos,
  571.                                       [self.repos.to_u(t) for t in tags])
  572.          for k, v in self.ctx.extra().iteritems():
  573.              if k != 'branch':
  574. @@ -1226,7 +1241,7 @@
  575.                  action = Changeset.MOVE
  576.              else:
  577.                  action = Changeset.COPY
  578. -            changes.append((f, Node.FILE, action, u(str_base_path),
  579. +            changes.append((f, Node.FILE, action, u(str_base_path),
  580.                              base_ctx.rev()))
  581.          # remaining str_deletions are real deletions
  582.          for str_file, p in str_deletions.items():
  583. @@ -1238,5 +1253,5 @@
  584.  
  585.      def get_branches(self):
  586.          """Yield branch names to which this changeset belong."""
  587. -        return self.branch and [(self.branch,
  588. +        return self.branch and [(self.branch,
  589.                                   len(self.ctx.children()) == 0)] or []
  590. diff -urN -x '*.pyc' -x '*.svn*' -x '*.egg*' mercurial-plugin/tracext/hg/templates/admin_mercurialalias.html mercurial-plugin-aliaspatch/tracext/hg/templates/admin_mercurialalias.html
  591. --- mercurial-plugin/tracext/hg/templates/admin_mercurialalias.html 1970-01-01 01:00:00.000000000 +0100
  592. +++ mercurial-plugin-aliaspatch/tracext/hg/templates/admin_mercurialalias.html  2012-03-24 16:32:39.472786230 +0100
  593. @@ -0,0 +1,60 @@
  594. +<!DOCTYPE html
  595. +    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  596. +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  597. +<html xmlns="http://www.w3.org/1999/xhtml"
  598. +      xmlns:xi="http://www.w3.org/2001/XInclude"
  599. +      xmlns:py="http://genshi.edgewall.org/">
  600. +  <xi:include href="admin.html" />
  601. +  <head>
  602. +    <title>Mercurial Aliases</title>
  603. +  </head>
  604. +
  605. +  <body>
  606. +    <h2>Manage Mercurial Aliases</h2>
  607. +
  608. +    <form id="hgalias-editor" class="addnew" method="post">
  609. +      <fieldset>
  610. +        <legend>Add Alias:</legend>
  611. +        <div class="field">
  612. +          <label>Username:<br />
  613. +            <input type="text" name="user" class="textwidget" />
  614. +          </label>
  615. +        </div>
  616. +        <div class="field">
  617. +          <label>Alias:<br />
  618. +            <input type="text" name="alias" class="textwidget" />
  619. +          </label>
  620. +        </div>
  621. +        <p class="help">Add a new alias.</p>
  622. +        <div class="buttons">
  623. +          <input type="submit" name="add" value="Add" />
  624. +        </div>
  625. +      </fieldset>
  626. +    </form>
  627. +
  628. +    <form method="post">
  629. +      <div id="aliaslist">
  630. +        <table class="listing">
  631. +          <thead>
  632. +            <tr>
  633. +              <th class="sel">&nbsp;</th>
  634. +              <th>Username</th><th>Alias</th>
  635. +            </tr>
  636. +          </thead>
  637. +          <tbody>
  638. +            <tr py:for="alias in aliases">
  639. +              <td>
  640. +                <input type="checkbox" name="sel" value="${alias.user}.${alias.key}" />
  641. +              </td>
  642. +              <td>${alias.user}</td>
  643. +              <td>${alias.alias}</td>
  644. +            </tr>
  645. +          </tbody>
  646. +        </table>
  647. +      </div>
  648. +      <div class="buttons">
  649. +        <input type="submit" name="remove" value="Remove" />
  650. +      </div>
  651. +    </form>
  652. +  </body>
  653. +</html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement