[rt-devel] RT contributor framework

Ruslan U. Zakirov cubic at acronis.ru
Fri Sep 12 13:23:53 EDT 2003

    I was searching a way of using CVS or Aegis to manage mine RT 
contributions for some time. May be because of lack of knowledge in VSs 
technologies or something else, but I didn't find solutions to solve 
next problems:
        - have no rights to commit in mainline;
        - easy resolve conflicts on merging own repository with mainline;
        - need more then one repository for different subprojects;
        - save change sets in CVS instead of changes for particular files;
        - get Aegis full clone of RT3.0.0 project from Best Practical web;
    1) setup mainline repository that consistent with Best Practical 
current version
    2) setup repository for fixes/changes that should be included in 
    3) setup repository for stable(currently working) version of RT
    4) setup other repositories for subprojects(contributions)
    5) write this article
    6) and many other tasks

    I've stop my searches on BitKeeper(www.bitkeeper.com) with Single 
User/Host license. I know that this license have restrictions on using 
some good stuffs, but allowed tools solve most of described problems. 
Everthing that you need to install bk on your machine you could find at 
its site. I mentioned only one problem, after installation bk doesn't 
start under root login with complaints about 'wm'.
    Now we need to do initial import of RT source tree in bk repository:
        - cd /tmp
        - wget http://fsck.com/pub/rt/release/rt-3-0-4.tar.gz
        - tar -zxvf rt-3-0-4.tar.gz
        - cd /to/where/you/want/to/create/your/bk/repository
        - bk setuptool bp_current
        following GUI instructions of Setup Tool
        - bk import -F -tCVS -A /tmp/rt-3-0-4 bp_current

    We have got  new bk  branch  without parent under bp_current dir. 
 It would be our clone off mainline. We should never push changes in it. 
It's only for import latest changes from Best Practical.
    I've started writing of script that automagically pull changes from 
aegis history 
but it still in development state. Script attached to this email. 
Coution!!! Be easy! Don't run it right now :) (It's still under 
development). This tool uses ChangeSets comments for last delta number 
identification. You must do "cd bp_current; bk comments -y'152/201 
Bumping to RT 3.0.4'" before starting this script. BUGS: Script skips 
deltas which creates new files and deletes old one.  A lot  of  output 
to STDOUT and more other .

    Any help with script are wellcome.

    Let forget about dirty script. And do some imort by hands.
        - cd bp_current
        - bk -r edit
        - wget -q -O - 
| gunzip -c | patch -p0
        -  bk -r ci  -y'153/195 #3042: Make max inline body size 
        -  bk commit -d -y'153/195 #3042: Make max inline body size 
    Now we have commited new changeset from aegis. This also skip new 
files, I found only next solution:
         - find . -type f | xargs bk ci -i -y'New files'

To be continued:
    Any sugestions and comments are wellcome.
    Is it interesting for somebody or may be it's useful only for me?

Best regards. Ruslan.
-------------- next part --------------
#!/usr/bin/perl -w

use strict;
use Compress::Zlib qw(uncompress);

$DEBUG = 1;
$VERSION = '0.1';
$AEGIS_URL = 'http://fsck.com';
$HISTORY_URL = $AEGIS_URL.'/aegis/aegis.cgi?file at proj_hstry+project@rt.3.0';

if ($DEBUG) {
	print check_bk()."\n";
	print check_rep()."\n";
	print get_rep()."\n";
} else {

my @ae_csets = ae_csets();
unless (@ae_csets) {
	die "No Aegis change sets found\n";

my $last_ae_delta = $ae_csets[0]->{delta};
my @deltas = get_history();
unless (@ae_csets) {
	die "No Aegis change sets found at $HISTORY_URL\n";
foreach my $delta (@deltas) {
	next if ($delta->{delta}<=$last_ae_delta);
	my $patch = get_patch($AEGIS_URL.$delta->{href});
	print $delta->{delta}."/".$delta->{cset}." ".$delta->{comment}."\n" if ($DEBUG);
	print $patch if ($DEBUG);


sub check_bk
	my $res = `bk version`;
	my ($ver) = ($res =~ /^BitKeeper\s?version is (.*?)$/m);
	die "$res" unless ($ver);
	return $ver;

sub check_rep
	my $res = `bk config`;
	my ($desc) = ($res =~ /^\s*description: (.*?)$/im);
	die "$res" unless ($desc);
	return $desc;

sub get_rep
	my $res = `bk -R -r edit 2>&1`;
	die "$res" unless ($res);
	return $res;

sub ci
	my $delta = shift;
	my $cmd = "bk -r -R ci -l -y\"".$delta->{delta}."/".$delta->{cset}." ".$delta->{comment}."\" 2>&1";
	my $res = `$cmd`;
	die "$res" unless ($res);
	print $res if ($DEBUG);
	return $res;

sub commit
	my $delta = shift;
	my $cmd = "bk commit -d -y\"".$delta->{delta}."/".$delta->{cset}." ".$delta->{comment}."\" 2>&1";
	my $res = `$cmd`;
	die "$res" unless ($res);
	return $res;

sub ae_csets
	my @res = `bk changes`;
	my @csets;
	foreach my $str (@res) {
		my ($delta,$cset,$comment) = ($str =~ /^\s*(\d+)\/(\d+) (.*)$/);
		next unless ($delta);
		if ($DEBUG) {
			print "Delta: $delta, CSet: $cset, Comment: $comment\n";
		push (@csets, {delta => $delta, cset => $cset, comment => $comment});
	return @csets;

sub apply_patch
	my $patch = shift;
	open (PATCH, "|patch -p0 -f") || die "$!";
	print PATCH $patch;
	close PATCH;
	return 1;

sub get_patch
	my $href=shift;
	require LWP::UserAgent;
	my $ua = LWP::UserAgent->new(env_proxy => 1,
		keep_alive => 1,
		timeout => 30,
	my $response = $ua->get($href);
	die "Error while getting ", $response->request->uri,
		" -- ", $response->status_line, "\nAborting"
		unless $response->is_success;
	my $content = $response->content;
	my $output = Compress::Zlib::memGunzip(\$content) || die "Bad patch\n";
	print "Patch $href geted\n" if ($DEBUG);
	return $output;

sub get_history
	my @deltas;
	require LWP::UserAgent;
	my $ua = LWP::UserAgent->new(env_proxy => 1,
		keep_alive => 1,
		timeout => 30,
	my $response = $ua->get($HISTORY_URL);
	die "Error while getting ", $response->request->uri,
		" -- ", $response->status_line, "\nAborting"
		unless $response->is_success;
	my $content = $response->content;
	($content) = ($content =~ /<table.*?^(.*?)^<\/table>/ms);
	while ($content =~ /\G.*?^<tr class="(?:odd|even)-group">\n<td valign=top align=right>\n(\d+)\n(?:.*?\n){4}(\d+)<\/a>\n<\/td><td valign=top>\n(.*?)\n<\/td><td valign=top>\n.*?href="(.*?)"/igms) {
		my ($delta,$cset,$comment,$href) = ($1,$2,$3,$4);
		if ($DEBUG) {
			print "Delta: $delta, CSet: $cset, Comment: $comment, HREF: $href\n";
		push (@deltas, {delta => $delta, cset => $cset, comment => $comment, href => $href});
	return @deltas;

More information about the Rt-devel mailing list