Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

nik (3476)

AOL IM: nikclayton (Add Buddy, Send Message)

Journal of nik (3476)

Friday December 16, 2005
11:11 AM

SVN::Web 0.42 released

I've just released SVN::Web 0.42. This release is a mix of bug fixes and architectural changes to make it easier for people to build on SVN::Web.

One of the big changes is that now, instead of calling die() at various points, the majority of the code is now exception based, using SVN::Web::X (which derives from Exception::Class).

I'm not convinced that I'm quite using exceptions in the 'proper' fashion. Instead of having different classes of exception (::PathIsMissing, ::RevisionDoesNotExist, and so on), there's a single exception type (the aforementioned SVN::Web::X. When throwing an exception the code includes a short error message, and then the localisation system is responsible for turning that in to a pretty web page.

Since SVN::Web only has two notional layers (SVN::Web, which dispatches to SVN::Web:: actions, and the actions themselves) I don't think that I'm missing much here.

There's a handful of new functionality -- you can now easily view diffs between arbitrary revisions of a file, for instance, which is quite handy.

And a few things have changed under the hood to make it easier for third-party SVN::Web:: to hook in and behave like fully integrated parts of the original codebase. This will make it much easier for my next trick, SVN::Web::Search, which will put a search interface on top of all the log messages, revisions, dates, and authors in your repository...

Wednesday November 09, 2005
06:03 AM

SVN::Web, Template::Plugin::{Subst, MultiFilter}

As described in an earlier entry, new versions of SVN::Web escaped over the weekend. First there was 0.40, which contained the bulk of the new code. Then 0.41 followed when I realised I'd made a few packaging cock ups.

One of the things you can do with the new version is pass SVN commit messages through multiple TT filters. Each filter can decorate the commit message in some way -- recognise URLs, e-mail addresses, RT ticket numbers, subversion revision numbers, etc, and convert them in to hyperlinks.

Say you've written "Fixes rt#1234" in your commit message. You'd like "rt#1234" to link straight to your bug database.

I thought that would be easy. Obviously, in straight Perl it's just the equivalent of:

$msg =~ s/rt#(\d+)/<a href="/rt.cgi?t=$1">$1</a>/;

I was quite surprised that TT doesn't offer this functionality. The built in replace method/filter doesn't cut it, as it doesn't handle backreferences. The TT:

[% msg.replace('rt#(\d+)', '<a href="/rt.cgi?t=$1">$1</a>') %]

results in the literal $1 being inserted into the output instead of the expected back reference.

The two popular suggestions in the TT list archives are to either use s/// directly in a [% PERL %] block, or write a custom filter to do the specific search and replace.

But [% PERL %] blocks might not be enabled in every TT install. And writing multiple filters (one to recognise RT tickets, one for subversion revision numbers, one for Sourceforge tickets, ...) would rapidly get boring.

Hence, Template::Plugin::Subst. With it, you can write:

[% msg.subst('rt#(\d+)', '<a href="/rt.cgi?t=$1">$1</a>') %]

and it will do the right thing. And as well as working as vmethod, it also works as a filter, so you can use that syntax instead.

The other thing that TT can't easily and cleanly do is stack multiple filters together, ignoring the ones that aren't installed.

SVN::Web ships with a config file that specifies a number of TT plugins to filter log messages through (to convert them to HTML, and make various things in the log clickable). These include plugins that might not be installed. In TT you can't say "Run all these filters, ignoring the ones that aren't installed". Trying to use a missing plugin (sensibly) generates a run-time error.

So, SVN::Web's log_msg_filter() implements this functionality. And the default SVN::Web configuration file can safely specify several different plugins, without the user having to worry about whether or not they're installed. Without them, everything works, and if they are installed then the user gets a slightly nicer output.

At the moment this is hardcoded in to SVN::Web, but I plan on releasing Template::Plugin::MultiFilter in the near future so that others can easily use this functionality.

Wednesday November 02, 2005
07:52 AM

New version of SVN::Web in the offing

I've been spending much of the last few weeks polishing up SVN::Web. It's a simple way to browse SVN repositories online, view diffs, compare revisions, check out log entries, and so forth.

Originally written by Chia-liang Kao, of SVK fame, he's handed the maintainer reins over to me.

Changes in the new version include:

An overhauled set of templates, so the out-of-the-box experience is much nicer.

A 'view' action that shows the contents of a file, along with the most recent log message.

More customisation options, making it easier to add or remove actions from the list of things that SVN::Web is allowed to do.

Added huge swathes of information to the documentation. It should now be much easier for anyone else to contribute code and/or templates to SVN::Web.

A fix for rt#12431.

A mechanism to 'stack' Template Toolkit filters. You can run easily run log messages through an arbitrary number of filters, without causing problems if one or more of the filters is not installed.

Inline display of some content from the repository where appropriate (e.g., viewing an image works properly).

Fixed a bug that meant the results from the automated tests weren't valid. Fixed the bugs that this uncovered.

And much more. It'll be hitting CPAN shortly. In the meantime, you can see the code (and the new, shiny, trac inspired interface) here.

Sunday October 02, 2005
03:10 PM

Finding the memory hogs

I sent this to the mailing list, and was surprised to get few responses. That probably means it's a hard problem. Still...

I'm having a stab at reducing the memory footprint of a Perl application I'm working with. When it's running it's ~80MB resident. I know it plays fast and loose with memory, allocating hashes and the like at the drop of a hat. What I'd like to know are the long hanging fruit that I can try and recode to be a little more memory friendly.

Devel::Symdump + Devel::Size gets me some of the way there. I can instrument the application by waiting until it's gone through its initialisation phase (after which the memory usage is reasonably constant), and then walk the symbol table, dumping the size of everything that's found.

But, natch, that won't work for lexical variables, many of which have been created in subs and had references returned.

Poking through CPAN hasn't turned up anything useful (although some of the B:: namespace looks like it could be coerced in to this). Anyone got any pointers to approaches that are likely to work?

Any takers?

Saturday July 09, 2005
05:59 AM

4 new Test::* modules

I've been busy over the past week producing four new Test::* modules.

These are a bit different from most other Test::* modules, which are normally written to help you test your code. These, however, are designed to help you test the environment that your code is going to be running in.

Test::Symlink lets you easily verify that a symlink exists, and that it links to the correct location.

    symlink_ok($src => $dst);

Test::Unix::Group and Test:::Unix::User let you verify that a user, group, and home directory exist.

    user_ok({ name => 'nik', uid => 1000}, 'nik has uid 1000');

    homedir_ok({ name => 'nik', group => 'staff' },
        "nik's homedir is owned by the staff group");

    group_ok({ name => 'wheel', members => [qw(root nik)]},
        "'wheel' has the correct members");

Finally, there's Test::Net::Connect, which lets you make sure that you can make a network connection to a particular host.

    connect_ok({ host => '', port => 80 },
        "Web server is reachable from here");

Friday December 24, 2004
04:49 AM

Test Anything in C

libtap made it to version 1.0 the other day, and there don't seem to be too many embarassing mistakes, so...

libtap is an implementation of the Test::Harness protocol for reporting test successes/failures (ok, not ok, skip, TODO, etc) in C, making it ideal for when you need to write test cases in C (Perl not available, Inline::C not available, that sort of thing). Full documentation is included.

More information, including links to the tarball, MD5 checksums, read-only access to the Subversion repository, and the bug/feature ticket system is at my Trac site.

This has only been tested on FreeBSD 5.x and 6.x at the moment; if you're on those systems then you can use ports/devel/libtap for ease of installation. Tests on other systems (and tickets reporting issues / patches to fix them) would be very welcome.

Friday December 10, 2004
01:19 PM

libtap getting more useful

Last week I wrote about some initial progress I was making with libtap, an implementation of the Test::More / Test::Harness protocol for communicating test results for tests written in C.

Since then I've managed to make a bit more progress.

  • There's a website for it now. This is also my opportunity to experiment with trac, a combination wiki, ticket system, and subversion repo browser.

  • This means I've got tickets that let me keep track of suggestions, and see how much more work there is to go.

  • Functionality improved, as can be seen at the timeline and the roadmap.

  • I turned on anonymous SVN access, described here. As a handy side effect, source code to development versions of my CPAN modules is available too.

All I need to do now is work on closing the tickets...

07:04 AM

Today, I am mostly hating...

... SPF.

More specifically, I am hating load-balancers that function by acting as DNS servers, handing out different A records for the services they balance depending on host load.

Self-same load-balancers can't publish TXT records...

Monday December 06, 2004
11:56 AM

Bad thing, good thing

Bad thing: My coffee machine's just blown up. There's ground coffee all over the kitchen.

Good thing: Krups' customer service. "Yes sir, just fax us a copy of the receipt and we'll ship a replacement to you free of charge."

I was expecting to have to box the old one up and send it back to them -- as Murphy dictates, I'd dumped the packaging it originally came in 2 weeks ago, something I do only after a bulky purchase has been in the house and working flawlessly for at least three months...

Saturday December 04, 2004
11:50 AM

Test::Harness's TAP in C -- libtap

A few weeks back I did the work to make most of the FreeBSD regression test suite produce output that's compatible with Test::Harness and prove(1).

Back then there wasn't a name for that format. Now, of course, there is.

This was very much a rough cut. A lot of the tests were written in C, consisting of a few hundred (or in some cases a few thousand) ASSERT() calls, with a printf("PASS\n"); at the bottom -- if your test didn't dump core you knew it worked.

Changing most of those to add printf("1..1\n"); and printf("ok 1\n"); was the work of an afternoon.

On the TODO list was to implement as much of TAP as possible in C -- having plans, ok(), and so on. By doing that, and removing the ASSERT()s, a failing test doesn't prevent all the other tests from running, and you get a truer picture about how many tests overall are being run. And we all know that seeing the test count go up is a strong incentive to keep writing them.

So, here's a very early draft of that; libtap. Right now, plan(), ok(), and diag() functionality is there, which is almost all the way to what I need for FreeBSD regression suite.