=================================================================== RCS file: /cvs/cvsweb/cvsweb.cgi,v retrieving revision 1.1 retrieving revision 1.7 diff -u -p -r1.1 -r1.7 --- cvsweb/cvsweb.cgi 1996/09/28 23:31:06 1.1 +++ cvsweb/cvsweb.cgi 1997/04/30 18:25:05 1.7 @@ -28,6 +28,9 @@ require 'timelocal.pl'; require 'ctime.pl'; +$hsty_base = ""; +require 'cgi-style.pl'; + $cvsroot = '/home/ncvs'; $intro = " This is a WWW interface to the FreeBSD CVS tree. @@ -41,6 +44,10 @@ diffs between that revision and the previous one, and a form at the bottom of the page that allows you to display diffs between arbitrary revisions.

+If you would like to use this CGI script on your own web server and +CVS tree, see +the CVSWeb distribution site. +

Please send any suggestions, comments, etc. to Bill Fenner <fenner@freebsd.org> "; @@ -62,33 +69,30 @@ $scriptwhere =~ s|/$||; if (!-d $cvsroot) { &fatal("500 Internal Error",'$CVSROOT not found!'); } + +if ($q = $ENV{'QUERY_STRING'}) { + foreach (split(/&/, $q)) { + s/%(..)/sprintf("%c", hex($1))/ge; # unquote %-quoted + if (/(\S+)=(.*)/) { + $input{$1} = $2; + } else { + $input{$_}++; + } + } +} if (-d $fullname) { -# Something that would be nice to support, although I have no real -# good idea of how, would be to get full directory diff's, using -# symbolic names (revision numbers would be meaningless). -# The problem is finding a list of symbolic names that is common -# to all the files in the directory. -# opendir(DIR, $fullname) || &fatal("404 Not Found","$where: $!"); @dir = readdir(DIR); closedir(DIR); - print "Content-type: text/html\n\n"; - print "FreeBSD CVS Tree: /$where\n"; - print "\n"; - print "

\"\" "; - print "FreeBSD CVS Tree

\n
\n"; -# print "\n"; -# print "
\n"; -# print "\"\"\n"; -# print "
\n"; -# print "

FreeBSD CVS Tree

\n"; if ($where eq '') { + print &html_header("FreeBSD CVS Repository"); print $intro; } else { + print &html_header("/$where"); print $shortinstr; } print "

Current directory: /$where\n"; - print "


\n"; + print "


\n"; # Using in this manner violates the HTML2.0 spec but # provides the results that I want in most browsers. Another # case of layout spooging up HTML. @@ -102,146 +106,30 @@ if (-d $fullname) { ($updir = $scriptwhere) =~ s|[^/]+$||; print " ", &link("Previous Directory",$updir), "
"; +# print " ", +# &link("Directory-wide diffs", $scriptwhere . '/*'), "
"; } elsif (-d $fullname . "/" . $_) { print " ", &link($_ . "/", $scriptwhere . '/' . $_ . '/'), "
"; } elsif (s/,v$//) { +# TODO: add date/time? How about sorting? print " ", &link($_, $scriptwhere . '/' . $_), "
"; } } print "
\n"; -print "
-\"FreeBSD -
- www@freebsd.org -
\n"; -# print "
\n"; -# print "\"FreeBSD\n"; -# print "\n"; + print &html_footer; print "\n"; } elsif (-f $fullname . ',v') { - if ($_ = $ENV{'QUERY_STRING'}) { - s/%(..)/sprintf("%c", hex($1))/ge; # unquote %-quoted - if (/rev=([\d\.]+)/) { - $rev = $1; - open(RCS, "co -p$rev '$fullname' 2>&1 |") || - &fail("500 Internal Error", "Couldn't co: $!"); -# /home/ncvs/src/sys/netinet/igmp.c,v --> standard output -# revision 1.1.1.2 -# /* - $_ = ; - if (/^$fullname,v\s+-->\s+standard output\s*$/o) { - # As expected - } else { - &fatal("500 Internal Error", - "Unexpected output from co: $_"); - } - $_ = ; - if (/^revision\s+$rev\s*$/) { - # As expected - } else { - &fatal("500 Internal Error", - "Unexpected output from co: $_"); - } - $| = 1; - print "Content-type: text/plain\n"; - print "Content-encoding: x-gzip\n\n"; - open(GZIP, "|gzip -1 -c"); # need lightweight compression - print GZIP ; - close(GZIP); - close(RCS); + if ($input{'rev'} =~ /^[\d\.]+$/) { + &checkout($fullname, $input{'rev'}); exit; - } - if (/r1=([^&:]+)(:([^&]+))?/) { - $rev1 = $1; - $sym1 = $3; - } - if ($rev1 eq 'text') { - if (/tr1=([^&]+)/) { - $rev1 = $1; - } - } - if (/r2=([^&:]+)(:([^&]+))?/) { - $rev2 = $1; - $sym2 = $3; - } - if ($rev2 eq 'text') { - if (/tr2=([^&]+)/) { - $rev2 = $1; - } - } - if (!($rev1 =~ /^[\d\.]+$/) || !($rev2 =~ /^[\d\.]+$/)) { - &fatal("404 Not Found", - "Malformed query \"$ENV{'QUERY_STRING'}\""); - } -# -# rev1 and rev2 are now both numeric revisions. -# Thus we do a DWIM here and swap them if rev1 is after rev2. -# XXX should we warn about the fact that we do this? - if (&revcmp($rev1,$rev2) > 0) { - ($tmp1, $tmp2) = ($rev1, $sym1); - ($rev1, $sym1) = ($rev2, $sym2); - ($rev2, $sym2) = ($tmp1, $tmp2); - } -# - $difftype = "-u"; - $diffname = "Unidiff"; - if (/f=([^&]+)/) { - if ($1 eq 'c') { - $difftype = '-c'; - $diffname = "Context diff"; - } - } -# XXX should this just be text/plain -# or should it have an HTML header and then a
-	    print "Content-type: text/plain\n\n";
-	    open(RCSDIFF, "rcsdiff $difftype -r$rev1 -r$rev2 '$fullname' 2>&1 |") ||
-		&fail("500 Internal Error", "Couldn't rcsdiff: $!");
-#
-#===================================================================
-#RCS file: /home/ncvs/src/sys/netinet/tcp_output.c,v
-#retrieving revision 1.16
-#retrieving revision 1.17
-#diff -c -r1.16 -r1.17
-#*** /home/ncvs/src/sys/netinet/tcp_output.c     1995/11/03 22:08:08     1.16
-#--- /home/ncvs/src/sys/netinet/tcp_output.c     1995/12/05 17:46:35     1.17
-#
-# Ideas:
-# - nuke the stderr output if it's what we expect it to be
-# - Add "no differences found" if the diff command supplied no output.
-#
-#*** src/sys/netinet/tcp_output.c     1995/11/03 22:08:08     1.16
-#--- src/sys/netinet/tcp_output.c     1995/12/05 17:46:35     1.17 RELENG_2_1_0
-# (bogus example, but...)
-#
-	    if ($difftype eq '-u') {
-		$f1 = '---';
-		$f2 = '\+\+\+';
-	    } else {
-		$f1 = '\*\*\*';
-		$f2 = '---';
-	    }
-	    while () {
-		if (m|^$f1 $cvsroot|o) {
-		    s|$cvsroot/||o;
-		    if ($sym1) {
-			chop;
-			$_ .= " " . $sym1 . "\n";
-		    }
-		} elsif (m|^$f2 $cvsroot|o) {
-		    s|$cvsroot/||o;
-		    if ($sym2) {
-			chop;
-			$_ .= " " . $sym2 . "\n";
-		    }
-		}
-		print $_;
-	    }
-	    close(RCSDIFF);
-	    exit;
 	}
+	if ($input{'r1'} && $input{'r2'}) {
+		&dodiff($fullname, $input{'r1'}, $input{'tr1'},
+			$input{'r2'}, $input{'tr2'}, $input{'f'});
+		exit;
+	}
 	open(RCS, "rlog '$fullname'|") || &fatal("500 Internal Error",
 						"Failed to spawn rlog");
 	while () {
@@ -262,6 +150,12 @@ print "
last; } } + + if ($onlyonbranch = $input{'only_on_branch'}) { + ($onlyonbranch = $symrev{$onlyonbranch}) =~ s/\.0\././; + ($onlybranchpoint = $onlyonbranch) =~ s/\.\d+$//; + } + # each log entry is of the form: # ---------------------------- # revision 3.7.1.1 @@ -334,6 +228,7 @@ print "
foreach (sort keys %symrev) { $rev = $symrev{$_}; if ($rev =~ /^(\d+(\.\d+)+)\.0\.(\d+)$/) { + push(@branchnames, $_); # # A revision number of A.B.0.D really translates into # "the highest current revision on branch A.B.D". @@ -364,15 +259,12 @@ print "
$sel .= "

\n"; } print "\n"; print "This form allows you to request diff's between any two\n"; @@ -453,7 +359,7 @@ print "
print "name using the selection box or you may type in a numeric\n"; print "name using the type-in text box.\n"; print "

\n"; - print "

\n"; + print "\n"; print "Diffs between \n"; print "\n"; print "
Unidiff
\n"; print "Context diff
\n"; + print "Side-by-Side
\n"; print "\n"; print "
\n"; -print "
-\"FreeBSD -
- www@freebsd.org -
\n"; -# print "
\n"; -# print "\"FreeBSD\n"; -# print "\n"; + print "
\n"; + print "\n"; + print "You may select to see revision information from only\n"; + print "a single branch.\n"; + print "

\n"; + print "

\n"; + print "Branch: \n"; + print "\n"; + print "\n"; + print "
\n"; + print &html_footer; print "\n"; +} elsif ($fullname =~ s/\.diff$// && -f $fullname . ",v" && + $input{'r1'} && $input{'r2'}) { + &dodiff($fullname, $input{'r1'}, $input{'tr1'}, + $input{'r2'}, $input{'tr2'}, $input{'f'}); + exit; +} elsif (0 && (@files = &safeglob($fullname . ",v"))) { + print "Content-type: text/plain\n\n"; + print "You matched the following files:\n"; + print join("\n", @files); + # Find the tags from each file + # Display a form offering diffs between said tags } else { + # Assume it's a module name with a potential path following it. + ($module = $where) =~ s|/.*||; + $xtra = $&; + # Is there an indexed version of modules? + if (open(MODULES, "$cvsroot/CVSROOT/modules")) { + while () { + if (/^${module}\s+(\S+)/o && -d "${cvsroot}/$1" && + $module ne $1) { + &redirect($scriptname . '/' . $1 . $xtra); + } + } + } &fatal("404 Not Found","$where: no such file or directory"); } sub htmlify { - local($string) = @_; + local($string, $pr) = @_; + $string =~ s/&/&/g; $string =~ s//>/g; + if ($pr) { + $string =~ s|\bpr(\W+[a-z]+/\W*)(\d+)|$&|ig; + } + $string; } @@ -505,7 +446,7 @@ sub revcmp { local(@r2) = split(/\./, $rev2); local($a,$b); - while (($a = pop(@r1)) && ($b = pop(@r2))) { + while (($a = shift(@r1)) && ($b = shift(@r2))) { if ($a != $b) { return $a <=> $b; } @@ -518,9 +459,169 @@ sub revcmp { sub fatal { local($errcode, $errmsg) = @_; print "Status: $errcode\n"; - print "Content-type: text/html\n"; - print "\n"; - print "Error\n"; - print "Error: $errmsg\n"; + print &html_header("Error"); +# print "Content-type: text/html\n"; +# print "\n"; +# print "Error\n"; +# print "Error: $errmsg\n"; + print "Error: $errmsg\n"; + print &html_footer; exit(1); +} + +sub redirect { + local($url) = @_; + print "Status: 301 Moved\n"; + print "Location: $url\n"; + print &html_header("Moved"); +# print "Content-type: text/html\n"; +# print "\n"; +# print "Moved\n"; +# print "This document is located here.\n"; + print "This document is located here.\n"; + print &html_footer; + exit(1); +} + +sub safeglob { + local($filename) = @_; + local($dirname); + local(@results); + + ($dirname = $filename) =~ s|/[^/]+$||; + $filename =~ s|.*/||; + + if (opendir(DIR, $dirname)) { + $glob = $filename; + # transform filename from glob to regex. Deal with: + # [, {, ?, * as glob chars + # make sure to escape all other regex chars + $glob =~ s/\./\./g; + $glob =~ s/\*/.*/g; + $glob =~ s/\?/./g; + foreach (readdir(DIR)) { + if (/^${glob}$/) { + push(@results, $dirname . "/" .$_); + } + } + } + + @results; +} +sub checkout { + local($fullname, $rev) = @_; + + open(RCS, "co -p$rev '$fullname' 2>&1 |") || + &fail("500 Internal Error", "Couldn't co: $!"); +# /home/ncvs/src/sys/netinet/igmp.c,v --> standard output +# revision 1.1.1.2 +# /* + $_ = ; + if (/^$fullname,v\s+-->\s+standard output\s*$/o) { + # As expected + } else { + &fatal("500 Internal Error", + "Unexpected output from co: $_"); + } + $_ = ; + if (/^revision\s+$rev\s*$/) { + # As expected + } else { + &fatal("500 Internal Error", + "Unexpected output from co: $_"); + } + $| = 1; + print "Content-type: text/plain\n\n"; + print ; + close(RCS); +} + +sub dodiff { + local($fullname, $r1, $tr1, $r2, $tr2, $f) = @_; + + if ($r1 =~ /([^:]+)(:(.+))?/) { + $rev1 = $1; + $sym1 = $3; + } + if ($rev1 eq 'text') { + $rev1 = $tr1; + } + if ($r2 =~ /([^:]+)(:(.+))?/) { + $rev2 = $1; + $sym2 = $3; + } + if ($rev2 eq 'text') { + $rev2 = $tr2; + } + if (!($rev1 =~ /^[\d\.]+$/) || !($rev2 =~ /^[\d\.]+$/)) { + &fatal("404 Not Found", + "Malformed query \"$ENV{'QUERY_STRING'}\""); + } +# +# rev1 and rev2 are now both numeric revisions. +# Thus we do a DWIM here and swap them if rev1 is after rev2. +# XXX should we warn about the fact that we do this? + if (&revcmp($rev1,$rev2) > 0) { + ($tmp1, $tmp2) = ($rev1, $sym1); + ($rev1, $sym1) = ($rev2, $sym2); + ($rev2, $sym2) = ($tmp1, $tmp2); + } +# +# XXX Putting '-p' here is a personal preference + if ($f eq 'c') { + $difftype = '-p -c'; + $diffname = "Context diff"; + } elsif ($f eq 's') { + $difftype = '--side-by-side --width=164'; + $diffname = "Side by Side"; + } else { + $difftype = '-p -u'; + $diffname = "Unidiff"; + } +# XXX should this just be text/plain +# or should it have an HTML header and then a
+	print "Content-type: text/plain\n\n";
+	open(RCSDIFF, "rcsdiff $difftype -r$rev1 -r$rev2 '$fullname' 2>&1 |") ||
+	    &fail("500 Internal Error", "Couldn't rcsdiff: $!");
+#
+#===================================================================
+#RCS file: /home/ncvs/src/sys/netinet/tcp_output.c,v
+#retrieving revision 1.16
+#retrieving revision 1.17
+#diff -c -r1.16 -r1.17
+#*** /home/ncvs/src/sys/netinet/tcp_output.c     1995/11/03 22:08:08     1.16
+#--- /home/ncvs/src/sys/netinet/tcp_output.c     1995/12/05 17:46:35     1.17
+#
+# Ideas:
+# - nuke the stderr output if it's what we expect it to be
+# - Add "no differences found" if the diff command supplied no output.
+#
+#*** src/sys/netinet/tcp_output.c     1995/11/03 22:08:08     1.16
+#--- src/sys/netinet/tcp_output.c     1995/12/05 17:46:35     1.17 RELENG_2_1_0
+# (bogus example, but...)
+#
+	if ($difftype eq '-u') {
+	    $f1 = '---';
+	    $f2 = '\+\+\+';
+	} else {
+	    $f1 = '\*\*\*';
+	    $f2 = '---';
+	}
+	while () {
+	    if (m|^$f1 $cvsroot|o) {
+		s|$cvsroot/||o;
+		if ($sym1) {
+		    chop;
+		    $_ .= " " . $sym1 . "\n";
+		}
+	    } elsif (m|^$f2 $cvsroot|o) {
+		s|$cvsroot/||o;
+		if ($sym2) {
+		    chop;
+		    $_ .= " " . $sym2 . "\n";
+		}
+	    }
+	    print $_;
+	}
+	close(RCSDIFF);
 }