diff -r 672eaaab9204 -r 52d12eb31c30 SEESenv/web/html/backup/abc.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SEESenv/web/html/backup/abc.html Fri Feb 12 01:11:21 2010 +0530 @@ -0,0 +1,530 @@ + +Chapter 9. Finding and fixing mistakes + + + + + + + + + + + +
+

+Chapter 14. Adding functionality with extensions

+
+

Table of Contents

+
+
14.1. Improve performance with the inotify extension
+
14.2. Flexible diff support with the extdiff extension
+
14.2.1. Defining command aliases
+
14.3. Cherrypicking changes with the transplant extension
+
14.4. Send changes via email with the patchbomb extension
+
14.4.1. Changing the behavior of patchbombs
+
+
+

While the core of Mercurial is quite complete from a + functionality standpoint, it's deliberately shorn of fancy + features. This approach of preserving simplicity keeps the + software easy to deal with for both maintainers and users.

+

However, Mercurial doesn't box you in with an inflexible + command set: you can add features to it as + extensions (sometimes known as + plugins). We've already discussed a few of + these extensions in earlier chapters.

+

When you provide a directory name, Mercurial will interpret + this as “operate on every file in this directory and its + subdirectories”. Mercurial traverses the files and + subdirectories in a directory in alphabetical order. When it + encounters a subdirectory, it will traverse that subdirectory + before continuing with the current directory.

+ + + +
+

In this chapter, we'll cover some of the other extensions that + are available for Mercurial, and briefly touch on some of the + machinery you'll need to know about if you want to write an + extension of your own.

+
+
+

+14.1. Improve performance with the inotify extension

+

Are you interested in having some of the most common + Mercurial operations run as much as a hundred times faster? + Read on!

+

Mercurial has great performance under normal circumstances. + For example, when you run the hg + status command, Mercurial has to scan almost every + directory and file in your repository so that it can display + file status. Many other Mercurial commands need to do the same + work behind the scenes; for example, the hg diff command uses the status + machinery to avoid doing an expensive comparison operation on + files that obviously haven't changed.

+

Because obtaining file status is crucial to good + performance, the authors of Mercurial have optimised this code + to within an inch of its life. However, there's no avoiding the + fact that when you run hg + status, Mercurial is going to have to perform at + least one expensive system call for each managed file to + determine whether it's changed since the last time Mercurial + checked. For a sufficiently large repository, this can take a + long time.

+

To put a number on the magnitude of this effect, I created a + repository containing 150,000 managed files. I timed hg status as taking ten seconds to + run, even when none of those files had been + modified.

+

Many modern operating systems contain a file notification + facility. If a program signs up to an appropriate service, the + operating system will notify it every time a file of interest is + created, modified, or deleted. On Linux systems, the kernel + component that does this is called + inotify.

+

Mercurial's inotify + extension talks to the kernel's inotify + component to optimise hg status + commands. The extension has two components. A daemon sits in + the background and receives notifications from the + inotify subsystem. It also listens for + connections from a regular Mercurial command. The extension + modifies Mercurial's behavior so that instead of scanning the + filesystem, it queries the daemon. Since the daemon has perfect + information about the state of the repository, it can respond + with a result instantaneously, avoiding the need to scan every + directory and file in the repository.

+

Recall the ten seconds that I measured plain Mercurial as + taking to run hg status on a + 150,000 file repository. With the inotify extension enabled, the time + dropped to 0.1 seconds, a factor of one + hundred faster.

+

Before we continue, please pay attention to some + caveats.

+
    +
  • The inotify + extension is Linux-specific. Because it interfaces directly + to the Linux kernel's inotify subsystem, + it does not work on other operating systems.

  • +
  • It should work on any Linux distribution that + was released after early 2005. Older distributions are + likely to have a kernel that lacks + inotify, or a version of + glibc that does not have the necessary + interfacing support.

  • +
  • Not all filesystems are suitable for use with + the inotify extension. + Network filesystems such as NFS are a non-starter, for + example, particularly if you're running Mercurial on several + systems, all mounting the same network filesystem. The + kernel's inotify system has no way of + knowing about changes made on another system. Most local + filesystems (e.g. ext3, XFS, ReiserFS) should work + fine.

  • +
+

The inotify extension is + not yet shipped with Mercurial as of May 2007, so it's a little + more involved to set up than other extensions. But the + performance improvement is worth it!

+

The extension currently comes in two parts: a set of patches + to the Mercurial source code, and a library of Python bindings + to the inotify subsystem.

+
+ + + + + +
[Note]Note

There are two Python + inotify binding libraries. One of them is + called pyinotify, and is packaged by some + Linux distributions as python-inotify. + This is not the one you'll need, as it is + too buggy and inefficient to be practical.

+

To get going, it's best to already have a functioning copy + of Mercurial installed.

+
+ + + + + +
[Note]Note

If you follow the instructions below, you'll be + replacing and overwriting any existing + installation of Mercurial that you might already have, using + the latest bleeding edge Mercurial code. Don't + say you weren't warned!

+
    +
  1. +

    Clone the Python inotify + binding repository. Build and install it.

    +
    hg clone http://hg.kublai.com/python/inotify
    +cd inotify
    +python setup.py build --force
    +sudo python setup.py install --skip-build
    +
  2. +
  3. +

    Clone the crew Mercurial repository. + Clone the inotify patch + repository so that Mercurial Queues will be able to apply + patches to your cope of the crew repository.

    +
    hg clone http://hg.intevation.org/mercurial/crew
    +hg clone crew inotify
    +hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
    +
  4. +
  5. Make sure that you have the Mercurial Queues + extension, mq, enabled. If + you've never used MQ, read Section 12.5, “Getting started with Mercurial Queues” to get started + quickly.

  6. +
  7. +

    Go into the inotify repo, and apply all + of the inotify patches + using the hg + -a option to the qpush command.

    +
    cd inotify
    +hg qpush -a
    +
  8. +
  9. If you get an error message from qpush, you should not continue. + Instead, ask for help.

  10. +
  11. +

    Build and install the patched version of + Mercurial.

    +
    python setup.py build --force
    +sudo python setup.py install --skip-build
    +
  12. +
+

Once you've build a suitably patched version of Mercurial, + all you need to do to enable the inotify extension is add an entry to + your ~/.hgrc.

+
[extensions] inotify =
+

When the inotify extension + is enabled, Mercurial will automatically and transparently start + the status daemon the first time you run a command that needs + status in a repository. It runs one status daemon per + repository.

+

The status daemon is started silently, and runs in the + background. If you look at a list of running processes after + you've enabled the inotify + extension and run a few commands in different repositories, + you'll thus see a few hg processes sitting + around, waiting for updates from the kernel and queries from + Mercurial.

+

The first time you run a Mercurial command in a repository + when you have the inotify + extension enabled, it will run with about the same performance + as a normal Mercurial command. This is because the status + daemon needs to perform a normal status scan so that it has a + baseline against which to apply later updates from the kernel. + However, every subsequent command that does + any kind of status check should be noticeably faster on + repositories of even fairly modest size. Better yet, the bigger + your repository is, the greater a performance advantage you'll + see. The inotify daemon makes + status operations almost instantaneous on repositories of all + sizes!

+

If you like, you can manually start a status daemon using + the inserve command. + This gives you slightly finer control over how the daemon ought + to run. This command will of course only be available when the + inotify extension is + enabled.

+

When you're using the inotify extension, you should notice + no difference at all in Mercurial's + behavior, with the sole exception of status-related commands + running a whole lot faster than they used to. You should + specifically expect that commands will not print different + output; neither should they give different results. If either of + these situations occurs, please report a bug.

+
+
+

+14.2. Flexible diff support with the extdiff extension

+

Mercurial's built-in hg + diff command outputs plaintext unified diffs.

+
$ hg diff
+diff -r 80997726a0ea myfile
+--- a/myfile	Wed Jan 06 06:50:18 2010 +0000
++++ b/myfile	Wed Jan 06 06:50:18 2010 +0000
+@@ -1,1 +1,2 @@
+ The first line.
++The second line.
+
+

If you would like to use an external tool to display + modifications, you'll want to use the extdiff extension. This will let you + use, for example, a graphical diff tool.

+

The extdiff extension is + bundled with Mercurial, so it's easy to set up. In the extensions section of your + ~/.hgrc, simply add a + one-line entry to enable the extension.

+
[extensions]
+extdiff =
+

This introduces a command named extdiff, which by default uses + your system's diff command to generate a + unified diff in the same form as the built-in hg diff command.

+
$ hg extdiff
+--- a.80997726a0ea/myfile	2010-01-06 06:50:18.613674526 +0000
++++ /tmp/extdiffNErQlu/a/myfile	2010-01-06 06:50:18.437687076 +0000
+@@ -1 +1,2 @@
+ The first line.
++The second line.
+
+

The result won't be exactly the same as with the built-in + hg diff variations, because the + output of diff varies from one system to + another, even when passed the same options.

+

As the making snapshot + lines of output above imply, the extdiff command works by + creating two snapshots of your source tree. The first snapshot + is of the source revision; the second, of the target revision or + working directory. The extdiff command generates + these snapshots in a temporary directory, passes the name of + each directory to an external diff viewer, then deletes the + temporary directory. For efficiency, it only snapshots the + directories and files that have changed between the two + revisions.

+

Snapshot directory names have the same base name as your + repository. If your repository path is /quux/bar/foo, then foo will be the name of each + snapshot directory. Each snapshot directory name has its + changeset ID appended, if appropriate. If a snapshot is of + revision a631aca1083f, the directory will be + named foo.a631aca1083f. + A snapshot of the working directory won't have a changeset ID + appended, so it would just be foo in this example. To see what + this looks like in practice, look again at the extdiff example above. Notice + that the diff has the snapshot directory names embedded in its + header.

+

The extdiff command + accepts two important options. The hg -p option + lets you choose a program to view differences with, instead of + diff. With the hg -o option, + you can change the options that extdiff passes to the program + (by default, these options are + -Npru, which only make sense + if you're running diff). In other respects, + the extdiff command + acts similarly to the built-in hg + diff command: you use the same option names, syntax, + and arguments to specify the revisions you want, the files you + want, and so on.

+

As an example, here's how to run the normal system + diff command, getting it to generate context + diffs (using the -c option) + instead of unified diffs, and five lines of context instead of + the default three (passing 5 as the argument + to the -C option).

+
$ hg extdiff -o -NprcC5
+*** a.80997726a0ea/myfile	Wed Jan  6 06:50:18 2010
+--- /tmp/extdiffNErQlu/a/myfile	Wed Jan  6 06:50:18 2010
+***************
+*** 1 ****
+--- 1,2 ----
+  The first line.
++ The second line.
+
+

Launching a visual diff tool is just as easy. Here's how to + launch the kdiff3 viewer.

+
hg extdiff -p kdiff3 -o
+

If your diff viewing command can't deal with directories, + you can easily work around this with a little scripting. For an + example of such scripting in action with the mq extension and the + interdiff command, see Section 13.9.2, “Viewing the history of a patch”.

+
+

+14.2.1. Defining command aliases

+

It can be cumbersome to remember the options to both the + extdiff command and + the diff viewer you want to use, so the extdiff extension lets you define + new commands that will invoke your diff + viewer with exactly the right options.

+

All you need to do is edit your ~/.hgrc, and add a section named + extdiff. Inside this + section, you can define multiple commands. Here's how to add + a kdiff3 command. Once you've defined + this, you can type hg kdiff3 + and the extdiff extension + will run kdiff3 for you.

+
[extdiff]
+cmd.kdiff3 =
+

If you leave the right hand side of the definition empty, + as above, the extdiff + extension uses the name of the command you defined as the name + of the external program to run. But these names don't have to + be the same. Here, we define a command named + hg wibble, which runs + kdiff3.

+
[extdiff]
+ cmd.wibble = kdiff3
+

You can also specify the default options that you want to + invoke your diff viewing program with. The prefix to use is + opts., followed by the name + of the command to which the options apply. This example + defines a hg vimdiff command + that runs the vim editor's + DirDiff extension.

+
[extdiff]
+ cmd.vimdiff = vim
+opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
+
+
+
+

+14.3. Cherrypicking changes with the transplant extension

+

Need to have a long chat with Brendan about this.

+
+
+

+14.4. Send changes via email with the patchbomb extension

+

Many projects have a culture of change + review, in which people send their modifications to a + mailing list for others to read and comment on before they + commit the final version to a shared repository. Some projects + have people who act as gatekeepers; they apply changes from + other people to a repository to which those others don't have + access.

+

Mercurial makes it easy to send changes over email for + review or application, via its patchbomb extension. The extension is + so named because changes are formatted as patches, and it's usual + to send one changeset per email message. Sending a long series + of changes by email is thus much like bombing the + recipient's inbox, hence patchbomb.

+

As usual, the basic configuration of the patchbomb extension takes just one or + two lines in your + /.hgrc.

+
[extensions]
+patchbomb =
+

Once you've enabled the extension, you will have a new + command available, named email.

+

The safest and best way to invoke the email command is to + always run it first with the hg -n option. + This will show you what the command would + send, without actually sending anything. Once you've had a + quick glance over the changes and verified that you are sending + the right ones, you can rerun the same command, with the hg -n option + removed.

+

The email command + accepts the same kind of revision syntax as every other + Mercurial command. For example, this command will send every + revision between 7 and tip, inclusive.

+
hg email -n 7:tip
+

You can also specify a repository to + compare with. If you provide a repository but no revisions, the + email command will + send all revisions in the local repository that are not present + in the remote repository. If you additionally specify revisions + or a branch name (the latter using the hg -b option), + this will constrain the revisions sent.

+

It's perfectly safe to run the email command without the + names of the people you want to send to: if you do this, it will + just prompt you for those values interactively. (If you're + using a Linux or Unix-like system, you should have enhanced + readline-style editing capabilities when + entering those headers, too, which is useful.)

+

When you are sending just one revision, the email command will by + default use the first line of the changeset description as the + subject of the single email message it sends.

+

If you send multiple revisions, the email command will usually + send one message per changeset. It will preface the series with + an introductory message, in which you should describe the + purpose of the series of changes you're sending.

+
+

+14.4.1. Changing the behavior of patchbombs

+

Not every project has exactly the same conventions for + sending changes in email; the patchbomb extension tries to + accommodate a number of variations through command line + options.

+
    +
  • You can write a subject for the introductory + message on the command line using the hg -s + option. This takes one argument, the text of the subject + to use.

  • +
  • To change the email address from which the + messages originate, use the hg -f + option. This takes one argument, the email address to + use.

  • +
  • The default behavior is to send unified diffs + (see Section 12.4, “Understanding patches” for a + description of the + format), one per message. You can send a binary bundle + instead with the hg -b + option.

  • +
  • Unified diffs are normally prefaced with a + metadata header. You can omit this, and send unadorned + diffs, with the hg + --plain option.

  • +
  • Diffs are normally sent inline, + in the same body part as the description of a patch. This + makes it easiest for the largest number of readers to + quote and respond to parts of a diff, as some mail clients + will only quote the first MIME body part in a message. If + you'd prefer to send the description and the diff in + separate body parts, use the hg -a + option.

  • +
  • Instead of sending mail messages, you can + write them to an mbox-format mail + folder using the hg -m + option. That option takes one argument, the name of the + file to write to.

  • +
  • If you would like to add a + diffstat-format summary to each patch, + and one to the introductory message, use the hg -d + option. The diffstat command displays + a table containing the name of each file patched, the + number of lines affected, and a histogram showing how much + each file is modified. This gives readers a qualitative + glance at how complex a patch is.

  • +
+
+
+
+ + +