0

In Mercurial (hg), a user can enter the following command --

hg log --branch branchName

This shows only the commits which were done against a specific named branch.

What bzr command can give me the same functionality? I could not find an option for "bzr log" that would do the same thing. For example, if I committed revs 1, 2, and 3 in branch nick "trunk" and 2.1.1, 2.1.2, and 4 in branch nick "ftr-foo", how can I print only the revs under branch nick "ftr-foo" such that I'd only see 2.1.1, 2.1.2, 4? And how would I get only the commits which were done against the "trunk" branch nick such that I'd only see 1, 2, and 3?

DAG graph below.

4 [ftr-foo]
|  \
3   \ [trunk]
|    \
|     2.1.2 [ftr-foo]
|      |
|     2.1.1 [ftr-foo]
|   /
|  /
2 [trunk]
|
1 [trunk]
Lazy Badger
  • 94,711
  • 9
  • 78
  • 110
Kevin Carrasco
  • 1,042
  • 7
  • 9

1 Answers1

0

While Bzr has the basic machinery to allow matching commits by other criteria, this is still a non-trivial exercise in plugin writing. A simpler alternative is to filter the output of bzr log or bzr log -n0 through a grep-like program that understands where commits begin and end.

The following Python program (which should work with both Python 2.7 and Python 3.x) allows you to grep bzr log output for arbitrary regular expressions:

#!/usr/bin/env python
import sys, re, os

args = sys.argv[1:]
if not args or args in [["--help"], ["-h"], ["-help"]]:
  prog = os.path.basename(sys.argv[0])
  print("Usage: bzr log BZRARGS | " + prog + " REGEX ...")
  sys.exit(1)
patterns = [re.compile(pat) for pat in args]

def handle(block):
  match = False
  for line in block:
    for pattern in patterns:
      if re.search(pattern, line):
        match = True
        break
    if match:
      break
  if match:
    try:
      for line in block:
        sys.stdout.write(line)
    except IOError:
      sys.exit(0)

def main():
  sep = "^\s*------------------------------------------------------------$"
  sep = re.compile(sep)
  stdin = sys.stdin
  block = []
  while True:
    line = stdin.readline()
    if not line:
      if block:
        handle(block)
      break
    if re.match(sep, line):
      if not block:
        block.append(line)
      else:
        handle(block)
        block = [ line ]
    else:
      block.append(line)

main()

If you call this program bzr-greplog, you can then do:

bzr log -n0 | bzr-greplog 'branch nick: foo'

to search for branches with the nick foo. Note that the pattern will match anywhere within a line, so it will match a nick of foobar also, for example, or a commit message that happens to have this pattern. In order to avoid (most) such false positives, use an anchored regex instead, e.g. '^\s*branch nick: foo$' (the \s* is necessary because indented commits may begin with spaces). You can also use a script that allows you to search specifically for a branch nick:

#!/bin/sh
bzr log -n0 | bzr-greplog '^\s*branch nick: '"$1"'$'

Known bug: If a commit message contains exactly a bzr log record separator (with the exact same number of dashes), then bzr-greplog will misinterpret the commit as two commits and may leave out the part following the separator.

Reimer Behrends
  • 8,600
  • 15
  • 19