#!/usr/bin/perl -w # vcsweb - a sample utility program to show off the power of # VCS:: # Do not edit this file, rather edit vcsweb.ini instead! sub BEGIN { # Read the configuration file my $configfile = 'vcsweb.ini'; unless (my $return = do $configfile) { die "Couldn't parse $configfile: $@" if $@; die "Couldn't do $configfile: $!" unless defined $return; die "Couldn't run $configfile" unless $return; } } use strict; no strict 'vars'; use CGI; use CGI::Carp 'fatalsToBrowser'; use VCS; $| = 1; my $q = new CGI; my $what = $q->param('what') || ""; if ($what =~ /\.\./) { print "Nice try."; exit 0; } my $base; my $project = $q->param('project'); $base = $projects{$project} if (defined $project); $base .= '/' if (defined $base && $base !~ m|/$|); print $q->header; if (defined $base) { print qq|vcsweb: $project

vcsweb: $project

|; } else { print qq|vcsweb

vcsweb

|; } if (not defined $base) { choose_project($q); } elsif (defined $q->param('show')) { show($q, $base, $what); } elsif (defined $q->param('diff')) { diff($q, $base, $what); } else { dir($q, $base, $what); } sub choose_project { my $q = shift; my $url; my $bgcol = '#ffffff'; print qq|
|; foreach my $project (sort keys %projects) { $q->param('project', $project); $url = $q->self_url; print qq|\n|; $bgcol = ($bgcol eq "#ffffff") ? "#ddddff" : "#ffffff"; } print "
Choose project to view...
$project


"; } sub html_encode { my $line = shift; $line =~ s|&|&|g; $line =~ s|\>|>|g; $line =~ s|\<|<|g; $line =~ s| |\ |g; $line; } sub diff { my($q, $base, $what) = @_; my $file = $base . $what; print qq|
/$what

"; print "


"; } # parse_diff takes a unified diff and returns a list of \%diff # %diff holds oldline=>num, newline=>num, difflines=>\list of \%difflines # %difflines holds old=>text, new=>text # It still needs the "flush" subroutine, just below # # And example structure follows, with one changed line (1), one empty # line which has not changed (2), one added line (3), and one deleted # line (15) # # ( # { # 'oldline' => 1, # 'newline' => 1, # 'difflines' => ( # { # 'old' => '# This is version 1.12', # 'new' => '# This is version 1.13' # }, # { # 'old' => '', # 'new' => '' # }, # { # 'old' => '', # 'new' => 'use DBI;' # } # ) # }, # { # 'oldline' => 15, # 'newline' => 16, # 'difflines' => ( # { # 'old' => 'use strict;', # 'new' => '' # }, # ) # } # ) sub parse_diff { my $diff_text = shift; my(@left, @right); my @difflist; # this holds a list of \%diff my $state = "dump"; my @difflines; foreach my $line (split "\n", $diff_text) { my ($oldline,$newline) = $line =~ /@@ \-(\d+).*\+(\d+).*@@/; if ($oldline) { if (@difflist) { $difflist[-1]->{'difflines'} = [ @difflines ]; @difflines = (); } push @difflist, { oldline => $oldline, newline => $newline, difflines => \@difflines, }; } elsif ($line =~ s|^\+||) { if ($state eq "dump") { push @difflines, { old => '', new => $line }; } else { $state = "PreChange"; push @right, $line; } } elsif ($line =~ s|^-||) { $state = "PreChangeRemove"; push @left, $line; } elsif ($line =~ m|^\\|) { } else { if ($state eq "PreChangeRemove") { push @difflines, map { { old => $_, new => '' } } @left; } elsif ($state eq "PreChange") { for (my $j = 0; $j < @left || $j < @right ; $j++) { push @difflines, { old => ($j < @left ? $left[$j] : ''), new => ($j < @right ? $right[$j] : ''), }; } } @left = (); @right = (); $state = "dump"; $line =~ s|^.||; push @difflines, { old => $line, new => $line }; } } if (@difflist) { my @newdifflines = @difflines; $difflist[-1]->{'difflines'} = \@newdifflines; } @difflist; } sub show { my($q, $base, $what) = @_; $q->delete('show'); my $file = $base . $what; print qq|


/$what

"; return; } my($version, $number, $author, $tags, $date, $reason, $diffversion, $url); my @versions = reverse $obj->versions; my @diffversions = @versions; shift @diffversions; foreach $version (@versions) { $number = $version->version; $author = $version->author; $tags = join ", ", sort $version->tags; $date = $version->date; $reason = html_encode($version->reason); $reason =~ s|\n|
|g; $diffversion = (@diffversions) ? (shift @diffversions)->version : ""; $q->param('to', $number); $q->param('from', $diffversion); $q->param('what', $what); $q->param('diff', 1); $url = $q->self_url; print qq| |; print qq|| if $tags; print qq||; print qq|| if $diffversion; print qq|
Revision $number $date
Tags: $tags
$author$reason
Diff with $diffversion...

|; } print "


"; } sub dir { my($q, $base, $what) = @_; my($file, $relfile, $name, $url, $thing); my $dir = $base . $what; print qq|
|; my $bgcol = "#ffffff"; my $d = VCS::Dir->new($dir); unless (defined $d) { print "
/$what

Not a VCS dir!"; return; } foreach $thing ($d->content) { next unless ref($thing); $file = $thing->path; ($name = $file) =~ s|$dir||; ($relfile = $file) =~ s|$base||; if (ref($thing) =~ /::Dir$/) { $q->param('what', "$relfile"); $url = $q->self_url; print qq| $name\n|; $bgcol = ($bgcol eq "#ffffff") ? "#ddddff" : "#ffffff"; } elsif (ref($thing) =~ /::File$/) { $q->param('what', "$relfile"); $q->param('show', 1); $url = $q->self_url; $q->delete('show'); print qq| $name\n|; $bgcol = ($bgcol eq "#ffffff") ? "#ddddff" : "#ffffff"; } } print "


"; } __END__ =head1 NAME vcsweb - a web interface to the VCS suite =head1 SYNOPSIS http://hostname/location/vcsweb.cgi =head1 DESCRIPTION C is a demonstration of the power of the C (Version Control System) suite, providing a web interface to projects under version control. A project under any VCS can be viewed, provided there is a C-compliant module for that system. To use, either copy or symlink C, C and C to somewhere appropriate in the document root of a web-server, and copy C. Modify C to taste. =head1 SEE ALSO L.