Josh VanderLinden  committed 4d3aac5

Added a new command: qticket

This lets you quickly and easily jump to the URL for a ticket that the patch addresses if you have some consistent naming convention for such patches.

  • Participants
  • Parent commits 6323f86
  • Branches default

Comments (0)

Files changed (2)

     - qserve: run ``hg serve`` for the patch queue repository
     - qreorder: reorder the patches in your patch queue.  Usage: hg qreorder [new index] [patch name]
       If no patch name is specified, it will move the currently applied patch to the specified 1-based index.
+    - qticket: open a ticket/issue tracking URL for a ticket based on some pattern in either the patch name or first line of the patch.  To use this command, simply add a new section to your .hg/hgrc file as such:
+        [ticket_urls]
+        bitbucket = (contents:#([0-9]+).*)\1/
+        bitbucket2 = (file:^([0-9]+)_.*)\1/
+      The format of your policies is as such:
+        (match type:regex) URL with back references
+      The two options that are currently available for "match type" are:
+        - file
+        - contents
+      If you use "file" you will only have the patch name to apply the regex to.  With "contents" you only get the first line of the patch.  You can set the first line of your patch by using `hg qref -e` (what you type here is also what will be your commit message in your hg logs).
+      If any policies succeed, the command will attempt to launch your default web browser to the location determined by the policy.
 - mpush: Multi-push and multi-pull commands.  This allows you to easily replicate your changesets across several different repos in one command.  These commands, mpush and mpull, will push to and pull from all repositories listed in the [paths] section of the local repository's .hg/hgrc file.
 from mercurial import hg, commands, util
 from hgext import mq
 import os
+import re
 LOG_KEY = '^log|history'
 SERVE_KEY = '^serve'
 PUSH_KEY = '^push'
+MAGIC_RE = re.compile('\((?P<type>\w+):(?P<pattern>.+?)\) (?P<url>.*)', re.M | re.S)
 def_prop = lambda k, i: commands.table[k][i]
 def qrepo(ui, repo):
         new_repo = hg.repository(ui, os.path.join(repo.root)) # refresh the series
         mq.goto(ui, new_repo, current_patch, force=False)
+def qticket(ui, repo, patch_name, **opts):
+    """Attempts to open a web browser to the location for the ticket that a patch addresses"""
+    q = qrepo(ui, repo)
+    patch = q.lookup(patch_name)
+    import webbrowser
+    ticket_urls = ui.configitems('ticket_urls')
+    for name, magic in ticket_urls:
+        match =
+        if match:
+            match_type, pattern, url = match.groups()
+            if match_type == 'file':
+                match_using = patch
+            elif match_type == 'contents':
+                patch_file = os.path.join(q.path, patch)
+                match_using = open(patch_file, 'r').readline()
+            else:
+                util.Abort('Invalid match type in policy %s: %s.  Options are "file" and "contents"\n' % (name, match_type))
+            magic_match = re.match(pattern, match_using)
+            if magic_match:
+                # replace junk in the URL with info from the patch
+                the_url = re.sub(pattern, url, match_using).strip()
+                if the_url != patch:
+        else:
+            util.Abort('Invalid ticket magic in policy %s: %s\n' % (name, magic))
 cmdtable = {
     'qlog': (qlog, def_prop(LOG_KEY, 1), def_prop(LOG_KEY, 2)),
     'pushq': (pushq, def_prop(PUSH_KEY, 1), def_prop(PUSH_KEY, 2)),
     'qserve': (qserve, def_prop(SERVE_KEY, 1), def_prop(SERVE_KEY, 2)),
     'qreorder': (qreorder, [], 'hg qreorder NEW_POSITION [PATCH]'),
+    'qticket': (qticket, [], 'hg qticket [PATCH]'),