VMS::CMS – Code Management System

A couple of jobs ago I found myself maintaining a rather large system that used the DEC Code Management System software for source code change management. I needed to create branches in CMS to develop new features. Several new sets of features could be in development at the same time. I would need to merge these branches back into the production version when development and testing was completed.

I was going to have to do some serious programming to get all of this to work.  DCL just wasn’t going to cut it. I was not interested in trying to parse the output of CMS. So I started writing some C programs to interface directly to CMS using its callable interface.

I completed a couple of minor parts of my build system and realized I was going to be there forever and end up with an unflexible system if I continued using C. But I had learned enough about the CMS API to realize it would be fairly easy to interface to it from Perl. That’s when I started writing VMS::CMS.

The module came together very quickly. Within a couple of weeks I was able to write perl scripts that could talk directly with CMS to reserve and replace modules. In another couple of weeks I was able to merge two CMS classes.

The script below compares the generations in a class to the files in the current default directory and reports differences for elements that are not reserved. This helps me catch files that I might have changed without first reserving them in CMS. It displays the differences and gives me the option to reserve and/or fetch the class’s generation.

I am again working for a company with a large code base in CMS. I have written many scripts that interface to CMS to assist in system development. About 80 lines of perl allow me to report file differences between two classes – something we need for code review that used to be a manual process. Another 260 line script controls my checkins and checkouts with tracking to make sure files are checked back into the same class they were reserved from and the ability to easily switch back and forth between multiple projects.

VMS::CMS is available from CPAN.  If you use CMS and know perl, this module could allow you to write tools to improve your development procedures.

use strict;
use warnings;
use VMS::CMS qw(CMS__DIFFERENT);
use VMS::Device 'device_info';
use SmgKB;

my $kb = SmgKB::new("kb");

my $pagesize = 0;
my $x = device_info('tt');
$pagesize = $x->{TT_PAGE} - 1 if ( $x->{DEVCLASS} eq "TERM" );

my $l = VMS::CMS::new;
$l->set_library('cms$lib');

my $gen = shift;

my $el = $l->show_generation( $gen ? {GENERATION=>$gen} : () );

for my $e (@$el) {
    if (-f $e->{ELEMENT}) {
        my @oput = ();
        my $sts = $l->differences({FILENAME1=>$e->{ELEMENT},
                                   GENERATION1=>$e->{GENERATION},
                                   FILENAME2=>$e->{ELEMENT},
                                   OUTPUT_ROUTINE=>sub {
                                       push @{$_[1]},($_[0]->{OUTPUT_RECORD} ||$
                                   },
                                   USER_ARG=>\@oput});
        if ($sts == CMS__DIFFERENT) {
            print $e->{ELEMENT}." has changed\n";
            my $rl = $l->show_reservations({ELEMENT=>$e->{ELEMENT}});
            if ($rl) {
                for my $r (@$rl) {
                    print "\tGeneration $r->{GENERATION} reserved by $r->{USER}$
                }
            } else {
                if ($pagesize) {
                    while (@oput) {
                        print splice(@oput,0,$pagesize);
                        last unless @oput;
                        my $resp = $kb->read_string("Press return for more, q t$
                        chomp $resp;
                        last if $resp eq 'q';
                    }
                }
                my %opt;
                $opt{GENERATION} = $e->{GENERATION};
                my $res = $kb->read_string("Reserve? ");
                if ($res =~ /^y/i) {
                    $res = 1;
                    $opt{RESERVE} = 1;
                    my $resp = $kb->read_composed_line('Remark: ');
                    chomp $resp;
                    $opt{REMARK} = $resp;
                } elsif ($res =~ /^q/i) {
                    exit();
                } else {
                    $res = 0;
                }
                my $fet = $kb->read_string("Fetch? ");
                if ($fet =~ /^y/i) {
                    $fet = 1;
                } elsif ($fet =~ /^q/i) {
                    exit();
                } else {
                    $fet = 0;
                    $opt{NOOUTPUT} = 1;
                }
                if ($res || $fet) {
                    $l->fetch($e->{ELEMENT},\%opt);
                    my $m = VMS::CMS::get_messages;
                    print $_,$/ for @$m;
                }
            }
        }
    }
}

By Thomas Pfau

I have been using perl since the mid '90s. I had started playing with linux in late '92 and was hearing alot about perl. Instead of trying to learn shell scripting I started looking for information about how to program in perl. I still haven't really learned much about writing shell scripts. Most of what I've needed to script was not only possible in perl but easier. Since then I've used perl to automate tasks on linux, OpenVMS and Windows systems. I have written several perl modules, some of which are available on CPAN.

Leave a comment

Your email address will not be published.