---
title: "Bzr hacks and tricks: diff -p"
publish_date: 2011-03-05
author: "MariaDB"
---

# Bzr hacks and tricks: diff -p

I don’t know about you, but I like **diff -p** \[[1](#sub1)\]. Having used it for years, I can read these diffs like a text, while diffs without **-p** often need to have the original file opened side by side, just to get enough of the context. Loving **diff -p** so much, I want to see it everywhere (evil laughter). Alas, in **bzr** only **diff** command can easily use **-p**, just run it as `bzr diff --diff-options=-p` or store it as an alias in the `~/.bazaar/bazaar.conf`. Actually, for an alias there is a better, although more verbose, alternative:

```

[ALIASES]
diff = "diff --diff-options='-F ^[[:alpha:]$_].*[^:]$'"
```

Unlike simple **-p** it will not think that a word ending with a semicolon (like a label or, say, `public:` and `private:`) is a “C function name”. But the problem is — only `bzr diff` can be tuned this way. Bzr **email** plugin still sends diffs without function names. And `bzr gdiff` does not show them. And, of course, all other bzr commands — `bzr commit`, for example, or `bzr shelve`, `bzr unshelve --preview`, `bzr log --show-diff` and others — they are still as unfriendly as before. I was solving it on a case by case basis — added a `post_commit_diffoptions` configuration option to the bzr-email plugin, then a command line option to `bzr gdiff`. But then it occurred to me that I can attack the problem at its core! And here it is: get this piece of the python code \[[2](#sub2)\], save it as the `~/.bazaar/plugins/diffoptions/__init__.py` file. Then you can add, say,

```

diff_options = -u -F ^[[:alpha:]$_].*[^:]$
```

to your `bazaar.conf` file and it will magically change everything. All bzr commands, bzr plugins — everything that generate diffs will use these options, and you can have nice C function names on all diff chunks, no matter what plugin or core bzr command generates them. Enjoy! *I wonder, whether bzr folks would like to get that as a core feature. They can do it properly, without hacks that I had to resort to.*

---

<a id="sub1" name="sub1">1)</a> If you haven’t heard about it before, **-p** option adds C function name to every **diff** chunk:

```

=== modified file 'sql-common/my_time.c'
--- sql-common/my_time.c        2010-08-27 14:12:44 +0000
+++ sql-common/my_time.c        2011-02-28 21:24:19 +0000
@@ -727,6 +727,9 @@ void my_init_time(void)
   my_time.hour=                (uint) l_time->tm_hour;
   my_time.minute=      (uint) l_time->tm_min;
   my_time.second=      (uint) l_time->tm_sec;
+  my_time.neg=          0;
+  my_time.second_part=  0;
+  my_time.time_type=    MYSQL_TIMESTAMP_DATETIME;
   my_system_gmt_sec(&my_time, &my_time_zone, &not_used);
 }

```

<a id="sub2" name="sub2">2)</a> This is the complete text of the **bzr diffoptions** plugin. It works for me with **bzr 2.2.4**, but I didn’t try it with any other bzr version.

```

#!/usr/bin/env python

"""global bzr diff options"""

version_info = (0, 0, 1)

from bzrlib import branch
from bzrlib import diff
from bzrlib import errors

def get_differ(tree):
  try:
    root = tree.id2path(tree.get_root_id())
    br = branch.Branch.open_containing(root)[0]
    diff_options = br.get_config().get_user_option('diff_options')
    if diff_options is not None:
      opts = diff_options.split()
      def diff_file(olab, olines, nlab, nlines, to_file, path_encoding=None):
          diff.external_diff(olab, olines, nlab, nlines, to_file, opts)
      return diff_file
  except (errors.NoSuchId, NotImplementedError):
    pass
  return None

old_init = diff.DiffText.__init__

def new_init(self, old_tree, new_tree, to_file, path_encoding='utf-8',
    old_label='', new_label='', differ=diff.internal_diff):

  if differ == diff.internal_diff:
    differ = get_differ(old_tree) or get_differ(new_tree) or diff.internal_diff

  old_init(self, old_tree, new_tree, to_file, path_encoding,
      old_label, new_label, differ)

diff.DiffText.__init__ = new_init

```