Original sources from CVS-1.4A2 munged to fit our directory structure.

This commit is contained in:
Nate Williams 1995-03-31 07:45:33 +00:00
parent 36d59faf6a
commit 33afdd16ab
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/cvs/dist/; revision=7514
92 changed files with 8903 additions and 4944 deletions

View File

@ -1,4 +1,4 @@
@(#)README 1.8 92/04/10 $CVSid: @(#)README 1.12 94/09/25 $
This "contrib" directory is a place holder for code/scripts sent to This "contrib" directory is a place holder for code/scripts sent to
me by contributors around the world. This READM file will be kept me by contributors around the world. This READM file will be kept
@ -66,3 +66,22 @@ Contents of this directory:
$CVSROOT/CVSROOT/history file, as it can grow quite $CVSROOT/CVSROOT/history file, as it can grow quite
large after extended use. large after extended use.
Contributed by David G. Grubbs <dgg@ksr.com> Contributed by David G. Grubbs <dgg@ksr.com>
sccs2rcs A C-shell script that can convert (some) SCCS files
into RCS files, retaining the info contained in the
SCCS file (like dates, author, and log message).
Contributed by Ken Cox <kenstir@viewlogic.com>.
intro.doc A user's view of what you need to know to get
started with CVS.
Contributed by <Steven.Pemberton@cwi.nl>.
rcs2sccs A shell script to convert simple RCS files into
SCCS files, originally gleaned off the network
somewhere (originally by "kenc") and modified by
Jerry Jelinek <jerry@rmtc.Central.Sun.COM> and
Brian Berliner <berliner@sun.com> to increase
robustness and add support for one-level of branches.
rcs2log A shell script to create a ChangeLog-format file
given only a set of RCS files.
Contributed by Paul Eggert <eggert@twinsun.com>.
clmerge A perl script to handle merge conflicts in GNU
style ChangeLog files .
Contributed by Tom Tromey <tromey@busco.lanl.gov>.

View File

@ -1,6 +1,6 @@
#!/usr/bin/perl -- # -*-Perl-*- #!/usr/bin/perl -- # -*-Perl-*-
# #
# cln_hist.pl,v 1.1 1992/04/10 03:04:15 berliner Exp # $Id: cln_hist.pl,v 1.1 1992/04/10 03:04:15 berliner Exp $
# Contributed by David G. Grubbs <dgg@ksr.com> # Contributed by David G. Grubbs <dgg@ksr.com>
# #
# Clean up the history file. 10 Record types: MAR OFT WUCG # Clean up the history file. 10 Record types: MAR OFT WUCG

View File

@ -1,6 +1,6 @@
#!/usr/bin/perl -- # -*-Perl-*- #!/usr/bin/perl -- # -*-Perl-*-
# #
# cvs_acls.pl,v 1.2 1992/04/11 16:01:24 berliner Exp # $Id: cvs_acls.pl,v 1.2 1992/04/11 16:01:24 berliner Exp $
# #
# Access control lists for CVS. dgg@ksr.com (David G. Grubbs) # Access control lists for CVS. dgg@ksr.com (David G. Grubbs)
# #

View File

@ -1,5 +1,5 @@
#! /bin/sh #! /bin/sh
# cvscheck,v 1.2 1992/04/10 03:04:19 berliner Exp # $Id: cvscheck,v 1.2 1992/04/10 03:04:19 berliner Exp $
# #
# cvscheck - identify files added, changed, or removed # cvscheck - identify files added, changed, or removed
# in CVS working directory # in CVS working directory

View File

@ -1,4 +1,4 @@
.\" cvscheck.man,v 1.1 1992/04/10 03:04:20 berliner Exp .\" $Id: cvscheck.man,v 1.1 1992/04/10 03:04:20 berliner Exp $
.\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> .\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net>
.TH CVSCHECK LOCAL "4 March 1991" FLUKE .TH CVSCHECK LOCAL "4 March 1991" FLUKE
.SH NAME .SH NAME

View File

@ -1,4 +1,4 @@
.\" cvshelp.man,v 1.1 1992/04/10 03:04:21 berliner Exp .\" $Id: cvshelp.man,v 1.1 1992/04/10 03:04:21 berliner Exp $
.\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> .\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net>
.\" Full space in nroff; half space in troff .\" Full space in nroff; half space in troff
.de SP .de SP

View File

@ -1,5 +1,5 @@
#! /bin/sh #! /bin/sh
# descend,v 1.1 1992/04/03 05:22:52 berliner Exp # $Id: descend,v 1.1 1992/04/03 05:22:52 berliner Exp $
# #
# descend - walk down a directory tree and execute a command at each node # descend - walk down a directory tree and execute a command at each node

View File

@ -1,4 +1,4 @@
.\" descend.man,v 1.1 1992/04/03 05:22:53 berliner Exp .\" $Id: descend.man,v 1.1 1992/04/03 05:22:53 berliner Exp $
.TH DESCEND 1 "31 March 1992" .TH DESCEND 1 "31 March 1992"
.SH NAME .SH NAME
descend \- walk directory tree and execute a command at each node descend \- walk directory tree and execute a command at each node

View File

@ -1,7 +1,7 @@
#!/usr/bin/perl #!/usr/bin/perl
# #
# Support for importing a source collection into CVS. # Support for importing a source collection into CVS.
# Trys to prevent the user from the most common pitfalls (like creating # Tries to prevent the user from the most common pitfalls (like creating
# new top-level repositories or second-level areas accidentally), and # new top-level repositories or second-level areas accidentally), and
# cares to do some of the `dirty' work like maintaining the modules # cares to do some of the `dirty' work like maintaining the modules
# database accordingly. # database accordingly.
@ -10,8 +10,22 @@
# #
require "complete.pl"; require "complete.pl";
require "getopts.pl";
sub scan_opts
{
&Getopts("n");
$dont_do_it = "-n" if $opt_n;
die "usage: $0 [-n] [moduledir]\n" .
" -n: don't do any commit, show only\n"
unless $#ARGV <= 0;
$moduledir = $ARGV[0] if $#ARGV == 0;
}
sub lsdir sub lsdir
{ {
# find all subdirectories under @_ # find all subdirectories under @_
@ -165,12 +179,29 @@ sub checktag
} }
&scan_opts;
&term_init; &term_init;
&cvs_init; &cvs_init;
if(! $moduledir) {
@dirs = &lsdir(".");
print "${so}Import from which directory?${se}\n";
@dirs = (@dirs, ".");
&list(@dirs);
$moduledir = &Complete("Which? [.]: ", @dirs);
$moduledir = "." unless $moduledir ne "";
}
chdir $moduledir || die "Cannot chdir to $moduledir\n";
print "${so}Available repositories:${se}\n"; print "${so}Available repositories:${se}\n";
&list(@reps); &list(@reps);
# the following kludge prevents the Complete package from starting
# over with the string just selected; Complete should better provide
# some reinitialize method
$Complete'return = ""; $Complete'r = 0;
$selected = $selected =
&Complete("Enter repository (<TAB>=complete, ^D=show): ", &Complete("Enter repository (<TAB>=complete, ^D=show): ",
@reps); @reps);
@ -188,9 +219,6 @@ print "\n${so}Selected repository:${se} ${us}$rep${ue}\n";
print "${so}Existent areas in this repository:${se}\n"; print "${so}Existent areas in this repository:${se}\n";
&list(@areas); &list(@areas);
# the following kludge prevents the Complete package from starting
# over with the string just selected; Complete should better provide
# some reinitialize method
$Complete'return = ""; $Complete'r = 0; $Complete'return = ""; $Complete'r = 0;
$selected = $selected =
@ -304,21 +332,34 @@ system("cvs co modules") && die "${us}failed.\n${ue}";
print "${so}Inserting new module...${se}\n"; print "${so}Inserting new module...${se}\n";
open(ED, "|ed modules/modules") || die "${us}Cannot start ed${ue}\n"; open(ED, "|ed modules/modules") || die "${us}Cannot start ed${ue}\n";
print(ED "${cmd}${modname}" . ' ' x (32 - length($modname)) . print(ED "${cmd}${modname}" . ' ' x (16 - length($modname)) .
"$area/${modpath}\n.\nw\nq\n"); "$area/${modpath}\n.\nw\nq\n");
close(ED); close(ED);
print "${so}Commiting new modules database...${se}\n"; print "${so}Commiting new modules database...${se}\n";
system("cvs commit -m \" ${modname} --> $area/${modpath}\" modules") system("cvs $dont_do_it commit -m \" " .
"${modname} --> $area/${modpath}\" modules")
&& die "Commit failed\n"; && die "Commit failed\n";
system("cvs release -dQ modules"); system("cvs $dont_do_it release -dQ modules");
print "${so}Importing source. Enter a commit message in the editor.${se}\n"; print "${so}Importing source. Enter a commit message in the editor.${se}\n";
system("cvs import $area/$modpath $vtag $rtag"); system("cvs $dont_do_it import $area/$modpath $vtag $rtag");
print "${so}You are done now. Go to a different directory, perform a${se}\n". print "${so}You are done now. Go to a different directory, perform a${se}\n".
"${us}cvs co ${modname}${ue} ${so}command, and see if your new module" . "${us}cvs co ${modname}${ue} ${so}command, and see if your new module" .
" builds ok.${se}\n"; " builds ok.${se}\n";
if($dont_do_it) {
print <<END
${so}Since you did not allow to commit anything, you'll have${se}
${so}to remove the edited modules' database yourself.${se}
${so}To do this, perform a${se}
${us}cd ${moduledir}; cvs release -dQ modules${ue}
${so}command.${se}
END
;
}

View File

@ -1,5 +1,9 @@
#!/usr/bin/perl #! /local/bin/perl
# Modified by woods@web.apc.org to add support for mailing 3/29/93
# use '-m user' for each user to receive cvs log reports
# and use '-f logfile' for the logfile to append to
#
# Modified by berliner@Sun.COM to add support for CVS 1.3 2/27/92 # Modified by berliner@Sun.COM to add support for CVS 1.3 2/27/92
# #
# Date: Tue, 6 Aug 91 13:27 EDT # Date: Tue, 6 Aug 91 13:27 EDT
@ -11,94 +15,134 @@
# now the output looks like this: # now the output looks like this:
# #
# ************************************** # **************************************
# date: Tuesday, August 6, 1991 @ 13:17 # Date: Tuesday, August 6, 1991 @ 13:17
# author: samborn # Author: samborn
#
# Update of /elmer/cvs/CVSROOT.adm # Update of /elmer/cvs/CVSROOT.adm
# In directory astro:/home/samborn/CVSROOT.adm # In directory astro:/home/samborn/CVSROOT.adm
# #
# Modified Files: # Modified Files:
# test3 # test3
#
# Added Files: # Added Files:
# test6 # test6
#
# Removed Files: # Removed Files:
# test4 # test4
#
# Log Message: # Log Message:
# wow, what a test # wow, what a test
# #
# RCS: 1.4 /elmer/cvs/CVSROOT.adm/test3,v # File: test.3 Status: Up-to-date
# RCS: 1.1 /elmer/cvs/CVSROOT.adm/test6,v # Version: 1.4 Thu Apr 29 14:47:07 EDT 1993
# RCS: 1.1 /elmer/cvs/CVSROOT.adm/Attic/test4,v # File: test6 Status: Up-to-date
# Version: 1.1 Thu Apr 29 14:47:33 EDT 1993
# File: test4 Status: Up-to-date
# Version: 1.1 Thu Apr 29 14:47:46 EDT 1993
# #
# $cvsroot = $ENV{'CVSROOT'};
# turn off setgid # turn off setgid
# #
$) = $(; $) = $(;
#
# parse command line arguments # parse command line arguments
# #
@files = split(/ /,$ARGV[0]); while (@ARGV) {
$logfile = $ARGV[1]; $arg = shift @ARGV;
$cvsroot = $ENV{'CVSROOT'};
if ($arg eq '-m') {
$users = "$users " . shift @ARGV;
} elsif ($arg eq '-f') {
($logfile) && die "Too many '-f' args";
$logfile = shift @ARGV;
} else {
($donefiles) && die "Too many arguments!\n";
$donefiles = 1;
@files = split(/ /, $arg);
}
}
$srepos = shift @files;
$mailcmd = "| Mail -s 'CVS update: $srepos'";
#
# Some date and time arrays # Some date and time arrays
# #
@mos = (January,February,March,April,May,June,July,August,September, @mos = (January,February,March,April,May,June,July,August,September,
October,November,December); October,November,December);
@days = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); @days = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
#
# get login name # get login name
# #
$login = getlogin || (getpwuid($<))[0] || "nobody"; $login = getlogin || (getpwuid($<))[0] || "nobody";
#
# open log file for appending # open log file for appending
# #
if ((open(OUT, ">>" . $logfile)) != 1) { open(OUT, ">>" . $logfile) || die "Could not open(" . $logfile . "): $!\n";
die "Could not open logfile " . $logfile . "\n"; if ($users) {
$mailcmd = "$mailcmd $users";
open(MAIL, $mailcmd) || die "Could not Exec($mailcmd): $!\n";
} }
# # print out the log Header
# Header
# #
print OUT "\n"; print OUT "\n";
print OUT "**************************************\n"; print OUT "**************************************\n";
print OUT "date: " . $days[$wday] . ", " . $mos[$mon] . " " . $mday . ", 19" . $year . print OUT "Date:\t$days[$wday] $mos[$mon] $mday, 19$year @ $hour:" . sprintf("%02d", $min) . "\n";
" @ " . $hour . ":" . sprintf("%02d", $min) . "\n"; print OUT "Author:\t$login\n\n";
print OUT "author: " . $login . "\n";
# if (MAIL) {
#print the stuff on stdin to the logfile print MAIL "\n";
print MAIL "Date:\t$days[$wday] $mos[$mon] $mday, 19$year @ $hour:" . sprintf("%02d", $min) . "\n";
print MAIL "Author:\t$login\n\n";
}
# print the stuff from logmsg that comes in on stdin to the logfile
# #
open(IN, "-"); open(IN, "-");
while(<IN>) { while (<IN>) {
print OUT $_; print OUT $_;
if (MAIL) {
print MAIL $_;
}
} }
close(IN); close(IN);
print OUT "\n"; print OUT "\n";
#
# after log information, do an 'cvs -Qn status' on each file in the arguments. # after log information, do an 'cvs -Qn status' on each file in the arguments.
# #
for $file (@files[1..$#files]) { while (@files) {
if ($file eq "-") { $file = shift @files;
last; if ($file eq "-") {
} print OUT "[input file was '-']\n";
open(RCS,"-|") || exec 'cvs', '-Qn', 'status', $file; if (MAIL) {
while (<RCS>) { print MAIL "[input file was '-']\n";
if (substr($_, 0, 7) eq " RCS") { }
print OUT; last;
} }
}
close (RCS); open(RCS, "-|") || exec 'cvs', '-Qn', 'status', $file;
while (<RCS>) {
if (/^[ \t]*Version/ || /^File:/) {
print OUT;
if (MAIL) {
print MAIL;
}
}
}
close(RCS);
} }
close (OUT); close(OUT);
die "Write to $logfile failed" if $?;
close(MAIL);
die "Pipe to $mailcmd failed" if $?;
exit 0;
### Local Variables:
### eval: (fundamental-mode)
### End:

View File

@ -11,7 +11,7 @@
# Especially if they regularly beat on the same directory. Anyway if you # Especially if they regularly beat on the same directory. Anyway if you
# think anyone would be interested here it is. # think anyone would be interested here it is.
# #
# mfpipe.pl,v 1.1 1992/03/02 01:22:41 berliner Exp # $Id: mfpipe.pl,v 1.1 1992/03/02 01:22:41 berliner Exp $
# #
# #
# File: mfpipe # File: mfpipe

View File

@ -1,3 +1,552 @@
Tue Jun 1 00:00:03 1993 Per Cederqvist (ceder@lysator.liu.se)
* Release 1.05. (This release was promised before the end of May,
but I didn't quite make it. No, I didn't fake the date above).
Mon May 31 01:32:25 1993 Per Cederqvist (ceder@lysator.liu.se)
* Removed the elib sub-directory. Users must now get the Elib
library separately.
* pcl-cvs.texinfo: Document it.
* pcl-cvs-lucid.el: A new version, supplied by Jamie Zawinsky,
added.
* pcl-cvs Id 68: Transform RCS keywords
* Makefile (pcl-cvs-$(VER)): Remove the $ signs in most files in
the distribution.
* pcl-cvs Id 76: Extra " in cvs-mode-add.
* pcl-cvs.el (cvs-mode-add): Don't add the extra level of quotes
around the log message, since it doesn't work with CVS.
* pcl-cvs Id 56: '-d <CVSROOT>' support in pcl-cvs
* pcl-cvs.el (cvs-change-cvsroot): New function.
* pcl-cvs Id 77: *cvs* isn't cleared properly
* pcl-cvs.el (cvs-do-update): Always erase the *cvs* buffer and
re-create the collection.
* pcl-cvs.el (cvs-do-update): Set mode-line-process in the *cvs*
buffer.
* pcl-cvs.el (cvs-mode): Reset mode-line-process.
* pcl-cvs Id 59: sort .cvsignore alphabetically!
* pcl-cvs.el (cvs-sort-ignore-file): New variable.
* pcl-cvs.el (cvs-mode-ignore): Use it.
* pcl-cvs.texinfo: Document it.
* pcl-cvs Id 75: Require final newline.
* pcl-cvs.el (cvs-commit-buffer-require-final-newline): New
variable.
* pcl-cvs.el (cvs-edit-done): Use it.
* pcl-cvs.texinfo: Document it.
* pcl-cvs Id 72: make clean deletes lucid-emacs.el
* dist-makefile (ELCFILES): Fixed a typo.
* pcl-cvs Id 46: "cvs remove f" "touch f" "cvs update f" -> parse err.
* pcl-cvs.el (cvs-fileinfo->type): New type: REM-EXIST.
* pcl-cvs.el (cvs-shadow-entry-p): A REMOVED that follows a
REM-EXIST is a shadow.
* pcl-cvs.el (cvs-parse-stderr): Recognize the "should be removed
and is still there" message.
* pcl-cvs.el (cvs-pp): Recognize REM-EXIST.
* pcl-cvs.el (cvs-mode-undo-local-changes): Recognize and complain
about REM-EXIST. Defensive test added: complain about unknown types.
* pcl-cvs.el (cvs-mode-add): Add an extra level of quotes around
the log message. This is apparently needed by RCVS. <This change
has been removed. --ceder>.
* pcl-cvs.el (cvs-parse-stderr): Ignore output from RCVS.
Tue Apr 27 00:48:40 1993 Per Cederqvist (ceder@lysator.liu.se)
* pcl-cvs.el (cvs-startup-message): Now a defconst instead of a
defvar.
* pcl-cvs.el (cvs-mode-commit): Add a defvar for it.
* dist-makefile (EMACS): Use $(EMACS) instead of hard-coding 'emacs'.
Sat Apr 17 12:47:10 1993 Per Cederqvist (ceder@lysator.liu.se)
* Release 1.04.
* pcl-cvs.texinfo: Updated the Contributors node.
* pcl-cvs Id 58: Lucid GNU Emacs support
* pcl-cvs-lucid.el: New file, contributed by the people at Lucid.
* pcl-cvs.el: Autoload pcl-cvs-lucid if running in an Lucid GNU
Emacs.
* compile-all.el: (files-to-compile): Add pcl-cvs-lucid.
* dist-makefile (ELFILES, ELCFILES): Dito.
* pcl-cvs Id 55: cvs-diff-backup swaps old and new version.
* pcl-cvs.el (cvs-diff-backup-extractor): Old version should be
first.
* pcl-cvs.el (cvs-mode-diff-backup): Call cvs-backup-diffable
correctly.
* pcl-cvs Id 64: elib substitute
* dist-makefile (install): Warn about Elib.
* pcl-cvs.texinfo: Talk about Elib.
* pcl-cvs Id 50: Committing the *commit* buffer twice.
* pcl-cvs.el (cvs-edit-done): Report an error if cvs-commit-list
is empty, and empty it when the commit is done.
* pcl-cvs Id 56: '-d <CVSROOT>' support.
* pcl-cvs.el (cvs-cvsroot): New variable.
* pcl-cvs.el (cvs-do-update, all callers of cvs-execute-list): Use
it everywhere CVS is called, to override CVSROOT.
* pcl-cvs.texinfo (Customization): Document it.
Thu Apr 1 00:34:55 1993 Per Cederqvist (ceder@lysator.liu.se)
* pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): Exit status nil
from call-process means everything was successful in some Emacs
versions.
* pcl-cvs.el (cvs-mode-map): Bind "q" to bury-buffer.
* pcl-cvs.texinfo: Document it.
Thu Mar 11 00:05:03 1993 Per Cederqvist (ceder@lysator.liu.se)
* Release 1.03-Emerge (not released).
* Makefile (pcl-cvs-$(VER)): Don't includ elib-dll-debug.el in the
distribution. (It's included as elib/dll-debug.el).
* pcl-cvs.el (cvs-mode): Document the "e" key (cvs-mode-emerge).
Tue Mar 9 00:02:57 1993 Per Cederqvist (ceder@lysator.liu.se)
* pcl-cvs.texinfo (Emerge): New node.
* pcl-cvs.el (cvs-kill-buffer-visiting): New function.
* pcl-cvs.el (cvs-mode-emerge): Handle Conflict and Merged files.
* pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): Handle any revision.
* pcl-cvs.el (cvs-fileinfo-*): Store base-revision instead of
backup-file.
* pcl-cvs.el (cvs-backup-diffable): The file is only diffable if
the backup file is readable.
* pcl-cvs.el (cvs-mode-map): Bind "e" to cvs-mode-emerge instead
of cvs-mode-find-file (which is anyhow bound to "f").
Mon Mar 8 23:06:52 1993 Per Cederqvist (ceder@lysator.liu.se)
* pcl-cvs.el (cvs-mode-emerge): New function. Currently only
handles emerge of Modified files.
* pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): New function.
Sun Jan 24 20:07:18 1993 Per Cederqvist (ceder@lysator.liu.se)
* elib-dll-debug.el: Moved to elib.
Mon Jan 18 00:35:59 1993 Per Cederqvist (ceder@mauritz)
* pcl-cvs.el (cvs-do-update): Added a probably unnecessary sit-for.
* Release 1.03-Elib-0.05.1 (not released).
* Elib 0.05 compatibility:
* elib-dll-debug.el, pcl-cvs-buffer.el, test-dll.el: Fix the
require strings.
* pcl-cvs.el (cvs-pp): Insert the string.
* Release 1.03-Elib-0.05 (not released).
* elib: New directory, containing the parts of elib that are
required for pcl-cvs. Changes to the files in that directory
that are present in Elib are documented in the ChangeLog of
Elib, not here.
* Makefile (pcl-cvs-$(VER)): Copy the new dir to the distribution.
* dist-makefile (ELFILES, ELCFILES): Don't include the Elib files.
Fri Jan 8 02:43:49 1993 Per Cederqvist (ceder@konrad)
* pcl-cvs.el (cvs-mode-map): Bind "e" to cvs-mode-find-file, like
in dired.
Sun Jan 3 23:25:13 1993 Per Cederqvist (ceder@konrad)
* elib-dll.el, elib-node.el, cookie.el: Moved to the elib package.
Pcl-cvs now requires elib.
Tue Dec 29 22:06:57 1992 Per Cederqvist (ceder@konrad)
* pcl-cvs.el: Tracked the latest (last?) rename of all functions
in cookie.el.
Thu Sep 24 00:29:16 1992 Per Cederqvist (ceder@robert)
* pcl-cvs.texinfo (Archives): This version is not distributed with
CVS 1.3, so don't claim that it is.
Fri Aug 21 15:17:08 1992 Per Cederqvist (ceder@maskros)
* pcl-cvs.el (cvs-parse-stderr): Fixed two "(set head" that should
be "(setq head".
Thu Aug 20 05:53:58 1992 Per Cederqvist (ceder@robin)
* cookie.el: Changes to this file is documented in the ChangeLog
of elib in the future.
Tue Aug 18 03:30:28 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el: Don't use cookie-last-tin (which no longer exists).
* cookie.el: Use prefix cookie:: for internal functions.
* cookie.el: (cookie:enter-after, cookie:enter-before,
cookie:nth-cookie): Implemented.
* cookie.el: No longer define (impl).
* cookie.el: More renames:
cookie:next-cookie -> cookie:goto-next-tin
cookie:previous-cookie -> cookie:goto-previous-tin
tin-next -> cookie:next-tin
tin-previous -> cookie:previous-tin
tin-nth -> cookie:nth-tin
tin-delete -> cookie:delete-tin
cookie:collect -> cookie:collect-cookies
cookie:tin-collect -> cookie:collect-tins
(new) -> cookie:tin-collect-cookies
(new) -> cookie:tin-collect-tins
cookie:refresh -> cookie:refresh-all
tin-invalidate-tins -> cookie:invalidate-tins
Mon Aug 17 01:39:49 1992 Per Cederqvist (ceder@robin)
* cookie.el (cookie:set-buffer-bind-dll-let*): New macro. Used in
many places instead of cookie:set-buffer-bind-dll.
* cookie.el (cookie:set-buffer-bind-dll): Renamed the macro
cookie:set-buffer to this.
* pcl-cvs.el (cvs-use-temp-buffer): Set default-directory.
Sun Aug 16 20:51:30 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-add-sub): Fixed call to cvs-add-file-update-buffer.
Sat Aug 8 20:28:21 1992 Per Cederqvist (ceder@robin)
* Release 1.03-Cookie-II (not released).
* pcl-cvs.el (cvs-mode-diff-cvs): Don't care about the exit status
from ``cvs diff''.
* pcl-cvs.el (cvs-mode): Document cvs-mode-undo-local-changes.
* pcl-cvs.el (cvs-diffable): New function.
* pcl-cvs.el: Use the new cookie package.
* pcl-cvs.el (cvs-cookie-handle): New variable.
* pcl-cvs.el (cvs-do-update): User the new cookie:create
interface, and cookie:clear if the buffer already existed. Make
the buffer read-only.
* pcl-cvs.el (cvs-mode-next-line, cvs-mode-previous-line): New
functions (used instead of cookie:next-cookie and
cookie:previous-cookie).
* cookie.el: Major redesign. The handle that is passed to all
cookie functions is now a new datatype, and not the buffer that
the cookies resides in. This way it is possible to have more than
one set of cookies in a buffer. Things that used to be
buffer-local variables are now fields in the handle data type.
cookie-last-tin is no longer available.
* cookie.el (cookie:create): The buffer is not cleared, nor set to
be read-only.
* cookie.el (cookie:next-cookie, cookie:previous-cookie): Since
the first argument is now a handle and not a buffer, these can no
longer be called interactively. You have to write a small wrapper
about them.
* cookie.el (cookie:buffer): New function.
Tue Aug 4 03:02:25 1992 Per Cederqvist (ceder@robert)
* pcl-cvs.texinfo (Bugs): Renamed "Reporting bugs and ideas" to
"Bugs" and added a table of known bugs/FAQ:s.
Mon Aug 3 00:19:39 1992 Per Cederqvist (ceder@robert)
* pcl-cvs.el, pcl-cvs.texinfo: Big Renaming Time!
The commands that operate in the *cvs* buffer:
cvs-add-change-log-entry-other-window -> cvs-mode-add-change-log-entry-other-window
cvs-mark-all-files -> cvs-mode-mark-all-files
cvs-revert-updated-buffers -> cvs-mode-revert-updated-buffers
cvs-undo-local-changes -> cvs-mode-undo-local-changes
cvs-unmark-up -> cvs-mode-unmark-up
cvs-acknowledge -> cvs-mode-acknowledge
cvs-unmark-all-files -> cvs-mode-unmark-all-files
cvs-add -> cvs-mode-add
cvs-diff-backup -> cvs-mode-diff-backup
cvs-commit -> cvs-mode-commit
cvs-diff-cvs -> cvs-mode-diff-cvs
cvs-find-file -> cvs-mode-find-file
cvs-update-no-prompt -> cvs-mode-update-no-prompt
cvs-ignore -> cvs-mode-ignore
cvs-log -> cvs-mode-log
cvs-mark -> cvs-mode-mark
cvs-find-file-other-window -> cvs-mode-find-file-other-window
cvs-remove-file -> cvs-mode-remove-file
cvs-status -> cvs-mode-status
cvs-remove-handled -> cvs-mode-remove-handled
cvs-unmark -> cvs-mode-unmark
* pcl-cvs.el (cvs-cvs-diff-flags): Variable deleted.
* pcl-cvs.el (cvs-diff-cvs): Use cvs-diff-flags instead.
* pcl-cvs.texinfo (Customization): Update the doc.
* pcl-cvs.el (cvs-diff-cvs): Handle exit status 0 (no diffs), 1
(diffs) and other (error).
* pcl-cvs.el (cvs-execute-list): Add support for this kind of
thing.
* Revert buffers for committed files:
* pcl-cvs.el (cvs-auto-revert-after-commit): New variable.
* pcl-cvs.texinfo (Committing changes, Customization): Document
it.
* pcl-cvs.el (cvs-after-commit-function): New function.
* pcl-cvs.el (cvs-execute-list): Return the exit status or nil.
* pcl-cvs.el (cvs-edit-done, cvs-diff-cvs, cvs-remove-file,
cvs-undo-local-changes, cvs-add, cvs-status, cvs-log): Use the
exit status to generate an error message.
* pcl-cvs.el (cvs-do-update): It should be "cvs -n update -l", not
"cvs -l update -n". Put the -n and/or -l in the message that is
displayed in the *cvs* buffer during the update.
Sat Aug 1 00:55:49 1992 Per Cederqvist (ceder@robert)
* cookie.el (cookie-sort): New function.
* cookie.el (cookie-clear): Rewritten. No longer clears all local
variables.
Tue Jul 28 17:21:17 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-parse-stderr): Try to handle the output from RCS
when it is compiled without DIFF3_BIN and a conflict occurs.
* pcl-cvs.texinfo (Getting Started): Fixed typo.
* pcl-cvs-startup.el (cvs-update-other-window): Make the autoload
be interactive.
Mon Jul 27 19:36:40 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-revert-updated-buffers, cvs-revert-fileinfo):
New functions.
* pcl-cvs.texinfo (Reverting your buffers): Document it.
* pcl-cvs.el (cvs-fileinfo->full-path): New function.
* pcl-cvs.el (cvs-full-path): Use it.
* cookie.el (cookie-map, cookie-map-reverse): Better doc-
string. Removed the unused local variable 'result'.
* compile-all.el: Renamed elib-files to files-to-compare.
* compile-all.el (compile-pcl-cvs): Bind load-path in a let
statement instead of globally.
Thu Jul 23 19:02:41 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-do-update): Check that CVSROOT is set.
* pcl-cvs.el (cvs-diff-cvs): Check that cvs-cvs-diff-flags is a
list.
* pcl-cvs.el (cvs-diff-backup): Check that cvs-diff-flags is a
list.
Tue Jul 21 11:27:39 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-parse-error): Make the *cvs* buffer writeable
before trying to write the email message. Require sendmail before
trying to switch to mail-mode.
* pcl-cvs.el (cvs-do-update): Check that cvs-program exists.
* pcl-cvs.el (cvs-skip-line): Fixed bracketing error.
Mon Jul 20 10:31:51 1992 Per Cederqvist (ceder@robin)
* Release 1.03.
* pcl-cvs.el, cookie.el: Indentation fixes.
* Makefile (pcl-cvs-$(VER)): Include NEWS in the distribution.
* pcl-cvs.el (cvs-rm-program): Deleted.
* pcl-cvs.el (cvs-rmdir-program, cvs-lock-file): New variables.
* Handle lock files in a nicer way:
* pcl-cvs.el (cvs-update-filter, cvs-delete-lock,
cvs-lock-file-p): New functions.
* pcl-cvs.el (cvs-do-update, cvs-sentinel): Redirect stdout to the
temporary file, not stderr. Use cvs-update-filter.
* pcl-cvs.el (cvs-parse-update): New arguments.
* pcl-cvs.el (cvs-parse-buffer): Renamed to cvs-parse-update.
* pcl-cvs.el (cvs-stderr-file): Renamed to cvs-stdout-file.
* pcl-cvs.texinfo (Miscellaneous commands, Updating the
directory): Document cvs-delete-lock.
* pcl-cvs.el (cvs-mode): Don't reset buffer-read-only.
* pcl-cvs.el (cvs-find-file-other-window): Don't save-some-buffers.
Thu Jul 16 00:19:58 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el, test-cookie-el: Use the new names from cookie.el.
* cookie.el: Big Renaming Time!
External functions:
cookie-next -> tin-next
cookie-previous -> tin-previous
cookie-nth -> tin-nth
cookie-delete -> tin-delete
cookie-filter-tins -> tin-filter
cookie-get-selection -> tin-get-selection
cookie-start-marker -> tin-start-marker
cookie-end-marker -> tin-end-marker
cookie-invalidate-tins -> tin-invalidate-tins
cookie-collect-tins -> tin-collect
cookie-collect-cookies -> cookie-collect
Internal functions:
cookie-create-tin -> cookie-create-wrapper
cookie-tin-start-marker -> cookie-wrapper-start-marker
cookie-tin-cookie-safe -> cookie-wrapper-cookie-safe
cookie-tin-cookie -> cookie-wrapper-cookie
set-cookie-tin-start-marker -> cookie-wrapper-set-start-marker
set-cookie-tin-cookie -> cookie-wrapper-set-cookie
cookie-tin-p -> cookie-wrapper-p
cookie-create-tin-and-insert -> cookie-create-wrapper-and-insert
* pcl-cvs.el (cvs-find-file, cvs-find-file-other-window): Signal
an appropriate error message if the *cvs* buffer is empty.
* cookie.el (cookie-create): Make the buffer read-only.
* cookie.el (cookie-create-tin-and-insert, cookie-refresh,
cookie-delete-tin-internal, cookie-refresh-tin): Bind
buffer-read-only to nil while changing the contents of
the buffer.
* pcl-cvs.el (cvs-byte-compile-files): New function.
* pcl-cvs.texinfo (Miscellaneous commands): Document it.
* pcl-cvs.el (cvs-diff-ignore-marks): New variable.
* pcl-cvs.el (cvs-diff-cvs, cvs-diff-backup): Don't consider
marked files to be selected if a prefix argument is given XOR the
variable cvs-diff-ignore-marks is non-nil.
* pcl-cvs.el (cvs-get-marked): New optional argument `ignore-marks'.
* pcl-cvs.texinfo (Customization, Viewing differences): Document
this behaviour.
* pcl-cvs.el (cvs-undo-local-changes): New function.
* pcl-cvs.texinfo (Undoing changes): Document
cvs-undo-local-changes.
* pcl-cvs.el (cvs-mode-map): cvs-unmark-all-files moved from "U"
to "ESC DEL". cvs-undo-local-changes bound to "U".
* pcl-cvs.texinfo (Marking files): Document ESC DEL.
* pcl-cvs.el (cvs-skip-line): New arguments. All callers updated.
Now calls cvs-parse-error if a parse error occurs.
* pcl-cvs.el (cvs-parse-error): New function that creates a bug
report.
* pcl-cvs.el (cvs-parse-stderr, cvs-parse-stdout): New arguments.
The only caller (cvs-parse-buffer) updated. Call cvs-parse-error
in case of parse error.
* pcl-cvs.el (pcl-cvs-version): New variable.
* cookie.el (cookie-create): Kill all local variables in the buffer.
Fri Jul 10 11:17:40 1992 Per Cederqvist (ceder@robin)
* Release 1.03beta1.
Thu Jul 9 03:12:00 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-update-running): New variable.
* pcl-cvs.el (cvs-do-update): Use it instead of the previous local
variable cvs-process (that no longer exists). Make sure that only
one `cvs update' runs at any given moment.
* pcl-cvs.el (cvs-sentinel): Reset cvs-update-running when the
update process exits.
* pcl-cvs.el (cvs-update): Switch to the *cvs* buffer.
* pcl-cvs.el (cvs-update-other-window): New function.
* pcl-cvs-startup.el (cvs-update-other-window): Added a autoload
for it.
* pcl-cvs.el (cvs-do-update): Don't pop up any buffer in a window
- let cvs-update or cvs-update-other-window handle that. Also
don't kill the *cvs* buffer, but rather insert a "Running cvs..."
message into it.
* pcl-cvs.el (cvs-parse-buffer): Don't change the window
configuration.
* pcl-cvs.el (cvs-create-fileinfo, cvs-pp, cvs-fileninfo->type):
New type for a fileinfo: MESSAGE.
* pcl-cvs.el (cvs-cvs-buffer): Deleted the variable. Use
cvs-buffer-name instead. (I no longer have any plans to allow more
than one cvs update to run at the same time - things only get
confusing). Changed all places where cvs-cvs-buffer was used.
* pcl-cvs.el: Take care of update programs (the -u option in the
modules file):
* pcl-cvs.el (cvs-update-prog-output-skip-regexp): New variable.
* pcl-cvs.el (cvs-parse-stdout): Skip output from the update
program (using cvs-update-prog-output-skip-regexp).
* pcl-cvs.texinfo (Future enhancements): Document that the
solution is not as good as it should be.
* pcl-cvs.texinfo (Customization): Document the variable.
Wed Jul 8 20:29:44 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.el (cvs-do-update): Check that this-dir really exists
and is a directory, and that this-dir/CVS exists and is a
directory.
Tue Jul 7 01:02:24 1992 Per Cederqvist (ceder@robin)
* pcl-cvs.texinfo (Customization): Document TMPDIR.
* This chunk of modifications should make it possible to run
pcl-cvs on hosts that do not line-buffer stdout (such as
DECstation). They work by diverting stdout and stderr from
`cvs update' and later sorting them together.
* pcl-cvs.el (cvs-parse-stderr): Don't fail to parse conflict
data.
* pcl-cvs.el (cvs-remove-stdout-shadows, cvs-shadow-entry-p): New
functions.
* pcl-cvs.el (cvs-parse-buffer): Use it.
* pcl-cvs.el (cvs-remove-empty-directories): New function.
* pcl-cvs.el (cvs-remove-handled, cvs-parse-buffer): Use it.
* pcl-cvs.el (cvs-get-current-dir): New argument ROOT-DIR. All
calls to cvs-get-current-dir updated.
* pcl-cvs.el (cvs-do-update): Allocate a tmp file. Use cvs-shell
(typically /bin/sh) to redirect stderr from CVS to the tmp file.
* pcl-cvs.el (cvs-sentinel): Handle the tmp file. Remove it when
it is parsed.
* pcl-cvs.el (cvs-parse-buffer): New argument STDERR-BUFFER. All
calls to cvs-parse-buffer updated. Rewritten to handle the
separation of stderr and stdout.
* pcl-cvs.el (cvs-shell, cvs-stderr-file): New variables.
* pcl-cvs.el (cvs-compare-fileinfos, cvs-parse-stderr,
cvs-parse-stdout): New functions.
* pcl-cvs.el (cvs-parse-buffer): Some modifications for output
from RCS 5.6.
Tue Apr 7 09:11:27 1992 Per Cederqvist (ceder@leopold) Tue Apr 7 09:11:27 1992 Per Cederqvist (ceder@leopold)
* Release 1.02. * Release 1.02.

View File

@ -3,47 +3,51 @@ This text is copied from the TeXinfo manual for pcl-cvs.
Installation of the pcl-cvs program Installation of the pcl-cvs program
=================================== ===================================
1. Edit the file `Makefile' to reflect the situation at your site. 1. Edit the file `Makefile' to reflect the situation at your site.
The only things you have to change is the definition of The only things you have to change is the definition of `lispdir'
`lispdir' and `infodir'. The elisp files will be copied to and `infodir'. The elisp files will be copied to `lispdir', and
`lispdir', and the info file to `infodir'. the info file to `infodir'.
2. Configure pcl-cvs.el 2. Configure pcl-cvs.el
There are a couple of paths that you have to check to make There are a couple of paths that you have to check to make sure
sure that they match you system. They appear early in the file that they match you system. They appear early in the file
pcl-cvs.el. pcl-cvs.el.
*NOTE:* If your system is running emacs 18.57 or earlier *NOTE:* If your system is running emacs 18.57 or earlier you
you MUST uncomment the line that says: MUST uncomment the line that says:
(setq delete-exited-processes nil) (setq delete-exited-processes nil)
Setting `delete-exited-processes' to `nil' works around a bug Setting `delete-exited-processes' to `nil' works around a bug in
in emacs that causes it to dump core. The bug was fixed in emacs that causes it to dump core. The bug was fixed in emacs
emacs 18.58. 18.58.
3. Type `make install' in the source directory. This will 3. Release 1.05 and later of pcl-cvs requires parts of the Elib
library, version 0.07 or later. Elib is available via anonymous
ftp from prep.ai.mit.edu in `pub/gnu/elib-0.07.tar.z', and from
a lot of other sites that mirrors prep. Get Elib, and install
it, before proceeding.
4. Type `make install' in the source directory. This will
byte-compile all `.el' files and copy both the `.el' and the byte-compile all `.el' files and copy both the `.el' and the
`.elc' into the directory you specified in step 1. `.elc' into the directory you specified in step 1.
If you don't want to install the `.el' files but only the If you don't want to install the `.el' files but only the `.elc'
`.elc' files (the byte-compiled files), you can type ``make files (the byte-compiled files), you can type ``make
install_elc'' instead of ``make install''. install_elc'' instead of ``make install''.
If you only want to create the compiled elisp files, but If you only want to create the compiled elisp files, but don't
don't want to install them, you can type `make elcfiles' want to install them, you can type `make elcfiles' instead.
instead. This is what happens if you only type `make' without This is what happens if you only type `make' without parameters.
parameters.
4. Edit the file `default.el' in your emacs lisp directory (usually 5. Edit the file `default.el' in your emacs lisp directory (usually
`/usr/gnu/emacs/lisp' or something similar) and enter the `/usr/gnu/emacs/lisp' or something similar) and enter the
contents of the file `pcl-cvs-startup.el' into it. It contains contents of the file `pcl-cvs-startup.el' into it. It contains
a couple of `auto-load's that facilitates the use of pcl-cvs. a couple of `auto-load's that facilitates the use of pcl-cvs.
Installation of the on-line manual. Installation of the on-line manual.
=================================== ===================================
@ -55,7 +59,7 @@ Installation of the on-line manual.
info file `pcl-cvs.info' that is included in the distribution info file `pcl-cvs.info' that is included in the distribution
(type `cp pcl-cvs.info pcl-cvs'). (type `cp pcl-cvs.info pcl-cvs').
2. Move the info file `pcl-cvs' to your standard info directory. 2. Move the info file `pcl-cvs' to your standard info directory.
This might be called something like `/usr/gnu/emacs/info'. This might be called something like `/usr/gnu/emacs/info'.
3. Edit the file `dir' in the info directory and enter one line to 3. Edit the file `dir' in the info directory and enter one line to
@ -65,8 +69,6 @@ Installation of the on-line manual.
* Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS. * Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS.
How to make typeset documentation from pcl-cvs.texinfo How to make typeset documentation from pcl-cvs.texinfo
====================================================== ======================================================
@ -81,3 +83,4 @@ manual from `pcl-cvs.texinfo'.
postscript printer there is a program, `dvi2ps', which does. postscript printer there is a program, `dvi2ps', which does.
There is also a program which comes together with TeX, `dvips', There is also a program which comes together with TeX, `dvips',
which you can use. which you can use.

View File

@ -1,6 +1,6 @@
# Makefile,v 1.2 1992/04/07 20:49:07 berliner Exp # @(#) Id: dist-makefile,v 1.19 1993/05/31 22:43:45 ceder Exp
# Makefile for pcl-cvs release 1.02. # Makefile for pcl-cvs release 1.05.
# Copyright (C) 1992 Per Cederqvist # Copyright (C) 1992, 1993 Per Cederqvist
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -26,6 +26,10 @@ lispdir = /usr/local/lib/elisp
prefix=/usr/local prefix=/usr/local
infodir = $(prefix)/info infodir = $(prefix)/info
# Used to byte-compile files.
EMACS=emacs
# #
# The rest of this file should not need to be modified. # The rest of this file should not need to be modified.
# #
@ -33,8 +37,8 @@ infodir = $(prefix)/info
# Just in case... # Just in case...
SHELL = /bin/sh SHELL = /bin/sh
ELFILES = pcl-cvs.el cookie.el elib-dll.el elib-node.el ELFILES = pcl-cvs.el pcl-cvs-lucid.el
ELCFILES = pcl-cvs.elc cookie.elc elib-dll.elc elib-node.elc ELCFILES = pcl-cvs.elc pcl-cvs-lucid.elc
INFOFILES = pcl-cvs INFOFILES = pcl-cvs
TEXTMPS = pcl-cvs.aux pcl-cvs.log pcl-cvs.toc pcl-cvs.dvi pcl-cvs.cp \ TEXTMPS = pcl-cvs.aux pcl-cvs.log pcl-cvs.toc pcl-cvs.dvi pcl-cvs.cp \
pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky pcl-cvs.pg \ pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky pcl-cvs.pg \
@ -45,7 +49,7 @@ INSTALL = install
INSTALL_DATA = $(INSTALL) INSTALL_DATA = $(INSTALL)
elcfiles: elcfiles:
emacs -batch -l ./compile-all.el -f compile-pcl-cvs $(EMACS) -batch -l ./compile-all.el -f compile-pcl-cvs
all: elcfiles info all: elcfiles info
@ -66,6 +70,7 @@ info pcl-cvs: pcl-cvs.texinfo
makeinfo +fill-column=70 pcl-cvs.texinfo makeinfo +fill-column=70 pcl-cvs.texinfo
pcl-cvs.dvi: pcl-cvs.texinfo pcl-cvs.dvi: pcl-cvs.texinfo
tex pcl-cvs.texinfo
tex pcl-cvs.texinfo tex pcl-cvs.texinfo
-texindex pcl-cvs.cp pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky \ -texindex pcl-cvs.cp pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky \
pcl-cvs.pg pcl-cvs.pg

View File

@ -1,6 +1,10 @@
README,v 1.2 1992/04/07 20:49:09 berliner Exp @(#) Id: README,v 1.14 1993/05/31 22:43:36 ceder Exp
This is the readme file for pcl-cvs, release 1.02. This is the readme file for pcl-cvs, release 1.05.
This release of pcl-cvs requires Elib 0.07 or later. Elib is no
longer distributed with pcl-cvs, since that caused too much confusion.
You can get Elib from ftp.lysator.liu.se in pub/emacs/elib-*.tar.?.
Pcl-cvs is a front-end to CVS version 1.3. It integrates the most Pcl-cvs is a front-end to CVS version 1.3. It integrates the most
frequently used CVS commands into emacs. frequently used CVS commands into emacs.
@ -9,6 +13,16 @@ There is some configuration that needs to be done in pcl-cvs.el to get
it to work. See the instructions in file INSTALL. it to work. See the instructions in file INSTALL.
Full documentation is in pcl-cvs.texinfo. Since it requires makeinfo Full documentation is in pcl-cvs.texinfo. Since it requires makeinfo
2.14 a preformatted info file is also included (pcl-cvs.info). version 2 or 3 a preformatted info file is also included (pcl-cvs.info).
ceder@lysator.liu.se If you have been using a previous version of pcl-cvs (for instance
1.02 which is distributed with CVS 1.3) you should read through the
file NEWS to see what has changed.
This release has been tested under Emacs 18.59, Emacs 19.10 and Lucid
Emacs 19.6. Emacs 19.10 unfortunately has a file named cookie.el that
collides with the cookie.el that is distributed in Elib. We are
trying to find a solution to that problem. In the mean time, there is
instructions in Elib 0.07 for how to work around the problem.
Per Cederqvist

View File

@ -1,9 +1,10 @@
;;;; compile-all.el,v 1.2 1992/04/07 20:49:10 berliner Exp ;;;; @(#) Id: compile-all.el,v 1.11 1993/05/31 18:40:25 ceder Exp
;;;; This file byte-compiles all .el files in pcl-cvs release 1.02. ;;;; This file byte-compiles all .el files in pcl-cvs release 1.05.
;;;; ;;;;
;;;; Copyright (C) 1991 Inge Wallin ;;;; Copyright (C) 1991 Inge Wallin
;;;; ;;;;
;;;; This file is part of the GNU Emacs lisp library, Elib. ;;;; This file was once upon a time part of Elib, but have since been
;;;; modified by Per Cederqvist.
;;;; ;;;;
;;;; GNU Elib is free software; you can redistribute it and/or modify ;;;; GNU Elib is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by ;;;; it under the terms of the GNU General Public License as published by
@ -21,14 +22,11 @@
;;;; ;;;;
(setq elib-files '("elib-node" (setq files-to-compile '("pcl-cvs" "pcl-cvs-lucid"))
"elib-dll"
"cookie"
"pcl-cvs"))
(defun compile-file-if-necessary (file) (defun compile-file-if-necessary (file)
"Compile the Elib file FILE if necessary. "Compile FILE if necessary.
This is done if FILE.el is newer than FILE.elc or if FILE.elc doesn't exist." This is done if FILE.el is newer than FILE.elc or if FILE.elc doesn't exist."
(let ((el-name (concat file ".el")) (let ((el-name (concat file ".el"))
@ -41,12 +39,14 @@ This is done if FILE.el is newer than FILE.elc or if FILE.elc doesn't exist."
(defun compile-pcl-cvs () (defun compile-pcl-cvs ()
"Byte-compile all uncompiled files of elib. "Byte-compile all uncompiled files of pcl-cvs."
Be sure to have . in load-path since a number of files in elib
depend on other files and we always want the newer one even if
a previous version of elib exists."
(interactive) (interactive)
(setq load-path (append '(".") load-path))
(mapcar (function compile-file-if-necessary) ;; Be sure to have . in load-path since a number of files
elib-files)) ;; depend on other files and we always want the newer one even if
;; a previous version of pcl-cvs exists.
(let ((load-path (append '(".") load-path)))
(mapcar (function compile-file-if-necessary)
files-to-compile)))

View File

@ -1,6 +1,14 @@
;;; pcl-cvs-startup.el,v 1.2 1992/04/07 20:49:17 berliner Exp ;;; @(#) Id: pcl-cvs-startup.el,v 1.4 1993/05/31 18:40:33 ceder Exp
(autoload 'cvs-update "pcl-cvs" (autoload 'cvs-update "pcl-cvs"
"Run a 'cvs update' in the current working directory. Feed the "Run a 'cvs update' in the current working directory. Feed the
output to a *cvs* buffer and run cvs-mode on it. output to a *cvs* buffer and run cvs-mode on it.
If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run." If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
t) t)
(autoload 'cvs-update-other-window "pcl-cvs"
"Run a 'cvs update' in the current working directory. Feed the
output to a *cvs* buffer, display it in the other window, and run
cvs-mode on it.
If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
t)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*- \input texinfo @c -*-texinfo-*-
@comment pcl-cvs.texinfo,v 1.2 1992/04/07 20:49:23 berliner Exp @comment Id: pcl-cvs.texinfo,v 1.45 1993/05/31 22:38:15 ceder Exp
@comment Documentation for the GNU Emacs CVS mode. @comment Documentation for the GNU Emacs CVS mode.
@comment Copyright (C) 1992 Per Cederqvist @comment Copyright (C) 1992 Per Cederqvist
@ -62,12 +62,12 @@ Free Software Foundation instead of in the original English.
@sp @sp
@center @titlefont{pcl-cvs - the Emacs Front-End to CVS} @center @titlefont{pcl-cvs - the Emacs Front-End to CVS}
@sp 2 @sp 2
@center release 1.02 @center release 1.05
@comment -release- @comment -release-
@sp 3 @sp 3
@center Per Cederqvist @center Per Cederqvist
@sp 3 @sp 3
@center last updated 29 Mar 1992 @center last updated 31 May 1993
@comment -date- @comment -date-
@comment The following two commands start the copyright page @comment The following two commands start the copyright page
@ -104,7 +104,7 @@ Free Software Foundation instead of in the original English.
@ifinfo @ifinfo
This info manual describes pcl-cvs which is a GNU Emacs front-end to This info manual describes pcl-cvs which is a GNU Emacs front-end to
CVS. It works with CVS version 1.3. This manual is updated to release CVS. It works with CVS version 1.3. This manual is updated to release
1.02 of pcl-cvs. 1.05 of pcl-cvs.
@end ifinfo @end ifinfo
@comment -release- @comment -release-
@ -119,9 +119,8 @@ CVS. It works with CVS version 1.3. This manual is updated to release
* Customization:: How you can tailor pcl-cvs to suit your needs. * Customization:: How you can tailor pcl-cvs to suit your needs.
* Future enhancements:: Future enhancements of pcl-cvs. * Future enhancements:: Future enhancements of pcl-cvs.
* Reporting bugs and ideas:: Where to report bugs. * Bugs:: Bugs (known and unknown).
* Function and Variable Index:: List of functions and variables.
* Function and Variable Index:: List of functions and variables.
* Concept Index:: List of concepts. * Concept Index:: List of concepts.
* Key Index:: List of keystrokes. * Key Index:: List of keystrokes.
@ -129,7 +128,7 @@ CVS. It works with CVS version 1.3. This manual is updated to release
Installation Installation
* Pcl-cvs installation:: How to install pcl-cvs on your system. * Pcl-cvs installation:: How to install pcl-cvs on your system.
* On-line manual installation:: How to install the on-line manual. * On-line manual installation:: How to install the on-line manual.
* Typeset manual installation:: How to create typeset documentation * Typeset manual installation:: How to create typeset documentation
about pcl-cvs. about pcl-cvs.
@ -155,9 +154,13 @@ Commands
* Editing files:: Loading files into Emacs. * Editing files:: Loading files into Emacs.
* Getting info about files:: Display the log and status of files. * Getting info about files:: Display the log and status of files.
* Adding and removing files:: Adding and removing files * Adding and removing files:: Adding and removing files
* Undoing changes:: Undoing changes
* Removing handled entries:: Uninteresting lines can easily be removed. * Removing handled entries:: Uninteresting lines can easily be removed.
* Ignoring files:: Telling CVS to ignore generated files. * Ignoring files:: Telling CVS to ignore generated files.
* Viewing differences:: Commands to @samp{diff} different versions. * Viewing differences:: Commands to @samp{diff} different versions.
* Emerge::
* Reverting your buffers:: Reverting your buffers
* Miscellaneous commands:: Miscellaneous commands
@end menu @end menu
@node Copying, Installation, Top, Top @node Copying, Installation, Top, Top
@ -565,7 +568,7 @@ steps are also described in the file @file{INSTALL} in the source
directory. directory.
@menu @menu
* Pcl-cvs installation:: How to install pcl-cvs on your system. * Pcl-cvs installation:: How to install pcl-cvs on your system.
* On-line manual installation:: How to install the on-line manual. * On-line manual installation:: How to install the on-line manual.
* Typeset manual installation:: How to create typeset documentation * Typeset manual installation:: How to create typeset documentation
about pcl-cvs. about pcl-cvs.
@ -600,6 +603,13 @@ Setting @code{delete-exited-processes} to @code{nil} works around a bug
in emacs that causes it to dump core. The bug was fixed in emacs in emacs that causes it to dump core. The bug was fixed in emacs
18.58.@refill 18.58.@refill
@item
Release 1.05 and later of pcl-cvs requires parts of the Elib library,
version 0.07 or later. Elib is available via anonymous ftp from
prep.ai.mit.edu in @file{pub/gnu/elib-0.07.tar.z}, and from a lot of
other sites that mirrors prep. Get Elib, and install it, before
proceeding.
@item @item
Type @samp{make install} in the source directory. This will Type @samp{make install} in the source directory. This will
byte-compile all @file{.el} files and copy both the @file{.el} and the byte-compile all @file{.el} files and copy both the @file{.el} and the
@ -701,7 +711,7 @@ frequently used CVS commands into emacs.
Contributions to the package are welcome. I have limited time to work Contributions to the package are welcome. I have limited time to work
on this project, but I will gladly add any code that you contribute to on this project, but I will gladly add any code that you contribute to
me to this package (@pxref{Reporting bugs and ideas}). me to this package (@pxref{Bugs}).
The following persons have made contributions to pcl-cvs. The following persons have made contributions to pcl-cvs.
@ -724,8 +734,17 @@ the files @file{elib-node.el} and @file{compile-all.el}. The file
Linus Tolke (@samp{linus@@lysator.liu.se}) contributed useful comments Linus Tolke (@samp{linus@@lysator.liu.se}) contributed useful comments
on both the functionality and the documentation.@refill on both the functionality and the documentation.@refill
@item
Jamie Zawinski (@samp{jwz@@lucid.com}) contributed
@file{pcl-cvs-lucid.el}.
@item
Leif Lonnblad contributed RCVS support.
@end itemize @end itemize
Apart from these, a lot of people have send me suggestions, ideas,
requests, bug reports and encouragement. Thanks a lot! Without your
there would be no new releases of pcl-cvs.
@node Archives, , Contributors, About pcl-cvs @node Archives, , Contributors, About pcl-cvs
@comment node-name, next, previous, up @comment node-name, next, previous, up
@ -736,11 +755,6 @@ on both the functionality and the documentation.@refill
@cindex Getting pcl-cvs @cindex Getting pcl-cvs
@cindex Email archives @cindex Email archives
This release of pcl-cvs is included in the CVS 1.3 distribution.
However, since pcl-cvs has had less time to mature (the first line of
code was written less than a year ago) it is likely that there will be a
new release of pcl-cvs before the next release of CVS.
The latest release of pcl-cvs can be fetched via anonymous ftp from The latest release of pcl-cvs can be fetched via anonymous ftp from
@code{ftp.lysator.liu.se}, (IP no. 130.236.254.1) in the directory @code{ftp.lysator.liu.se}, (IP no. 130.236.254.1) in the directory
@code{pub/emacs}. If you don't live in Scandinavia you should probably @code{pub/emacs}. If you don't live in Scandinavia you should probably
@ -765,7 +779,7 @@ Pcl-cvs is only useful once you have checked out a module. So before
you invoke it you must have a copy of a module somewhere in the file you invoke it you must have a copy of a module somewhere in the file
system. system.
You invoke pcl-cvs by typing @kbd{M-x pcl-cvs RET}. If your emacs You invoke pcl-cvs by typing @kbd{M-x cvs-update RET}. If your emacs
responds with @samp{[No match]} your system administrator has not responds with @samp{[No match]} your system administrator has not
installed pcl-cvs properly. Try @kbd{M-x load-library RET pcl-cvs RET}. installed pcl-cvs properly. Try @kbd{M-x load-library RET pcl-cvs RET}.
If that also fails - talk to your root. If it succeeds you might put If that also fails - talk to your root. If it succeeds you might put
@ -783,7 +797,7 @@ files that have been checked out from a CVS archive.) The output from
@samp{*cvs*}. It might look something like this: @samp{*cvs*}. It might look something like this:
@example @example
PCL-CVS release 1.02. PCL-CVS release 1.05.
@comment -release- @comment -release-
In directory /users/ceder/FOO/test: In directory /users/ceder/FOO/test:
@ -979,16 +993,22 @@ you can use in pcl-cvs. They are grouped together by type.
* Editing files:: Loading files into Emacs. * Editing files:: Loading files into Emacs.
* Getting info about files:: Display the log and status of files. * Getting info about files:: Display the log and status of files.
* Adding and removing files:: Adding and removing files * Adding and removing files:: Adding and removing files
* Undoing changes:: Undoing changes
* Removing handled entries:: Uninteresting lines can easily be removed. * Removing handled entries:: Uninteresting lines can easily be removed.
* Ignoring files:: Telling CVS to ignore generated files. * Ignoring files:: Telling CVS to ignore generated files.
* Viewing differences:: Commands to @samp{diff} different versions. * Viewing differences:: Commands to @samp{diff} different versions.
* Emerge::
* Reverting your buffers:: Reverting your buffers
* Miscellaneous commands:: Miscellaneous commands
@end menu @end menu
@node Updating the directory, Movement commands, Commands, Commands @node Updating the directory, Movement commands, Commands, Commands
@comment node-name, next, previous, up @comment node-name, next, previous, up
@section Updating the directory @section Updating the directory
@findex cvs-update @findex cvs-update
@findex cvs-update-no-prompt @findex cvs-mode-update-no-prompt
@findex cvs-delete-lock
@cindex Getting the *cvs* buffer
@kindex g - Rerun @samp{cvs update} @kindex g - Rerun @samp{cvs update}
@ -1007,11 +1027,21 @@ argument to it (e.g., by typing @kbd{C-u M-x cvs-update RET}).@refill
All other commands in pcl-cvs requires that you have a @samp{*cvs*} All other commands in pcl-cvs requires that you have a @samp{*cvs*}
buffer. This is the command that you use to get one.@refill buffer. This is the command that you use to get one.@refill
CVS uses lock files in the repository to ensure the integrity of the
data files in the repository. They might be left behind i.e. if a
workstation crashes in the middle of a CVS operation. CVS outputs a
message when it is waiting for a lock file to go away. Pcl-cvs will
show the same message in the *cvs* buffer, together with instructions
for deleting the lock files. You should normally not have to delete
them manually --- just wait a little while and the problem should fix
itself. But if the lock files doesn't disappear you can delete them
with @kbd{M-x cvs-delete-lock RET}.@refill
@item g @item g
This will run @samp{cvs update} again. It will always use the same This will run @samp{cvs update} again. It will always use the same
buffer that was used with the previous @samp{cvs update}. Give a prefix buffer that was used with the previous @samp{cvs update}. Give a prefix
argument to avoid descending into subdirectories. This runs the command argument to avoid descending into subdirectories. This runs the command
@samp{cvs-update-no-prompt}.@refill @samp{cvs-mode-update-no-prompt}.@refill
@end table @end table
@node Movement commands, Marking files, Updating the directory, Commands @node Movement commands, Marking files, Updating the directory, Commands
@comment node-name, next, previous, up @comment node-name, next, previous, up
@ -1051,13 +1081,13 @@ These keys move one file backward, towards the beginning of the buffer
@kindex m - marking a file @kindex m - marking a file
@kindex M - marking all files @kindex M - marking all files
@kindex u - unmark a file @kindex u - unmark a file
@kindex U - unmark all files @kindex ESC DEL - unmark all files
@kindex DEL - unmark previous file @kindex DEL - unmark previous file
@findex cvs-mark @findex cvs-mode-mark
@findex cvs-unmark @findex cvs-mode-unmark
@findex cvs-mark-all-files @findex cvs-mode-mark-all-files
@findex cvs-unmark-all-files @findex cvs-mode-unmark-all-files
@findex cvs-unmark-up @findex cvs-mode-unmark-up
Pcl-cvs works on a set of @dfn{selected files} (@pxref{Selected files}). Pcl-cvs works on a set of @dfn{selected files} (@pxref{Selected files}).
You can mark and unmark files with these commands: You can mark and unmark files with these commands:
@ -1066,22 +1096,22 @@ You can mark and unmark files with these commands:
@item m @item m
This marks the file that the cursor is positioned on. If the cursor is This marks the file that the cursor is positioned on. If the cursor is
positioned on a directory all files in that directory will be marked. positioned on a directory all files in that directory will be marked.
(@code{cvs-mark}). (@code{cvs-mode-mark}).
@item u @item u
Unmark the file that the cursor is positioned on. If the cursor is on a Unmark the file that the cursor is positioned on. If the cursor is on a
directory, all files in that directory will be unmarked. directory, all files in that directory will be unmarked.
(@code{cvs-unmark}).@refill (@code{cvs-mode-unmark}).@refill
@item M @item M
Mark @emph{all} files in the buffer (@code{cvs-mark-all-files}). Mark @emph{all} files in the buffer (@code{cvs-mode-mark-all-files}).
@item U @item @key{ESC} @key{DEL}
Unmark @emph{all} files (@code{cvs-unmark-all-files}). Unmark @emph{all} files (@code{cvs-mode-unmark-all-files}).
@item @key{DEL} @item @key{DEL}
Unmark the file on the previous line, and move point to that line Unmark the file on the previous line, and move point to that line
(@code{cvs-unmark-up}). (@code{cvs-mode-unmark-up}).
@end table @end table
@node Committing changes, Editing files, Marking files, Commands @node Committing changes, Editing files, Marking files, Commands
@ -1089,12 +1119,14 @@ Unmark the file on the previous line, and move point to that line
@section Committing changes @section Committing changes
@cindex Committing changes @cindex Committing changes
@cindex Ci @cindex Ci
@findex cvs-commit @findex cvs-mode-commit
@kindex c - commit files @kindex c - commit files
@vindex cvs-erase-input-buffer (variable) @vindex cvs-erase-input-buffer (variable)
@vindex cvs-auto-revert-after-commit (variable)
@cindex Commit buffer @cindex Commit buffer
@cindex Edit buffer @cindex Edit buffer
@cindex Erasing commit message @cindex Erasing commit message
@cindex Reverting buffers after commit
@table @kbd @table @kbd
@item c @item c
@ -1102,7 +1134,7 @@ All files that have a "need to be checked in"-marker (@pxref{Buffer
contents}) can be checked in with the @kbd{c} command. It checks in all contents}) can be checked in with the @kbd{c} command. It checks in all
selected files (@pxref{Selected files}) (except those who lack the selected files (@pxref{Selected files}) (except those who lack the
"ci"-marker - they are ignored). Pressing @kbd{c} causes "ci"-marker - they are ignored). Pressing @kbd{c} causes
@code{cvs-commit} to be run.@refill @code{cvs-mode-commit} to be run.@refill
When you press @kbd{c} you will get a buffer called When you press @kbd{c} you will get a buffer called
@samp{*cvs-commit-message*}. Enter the log message for the file(s) in @samp{*cvs-commit-message*}. Enter the log message for the file(s) in
@ -1111,10 +1143,18 @@ commit the files (using @code{cvs-edit-done}).
Normally the @samp{*cvs-commit-message*} buffer will retain the log Normally the @samp{*cvs-commit-message*} buffer will retain the log
message from the previous commit, but if the variable message from the previous commit, but if the variable
@code{cvs-erase-input-buffer} is set to a non-nil value the buffer will @code{cvs-erase-input-buffer} is set to a non-@code{nil} value the
be erased. Point and mark will always be located around the entire buffer will be erased. Point and mark will always be located around the
buffer so that you can easily erase it with @kbd{C-w} entire buffer so that you can easily erase it with @kbd{C-w}
(@samp{kill-region}).@refill (@samp{kill-region}).@refill
If you are editing the files in your emacs an automatic
@samp{revert-buffer} will be performed. (If the file contains
@samp{$@asis{Id}$} keywords @samp{cvs commit} will write a new file with
the new values substituted. The auto-revert makes sure that you get
them into your buffer). The revert will not occur if you have modified
your buffer, or if @samp{cvs-auto-revert-after-commit} is set to
@samp{nil}.@refill
@end table @end table
@node Editing files, Getting info about files, Committing changes, Commands @node Editing files, Getting info about files, Committing changes, Commands
@ -1126,9 +1166,9 @@ buffer so that you can easily erase it with @kbd{C-w}
@cindex Loading files @cindex Loading files
@cindex Dired @cindex Dired
@cindex Invoking dired @cindex Invoking dired
@findex cvs-find-file @findex cvs-mode-find-file
@findex cvs-find-file-other-window @findex cvs-mode-find-file-other-window
@findex cvs-add-change-log-entry-other-window @findex cvs-mode-add-change-log-entry-other-window
@kindex f - find file or directory @kindex f - find file or directory
@kindex o - find file in other window @kindex o - find file in other window
@kindex A - add ChangeLog entry @kindex A - add ChangeLog entry
@ -1144,17 +1184,17 @@ Find the file that the cursor points to. Run @samp{dired}
@ifinfo @ifinfo
(@pxref{Dired,,,Emacs}) (@pxref{Dired,,,Emacs})
@end ifinfo @end ifinfo
if the cursor points to a directory (@code{cvs-find-file}).@refill if the cursor points to a directory (@code{cvs-mode-find-file}).@refill
@item o @item o
Like @kbd{f}, but use another window Like @kbd{f}, but use another window
(@code{cvs-find-file-other-window}).@refill (@code{cvs-mode-find-file-other-window}).@refill
@item A @item A
Invoke @samp{add-change-log-entry-other-window} to edit a Invoke @samp{add-change-log-entry-other-window} to edit a
@samp{ChangeLog} file. The @samp{ChangeLog} will be found in the @samp{ChangeLog} file. The @samp{ChangeLog} will be found in the
directory of the file the cursor points to. directory of the file the cursor points to.
(@code{cvs-add-change-log-entry-other-window}).@refill (@code{cvs-mode-add-change-log-entry-other-window}).@refill
@end table @end table
@node Getting info about files, Adding and removing files, Editing files, Commands @node Getting info about files, Adding and removing files, Editing files, Commands
@ -1165,8 +1205,8 @@ directory of the file the cursor points to.
@cindex Getting status @cindex Getting status
@kindex l - run @samp{cvs log} @kindex l - run @samp{cvs log}
@kindex s - run @samp{cvs status} @kindex s - run @samp{cvs status}
@findex cvs-log @findex cvs-mode-log
@findex cvs-status @findex cvs-mode-status
Both of the following commands can be customized. Both of the following commands can be customized.
@xref{Customization}.@refill @xref{Customization}.@refill
@ -1174,14 +1214,14 @@ Both of the following commands can be customized.
@table @kbd @table @kbd
@item l @item l
Run @samp{cvs log} on all selected files, and show the result in a Run @samp{cvs log} on all selected files, and show the result in a
temporary buffer (@code{cvs-log}). temporary buffer (@code{cvs-mode-log}).
@item s @item s
Run @samp{cvs status} on all selected files, and show the result in a Run @samp{cvs status} on all selected files, and show the result in a
temporary buffer (@code{cvs-status}). temporary buffer (@code{cvs-mode-status}).
@end table @end table
@node Adding and removing files, Removing handled entries, Getting info about files, Commands @node Adding and removing files, Undoing changes, Getting info about files, Commands
@comment node-name, next, previous, up @comment node-name, next, previous, up
@section Adding and removing files @section Adding and removing files
@cindex Adding files @cindex Adding files
@ -1191,8 +1231,8 @@ temporary buffer (@code{cvs-status}).
@cindex Putting files under CVS control @cindex Putting files under CVS control
@kindex a - add a file @kindex a - add a file
@kindex r - remove a file @kindex r - remove a file
@findex cvs-add @findex cvs-mode-add
@findex cvs-remove-file @findex cvs-mode-remove-file
The following commands are available to make it easy to add and remove The following commands are available to make it easy to add and remove
files from the CVS repository. files from the CVS repository.
@ -1201,7 +1241,7 @@ files from the CVS repository.
@item a @item a
Add all selected files. This command can be used on @samp{Unknown} Add all selected files. This command can be used on @samp{Unknown}
files (see @pxref{File status}). The status of the file will change to files (see @pxref{File status}). The status of the file will change to
@samp{Added}, and you will have to use @kbd{c} (@samp{cvs-commit}, see @samp{Added}, and you will have to use @kbd{c} (@samp{cvs-mode-commit}, see
@pxref{Committing changes}) to really add the file to the @pxref{Committing changes}) to really add the file to the
repository.@refill repository.@refill
@ -1211,7 +1251,7 @@ them) to resurrect them.
Selected files that are neither @samp{Unknown} nor @samp{Removed} will Selected files that are neither @samp{Unknown} nor @samp{Removed} will
be ignored by this command. be ignored by this command.
The command that is run is @code{cvs-add}. The command that is run is @code{cvs-mode-add}.
@item r @item r
This command removes the selected files (after prompting for This command removes the selected files (after prompting for
@ -1219,13 +1259,29 @@ confirmation). The files are @samp{rm}ed from your directory and
(unless the status was @samp{Unknown}; @pxref{File status}) they will (unless the status was @samp{Unknown}; @pxref{File status}) they will
also be @samp{cvs remove}d. If the files were @samp{Unknown} they will also be @samp{cvs remove}d. If the files were @samp{Unknown} they will
disappear from the buffer. Otherwise their status will change to disappear from the buffer. Otherwise their status will change to
@samp{Removed}, and you must use @kbd{c} (@samp{cvs-commit}, @samp{Removed}, and you must use @kbd{c} (@samp{cvs-mode-commit},
@pxref{Committing changes}) to commit the removal.@refill @pxref{Committing changes}) to commit the removal.@refill
The command that is run is @code{cvs-remove-file}. The command that is run is @code{cvs-mode-remove-file}.
@end table @end table
@node Removing handled entries, Ignoring files, Adding and removing files, Commands @node Undoing changes, Removing handled entries, Adding and removing files, Commands
@comment node-name, next, previous, up
@section Undoing changes
@cindex Undo changes
@cindex Flush changes
@kindex U - undo changes
@findex cvs-mode-undo-local-changes
@table @kbd
@item U
If you have modified a file, and for some reason decide that you don't
want to keep the changes, you can undo them with this command. It works
by removing your working copy of the file and then getting the latest
version from the repository (@code{cvs-mode-undo-local-changes}.
@end table
@node Removing handled entries, Ignoring files, Undoing changes, Commands
@comment node-name, next, previous, up @comment node-name, next, previous, up
@section Removing handled entries @section Removing handled entries
@cindex Expunging uninteresting entries @cindex Expunging uninteresting entries
@ -1235,8 +1291,9 @@ The command that is run is @code{cvs-remove-file}.
@cindex Handled lines, removing them @cindex Handled lines, removing them
@kindex x - remove processed entries @kindex x - remove processed entries
@kindex C-k - remove selected entries @kindex C-k - remove selected entries
@findex cvs-remove-handled @findex cvs-mode-remove-handled
@findex cvs-acknowledge @findex cvs-mode-acknowledge
@findex cvs-mode-ignore
@table @kbd @table @kbd
@item x @item x
@ -1247,13 +1304,13 @@ are removed from the buffer. If a directory becomes empty the heading
for that directory is also removed. This makes it easier to get an for that directory is also removed. This makes it easier to get an
overview of what needs to be done. overview of what needs to be done.
The command is called @code{cvs-remove-handled}. If The command is called @code{cvs-mode-remove-handled}. If
@samp{cvs-auto-remove-handled} is set to non-@samp{nil} this will @samp{cvs-auto-remove-handled} is set to non-@code{nil} this will
automatically be performed after every commit.@refill automatically be performed after every commit.@refill
@item C-k @item C-k
This command can be used for lines that @samp{cvs-remove-handled} would This command can be used for lines that @samp{cvs-mode-remove-handled} would
not delete, but that you want to delete (@code{cvs-acknowledge}). not delete, but that you want to delete (@code{cvs-mode-acknowledge}).
@end table @end table
@node Ignoring files, Viewing differences, Removing handled entries, Commands @node Ignoring files, Viewing differences, Removing handled entries, Commands
@ -1269,10 +1326,10 @@ the @file{.cvsignore} doesn't exist it will be created.
The @file{.cvsignore} file should normally be added to the repository, The @file{.cvsignore} file should normally be added to the repository,
but you could ignore it also if you like it better that way. but you could ignore it also if you like it better that way.
This runs @code{cvs-ignore}. This runs @code{cvs-mode-ignore}.
@end table @end table
@node Viewing differences, , Ignoring files, Commands @node Viewing differences, Emerge, Ignoring files, Commands
@comment node-name, next, previous, up @comment node-name, next, previous, up
@section Viewing differences @section Viewing differences
@cindex Diff @cindex Diff
@ -1280,29 +1337,122 @@ This runs @code{cvs-ignore}.
@cindex Viewing differences @cindex Viewing differences
@kindex d - run @samp{cvs diff} @kindex d - run @samp{cvs diff}
@kindex b - diff backup file @kindex b - diff backup file
@findex cvs-diff-cvs @findex cvs-mode-diff-cvs
@findex cvs-diff-backup @findex cvs-mode-diff-backup
@vindex cvs-diff-ignore-marks (variable)
@table @kbd @table @kbd
@item d @item d
Display a @samp{cvs diff} between the selected files and the RCS version Display a @samp{cvs diff} between the selected files and the RCS version
that they are based on. @xref{Customization} describes how you can send that they are based on. @xref{Customization} describes how you can send
flags to @samp{cvs diff}. (The function that does the job is flags to @samp{cvs diff}. If @var{cvs-diff-ignore-marks} is set to a
@code{cvs-diff-cvs}).@refill non-@code{nil} value or if a prefix argument is given (but not both) any
marked files will not be considered to be selected.
(@code{cvs-mode-diff-cvs}).@refill
@item b @item b
If CVS finds a conflict while merging two versions of a file (during a If CVS finds a conflict while merging two versions of a file (during a
@samp{cvs update}, @pxref{Updating the directory}) it will save the @samp{cvs update}, @pxref{Updating the directory}) it will save the
original file in a file called @file{.#@var{FILE}.@var{VERSION}} where original file in a file called @file{.#@var{FILE}.@var{VERSION}} where
@var{FILE} is the name of the file, and @var{VERSION} is the RCS version @var{FILE} is the name of the file, and @var{VERSION} is the RCS version
number that your file was based on. number that your file was based on.@refill
With the @kbd{b} command you can run a @samp{diff} on the files With the @kbd{b} command you can run a @samp{diff} on the files
@file{.#@var{FILE}.@var{VERSION}} and @file{@var{FILE}}. You can get a @file{.#@var{FILE}.@var{VERSION}} and @file{@var{FILE}}. You can get a
context- or Unidiff by setting @samp{cvs-diff-flags} - context- or Unidiff by setting @samp{cvs-diff-flags} -
@pxref{Customization}. This command only works on files that have @pxref{Customization}. This command only works on files that have
status @samp{Conflict} or @samp{Merged}. The name of the command is status @samp{Conflict} or @samp{Merged}.@refill
@code{cvs-diff-backup}. @refill
If @var{cvs-diff-ignore-marks} is set to a non-@code{nil} value or if a
prefix argument is given (but not both) any marked files will not be
considered to be selected. (@code{cvs-mode-diff-backup}).@refill
@end table
@node Emerge, Reverting your buffers, Viewing differences, Commands
@comment node-name, next, previous, up
@section Running emerge
@cindex Emerge
@cindex Invoking emerge
@cindex Conflicts, resolving
@cindex Resolving conflicts
@kindex e - invoke @samp{emerge}
@findex cvs-mode-emerge
@table @kbd
@item e
Invoke @samp{emerge} on one file. This command works slightly different
depending on the file status.
@table @asis
@item @samp{Modified}
Run @samp{emerge-files} with your working file as file A, and the latest
revision in the repository as file B.
@item @samp{Merged}
@itemx @samp{Conflict}
Run @samp{emerge-files-with-ancestor} with your working file (as it was
prior to your invocation of @samp{cvs-update}) as file A, the latest
revision in the repository as file B, and the revision that you based
your local modifications on as ancestor.
@end table
@strong{Note:} CVS has already performed a merge. The resulting file is
not used in any way if you use this command. If you use the @kbd{q}
command inside @samp{emerge} (to successfully terminate the merge) the
file that CVS created will be overwritten.
@end table
@node Reverting your buffers, Miscellaneous commands, Emerge, Commands
@comment node-name, next, previous, up
@section Reverting your buffers
@findex cvs-mode-revert-updated-buffers
@kindex R - revert buffers
@cindex Syncing buffers
@cindex Reverting buffers
@table @kbd
@item R
If you are editing (or just viewing) a file in a buffer, and that file
is changed by CVS during a @samp{cvs-update}, all you have to do is type
@kbd{R} in the *cvs* buffer to read in the new versions of the
files.@refill
All files that are @samp{Updated}, @samp{Merged} or in @samp{Conflict}
are reverted from the disk. Any other files are ignored. Only files
that you were already editing are read.@refill
An error is signalled if you have modified the buffer since it was last
changed. (@code{cvs-mode-revert-updated-buffers}).@refill
@end table
@node Miscellaneous commands, , Reverting your buffers, Commands
@comment node-name, next, previous, up
@section Miscellaneous commands
@findex cvs-byte-compile-files
@cindex Recompiling elisp files
@cindex Byte compilation
@cindex Getting rid of lock files
@cindex Lock files
@kindex q - bury the *cvs* buffer
@findex bury-buffer
@table @kbd
@item M-x cvs-byte-compile-files
Byte compile all selected files that end in .el.
@item M-x cvs-delete-lock
This command can be used in any buffer, and deletes the lock files that
the *cvs* buffer informs you about. You should normally never have to
use this command since CVS tries very carefully to always remove the
lock files itself.
You can only use this command when a message in the *cvs* buffer tells
you so. You should wait a while before using this command in case
someone else is running a cvs command.
@item q
Bury the *cvs* buffer. (@code{bury-buffer}).
@end table @end table
@node Customization, Future enhancements, Commands, Top @node Customization, Future enhancements, Commands, Top
@ -1310,11 +1460,17 @@ status @samp{Conflict} or @samp{Merged}. The name of the command is
@chapter Customization @chapter Customization
@vindex cvs-erase-input-buffer (variable) @vindex cvs-erase-input-buffer (variable)
@vindex cvs-inhibit-copyright-message (variable) @vindex cvs-inhibit-copyright-message (variable)
@vindex cvs-cvs-diff-flags (variable)
@vindex cvs-diff-flags (variable) @vindex cvs-diff-flags (variable)
@vindex cvs-diff-ignore-marks (variable)
@vindex cvs-log-flags (variable) @vindex cvs-log-flags (variable)
@vindex cvs-status-flags (variable) @vindex cvs-status-flags (variable)
@vindex cvs-auto-remove-handled (variable) @vindex cvs-auto-remove-handled (variable)
@vindex cvs-update-prog-output-skip-regexp (variable)
@vindex cvs-cvsroot (variable)
@vindex TMPDIR (environment variable)
@vindex cvs-auto-revert-after-commit (variable)
@vindex cvs-commit-buffer-require-final-newline (variable)
@vindex cvs-sort-ignore-file (variable)
@cindex Inhibiting the Copyright message. @cindex Inhibiting the Copyright message.
@cindex Copyright message, getting rid of it @cindex Copyright message, getting rid of it
@cindex Getting rid of the Copyright message. @cindex Getting rid of the Copyright message.
@ -1324,14 +1480,24 @@ status @samp{Conflict} or @samp{Merged}. The name of the command is
@cindex Context diff, how to get @cindex Context diff, how to get
@cindex Unidiff, how to get @cindex Unidiff, how to get
@cindex Automatically remove handled files @cindex Automatically remove handled files
@cindex -u option in modules file
@cindex Modules file (-u option)
@cindex Update program (-u option in modules file)
@cindex Reverting buffers after commit
@cindex Require final newline
@cindex Automatically inserting newline
@cindex Commit message, inserting newline
@cindex Sorting the .cvsignore file
@cindex .cvsignore file, sorting
@cindex Automatically sorting .cvsignore
If you have an idea about any customization that would be handy but If you have an idea about any customization that would be handy but
isn't present in this list, please tell me! @xref{Reporting bugs and isn't present in this list, please tell me! @xref{Bugs} for info on how
ideas} for info on how to reach me.@refill to reach me.@refill
@table @samp @table @samp
@item cvs-erase-input-buffer @item cvs-erase-input-buffer
If set to anything else than @samp{nil} the edit buffer will be erased If set to anything else than @code{nil} the edit buffer will be erased
before you write the log message (@pxref{Committing changes}). before you write the log message (@pxref{Committing changes}).
@item cvs-inhibit-copyright-message @item cvs-inhibit-copyright-message
@ -1340,71 +1506,180 @@ a while. Set this variable to @samp{t} if you want to get rid of it.
(But don't set this to @samp{t} in the system defaults file - new users (But don't set this to @samp{t} in the system defaults file - new users
should see this message at least once). should see this message at least once).
@item cvs-cvs-diff-flags @item cvs-diff-flags
A list of strings to pass as arguments to the @samp{cvs diff} program. A list of strings to pass as arguments to the @samp{cvs diff} and
This is used by @samp{cvs-diff-cvs} (key @kbd{d}, @pxref{Viewing @samp{diff} programs. This is used by @samp{cvs-mode-diff-cvs} and
differences}). If you prefer the Unidiff format you could add this line @samp{cvs-mode-diff-backup} (key @kbd{b}, @pxref{Viewing differences}). If
to your @file{.emacs} file:@refill you prefer the Unidiff format you could add this line to your
@file{.emacs} file:@refill
@example @example
(setq cvs-cvs-diff-flags '("-u")) (setq cvs-diff-flags '("-u"))
@end example @end example
@item cvs-diff-flags @item cvs-diff-ignore-marks
Like @samp{cvs-cvs-diff-flags}, but passed to @samp{diff}. This is used If this variable is non-@code{nil} or if a prefix argument is given (but
by @samp{cvs-diff-backup} (key @kbd{b}, @pxref{Viewing differences}). not both) to @samp{cvs-mode-diff-cvs} or @samp{cvs-mode-diff-backup}
marked files are not considered selected.
@item cvs-log-flags @item cvs-log-flags
List of strings to send to @samp{cvs log}. Used by @samp{cvs-log} (key List of strings to send to @samp{cvs log}. Used by @samp{cvs-mode-log}
@kbd{l}, @pxref{Getting info about files}). (key @kbd{l}, @pxref{Getting info about files}).
@item cvs-status-flags @item cvs-status-flags
List of strings to send to @samp{cvs status}. Used by @samp{cvs-status} List of strings to send to @samp{cvs status}. Used by @samp{cvs-mode-status}
(key @kbd{s}, @pxref{Getting info about files}). (key @kbd{s}, @pxref{Getting info about files}).
@item cvs-auto-remove-handled @item cvs-auto-remove-handled
If this variable is set to any non-@samp{nil} value If this variable is set to any non-@code{nil} value
@samp{cvs-remove-handled} will be called every time you check in files, @samp{cvs-mode-remove-handled} will be called every time you check in
after the check-in is ready. @xref{Removing handled entries}.@refill files, after the check-in is ready. @xref{Removing handled
entries}.@refill
@item cvs-auto-revert-after-commit
If this variable is set to any non-@samp{nil} value any buffers you have
that visit a file that is committed will be automatically reverted.
This variable is default @samp{t}. @xref{Committing changes}.@refill
@item cvs-update-prog-output-skip-regexp
The @samp{-u} flag in the @file{modules} file can be used to run a command
whenever a @samp{cvs update} is performed (see cvs(5)). This regexp
is used to search for the last line in that output. It is normally set
to @samp{"$"}. That setting is only correct if the command outputs
nothing. Note that pcl-cvs will get very confused if the command
outputs @emph{anything} to @samp{stderr}.
@item cvs-cvsroot
This variable can be set to override @samp{CVSROOT}. It should be a
string. If it is set then everytime a cvs command is run it will be
called as @samp{cvs -d @var{cvs-cvsroot}@dots{}} This can be useful if
your site has several repositories.
@item TMPDIR
Pcl-cvs uses this @emph{environment variable} to decide where to put the
temporary files it needs. It defaults to @file{/tmp} if it is not set.
@item cvs-commit-buffer-require-final-newline
When you enter a log message in the @samp{*cvs-commit-message*} buffer
pcl-cvs will normally automatically insert a trailing newline, unless
there already is one. This behavior can be controlled via
@samp{cvs-commit-buffer-require-final-newline}. If it is @samp{t} (the
default behavior), a newline will always be appended. If it is
@samp{nil}, newlines will never be appended. Any other value causes
pcl-cvs to ask the user whenever there is no trailing newline in the
commit message buffer.
@item cvs-sort-ignore-file
If this variable is set to any non-@samp{nil} value the
@file{.cvsignore} will always be sorted whenever you use
@samp{cvs-mode-ignore} to add a file to it. This option is on by
default.
@end table @end table
@node Future enhancements, Reporting bugs and ideas, Customization, Top @node Future enhancements, Bugs, Customization, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@chapter Future enhancements @chapter Future enhancements
@cindex Enhancements @cindex Enhancements
Pcl-cvs is still under development and needs a number of enhancements to Pcl-cvs is still under development and needs a number of enhancements to
be called complete. Here is my current wish-list for future releases of be called complete. Below is my current wish-list for future releases
pcl-cvs: of pcl-cvs. Please, let me know which of these features you want most.
They are listed below in approximately the order that I currently think
I will implement them in.
@itemize @bullet @itemize @bullet
@item @item
Dired support. I have an experimental @file{dired-cvs.el} that works Rewritten parser code. There are many situations where pcl-cvs will
together with CVS 1.2. Unfortunately I wrote it on top of a fail to recognize the output from CVS. The situation could be greatly
non-standard @file{dired.el}, so it must be rewritten.@refill increased.
@item
@samp{cvs-status}. This will run @samp{cvs status} in a directory and
produce a buffer that looks pretty much like the current *cvs* buffer.
That buffer will include information for all version-controlled files.
(There will be a simple keystroke to remove all "uninteresting" files,
that is, files that are "Up-to-date"). In this new buffer you will be
able to update a file, commit a file, et c. The big win with this is
that you will be able to watch the differences between your current
working file and the head revision in the repository before you update
the file, and you can then choose to update it or let it wait for a
while longer.
@item
Log mode. When this mode is finished you will be able to move around
(using @kbd{n} and @kbd{p}) between the revisions of a file, mark two of
them, and run a diff between them. You will be able to hide branches
(similar to the way you can hide sub-paragraphs in outline-mode) and do
merges between revisions. Other ideas about this are welcome.
@item
The current model for marks in the *cvs* buffer seems to be confusing.
I am considering to use the VM model instead, where marks are normally
inactive. To activate the mark, you issue a command like
@samp{cvs-mode-next-command-uses-marks}. I might implement a flag so
that you can use either version. Feedback on this before I start coding
it is very welcome.
@item @item
It should be possible to run commands such as @samp{cvs log}, @samp{cvs It should be possible to run commands such as @samp{cvs log}, @samp{cvs
status} and @samp{cvs commit} directly from a buffer containing a file, status} and @samp{cvs commit} directly from a buffer containing a file,
instead of having to @samp{cvs-update}. If the directory contains many instead of having to @samp{cvs-update}. If the directory contains many
files the @samp{cvs-update} can take quite some time, especially on a files the @samp{cvs-update} can take quite some time, especially on a
slow machine. slow machine. I planed to put these kind of commands on the prefix
@kbd{C-c C-v}, but that turned out to be used by for instance c++-mode.
If you have any suggestions for a better prefix key, please let me know.
@item
Increased robustness. For instance, you can not currently press
@kbd{C-g} when you are entering the description of a file that you are
adding without confusing pcl-cvs.
@item
Support for multiple active *cvs* buffers.
@item
Dired support. I have an experimental @file{dired-cvs.el} that works
together with CVS 1.2. Unfortunately I wrote it on top of a
non-standard @file{dired.el}, so it must be rewritten.@refill
@item
An ability to send user-supplied options to all the cvs commands.
@item
Pcl-cvs is not at all clever about what it should do when @samp{cvs
update} runs a program (due to the @samp{-u} option in the
@file{modules} file --- see @samp{cvs(5)}). The current release uses a
regexp to search for the end. At the very least that regexp should be
configured for different modules. Tell me if you have any idea about
what is the right thing to do. In a perfect world the program should
also be allowed to print to @samp{stderr} without causing pcl-cvs to
crash.
@end itemize @end itemize
If you miss something in this wish-list, let me know! I don't promise If you miss something in this wish-list, let me know! I don't promise
that I will write it, but I will at least try to coordinate the efforts that I will write it, but I will at least try to coordinate the efforts
of making a good Emacs front end to CVS. See @xref{Reporting bugs and of making a good Emacs front end to CVS. See @xref{Bugs} for
ideas} for information about how to reach me.@refill information about how to reach me.@refill
So far, I have written most of pcl-cvs in my all-to-rare spare time. If
you want pcl-cvs to be developed faster you can write a contract with
Signum Support to do the extension. You can reach Signum Support by
email to @samp{info@@signum.se} or via mail to Signum Support AB, Box
2044, S-580 02 Linkoping, Sweden. Phone: +46 (0) 13 - 21 46 00. Fax: +46
(0) 13 - 21 47 00.
@node Reporting bugs and ideas, Function and Variable Index, Future enhancements, Top @node Bugs, Function and Variable Index, Future enhancements, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@chapter Reporting bugs and ideas @chapter Bugs (known and unknown)
@cindex Reporting bugs and ideas @cindex Reporting bugs and ideas
@cindex Bugs, how to report them @cindex Bugs, how to report them
@cindex Author, how to reach @cindex Author, how to reach
@cindex Email to the author @cindex Email to the author
@cindex Known bugs
@cindex Bugs, known
@cindex FAQ
@cindex Problems, list of common
If you find a bug or misfeature, don't hesitate to tell me! Send email If you find a bug or misfeature, don't hesitate to tell me! Send email
to @samp{ceder@@lysator.liu.se}. to @samp{ceder@@lysator.liu.se}.
@ -1413,8 +1688,40 @@ If you have ideas for improvements, or if you have written some
extensions to this package, I would like to hear from you. I hope that extensions to this package, I would like to hear from you. I hope that
you find this package useful! you find this package useful!
Below is a partial list of currently known problems with pcl-cvs version
1.05.
@node Function and Variable Index, Concept Index, Reporting bugs and ideas, Top @table @asis
@item Commit causes Emacs to hang
Emacs waits for the @samp{cvs commit} command to finish before you can
do anything. If you start a background job from the loginfo file you
must take care that it closes @samp{stdout} and @samp{stderr} if you do
not want to wait for it. (You do that with @samp{background-command &>-
2&>- &} if you are starting @samp{background-command} from a
@samp{/bin/sh} shell script).
Your emacs will also hang if there was a lock file in the repository.
In this case you can type @kbd{C-g} to get control over your emacs
again.
@item Name clash in Emacs 19
This is really a bug in Elib or the Emacs 19 distribution. Both Elib and
Emacs 19.6 through at least 19.10 contains a file named
@file{cookie.el}. One of the files will have to be renamed, and we are
currently negotiating about which of the files to rename.
@item Commands while cvs-update is running
It is possible to type commands in the *cvs* buffer while the update is
running, but error messages is all that you will get. The error
messages should be better.
@item Unexpected output from CVS
Unexpected output from CVS confuses pcl-cvs. It will currently create a
bug report that you can mail to me. It should do something more
civilized.
@end table
@node Function and Variable Index, Concept Index, Bugs, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@unnumbered Function and Variable Index @unnumbered Function and Variable Index

View File

@ -1,208 +1,184 @@
#!/bin/csh #!/bin/sh
# #
# rcs-to-cvs,v 1.3 1992/04/10 03:04:25 berliner Exp # $Id: rcs-to-cvs,v 1.4 1994/09/21 07:23:16 berliner Exp $
# Contributed by Per Cederqvist <ceder@lysator.liu.se>. # Based on the CVS 1.0 checkin csh script.
# Contributed by Per Cederqvist <ceder@signum.se>.
# Rewritten in sh by David MacKenzie <djm@cygnus.com>.
# #
# Copyright (c) 1989, Brian Berliner # Copyright (c) 1989, Brian Berliner
# #
# You may distribute under the terms of the GNU General Public License # You may distribute under the terms of the GNU General Public License.
# as specified in the README file that comes with the CVS 1.0 kit.
# #
############################################################################# #############################################################################
# # #
# This script is used to check in sources that previously was under RCS or # # Check in sources that previously were under RCS or no source control system.
# no source control system. # #
# # # The repository is the directory where the sources should be deposited.
# Usage: rcs-to-cvs repository # #
# # # Traverses the current directory, ensuring that an
# The repository is the directory where the sources should # # identical directory structure exists in the repository directory. It
# be deposited. # then checks the files in in the following manner:
# # #
# checkin traverses the current directory, ensuring that an # # 1) If the file doesn't yet exist, check it in as revision 1.1
# identical directory structure exists in the repository directory. It # #
# then checks the files in in the following manner: # # The script also is somewhat verbose in letting the user know what is
# # # going on. It prints a diagnostic when it creates a new file, or updates
# 1) If the file doesn't yet exist, check it in # # a file that has been modified on the trunk.
# as revision 0.1 # #
# # # Bugs: doesn't put the files in branch 1.1.1
# The script also is somewhat verbose in letting the user know what is # # doesn't put in release and vendor tags
# going on. It prints a diagnostic when it creates a new file, or updates # #
# a file that has been modified on the trunk. #
# #
############################################################################# #############################################################################
set vbose = 0 usage="Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository"
set message = "" vbose=0
set cvsbin = /usr/gnu/bin message=""
set rcsbin = /usr/gnu/bin message_file=/usr/tmp/checkin.$$
set grep = /bin/grep got_one=0
set message_file = /usr/tmp/checkin.$$
set got_one = 0
if ( $#argv < 1 ) then if [ $# -lt 1 ]; then
echo "Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository" echo "$usage" >&2
exit 1 exit 1
endif fi
while ( $#argv )
switch ( $argv[1] ) while [ $# -ne 0 ]; do
case -v: case "$1" in
set vbose = 1 -v)
breaksw vbose=1
case -m: ;;
-m)
shift shift
echo $argv[1] > $message_file echo $1 > $message_file
set got_one = 1 got_one=1
breaksw ;;
case -f: -f)
shift shift
set message_file = $argv[1] message_file=$1
set got_one = 2 got_one=2
breaksw ;;
default: *)
break break
endsw esac
shift shift
end done
if ( $#argv < 1 ) then
echo "Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository" if [ $# -lt 1 ]; then
echo "$usage" >&2
exit 1 exit 1
endif fi
set repository = $argv[1]
repository=$1
shift shift
if ( ! $?CVSROOT ) then if [ -z "$CVSROOT" ]; then
echo "Please set the environmental variable CVSROOT to the root" echo "Please the environmental variable CVSROOT to the root" >&2
echo " of the tree you wish to update" echo " of the tree you wish to update" >&2
exit 1 exit 1
endif fi
if ( $got_one == 0 ) then if [ $got_one -eq 0 ]; then
echo "Please Edit this file to contain the RCS log information" >$message_file echo "Please Edit this file to contain the RCS log information" >$message_file
echo "to be associated with this file (please remove these lines)">>$message_file echo "to be associated with this directory (please remove these lines)">>$message_file
if ( $?EDITOR ) then ${EDITOR-/usr/ucb/vi} $message_file
$EDITOR $message_file > /dev/tty got_one=1
else fi
/usr/ucb/vi $message_file > /dev/tty
endif
set got_one = 1
endif
umask 22 umask 22
set update_dir = ${CVSROOT}/${repository} update_dir=${CVSROOT}/${repository}
if ( -d SCCS ) then [ ! -d ${update_dir} ] && mkdir $update_dir
echo SCCS files detected!
if [ -d SCCS ]; then
echo SCCS files detected! >&2
exit 1 exit 1
endif fi
if ( -d RCS ) then if [ -d RCS ]; then
$rcsbin/co RCS/* >& /dev/null co RCS/*
endif fi
foreach name ( * .[a-zA-Z0-9]* )
for name in * .[a-zA-Z0-9]*
do
case "$name" in
RCS | \* | .\[a-zA-Z0-9\]\* ) continue ;;
esac
echo $name echo $name
if ( "$name" == SCCS ) then if [ $vbose -ne 0 ]; then
continue
endif
if ( "$name" == RCS ) then
continue
endif
if ( $vbose ) then
echo "Updating ${repository}/${name}" echo "Updating ${repository}/${name}"
endif fi
if ( -d "$name" ) then if [ -d "$name" ]; then
if ( ! -d "${update_dir}/${name}" ) then if [ ! -d "${update_dir}/${name}" ]; then
echo "WARNING: Creating new directory ${repository}/${name}" echo "WARNING: Creating new directory ${repository}/${name}"
mkdir "${update_dir}/${name}" mkdir "${update_dir}/${name}"
if ( $status ) then if [ $? -ne 0 ]; then
echo "ERROR: mkdir failed - aborting" echo "ERROR: mkdir failed - aborting" >&2
exit 1 exit 1
endif fi
endif fi
chdir "$name" cd "$name"
if ( $status ) then if [ $? -ne 0 ]; then
echo "ERROR: Couldn\'t chdir to "$name" - aborting" echo "ERROR: Couldn\'t cd to $name - aborting" >&2
exit 1 exit 1
endif fi
if ( $vbose ) then if [ $vbose -ne 0 ]; then
rcs-to-cvs -v -f $message_file "${repository}/${name}" $0 -v -f $message_file "${repository}/${name}"
else else
rcs-to-cvs -f $message_file "${repository}/${name}" $0 -f $message_file "${repository}/${name}"
endif fi
if ( $status ) then if [ $? -ne 0 ]; then
exit 1 exit 1
endif fi
chdir .. cd ..
else # if not directory else # if not directory
if ( ! -f "$name" ) then if [ ! -f "$name" ]; then
echo "WARNING: "$name" is neither a regular file" echo "WARNING: $name is neither a regular file"
echo " nor a directory - ignored" echo " nor a directory - ignored"
continue continue
endif fi
set file = "${update_dir}/${name},v" file="${update_dir}/${name},v"
set new = 0 comment=""
set comment = "" if grep -s '\$Log.*\$' "${name}"; then # If $Log keyword
grep -s '\$Log.*\$' "${name}" myext=`echo $name | sed 's,.*\.,,'`
if ( $status == 0 ) then # If $Log keyword [ "$myext" = "$name" ] && myext=
set myext = ${name:e} case "$myext" in
set knownext = 0 c | csh | e | f | h | l | mac | me | mm | ms | p | r | red | s | sh | sl | cl | ml | el | tex | y | ye | yr | "" )
foreach xx ( "c" "csh" "e" "f" "h" "l" "mac" "me" "mm" "ms" "p" "r" "red" "s" "sh" "sl" "cl" "ml" "el" "tex" "y" "ye" "yr" "" ) ;;
if ( "${myext}" == "${xx}" ) then
set knownext = 1 * )
break echo "For file ${file}:"
endif
end
if ( $knownext == 0 ) then
echo For file ${file}:
grep '\$Log.*\$' "${name}" grep '\$Log.*\$' "${name}"
echo -n "Please insert a comment leader for file ${name} > " echo -n "Please insert a comment leader for file ${name} > "
set comment = $< read comment
endif ;;
endif esac
if ( ! -f "$file" ) then # If not exists in repository fi
if ( ! -f "${update_dir}/Attic/${name},v" ) then if [ ! -f "$file" ]; then # If not exists in repository
if [ ! -f "${update_dir}/Attic/${name},v" ]; then
echo "WARNING: Creating new file ${repository}/${name}" echo "WARNING: Creating new file ${repository}/${name}"
if ( -f RCS/"${name}",v ) then if [ -f RCS/"${name}",v ]; then
echo "MSG: Copying old rcs file." echo "MSG: Copying old rcs file."
cp RCS/"${name}",v "$file" cp RCS/"${name}",v "$file"
else else
if ( "${comment}" != "" ) then if [ -n "${comment}" ]; then
$rcsbin/rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file" rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file"
endif fi
$rcsbin/ci -q -u0.1 -t${message_file} -m'.' "$file" ci -q -u1.1 -t${message_file} -m'.' "$file"
if ( $status ) then if [ $? -ne 0 ]; then
echo "ERROR: Initial check-in of $file failed - aborting" echo "ERROR: Initial check-in of $file failed - aborting" >&2
exit 1 exit 1
endif fi
set new = 1 fi
endif
else else
set file = "${update_dir}/Attic/${name},v" file="${update_dir}/Attic/${name},v"
echo "WARNING: IGNORED: ${repository}/Attic/${name}" echo "WARNING: IGNORED: ${repository}/Attic/${name}"
continue continue
endif fi
else # File existed else # File existed
echo ERROR: File exists: Ignored: "$file" echo "ERROR: File exists in repository: Ignored: $file"
continue continue
# set headbranch = `sed -n '/^head/p; /^branch/p; 2q' $file` fi
# if ( $#headbranch != 2 && $#headbranch != 4 ) then fi
# echo "ERROR: corrupted RCS file $file - aborting" done
# endif
# set head = "$headbranch[2]" [ $got_one -eq 1 ] && rm -f $message_file
# set branch = ""
# if ( $#headbranch == 4 ) then exit 0
# set branch = "$headbranch[4]"
# endif
# if ( "$head" == "1.1;" && "$branch" != "1.1.1;" ) then
# ${rcsbin}/rcsdiff -q -r1.1 $file > /dev/null
# if ( ! $status ) then
# set new = 1
# endif
# else
# if ( "$branch" != "1.1.1;" ) then
# echo -n "WARNING: Updating locally modified file "
# echo "${repository}/${name}"
# endif
# endif
endif
endif
end
if ( $got_one == 1 ) rm $message_file

View File

@ -43,7 +43,7 @@
# #
# Various hacks made by Brian Berliner before inclusion in CVS contrib area. # Various hacks made by Brian Berliner before inclusion in CVS contrib area.
# #
# sccs2rcs,v 1.1 1992/04/10 03:04:26 berliner Exp # $Id: sccs2rcs,v 1.1 1992/04/10 03:04:26 berliner Exp $
#we'll assume the user set up the path correctly #we'll assume the user set up the path correctly

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Add * Add
* *
@ -27,17 +27,13 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)add.c 1.46 92/04/03"; static char rcsid[] = "$CVSid: @(#)add.c 1.55 94/10/22 $";
USE(rcsid)
#endif #endif
#if __STDC__ static int add_directory PROTO((char *repository, char *dir));
static int add_directory (char *repository, char *dir); static int build_entry PROTO((char *repository, char *user, char *options,
static int build_entry (char *repository, char *user, char *options, char *message, List * entries, char *tag));
char *message, List * entries);
#else
static int add_directory ();
static int build_entry ();
#endif /* __STDC__ */
static char *add_usage[] = static char *add_usage[] =
{ {
@ -52,7 +48,7 @@ add (argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
char message[MAXMESGLEN]; char *message = NULL;
char *user; char *user;
int i; int i;
char *repository; char *repository;
@ -67,9 +63,8 @@ add (argc, argv)
usage (add_usage); usage (add_usage);
/* parse args */ /* parse args */
message[0] = '\0';
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "k:m:")) != -1) while ((c = getopt (argc, argv, "k:m:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -80,14 +75,7 @@ add (argc, argv)
break; break;
case 'm': case 'm':
if (strlen (optarg) >= sizeof (message)) message = xstrdup (optarg);
{
error (0, 0, "warning: message too long; truncated!");
(void) strncpy (message, optarg, sizeof (message));
message[sizeof (message) - 1] = '\0';
}
else
(void) strcpy (message, optarg);
break; break;
case '?': case '?':
default: default:
@ -111,7 +99,8 @@ add (argc, argv)
int begin_err = err; int begin_err = err;
user = argv[i]; user = argv[i];
if (index (user, '/') != NULL) strip_trailing_slashes (user);
if (strchr (user, '/') != NULL)
{ {
error (0, 0, error (0, 0,
"cannot add files with '/' in their name; %s not added", user); "cannot add files with '/' in their name; %s not added", user);
@ -153,19 +142,18 @@ add (argc, argv)
/* There is a user file, so build the entry for it */ /* There is a user file, so build the entry for it */
if (build_entry (repository, user, vers->options, if (build_entry (repository, user, vers->options,
message, entries) != 0) message, entries, vers->tag) != 0)
err++; err++;
else if (!quiet) else
{ {
added_files++; added_files++;
error (0, 0, "scheduling file `%s' for addition", if (!quiet)
user); error (0, 0, "scheduling file `%s' for addition", user);
} }
} }
} }
else else
{ {
/* /*
* There is an RCS file already, so somebody else must've * There is an RCS file already, so somebody else must've
* added it * added it
@ -214,7 +202,7 @@ add (argc, argv)
(void) strcpy (vers->vn_user, tmp); (void) strcpy (vers->vn_user, tmp);
(void) sprintf (tmp, "Resurrected %s", user); (void) sprintf (tmp, "Resurrected %s", user);
Register (entries, user, vers->vn_user, tmp, vers->options, Register (entries, user, vers->vn_user, tmp, vers->options,
vers->tag, vers->date); vers->tag, vers->date, vers->ts_conflict);
free (tmp); free (tmp);
/* XXX - bugs here; this really resurrect the head */ /* XXX - bugs here; this really resurrect the head */
@ -257,6 +245,10 @@ add (argc, argv)
error (0, 0, "use 'cvs commit' to add %s permanently", error (0, 0, "use 'cvs commit' to add %s permanently",
(added_files == 1) ? "this file" : "these files"); (added_files == 1) ? "this file" : "these files");
dellist (&entries); dellist (&entries);
if (message)
free (message);
return (err); return (err);
} }
@ -276,7 +268,7 @@ add_directory (repository, dir)
char message[PATH_MAX + 100]; char message[PATH_MAX + 100];
char *tag, *date; char *tag, *date;
if (index (dir, '/') != NULL) if (strchr (dir, '/') != NULL)
{ {
error (0, 0, error (0, 0,
"directory %s not added; must be a direct sub-directory", dir); "directory %s not added; must be a direct sub-directory", dir);
@ -334,10 +326,12 @@ add_directory (repository, dir)
if (!isdir (rcsdir)) if (!isdir (rcsdir))
{ {
mode_t omask; mode_t omask;
char line[MAXLINELEN];
Node *p; Node *p;
List *ulist; List *ulist;
#if 0
char line[MAXLINELEN];
(void) printf ("Add directory %s to the repository (y/n) [n] ? ", (void) printf ("Add directory %s to the repository (y/n) [n] ? ",
rcsdir); rcsdir);
(void) fflush (stdout); (void) fflush (stdout);
@ -348,6 +342,8 @@ add_directory (repository, dir)
error (0, 0, "directory %s not added", rcsdir); error (0, 0, "directory %s not added", rcsdir);
goto out; goto out;
} }
#endif
omask = umask (2); omask = umask (2);
if (mkdir (rcsdir, 0777) < 0) if (mkdir (rcsdir, 0777) < 0)
{ {
@ -389,12 +385,13 @@ add_directory (repository, dir)
* interrogating the user. Returns non-zero on error. * interrogating the user. Returns non-zero on error.
*/ */
static int static int
build_entry (repository, user, options, message, entries) build_entry (repository, user, options, message, entries, tag)
char *repository; char *repository;
char *user; char *user;
char *options; char *options;
char *message; char *message;
List *entries; List *entries;
char *tag;
{ {
char fname[PATH_MAX]; char fname[PATH_MAX];
char line[MAXLINELEN]; char line[MAXLINELEN];
@ -418,6 +415,7 @@ build_entry (repository, user, options, message, entries)
/* /*
* The options for the "add" command are store in the file CVS/user,p * The options for the "add" command are store in the file CVS/user,p
* XXX - no they are not!
*/ */
(void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_OPT); (void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_OPT);
fp = open_file (fname, "w+"); fp = open_file (fname, "w+");
@ -431,7 +429,7 @@ build_entry (repository, user, options, message, entries)
*/ */
(void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_LOG); (void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_LOG);
fp = open_file (fname, "w+"); fp = open_file (fname, "w+");
if (*message && fputs (message, fp) == EOF) if (message && fputs (message, fp) == EOF)
error (1, errno, "cannot write to %s", fname); error (1, errno, "cannot write to %s", fname);
if (fclose(fp) == EOF) if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", fname); error(1, errno, "cannot close %s", fname);
@ -442,6 +440,6 @@ build_entry (repository, user, options, message, entries)
* and ,t files, but who cares). * and ,t files, but who cares).
*/ */
(void) sprintf (line, "Initial %s", user); (void) sprintf (line, "Initial %s", user);
Register (entries, user, "0", line, options, (char *) 0, (char *) 0); Register (entries, user, "0", line, options, tag, (char *) 0, (char *) 0);
return (0); return (0);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Administration * Administration
* *
@ -14,18 +14,14 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)admin.c 1.17 92/03/31"; static char rcsid[] = "$CVSid: @(#)admin.c 1.20 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype admin_dirproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype admin_dirproc (char *dir, char *repos, char *update_dir); static int admin_fileproc PROTO((char *file, char *update_dir,
static int admin_fileproc (char *file, char *update_dir,
char *repository, List *entries, char *repository, List *entries,
List *srcfiles); List *srcfiles));
#else
static int admin_fileproc ();
static Dtype admin_dirproc ();
#endif /* __STDC__ */
static char *admin_usage[] = static char *admin_usage[] =
{ {
@ -60,7 +56,7 @@ admin (argc, argv)
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc, err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
(int (*) ()) NULL, argc, argv, 0, (int (*) ()) NULL, argc, argv, 0,
W_LOCAL, 0, 1, (char *) NULL, 1); W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err); return (err);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Check In * Check In
* *
@ -18,22 +18,25 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)checkin.c 1.40 92/03/31"; static char rcsid[] = "$CVSid: @(#)checkin.c 1.48 94/10/07 $";
USE(rcsid)
#endif #endif
int int
Checkin (type, file, repository, rcs, rev, tag, message, entries) Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
int type; int type;
char *file; char *file;
char *repository; char *repository;
char *rcs; char *rcs;
char *rev; char *rev;
char *tag; char *tag;
char *options;
char *message; char *message;
List *entries; List *entries;
{ {
char fname[PATH_MAX]; char fname[PATH_MAX];
Vers_TS *vers; Vers_TS *vers;
int set_time;
(void) printf ("Checking in %s;\n", file); (void) printf ("Checking in %s;\n", file);
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file); (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
@ -48,7 +51,8 @@ Checkin (type, file, repository, rcs, rev, tag, message, entries)
run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI, run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
rev ? "-r" : "", rev ? rev : ""); rev ? "-r" : "", rev ? rev : "");
run_args ("-m%s", message); run_args ("-m%s", (*message == '\0' || strcmp(message, "\n") == 0) ?
"*** empty log message ***\n" : message);
run_arg (rcs); run_arg (rcs);
switch (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) switch (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL))
@ -64,16 +68,25 @@ Checkin (type, file, repository, rcs, rev, tag, message, entries)
* original user file. * original user file.
*/ */
/* XXX - make sure -k options are used on the co; and tag/date? */ if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */
run_setup ("%s%s -q %s%s", Rcsbin, RCS_CO, options[0] = '\0';
run_setup ("%s%s -q %s %s%s", Rcsbin, RCS_CO, options,
rev ? "-r" : "", rev ? rev : ""); rev ? "-r" : "", rev ? rev : "");
run_arg (rcs); run_arg (rcs);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
xchmod (file, 1); xchmod (file, 1);
if (xcmp (file, fname) == 0) if (xcmp (file, fname) == 0)
{
rename_file (fname, file); rename_file (fname, file);
/* the time was correct, so leave it alone */
set_time = 0;
}
else else
{
(void) unlink_file (fname); (void) unlink_file (fname);
/* sync up with the time from the RCS file */
set_time = 1;
}
/* /*
* If we want read-only files, muck the permissions here, before * If we want read-only files, muck the permissions here, before
@ -92,11 +105,11 @@ Checkin (type, file, repository, rcs, rev, tag, message, entries)
/* re-register with the new data */ /* re-register with the new data */
vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL, vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
file, 1, 1, entries, (List *) NULL); file, 1, set_time, entries, (List *) NULL);
if (strcmp (vers->options, "-V4") == 0) if (strcmp (vers->options, "-V4") == 0)
vers->options[0] = '\0'; vers->options[0] = '\0';
Register (entries, file, vers->vn_rcs, vers->ts_user, vers->options, Register (entries, file, vers->vn_rcs, vers->ts_user,
vers->tag, vers->date); vers->options, vers->tag, vers->date, (char *) 0);
history_write (type, (char *) 0, vers->vn_rcs, file, repository); history_write (type, (char *) 0, vers->vn_rcs, file, repository);
freevers_ts (&vers); freevers_ts (&vers);
break; break;
@ -131,5 +144,6 @@ Checkin (type, file, repository, rcs, rev, tag, message, entries)
run_arg (rcs); run_arg (rcs);
(void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL); (void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
} }
return (0); return (0);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Create Version * Create Version
* *
@ -36,22 +36,17 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)checkout.c 1.67 92/04/10"; static char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static char *findslash PROTO((char *start, char *p));
static char *findslash (char *start, char *p); static int build_dirs_and_chdir PROTO((char *dir, char *prepath, char *realdir,
static int build_dirs_and_chdir (char *dir, char *prepath, char *realdir, int sticky));
int sticky); static int checkout_proc PROTO((int *pargc, char *argv[], char *where,
static int checkout_proc (int *pargc, char *argv[], char *where,
char *mwhere, char *mfile, int shorten, char *mwhere, char *mfile, int shorten,
int local_specified, char *omodule, int local_specified, char *omodule,
char *msg); char *msg));
#else
static int checkout_proc ();
static char *findslash ();
static int build_dirs_and_chdir ();
#endif /* __STDC__ */
static char *checkout_usage[] = static char *checkout_usage[] =
{ {
@ -84,8 +79,8 @@ static char *export_usage[] =
"\t-l\tLocal directory only, not recursive\n", "\t-l\tLocal directory only, not recursive\n",
"\t-n\tDo not run module program (if any).\n", "\t-n\tDo not run module program (if any).\n",
"\t-q\tSomewhat quiet.\n", "\t-q\tSomewhat quiet.\n",
"\t-r rev\tCheck out revision or tag. (implies -P)\n", "\t-r rev\tCheck out revision or tag.\n",
"\t-D date\tCheck out revisions as of date. (implies -P)\n", "\t-D date\tCheck out revisions as of date.\n",
"\t-d dir\tCheck out into dir instead of module name.\n", "\t-d dir\tCheck out into dir instead of module name.\n",
NULL NULL
}; };
@ -106,7 +101,7 @@ checkout (argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
register int i; int i;
int c; int c;
DBM *db; DBM *db;
int cat = 0, err = 0, status = 0; int cat = 0, err = 0, status = 0;
@ -139,7 +134,7 @@ checkout (argc, argv)
ign_setup (); ign_setup ();
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, valid_options)) != -1) while ((c = getopt (argc, argv, valid_options)) != -1)
{ {
switch (c) switch (c)
{ {
@ -261,9 +256,15 @@ checkout (argc, argv)
where = (char *) NULL; where = (char *) NULL;
if (!isfile (CVSADM) && !isfile (OCVSADM)) if (!isfile (CVSADM) && !isfile (OCVSADM))
{ {
(void) sprintf (repository, "%s/%s", CVSroot, CVSNULLREPOS); (void) sprintf (repository, "%s/%s/%s", CVSroot, CVSROOTADM,
CVSNULLREPOS);
if (!isfile (repository)) if (!isfile (repository))
(void) mkdir (repository, 0777); (void) mkdir (repository, 0777);
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
Create_Admin (".", repository, (char *) NULL, (char *) NULL); Create_Admin (".", repository, (char *) NULL, (char *) NULL);
if (!noexec) if (!noexec)
{ {
@ -283,11 +284,11 @@ checkout (argc, argv)
* attempt to cd to the indicated place. where then becomes simply the * attempt to cd to the indicated place. where then becomes simply the
* last component * last component
*/ */
if (where != NULL && index (where, '/') != NULL) if (where != NULL && strchr (where, '/') != NULL)
{ {
char *slash; char *slash;
slash = rindex (where, '/'); slash = strrchr (where, '/');
*slash = '\0'; *slash = '\0';
if (chdir (where) < 0) if (chdir (where) < 0)
@ -358,7 +359,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
char file[PATH_MAX]; char file[PATH_MAX];
/* if mfile is really a path, straighten it out first */ /* if mfile is really a path, straighten it out first */
if ((cp = rindex (mfile, '/')) != NULL) if ((cp = strrchr (mfile, '/')) != NULL)
{ {
*cp = 0; *cp = 0;
(void) strcat (repository, "/"); (void) strcat (repository, "/");
@ -386,7 +387,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
{ {
char *slash; char *slash;
if ((slash = rindex (mfile, '/')) != NULL) if ((slash = strrchr (mfile, '/')) != NULL)
mwhere = slash + 1; mwhere = slash + 1;
else else
mwhere = mfile; mwhere = mfile;
@ -448,7 +449,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
*/ */
if (shorten && where == NULL) if (shorten && where == NULL)
{ {
if ((cp = rindex (argv[0], '/')) != NULL) if ((cp = strrchr (argv[0], '/')) != NULL)
{ {
(void) strcpy (xwhere, cp + 1); (void) strcpy (xwhere, cp + 1);
where = xwhere; where = xwhere;
@ -498,8 +499,8 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
* elements exist in where. Big Black Magic * elements exist in where. Big Black Magic
*/ */
prepath = xstrdup (repository); prepath = xstrdup (repository);
cp = rindex (where, '/'); cp = strrchr (where, '/');
cp2 = rindex (prepath, '/'); cp2 = strrchr (prepath, '/');
while (cp != NULL) while (cp != NULL)
{ {
cp = findslash (where, cp - 1); cp = findslash (where, cp - 1);
@ -533,13 +534,23 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
if (!noexec && *pargc > 1) if (!noexec && *pargc > 1)
{ {
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
Create_Admin (".", repository, (char *) NULL, (char *) NULL); Create_Admin (".", repository, (char *) NULL, (char *) NULL);
fp = open_file (CVSADM_ENTSTAT, "w+"); fp = open_file (CVSADM_ENTSTAT, "w+");
if (fclose(fp) == EOF) if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", CVSADM_ENTSTAT); error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
} }
else else
{
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
Create_Admin (".", repository, tag, date); Create_Admin (".", repository, tag, date);
}
} }
else else
{ {
@ -622,8 +633,9 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
if (vers->ts_user == NULL) if (vers->ts_user == NULL)
{ {
(void) sprintf (line, "Initial %s", user); (void) sprintf (line, "Initial %s", user);
Register (entries, user, vers->vn_rcs, line, vers->options, Register (entries, user, vers->vn_rcs ? vers->vn_rcs : "0",
vers->tag, vers->date); line, vers->options, vers->tag,
vers->date, (char *) 0);
} }
freevers_ts (&vers); freevers_ts (&vers);
} }
@ -650,9 +662,9 @@ findslash (start, p)
char *start; char *start;
char *p; char *p;
{ {
while ((int) p >= (int) start && *p != '/') while (p >= start && *p != '/')
p--; p--;
if ((int) p < (int) start) if (p < start)
return (NULL); return (NULL);
else else
return (p); return (p);
@ -681,7 +693,7 @@ build_dirs_and_chdir (dir, prepath, realdir, sticky)
(void) strcpy (path, dir); (void) strcpy (path, dir);
(void) strcpy (path2, realdir); (void) strcpy (path2, realdir);
for (cp = path, cp2 = path2; for (cp = path, cp2 = path2;
(slash = index (cp, '/')) != NULL && (slash2 = index (cp2, '/')) != NULL; (slash = strchr (cp, '/')) != NULL && (slash2 = strchr (cp2, '/')) != NULL;
cp = slash + 1, cp2 = slash2 + 1) cp = slash + 1, cp2 = slash2 + 1)
{ {
*slash = '\0'; *slash = '\0';
@ -696,6 +708,9 @@ build_dirs_and_chdir (dir, prepath, realdir, sticky)
strcmp (command_name, "export") != 0) strcmp (command_name, "export") != 0)
{ {
(void) sprintf (repository, "%s/%s", prepath, path2); (void) sprintf (repository, "%s/%s", prepath, path2);
/* I'm not sure whether this check is redundant. */
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
Create_Admin (".", repository, sticky ? (char *) NULL : tag, Create_Admin (".", repository, sticky ? (char *) NULL : tag,
sticky ? (char *) NULL : date); sticky ? (char *) NULL : date);
if (!noexec) if (!noexec)

View File

@ -3,28 +3,25 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)classify.c 1.11 92/03/31"; static char rcsid[] = "$CVSid: @(#)classify.c 1.17 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers, List * entries));
static void sticky_ck (char *file, int aflag, Vers_TS * vers, List * entries);
#else
static void sticky_ck ();
#endif /* __STDC__ */
/* /*
* Classify the state of a file * Classify the state of a file
*/ */
Ctype Ctype
Classify_File (file, tag, date, options, force_tag_match, aflag, repository, Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
entries, srcfiles, versp) entries, srcfiles, versp, update_dir, pipeout)
char *file; char *file;
char *tag; char *tag;
char *date; char *date;
@ -35,9 +32,18 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
List *entries; List *entries;
List *srcfiles; List *srcfiles;
Vers_TS **versp; Vers_TS **versp;
char *update_dir;
int pipeout;
{ {
Vers_TS *vers; Vers_TS *vers;
Ctype ret; Ctype ret;
char *fullname;
fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
if (update_dir[0] == '\0')
strcpy (fullname, file);
else
sprintf (fullname, "%s/%s", update_dir, file);
/* get all kinds of good data about the file */ /* get all kinds of good data about the file */
vers = Version_TS (repository, options, tag, date, file, vers = Version_TS (repository, options, tag, date, file,
@ -54,7 +60,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
/* there is no user file */ /* there is no user file */
if (!force_tag_match || !(vers->tag || vers->date)) if (!force_tag_match || !(vers->tag || vers->date))
if (!really_quiet) if (!really_quiet)
error (0, 0, "nothing known about %s", file); error (0, 0, "nothing known about %s", fullname);
ret = T_UNKNOWN; ret = T_UNKNOWN;
} }
else else
@ -63,7 +69,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!force_tag_match || !(vers->tag || vers->date)) if (!force_tag_match || !(vers->tag || vers->date))
if (!really_quiet) if (!really_quiet)
error (0, 0, "use `cvs add' to create an entry for %s", error (0, 0, "use `cvs add' to create an entry for %s",
file); fullname);
ret = T_UNKNOWN; ret = T_UNKNOWN;
} }
} }
@ -78,16 +84,26 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
} }
else else
{ {
if (pipeout)
{
/*
* The user file doesn't necessarily have anything
* to do with this.
*/
ret = T_CHECKOUT;
}
/* /*
* There is a user file; print a warning and add it to the * There is a user file; print a warning and add it to the
* conflict list, only if it is indeed different from what we * conflict list, only if it is indeed different from what we
* plan to extract * plan to extract
*/ */
if (No_Difference (file, vers, entries)) else if (No_Difference (file, vers, entries,
repository, update_dir))
{ {
/* the files were different so it is a conflict */ /* the files were different so it is a conflict */
if (!really_quiet) if (!really_quiet)
error (0, 0, "move away %s; it is in the way", file); error (0, 0, "move away %s; it is in the way",
fullname);
ret = T_CONFLICT; ret = T_CONFLICT;
} }
else else
@ -107,7 +123,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
* entry * entry
*/ */
if (!really_quiet) if (!really_quiet)
error (0, 0, "warning: new-born %s has disappeared", file); error (0, 0, "warning: new-born %s has disappeared", fullname);
ret = T_REMOVE_ENTRY; ret = T_REMOVE_ENTRY;
} }
else else
@ -126,7 +142,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet) if (!really_quiet)
error (0, 0, error (0, 0,
"conflict: %s created independently by second party", "conflict: %s created independently by second party",
file); fullname);
ret = T_CONFLICT; ret = T_CONFLICT;
} }
} }
@ -169,7 +185,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet) if (!really_quiet)
error (0, 0, error (0, 0,
"conflict: removed %s was modified by second party", "conflict: removed %s was modified by second party",
file); fullname);
ret = T_CONFLICT; ret = T_CONFLICT;
} }
} }
@ -177,7 +193,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
{ {
/* The user file shouldn't be there */ /* The user file shouldn't be there */
if (!really_quiet) if (!really_quiet)
error (0, 0, "%s should be removed and is still there", file); error (0, 0, "%s should be removed and is still there",
fullname);
ret = T_REMOVED; ret = T_REMOVED;
} }
} }
@ -193,7 +210,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
/* There is no user file, so just remove the entry */ /* There is no user file, so just remove the entry */
if (!really_quiet) if (!really_quiet)
error (0, 0, "warning: %s is not (any longer) pertinent", error (0, 0, "warning: %s is not (any longer) pertinent",
file); fullname);
ret = T_REMOVE_ENTRY; ret = T_REMOVE_ENTRY;
} }
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0) else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
@ -204,7 +221,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
* the entry list * the entry list
*/ */
if (!really_quiet) if (!really_quiet)
error (0, 0, "%s is no longer in the repository", file); error (0, 0, "%s is no longer in the repository",
fullname);
ret = T_REMOVE_ENTRY; ret = T_REMOVE_ENTRY;
} }
else else
@ -213,13 +231,14 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
* The user file has been modified and since it is no longer * The user file has been modified and since it is no longer
* in the repository, a conflict is raised * in the repository, a conflict is raised
*/ */
if (No_Difference (file, vers, entries)) if (No_Difference (file, vers, entries,
repository, update_dir))
{ {
/* they are different -> conflict */ /* they are different -> conflict */
if (!really_quiet) if (!really_quiet)
error (0, 0, error (0, 0,
"conflict: %s is modified but no longer in the repository", "conflict: %s is modified but no longer in the repository",
file); fullname);
ret = T_CONFLICT; ret = T_CONFLICT;
} }
else else
@ -228,7 +247,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet) if (!really_quiet)
error (0, 0, error (0, 0,
"warning: %s is not (any longer) pertinent", "warning: %s is not (any longer) pertinent",
file); fullname);
ret = T_REMOVE_ENTRY; ret = T_REMOVE_ENTRY;
} }
} }
@ -246,7 +265,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
*/ */
if (strcmp (command_name, "update") == 0) if (strcmp (command_name, "update") == 0)
if (!really_quiet) if (!really_quiet)
error (0, 0, "warning: %s was lost", file); error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT; ret = T_CHECKOUT;
} }
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0) else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
@ -274,7 +293,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
* The user file appears to have been modified, but we call * The user file appears to have been modified, but we call
* No_Difference to verify that it really has been modified * No_Difference to verify that it really has been modified
*/ */
if (No_Difference (file, vers, entries)) if (No_Difference (file, vers, entries,
repository, update_dir))
{ {
/* /*
@ -323,7 +343,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (strcmp (command_name, "update") == 0) if (strcmp (command_name, "update") == 0)
if (!really_quiet) if (!really_quiet)
error (0, 0, "warning: %s was lost", file); error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT; ret = T_CHECKOUT;
} }
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0) else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
@ -336,7 +356,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
} }
else else
{ {
if (No_Difference (file, vers, entries)) if (No_Difference (file, vers, entries,
repository, update_dir))
/* really modified, needs to merge */ /* really modified, needs to merge */
ret = T_NEEDS_MERGE; ret = T_NEEDS_MERGE;
else else
@ -352,6 +373,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
else else
freevers_ts (&vers); freevers_ts (&vers);
free (fullname);
/* return the status of the file */ /* return the status of the file */
return (ret); return (ret);
} }
@ -374,7 +397,7 @@ sticky_ck (file, aflag, vers, entries)
((entdate && !vers->date) || (!entdate && vers->date))) ((entdate && !vers->date) || (!entdate && vers->date)))
{ {
Register (entries, file, vers->vn_user, vers->ts_rcs, Register (entries, file, vers->vn_user, vers->ts_rcs,
vers->options, vers->tag, vers->date); vers->options, vers->tag, vers->date, vers->ts_conflict);
} }
} }
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Commit Files * Commit Files
* *
@ -17,68 +17,46 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)commit.c 1.84 92/03/31"; static char rcsid[] = "$CVSid: @(#)commit.c 1.101 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype check_direntproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype check_direntproc (char *dir, char *repos, char *update_dir); static int check_fileproc PROTO((char *file, char *update_dir, char *repository,
static int check_fileproc (char *file, char *update_dir, char *repository, List * entries, List * srcfiles));
List * entries, List * srcfiles); static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
static int check_filesdoneproc (int err, char *repos, char *update_dir); static int checkaddfile PROTO((char *file, char *repository, char *tag,
static int checkaddfile (char *file, char *repository, char *tag); List *srcfiles));
static Dtype commit_direntproc (char *dir, char *repos, char *update_dir); static Dtype commit_direntproc PROTO((char *dir, char *repos, char *update_dir));
static int commit_dirleaveproc (char *dir, int err, char *update_dir); static int commit_dirleaveproc PROTO((char *dir, int err, char *update_dir));
static int commit_fileproc (char *file, char *update_dir, char *repository, static int commit_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles); List * entries, List * srcfiles));
static int commit_filesdoneproc (int err, char *repository, char *update_dir); static int commit_filesdoneproc PROTO((int err, char *repository, char *update_dir));
static int finaladd (char *file, char *revision, char *tag, char *repository, static int finaladd PROTO((char *file, char *revision, char *tag, char *options,
List *entries); char *repository, List *entries));
static int findmaxrev (Node * p); static int findmaxrev PROTO((Node * p, void *closure));
static int fsortcmp (Node * p, Node * q); static int fsortcmp PROTO((Node * p, Node * q));
static int lock_RCS (char *user, char *rcs, char *rev, char *repository); static int lock_RCS PROTO((char *user, char *rcs, char *rev, char *repository));
static int lock_filesdoneproc (int err, char *repository, char *update_dir); static int lock_filesdoneproc PROTO((int err, char *repository, char *update_dir));
static int lockrcsfile (char *file, char *repository, char *rev); static int lockrcsfile PROTO((char *file, char *repository, char *rev));
static int precommit_list_proc (Node * p); static int precommit_list_proc PROTO((Node * p, void *closure));
static int precommit_proc (char *repository, char *filter); static int precommit_proc PROTO((char *repository, char *filter));
static int remove_file (char *file, char *repository, char *tag, static int remove_file PROTO((char *file, char *repository, char *tag,
List *entries); char *message, List *entries, List *srcfiles));
static void fix_rcs_modes (char *rcs, char *user); static void fix_rcs_modes PROTO((char *rcs, char *user));
static void fixaddfile (char *file, char *repository); static void fixaddfile PROTO((char *file, char *repository));
static void fixbranch (char *file, char *repository, char *branch); static void fixbranch PROTO((char *file, char *repository, char *branch));
static void unlockrcs (char *file, char *repository); static void unlockrcs PROTO((char *file, char *repository));
static void ci_delproc (Node *p); static void ci_delproc PROTO((Node *p));
static void locate_rcs (char *file, char *repository, char *rcs); static void masterlist_delproc PROTO((Node *p));
#else static void locate_rcs PROTO((char *file, char *repository, char *rcs));
static int fsortcmp ();
static int lock_filesdoneproc ();
static int check_fileproc ();
static Dtype check_direntproc ();
static int precommit_list_proc ();
static int precommit_proc ();
static int check_filesdoneproc ();
static int commit_fileproc ();
static int commit_filesdoneproc ();
static Dtype commit_direntproc ();
static int commit_dirleaveproc ();
static int findmaxrev ();
static int remove_file ();
static int finaladd ();
static void unlockrcs ();
static void fixaddfile ();
static void fixbranch ();
static int checkaddfile ();
static int lockrcsfile ();
static int lock_RCS ();
static void fix_rcs_modes ();
static void ci_delproc ();
static void locate_rcs ();
#endif /* __STDC__ */
struct commit_info struct commit_info
{ {
Ctype status; /* as returned from Classify_File() */ Ctype status; /* as returned from Classify_File() */
char *rev; /* a numeric rev, if we know it */ char *rev; /* a numeric rev, if we know it */
char *tag; /* any sticky tag, or -r option */ char *tag; /* any sticky tag, or -r option */
char *options; /* Any sticky -k option */
}; };
struct master_lists struct master_lists
{ {
@ -86,6 +64,7 @@ struct master_lists
List *cilist; /* list with commit_info structs */ List *cilist; /* list with commit_info structs */
}; };
static int force_ci;
static int got_message; static int got_message;
static int run_module_prog = 1; static int run_module_prog = 1;
static int aflag; static int aflag;
@ -98,11 +77,12 @@ static char *message;
static char *commit_usage[] = static char *commit_usage[] =
{ {
"Usage: %s %s [-nRl] [-m msg | -f logfile] [-r rev] files...\n", "Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n",
"\t-n\tDo not run the module program (if any).\n", "\t-n\tDo not run the module program (if any).\n",
"\t-R\tProcess directories recursively.\n", "\t-R\tProcess directories recursively.\n",
"\t-l\tLocal directory only (not recursive).\n", "\t-l\tLocal directory only (not recursive).\n",
"\t-f file\tRead the log message from file.\n", "\t-f\tForce the file to be committed; disables recursion.\n",
"\t-F file\tRead the log message from file.\n",
"\t-m msg\tLog message.\n", "\t-m msg\tLog message.\n",
"\t-r rev\tCommit to this branch or trunk revision.\n", "\t-r rev\tCommit to this branch or trunk revision.\n",
NULL NULL
@ -136,10 +116,8 @@ commit (argc, argv)
} }
#endif /* CVS_BADROOT */ #endif /* CVS_BADROOT */
message = xmalloc (MAXMESGLEN + 1);
message[0] = '\0'; /* Null message by default */
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "nlRm:f:r:")) != -1) while ((c = getopt (argc, argv, "nlRm:fF:r:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -152,14 +130,13 @@ commit (argc, argv)
#else #else
use_editor = FALSE; use_editor = FALSE;
#endif #endif
if (strlen (optarg) >= (size_t) MAXMESGLEN) if (message)
{ {
error (0, 0, "warning: message too long; truncated!"); free (message);
(void) strncpy (message, optarg, MAXMESGLEN); message = NULL;
message[MAXMESGLEN] = '\0';
} }
else
(void) strcpy (message, optarg); message = xstrdup(optarg);
break; break;
case 'r': case 'r':
if (tag) if (tag)
@ -173,6 +150,10 @@ commit (argc, argv)
local = 0; local = 0;
break; break;
case 'f': case 'f':
force_ci = 1;
local = 1; /* also disable recursion */
break;
case 'F':
#ifdef FORCE_USE_EDITOR #ifdef FORCE_USE_EDITOR
use_editor = TRUE; use_editor = TRUE;
#else #else
@ -198,19 +179,26 @@ commit (argc, argv)
tag[strlen (tag) - 1] = '\0'; tag[strlen (tag) - 1] = '\0';
} }
/* some checks related to the "-f logfile" option */ /* some checks related to the "-F logfile" option */
if (logfile) if (logfile)
{ {
int n, logfd; int n, logfd;
struct stat statbuf;
if (*message) if (message)
error (1, 0, "cannot specify both a message and a log file"); error (1, 0, "cannot specify both a message and a log file");
if ((logfd = open (logfile, O_RDONLY)) < 0 || if ((logfd = open (logfile, O_RDONLY)) < 0)
(n = read (logfd, message, MAXMESGLEN)) < 0) error (1, errno, "cannot open log file %s", logfile);
{
if (fstat(logfd, &statbuf) < 0)
error (1, errno, "cannot find size of log file %s", logfile);
message = xmalloc (statbuf.st_size + 1);
if ((n = read (logfd, message, statbuf.st_size + 1)) < 0)
error (1, errno, "cannot read log message from %s", logfile); error (1, errno, "cannot read log message from %s", logfile);
}
(void) close (logfd); (void) close (logfd);
message[n] = '\0'; message[n] = '\0';
} }
@ -226,7 +214,8 @@ commit (argc, argv)
locklist = getlist (); locklist = getlist ();
err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc, err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
(Dtype (*) ()) NULL, (int (*) ()) NULL, argc, (Dtype (*) ()) NULL, (int (*) ()) NULL, argc,
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0); argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0,
0);
sortlist (locklist, fsortcmp); sortlist (locklist, fsortcmp);
if (Writer_Lock (locklist) != 0) if (Writer_Lock (locklist) != 0)
error (1, 0, "lock failed - giving up"); error (1, 0, "lock failed - giving up");
@ -241,7 +230,8 @@ commit (argc, argv)
*/ */
err = start_recursion (check_fileproc, check_filesdoneproc, err = start_recursion (check_fileproc, check_filesdoneproc,
check_direntproc, (int (*) ()) NULL, argc, check_direntproc, (int (*) ()) NULL, argc,
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1); argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1,
0);
if (err) if (err)
{ {
Lock_Cleanup (); Lock_Cleanup ();
@ -255,7 +245,7 @@ commit (argc, argv)
err = start_recursion (commit_fileproc, commit_filesdoneproc, err = start_recursion (commit_fileproc, commit_filesdoneproc,
commit_direntproc, commit_dirleaveproc, commit_direntproc, commit_dirleaveproc,
argc, argv, local, W_LOCAL, aflag, 0, argc, argv, local, W_LOCAL, aflag, 0,
(char *) NULL, 1); (char *) NULL, 1, 0);
/* /*
* Unlock all the dirs and clean up * Unlock all the dirs and clean up
@ -291,6 +281,7 @@ lock_filesdoneproc (err, repository, update_dir)
p = getnode (); p = getnode ();
p->type = LOCK; p->type = LOCK;
p->key = xstrdup (repository); p->key = xstrdup (repository);
/* FIXME-KRP: this error condition should not simply be passed by. */
if (p->key == NULL || addnode (locklist, p) != 0) if (p->key == NULL || addnode (locklist, p) != 0)
freenode (p); freenode (p);
return (err); return (err);
@ -330,15 +321,23 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
status = Classify_File (file, (char *) NULL, (char *) NULL, status = Classify_File (file, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, repository, (char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers); entries, srcfiles, &vers, update_dir, 0);
if (status == T_UPTODATE) if (status == T_UPTODATE || status == T_MODIFIED ||
status == T_ADDED)
{ {
Ctype xstatus;
freevers_ts (&vers); freevers_ts (&vers);
status = Classify_File (file, tag, (char *) NULL, xstatus = Classify_File (file, tag, (char *) NULL,
(char *) NULL, 1, aflag, repository, (char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers); entries, srcfiles, &vers, update_dir,
if (status == T_REMOVE_ENTRY) 0);
if (xstatus == T_REMOVE_ENTRY)
status = T_MODIFIED; status = T_MODIFIED;
else if (status == T_MODIFIED && xstatus == T_CONFLICT)
status = T_MODIFIED;
else
status = xstatus;
} }
} }
else else
@ -352,21 +351,22 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
xtag = xstrdup (tag); xtag = xstrdup (tag);
if ((numdots (xtag) & 1) != 0) if ((numdots (xtag) & 1) != 0)
{ {
cp = rindex (xtag, '.'); cp = strrchr (xtag, '.');
*cp = '\0'; *cp = '\0';
} }
status = Classify_File (file, xtag, (char *) NULL, status = Classify_File (file, xtag, (char *) NULL,
(char *) NULL, 1, aflag, repository, (char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers); entries, srcfiles, &vers, update_dir, 0);
if ((status == T_REMOVE_ENTRY || status == T_CONFLICT) if ((status == T_REMOVE_ENTRY || status == T_CONFLICT)
&& (cp = rindex (xtag, '.')) != NULL) && (cp = strrchr (xtag, '.')) != NULL)
{ {
/* pluck one more dot off the revision */ /* pluck one more dot off the revision */
*cp = '\0'; *cp = '\0';
freevers_ts (&vers); freevers_ts (&vers);
status = Classify_File (file, xtag, (char *) NULL, status = Classify_File (file, xtag, (char *) NULL,
(char *) NULL, 1, aflag, repository, (char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers); entries, srcfiles, &vers, update_dir,
0);
if (status == T_UPTODATE || status == T_REMOVE_ENTRY) if (status == T_UPTODATE || status == T_REMOVE_ENTRY)
status = T_MODIFIED; status = T_MODIFIED;
} }
@ -378,17 +378,30 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
} }
else else
status = Classify_File (file, tag, (char *) NULL, (char *) NULL, status = Classify_File (file, tag, (char *) NULL, (char *) NULL,
1, 0, repository, entries, srcfiles, &vers); 1, 0, repository, entries, srcfiles, &vers,
update_dir, 0);
noexec = save_noexec; noexec = save_noexec;
quiet = save_quiet; quiet = save_quiet;
really_quiet = save_really_quiet; really_quiet = save_really_quiet;
/*
* If the force-commit option is enabled, and the file in question
* appears to be up-to-date, just make it look modified so that
* it will be committed.
*/
if (force_ci && status == T_UPTODATE)
status = T_MODIFIED;
switch (status) switch (status)
{ {
case T_CHECKOUT: case T_CHECKOUT:
case T_NEEDS_MERGE: case T_NEEDS_MERGE:
case T_CONFLICT: case T_CONFLICT:
case T_REMOVE_ENTRY: if (update_dir[0] == '\0')
error (0, 0, "Up-to-date check failed for `%s'", file);
else
error (0, 0, "Up-to-date check failed for `%s/%s'",
update_dir, file);
error (0, 0, "Up-to-date check failed for `%s'", file); error (0, 0, "Up-to-date check failed for `%s'", file);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
@ -403,32 +416,115 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
* - if status is T_REMOVED, can't have a numeric tag * - if status is T_REMOVED, can't have a numeric tag
* - if status is T_ADDED, rcs file must not exist * - if status is T_ADDED, rcs file must not exist
* - if status is T_ADDED, can't have a non-trunk numeric rev * - if status is T_ADDED, can't have a non-trunk numeric rev
* - if status is T_MODIFIED and a Conflict marker exists, don't
* allow the commit if timestamp is identical or if we find
* an RCS_MERGE_PAT in the file.
*/ */
if (!tag || !isdigit (*tag)) if (!tag || !isdigit (*tag))
{ {
if (vers->date) if (vers->date)
{ {
error (0, 0, if (update_dir[0] == '\0')
"cannot commit with sticky date for file `%s'", error (0, 0,
file); "cannot commit with sticky date for file `%s'",
file);
else
error
(0, 0,
"cannot commit with sticky date for file `%s/%s'",
update_dir, file);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
if (status == T_MODIFIED && vers->tag && if (status == T_MODIFIED && vers->tag &&
!RCS_isbranch (file, vers->tag, srcfiles)) !RCS_isbranch (file, vers->tag, srcfiles))
{ {
error (0, 0, if (update_dir[0] == '\0')
"sticky tag `%s' for file `%s' is not a branch", error (0, 0,
vers->tag, file); "sticky tag `%s' for file `%s' is not a branch",
vers->tag, file);
else
error
(0, 0,
"sticky tag `%s' for file `%s/%s' is not a branch",
vers->tag, update_dir, file);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
} }
if (status == T_MODIFIED && !force_ci && vers->ts_conflict)
{
char *filestamp;
int retcode;
/*
* We found a "conflict" marker.
*
* If the timestamp on the file is the same as the
* timestamp stored in the Entries file, we block the commit.
*/
filestamp = time_stamp (file);
retcode = strcmp (vers->ts_conflict, filestamp);
free (filestamp);
if (retcode == 0)
{
if (update_dir[0] == '\0')
error (0, 0,
"file `%s' had a conflict and has not been modified",
file);
else
error (0, 0,
"file `%s/%s' had a conflict and has not been modified",
update_dir, file);
freevers_ts (&vers);
return (1);
}
/*
* If the timestamps differ, look for Conflict indicators
* in the file to see if we should block the commit anyway
*/
run_setup ("%s -s", GREP);
run_arg (RCS_MERGE_PAT);
run_arg (file);
retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
if (retcode == -1)
{
if (update_dir[0] == '\0')
error (1, errno,
"fork failed while examining conflict in `%s'",
file);
else
error (1, errno,
"fork failed while examining conflict in `%s/%s'",
update_dir, file);
}
else if (retcode == 0)
{
if (update_dir[0] == '\0')
error (0, 0,
"file `%s' still contains conflict indicators",
file);
else
error (0, 0,
"file `%s/%s' still contains conflict indicators",
update_dir, file);
freevers_ts (&vers);
return (1);
}
}
if (status == T_REMOVED && vers->tag && isdigit (*vers->tag)) if (status == T_REMOVED && vers->tag && isdigit (*vers->tag))
{ {
error (0, 0, if (update_dir[0] == '\0')
error (0, 0,
"cannot remove file `%s' which has a numeric sticky tag of `%s'", "cannot remove file `%s' which has a numeric sticky tag of `%s'",
file, vers->tag); file, vers->tag);
else
error (0, 0,
"cannot remove file `%s/%s' which has a numeric sticky tag of `%s'",
update_dir, file, vers->tag);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
@ -439,18 +535,28 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
locate_rcs (file, repository, rcs); locate_rcs (file, repository, rcs);
if (isreadable (rcs)) if (isreadable (rcs))
{ {
error (0, 0, if (update_dir[0] == '\0')
error (0, 0,
"cannot add file `%s' when RCS file `%s' already exists", "cannot add file `%s' when RCS file `%s' already exists",
file, rcs); file, rcs);
else
error (0, 0,
"cannot add file `%s/%s' when RCS file `%s' already exists",
update_dir, file, rcs);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
if (vers->tag && isdigit (*vers->tag) && if (vers->tag && isdigit (*vers->tag) &&
numdots (vers->tag) > 1) numdots (vers->tag) > 1)
{ {
error (0, 0, if (update_dir[0] == '\0')
error (0, 0,
"cannot add file `%s' with revision `%s'; must be on trunk", "cannot add file `%s' with revision `%s'; must be on trunk",
file, vers->tag); file, vers->tag);
else
error (0, 0,
"cannot add file `%s/%s' with revision `%s'; must be on trunk",
update_dir, file, vers->tag);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
@ -480,6 +586,7 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
ml->ulist = ulist; ml->ulist = ulist;
ml->cilist = cilist; ml->cilist = cilist;
p->data = (char *) ml; p->data = (char *) ml;
p->delproc = masterlist_delproc;
(void) addnode (mulist, p); (void) addnode (mulist, p);
} }
@ -505,17 +612,21 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
else else
ci->rev = (char *) NULL; ci->rev = (char *) NULL;
ci->tag = xstrdup (vers->tag); ci->tag = xstrdup (vers->tag);
ci->options = xstrdup(vers->options);
p->data = (char *) ci; p->data = (char *) ci;
(void) addnode (cilist, p); (void) addnode (cilist, p);
break; break;
case T_UNKNOWN: case T_UNKNOWN:
error (0, 0, "nothing known about `%s'", file); if (update_dir[0] == '\0')
error (0, 0, "nothing known about `%s'", file);
else
error (0, 0, "nothing known about `%s/%s'", update_dir, file);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
case T_UPTODATE: case T_UPTODATE:
break; break;
default: default:
error (0, 0, "Unknown status 0x%x for `%s'", status, file); error (0, 0, "CVS internal error: unknown status %d", status);
break; break;
} }
@ -543,11 +654,15 @@ check_direntproc (dir, repos, update_dir)
* Walklist proc to run pre-commit checks * Walklist proc to run pre-commit checks
*/ */
static int static int
precommit_list_proc (p) precommit_list_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (p->data == (char *) T_ADDED || p->data == (char *) T_MODIFIED) if (p->data == (char *) T_ADDED || p->data == (char *) T_MODIFIED ||
p->data == (char *) T_REMOVED)
{
run_arg (p->key); run_arg (p->key);
}
return (0); return (0);
} }
@ -561,14 +676,28 @@ precommit_proc (repository, filter)
char *filter; char *filter;
{ {
/* see if the filter is there, only if it's a full path */ /* see if the filter is there, only if it's a full path */
if (filter[0] == '/' && !isfile (filter)) if (filter[0] == '/')
{ {
error (0, errno, "cannot find pre-commit filter `%s'", filter); char *s, *cp;
return (1); /* so it fails! */
s = xstrdup (filter);
for (cp = s; *cp; cp++)
if (isspace (*cp))
{
*cp = '\0';
break;
}
if (!isfile (s))
{
error (0, errno, "cannot find pre-commit filter `%s'", s);
free (s);
return (1); /* so it fails! */
}
free (s);
} }
run_setup ("%s %s", filter, repository); run_setup ("%s %s", filter, repository);
(void) walklist (ulist, precommit_list_proc); (void) walklist (ulist, precommit_list_proc, NULL);
return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY)); return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
} }
@ -647,10 +776,10 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
* need to get the commit message ourselves * need to get the commit message ourselves
*/ */
if (use_editor && !got_message) if (use_editor && !got_message)
{ {
got_message = 1; got_message = 1;
do_editor (update_dir, message, repository, ulist); do_editor (update_dir, &message, repository, ulist);
} }
p = findnode (cilist, file); p = findnode (cilist, file);
if (p == NULL) if (p == NULL)
@ -662,15 +791,17 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
if (lockrcsfile (file, repository, ci->rev) != 0) if (lockrcsfile (file, repository, ci->rev) != 0)
{ {
unlockrcs (file, repository); unlockrcs (file, repository);
return (1); err = 1;
goto out;
} }
} }
else if (ci->status == T_ADDED) else if (ci->status == T_ADDED)
{ {
if (checkaddfile (file, repository, ci->tag) != 0) if (checkaddfile (file, repository, ci->tag, srcfiles) != 0)
{ {
fixaddfile (file, repository); fixaddfile (file, repository);
return (1); err = 1;
goto out;
} }
} }
@ -685,7 +816,7 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
/* find the max major rev number in this directory */ /* find the max major rev number in this directory */
maxrev = 0; maxrev = 0;
(void) walklist (entries, findmaxrev); (void) walklist (entries, findmaxrev, NULL);
if (maxrev == 0) if (maxrev == 0)
maxrev = 1; maxrev = 1;
xrev = xmalloc (20); xrev = xmalloc (20);
@ -693,27 +824,34 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
} }
/* XXX - an added file with symbolic -r should add tag as well */ /* XXX - an added file with symbolic -r should add tag as well */
err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag, err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag, ci->options,
repository, entries); repository, entries);
if (xrev) if (xrev)
free (xrev); free (xrev);
return (err);
} }
else if (ci->status == T_MODIFIED)
if (ci->status == T_MODIFIED)
{ {
locate_rcs (file, repository, rcs); locate_rcs (file, repository, rcs);
err = Checkin ('M', file, repository, rcs, ci->rev, ci->tag, err = Checkin ('M', file, repository, rcs, ci->rev, ci->tag,
message, entries); ci->options, message, entries);
if (err != 0) if (err != 0)
{ {
unlockrcs (file, repository); unlockrcs (file, repository);
fixbranch (file, repository, sbranch); fixbranch (file, repository, sbranch);
} }
} }
else if (ci->status == T_REMOVED)
err = remove_file (file, repository, ci->tag, message,
entries, srcfiles);
if (ci->status == T_REMOVED) out:
err = remove_file (file, repository, ci->tag, entries); if (err != 0)
{
/* on failure, remove the file from ulist */
p = findnode (ulist, file);
if (p)
delnode (p);
}
return (err); return (err);
} }
@ -728,19 +866,16 @@ commit_filesdoneproc (err, repository, update_dir)
char *repository; char *repository;
char *update_dir; char *update_dir;
{ {
List *ulist, *cilist;
char *xtag = (char *) NULL; char *xtag = (char *) NULL;
Node *p; Node *p;
List *ulist;
p = findnode (mulist, update_dir); p = findnode (mulist, update_dir);
if (p != NULL) if (p == NULL)
{
ulist = ((struct master_lists *) p->data)->ulist;
cilist = ((struct master_lists *) p->data)->cilist;
}
else
return (err); return (err);
ulist = ((struct master_lists *) p->data)->ulist;
got_message = 0; got_message = 0;
/* see if we need to specify a per-directory or -r option tag */ /* see if we need to specify a per-directory or -r option tag */
@ -748,8 +883,6 @@ commit_filesdoneproc (err, repository, update_dir)
ParseTag (&xtag, (char **) NULL); ParseTag (&xtag, (char **) NULL);
Update_Logfile (repository, message, tag ? tag : xtag, (FILE *) 0, ulist); Update_Logfile (repository, message, tag ? tag : xtag, (FILE *) 0, ulist);
dellist (&ulist);
dellist (&cilist);
if (xtag) if (xtag)
free (xtag); free (xtag);
@ -765,7 +898,7 @@ commit_filesdoneproc (err, repository, update_dir)
{ {
if (fgets (line, sizeof (line), fp) != NULL) if (fgets (line, sizeof (line), fp) != NULL)
{ {
if ((cp = rindex (line, '\n')) != NULL) if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0'; *cp = '\0';
repository = Name_Repository ((char *) NULL, update_dir); repository = Name_Repository ((char *) NULL, update_dir);
run_setup ("%s %s", line, repository); run_setup ("%s %s", line, repository);
@ -817,7 +950,7 @@ commit_direntproc (dir, repos, update_dir)
{ {
got_message = 1; got_message = 1;
real_repos = Name_Repository (dir, update_dir); real_repos = Name_Repository (dir, update_dir);
do_editor (update_dir, message, real_repos, ulist); do_editor (update_dir, &message, real_repos, ulist);
free (real_repos); free (real_repos);
} }
return (R_PROCESS); return (R_PROCESS);
@ -844,15 +977,16 @@ commit_dirleaveproc (dir, err, update_dir)
* find the maximum major rev number in an entries file * find the maximum major rev number in an entries file
*/ */
static int static int
findmaxrev (p) findmaxrev (p, closure)
Node *p; Node *p;
void *closure;
{ {
char *cp; char *cp;
int thisrev; int thisrev;
Entnode *entdata; Entnode *entdata;
entdata = (Entnode *) p->data; entdata = (Entnode *) p->data;
cp = index (entdata->version, '.'); cp = strchr (entdata->version, '.');
if (cp != NULL) if (cp != NULL)
*cp = '\0'; *cp = '\0';
thisrev = atoi (entdata->version); thisrev = atoi (entdata->version);
@ -870,18 +1004,23 @@ findmaxrev (p)
* link to keep it relative after we move it into the attic. * link to keep it relative after we move it into the attic.
*/ */
static int static int
remove_file (file, repository, tag, entries) remove_file (file, repository, tag, message, entries, srcfiles)
char *file; char *file;
char *repository; char *repository;
char *tag; char *tag;
char *message;
List *entries; List *entries;
List *srcfiles;
{ {
int omask; mode_t omask;
int retcode; int retcode;
char rcs[PATH_MAX]; char rcs[PATH_MAX];
char tmp[PATH_MAX]; char *tmp;
retcode = 0;
locate_rcs (file, repository, rcs); locate_rcs (file, repository, rcs);
if (tag) if (tag)
{ {
/* a symbolic tag is specified; just remove the tag from the file */ /* a symbolic tag is specified; just remove the tag from the file */
@ -894,20 +1033,28 @@ remove_file (file, repository, tag, entries)
"failed to remove tag `%s' from `%s'", tag, rcs); "failed to remove tag `%s' from `%s'", tag, rcs);
return (1); return (1);
} }
Scratch_Entry (entries, file);
return (0); return (0);
} }
else else
{ {
/* no symbolic tag specified; really move it into the Attic */ /* this was the head; really move it into the Attic */
tmp = xmalloc(strlen(repository) +
sizeof('/') +
sizeof(CVSATTIC) +
sizeof('/') +
strlen(file) +
sizeof(RCSEXT) + 1);
(void) sprintf (tmp, "%s/%s", repository, CVSATTIC); (void) sprintf (tmp, "%s/%s", repository, CVSATTIC);
omask = umask (2); omask = umask (2);
(void) mkdir (tmp, 0777); (void) mkdir (tmp, 0777);
(void) umask (omask); (void) umask (omask);
(void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT); (void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
if ((strcmp (rcs, tmp) == 0 || rename (rcs, tmp) != -1) || if ((strcmp (rcs, tmp) == 0 || rename (rcs, tmp) != -1) ||
(!isreadable (rcs) && isreadable (tmp))) (!isreadable (rcs) && isreadable (tmp)))
{ {
Scratch_Entry (entries, file); Scratch_Entry (entries, file);
return (0); return (0);
} }
@ -919,10 +1066,11 @@ remove_file (file, repository, tag, entries)
* Do the actual checkin for added files * Do the actual checkin for added files
*/ */
static int static int
finaladd (file, rev, tag, repository, entries) finaladd (file, rev, tag, options, repository, entries)
char *file; char *file;
char *rev; char *rev;
char *tag; char *tag;
char *options;
char *repository; char *repository;
List *entries; List *entries;
{ {
@ -931,7 +1079,7 @@ finaladd (file, rev, tag, repository, entries)
char rcs[PATH_MAX]; char rcs[PATH_MAX];
locate_rcs (file, repository, rcs); locate_rcs (file, repository, rcs);
ret = Checkin ('A', file, repository, rcs, rev, tag, ret = Checkin ('A', file, repository, rcs, rev, tag, options,
message, entries); message, entries);
if (ret == 0) if (ret == 0)
{ {
@ -1015,24 +1163,27 @@ fixbranch (file, repository, branch)
* with a tag, put the file in the Attic and point the symbolic tag * with a tag, put the file in the Attic and point the symbolic tag
* at the committed revision. * at the committed revision.
*/ */
static int static int
checkaddfile (file, repository, tag) checkaddfile (file, repository, tag, srcfiles)
char *file; char *file;
char *repository; char *repository;
char *tag; char *tag;
List *srcfiles;
{ {
FILE *fp; FILE *fp;
char *cp; char *cp;
char rcs[PATH_MAX]; char rcs[PATH_MAX];
char fname[PATH_MAX]; char fname[PATH_MAX];
int omask; mode_t omask;
int retcode = 0; int retcode = 0;
if (tag) if (tag)
{ {
(void) sprintf(rcs, "%s/%s", repository, CVSATTIC); (void) sprintf(rcs, "%s/%s", repository, CVSATTIC);
omask = umask (2); omask = umask (2);
(void) mkdir (rcs, 0777); if (mkdir (rcs, 0777) != 0 && errno != EEXIST)
error (1, errno, "cannot make directory `%s'", rcs);;
(void) umask (omask); (void) umask (omask);
(void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT); (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
} }
@ -1045,7 +1196,7 @@ checkaddfile (file, repository, tag)
fp = open_file (fname, "r"); fp = open_file (fname, "r");
while (fgets (fname, sizeof (fname), fp) != NULL) while (fgets (fname, sizeof (fname), fp) != NULL)
{ {
if ((cp = rindex (fname, '\n')) != NULL) if ((cp = strrchr (fname, '\n')) != NULL)
*cp = '\0'; *cp = '\0';
if (*fname) if (*fname)
run_arg (fname); run_arg (fname);
@ -1058,6 +1209,7 @@ checkaddfile (file, repository, tag)
"could not create %s", rcs); "could not create %s", rcs);
return (1); return (1);
} }
fix_rcs_modes (rcs, file); fix_rcs_modes (rcs, file);
return (0); return (0);
} }
@ -1207,9 +1359,26 @@ ci_delproc (p)
free (ci->rev); free (ci->rev);
if (ci->tag) if (ci->tag)
free (ci->tag); free (ci->tag);
if (ci->options)
free (ci->options);
free (ci); free (ci);
} }
/*
* Free the commit_info structure in p.
*/
static void
masterlist_delproc (p)
Node *p;
{
struct master_lists *ml;
ml = (struct master_lists *) p->data;
dellist (&ml->ulist);
dellist (&ml->cilist);
free (ml);
}
/* /*
* Find an RCS file in the repository. * Find an RCS file in the repository.
*/ */

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Create Administration. * Create Administration.
* *
@ -14,7 +14,8 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)create_adm.c 1.24 92/03/31"; static char rcsid[] = "$CVSid: @(#)create_adm.c 1.28 94/09/23 $";
USE(rcsid)
#endif #endif
void void
@ -31,9 +32,6 @@ Create_Admin (dir, repository, tag, date)
if (noexec) if (noexec)
return; return;
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
if (dir != NULL) if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM); (void) sprintf (tmp, "%s/%s", dir, CVSADM);
else else
@ -58,6 +56,11 @@ Create_Admin (dir, repository, tag, date)
(void) strcpy (tmp, CVSADM); (void) strcpy (tmp, CVSADM);
make_directory (tmp); make_directory (tmp);
#ifdef CVSADM_ROOT
/* record the current cvs root for later use */
Create_Root (dir, CVSroot);
#endif /* CVSADM_ROOT */
if (dir != NULL) if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM_REP); (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
else else

View File

@ -2,7 +2,7 @@
.ds Rv \\$3 .ds Rv \\$3
.ds Dt \\$4 .ds Dt \\$4
.. ..
.Id cvs.1,v 1.12 1992/04/10 03:05:16 berliner Exp .Id $Id: cvs.1,v 1.16 1994/10/03 21:26:10 berliner Exp $
.TH CVS 1 "\*(Dt" .TH CVS 1 "\*(Dt"
.\" Full space in nroff; half space in troff .\" Full space in nroff; half space in troff
.de SP .de SP
@ -181,8 +181,10 @@ Use
.I editor .I editor
to enter revision log information. to enter revision log information.
Overrides the setting of the Overrides the setting of the
.SM CVSEDITOR
and the
.SM EDITOR .SM EDITOR
environment variable. environment variables.
.TP .TP
.B \-l .B \-l
Do not log the Do not log the
@ -206,7 +208,7 @@ activity. Particularly useful with
to explore the potential impact of an unfamiliar command. to explore the potential impact of an unfamiliar command.
.TP .TP
.B \-r .B \-r
Makes new working files files read-only. Makes new working files read-only.
Same effect as if the Same effect as if the
.SM CVSREAD .SM CVSREAD
environment variable is set. environment variable is set.
@ -388,7 +390,7 @@ same date (unless you explicitly override it; see the description of
the \fBupdate\fP command). the \fBupdate\fP command).
.B \-D .B \-D
is available with the is available with the
.BR checkout ", " diff, ", " history ", " export ", " .BR checkout ", " diff ", " history ", " export ", "
.BR rdiff ", " rtag ", and " .BR rdiff ", " rtag ", and "
.B update .B update
commands. commands.
@ -437,7 +439,7 @@ options described in
.BR rcs ( 1 ) .BR rcs ( 1 )
are available. The \fB\-k\fP option is available with the are available. The \fB\-k\fP option is available with the
.BR add ", " checkout ", " diff ", " .BR add ", " checkout ", " diff ", "
.RB rdiff ", and " update .BR rdiff ", and " update
commands. Your \fIkflag\fP specification is ``sticky'' when you use commands. Your \fIkflag\fP specification is ``sticky'' when you use
it to create a private copy of a source file; that is, when you use it to create a private copy of a source file; that is, when you use
this option with the \fBcheckout\fP or \fBupdate\fP commands, this option with the \fBcheckout\fP or \fBupdate\fP commands,
@ -911,6 +913,13 @@ changed; you can use the
option to limit option to limit
.B commit .B commit
to the current directory only. to the current directory only.
Sometimes you may want to force a file to be committed even though it
is unchanged; this is achieved with the
.B \-f
flag, which also has the effect of disabling recursion (you can turn
it back on with
.B \-R
of course).
.SP .SP
.B commit .B commit
verifies that the selected files are up to date with the current revisions verifies that the selected files are up to date with the current revisions
@ -931,7 +940,7 @@ source repository file.
You can instead specify the log message on the command line with the You can instead specify the log message on the command line with the
.B \-m .B \-m
option, thus suppressing the editor invocation, or use the option, thus suppressing the editor invocation, or use the
.B \-f .B \-F
option to specify that the argument \fIfile\fP contains the log message. option to specify that the argument \fIfile\fP contains the log message.
.SP .SP
The The
@ -960,7 +969,8 @@ number of dots) with the
.B \-r .B \-r
option. option.
To create a branch revision, one typically use the To create a branch revision, one typically use the
.B \-b option of the .B \-b
option of the
.BR rtag " or " tag .BR rtag " or " tag
commands. commands.
Then, either Then, either
@ -1144,7 +1154,7 @@ Report on checked-out modules.
.B \ \ \ \ \ \ \-T .B \ \ \ \ \ \ \-T
Report on all tags. Report on all tags.
.TP 1i .TP 1i
\fB\ \ \ \ \ \ \-x\fP \fItyp\fP \fB\ \ \ \ \ \ \-x\fP \fItype\fP
Extract a particular set of record types \fIX\fP from the \fBcvs\fP Extract a particular set of record types \fIX\fP from the \fBcvs\fP
history. The types are indicated by single letters, which you may history. The types are indicated by single letters, which you may
specify in combination. specify in combination.
@ -1162,6 +1172,18 @@ added; and `R', when a file is removed.
.B \ \ \ \ \ \ \-e .B \ \ \ \ \ \ \-e
Everything (all record types); equivalent to specifying Everything (all record types); equivalent to specifying
.` "\-xMACFROGWUT". .` "\-xMACFROGWUT".
.TP 1i
\fB\ \ \ \ \ \ \-z\fP \fIzone\fP
Use time zone
.I zone
when outputting history records.
The zone name
.B LT
stands for local time;
numeric offsets stand for hours and minutes ahead of UTC.
For example,
.B +0530
stands for 5 hours and 30 minutes ahead of (i.e. east of) UTC.
.PP .PP
.RS .5i .RS .5i
The options shown as \fB\-\fP\fIflags\fP constrain the report without The options shown as \fB\-\fP\fIflags\fP constrain the report without
@ -1260,8 +1282,8 @@ CVS* cvslog.*
tags TAGS tags TAGS
\&.make.state .nse_depinfo \&.make.state .nse_depinfo
*~ #* .#* ,* *~ #* .#* ,*
*.old *.bak *.orig *.rej .del\-* *.old *.bak *.BAK *.orig *.rej .del\-*
*.a *.o *.Z *.elc *.ln core *.a *.o *.so *.Z *.elc *.ln core
.fi .fi
.ft P .ft P
.in -1i .in -1i
@ -1295,7 +1317,12 @@ command options are available: \fB\-Q\fP, \fB\-q\fP, and \fB\-m\fP
\fB\-m\fP, your editor is invoked (as with \fBcommit\fP) to allow you \fB\-m\fP, your editor is invoked (as with \fBcommit\fP) to allow you
to enter one. to enter one.
.SP .SP
There are two additional special options. There are three additional special options.
.SP
Use
.` "\-d"
to specify that each file's time of last modification should be used
for the checkin date and time.
.SP .SP
Use Use
.` "\-b \fIbranch\fP" .` "\-b \fIbranch\fP"
@ -1481,7 +1508,7 @@ into the
.` "Attic" .` "Attic"
directory (also within the source repository). directory (also within the source repository).
.SP .SP
This command is recursive by default, scheduing all physically removed This command is recursive by default, scheduling all physically removed
files that it finds for removal by the next files that it finds for removal by the next
.BR commit . .BR commit .
Use the Use the
@ -1546,7 +1573,7 @@ option to have
.B rtag .B rtag
look in the look in the
.` "Attic" .` "Attic"
for removed files that contin the specified tag. for removed files that contain the specified tag.
The tag is removed from these files, which makes it convenient to re-use a The tag is removed from these files, which makes it convenient to re-use a
symbolic tag as development continues (and files get removed from the symbolic tag as development continues (and files get removed from the
up-coming distribution). up-coming distribution).
@ -1796,8 +1823,8 @@ CVS* cvslog.*
tags TAGS tags TAGS
\&.make.state .nse_depinfo \&.make.state .nse_depinfo
*~ #* .#* ,* *~ #* .#* ,*
*.old *.bak *.orig *.rej .del\-* *.old *.bak *.BAK *.orig *.rej .del\-*
*.a *.o *.Z *.elc *.ln core *.a *.o *.so *.Z *.elc *.ln core
.fi .fi
.ft P .ft P
.in -1i .in -1i
@ -1881,7 +1908,7 @@ Records programs for piping
log entries. log entries.
.TP .TP
CVSROOT/rcsinfo,v CVSROOT/rcsinfo,v
Records pathnames to templates used dueing a Records pathnames to templates used during a
.` "cvs commit" .` "cvs commit"
operation. operation.
.TP .TP
@ -1946,10 +1973,15 @@ and
If not set, a compiled-in value is used; see the display from If not set, a compiled-in value is used; see the display from
.` "cvs \-v". .` "cvs \-v".
.TP .TP
.SM EDITOR .SM CVSEDITOR
Specifies the program to use for recording log messages during Specifies the program to use for recording log messages during
.BR commit . .BR commit .
If not set, the default is If not set, the
.SM EDITOR
environment variable is used instead.
If
.SM EDITOR
is not set either, the default is
.BR /usr/ucb/vi . .BR /usr/ucb/vi .
.SH "AUTHORS" .SH "AUTHORS"
.TP .TP

View File

@ -243,7 +243,7 @@ removed by this \fBcommit\fP invocation.
.SP .SP
For `\|commitinfo\|', the rest of the line is a command-line template to For `\|commitinfo\|', the rest of the line is a command-line template to
execute. execute.
The template can include can include not only a program name, but whatever The template can include not only a program name, but whatever
list of arguments you wish. list of arguments you wish.
The full path to the current source repository is appended to the template, The full path to the current source repository is appended to the template,
followed by the file names of any files involved in the commit (added, followed by the file names of any files involved in the commit (added,
@ -254,7 +254,7 @@ should be loaded into the log message template.
.SP .SP
For `\|editinfo\|', the rest of the line is a command-line template to For `\|editinfo\|', the rest of the line is a command-line template to
execute. execute.
The template can include can include not only a program name, but whatever The template can include not only a program name, but whatever
list of arguments you wish. list of arguments you wish.
The full path to the current log message template file is appended to the The full path to the current log message template file is appended to the
template. template.

View File

@ -1,35 +1,30 @@
/* @(#)cvs.h 1.72 92/03/31 */ /* $CVSid: @(#)cvs.h 1.86 94/10/22 $ */
#include "system.h" /*
#include <stdio.h> * basic information used in all source files
#include <ctype.h> *
#include <pwd.h> */
#include <signal.h>
#include "hash.h"
#include "rcs.h"
#include "regex.h"
#include "fnmatch.h"
#include "getopt.h"
#include "wait.h"
#include "config.h"
#ifdef MY_NDBM
#include "myndbm.h"
#else
#include <ndbm.h>
#endif /* !MY_NDBM */
/* XXX - for now this is static */
#undef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN+2
#else
#define PATH_MAX 1024+2
#endif
/* just in case this implementation does not define this */ #include "config.h" /* this is stuff found via autoconf */
#ifndef L_tmpnam #include "options.h" /* these are some larger questions which
#define L_tmpnam 50 can't easily be automatically checked
#endif for */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#if HAVE_ALLOCA_H
#include <alloca.h>
#else /* not HAVE_ALLOCA_H */
#ifdef _AIX
#pragma alloca
#else /* not _AIX */
char *alloca ();
#endif /* not _AIX */
#endif /* not HAVE_ALLOCA_H */
#endif /* not __GNUC__ */
#if __STDC__ #if __STDC__
#define CONST const #define CONST const
@ -39,12 +34,86 @@
#define PTR char * #define PTR char *
#endif #endif
/* Add prototype support. */
#ifndef PROTO
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
#define PROTO(ARGS) ARGS
#else
#define PROTO(ARGS) ()
#endif
#endif
#if __GNUC__ == 2
#define USE(var) static char sizeof##var = sizeof(sizeof##var) + sizeof(var);
#else
#define USE(var)
#endif
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <fnmatch.h> /* This is supposed to be available on Posix systems */
#include <ctype.h>
#include <pwd.h>
#include <signal.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#else
#ifndef errno
extern int errno;
#endif /* !errno */
#endif /* HAVE_ERRNO_H */
#include "system.h"
#include "hash.h"
#ifdef MY_NDBM
#include "myndbm.h"
#else
#include <ndbm.h>
#endif /* MY_NDBM */
#include "regex.h"
#include "getopt.h"
#include "wait.h"
#include "rcs.h"
/* XXX - for now this is static */
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN+2
#else
#define PATH_MAX 1024+2
#endif
#endif /* PATH_MAX */
/* just in case this implementation does not define this */
#ifndef L_tmpnam
#define L_tmpnam 50
#endif
/* /*
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Definitions for the CVS Administrative directory and the files it contains. * Definitions for the CVS Administrative directory and the files it contains.
* Here as #define's to make changing the names a simple task. * Here as #define's to make changing the names a simple task.
@ -54,6 +123,7 @@
#define CVSADM_ENTBAK "CVS/Entries.Backup" #define CVSADM_ENTBAK "CVS/Entries.Backup"
#define CVSADM_ENTSTAT "CVS/Entries.Static" #define CVSADM_ENTSTAT "CVS/Entries.Static"
#define CVSADM_REP "CVS/Repository" #define CVSADM_REP "CVS/Repository"
#define CVSADM_ROOT "CVS/Root"
#define CVSADM_CIPROG "CVS/Checkin.prog" #define CVSADM_CIPROG "CVS/Checkin.prog"
#define CVSADM_UPROG "CVS/Update.prog" #define CVSADM_UPROG "CVS/Update.prog"
#define CVSADM_TAG "CVS/Tag" #define CVSADM_TAG "CVS/Tag"
@ -80,6 +150,7 @@
#define CVSROOTADM_EDITINFO "editinfo" #define CVSROOTADM_EDITINFO "editinfo"
#define CVSROOTADM_HISTORY "history" #define CVSROOTADM_HISTORY "history"
#define CVSROOTADM_IGNORE "cvsignore" #define CVSROOTADM_IGNORE "cvsignore"
#define CVSROOTADM_CHECKOUTLIST "checkoutlist"
#define CVSNULLREPOS "Emptydir" /* an empty directory */ #define CVSNULLREPOS "Emptydir" /* an empty directory */
/* support for the modules file (CVSROOTADM_MODULES) */ /* support for the modules file (CVSROOTADM_MODULES) */
@ -98,6 +169,7 @@
#define CVSTFL "#cvs.tfl" #define CVSTFL "#cvs.tfl"
#define CVSRFL "#cvs.rfl" #define CVSRFL "#cvs.rfl"
#define CVSWFL "#cvs.wfl" #define CVSWFL "#cvs.wfl"
#define CVSRFLPAT "#cvs.rfl.*" /* wildcard expr to match read locks */
#define CVSEXT_OPT ",p" #define CVSEXT_OPT ",p"
#define CVSEXT_LOG ",t" #define CVSEXT_LOG ",t"
#define CVSPREFIX ",," #define CVSPREFIX ",,"
@ -129,7 +201,8 @@
#define RCSBIN_ENV "RCSBIN" /* RCS binary directory */ #define RCSBIN_ENV "RCSBIN" /* RCS binary directory */
/* #define RCSBIN_DFLT Set by config.h */ /* #define RCSBIN_DFLT Set by config.h */
#define EDITOR_ENV "EDITOR" /* which editor to use */ #define EDITOR1_ENV "CVSEDITOR" /* which editor to use */
#define EDITOR2_ENV "EDITOR" /* which editor to use */
/* #define EDITOR_DFLT Set by config.h */ /* #define EDITOR_DFLT Set by config.h */
#define CVSROOT_ENV "CVSROOT" /* source directory root */ #define CVSROOT_ENV "CVSROOT" /* source directory root */
@ -154,7 +227,6 @@
#define MAXLINELEN 5000 /* max input line from a file */ #define MAXLINELEN 5000 /* max input line from a file */
#define MAXPROGLEN 30000 /* max program length to system() */ #define MAXPROGLEN 30000 /* max program length to system() */
#define MAXLISTLEN 40000 /* For [A-Z]list holders */ #define MAXLISTLEN 40000 /* For [A-Z]list holders */
#define MAXMESGLEN 10000 /* max RCS log message size */
#define MAXDATELEN 50 /* max length for a date */ #define MAXDATELEN 50 /* max length for a date */
/* The type of request that is being done in do_module() */ /* The type of request that is being done in do_module() */
@ -198,12 +270,13 @@ struct vers_ts
* empty = no user file * empty = no user file
* 0 = user file is new * 0 = user file is new
* -vers = user file to be removed */ * -vers = user file to be removed */
char *vn_rcs; /* the verion for the rcs file char *vn_rcs; /* the version for the rcs file
* (tag version?) */ * (tag version?) */
char *ts_user; /* the timestamp for the user file */ char *ts_user; /* the timestamp for the user file */
char *ts_rcs; /* the user timestamp from entries */ char *ts_rcs; /* the user timestamp from entries */
char *options; /* opts from Entries file char *options; /* opts from Entries file
* (keyword expansion) */ * (keyword expansion) */
char *ts_conflict; /* Holds time_stamp of conflict */
char *tag; /* tag stored in the Entries file */ char *tag; /* tag stored in the Entries file */
char *date; /* date stored in the Entries file */ char *date; /* date stored in the Entries file */
Entnode *entdata; /* pointer to entries file node */ Entnode *entdata; /* pointer to entries file node */
@ -249,190 +322,126 @@ typedef enum direnter_type Dtype;
extern char *program_name, *command_name; extern char *program_name, *command_name;
extern char *Rcsbin, *Editor, *CVSroot; extern char *Rcsbin, *Editor, *CVSroot;
#ifdef CVSADM_ROOT
extern char *CVSADM_Root;
extern int cvsadmin_root;
#endif /* CVSADM_ROOT */
extern char *CurDir; extern char *CurDir;
extern int really_quiet, quiet; extern int really_quiet, quiet;
extern int use_editor; extern int use_editor;
extern int cvswrite; extern int cvswrite;
extern int trace; /* Show all commands */ extern int trace; /* Show all commands */
extern int noexec; /* Don't modify disk anywhere */ extern int noexec; /* Don't modify disk anywhere */
extern int logoff; /* Don't write history entry */ extern int logoff; /* Don't write history entry */
/* Externs that are included directly in the CVS sources */ /* Externs that are included directly in the CVS sources */
#if __STDC__ DBM *open_module PROTO((void));
int Reader_Lock (char *xrepository); FILE *Fopen PROTO((char *name, char *mode));
DBM *open_module (void); FILE *open_file PROTO((char *name, char *mode));
FILE *Fopen (char *name, char *mode); List *Find_Dirs PROTO((char *repository, int which));
FILE *open_file (char *name, char *mode); List *ParseEntries PROTO((int aflag));
List *Find_Dirs (char *repository, int which); char *Make_Date PROTO((char *rawdate));
List *ParseEntries (int aflag); char *Name_Repository PROTO((char *dir, char *update_dir));
char *Make_Date (char *rawdate); #ifdef CVSADM_ROOT
char *Name_Repository (char *dir, char *update_dir); char *Name_Root PROTO((char *dir, char *update_dir));
char *Short_Repository (char *repository); void Create_Root PROTO((char *dir, char *rootdir));
char *getcaller (void); int same_directories PROTO((char *dir1, char *dir2));
char *time_stamp (char *file); #endif /* CVSADM_ROOT */
char *xmalloc (int bytes); char *Short_Repository PROTO((char *repository));
char *xrealloc (char *ptr, int bytes); char *gca PROTO((char *rev1, char *rev2));
char *xstrdup (char *str); char *getcaller PROTO((void));
int No_Difference (char *file, Vers_TS * vers, List * entries); char *time_stamp PROTO((char *file));
int Parse_Info (char *infofile, char *repository, int (*callproc) (), int all); char *xmalloc PROTO((size_t bytes));
int Reader_Lock (char *xrepository); char *xrealloc PROTO((char *ptr, size_t bytes));
int SIG_register (int sig, SIGTYPE (*fn) ()); char *xstrdup PROTO((char *str));
int Writer_Lock (List * list); int No_Difference PROTO((char *file, Vers_TS * vers, List * entries,
int gethostname (char *name, int namelen); char *repository, char *update_dir));
int ign_name (char *name); int Parse_Info PROTO((char *infofile, char *repository, int PROTO((*callproc)) PROTO(()), int all));
int isdir (char *file); int Reader_Lock PROTO((char *xrepository));
int isfile (char *file); int SIG_register PROTO((int sig, RETSIGTYPE PROTO((*fn)) PROTO(())));
int islink (char *file); int Writer_Lock PROTO((List * list));
int isreadable (char *file); int ign_name PROTO((char *name));
int iswritable (char *file); int isdir PROTO((char *file));
int link_file (char *from, char *to); int isfile PROTO((char *file));
int numdots (char *s); int islink PROTO((char *file));
int run_exec (char *stin, char *stout, char *sterr, int flags); int isreadable PROTO((char *file));
int unlink_file (char *f); int iswritable PROTO((char *file));
int update (int argc, char *argv[]); int joining PROTO((void));
int xcmp (char *file1, char *file2); int link_file PROTO((char *from, char *to));
int yesno (void); int numdots PROTO((char *s));
time_t get_date (char *date, struct timeb *now); int run_exec PROTO((char *stin, char *stout, char *sterr, int flags));
void Create_Admin (char *dir, char *repository, char *tag, char *date); int unlink_file PROTO((char *f));
void Lock_Cleanup (void); int update PROTO((int argc, char *argv[]));
void ParseTag (char **tagp, char **datep); int xcmp PROTO((char *file1, char *file2));
void Scratch_Entry (List * list, char *fname); int yesno PROTO((void));
void WriteTag (char *dir, char *tag, char *date); time_t get_date PROTO((char *date, struct timeb *now));
void cat_module (int status); void Create_Admin PROTO((char *dir, char *repository, char *tag, char *date));
void check_entries (char *dir); void Lock_Cleanup PROTO((void));
void close_module (DBM * db); void ParseTag PROTO((char **tagp, char **datep));
void copy_file (char *from, char *to); void Scratch_Entry PROTO((List * list, char *fname));
void error (int status, int errnum, char *message,...); void WriteTag PROTO((char *dir, char *tag, char *date));
void fperror (FILE * fp, int status, int errnum, char *message,...); void cat_module PROTO((int status));
void free_names (int *pargc, char *argv[]); void check_entries PROTO((char *dir));
void freevers_ts (Vers_TS ** versp); void close_module PROTO((DBM * db));
void ign_add (char *ign, int hold); void copy_file PROTO((char *from, char *to));
void ign_add_file (char *file, int hold); void error PROTO((int status, int errnum, char *message,...));
void ign_setup (void); void fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
void line2argv (int *pargc, char *argv[], char *line); void free_names PROTO((int *pargc, char *argv[]));
void make_directories (char *name); void freevers_ts PROTO((Vers_TS ** versp));
void make_directory (char *name); void ign_add PROTO((char *ign, int hold));
void rename_file (char *from, char *to); void ign_add_file PROTO((char *file, int hold));
void run_arg (char *s); void ign_setup PROTO((void));
void run_args (char *fmt,...); void ign_dir_add PROTO((char *name));
void run_print (FILE * fp); int ignore_directory PROTO((char *name));
void run_setup (char *fmt,...); void line2argv PROTO((int *pargc, char *argv[], char *line));
void strip_path (char *path); void make_directories PROTO((char *name));
void update_delproc (Node * p); void make_directory PROTO((char *name));
void usage (char **cpp); void rename_file PROTO((char *from, char *to));
void xchmod (char *fname, int writable); void run_arg PROTO((char *s));
int Checkin (int type, char *file, char *repository, char *rcs, char *rev, void run_args PROTO((char *fmt,...));
char *tag, char *message, List * entries); void run_print PROTO((FILE * fp));
Ctype Classify_File (char *file, char *tag, char *date, char *options, void run_setup PROTO((char *fmt,...));
void strip_path PROTO((char *path));
void strip_trailing_slashes PROTO((char *path));
void update_delproc PROTO((Node * p));
void usage PROTO((char **cpp));
void xchmod PROTO((char *fname, int writable));
int Checkin PROTO((int type, char *file, char *repository, char *rcs, char *rev,
char *tag, char *options, char *message, List *entries));
Ctype Classify_File PROTO((char *file, char *tag, char *date, char *options,
int force_tag_match, int aflag, char *repository, int force_tag_match, int aflag, char *repository,
List *entries, List *srcfiles, Vers_TS **versp); List *entries, List *srcfiles, Vers_TS **versp,
List *Find_Names (char *repository, int which, int aflag, char *update_dir, int pipeout));
List ** optentries); List *Find_Names PROTO((char *repository, int which, int aflag,
void Register (List * list, char *fname, char *vn, char *ts, List ** optentries));
char *options, char *tag, char *date); void Register PROTO((List * list, char *fname, char *vn, char *ts,
void Update_Logfile (char *repository, char *xmessage, char *xrevision, char *options, char *tag, char *date, char *ts_conflict));
FILE * xlogfp, List * xchanges); void Update_Logfile PROTO((char *repository, char *xmessage, char *xrevision,
Vers_TS *Version_TS (char *repository, char *options, char *tag, FILE * xlogfp, List * xchanges));
Vers_TS *Version_TS PROTO((char *repository, char *options, char *tag,
char *date, char *user, int force_tag_match, char *date, char *user, int force_tag_match,
int set_time, List * entries, List * xfiles); int set_time, List * entries, List * xfiles));
void do_editor (char *dir, char *message, char *repository, void do_editor PROTO((char *dir, char **messagep,
List * changes); char *repository, List * changes));
int do_module (DBM * db, char *mname, enum mtype m_type, char *msg, int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
int (*callback_proc) (), char *where, int shorten, int PROTO((*callback_proc)) (), char *where, int shorten,
int local_specified, int run_module_prog, char *extra_arg); int local_specified, int run_module_prog, char *extra_arg));
int do_recursion (int (*xfileproc) (), int (*xfilesdoneproc) (), int do_recursion PROTO((int PROTO((*xfileproc)) (), int PROTO((*xfilesdoneproc)) (),
Dtype (*xdirentproc) (), int (*xdirleaveproc) (), Dtype PROTO((*xdirentproc)) (), int PROTO((*xdirleaveproc)) (),
Dtype xflags, int xwhich, int xaflag, int xreadlock, Dtype xflags, int xwhich, int xaflag, int xreadlock,
int xdosrcs); int xdosrcs));
int do_update (int argc, char *argv[], char *xoptions, char *xtag, int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
char *xdate, int xforce, int local, int xbuild, char *xdate, int xforce, int local, int xbuild,
int xaflag, int xprune, int xpipeout, int which, int xaflag, int xprune, int xpipeout, int which,
char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir); char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir));
void history_write (int type, char *update_dir, char *revs, char *name, void history_write PROTO((int type, char *update_dir, char *revs, char *name,
char *repository); char *repository));
int start_recursion (int (*fileproc) (), int (*filesdoneproc) (), int start_recursion PROTO((int PROTO((*fileproc)) (), int PROTO((*filesdoneproc)) (),
Dtype (*direntproc) (), int (*dirleaveproc) (), Dtype PROTO((*direntproc)) (), int PROTO((*dirleaveproc)) (),
int argc, char *argv[], int local, int which, int argc, char *argv[], int local, int which,
int aflag, int readlock, char *update_preload, int aflag, int readlock, char *update_preload,
int dosrcs); int dosrcs, int wd_is_repos));
void SIG_beginCrSect (); void SIG_beginCrSect PROTO((void));
void SIG_endCrSect (); void SIG_endCrSect PROTO((void));
#else /* !__STDC__ */ void read_cvsrc PROTO((int *argc, char ***argv));
DBM *open_module ();
FILE *Fopen ();
FILE *open_file ();
List *Find_Dirs ();
List *Find_Names ();
List *ParseEntries ();
Vers_TS *Version_TS ();
char *Make_Date ();
char *Name_Repository ();
char *Short_Repository ();
char *getcaller ();
char *time_stamp ();
char *xmalloc ();
char *xrealloc ();
char *xstrdup ();
int Checkin ();
Ctype Classify_File ();
int No_Difference ();
int Parse_Info ();
int Reader_Lock ();
int SIG_register ();
int Writer_Lock ();
int do_module ();
int do_recursion ();
int do_update ();
int gethostname ();
int ign_name ();
int isdir ();
int isfile ();
int islink ();
int isreadable ();
int iswritable ();
int link_file ();
int numdots ();
int run_exec ();
int start_recursion ();
int unlink_file ();
int update ();
int xcmp ();
int yesno ();
time_t get_date ();
void Create_Admin ();
void Lock_Cleanup ();
void ParseTag ();
void ParseTag ();
void Register ();
void Scratch_Entry ();
void Update_Logfile ();
void WriteTag ();
void cat_module ();
void check_entries ();
void close_module ();
void copy_file ();
void do_editor ();
void error ();
void fperror ();
void free_names ();
void freevers_ts ();
void history_write ();
void ign_add ();
void ign_add_file ();
void ign_setup ();
void line2argv ();
void make_directories ();
void make_directory ();
void rename_file ();
void run_arg ();
void run_args ();
void run_print ();
void run_setup ();
void strip_path ();
void update_delproc ();
void usage ();
void xchmod ();
void SIG_beginCrSect ();
void SIG_endCrSect ();
#endif /* __STDC__ */

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Difference * Difference
* *
@ -17,24 +17,18 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)diff.c 1.52 92/04/10"; static char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype diff_dirproc PROTO((char *dir, char *pos_repos, char *update_dir));
static Dtype diff_dirproc (char *dir, char *pos_repos, char *update_dir); static int diff_filesdoneproc PROTO((int err, char *repos, char *update_dir));
static int diff_dirleaveproc (char *dir, int err, char *update_dir); static int diff_dirleaveproc PROTO((char *dir, int err, char *update_dir));
static int diff_file_nodiff (char *file, char *repository, List *entries, static int diff_file_nodiff PROTO((char *file, char *repository, List *entries,
List *srcfiles, Vers_TS *vers); List *srcfiles, Vers_TS *vers));
static int diff_fileproc (char *file, char *update_dir, char *repository, static int diff_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles); List * entries, List * srcfiles));
static void diff_mark_errors (int err); static void diff_mark_errors PROTO((int err));
#else
static int diff_fileproc ();
static Dtype diff_dirproc ();
static int diff_dirleaveproc ();
static int diff_file_nodiff ();
static void diff_mark_errors ();
#endif /* __STDC__ */
static char *diff_rev1, *diff_rev2; static char *diff_rev1, *diff_rev2;
static char *diff_date1, *diff_date2; static char *diff_date1, *diff_date2;
@ -42,10 +36,11 @@ static char *use_rev1, *use_rev2;
static char *options; static char *options;
static char opts[PATH_MAX]; static char opts[PATH_MAX];
static int diff_errors; static int diff_errors;
static int empty_files = 0;
static char *diff_usage[] = static char *diff_usage[] =
{ {
"Usage: %s %s [-l] [rcsdiff-options]\n", "Usage: %s %s [-lN] [rcsdiff-options]\n",
#ifdef CVS_DIFFDATE #ifdef CVS_DIFFDATE
" [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n", " [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n",
#else #else
@ -54,6 +49,7 @@ static char *diff_usage[] =
"\t-l\tLocal directory only, not recursive\n", "\t-l\tLocal directory only, not recursive\n",
"\t-D d1\tDiff revision for date against working file.\n", "\t-D d1\tDiff revision for date against working file.\n",
"\t-D d2\tDiff rev1/date1 against date2.\n", "\t-D d2\tDiff rev1/date1 against date2.\n",
"\t-N\tinclude diffs for added and removed files.\n",
"\t-r rev1\tDiff revision for rev1 against working file.\n", "\t-r rev1\tDiff revision for rev1 against working file.\n",
"\t-r rev2\tDiff rev1/date1 against rev2.\n", "\t-r rev2\tDiff rev1/date1 against rev2.\n",
NULL NULL
@ -67,6 +63,7 @@ diff (argc, argv)
char tmp[50]; char tmp[50];
int c, err = 0; int c, err = 0;
int local = 0; int local = 0;
int which;
if (argc == -1) if (argc == -1)
usage (diff_usage); usage (diff_usage);
@ -77,8 +74,8 @@ diff (argc, argv)
* non-recursive/recursive diff. * non-recursive/recursive diff.
*/ */
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, while ((c = getopt (argc, argv,
"abcdefhilnpqtuw0123456789BHQRTC:D:F:I:L:V:k:r:")) != -1) "abcdefhilnpqtuw0123456789BHNQRTC:D:F:I:L:V:k:r:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -137,6 +134,9 @@ diff (argc, argv)
diff_date1 = Make_Date (optarg); diff_date1 = Make_Date (optarg);
break; break;
#endif #endif
case 'N':
empty_files = 1;
break;
case '?': case '?':
default: default:
usage (diff_usage); usage (diff_usage);
@ -150,10 +150,14 @@ diff (argc, argv)
if (!options) if (!options)
options = xstrdup (""); options = xstrdup ("");
which = W_LOCAL;
if (diff_rev2 != NULL || diff_date2 != NULL)
which |= W_REPOS | W_ATTIC;
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (diff_fileproc, (int (*) ()) NULL, diff_dirproc, err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
diff_dirleaveproc, argc, argv, local, diff_dirleaveproc, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1); which, 0, 1, (char *) NULL, 1, 0);
/* clean up */ /* clean up */
free (options); free (options);
@ -174,11 +178,23 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
int status, err = 2; /* 2 == trouble, like rcsdiff */ int status, err = 2; /* 2 == trouble, like rcsdiff */
Vers_TS *vers; Vers_TS *vers;
enum {
DIFF_ERROR,
DIFF_ADDED,
DIFF_REMOVED,
DIFF_NEITHER
} empty_file = DIFF_NEITHER;
char tmp[L_tmpnam+1];
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL, vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
file, 1, 0, entries, srcfiles); file, 1, 0, entries, srcfiles);
if (vers->vn_user == NULL) if (diff_rev2 != NULL || diff_date2 != NULL)
{
/* Skip all the following checks regarding the user file; we're
not using it. */
}
else if (vers->vn_user == NULL)
{ {
error (0, 0, "I know nothing about %s", file); error (0, 0, "I know nothing about %s", file);
freevers_ts (&vers); freevers_ts (&vers);
@ -187,17 +203,27 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
} }
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0') else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
{ {
error (0, 0, "%s is a new entry, no comparison available", file); if (empty_files)
freevers_ts (&vers); empty_file = DIFF_ADDED;
diff_mark_errors (err); else
return (err); {
error (0, 0, "%s is a new entry, no comparison available", file);
freevers_ts (&vers);
diff_mark_errors (err);
return (err);
}
} }
else if (vers->vn_user[0] == '-') else if (vers->vn_user[0] == '-')
{ {
error (0, 0, "%s was removed, no comparison available", file); if (empty_files)
freevers_ts (&vers); empty_file = DIFF_REMOVED;
diff_mark_errors (err); else
return (err); {
error (0, 0, "%s was removed, no comparison available", file);
freevers_ts (&vers);
diff_mark_errors (err);
return (err);
}
} }
else else
{ {
@ -220,25 +246,65 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
} }
} }
if (diff_file_nodiff (file, repository, entries, srcfiles, vers)) if (empty_file == DIFF_NEITHER && diff_file_nodiff (file, repository, entries, srcfiles, vers))
{ {
freevers_ts (&vers); freevers_ts (&vers);
return (0); return (0);
} }
/* Output an "Index:" line for patch to use */
(void) fflush (stdout); (void) fflush (stdout);
if (use_rev2) if (update_dir[0])
(void) printf ("Index: %s/%s\n", update_dir, file);
else
(void) printf ("Index: %s\n", file);
(void) fflush (stdout);
if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
{ {
run_setup ("%s%s %s %s -r%s -r%s", Rcsbin, RCS_DIFF, (void) printf ("===================================================================\nRCS file: %s\n",
opts, *options ? options : vers->options, file);
use_rev1, use_rev2); (void) printf ("diff -N %s\n", file);
if (empty_file == DIFF_ADDED)
{
run_setup ("%s %s %s %s", DIFF, opts, DEVNULL, file);
}
else
{
/*
* FIXME: Should be setting use_rev1 using the logic in
* diff_file_nodiff, and using that revision. This code
* is broken for "cvs diff -N -r foo".
*/
run_setup ("%s%s -p -q %s -r%s", Rcsbin, RCS_CO,
*options ? options : vers->options, vers->vn_rcs);
run_arg (vers->srcfile->path);
if (run_exec (RUN_TTY, tmpnam (tmp), RUN_TTY, RUN_REALLY) == -1)
{
(void) unlink (tmp);
error (1, errno, "fork failed during checkout of %s",
vers->srcfile->path);
}
run_setup ("%s %s %s %s", DIFF, opts, tmp, DEVNULL);
}
} }
else else
{ {
run_setup ("%s%s %s %s -r%s", Rcsbin, RCS_DIFF, opts, if (use_rev2)
*options ? options : vers->options, use_rev1); {
run_setup ("%s%s %s %s -r%s -r%s", Rcsbin, RCS_DIFF,
opts, *options ? options : vers->options,
use_rev1, use_rev2);
}
else
{
run_setup ("%s%s %s %s -r%s", Rcsbin, RCS_DIFF, opts,
*options ? options : vers->options, use_rev1);
}
run_arg (vers->srcfile->path);
} }
run_arg (vers->srcfile->path);
switch ((status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, switch ((status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
RUN_REALLY|RUN_COMBINED))) RUN_REALLY|RUN_COMBINED)))
@ -254,6 +320,9 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
break; break;
} }
if (empty_file == DIFF_REMOVED)
(void) unlink (tmp);
(void) fflush (stdout); (void) fflush (stdout);
freevers_ts (&vers); freevers_ts (&vers);
diff_mark_errors (err); diff_mark_errors (err);
@ -288,7 +357,20 @@ diff_dirproc (dir, pos_repos, update_dir)
} }
/* /*
* Concoct the proper exit status. * Concoct the proper exit status - done with files
*/
/* ARGSUSED */
static int
diff_filesdoneproc (err, repos, update_dir)
int err;
char *repos;
char *update_dir;
{
return (diff_errors);
}
/*
* Concoct the proper exit status - leaving directories
*/ */
/* ARGSUSED */ /* ARGSUSED */
static int static int
@ -366,7 +448,12 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
} }
/* now, see if we really need to do the diff */ /* now, see if we really need to do the diff */
return (strcmp (use_rev1, use_rev2) == 0); if (use_rev1 && use_rev2) {
return (strcmp (use_rev1, use_rev2) == 0);
} else {
error(0, 0, "No HEAD revision for file %s", file);
return (1);
}
} }
if (use_rev1 == NULL || strcmp (use_rev1, vers->vn_user) == 0) if (use_rev1 == NULL || strcmp (use_rev1, vers->vn_user) == 0)
{ {

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Entries file to Files file * Entries file to Files file
* *
@ -14,16 +14,13 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)entries.c 1.37 92/03/31"; static char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Node *AddEntryNode PROTO((List * list, char *name, char *version,
static Node *AddEntryNode (List * list, char *name, char *version,
char *timestamp, char *options, char *tag, char *timestamp, char *options, char *tag,
char *date); char *date, char *conflict));
#else
static Node *AddEntryNode ();
#endif /* __STDC__ */
static FILE *entfile; static FILE *entfile;
static char *entfilename; /* for error messages */ static char *entfilename; /* for error messages */
@ -32,15 +29,24 @@ static char *entfilename; /* for error messages */
* Write out the line associated with a node of an entries file * Write out the line associated with a node of an entries file
*/ */
static int static int
write_ent_proc (node) write_ent_proc (node, closure)
Node *node; Node *node;
void *closure;
{ {
Entnode *p; Entnode *p;
p = (Entnode *) node->data; p = (Entnode *) node->data;
if (fprintf (entfile, "/%s/%s/%s/%s/", node->key, p->version, if (fprintf (entfile, "/%s/%s/%s", node->key, p->version,
p->timestamp, p->options) == EOF) p->timestamp) == EOF)
error (1, errno, "cannot write %s", entfilename); error (1, errno, "cannot write %s", entfilename);
if (p->conflict)
{
if (fprintf (entfile, "+%s", p->conflict) == EOF)
error (1, errno, "cannot write %s", entfilename);
}
if (fprintf (entfile, "/%s/", p->options) == EOF)
error (1, errno, "cannot write %s", entfilename);
if (p->tag) if (p->tag)
{ {
if (fprintf (entfile, "T%s\n", p->tag) == EOF) if (fprintf (entfile, "T%s\n", p->tag) == EOF)
@ -67,7 +73,7 @@ write_entries (list)
/* open the new one and walk the list writing entries */ /* open the new one and walk the list writing entries */
entfilename = CVSADM_ENTBAK; entfilename = CVSADM_ENTBAK;
entfile = open_file (entfilename, "w+"); entfile = open_file (entfilename, "w+");
(void) walklist (list, write_ent_proc); (void) walklist (list, write_ent_proc, NULL);
if (fclose (entfile) == EOF) if (fclose (entfile) == EOF)
error (1, errno, "error closing %s", entfilename); error (1, errno, "error closing %s", entfilename);
@ -102,7 +108,7 @@ Scratch_Entry (list, fname)
* removing the old entry first, if necessary. * removing the old entry first, if necessary.
*/ */
void void
Register (list, fname, vn, ts, options, tag, date) Register (list, fname, vn, ts, options, tag, date, ts_conflict)
List *list; List *list;
char *fname; char *fname;
char *vn; char *vn;
@ -110,13 +116,19 @@ Register (list, fname, vn, ts, options, tag, date)
char *options; char *options;
char *tag; char *tag;
char *date; char *date;
char *ts_conflict;
{ {
int should_write_file = !noexec;
Node *node; Node *node;
if (trace) if (trace)
(void) fprintf (stderr, "-> Register(%s, %s, %s, %s, %s %s)\n", {
fname, vn, ts, options, tag ? tag : "", (void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
date ? date : ""); fname, vn, ts,
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
options, tag ? tag : "", date ? date : "");
}
/* was it already there? */ /* was it already there? */
if ((node = findnode (list, fname)) != NULL) if ((node = findnode (list, fname)) != NULL)
{ {
@ -124,21 +136,24 @@ Register (list, fname, vn, ts, options, tag, date)
delnode (node); delnode (node);
/* add the new one and re-write the file */ /* add the new one and re-write the file */
(void) AddEntryNode (list, fname, vn, ts, options, tag, date); (void) AddEntryNode (list, fname, vn, ts, options, tag,
if (!noexec) date, ts_conflict);
if (should_write_file)
write_entries (list); write_entries (list);
} }
else else
{ {
/* add the new one */ /* add the new one */
node = AddEntryNode (list, fname, vn, ts, options, tag, date); node = AddEntryNode (list, fname, vn, ts, options, tag,
date, ts_conflict);
if (!noexec) if (should_write_file)
{ {
/* append it to the end */ /* append it to the end */
entfilename = CVSADM_ENT; entfilename = CVSADM_ENT;
entfile = open_file (entfilename, "a"); entfile = open_file (entfilename, "a");
(void) write_ent_proc (node); (void) write_ent_proc (node, NULL);
if (fclose (entfile) == EOF) if (fclose (entfile) == EOF)
error (1, errno, "error closing %s", entfilename); error (1, errno, "error closing %s", entfilename);
} }
@ -174,11 +189,14 @@ ParseEntries (aflag)
List *entries; List *entries;
char line[MAXLINELEN]; char line[MAXLINELEN];
char *cp, *user, *vn, *ts, *options; char *cp, *user, *vn, *ts, *options;
char *tag_or_date, *tag, *date; char *tag_or_date, *tag, *date, *ts_conflict;
char *dirtag, *dirdate; char *dirtag, *dirdate;
int lineno = 0; int lineno = 0;
int do_rewrite = 0;
FILE *fpin; FILE *fpin;
vn = ts = options = tag = date = ts_conflict = 0;
/* get a fresh list... */ /* get a fresh list... */
entries = getlist (); entries = getlist ();
@ -192,7 +210,7 @@ ParseEntries (aflag)
struct stickydirtag *sdtp; struct stickydirtag *sdtp;
sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp)); sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
bzero ((char *) sdtp, sizeof (*sdtp)); memset ((char *) sdtp, 0, sizeof (*sdtp));
sdtp->aflag = aflag; sdtp->aflag = aflag;
sdtp->tag = xstrdup (dirtag); sdtp->tag = xstrdup (dirtag);
sdtp->date = xstrdup (dirdate); sdtp->date = xstrdup (dirdate);
@ -214,23 +232,23 @@ ParseEntries (aflag)
if (line[0] == '/') if (line[0] == '/')
{ {
user = line + 1; user = line + 1;
if ((cp = index (user, '/')) == NULL) if ((cp = strchr (user, '/')) == NULL)
continue; continue;
*cp++ = '\0'; *cp++ = '\0';
vn = cp; vn = cp;
if ((cp = index (vn, '/')) == NULL) if ((cp = strchr (vn, '/')) == NULL)
continue; continue;
*cp++ = '\0'; *cp++ = '\0';
ts = cp; ts = cp;
if ((cp = index (ts, '/')) == NULL) if ((cp = strchr (ts, '/')) == NULL)
continue; continue;
*cp++ = '\0'; *cp++ = '\0';
options = cp; options = cp;
if ((cp = index (options, '/')) == NULL) if ((cp = strchr (options, '/')) == NULL)
continue; continue;
*cp++ = '\0'; *cp++ = '\0';
tag_or_date = cp; tag_or_date = cp;
if ((cp = index (tag_or_date, '\n')) == NULL) if ((cp = strchr (tag_or_date, '\n')) == NULL)
continue; continue;
*cp = '\0'; *cp = '\0';
tag = (char *) NULL; tag = (char *) NULL;
@ -239,7 +257,40 @@ ParseEntries (aflag)
tag = tag_or_date + 1; tag = tag_or_date + 1;
else if (*tag_or_date == 'D') else if (*tag_or_date == 'D')
date = tag_or_date + 1; date = tag_or_date + 1;
(void) AddEntryNode (entries, user, vn, ts, options, tag, date);
if (ts_conflict = strchr (ts, '+'))
*ts_conflict++ = '\0';
/*
* XXX - Convert timestamp from old format to new format.
*
* If the timestamp doesn't match the file's current
* mtime, we'd have to generate a string that doesn't
* match anyways, so cheat and base it on the existing
* string; it doesn't have to match the same mod time.
*
* For an unmodified file, write the correct timestamp.
*/
{
struct stat sb;
if (strlen (ts) > 30 && stat (user, &sb) == 0)
{
extern char *ctime ();
char *c = ctime (&sb.st_mtime);
if (!strncmp (ts + 25, c, 24))
ts = time_stamp (user);
else
{
ts += 24;
ts[0] = '*';
}
do_rewrite = 1;
}
}
(void) AddEntryNode (entries, user, vn, ts, options, tag,
date, ts_conflict);
} }
else else
{ {
@ -254,6 +305,9 @@ ParseEntries (aflag)
} }
} }
if (do_rewrite && !noexec)
write_entries (entries);
/* clean up and return */ /* clean up and return */
if (fpin) if (fpin)
(void) fclose (fpin); (void) fclose (fpin);
@ -311,13 +365,13 @@ check_entries (dir)
continue; continue;
} }
rev = line; rev = line;
if ((ts = index (line, '|')) == NULL) if ((ts = strchr (line, '|')) == NULL)
continue; continue;
*ts++ = '\0'; *ts++ = '\0';
if ((user = rindex (ts, ' ')) == NULL) if ((user = strrchr (ts, ' ')) == NULL)
continue; continue;
*user++ = '\0'; *user++ = '\0';
if ((cp = index (user, '|')) == NULL) if ((cp = strchr (user, '|')) == NULL)
continue; continue;
*cp = '\0'; *cp = '\0';
opt = ""; opt = "";
@ -368,6 +422,8 @@ Entries_delproc (node)
free (p->tag); free (p->tag);
if (p->date) if (p->date)
free (p->date); free (p->date);
if (p->conflict)
free (p->conflict);
free ((char *) p); free ((char *) p);
} }
@ -376,7 +432,7 @@ Entries_delproc (node)
* list * list
*/ */
static Node * static Node *
AddEntryNode (list, name, version, timestamp, options, tag, date) AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
List *list; List *list;
char *name; char *name;
char *version; char *version;
@ -384,6 +440,7 @@ AddEntryNode (list, name, version, timestamp, options, tag, date)
char *options; char *options;
char *tag; char *tag;
char *date; char *date;
char *conflict;
{ {
Node *p; Node *p;
Entnode *entdata; Entnode *entdata;
@ -404,6 +461,7 @@ AddEntryNode (list, name, version, timestamp, options, tag, date)
entdata->options = xstrdup (options); entdata->options = xstrdup (options);
if (entdata->options == NULL) if (entdata->options == NULL)
entdata->options = xstrdup ("");/* must be non-NULL */ entdata->options = xstrdup ("");/* must be non-NULL */
entdata->conflict = xstrdup (conflict);
entdata->tag = xstrdup (tag); entdata->tag = xstrdup (tag);
entdata->date = xstrdup (date); entdata->date = xstrdup (date);
@ -452,7 +510,8 @@ WriteTag (dir, tag, date)
error (1, errno, "cannot close %s", tmp); error (1, errno, "cannot close %s", tmp);
} }
else else
(void) unlink_file (tmp); if (unlink_file (tmp) < 0 && errno != ENOENT)
error (1, errno, "cannot remove %s", tmp);
} }
/* /*
@ -476,7 +535,7 @@ ParseTag (tagp, datep)
{ {
if (fgets (line, sizeof (line), fp) != NULL) if (fgets (line, sizeof (line), fp) != NULL)
{ {
if ((cp = rindex (line, '\n')) != NULL) if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0'; *cp = '\0';
if (*line == 'T' && tagp) if (*line == 'T' && tagp)
*tagp = xstrdup (line + 1); *tagp = xstrdup (line + 1);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Find Names * Find Names
* *
@ -19,16 +19,12 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)find_names.c 1.38 92/04/10"; static char rcsid[] = "$CVSid: @(#)find_names.c 1.45 94/10/22 $";
USE(rcsid)
#endif #endif
#if __STDC__ static int find_dirs PROTO((char *dir, List * list, int checkadm));
static int find_dirs (char *dir, List * list, int checkadm); static int find_rcs PROTO((char *dir, List * list));
static int find_rcs (char *dir, List * list);
#else
static int find_rcs ();
static int find_dirs ();
#endif /* __STDC__ */
static List *filelist; static List *filelist;
@ -36,8 +32,9 @@ static List *filelist;
* add the key from entry on entries list to the files list * add the key from entry on entries list to the files list
*/ */
static int static int
add_entries_proc (node) add_entries_proc (node, closure)
Node *node; Node *node;
void *closure;
{ {
Node *fnode; Node *fnode;
@ -82,7 +79,7 @@ Find_Names (repository, which, aflag, optentries)
if (entries != NULL) if (entries != NULL)
{ {
/* walk the entries file adding elements to the files list */ /* walk the entries file adding elements to the files list */
(void) walklist (entries, add_entries_proc); (void) walklist (entries, add_entries_proc, NULL);
/* if our caller wanted the entries list, return it; else free it */ /* if our caller wanted the entries list, return it; else free it */
if (optentries != NULL) if (optentries != NULL)
@ -167,28 +164,21 @@ find_rcs (dir, list)
List *list; List *list;
{ {
Node *p; Node *p;
CONST char *regex_err; struct dirent *dp;
char line[50];
struct direct *dp;
DIR *dirp; DIR *dirp;
/* set up to read the dir */ /* set up to read the dir */
if ((dirp = opendir (dir)) == NULL) if ((dirp = opendir (dir)) == NULL)
return (1); return (1);
/* set up a regular expression to find the ,v files */
(void) sprintf (line, ".*%s$", RCSEXT);
if ((regex_err = re_comp (line)) != NULL)
error (1, 0, "%s", regex_err);
/* read the dir, grabbing the ,v files */ /* read the dir, grabbing the ,v files */
while ((dp = readdir (dirp)) != NULL) while ((dp = readdir (dirp)) != NULL)
{ {
if (re_exec (dp->d_name)) if (fnmatch (RCSPAT, dp->d_name, 0) == 0)
{ {
char *comma; char *comma;
comma = rindex (dp->d_name, ','); /* strip the ,v */ comma = strrchr (dp->d_name, ','); /* strip the ,v */
*comma = '\0'; *comma = '\0';
p = getnode (); p = getnode ();
p->type = FILES; p->type = FILES;
@ -213,17 +203,10 @@ find_dirs (dir, list, checkadm)
int checkadm; int checkadm;
{ {
Node *p; Node *p;
CONST char *regex_err;
char tmp[PATH_MAX]; char tmp[PATH_MAX];
char admdir[PATH_MAX]; struct dirent *dp;
struct direct *dp;
DIR *dirp; DIR *dirp;
/* build a regex to blow off ,v files */
(void) sprintf (tmp, ".*%s$", RCSEXT);
if ((regex_err = re_comp (tmp)) != NULL)
error (1, 0, "%s", regex_err);
/* set up to read the dir */ /* set up to read the dir */
if ((dirp = opendir (dir)) == NULL) if ((dirp = opendir (dir)) == NULL)
return (1); return (1);
@ -234,38 +217,61 @@ find_dirs (dir, list, checkadm)
if (strcmp (dp->d_name, ".") == 0 || if (strcmp (dp->d_name, ".") == 0 ||
strcmp (dp->d_name, "..") == 0 || strcmp (dp->d_name, "..") == 0 ||
strcmp (dp->d_name, CVSATTIC) == 0 || strcmp (dp->d_name, CVSATTIC) == 0 ||
strcmp (dp->d_name, CVSLCK) == 0 || strcmp (dp->d_name, CVSLCK) == 0)
re_exec (dp->d_name)) /* don't bother stating ,v files */
continue; continue;
(void) sprintf (tmp, "%s/%s", dir, dp->d_name); #ifdef DT_DIR
if (isdir (tmp)) if (dp->d_type != DT_DIR)
{ {
/* check for administration directories (if needed) */ if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
if (checkadm) continue;
#endif
/* don't bother stating ,v files */
if (fnmatch (RCSPAT, dp->d_name, 0) == 0)
continue;
sprintf (tmp, "%s/%s", dir, dp->d_name);
if (!isdir (tmp))
continue;
#ifdef DT_DIR
}
#endif
/* check for administration directories (if needed) */
if (checkadm)
{
/* blow off symbolic links to dirs in local dir */
#ifdef DT_DIR
if (dp->d_type != DT_DIR)
{ {
/* blow off symbolic links to dirs in local dir */ /* we're either unknown or a symlink at this point */
if (dp->d_type == DT_LNK)
continue;
#endif
if (islink (tmp)) if (islink (tmp))
continue; continue;
#ifdef DT_DIR
/* check for new style */
(void) sprintf (admdir, "%s/%s", tmp, CVSADM);
if (!isdir (admdir))
{
/* and old style */
(void) sprintf (admdir, "%s/%s", tmp, OCVSADM);
if (!isdir (admdir))
continue;
}
} }
#endif
/* put it in the list */ /* check for new style */
p = getnode (); (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
p->type = DIRS; if (!isdir (tmp))
p->key = xstrdup (dp->d_name); {
if (addnode (list, p) != 0) /* and old style */
freenode (p); (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, OCVSADM);
if (!isdir (tmp))
continue;
}
} }
/* put it in the list */
p = getnode ();
p->type = DIRS;
p->key = xstrdup (dp->d_name);
if (addnode (list, p) != 0)
freenode (p);
} }
(void) closedir (dirp); (void) closedir (dirp);
return (0); return (0);

View File

@ -179,7 +179,8 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)history.c 1.31 92/04/10"; static char rcsid[] = "$CVSid: @(#)history.c 1.33 94/09/21 $";
USE(rcsid)
#endif #endif
static struct hrec static struct hrec
@ -197,33 +198,18 @@ static struct hrec
} *hrec_head; } *hrec_head;
#if __STDC__ static char *fill_hrec PROTO((char *line, struct hrec * hr));
static char *fill_hrec (char *line, struct hrec * hr); static int accept_hrec PROTO((struct hrec * hr, struct hrec * lr));
static int accept_hrec (struct hrec * hr, struct hrec * lr); static int select_hrec PROTO((struct hrec * hr));
static int select_hrec (struct hrec * hr); static int sort_order PROTO((CONST PTR l, CONST PTR r));
static int sort_order (CONST PTR l, CONST PTR r); static int within PROTO((char *find, char *string));
static int within (char *find, char *string); static time_t date_and_time PROTO((char *date_str));
static time_t date_and_time (char *date_str); static void expand_modules PROTO((void));
static void expand_modules (void); static void read_hrecs PROTO((char *fname));
static void read_hrecs (char *fname); static void report_hrecs PROTO((void));
static void report_hrecs (void); static void save_file PROTO((char *dir, char *name, char *module));
static void save_file (char *dir, char *name, char *module); static void save_module PROTO((char *module));
static void save_module (char *module); static void save_user PROTO((char *name));
static void save_user (char *name);
#else
static int sort_order ();
static time_t date_and_time ();
static void save_user ();
static void save_file ();
static void save_module ();
static void expand_modules ();
static char *fill_hrec ();
static void read_hrecs ();
static int within ();
static int select_hrec ();
static void report_hrecs ();
static int accept_hrec ();
#endif /* __STDC__ */
#define ALL_REC_TYPES "TOFWUCGMAR" #define ALL_REC_TYPES "TOFWUCGMAR"
#define USER_INCREMENT 2 #define USER_INCREMENT 2
@ -247,6 +233,14 @@ static short repos_sort;
static short file_sort; static short file_sort;
static short module_sort; static short module_sort;
#ifdef HAVE_RCS5
static short tz_local;
static time_t tz_seconds_east_of_GMT;
static char *tz_name = "+0000";
#else
static char tz_name[] = "LT";
#endif
static time_t since_date; static time_t since_date;
static char since_rev[20]; /* Maxrev ~= 99.99.99.999 */ static char since_rev[20]; /* Maxrev ~= 99.99.99.999 */
static char since_tag[64]; static char since_tag[64];
@ -301,6 +295,7 @@ static char *history_usg[] =
" -r <rev/tag> Since rev or tag (looks inside RCS files!)\n", " -r <rev/tag> Since rev or tag (looks inside RCS files!)\n",
" -t <tag> Since tag record placed in history file (by anyone).\n", " -t <tag> Since tag record placed in history file (by anyone).\n",
" -u <user> For user name (repeatable)\n", " -u <user> For user name (repeatable)\n",
" -z <tz> Output for time zone <tz> (e.g. -z -0700)\n",
NULL}; NULL};
/* Sort routine for qsort: /* Sort routine for qsort:
@ -385,7 +380,7 @@ history (argc, argv)
usage (history_usg); usage (history_usg);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "Tacelow?D:b:f:m:n:p:r:t:u:x:X:")) != -1) while ((c = getopt (argc, argv, "Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -481,11 +476,47 @@ history (argc, argv)
char *cp; char *cp;
for (cp = optarg; *cp; cp++) for (cp = optarg; *cp; cp++)
if (!index (ALL_REC_TYPES, *cp)) if (!strchr (ALL_REC_TYPES, *cp))
error (1, 0, "%c is not a valid report type", cp); error (1, 0, "%c is not a valid report type", *cp);
} }
(void) strcpy (rec_types, optarg); (void) strcpy (rec_types, optarg);
break; break;
case 'z':
#ifndef HAVE_RCS5
error (0, 0, "-z not supported with RCS 4");
#else
tz_local =
(optarg[0] == 'l' || optarg[0] == 'L')
&& (optarg[1] == 't' || optarg[1] == 'T')
&& !optarg[2];
if (tz_local)
tz_name = optarg;
else
{
/*
* Convert a known time with the given timezone to time_t.
* Use the epoch + 23 hours, so timezones east of GMT work.
*/
static char f[] = "1/1/1970 23:00 %s";
char *buf = xmalloc (sizeof (f) - 2 + strlen (optarg));
time_t t;
sprintf (buf, f, optarg);
t = get_date (buf, (struct timeb *) NULL);
free (buf);
if (t == (time_t) -1)
error (0, 0, "%s is not a known time zone", optarg);
else
{
/*
* Convert to seconds east of GMT, removing the
* 23-hour offset mentioned above.
*/
tz_seconds_east_of_GMT = (time_t)23 * 60 * 60 - t;
tz_name = optarg;
}
}
#endif
break;
case '?': case '?':
default: default:
usage (history_usg); usage (history_usg);
@ -508,7 +539,7 @@ history (argc, argv)
if (tag_report) if (tag_report)
{ {
if (!index (rec_types, 'T')) if (!strchr (rec_types, 'T'))
(void) strcat (rec_types, "T"); (void) strcat (rec_types, "T");
} }
else if (extract) else if (extract)
@ -559,7 +590,7 @@ history (argc, argv)
save_user (getcaller ()); save_user (getcaller ());
/* If we're looking back to a Tag value, must consider "Tag" records */ /* If we're looking back to a Tag value, must consider "Tag" records */
if (*since_tag && !index (rec_types, 'T')) if (*since_tag && !strchr (rec_types, 'T'))
(void) strcat (rec_types, "T"); (void) strcat (rec_types, "T");
argc -= c; argc -= c;
@ -637,7 +668,7 @@ history_write (type, update_dir, revs, name, repository)
if (chdir (pw->pw_dir) < 0) if (chdir (pw->pw_dir) < 0)
error (1, errno, "can't chdir(%s)", pw->pw_dir); error (1, errno, "can't chdir(%s)", pw->pw_dir);
if (!getwd (homedir)) if (!getwd (homedir))
error (1, errno, "can't getwd in:", pw->pw_dir); error (1, errno, "can't getwd in %s", pw->pw_dir);
(void) chdir (workdir); (void) chdir (workdir);
i = strlen (homedir); i = strlen (homedir);
@ -837,16 +868,16 @@ fill_hrec (line, hr)
int off; int off;
static int idx = 0; static int idx = 0;
bzero ((char *) hr, sizeof (*hr)); memset ((char *) hr, 0, sizeof (*hr));
while (isspace (*line)) while (isspace (*line))
line++; line++;
if (!(rtn = index (line, '\n'))) if (!(rtn = strchr (line, '\n')))
return (""); return ("");
*rtn++ = '\0'; *rtn++ = '\0';
hr->type = line++; hr->type = line++;
(void) sscanf (line, "%x", &hr->date); (void) sscanf (line, "%x", &hr->date);
while (*line && index ("0123456789abcdefABCDEF", *line)) while (*line && strchr ("0123456789abcdefABCDEF", *line))
line++; line++;
if (*line == '\0') if (*line == '\0')
return (rtn); return (rtn);
@ -854,7 +885,7 @@ fill_hrec (line, hr)
line++; line++;
NEXT_BAR (user); NEXT_BAR (user);
NEXT_BAR (dir); NEXT_BAR (dir);
if ((cp = rindex (hr->dir, '*')) != NULL) if ((cp = strrchr (hr->dir, '*')) != NULL)
{ {
*cp++ = '\0'; *cp++ = '\0';
(void) sscanf (cp, "%x", &off); (void) sscanf (cp, "%x", &off);
@ -865,7 +896,7 @@ fill_hrec (line, hr)
NEXT_BAR (repos); NEXT_BAR (repos);
NEXT_BAR (rev); NEXT_BAR (rev);
hr->idx = idx++; hr->idx = idx++;
if (index ("FOT", *(hr->type))) if (strchr ("FOT", *(hr->type)))
hr->mod = line; hr->mod = line;
NEXT_BAR (file); /* This returns ptr to next line or final '\0' */ NEXT_BAR (file); /* This returns ptr to next line or final '\0' */
@ -981,7 +1012,7 @@ within (find, string)
while (*string) while (*string)
{ {
if (!(string = index (string, c))) if (!(string = strchr (string, c)))
return (0); return (0);
string++; string++;
if (!strncmp (find, string, len)) if (!strncmp (find, string, len))
@ -1104,9 +1135,9 @@ select_hrec (hr)
* file_list is null, keep everything. Otherwise, keep only files on * file_list is null, keep everything. Otherwise, keep only files on
* file_list, matched appropriately. * file_list, matched appropriately.
*/ */
if (!index (rec_types, *(hr->type))) if (!strchr (rec_types, *(hr->type)))
return (0); return (0);
if (!index ("TFO", *(hr->type))) /* Don't bother with "file" if "TFO" */ if (!strchr ("TFO", *(hr->type))) /* Don't bother with "file" if "TFO" */
{ {
if (file_list) /* If file_list is null, accept all */ if (file_list) /* If file_list is null, accept all */
{ {
@ -1132,7 +1163,7 @@ select_hrec (hr)
} }
else else
{ {
if (index (cp, '/')) if (strchr (cp, '/'))
{ {
(void) sprintf (cp2 = cmpfile, "%s/%s", (void) sprintf (cp2 = cmpfile, "%s/%s",
hr->repos, hr->file); hr->repos, hr->file);
@ -1215,7 +1246,7 @@ report_hrecs ()
ty = *(lr->type); ty = *(lr->type);
(void) strcpy (repos, lr->repos); (void) strcpy (repos, lr->repos);
if ((cp = rindex (repos, '/')) != NULL) if ((cp = strrchr (repos, '/')) != NULL)
{ {
if (lr->mod && !strcmp (++cp, lr->mod)) if (lr->mod && !strcmp (++cp, lr->mod))
{ {
@ -1253,12 +1284,21 @@ report_hrecs ()
continue; continue;
ty = *(lr->type); ty = *(lr->type);
#ifdef HAVE_RCS5
if (!tz_local)
{
time_t t = lr->date + tz_seconds_east_of_GMT;
tm = gmtime (&t);
}
else
#endif
tm = localtime (&(lr->date)); tm = localtime (&(lr->date));
(void) printf ("%c %02d/%02d %02d:%02d %-*s", ty, tm->tm_mon + 1, (void) printf ("%c %02d/%02d %02d:%02d %s %-*s", ty, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, user_len, lr->user); tm->tm_mday, tm->tm_hour, tm->tm_min, tz_name,
user_len, lr->user);
(void) sprintf (workdir, "%s%s", lr->dir, lr->end); (void) sprintf (workdir, "%s%s", lr->dir, lr->end);
if ((cp = rindex (workdir, '/')) != NULL) if ((cp = strrchr (workdir, '/')) != NULL)
{ {
if (lr->mod && !strcmp (++cp, lr->mod)) if (lr->mod && !strcmp (++cp, lr->mod))
{ {
@ -1266,7 +1306,7 @@ report_hrecs ()
} }
} }
(void) strcpy (repos, lr->repos); (void) strcpy (repos, lr->repos);
if ((cp = rindex (repos, '/')) != NULL) if ((cp = strrchr (repos, '/')) != NULL)
{ {
if (lr->mod && !strcmp (++cp, lr->mod)) if (lr->mod && !strcmp (++cp, lr->mod))
{ {

View File

@ -1,11 +1,12 @@
/* /*
* .cvsignore file support contributed by David G. Grubbs <dgg@ksr.com> * .cvsignore file support contributed by David G. Grubbs <dgg@odi.com>
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)ignore.c 1.13 92/04/03"; static char rcsid[] = "$CVSid: @(#)ignore.c 1.16 94/09/24 $";
USE(rcsid)
#endif #endif
/* /*
@ -147,7 +148,7 @@ ign_add (ign, hold)
* (saving it if necessary). We also catch * as a special case in a * (saving it if necessary). We also catch * as a special case in a
* global ignore file as an optimization * global ignore file as an optimization
*/ */
if (isspace (*(ign + 1)) && (*ign == '!' || *ign == '*')) if ((!*(ign+1) || isspace (*(ign+1))) && (*ign == '!' || *ign == '*'))
{ {
if (!hold) if (!hold)
{ {
@ -225,3 +226,47 @@ ign_name (name)
return (1); return (1);
return (0); return (0);
} }
static char **dir_ign_list = NULL;
static int dir_ign_max = 0;
static int dir_ign_current = 0;
/* add a directory to list of dirs to ignore */
void ign_dir_add (name)
char *name;
{
/* make sure we've got the space for the entry */
if (dir_ign_current <= dir_ign_max)
{
dir_ign_max += IGN_GROW;
dir_ign_list = (char **) xrealloc ((char *) dir_ign_list, (dir_ign_max+1) * sizeof(char*));
}
dir_ign_list[dir_ign_current] = name;
dir_ign_current += 1 ;
}
/* this function returns 1 (true) if the given directory name is part of
* the list of directories to ignore
*/
int ignore_directory (name)
char *name;
{
int i;
if (!dir_ign_list)
return 0;
i = dir_ign_current;
while (i--)
{
if (strncmp(name, dir_ign_list[i], strlen(dir_ign_list[i])) == 0)
return 1;
}
return 0;
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* "import" checks in the vendor release located in the current directory into * "import" checks in the vendor release located in the current directory into
* the CVS source repository. The CVS vendor branch support is utilized. * the CVS source repository. The CVS vendor branch support is utilized.
@ -19,39 +19,29 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)import.c 1.52 92/03/31"; static char rcsid[] = "$CVSid: @(#)import.c 1.63 94/09/30 $";
USE(rcsid)
#endif #endif
#define FILE_HOLDER ".#cvsxxx" #define FILE_HOLDER ".#cvsxxx"
#if __STDC__ static char *get_comment PROTO((char *user));
static char *get_comment (char *user); static int add_rcs_file PROTO((char *message, char *rcs, char *user, char *vtag,
static int add_rcs_file (char *message, char *rcs, char *user, char *vtag, int targc, char *targv[]));
int targc, char *targv[]); static int expand_at_signs PROTO((char *buf, off_t size, FILE *fp));
static int expand_at_signs (char *buf, off_t size, FILE *fp); static int add_rev PROTO((char *message, char *rcs, char *vfile, char *vers));
static int add_rev (char *message, char *rcs, char *vfile, char *vers); static int add_tags PROTO((char *rcs, char *vfile, char *vtag, int targc,
static int add_tags (char *rcs, char *vfile, char *vtag, int targc, char *targv[]));
char *targv[]); static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]));
static int import_descend (char *message, char *vtag, int targc, char *targv[]); static int import_descend_dir PROTO((char *message, char *dir, char *vtag,
static int import_descend_dir (char *message, char *dir, char *vtag, int targc, char *targv[]));
int targc, char *targv[]); static int process_import_file PROTO((char *message, char *vfile, char *vtag,
static int process_import_file (char *message, char *vfile, char *vtag, int targc, char *targv[]));
int targc, char *targv[]); static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
static int update_rcs_file (char *message, char *vfile, char *vtag, int targc, char *targv[], int inattic));
char *targv[]); static void add_log PROTO((int ch, char *fname));
static void add_log (int ch, char *fname); static int str2expmode PROTO((char const* expstring));
#else static int strn2expmode PROTO((char const* expstring, size_t n));
static int import_descend ();
static int process_import_file ();
static int update_rcs_file ();
static int add_rev ();
static int add_tags ();
static char *get_comment ();
static int add_rcs_file ();
static int expand_at_signs ();
static void add_log ();
static int import_descend_dir ();
#endif /* __STDC__ */
static int repos_len; static int repos_len;
static char vhead[50]; static char vhead[50];
@ -59,25 +49,42 @@ static char vbranch[50];
static FILE *logfp; static FILE *logfp;
static char repository[PATH_MAX]; static char repository[PATH_MAX];
static int conflicts; static int conflicts;
static int use_file_modtime;
static char *keyword_opt = NULL;
static char *import_usage[] = static char *import_usage[] =
{ {
"Usage: %s %s [-Qq] [-I ign] [-m msg] [-b branch]\n", "Usage: %s %s [-Qq] [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
" repository vendor-tag release-tags...\n", " repository vendor-tag release-tags...\n",
"\t-Q\tReally quiet.\n", "\t-Q\tReally quiet.\n",
"\t-q\tSomewhat quiet.\n", "\t-q\tSomewhat quiet.\n",
"\t-d\tUse the file's modification time as the time of import.\n",
"\t-k sub\tSet default RCS keyword substitution mode.\n",
"\t-I ign\tMore files to ignore (! to reset).\n", "\t-I ign\tMore files to ignore (! to reset).\n",
"\t-b bra\tVendor branch id.\n", "\t-b bra\tVendor branch id.\n",
"\t-m msg\tLog message.\n", "\t-m msg\tLog message.\n",
NULL NULL
}; };
static char *keyword_usage[] =
{
"%s %s: invalid RCS keyword expansion mode\n",
"Valid expansion modes include:\n",
" -kkv\tGenerate keywords using the default form.\n",
" -kkvl\tLike -kkv, except locker's name inserted.\n",
" -kk\tGenerate only keyword names in keyword strings.\n",
" -kv\tGenerate only keyword values in keyword strings.\n",
" -ko\tGenerate the old keyword string (no changes from checked in file).\n",
NULL,
};
int int
import (argc, argv) import (argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
char message[MAXMESGLEN]; char *message = NULL;
char tmpfile[L_tmpnam+1]; char tmpfile[L_tmpnam+1];
char *cp; char *cp;
int i, c, msglen, err; int i, c, msglen, err;
@ -90,9 +97,8 @@ import (argc, argv)
ign_setup (); ign_setup ();
(void) strcpy (vbranch, CVSBRANCH); (void) strcpy (vbranch, CVSBRANCH);
message[0] = '\0';
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "Qqb:m:I:")) != -1) while ((c = getopt (argc, argv, "Qqdb:m:I:k:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -102,6 +108,9 @@ import (argc, argv)
case 'q': case 'q':
quiet = 1; quiet = 1;
break; break;
case 'd':
use_file_modtime = 1;
break;
case 'b': case 'b':
(void) strcpy (vbranch, optarg); (void) strcpy (vbranch, optarg);
break; break;
@ -111,18 +120,17 @@ import (argc, argv)
#else #else
use_editor = FALSE; use_editor = FALSE;
#endif #endif
if (strlen (optarg) >= (sizeof (message) - 1)) message = xstrdup(optarg);
{
error (0, 0, "warning: message too long; truncated!");
(void) strncpy (message, optarg, sizeof (message));
message[sizeof (message) - 2] = '\0';
}
else
(void) strcpy (message, optarg);
break; break;
case 'I': case 'I':
ign_add (optarg, 0); ign_add (optarg, 0);
break; break;
case 'k':
if (str2expmode(optarg) != -1)
keyword_opt = optarg;
else
usage (keyword_usage);
break;
case '?': case '?':
default: default:
usage (import_usage); usage (import_usage);
@ -167,15 +175,25 @@ import (argc, argv)
if (numdots (vbranch) != 2) if (numdots (vbranch) != 2)
error (1, 0, "Only branches with two dots are supported: %s", vbranch); error (1, 0, "Only branches with two dots are supported: %s", vbranch);
(void) strcpy (vhead, vbranch); (void) strcpy (vhead, vbranch);
cp = rindex (vhead, '.'); cp = strrchr (vhead, '.');
*cp = '\0'; *cp = '\0';
if (use_editor) if (use_editor)
do_editor ((char *) NULL, message, repository, (List *) NULL); {
msglen = strlen (message); do_editor ((char *) NULL, &message, repository,
(List *) NULL);
}
msglen = message == NULL ? 0 : strlen (message);
if (msglen == 0 || message[msglen - 1] != '\n') if (msglen == 0 || message[msglen - 1] != '\n')
{ {
message[msglen] = '\n'; char *nm = xmalloc (msglen + 2);
message[msglen + 1] = '\0'; if (message != NULL)
{
(void) strcpy (nm, message);
free (message);
}
(void) strcat (nm + msglen, "\n");
message = nm;
} }
/* /*
@ -235,6 +253,10 @@ import (argc, argv)
Update_Logfile (repository, message, vbranch, logfp, ulist); Update_Logfile (repository, message, vbranch, logfp, ulist);
dellist (&ulist); dellist (&ulist);
(void) fclose (logfp); (void) fclose (logfp);
if (message)
free (message);
return (err); return (err);
} }
@ -249,7 +271,7 @@ import_descend (message, vtag, targc, targv)
char *targv[]; char *targv[];
{ {
DIR *dirp; DIR *dirp;
struct direct *dp; struct dirent *dp;
int err = 0; int err = 0;
int has_dirs = 0; int has_dirs = 0;
@ -299,10 +321,14 @@ import_descend (message, vtag, targc, targv)
{ {
while ((dp = readdir (dirp)) != NULL) while ((dp = readdir (dirp)) != NULL)
{ {
if (ign_name (dp->d_name) || !isdir (dp->d_name)) if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
continue;
if (!isdir (dp->d_name) || ign_name (dp->d_name))
continue; continue;
err += import_descend_dir (message, dp->d_name, err += import_descend_dir (message, dp->d_name,
vtag, targc, targv); vtag, targc, targv);
/* need to re-load .cvsignore after each dir traversal */
ign_add_file (CVSDOTIGNORE, 1);
} }
(void) closedir (dirp); (void) closedir (dirp);
} }
@ -323,6 +349,7 @@ process_import_file (message, vfile, vtag, targc, targv)
{ {
char attic_name[PATH_MAX]; char attic_name[PATH_MAX];
char rcs[PATH_MAX]; char rcs[PATH_MAX];
int inattic = 0;
(void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT); (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
if (!isfile (rcs)) if (!isfile (rcs))
@ -339,12 +366,13 @@ process_import_file (message, vfile, vtag, targc, targv)
add_log ('N', vfile); add_log ('N', vfile);
return (add_rcs_file (message, rcs, vfile, vtag, targc, targv)); return (add_rcs_file (message, rcs, vfile, vtag, targc, targv));
} }
inattic = 1;
} }
/* /*
* an rcs file exists. have to do things the official, slow, way. * an rcs file exists. have to do things the official, slow, way.
*/ */
return (update_rcs_file (message, vfile, vtag, targc, targv)); return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
} }
/* /*
@ -352,27 +380,32 @@ process_import_file (message, vfile, vtag, targc, targv)
* (possibly already existing) vendor branch. * (possibly already existing) vendor branch.
*/ */
static int static int
update_rcs_file (message, vfile, vtag, targc, targv) update_rcs_file (message, vfile, vtag, targc, targv, inattic)
char *message; char *message;
char *vfile; char *vfile;
char *vtag; char *vtag;
int targc; int targc;
char *targv[]; char *targv[];
int inattic;
{ {
Vers_TS *vers; Vers_TS *vers;
char letter; int letter;
int ierrno; int ierrno;
char *tmpdir;
vers = Version_TS (repository, (char *) NULL, vbranch, (char *) NULL, vfile, vers = Version_TS (repository, (char *) NULL, vbranch, (char *) NULL, vfile,
1, 0, (List *) NULL, (List *) NULL); 1, 0, (List *) NULL, (List *) NULL);
if (vers->vn_rcs != NULL) if (vers->vn_rcs != NULL)
{ {
char xtmpfile[50]; char xtmpfile[PATH_MAX];
int different; int different;
int retcode = 0; int retcode = 0;
/* XXX - should be more unique */ tmpdir = getenv ("TMPDIR");
(void) sprintf (xtmpfile, "/tmp/%s", FILE_HOLDER); if (tmpdir == NULL || tmpdir[0] == '\0')
tmpdir = "/tmp";
(void) sprintf (xtmpfile, "%s/cvs-imp%d", tmpdir, getpid());
/* /*
* The rcs file does have a revision on the vendor branch. Compare * The rcs file does have a revision on the vendor branch. Compare
@ -422,15 +455,15 @@ update_rcs_file (message, vfile, vtag, targc, targv)
} }
/* We may have failed to parse the RCS file; check just in case */ /* We may have failed to parse the RCS file; check just in case */
if (vers->srcfile == NULL || add_rev (message, vers->srcfile->path, if (vers->srcfile == NULL ||
vfile, vers->vn_rcs) || add_rev (message, vers->srcfile->path, vfile, vers->vn_rcs) ||
add_tags (vers->srcfile->path, vfile, vtag, targc, targv)) add_tags (vers->srcfile->path, vfile, vtag, targc, targv))
{ {
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }
if (vers->srcfile->branch == NULL || if (vers->srcfile->branch == NULL || inattic ||
strcmp (vers->srcfile->branch, vbranch) != 0) strcmp (vers->srcfile->branch, vbranch) != 0)
{ {
conflicts++; conflicts++;
@ -490,6 +523,8 @@ add_rev (message, rcs, vfile, vers)
} }
run_setup ("%s%s -q -f -r%s", Rcsbin, RCS_CI, vbranch); run_setup ("%s%s -q -f -r%s", Rcsbin, RCS_CI, vbranch);
run_args ("-m%s", message); run_args ("-m%s", message);
if (use_file_modtime)
run_arg ("-d");
run_arg (rcs); run_arg (rcs);
status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
ierrno = errno; ierrno = errno;
@ -583,8 +618,11 @@ struct compair comtable[] =
*/ */
"a", "-- ", /* Ada */ "a", "-- ", /* Ada */
"ada", "-- ", "ada", "-- ",
"adb", "-- ",
"asm", ";; ", /* assembler (MS-DOS) */ "asm", ";; ", /* assembler (MS-DOS) */
"ads", "-- ", /* Ada */
"bat", ":: ", /* batch (MS-DOS) */ "bat", ":: ", /* batch (MS-DOS) */
"body", "-- ", /* Ada */
"c", " * ", /* C */ "c", " * ", /* C */
"c++", "// ", /* C++ in all its infinite guises */ "c++", "// ", /* C++ in all its infinite guises */
"cc", "// ", "cc", "// ",
@ -596,6 +634,8 @@ struct compair comtable[] =
"cs", " * ", /* C* */ "cs", " * ", /* C* */
"csh", "# ", /* shell */ "csh", "# ", /* shell */
"e", "# ", /* efl */ "e", "# ", /* efl */
"epsf", "% ", /* encapsulated postscript */
"epsi", "% ", /* encapsulated postscript */
"el", "; ", /* Emacs Lisp */ "el", "; ", /* Emacs Lisp */
"f", "c ", /* Fortran */ "f", "c ", /* Fortran */
"for", "c ", "for", "c ",
@ -646,6 +686,7 @@ struct compair comtable[] =
#endif #endif
"sh", "# ", /* shell */ "sh", "# ", /* shell */
"sl", "% ", /* psl */ "sl", "% ", /* psl */
"spec", "-- ", /* Ada */
"tex", "% ", /* tex */ "tex", "% ", /* tex */
"y", " * ", /* yacc */ "y", " * ", /* yacc */
"ye", " * ", /* yacc-efl */ "ye", " * ", /* yacc-efl */
@ -663,7 +704,7 @@ get_comment (user)
char suffix_path[PATH_MAX]; char suffix_path[PATH_MAX];
int i; int i;
cp = rindex (user, '.'); cp = strrchr (user, '.');
if (cp != NULL) if (cp != NULL)
{ {
cp++; cp++;
@ -702,7 +743,10 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
struct stat sb; struct stat sb;
struct tm *ftm; struct tm *ftm;
time_t now; time_t now;
char altdate1[50], altdate2[50]; char altdate1[50];
#ifndef HAVE_RCS5
char altdate2[50];
#endif
char *author, *buf; char *author, *buf;
int i, mode, ierrno, err = 0; int i, mode, ierrno, err = 0;
@ -730,15 +774,29 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) == EOF || if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) == EOF ||
fprintf (fprcs, "locks ; strict;\n") == EOF || fprintf (fprcs, "locks ; strict;\n") == EOF ||
/* XXX - make sure @@ processing works in the RCS file */ /* XXX - make sure @@ processing works in the RCS file */
fprintf (fprcs, "comment @%s@;\n\n", get_comment (user)) == EOF) fprintf (fprcs, "comment @%s@;\n", get_comment (user)) == EOF)
{ {
goto write_error; goto write_error;
} }
if (keyword_opt != NULL)
if (fprintf (fprcs, "expand @%s@;\n", keyword_opt) == EOF)
{
goto write_error;
}
if (fprintf (fprcs, "\n") == EOF)
goto write_error;
/* /*
* puttree() * puttree()
*/ */
(void) time (&now); if (fstat (fileno (fpuser), &sb) < 0)
error (1, errno, "cannot fstat %s", user);
if (use_file_modtime)
now = sb.st_mtime;
else
(void) time (&now);
#ifdef HAVE_RCS5 #ifdef HAVE_RCS5
ftm = gmtime (&now); ftm = gmtime (&now);
#else #else
@ -748,16 +806,20 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
ftm->tm_min, ftm->tm_sec); ftm->tm_min, ftm->tm_sec);
now++;
#ifdef HAVE_RCS5 #ifdef HAVE_RCS5
ftm = gmtime (&now); #define altdate2 altdate1
#else #else
/*
* If you don't have RCS V5 or later, you need to lie about the ci
* time, since RCS V4 and earlier insist that the times differ.
*/
now++;
ftm = localtime (&now); ftm = localtime (&now);
#endif
(void) sprintf (altdate2, DATEFORM, (void) sprintf (altdate2, DATEFORM,
ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
ftm->tm_min, ftm->tm_sec); ftm->tm_min, ftm->tm_sec);
#endif
author = getcaller (); author = getcaller ();
if (fprintf (fprcs, "\n%s\n", vhead) == EOF || if (fprintf (fprcs, "\n%s\n", vhead) == EOF ||
@ -786,8 +848,6 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
goto write_error; goto write_error;
} }
if (fstat (fileno (fpuser), &sb) < 0)
error (1, errno, "cannot fstat %s", user);
if (sb.st_size > 0) if (sb.st_size > 0)
{ {
off_t size; off_t size;
@ -797,7 +857,10 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
if (fread (buf, (int) size, 1, fpuser) != 1) if (fread (buf, (int) size, 1, fpuser) != 1)
error (1, errno, "cannot read file %s for copying", user); error (1, errno, "cannot read file %s for copying", user);
if (expand_at_signs (buf, size, fprcs) == EOF) if (expand_at_signs (buf, size, fprcs) == EOF)
{
free (buf);
goto write_error; goto write_error;
}
free (buf); free (buf);
} }
if (fprintf (fprcs, "@\n\n") == EOF || if (fprintf (fprcs, "@\n\n") == EOF ||
@ -874,7 +937,7 @@ expand_at_signs (buf, size, fp)
*/ */
static void static void
add_log (ch, fname) add_log (ch, fname)
char ch; int ch;
char *fname; char *fname;
{ {
if (!really_quiet) /* write to terminal */ if (!really_quiet) /* write to terminal */
@ -964,7 +1027,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
} }
err = import_descend (message, vtag, targc, targv); err = import_descend (message, vtag, targc, targv);
out: out:
if ((cp = rindex (repository, '/')) != NULL) if ((cp = strrchr (repository, '/')) != NULL)
*cp = '\0'; *cp = '\0';
else else
repository[0] = '\0'; repository[0] = '\0';
@ -972,3 +1035,36 @@ import_descend_dir (message, dir, vtag, targc, targv)
error (1, errno, "cannot chdir to %s", cwd); error (1, errno, "cannot chdir to %s", cwd);
return (err); return (err);
} }
/* the following code is taken from code in rcs/src/rcssyn.c, and returns a
* positive value if 'expstring' contains a valid RCS expansion token for
* the -k option. If an invalid expansion is named, then return -1.
*/
char const *const expand_names[] = {
/* These must agree with *_EXPAND in rcs/src/rcsbase.h. */
"kv","kvl","k","v","o",
0
};
static int
str2expmode(s)
char const *s;
/* Yield expand mode corresponding to S, or -1 if bad. */
{
return strn2expmode(s, strlen(s));
}
static int
strn2expmode(s, n)
char const *s;
size_t n;
{
char const *const *p;
for (p = expand_names; *p; ++p)
if (memcmp(*p,s,n) == 0 && !(*p)[n])
return p - expand_names;
return -1;
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Set Lock * Set Lock
* *
@ -13,30 +13,20 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)lock.c 1.42 92/04/10"; static char rcsid[] = "$CVSid: @(#)lock.c 1.50 94/09/30 $";
USE(rcsid)
#endif #endif
extern char *ctime (); extern char *ctime ();
#if __STDC__ static int readers_exist PROTO((char *repository));
static int readers_exist (char *repository); static int set_lock PROTO((char *lockdir, int will_wait, char *repository));
static int set_lock (char *lockdir, int will_wait, char *repository); static void set_lockers_name PROTO((struct stat *statp));
static void set_lockers_name (struct stat *statp); static int set_writelock_proc PROTO((Node * p, void *closure));
static int set_writelock_proc (Node * p); static int unlock_proc PROTO((Node * p, void *closure));
static int unlock_proc (Node * p); static int write_lock PROTO((char *repository));
static int write_lock (char *repository); static void unlock PROTO((char *repository));
static void unlock (char *repository); static void lock_wait PROTO((char *repository));
static void lock_wait ();
#else
static int unlock_proc ();
static void unlock ();
static int set_writelock_proc ();
static int write_lock ();
static int readers_exist ();
static int set_lock ();
static void set_lockers_name ();
static void lock_wait ();
#endif /* __STDC__ */
static char lockers_name[20]; static char lockers_name[20];
static char *repository; static char *repository;
@ -65,7 +55,7 @@ Lock_Cleanup ()
/* clean up multiple locks (if any) */ /* clean up multiple locks (if any) */
if (locklist != (List *) NULL) if (locklist != (List *) NULL)
{ {
(void) walklist (locklist, unlock_proc); (void) walklist (locklist, unlock_proc, NULL);
locklist = (List *) NULL; locklist = (List *) NULL;
} }
} }
@ -74,8 +64,9 @@ Lock_Cleanup ()
* walklist proc for removing a list of locks * walklist proc for removing a list of locks
*/ */
static int static int
unlock_proc (p) unlock_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
unlock (p->key); unlock (p->key);
return (0); return (0);
@ -94,13 +85,15 @@ unlock (repository)
if (readlock[0] != '\0') if (readlock[0] != '\0')
{ {
(void) sprintf (tmp, "%s/%s", repository, readlock); (void) sprintf (tmp, "%s/%s", repository, readlock);
(void) unlink (tmp); if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
} }
if (writelock[0] != '\0') if (writelock[0] != '\0')
{ {
(void) sprintf (tmp, "%s/%s", repository, writelock); (void) sprintf (tmp, "%s/%s", repository, writelock);
(void) unlink (tmp); if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
} }
/* /*
@ -117,6 +110,13 @@ unlock (repository)
cleanup_lckdir = 0; cleanup_lckdir = 0;
} }
/*
* Since some systems don't define this...
*/
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
/* /*
* Create a lock file for readers * Create a lock file for readers
*/ */
@ -127,10 +127,18 @@ Reader_Lock (xrepository)
int err = 0; int err = 0;
FILE *fp; FILE *fp;
char tmp[PATH_MAX]; char tmp[PATH_MAX];
#ifdef HAVE_LONG_FILE_NAMES
char hostname[MAXHOSTNAMELEN];
#endif
if (noexec) if (noexec)
return (0); return (0);
#ifdef HAVE_LONG_FILE_NAMES
memset(hostname, 0, sizeof(hostname));
gethostname(hostname, sizeof(hostname) - 1);
#endif
/* we only do one directory at a time for read locks! */ /* we only do one directory at a time for read locks! */
if (repository != NULL) if (repository != NULL)
{ {
@ -139,7 +147,13 @@ Reader_Lock (xrepository)
} }
if (readlock[0] == '\0') if (readlock[0] == '\0')
(void) sprintf (readlock, "%s.%d", CVSRFL, getpid ()); (void) sprintf (readlock,
#ifdef HAVE_LONG_FILE_NAMES
"%s.%s.%d", CVSRFL, hostname,
#else
"%s.%d", CVSRFL,
#endif
getpid ());
/* remember what we're locking (for lock_cleanup) */ /* remember what we're locking (for lock_cleanup) */
repository = xrepository; repository = xrepository;
@ -152,16 +166,24 @@ Reader_Lock (xrepository)
(void) SIG_register (SIGTERM, Lock_Cleanup); (void) SIG_register (SIGTERM, Lock_Cleanup);
/* make sure we can write the repository */ /* make sure we can write the repository */
(void) sprintf (tmp, "%s/%s.%d", xrepository, CVSTFL, getpid ()); (void) sprintf (tmp,
#ifdef HAVE_LONG_FILE_NAMES
"%s/%s.%s.%d", xrepository, CVSTFL, hostname,
#else
"%s/%s.%d", xrepository, CVSTFL,
#endif
getpid());
if ((fp = fopen (tmp, "w+")) == NULL || fclose (fp) == EOF) if ((fp = fopen (tmp, "w+")) == NULL || fclose (fp) == EOF)
{ {
error (0, errno, "cannot create read lock in repository `%s'", error (0, errno, "cannot create read lock in repository `%s'",
xrepository); xrepository);
readlock[0] = '\0'; readlock[0] = '\0';
(void) unlink (tmp); if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
return (1); return (1);
} }
(void) unlink (tmp); if (unlink (tmp) < 0)
error (0, errno, "failed to remove lock %s", tmp);
/* get the lock dir for our own */ /* get the lock dir for our own */
(void) sprintf (tmp, "%s/%s", xrepository, CVSLCK); (void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
@ -218,7 +240,7 @@ Writer_Lock (list)
locklist = list; /* init for Lock_Cleanup */ locklist = list; /* init for Lock_Cleanup */
(void) strcpy (lockers_name, "unknown"); (void) strcpy (lockers_name, "unknown");
(void) walklist (list, set_writelock_proc); (void) walklist (list, set_writelock_proc, NULL);
switch (lock_error) switch (lock_error)
{ {
@ -247,8 +269,9 @@ Writer_Lock (list)
* walklist proc for setting write locks * walklist proc for setting write locks
*/ */
static int static int
set_writelock_proc (p) set_writelock_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
/* if some lock was not OK, just skip this one */ /* if some lock was not OK, just skip this one */
if (lock_error != L_OK) if (lock_error != L_OK)
@ -271,9 +294,23 @@ write_lock (repository)
int status; int status;
FILE *fp; FILE *fp;
char tmp[PATH_MAX]; char tmp[PATH_MAX];
#ifdef HAVE_LONG_FILE_NAMES
char hostname[MAXHOSTNAMELEN];
#endif
#ifdef HAVE_LONG_FILE_NAMES
memset(hostname, 0, sizeof(hostname));
gethostname(hostname, sizeof(hostname) - 1);
#endif
if (writelock[0] == '\0') if (writelock[0] == '\0')
(void) sprintf (writelock, "%s.%d", CVSWFL, getpid ()); (void) sprintf (writelock,
#ifdef HAVE_LONG_FILE_NAMES
"%s.%s.%d", CVSWFL, hostname,
#else
"%s.%d", CVSWFL,
#endif
getpid());
/* make sure we clean up on error */ /* make sure we clean up on error */
(void) SIG_register (SIGHUP, Lock_Cleanup); (void) SIG_register (SIGHUP, Lock_Cleanup);
@ -283,15 +320,23 @@ write_lock (repository)
(void) SIG_register (SIGTERM, Lock_Cleanup); (void) SIG_register (SIGTERM, Lock_Cleanup);
/* make sure we can write the repository */ /* make sure we can write the repository */
(void) sprintf (tmp, "%s/%s.%d", repository, CVSTFL, getpid ()); (void) sprintf (tmp,
#ifdef HAVE_LONG_FILE_NAMES
"%s/%s.%s.%d", repository, CVSTFL, hostname,
#else
"%s/%s.%d", repository, CVSTFL,
#endif
getpid ());
if ((fp = fopen (tmp, "w+")) == NULL || fclose (fp) == EOF) if ((fp = fopen (tmp, "w+")) == NULL || fclose (fp) == EOF)
{ {
error (0, errno, "cannot create write lock in repository `%s'", error (0, errno, "cannot create write lock in repository `%s'",
repository); repository);
(void) unlink (tmp); if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
return (L_ERROR); return (L_ERROR);
} }
(void) unlink (tmp); if (unlink (tmp) < 0)
error (0, errno, "failed to remove lock %s", tmp);
/* make sure the lock dir is ours (not necessarily unique to us!) */ /* make sure the lock dir is ours (not necessarily unique to us!) */
(void) sprintf (tmp, "%s/%s", repository, CVSLCK); (void) sprintf (tmp, "%s/%s", repository, CVSLCK);
@ -318,7 +363,9 @@ write_lock (repository)
{ {
int xerrno = errno; int xerrno = errno;
(void) unlink (tmp); if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
/* free the lock dir if we created it */ /* free the lock dir if we created it */
if (status == L_OK) if (status == L_OK)
{ {
@ -349,9 +396,8 @@ readers_exist (repository)
{ {
char line[MAXLINELEN]; char line[MAXLINELEN];
DIR *dirp; DIR *dirp;
struct direct *dp; struct dirent *dp;
struct stat sb; struct stat sb;
CONST char *regex_err;
int ret = 0; int ret = 0;
#ifdef CVS_FUDGELOCKS #ifdef CVS_FUDGELOCKS
@ -361,43 +407,46 @@ readers_exist (repository)
if ((dirp = opendir (repository)) == NULL) if ((dirp = opendir (repository)) == NULL)
error (1, 0, "cannot open directory %s", repository); error (1, 0, "cannot open directory %s", repository);
(void) sprintf (line, "^%s.*", CVSRFL); errno = 0;
if ((regex_err = re_comp (line)) != NULL)
error (1, 0, "%s", regex_err);
while ((dp = readdir (dirp)) != NULL) while ((dp = readdir (dirp)) != NULL)
{ {
(void) sprintf (line, "%s/%s", repository, dp->d_name); if (fnmatch (CVSRFLPAT, dp->d_name, 0) == 0)
if (re_exec (dp->d_name))
{ {
#ifdef CVS_FUDGELOCKS #ifdef CVS_FUDGELOCKS
time_t now; time_t now;
(void) time (&now); (void) time (&now);
#endif
/* (void) sprintf (line, "%s/%s", repository, dp->d_name);
* If the create time of the file is more than CVSLCKAGE seconds
* ago, try to clean-up the lock file, and if successful, re-open
* the directory and try again.
*/
if (stat (line, &sb) != -1) if (stat (line, &sb) != -1)
{ {
#ifdef CVS_FUDGELOCKS
/*
* If the create time of the file is more than CVSLCKAGE
* seconds ago, try to clean-up the lock file, and if
* successful, re-open the directory and try again.
*/
if (now >= (sb.st_ctime + CVSLCKAGE) && unlink (line) != -1) if (now >= (sb.st_ctime + CVSLCKAGE) && unlink (line) != -1)
{ {
(void) closedir (dirp); if (closedir (dirp) < 0)
error (0, errno,
"error closing directory %s", repository);
goto again; goto again;
} }
#endif
set_lockers_name (&sb); set_lockers_name (&sb);
} }
#else
if (stat (line, &sb) != -1)
set_lockers_name (&sb);
#endif
ret = 1; ret = 1;
break; break;
} }
errno = 0;
} }
(void) closedir (dirp); if (errno != 0)
error (0, errno, "error reading directory %s", repository);
if (closedir (dirp) < 0)
error (0, errno, "error closing directory %s", repository);
return (ret); return (ret);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Print Log Information * Print Log Information
* *
@ -15,17 +15,13 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)log.c 1.39 92/03/31"; static char rcsid[] = "$CVSid: @(#)log.c 1.44 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype log_dirproc PROTO((char *dir, char *repository, char *update_dir));
static Dtype log_dirproc (char *dir, char *repository, char *update_dir); static int log_fileproc PROTO((char *file, char *update_dir, char *repository,
static int log_fileproc (char *file, char *update_dir, char *repository, List * entries, List * srcfiles));
List * entries, List * srcfiles);
#else
static int log_fileproc ();
static Dtype log_dirproc ();
#endif /* __STDC__ */
static char options[PATH_MAX]; static char options[PATH_MAX];
@ -76,7 +72,7 @@ cvslog (argc, argv)
err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc, err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
(int (*) ()) NULL, argc, argv, local, (int (*) ()) NULL, argc, argv, local,
W_LOCAL | W_REPOS | W_ATTIC, 0, 1, W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
(char *) NULL, 1); (char *) NULL, 1, 0);
return (err); return (err);
} }
@ -99,8 +95,25 @@ log_fileproc (file, update_dir, repository, entries, srcfiles)
p = findnode (srcfiles, file); p = findnode (srcfiles, file);
if (p == NULL || (rcsfile = (RCSNode *) p->data) == NULL) if (p == NULL || (rcsfile = (RCSNode *) p->data) == NULL)
{ {
/* no rcs file. What *do* we know about this file? */
p = findnode (entries, file);
if (p != NULL)
{
Entnode *e;
e = (Entnode *) p->data;
if (e->version[0] == '0' || e->version[1] == '\0')
{
if (!really_quiet)
error (0, 0, "%s has been added, but not committed",
file);
return(0);
}
}
if (!really_quiet) if (!really_quiet)
error (0, 0, "nothing known about %s", file); error (0, 0, "nothing known about %s", file);
return (1); return (1);
} }

View File

@ -3,36 +3,34 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)logmsg.c 1.40 92/04/10"; static char rcsid[] = "$CVSid: @(#)logmsg.c 1.48 94/09/29 $";
USE(rcsid)
#endif #endif
#if __STDC__ /* this is slightly dangerous, since it could conflict with other systems'
static int find_type (Node * p); * own prototype.
static int fmt_proc (Node * p); */
static int logfile_write (char *repository, char *filter, char *title, #if 0
/* Which is why I'll nuke this */
extern int gethostname PROTO((char *name, int len));
#endif
static int find_type PROTO((Node * p, void *closure));
static int fmt_proc PROTO((Node * p, void *closure));
static int logfile_write PROTO((char *repository, char *filter, char *title,
char *message, char *revision, FILE * logfp, char *message, char *revision, FILE * logfp,
List * changes); List * changes));
static int rcsinfo_proc (char *repository, char *template); static int rcsinfo_proc PROTO((char *repository, char *template));
static int title_proc (Node * p); static int title_proc PROTO((Node * p, void *closure));
static int update_logfile_proc (char *repository, char *filter); static int update_logfile_proc PROTO((char *repository, char *filter));
static void setup_tmpfile (FILE * xfp, char *xprefix, List * changes); static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes));
static int editinfo_proc (char *repository, char *template); static int editinfo_proc PROTO((char *repository, char *template));
#else
static void setup_tmpfile ();
static int find_type ();
static int fmt_proc ();
static int rcsinfo_proc ();
static int update_logfile_proc ();
static int title_proc ();
static int logfile_write ();
static int editinfo_proc ();
#endif /* __STDC__ */
static FILE *fp; static FILE *fp;
static char *strlist; static char *strlist;
@ -42,8 +40,7 @@ static Ctype type;
/* /*
* Puts a standard header on the output which is either being prepared for an * Puts a standard header on the output which is either being prepared for an
* editor session, or being sent to a logfile program. The modified, added, * editor session, or being sent to a logfile program. The modified, added,
* and removed files are included (if any) and formatted to look pretty. * and removed files are included (if any) and formatted to look pretty. */
*/
static char *prefix; static char *prefix;
static int col; static int col;
static void static void
@ -57,30 +54,30 @@ setup_tmpfile (xfp, xprefix, changes)
prefix = xprefix; prefix = xprefix;
type = T_MODIFIED; type = T_MODIFIED;
if (walklist (changes, find_type) != 0) if (walklist (changes, find_type, NULL) != 0)
{ {
(void) fprintf (fp, "%sModified Files:\n", prefix); (void) fprintf (fp, "%sModified Files:\n", prefix);
(void) fprintf (fp, "%s\t", prefix); (void) fprintf (fp, "%s\t", prefix);
col = 8; col = 8;
(void) walklist (changes, fmt_proc); (void) walklist (changes, fmt_proc, NULL);
(void) fprintf (fp, "\n"); (void) fprintf (fp, "\n");
} }
type = T_ADDED; type = T_ADDED;
if (walklist (changes, find_type) != 0) if (walklist (changes, find_type, NULL) != 0)
{ {
(void) fprintf (fp, "%sAdded Files:\n", prefix); (void) fprintf (fp, "%sAdded Files:\n", prefix);
(void) fprintf (fp, "%s\t", prefix); (void) fprintf (fp, "%s\t", prefix);
col = 8; col = 8;
(void) walklist (changes, fmt_proc); (void) walklist (changes, fmt_proc, NULL);
(void) fprintf (fp, "\n"); (void) fprintf (fp, "\n");
} }
type = T_REMOVED; type = T_REMOVED;
if (walklist (changes, find_type) != 0) if (walklist (changes, find_type, NULL) != 0)
{ {
(void) fprintf (fp, "%sRemoved Files:\n", prefix); (void) fprintf (fp, "%sRemoved Files:\n", prefix);
(void) fprintf (fp, "%s\t", prefix); (void) fprintf (fp, "%s\t", prefix);
col = 8; col = 8;
(void) walklist (changes, fmt_proc); (void) walklist (changes, fmt_proc, NULL);
(void) fprintf (fp, "\n"); (void) fprintf (fp, "\n");
} }
} }
@ -89,8 +86,9 @@ setup_tmpfile (xfp, xprefix, changes)
* Looks for nodes of a specified type and returns 1 if found * Looks for nodes of a specified type and returns 1 if found
*/ */
static int static int
find_type (p) find_type (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (p->data == (char *) type) if (p->data == (char *) type)
return (1); return (1);
@ -104,8 +102,9 @@ find_type (p)
* match the one we're looking for * match the one we're looking for
*/ */
static int static int
fmt_proc (p) fmt_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (p->data == (char *) type) if (p->data == (char *) type)
{ {
@ -131,41 +130,40 @@ fmt_proc (p)
* *
*/ */
void void
do_editor (dir, message, repository, changes) do_editor (dir, messagep, repository, changes)
char *dir; char *dir;
char *message; char **messagep;
char *repository; char *repository;
List *changes; List *changes;
{ {
static int reuse_log_message = 0; static int reuse_log_message = 0;
char line[MAXLINELEN], fname[L_tmpnam+1]; char line[MAXLINELEN], fname[L_tmpnam+1];
char *orig_message;
struct stat pre_stbuf, post_stbuf; struct stat pre_stbuf, post_stbuf;
int retcode = 0; int retcode = 0;
char *p;
if (noexec || reuse_log_message) if (noexec || reuse_log_message)
return; return;
orig_message = xstrdup (message); /* save it for later */
/* Create a temporary file */ /* Create a temporary file */
(void) tmpnam (fname); (void) tmpnam (fname);
again: again:
if ((fp = fopen (fname, "w+")) == NULL) if ((fp = fopen (fname, "w+")) == NULL)
error (1, 0, "cannot create temporary file %s", fname); error (1, 0, "cannot create temporary file %s", fname);
/* set up the file so that the first line is blank if no msg specified */ if (*messagep)
if (*orig_message)
{ {
(void) fprintf (fp, "%s", orig_message); (void) fprintf (fp, "%s", *messagep);
if (orig_message[strlen (orig_message) - 1] != '\n')
if ((*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "\n"); (void) fprintf (fp, "\n");
} }
else else
(void) fprintf (fp, "\n"); (void) fprintf (fp, "\n");
/* tack templates on if necessary */ if (repository != NULL)
(void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc, 1); /* tack templates on if necessary */
(void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc, 1);
(void) fprintf (fp, (void) fprintf (fp,
"%s----------------------------------------------------------------------\n", "%s----------------------------------------------------------------------\n",
@ -176,7 +174,8 @@ do_editor (dir, message, repository, changes)
if (dir != NULL) if (dir != NULL)
(void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX, (void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
dir, CVSEDITPREFIX); dir, CVSEDITPREFIX);
setup_tmpfile (fp, CVSEDITPREFIX, changes); if (changes != NULL)
setup_tmpfile (fp, CVSEDITPREFIX, changes);
(void) fprintf (fp, (void) fprintf (fp,
"%s----------------------------------------------------------------------\n", "%s----------------------------------------------------------------------\n",
CVSEDITPREFIX); CVSEDITPREFIX);
@ -189,7 +188,8 @@ do_editor (dir, message, repository, changes)
if (editinfo_editor) if (editinfo_editor)
free (editinfo_editor); free (editinfo_editor);
editinfo_editor = (char *) NULL; editinfo_editor = (char *) NULL;
(void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0); if (repository != NULL)
(void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0);
/* run the editor */ /* run the editor */
run_setup ("%s", editinfo_editor ? editinfo_editor : Editor); run_setup ("%s", editinfo_editor ? editinfo_editor : Editor);
@ -200,29 +200,47 @@ do_editor (dir, message, repository, changes)
editinfo_editor ? "Logfile verification failed" : editinfo_editor ? "Logfile verification failed" :
"warning: editor session failed"); "warning: editor session failed");
/* put the entire message back into the message variable */ /* put the entire message back into the *messagep variable */
fp = open_file (fname, "r"); fp = open_file (fname, "r");
*message = '\0';
while (fgets (line, sizeof (line), fp) != NULL) if (*messagep)
free (*messagep);
if (stat (fname, &post_stbuf) != 0)
error (1, errno, "cannot find size of temp file %s", fname);
if (post_stbuf.st_size == 0)
*messagep = NULL;
else
{ {
if (strncmp (line, CVSEDITPREFIX, sizeof (CVSEDITPREFIX) - 1) == 0) *messagep = (char *) xmalloc (post_stbuf.st_size);
continue; *messagep[0] = '\0';
if (((int) strlen (message) + (int) strlen (line)) >= MAXMESGLEN) }
/* !!! XXX FIXME: fgets is broken. This should not have any line
length limits. */
if (*messagep)
{
p = *messagep;
while (fgets (line, sizeof (line), fp) != NULL)
{ {
error (0, 0, "warning: log message truncated!"); if (strncmp (line, CVSEDITPREFIX, sizeof (CVSEDITPREFIX) - 1) == 0)
break; continue;
(void) strcpy (p, line);
p += strlen (line);
} }
(void) strcat (message, line);
} }
(void) fclose (fp); (void) fclose (fp);
if ((stat (fname, &post_stbuf) == 0 && if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
pre_stbuf.st_mtime == post_stbuf.st_mtime) || *messagep == NULL ||
(*message == '\0' || strcmp (message, "\n") == 0)) strcmp (*messagep, "\n") == 0)
{ {
for (;;) for (;;)
{ {
(void) printf ("\nLog message unchanged or not specified\n"); (void) printf ("\nLog message unchanged or not specified\n");
(void) printf ("a)bort, c)continue, e)dit, !)reuse this message unchanged for remaining dirs\n"); (void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
(void) printf ("Action: (continue) "); (void) printf ("Action: (continue) ");
(void) fflush (stdout); (void) fflush (stdout);
*line = '\0'; *line = '\0';
@ -241,7 +259,6 @@ do_editor (dir, message, repository, changes)
(void) printf ("Unknown input\n"); (void) printf ("Unknown input\n");
} }
} }
free (orig_message);
(void) unlink_file (fname); (void) unlink_file (fname);
} }
@ -303,6 +320,10 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
{ {
char *srepos; char *srepos;
/* nothing to do if the list is empty */
if (xchanges == NULL || xchanges->list->next == xchanges->list)
return;
/* set up static vars for update_logfile_proc */ /* set up static vars for update_logfile_proc */
message = xmessage; message = xmessage;
revision = xrevision; revision = xrevision;
@ -318,13 +339,13 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
strlist[0] = '\0'; strlist[0] = '\0';
type = T_TITLE; type = T_TITLE;
(void) walklist (changes, title_proc); (void) walklist (changes, title_proc, NULL);
type = T_ADDED; type = T_ADDED;
(void) walklist (changes, title_proc); (void) walklist (changes, title_proc, NULL);
type = T_MODIFIED; type = T_MODIFIED;
(void) walklist (changes, title_proc); (void) walklist (changes, title_proc, NULL);
type = T_REMOVED; type = T_REMOVED;
(void) walklist (changes, title_proc); (void) walklist (changes, title_proc, NULL);
title = xmalloc (strlen (srepos) + strlen (strlist) + 1 + 2); /* for 's */ title = xmalloc (strlen (srepos) + strlen (strlist) + 1 + 2); /* for 's */
(void) sprintf (title, "'%s%s'", srepos, strlist); (void) sprintf (title, "'%s%s'", srepos, strlist);
@ -355,8 +376,9 @@ update_logfile_proc (repository, filter)
* concatenate each name onto strlist * concatenate each name onto strlist
*/ */
static int static int
title_proc (p) title_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (p->data == (char *) type) if (p->data == (char *) type)
{ {

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License * You may distribute under the terms of the GNU General Public License
* as specified in the README file that comes with the CVS 1.3 kit. * as specified in the README file that comes with the CVS 1.4 kit.
* *
* This is the main C driver for the CVS system. * This is the main C driver for the CVS system.
* *
@ -35,7 +35,10 @@
#include "cvs.h" #include "cvs.h"
#include "patchlevel.h" #include "patchlevel.h"
char rcsid[] = "@(#)main.c 1.64 92/03/31\n"; #ifndef lint
char rcsid[] = "$CVSid: @(#)main.c 1.78 94/10/07 $\n";
USE(rcsid)
#endif
extern char *getenv (); extern char *getenv ();
@ -43,6 +46,7 @@ char *program_name;
char *command_name = ""; char *command_name = "";
int use_editor = TRUE; int use_editor = TRUE;
int use_cvsrc = TRUE;
int cvswrite = !CVSREAD_DFLT; int cvswrite = !CVSREAD_DFLT;
int really_quiet = FALSE; int really_quiet = FALSE;
int quiet = FALSE; int quiet = FALSE;
@ -58,40 +62,28 @@ char *CurDir;
char *Rcsbin = RCSBIN_DFLT; char *Rcsbin = RCSBIN_DFLT;
char *Editor = EDITOR_DFLT; char *Editor = EDITOR_DFLT;
char *CVSroot = CVSROOT_DFLT; char *CVSroot = CVSROOT_DFLT;
#ifdef CVSADM_ROOT
/*
* The path found in CVS/Root must match $CVSROOT and/or 'cvs -d root'
*/
char *CVSADM_Root = CVSROOT_DFLT;
#endif /* CVSADM_ROOT */
#if __STDC__ int add PROTO((int argc, char **argv));
int add (int argc, char **argv); int admin PROTO((int argc, char **argv));
int admin (int argc, char **argv); int checkout PROTO((int argc, char **argv));
int checkout (int argc, char **argv); int commit PROTO((int argc, char **argv));
int commit (int argc, char **argv); int diff PROTO((int argc, char **argv));
int diff (int argc, char **argv); int history PROTO((int argc, char **argv));
int history (int argc, char **argv); int import PROTO((int argc, char **argv));
int import (int argc, char **argv); int cvslog PROTO((int argc, char **argv));
int cvslog (int argc, char **argv); int patch PROTO((int argc, char **argv));
int patch (int argc, char **argv); int release PROTO((int argc, char **argv));
int release (int argc, char **argv); int cvsremove PROTO((int argc, char **argv));
int cvsremove (int argc, char **argv); int rtag PROTO((int argc, char **argv));
int rtag (int argc, char **argv); int status PROTO((int argc, char **argv));
int status (int argc, char **argv); int tag PROTO((int argc, char **argv));
int tag (int argc, char **argv); int update PROTO((int argc, char **argv));
int update (int argc, char **argv);
#else
int add ();
int admin ();
int checkout ();
int commit ();
int diff ();
int history ();
int import ();
int cvslog ();
int patch ();
int release ();
int cvsremove ();
int rtag ();
int status ();
int tag ();
int update ();
#endif /* __STDC__ */
struct cmd struct cmd
{ {
@ -137,6 +129,7 @@ static char *usg[] =
" -b bindir Find RCS programs in 'bindir'\n", " -b bindir Find RCS programs in 'bindir'\n",
" -e editor Use 'editor' for editing log information\n", " -e editor Use 'editor' for editing log information\n",
" -d CVS_root Overrides $CVSROOT as the root of the CVS tree\n", " -d CVS_root Overrides $CVSROOT as the root of the CVS tree\n",
" -f Do not use the ~/.cvsrc file\n",
"\n", "\n",
" and where 'command' is:\n", " and where 'command' is:\n",
" add Adds a new file/directory to the repository\n", " add Adds a new file/directory to the repository\n",
@ -158,7 +151,7 @@ static char *usg[] =
NULL, NULL,
}; };
static SIGTYPE static RETSIGTYPE
main_cleanup () main_cleanup ()
{ {
exit (1); exit (1);
@ -173,13 +166,13 @@ main (argc, argv)
char *cp; char *cp;
struct cmd *cm; struct cmd *cm;
int c, help = FALSE, err = 0; int c, help = FALSE, err = 0;
int rcsbin_update_env, cvs_update_env; int rcsbin_update_env, cvs_update_env = 0;
char tmp[PATH_MAX]; char tmp[PATH_MAX];
/* /*
* Just save the last component of the path for error messages * Just save the last component of the path for error messages
*/ */
if ((program_name = rindex (argv[0], '/')) == NULL) if ((program_name = strrchr (argv[0], '/')) == NULL)
program_name = argv[0]; program_name = argv[0];
else else
program_name++; program_name++;
@ -193,12 +186,15 @@ main (argc, argv)
* they can be overridden by command line arguments * they can be overridden by command line arguments
*/ */
rcsbin_update_env = *Rcsbin; /* RCSBIN_DFLT must be set */ rcsbin_update_env = *Rcsbin; /* RCSBIN_DFLT must be set */
cvs_update_env = 0;
if ((cp = getenv (RCSBIN_ENV)) != NULL) if ((cp = getenv (RCSBIN_ENV)) != NULL)
{ {
Rcsbin = cp; Rcsbin = cp;
rcsbin_update_env = 0; /* it's already there */ rcsbin_update_env = 0; /* it's already there */
} }
if ((cp = getenv (EDITOR_ENV)) != NULL) if ((cp = getenv (EDITOR1_ENV)) != NULL)
Editor = cp;
else if ((cp = getenv (EDITOR2_ENV)) != NULL)
Editor = cp; Editor = cp;
if ((cp = getenv (CVSROOT_ENV)) != NULL) if ((cp = getenv (CVSROOT_ENV)) != NULL)
{ {
@ -209,7 +205,7 @@ main (argc, argv)
cvswrite = FALSE; cvswrite = FALSE;
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "Qqrwtnlvb:e:d:H")) != -1) while ((c = getopt (argc, argv, "Qqrwtnlvb:e:d:Hf")) != -1)
{ {
switch (c) switch (c)
{ {
@ -234,11 +230,10 @@ main (argc, argv)
logoff = TRUE; logoff = TRUE;
break; break;
case 'v': case 'v':
(void) fputs (rcsid, stdout);
(void) fputs (version_string, stdout); (void) fputs (version_string, stdout);
(void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL); (void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL);
(void) fputs (tmp, stdout); (void) fputs (tmp, stdout);
(void) fputs ("\nCopyright (c) 1992, Brian Berliner and Jeff Polk\nCopyright (c) 1989-1992, Brian Berliner\n\nCVS may be copied only under the terms of the GNU General Public License,\na copy of which can be found with the CVS 1.3 distribution kit.\n", stdout); (void) fputs ("\nCopyright (c) 1993-1994 Brian Berliner\nCopyright (c) 1993-1994 david d `zoo' zuhn\nCopyright (c) 1992, Brian Berliner and Jeff Polk\nCopyright (c) 1989-1992, Brian Berliner\n\nCVS may be copied only under the terms of the GNU General Public License,\na copy of which can be found with the CVS distribution kit.\n", stdout);
exit (0); exit (0);
break; break;
case 'b': case 'b':
@ -253,8 +248,12 @@ main (argc, argv)
cvs_update_env = 1; /* need to update environment */ cvs_update_env = 1; /* need to update environment */
break; break;
case 'H': case 'H':
use_cvsrc = FALSE; /* this ensure that cvs -H works */
help = TRUE; help = TRUE;
break; break;
case 'f':
use_cvsrc = FALSE;
break;
case '?': case '?':
default: default:
usage (usg); usage (usg);
@ -265,25 +264,49 @@ main (argc, argv)
if (argc < 1) if (argc < 1)
usage (usg); usage (usg);
#ifdef CVSADM_ROOT
/* /*
* XXX - Compatibility. This can be removed in the release after CVS 1.3. * See if we are able to find a 'better' value for CVSroot in the
* Try to rename the CVSROOT.adm file to CVSROOT, unless there already is * CVSADM_ROOT directory.
* a CVSROOT directory.
*/ */
if (CVSroot != NULL) CVSADM_Root = Name_Root((char *) NULL, (char *) NULL);
if (CVSADM_Root != NULL)
{ {
char rootadm[PATH_MAX]; if (CVSroot == NULL)
char orootadm[PATH_MAX]; {
CVSroot = CVSADM_Root;
(void) sprintf (rootadm, "%s/%s", CVSroot, CVSROOTADM); cvs_update_env = 1; /* need to update environment */
if (!isdir (rootadm)) }
{ else
(void) sprintf (orootadm, "%s/%s", CVSroot, OCVSROOTADM); {
if (isdir (orootadm)) /*
(void) rename (orootadm, rootadm); * Now for the hard part, compare the two directories. If they
} * are not identical, then abort this command.
strip_path (CVSroot); */
if ((strcmp (CVSroot, CVSADM_Root) != 0) &&
!same_directories(CVSroot, CVSADM_Root))
{
error (0, 0, "%s value for CVS Root found in %s",
CVSADM_Root, CVSADM_ROOT);
if (cvs_update_env)
{
error (0, 0, "does not match command line -d %s setting",
CVSroot);
error (1, 0,
"you may wish to try the cvs command again without the -d option ");
}
else
{
error (0, 0,
"does not match CVSROOT environment value of %s",
CVSroot);
error (1, 0,
"you may wish to unsetenv CVSROOT and try again");
}
}
}
} }
#endif /* CVSADM_ROOT */
/* /*
* Specifying just the '-H' flag to the sub-command causes a Usage * Specifying just the '-H' flag to the sub-command causes a Usage
@ -326,7 +349,7 @@ main (argc, argv)
} }
} }
#ifndef PUTENV_MISSING #ifdef HAVE_PUTENV
/* Now, see if we should update the environment with the Rcsbin value */ /* Now, see if we should update the environment with the Rcsbin value */
if (cvs_update_env) if (cvs_update_env)
{ {
@ -387,7 +410,7 @@ main (argc, argv)
(void) SIG_register (SIGPIPE, main_cleanup); (void) SIG_register (SIGPIPE, main_cleanup);
(void) SIG_register (SIGTERM, main_cleanup); (void) SIG_register (SIGTERM, main_cleanup);
#ifndef SETVBUF_MISSING #ifdef HAVE_SETVBUF
/* /*
* Make stdout line buffered, so 'tail -f' can monitor progress. * Make stdout line buffered, so 'tail -f' can monitor progress.
* Patch creates too much output to monitor and it runs slowly. * Patch creates too much output to monitor and it runs slowly.
@ -396,7 +419,11 @@ main (argc, argv)
(void) setvbuf (stdout, (char *) NULL, _IOLBF, 0); (void) setvbuf (stdout, (char *) NULL, _IOLBF, 0);
#endif #endif
if (use_cvsrc)
read_cvsrc(&argc, &argv);
err = (*(cm->func)) (argc, argv); err = (*(cm->func)) (argc, argv);
} }
/* /*
* If the command's error count is modulo 256, we need to change it * If the command's error count is modulo 256, we need to change it

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License * You may distribute under the terms of the GNU General Public License
* as specified in the README file that comes with the CVS 1.3 kit. * as specified in the README file that comes with the CVS 1.4 kit.
* *
* Modules * Modules
* *
@ -23,7 +23,8 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)modules.c 1.57 92/04/10"; static char rcsid[] = "$CVSid: @(#)modules.c 1.62 94/09/29 $";
USE(rcsid)
#endif #endif
struct sortrec struct sortrec
@ -34,13 +35,8 @@ struct sortrec
char *comment; char *comment;
}; };
#if __STDC__ static int sort_order PROTO((CONST PTR l, CONST PTR r));
static int sort_order (CONST PTR l, CONST PTR r); static void save_d PROTO((char *k, int ks, char *d, int ds));
static void save_d (char *k, int ks, char *d, int ds);
#else
static int sort_order ();
static void save_d ();
#endif /* __STDC__ */
/* /*
@ -117,6 +113,13 @@ do_module (db, mname, m_type, msg, callback_proc, where,
if (getwd (cwd) == NULL) if (getwd (cwd) == NULL)
error (1, 0, "cannot get current working directory: %s", cwd); error (1, 0, "cannot get current working directory: %s", cwd);
/* if this is a directory to ignore, add it to that list */
if (mname[0] == '!' && mname[1] != '\0')
{
ign_dir_add (mname+1);
return(err);
}
/* strip extra stuff from the module name */ /* strip extra stuff from the module name */
strip_path (mname); strip_path (mname);
@ -142,12 +145,20 @@ do_module (db, mname, m_type, msg, callback_proc, where,
val.dptr[val.dsize] = '\0'; val.dptr[val.dsize] = '\0';
/* If the line ends in a comment, strip it off */ /* If the line ends in a comment, strip it off */
if ((cp = index (val.dptr, '#')) != NULL) if ((cp = strchr (val.dptr, '#')) != NULL)
{ {
do do
*cp-- = '\0'; *cp-- = '\0';
while (isspace (*cp)); while (isspace (*cp));
} }
else
{
/* Always strip trailing spaces */
cp = strchr (val.dptr, '\0');
while (cp > val.dptr && isspace(*--cp))
*cp = '\0';
}
value = val.dptr; value = val.dptr;
mwhere = xstrdup (mname); mwhere = xstrdup (mname);
goto found; goto found;
@ -161,7 +172,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
/* check to see if mname is a directory or file */ /* check to see if mname is a directory or file */
(void) sprintf (file, "%s/%s", CVSroot, mname); (void) sprintf (file, "%s/%s", CVSroot, mname);
if ((acp = rindex (mname, '/')) != NULL) if ((acp = strrchr (mname, '/')) != NULL)
{ {
*acp = '\0'; *acp = '\0';
(void) sprintf (attic_file, "%s/%s/%s/%s%s", CVSroot, mname, (void) sprintf (attic_file, "%s/%s/%s/%s%s", CVSroot, mname,
@ -183,13 +194,13 @@ do_module (db, mname, m_type, msg, callback_proc, where,
if (isfile (file) || isfile (attic_file)) if (isfile (file) || isfile (attic_file))
{ {
/* if mname was a file, we have to split it into "dir file" */ /* if mname was a file, we have to split it into "dir file" */
if ((cp = rindex (mname, '/')) != NULL && cp != mname) if ((cp = strrchr (mname, '/')) != NULL && cp != mname)
{ {
char *slashp; char *slashp;
/* put the ' ' in a copy so we don't mess up the original */ /* put the ' ' in a copy so we don't mess up the original */
value = strcpy (xvalue, mname); value = strcpy (xvalue, mname);
slashp = rindex (value, '/'); slashp = strrchr (value, '/');
*slashp = ' '; *slashp = ' ';
} }
else else
@ -218,7 +229,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
} }
/* look up everything to the first / as a module */ /* look up everything to the first / as a module */
if (mname[0] != '/' && (cp = index (mname, '/')) != NULL) if (mname[0] != '/' && (cp = strchr (mname, '/')) != NULL)
{ {
/* Make the slash the new end of the string temporarily */ /* Make the slash the new end of the string temporarily */
*cp = '\0'; *cp = '\0';
@ -240,7 +251,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
val.dptr[val.dsize] = '\0'; val.dptr[val.dsize] = '\0';
/* If the line ends in a comment, strip it off */ /* If the line ends in a comment, strip it off */
if ((cp2 = index (val.dptr, '#')) != NULL) if ((cp2 = strchr (val.dptr, '#')) != NULL)
{ {
do do
*cp2-- = '\0'; *cp2-- = '\0';
@ -282,7 +293,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
value = zvalue; value = zvalue;
/* search the value for the special delimiter and save for later */ /* search the value for the special delimiter and save for later */
if ((cp = index (value, CVSMODULE_SPEC)) != NULL) if ((cp = strchr (value, CVSMODULE_SPEC)) != NULL)
{ {
*cp = '\0'; /* null out the special char */ *cp = '\0'; /* null out the special char */
spec_opt = cp + 1; /* save the options for later */ spec_opt = cp + 1; /* save the options for later */
@ -326,6 +337,9 @@ do_module (db, mname, m_type, msg, callback_proc, where,
CVSROOTADM, CVSNULLREPOS); CVSROOTADM, CVSNULLREPOS);
if (!isfile (nullrepos)) if (!isfile (nullrepos))
(void) mkdir (nullrepos, 0777); (void) mkdir (nullrepos, 0777);
if (!isdir (nullrepos))
error (1, 0, "there is no repository %s", nullrepos);
Create_Admin (".", nullrepos, (char *) NULL, (char *) NULL); Create_Admin (".", nullrepos, (char *) NULL, (char *) NULL);
if (!noexec) if (!noexec)
{ {
@ -363,7 +377,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
/* parse the args */ /* parse the args */
optind = 1; optind = 1;
while ((c = gnu_getopt (modargc, modargv, CVSMODULE_OPTS)) != -1) while ((c = getopt (modargc, modargv, CVSMODULE_OPTS)) != -1)
{ {
switch (c) switch (c)
{ {
@ -417,9 +431,16 @@ do_module (db, mname, m_type, msg, callback_proc, where,
int i; int i;
for (i = 0; i < modargc; i++) for (i = 0; i < modargc; i++)
err += do_module (db, modargv[i], m_type, msg, callback_proc, {
where, shorten, local_specified, if (strcmp (mname, modargv[i]) == 0)
run_module_prog, extra_arg); error (0, 0,
"module `%s' in modules file contains infinite loop",
mname);
else
err += do_module (db, modargv[i], m_type, msg, callback_proc,
where, shorten, local_specified,
run_module_prog, extra_arg);
}
if (mwhere) if (mwhere)
free (mwhere); free (mwhere);
free (zvalue); free (zvalue);
@ -445,7 +466,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
{ {
char *next_opt; char *next_opt;
cp = index (spec_opt, CVSMODULE_SPEC); cp = strchr (spec_opt, CVSMODULE_SPEC);
if (cp != NULL) if (cp != NULL)
{ {
/* save the beginning of the next arg */ /* save the beginning of the next arg */
@ -648,7 +669,7 @@ save_d (k, ks, d, ds)
s_rec->status = def_status; s_rec->status = def_status;
/* Minor kluge, but general enough to maintain */ /* Minor kluge, but general enough to maintain */
for (cp = s_rec->rest; (cp2 = index (cp, '-')) != NULL; cp = ++cp2) for (cp = s_rec->rest; (cp2 = strchr (cp, '-')) != NULL; cp = ++cp2)
{ {
if (*(cp2 + 1) == 's' && *(cp2 + 2) == ' ') if (*(cp2 + 1) == 's' && *(cp2 + 2) == ' ')
{ {
@ -665,7 +686,7 @@ save_d (k, ks, d, ds)
cp = s_rec->rest; cp = s_rec->rest;
/* Find comment field, clean up on all three sides & compress blanks */ /* Find comment field, clean up on all three sides & compress blanks */
if ((cp2 = cp = index (cp, '#')) != NULL) if ((cp2 = cp = strchr (cp, '#')) != NULL)
{ {
if (*--cp2 == ' ') if (*--cp2 == ' ')
*cp2 = '\0'; *cp2 = '\0';
@ -748,13 +769,13 @@ cat_module (status)
optind = 1; optind = 1;
wid = 0; wid = 0;
while ((c = gnu_getopt (argc, argv, CVSMODULE_OPTS)) != -1) while ((c = getopt (argc, argv, CVSMODULE_OPTS)) != -1)
{ {
if (!status) if (!status)
{ {
if (c == 'a') if (c == 'a' || c == 'l')
{ {
(void) printf (" -a"); (void) printf (" -%c", c);
wid += 3; /* Could just set it to 3 */ wid += 3; /* Could just set it to 3 */
} }
else else

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* No Difference * No Difference
* *
@ -17,14 +17,17 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)no_diff.c 1.35 92/03/31"; static char rcsid[] = "$CVSid: @(#)no_diff.c 1.39 94/10/07 $";
USE(rcsid)
#endif #endif
int int
No_Difference (file, vers, entries) No_Difference (file, vers, entries, repository, update_dir)
char *file; char *file;
Vers_TS *vers; Vers_TS *vers;
List *entries; List *entries;
char *repository;
char *update_dir;
{ {
Node *p; Node *p;
char tmp[L_tmpnam+1]; char tmp[L_tmpnam+1];
@ -58,7 +61,7 @@ No_Difference (file, vers, entries)
ts = time_stamp (file); ts = time_stamp (file);
Register (entries, file, Register (entries, file,
vers->vn_user ? vers->vn_user : vers->vn_rcs, ts, vers->vn_user ? vers->vn_user : vers->vn_rcs, ts,
options, vers->tag, vers->date); options, vers->tag, vers->date, (char *) 0);
free (ts); free (ts);
/* update the entdata pointer in the vers_ts structure */ /* update the entdata pointer in the vers_ts structure */
@ -72,14 +75,21 @@ No_Difference (file, vers, entries)
} }
else else
{ {
error (0, retcode == -1 ? errno : 0, if (update_dir[0] == '\0')
"could not check out revision %s of %s", vers->vn_user, file); error (0, retcode == -1 ? errno : 0,
"could not check out revision %s of %s",
vers->vn_user, file);
else
error (0, retcode == -1 ? errno : 0,
"could not check out revision %s of %s/%s",
vers->vn_user, update_dir, file);
ret = -1; /* different since we couldn't tell */ ret = -1; /* different since we couldn't tell */
} }
if (trace) if (trace)
(void) fprintf (stderr, "-> unlink(%s)\n", tmp); (void) fprintf (stderr, "-> unlink(%s)\n", tmp);
(void) unlink (tmp); if (unlink (tmp) < 0)
error (0, errno, "could not remove %s", tmp);
free (options); free (options);
return (ret); return (ret);
} }

View File

@ -3,13 +3,14 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)parseinfo.c 1.16 92/04/10"; static char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
USE(rcsid)
#endif #endif
/* /*
@ -87,7 +88,7 @@ Parse_Info (infofile, repository, callproc, all)
value = cp; value = cp;
/* strip the newline off the end of the value */ /* strip the newline off the end of the value */
if ((cp = rindex (value, '\n')) != NULL) if ((cp = strrchr (value, '\n')) != NULL)
*cp = '\0'; *cp = '\0';
/* /*

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Patch * Patch
* *
@ -15,24 +15,17 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)patch.c 1.50 92/04/10"; static char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static RETSIGTYPE patch_cleanup PROTO((void));
static SIGTYPE patch_cleanup (void); static Dtype patch_dirproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype patch_dirproc (char *dir, char *repos, char *update_dir); static int patch_fileproc PROTO((char *file, char *update_dir, char *repository,
static int patch_fileproc (char *file, char *update_dir, char *repository, List * entries, List * srcfiles));
List * entries, List * srcfiles); static int patch_proc PROTO((int *pargc, char *argv[], char *xwhere,
static int patch_proc (int *pargc, char *argv[], char *xwhere,
char *mwhere, char *mfile, int shorten, char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg); int local_specified, char *mname, char *msg));
#else
static int patch_proc ();
static int patch_fileproc ();
static Dtype patch_dirproc ();
static SIGTYPE patch_cleanup ();
#endif /* __STDC__ */
static int force_tag_match = 1; static int force_tag_match = 1;
static int patch_short = 0; static int patch_short = 0;
@ -77,7 +70,7 @@ patch (argc, argv)
usage (patch_usage); usage (patch_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "V:k:cuftsQqlRD:r:")) != -1) while ((c = getopt (argc, argv, "V:k:cuftsQqlRD:r:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -218,7 +211,7 @@ patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
char path[PATH_MAX]; char path[PATH_MAX];
/* if the portion of the module is a path, put the dir part on repos */ /* if the portion of the module is a path, put the dir part on repos */
if ((cp = rindex (mfile, '/')) != NULL) if ((cp = strrchr (mfile, '/')) != NULL)
{ {
*cp = '\0'; *cp = '\0';
(void) strcat (repository, "/"); (void) strcat (repository, "/");
@ -264,7 +257,7 @@ patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc, err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc,
(int (*) ()) NULL, *pargc - 1, argv + 1, local, (int (*) ()) NULL, *pargc - 1, argv + 1, local,
which, 0, 1, where, 1); which, 0, 1, where, 1, 1);
return (err); return (err);
} }
@ -282,6 +275,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
List *entries; List *entries;
List *srcfiles; List *srcfiles;
{ {
struct utimbuf t;
char *vers_tag, *vers_head; char *vers_tag, *vers_head;
char rcsspace[PATH_MAX]; char rcsspace[PATH_MAX];
char *rcs = rcsspace; char *rcs = rcsspace;
@ -296,7 +290,6 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
char *cp1, *cp2, *commap; char *cp1, *cp2, *commap;
FILE *fp; FILE *fp;
/* find the parsed rcs file */ /* find the parsed rcs file */
p = findnode (srcfiles, file); p = findnode (srcfiles, file);
if (p == NULL) if (p == NULL)
@ -374,6 +367,10 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
ret = 1; ret = 1;
goto out; goto out;
} }
memset ((char *) &t, 0, sizeof (t));
if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag,
(char *) 0, 0)) != -1)
(void) utime (tmpfile1, &t);
} }
else if (toptwo_diffs) else if (toptwo_diffs)
{ {
@ -392,6 +389,9 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
ret = 1; ret = 1;
goto out; goto out;
} }
if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head,
(char *) 0, 0)) != -1)
(void) utime (tmpfile2, &t);
} }
run_setup ("%s -%c", DIFF, unidiff ? 'u' : 'c'); run_setup ("%s -%c", DIFF, unidiff ? 'u' : 'c');
run_arg (tmpfile1); run_arg (tmpfile1);
@ -409,6 +409,15 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
* lines of the diff output file, and munge them to include more * lines of the diff output file, and munge them to include more
* reasonable file names that "patch" will understand. * reasonable file names that "patch" will understand.
*/ */
/* Output an "Index:" line for patch to use */
(void) fflush (stdout);
if (update_dir[0])
(void) printf ("Index: %s/%s\n", update_dir, file);
else
(void) printf ("Index: %s\n", file);
(void) fflush (stdout);
fp = open_file (tmpfile3, "r"); fp = open_file (tmpfile3, "r");
if (fgets (line1, sizeof (line1), fp) == NULL || if (fgets (line1, sizeof (line1), fp) == NULL ||
fgets (line2, sizeof (line2), fp) == NULL) fgets (line2, sizeof (line2), fp) == NULL)
@ -423,8 +432,8 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
if (strncmp (line1, "*** ", 4) != 0 || if (strncmp (line1, "*** ", 4) != 0 ||
strncmp (line2, "--- ", 4) != 0 || strncmp (line2, "--- ", 4) != 0 ||
(cp1 = index (line1, '\t')) == NULL || (cp1 = strchr (line1, '\t')) == NULL ||
(cp2 = index (line2, '\t')) == NULL) (cp2 = strchr (line2, '\t')) == NULL)
{ {
error (0, 0, "invalid diff header for %s", rcs); error (0, 0, "invalid diff header for %s", rcs);
ret = 1; ret = 1;
@ -436,8 +445,8 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
if (strncmp (line1, "--- ", 4) != 0 || if (strncmp (line1, "--- ", 4) != 0 ||
strncmp (line2, "+++ ", 4) != 0 || strncmp (line2, "+++ ", 4) != 0 ||
(cp1 = index (line1, '\t')) == NULL || (cp1 = strchr (line1, '\t')) == NULL ||
(cp2 = index (line2, '\t')) == NULL) (cp2 = strchr (line2, '\t')) == NULL)
{ {
error (0, 0, "invalid unidiff header for %s", rcs); error (0, 0, "invalid unidiff header for %s", rcs);
ret = 1; ret = 1;
@ -451,7 +460,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
(void) strcpy (strippath, REPOS_STRIP); (void) strcpy (strippath, REPOS_STRIP);
if (strncmp (rcs, strippath, strlen (strippath)) == 0) if (strncmp (rcs, strippath, strlen (strippath)) == 0)
rcs += strlen (strippath); rcs += strlen (strippath);
commap = rindex (rcs, ','); commap = strrchr (rcs, ',');
*commap = '\0'; *commap = '\0';
if (vers_tag != NULL) if (vers_tag != NULL)
{ {
@ -511,7 +520,7 @@ patch_dirproc (dir, repos, update_dir)
/* /*
* Clean up temporary files * Clean up temporary files
*/ */
static SIGTYPE static RETSIGTYPE
patch_cleanup () patch_cleanup ()
{ {
if (tmpfile1[0] != '\0') if (tmpfile1[0] != '\0')

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* The routines contained in this file do all the rcs file parsing and * The routines contained in this file do all the rcs file parsing and
* manipulation * manipulation
@ -11,36 +11,53 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)rcs.c 1.28 92/03/31"; static char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, char *rcsfile));
static char *RCS_getbranch (RCSNode * rcs, char *tag, int force_tag_match); static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
static char *RCS_getdatebranch (RCSNode * rcs, char *date, char *branch); static int getrcskey PROTO((FILE * fp, char **keyp, char **valp));
static int getrcskey (FILE * fp, char **keyp, char **valp); static int parse_rcs_proc PROTO((Node * file, void *closure));
static int parse_rcs_proc (Node * file); static int checkmagic_proc PROTO((Node *p, void *closure));
static int checkmagic_proc (Node *p); static void do_branches PROTO((List * list, char *val));
static void do_branches (List * list, char *val); static void do_symbols PROTO((List * list, char *val));
static void do_symbols (List * list, char *val); static void null_delproc PROTO((Node * p));
static void null_delproc (Node * p); static void rcsnode_delproc PROTO((Node * p));
static void rcsnode_delproc (Node * p); static void rcsvers_delproc PROTO((Node * p));
static void rcsvers_delproc (Node * p);
#else
static int parse_rcs_proc ();
static int checkmagic_proc ();
static void rcsnode_delproc ();
static void rcsvers_delproc ();
static void null_delproc ();
static int getrcskey ();
static void do_symbols ();
static void do_branches ();
static char *RCS_getbranch ();
static char *RCS_getdatebranch ();
#endif /* __STDC__ */
static List *rcslist; static List *rcslist;
static char *repository; static char *repository;
/*
* We don't want to use isspace() from the C library because:
*
* 1. The definition of "whitespace" in RCS files includes ASCII
* backspace, but the C locale doesn't.
* 2. isspace is an very expensive function call in some implementations
* due to the addition of wide character support.
*/
static const char spacetab[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x00 - 0x0f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
};
#define whitespace(c) (spacetab[c] != 0)
/* /*
* Parse all the rcs files specified and return a list * Parse all the rcs files specified and return a list
*/ */
@ -54,7 +71,7 @@ RCS_parsefiles (files, xrepos)
rcslist = getlist (); rcslist = getlist ();
/* walk the list parsing files */ /* walk the list parsing files */
if (walklist (files, parse_rcs_proc) != 0) if (walklist (files, parse_rcs_proc, NULL) != 0)
{ {
/* free the list and return NULL on error */ /* free the list and return NULL on error */
dellist (&rcslist); dellist (&rcslist);
@ -69,10 +86,10 @@ RCS_parsefiles (files, xrepos)
* Parse an rcs file into a node on the rcs list * Parse an rcs file into a node on the rcs list
*/ */
static int static int
parse_rcs_proc (file) parse_rcs_proc (file, closure)
Node *file; Node *file;
void *closure;
{ {
Node *p;
RCSNode *rdata; RCSNode *rdata;
/* parse the rcs file into rdata */ /* parse the rcs file into rdata */
@ -80,17 +97,32 @@ parse_rcs_proc (file)
/* if we got a valid RCSNode back, put it on the list */ /* if we got a valid RCSNode back, put it on the list */
if (rdata != (RCSNode *) NULL) if (rdata != (RCSNode *) NULL)
{ RCS_addnode (file->key, rdata, rcslist);
p = getnode ();
p->key = xstrdup (file->key);
p->delproc = rcsnode_delproc;
p->type = RCSNODE;
p->data = (char *) rdata;
(void) addnode (rcslist, p);
}
return (0); return (0);
} }
/*
* Add an RCSNode to a list of them.
*/
void
RCS_addnode (file, rcs, list)
char *file;
RCSNode *rcs;
List *list;
{
Node *p;
p = getnode ();
p->key = xstrdup (file);
p->delproc = rcsnode_delproc;
p->type = RCSNODE;
p->data = (char *) rcs;
(void) addnode (list, p);
}
/* /*
* Parse an rcsfile given a user file name and a repository * Parse an rcsfile given a user file name and a repository
*/ */
@ -100,43 +132,46 @@ RCS_parse (file, repos)
char *repos; char *repos;
{ {
RCSNode *rcs; RCSNode *rcs;
FILE *fp;
char rcsfile[PATH_MAX]; char rcsfile[PATH_MAX];
(void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT); (void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
if (!isreadable (rcsfile)) if ((fp = fopen (rcsfile, "r")) != NULL)
{ {
(void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, rcs = RCS_parsercsfile_i(fp, rcsfile);
file, RCSEXT); if (rcs != NULL)
if (!isreadable (rcsfile)) rcs->flags |= VALID;
return (NULL);
rcs = RCS_parsercsfile (rcsfile); fclose (fp);
return (rcs);
}
(void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
if ((fp = fopen (rcsfile, "r")) != NULL)
{
rcs = RCS_parsercsfile_i(fp, rcsfile);
if (rcs != NULL) if (rcs != NULL)
{ {
rcs->flags |= INATTIC; rcs->flags |= INATTIC;
rcs->flags |= VALID; rcs->flags |= VALID;
} }
fclose (fp);
return (rcs); return (rcs);
} }
rcs = RCS_parsercsfile (rcsfile);
if (rcs != NULL) return (NULL);
rcs->flags |= VALID;
return (rcs);
} }
/* /*
* Do the real work of parsing an RCS file * Parse a specific rcsfile.
*/ */
RCSNode * RCSNode *
RCS_parsercsfile (rcsfile) RCS_parsercsfile (rcsfile)
char *rcsfile; char *rcsfile;
{ {
Node *q, *r;
RCSNode *rdata;
RCSVers *vnode;
int n;
char *cp;
char *key, *value;
FILE *fp; FILE *fp;
RCSNode *rcs;
/* open the rcsfile */ /* open the rcsfile */
if ((fp = fopen (rcsfile, "r")) == NULL) if ((fp = fopen (rcsfile, "r")) == NULL)
@ -145,9 +180,30 @@ RCS_parsercsfile (rcsfile)
return (NULL); return (NULL);
} }
rcs = RCS_parsercsfile_i (fp, rcsfile);
fclose (fp);
return (rcs);
}
/*
* Do the real work of parsing an RCS file
*/
static RCSNode *
RCS_parsercsfile_i (fp, rcsfile)
FILE *fp;
char *rcsfile;
{
Node *q, *r;
RCSNode *rdata;
RCSVers *vnode;
int n;
char *cp;
char *key, *value;
/* make a node */ /* make a node */
rdata = (RCSNode *) xmalloc (sizeof (RCSNode)); rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
bzero ((char *) rdata, sizeof (RCSNode)); memset ((char *) rdata, 0, sizeof (RCSNode));
rdata->refcount = 1; rdata->refcount = 1;
rdata->path = xstrdup (rcsfile); rdata->path = xstrdup (rcsfile);
rdata->versions = getlist (); rdata->versions = getlist ();
@ -161,14 +217,24 @@ RCS_parsercsfile (rcsfile)
{ {
/* get the next key/value pair */ /* get the next key/value pair */
/* if key is NULL here, then the file is missing some headers */ /* if key is NULL here, then the file is missing some headers
or we had trouble reading the file. */
if (getrcskey (fp, &key, &value) == -1 || key == NULL) if (getrcskey (fp, &key, &value) == -1 || key == NULL)
{ {
if (!really_quiet) if (!really_quiet)
error (0, 0, "`%s' does not appear to be a valid rcs file", {
rcsfile); if (ferror(fp))
{
error (1, 0, "error reading `%s'", rcsfile);
}
else
{
error (0, 0, "`%s' does not appear to be a valid rcs file",
rcsfile);
}
}
freercsnode (&rdata); freercsnode (&rdata);
(void) fclose (fp);
return (NULL); return (NULL);
} }
@ -184,7 +250,7 @@ RCS_parsercsfile (rcsfile)
if ((numdots (rdata->branch) & 1) != 0) if ((numdots (rdata->branch) & 1) != 0)
{ {
/* turn it into a branch if it's a revision */ /* turn it into a branch if it's a revision */
cp = rindex (rdata->branch, '.'); cp = strrchr (rdata->branch, '.');
*cp = '\0'; *cp = '\0';
} }
continue; continue;
@ -193,9 +259,7 @@ RCS_parsercsfile (rcsfile)
{ {
if (value != NULL) if (value != NULL)
{ {
/* if there are tags, set up the tag list */ rdata->symbols_data = xstrdup(value);
rdata->symbols = getlist ();
do_symbols (rdata->symbols, value);
continue; continue;
} }
} }
@ -225,7 +289,7 @@ RCS_parsercsfile (rcsfile)
/* grab the value of the date from value */ /* grab the value of the date from value */
valp = value + strlen (RCSDATE);/* skip the "date" keyword */ valp = value + strlen (RCSDATE);/* skip the "date" keyword */
while (isspace (*valp)) /* take space off front of value */ while (whitespace (*valp)) /* take space off front of value */
valp++; valp++;
(void) strcpy (date, valp); (void) strcpy (date, valp);
@ -237,7 +301,7 @@ RCS_parsercsfile (rcsfile)
q->delproc = rcsvers_delproc; q->delproc = rcsvers_delproc;
r->delproc = null_delproc; r->delproc = null_delproc;
q->data = r->data = xmalloc (sizeof (RCSVers)); q->data = r->data = xmalloc (sizeof (RCSVers));
bzero (q->data, sizeof (RCSVers)); memset (q->data, 0, sizeof (RCSVers));
vnode = (RCSVers *) q->data; vnode = (RCSVers *) q->data;
/* fill in the version before we forget it */ /* fill in the version before we forget it */
@ -290,7 +354,6 @@ RCS_parsercsfile (rcsfile)
break; break;
} }
(void) fclose (fp);
return (rdata); return (rdata);
} }
@ -325,6 +388,8 @@ freercsnode (rnodep)
dellist (&(*rnodep)->dates); dellist (&(*rnodep)->dates);
if ((*rnodep)->symbols != (List *) NULL) if ((*rnodep)->symbols != (List *) NULL)
dellist (&(*rnodep)->symbols); dellist (&(*rnodep)->symbols);
if ((*rnodep)->symbols_data != (char *) NULL)
free ((*rnodep)->symbols_data);
if ((*rnodep)->head != (char *) NULL) if ((*rnodep)->head != (char *) NULL)
free ((*rnodep)->head); free ((*rnodep)->head);
if ((*rnodep)->branch != (char *) NULL) if ((*rnodep)->branch != (char *) NULL)
@ -405,14 +470,14 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL; *valp = (char *) NULL;
return (-1); return (-1);
} }
if (!isspace (c)) if (!whitespace (c))
break; break;
} }
/* fill in key */ /* fill in key */
cur = key; cur = key;
max = key + keysize; max = key + keysize;
while (!isspace (c) && c != ';') while (!whitespace (c) && c != ';')
{ {
if (cur < max) if (cur < max)
*cur++ = c; *cur++ = c;
@ -432,6 +497,14 @@ getrcskey (fp, keyp, valp)
return (-1); return (-1);
} }
} }
if (cur >= max)
{
key = xrealloc (key, keysize + ALLOCINCR);
cur = key + keysize;
keysize += ALLOCINCR;
max = key + keysize;
}
*cur = '\0'; *cur = '\0';
/* if we got "desc", we are done with the file */ /* if we got "desc", we are done with the file */
@ -538,10 +611,10 @@ getrcskey (fp, keyp, valp)
*/ */
/* whitespace with white set means compress it out */ /* whitespace with white set means compress it out */
if (white && isspace (c)) if (white && whitespace (c))
continue; continue;
if (isspace (c)) if (whitespace (c))
{ {
/* make c a space and set white */ /* make c a space and set white */
white = 1; white = 1;
@ -568,7 +641,16 @@ getrcskey (fp, keyp, valp)
/* terminate the string */ /* terminate the string */
if (cur) if (cur)
{
if (cur >= max)
{
value = xrealloc (value, valsize + ALLOCINCR);
cur = value + valsize;
valsize += ALLOCINCR;
max = value + valsize;
}
*cur = '\0'; *cur = '\0';
}
/* if the string is empty, make it null */ /* if the string is empty, make it null */
if (value && *value != '\0') if (value && *value != '\0')
@ -594,7 +676,7 @@ do_symbols (list, val)
for (;;) for (;;)
{ {
/* skip leading whitespace */ /* skip leading whitespace */
while (isspace (*cp)) while (whitespace (*cp))
cp++; cp++;
/* if we got to the end, we are done */ /* if we got to the end, we are done */
@ -603,10 +685,10 @@ do_symbols (list, val)
/* split it up into tag and rev */ /* split it up into tag and rev */
tag = cp; tag = cp;
cp = index (cp, ':'); cp = strchr (cp, ':');
*cp++ = '\0'; *cp++ = '\0';
rev = cp; rev = cp;
while (!isspace (*cp) && *cp != '\0') while (!whitespace (*cp) && *cp != '\0')
cp++; cp++;
if (*cp != '\0') if (*cp != '\0')
*cp++ = '\0'; *cp++ = '\0';
@ -634,7 +716,7 @@ do_branches (list, val)
for (;;) for (;;)
{ {
/* skip leading whitespace */ /* skip leading whitespace */
while (isspace (*cp)) while (whitespace (*cp))
cp++; cp++;
/* if we got to the end, we are done */ /* if we got to the end, we are done */
@ -643,7 +725,7 @@ do_branches (list, val)
/* find the end of this branch */ /* find the end of this branch */
branch = cp; branch = cp;
while (!isspace (*cp) && *cp != '\0') while (!whitespace (*cp) && *cp != '\0')
cp++; cp++;
if (*cp != '\0') if (*cp != '\0')
*cp++ = '\0'; *cp++ = '\0';
@ -686,7 +768,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
if (tagrev == NULL) if (tagrev == NULL)
return ((char *) NULL); return ((char *) NULL);
if ((cp = rindex (tagrev, '.')) != NULL) if ((cp = strrchr (tagrev, '.')) != NULL)
*cp = '\0'; *cp = '\0';
rev = RCS_getdatebranch (rcs, date, tagrev); rev = RCS_getdatebranch (rcs, date, tagrev);
free (tagrev); free (tagrev);
@ -733,8 +815,9 @@ RCS_gettag (rcs, tag, force_tag_match)
/* If we got a symbolic tag, resolve it to a numeric */ /* If we got a symbolic tag, resolve it to a numeric */
if (rcs == NULL) if (rcs == NULL)
p = NULL; p = NULL;
else else {
p = findnode (rcs->symbols, tag); p = findnode (RCS_symbols(rcs), tag);
}
if (p != NULL) if (p != NULL)
{ {
int dots; int dots;
@ -750,7 +833,7 @@ RCS_gettag (rcs, tag, force_tag_match)
dots = numdots (tag); dots = numdots (tag);
if (dots > 2 && (dots & 1) != 0) if (dots > 2 && (dots & 1) != 0)
{ {
branch = rindex (tag, '.'); branch = strrchr (tag, '.');
cp = branch++ - 1; cp = branch++ - 1;
while (*cp != '.') while (*cp != '.')
cp--; cp--;
@ -874,7 +957,7 @@ RCS_magicrev (rcs, rev)
(void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num); (void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
/* walk the symbols list to see if a magic one already exists */ /* walk the symbols list to see if a magic one already exists */
if (walklist (rcs->symbols, checkmagic_proc) != 0) if (walklist (RCS_symbols(rcs), checkmagic_proc, NULL) != 0)
continue; continue;
/* we found a free magic branch. Claim it as ours */ /* we found a free magic branch. Claim it as ours */
@ -887,8 +970,9 @@ RCS_magicrev (rcs, rev)
* Returns 0 if the symbol does not match, 1 if it does. * Returns 0 if the symbol does not match, 1 if it does.
*/ */
static int static int
checkmagic_proc (p) checkmagic_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (strcmp (check_rev, p->data) == 0) if (strcmp (check_rev, p->data) == 0)
return (1); return (1);
@ -897,9 +981,9 @@ checkmagic_proc (p)
} }
/* /*
* Returns non-zero if the specified revision number or symbolic tag * Given a list of RCSNodes, returns non-zero if the specified
* resolves to a "branch" within the rcs file. We do take into account * revision number or symbolic tag resolves to a "branch" within the
* any magic branches as well. * rcs file.
*/ */
int int
RCS_isbranch (file, rev, srcfiles) RCS_isbranch (file, rev, srcfiles)
@ -907,7 +991,6 @@ RCS_isbranch (file, rev, srcfiles)
char *rev; char *rev;
List *srcfiles; List *srcfiles;
{ {
int dots;
Node *p; Node *p;
RCSNode *rcs; RCSNode *rcs;
@ -922,7 +1005,27 @@ RCS_isbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */ /* now, look for a match in the symbols list */
rcs = (RCSNode *) p->data; rcs = (RCSNode *) p->data;
p = findnode (rcs->symbols, rev); return (RCS_nodeisbranch (rev, rcs));
}
/*
* Given an RCSNode, returns non-zero if the specified revision number
* or symbolic tag resolves to a "branch" within the rcs file. We do
* take into account any magic branches as well.
*/
int
RCS_nodeisbranch (rev, rcs)
char *rev;
RCSNode *rcs;
{
int dots;
Node *p;
/* numeric revisions are easy -- even number of dots is a branch */
if (isdigit (*rev))
return ((numdots (rev) & 1) == 0);
p = findnode (RCS_symbols(rcs), rev);
if (p == NULL) if (p == NULL)
return (0); return (0);
dots = numdots (p->data); dots = numdots (p->data);
@ -933,7 +1036,7 @@ RCS_isbranch (file, rev, srcfiles)
if (dots > 2) if (dots > 2)
{ {
char *magic; char *magic;
char *branch = rindex (p->data, '.'); char *branch = strrchr (p->data, '.');
char *cp = branch - 1; char *cp = branch - 1;
while (*cp != '.') while (*cp != '.')
cp--; cp--;
@ -972,7 +1075,7 @@ RCS_whatbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */ /* now, look for a match in the symbols list */
rcs = (RCSNode *) p->data; rcs = (RCSNode *) p->data;
p = findnode (rcs->symbols, rev); p = findnode (RCS_symbols(rcs), rev);
if (p == NULL) if (p == NULL)
return ((char *) NULL); return ((char *) NULL);
dots = numdots (p->data); dots = numdots (p->data);
@ -983,7 +1086,7 @@ RCS_whatbranch (file, rev, srcfiles)
if (dots > 2) if (dots > 2)
{ {
char *magic; char *magic;
char *branch = rindex (p->data, '.'); char *branch = strrchr (p->data, '.');
char *cp = branch++ - 1; char *cp = branch++ - 1;
while (*cp != '.') while (*cp != '.')
cp--; cp--;
@ -1008,7 +1111,7 @@ RCS_whatbranch (file, rev, srcfiles)
* Get the head of the specified branch. If the branch does not exist, * Get the head of the specified branch. If the branch does not exist,
* return NULL or RCS_head depending on force_tag_match * return NULL or RCS_head depending on force_tag_match
*/ */
static char * char *
RCS_getbranch (rcs, tag, force_tag_match) RCS_getbranch (rcs, tag, force_tag_match)
RCSNode *rcs; RCSNode *rcs;
char *tag; char *tag;
@ -1025,7 +1128,7 @@ RCS_getbranch (rcs, tag, force_tag_match)
return ((char *) NULL); return ((char *) NULL);
/* find out if the tag contains a dot, or is on the trunk */ /* find out if the tag contains a dot, or is on the trunk */
cp = rindex (tag, '.'); cp = strrchr (tag, '.');
/* trunk processing is the special case */ /* trunk processing is the special case */
if (cp == NULL) if (cp == NULL)
@ -1237,7 +1340,7 @@ RCS_getdatebranch (rcs, date, branch)
/* look up the first revision on the branch */ /* look up the first revision on the branch */
xrev = xstrdup (branch); xrev = xstrdup (branch);
cp = rindex (xrev, '.'); cp = strrchr (xrev, '.');
if (cp == NULL) if (cp == NULL)
{ {
free (xrev); free (xrev);
@ -1374,6 +1477,20 @@ RCS_getrevtime (rcs, rev, date, fudge)
return (revdate); return (revdate);
} }
List *
RCS_symbols(rcs)
RCSNode *rcs;
{
if (rcs->symbols_data) {
rcs->symbols = getlist ();
do_symbols (rcs->symbols, rcs->symbols_data);
free(rcs->symbols_data);
rcs->symbols_data = NULL;
}
return rcs->symbols;
}
/* /*
* The argument ARG is the getopt remainder of the -k option specified on the * The argument ARG is the getopt remainder of the -k option specified on the
* command line. This function returns malloc'ed space that can be used * command line. This function returns malloc'ed space that can be used
@ -1439,7 +1556,7 @@ RCS_check_tag (tag)
if (!isgraph (*cp)) if (!isgraph (*cp))
error (1, 0, "tag `%s' has non-visible graphic characters", error (1, 0, "tag `%s' has non-visible graphic characters",
tag); tag);
if (index (invalid, *cp)) if (strchr (invalid, *cp))
error (1, 0, "tag `%s' must not contain the characters `%s'", error (1, 0, "tag `%s' must not contain the characters `%s'",
tag, invalid); tag, invalid);
} }
@ -1447,3 +1564,4 @@ RCS_check_tag (tag)
else else
error (1, 0, "tag `%s' must start with a letter", tag); error (1, 0, "tag `%s' must start with a letter", tag);
} }

View File

@ -1,11 +1,11 @@
/* @(#)rcs.h 1.14 92/03/31 */ /* $CVSid: @(#)rcs.h 1.18 94/09/23 $ */
/* /*
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* RCS source control definitions needed by rcs.c and friends * RCS source control definitions needed by rcs.c and friends
*/ */
@ -19,6 +19,7 @@
#define RCS_RCSMERGE "rcsmerge" #define RCS_RCSMERGE "rcsmerge"
#define RCS_MERGE_PAT "^>>>>>>> " /* runs "grep" with this pattern */ #define RCS_MERGE_PAT "^>>>>>>> " /* runs "grep" with this pattern */
#define RCSEXT ",v" #define RCSEXT ",v"
#define RCSPAT "*,v"
#define RCSHEAD "head" #define RCSHEAD "head"
#define RCSBRANCH "branch" #define RCSBRANCH "branch"
#define RCSSYMBOLS "symbols" #define RCSSYMBOLS "symbols"
@ -39,6 +40,7 @@ struct rcsnode
char *path; char *path;
char *head; char *head;
char *branch; char *branch;
char *symbols_data;
List *symbols; List *symbols;
List *versions; List *versions;
List *dates; List *dates;
@ -66,37 +68,23 @@ typedef struct rcsversnode RCSVers;
/* /*
* exported interfaces * exported interfaces
*/ */
#if __STDC__ List *RCS_parsefiles PROTO((List * files, char *xrepos));
List *RCS_parsefiles (List * files, char *xrepos); RCSNode *RCS_parse PROTO((char *file, char *repos));
RCSNode *RCS_parse (char *file, char *repos); RCSNode *RCS_parsercsfile PROTO((char *rcsfile));
RCSNode *RCS_parsercsfile (char *rcsfile); char *RCS_check_kflag PROTO((char *arg));
char *RCS_check_kflag (char *arg); char *RCS_getdate PROTO((RCSNode * rcs, char *date, int force_tag_match));
char *RCS_getdate (RCSNode * rcs, char *date, int force_tag_match); char *RCS_gettag PROTO((RCSNode * rcs, char *tag, int force_tag_match));
char *RCS_gettag (RCSNode * rcs, char *tag, int force_tag_match); char *RCS_getversion PROTO((RCSNode * rcs, char *tag, char *date,
char *RCS_getversion (RCSNode * rcs, char *tag, char *date, int force_tag_match));
int force_tag_match); char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
char *RCS_magicrev (RCSNode *rcs, char *rev); int RCS_isbranch PROTO((char *file, char *rev, List *srcfiles));
int RCS_isbranch (char *file, char *rev, List *srcfiles); int RCS_nodeisbranch PROTO((char *rev, RCSNode *rcs));
char *RCS_whatbranch (char *file, char *tag, List *srcfiles); char *RCS_whatbranch PROTO((char *file, char *tag, List *srcfiles));
char *RCS_head (RCSNode * rcs); char *RCS_head PROTO((RCSNode * rcs));
int RCS_datecmp (char *date1, char *date2); int RCS_datecmp PROTO((char *date1, char *date2));
time_t RCS_getrevtime (RCSNode * rcs, char *rev, char *date, int fudge); time_t RCS_getrevtime PROTO((RCSNode * rcs, char *rev, char *date, int fudge));
void RCS_check_tag (char *tag); List *RCS_symbols PROTO((RCSNode *rcs));
void freercsnode (RCSNode ** rnodep); void RCS_check_tag PROTO((char *tag));
#else void freercsnode PROTO((RCSNode ** rnodep));
List *RCS_parsefiles (); void RCS_addnode PROTO((char *file, RCSNode *rcs, List *list));
RCSNode *RCS_parse (); char *RCS_getbranch PROTO((RCSNode * rcs, char *tag, int force_tag_match));
char *RCS_head ();
char *RCS_getversion ();
char *RCS_magicrev ();
int RCS_isbranch ();
char *RCS_whatbranch ();
char *RCS_gettag ();
char *RCS_getdate ();
char *RCS_check_kflag ();
void RCS_check_tag ();
time_t RCS_getrevtime ();
RCSNode *RCS_parsercsfile ();
int RCS_datecmp ();
void freercsnode ();
#endif /* __STDC__ */

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* General recursion handler * General recursion handler
* *
@ -11,18 +11,15 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)recurse.c 1.22 92/04/10"; static char rcsid[] = "$CVSid: @(#)recurse.c 1.31 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static int do_dir_proc PROTO((Node * p, void *closure));
static int do_dir_proc (Node * p); static int do_file_proc PROTO((Node * p, void *closure));
static int do_file_proc (Node * p); static void addlist PROTO((List ** listp, char *key));
static void addlist (List ** listp, char *key); static int unroll_files_proc PROTO((Node *p, void *closure));
#else static void addfile PROTO((List **listp, char *dir, char *file));
static int do_file_proc ();
static int do_dir_proc ();
static void addlist ();
#endif /* __STDC__ */
/* /*
@ -41,17 +38,35 @@ static char update_dir[PATH_MAX];
static char *repository = NULL; static char *repository = NULL;
static List *entries = NULL; static List *entries = NULL;
static List *srcfiles = NULL; static List *srcfiles = NULL;
static List *filelist = NULL;
static List *dirlist = NULL; static List *filelist = NULL; /* holds list of files on which to operate */
static List *dirlist = NULL; /* holds list of directories on which to operate */
struct recursion_frame {
int (*fileproc)();
int (*filesdoneproc) ();
Dtype (*direntproc) ();
int (*dirleaveproc) ();
Dtype flags;
int which;
int aflag;
int readlock;
int dosrcs;
};
/* /*
* Called to start a recursive command Command line arguments are processed * Called to start a recursive command.
* if present, otherwise the local directory is processed. *
* Command line arguments dictate the directories and files on which
* we operate. In the special case of no arguments, we default to
* ".".
*
* The general algorythm is as follows.
*/ */
int int
start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
argc, argv, local, which, aflag, readlock, argc, argv, local, which, aflag, readlock,
update_preload, dosrcs) update_preload, dosrcs, wd_is_repos)
int (*fileproc) (); int (*fileproc) ();
int (*filesdoneproc) (); int (*filesdoneproc) ();
Dtype (*direntproc) (); Dtype (*direntproc) ();
@ -64,9 +79,12 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
int readlock; int readlock;
char *update_preload; char *update_preload;
int dosrcs; int dosrcs;
int wd_is_repos; /* Set if caller has already cd'd to the repository */
{ {
int i, err = 0; int i, err = 0;
Dtype flags; Dtype flags;
List *files_by_dir = NULL;
struct recursion_frame frame;
if (update_preload == NULL) if (update_preload == NULL)
update_dir[0] = '\0'; update_dir[0] = '\0';
@ -89,7 +107,8 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
if (srcfiles) if (srcfiles)
dellist (&srcfiles); dellist (&srcfiles);
if (filelist) if (filelist)
dellist (&filelist); dellist (&filelist); /* FIXME-krp: no longer correct. */
/* FIXME-krp: clean up files_by_dir */
if (dirlist) if (dirlist)
dellist (&dirlist); dellist (&dirlist);
@ -111,139 +130,128 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
err += do_recursion (fileproc, filesdoneproc, direntproc, err += do_recursion (fileproc, filesdoneproc, direntproc,
dirleaveproc, flags, which, aflag, dirleaveproc, flags, which, aflag,
readlock, dosrcs); readlock, dosrcs);
return(err);
} }
else
/*
* There were arguments, so we have to handle them by hand. To do
* that, we set up the filelist and dirlist with the arguments and
* call do_recursion. do_recursion recognizes the fact that the
* lists are non-null when it starts and doesn't update them.
*
* explicitly named directories are stored in dirlist.
* explicitly named files are stored in filelist.
* other possibility is named entities whicha are not currently in
* the working directory.
*/
for (i = 0; i < argc; i++)
{ {
/* if this argument is a directory, then add it to the list of
directories. */
/* if (isdir(argv[i]))
* There were arguments, so we have to handle them by hand. To do addlist (&dirlist, argv[i]);
* that, we set up the filelist and dirlist with the arguments and
* call do_recursion. do_recursion recognizes the fact that the
* lists are non-null when it starts and doesn't update them
*/
/* look for args with /-s in them */
for (i = 0; i < argc; i++)
if (index (argv[i], '/') != NULL)
break;
/* if we didn't find any hard one's, do it the easy way */
if (i == argc)
{
/* set up the lists */
for (i = 0; i < argc; i++)
{
if (isdir (argv[i]))
addlist (&dirlist, argv[i]);
else
{
if (isdir (CVSADM) || isdir (OCVSADM))
{
char *repos;
char tmp[PATH_MAX];
repos = Name_Repository ((char *) NULL, update_dir);
(void) sprintf (tmp, "%s/%s", repos, argv[i]);
if (isdir (tmp))
addlist (&dirlist, argv[i]);
else
addlist (&filelist, argv[i]);
free (repos);
}
else
addlist (&filelist, argv[i]);
}
}
/* we aren't recursive if no directories were specified */
if (dirlist == NULL)
local = 1;
/* process the lists */
err += do_recursion (fileproc, filesdoneproc, direntproc,
dirleaveproc, flags, which, aflag,
readlock, dosrcs);
}
/* otherwise - do it the hard way */
else else
{ {
char *cp; /* otherwise, split argument into directory and component names. */
char *dir = (char *) NULL; char *dir;
char *comp = (char *) NULL; char *comp;
char *oldupdate = (char *) NULL; char tmp[PATH_MAX];
char savewd[PATH_MAX]; char *file_to_try;
if (getwd (savewd) == NULL) dir = xstrdup (argv[i]);
error (1, 0, "could not get working directory: %s", savewd); if ((comp = strrchr (dir, '/')) == NULL)
for (i = 0; i < argc; i++)
{ {
/* split the arg into the dir and component parts */ /* no dir component. What we have is an implied "./" */
dir = xstrdup (argv[i]); comp = dir;
if ((cp = rindex (dir, '/')) != NULL) dir = xstrdup(".");
{
*cp = '\0';
comp = xstrdup (cp + 1);
oldupdate = xstrdup (update_dir);
if (update_dir[0] != '\0')
(void) strcat (update_dir, "/");
(void) strcat (update_dir, dir);
}
else
{
comp = xstrdup (dir);
if (dir)
free (dir);
dir = (char *) NULL;
}
/* chdir to the appropriate place if necessary */
if (dir && chdir (dir) < 0)
error (1, errno, "could not chdir to %s", dir);
/* set up the list */
if (isdir (comp))
addlist (&dirlist, comp);
else
{
if (isdir (CVSADM) || isdir (OCVSADM))
{
char *repos;
char tmp[PATH_MAX];
repos = Name_Repository ((char *) NULL, update_dir);
(void) sprintf (tmp, "%s/%s", repos, comp);
if (isdir (tmp))
addlist (&dirlist, comp);
else
addlist (&filelist, comp);
free (repos);
}
else
addlist (&filelist, comp);
}
/* do the recursion */
err += do_recursion (fileproc, filesdoneproc, direntproc,
dirleaveproc, flags, which,
aflag, readlock, dosrcs);
/* chdir back and fix update_dir if necessary */
if (dir && chdir (savewd) < 0)
error (1, errno, "could not chdir to %s", dir);
if (oldupdate)
{
(void) strcpy (update_dir, oldupdate);
free (oldupdate);
}
} }
if (dir) else
free (dir); {
if (comp) char *p = comp;
free (comp);
*p++ = '\0';
comp = xstrdup (p);
}
/* if this argument exists as a file in the current
working directory tree, then add it to the files list. */
if (wd_is_repos)
{
/* If doing rtag, we've done a chdir to the repository. */
sprintf (tmp, "%s%s", argv[i], RCSEXT);
file_to_try = tmp;
}
else
file_to_try = argv[i];
if(isfile(file_to_try))
addfile (&files_by_dir, dir, comp);
else if (isdir (dir))
{
if (isdir (CVSADM) || isdir (OCVSADM))
{
/* otherwise, look for it in the repository. */
char *save_update_dir;
char *repos;
/* save & set (aka push) update_dir */
save_update_dir = xstrdup (update_dir);
if (*update_dir != '\0')
(void) strcat (update_dir, "/");
(void) strcat (update_dir, dir);
/* look for it in the repository. */
repos = Name_Repository (dir, update_dir);
(void) sprintf (tmp, "%s/%s", repos, comp);
if (isdir(tmp))
addlist (&dirlist, argv[i]);
else
addfile (&files_by_dir, dir, comp);
(void) sprintf (update_dir, "%s", save_update_dir);
free (save_update_dir);
}
else
addfile (&files_by_dir, dir, comp);
}
else
error (1, 0, "no such directory `%s'", dir);
free (dir);
free (comp);
} }
} }
/* At this point we have looped over all named arguments and built
a coupla lists. Now we unroll the lists, setting up and
calling do_recursion. */
frame.fileproc = fileproc;
frame.filesdoneproc = filesdoneproc;
frame.direntproc = direntproc;
frame.dirleaveproc = dirleaveproc;
frame.flags = flags;
frame.which = which;
frame.aflag = aflag;
frame.readlock = readlock;
frame.dosrcs = dosrcs;
err += walklist (files_by_dir, unroll_files_proc, (void *) &frame);
/* then do_recursion on the dirlist. */
if (dirlist != NULL)
err += do_recursion (frame.fileproc, frame.filesdoneproc,
frame.direntproc, frame.dirleaveproc,
frame.flags, frame.which, frame.aflag,
frame.readlock, frame.dosrcs);
return (err); return (err);
} }
@ -360,7 +368,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
srcfiles = (List *) NULL; srcfiles = (List *) NULL;
/* process the files */ /* process the files */
err += walklist (filelist, do_file_proc); err += walklist (filelist, do_file_proc, NULL);
/* unlock it */ /* unlock it */
if (readlock) if (readlock)
@ -378,7 +386,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
/* process the directories (if necessary) */ /* process the directories (if necessary) */
if (dirlist != NULL) if (dirlist != NULL)
err += walklist (dirlist, do_dir_proc); err += walklist (dirlist, do_dir_proc, NULL);
#ifdef notdef #ifdef notdef
else if (dirleaveproc != NULL) else if (dirleaveproc != NULL)
err += dirleaveproc(".", err, "."); err += dirleaveproc(".", err, ".");
@ -399,8 +407,9 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
* Process each of the files in the list with the callback proc * Process each of the files in the list with the callback proc
*/ */
static int static int
do_file_proc (p) do_file_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
if (fileproc != NULL) if (fileproc != NULL)
return (fileproc (p->key, update_dir, repository, entries, srcfiles)); return (fileproc (p->key, update_dir, repository, entries, srcfiles));
@ -412,8 +421,9 @@ do_file_proc (p)
* Process each of the directories in the list (recursing as we go) * Process each of the directories in the list (recursing as we go)
*/ */
static int static int
do_dir_proc (p) do_dir_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
char *dir = p->key; char *dir = p->key;
char savewd[PATH_MAX]; char savewd[PATH_MAX];
@ -508,7 +518,7 @@ do_dir_proc (p)
} }
/* put back update_dir */ /* put back update_dir */
if ((cp = rindex (update_dir, '/')) != NULL) if ((cp = strrchr (update_dir, '/')) != NULL)
*cp = '\0'; *cp = '\0';
else else
update_dir[0] = '\0'; update_dir[0] = '\0';
@ -517,7 +527,7 @@ do_dir_proc (p)
} }
/* /*
* Add a node to a list allocating the list if necessary * Add a node to a list allocating the list if necessary.
*/ */
static void static void
addlist (listp, key) addlist (listp, key)
@ -531,5 +541,87 @@ addlist (listp, key)
p = getnode (); p = getnode ();
p->type = FILES; p->type = FILES;
p->key = xstrdup (key); p->key = xstrdup (key);
(void) addnode (*listp, p); if (addnode (*listp, p) != 0)
freenode (p);
}
static void
addfile (listp, dir, file)
List **listp;
char *dir;
char *file;
{
Node *n;
/* add this dir. */
(void) addlist (listp, dir);
n = findnode (*listp, dir);
if (n == NULL)
{
error (1, 0, "can't find recently added dir node `%s' in start_recursion.",
dir);
}
n->type = DIRS;
addlist ((List **) &n->data, file);
return;
}
static int
unroll_files_proc (p, closure)
Node *p;
void *closure;
{
Node *n;
struct recursion_frame *frame = (struct recursion_frame *) closure;
int err = 0;
List *save_dirlist;
char savewd[PATH_MAX];
char *save_update_dir = NULL;
/* if this dir was also an explicitly named argument, then skip
it. We'll catch it later when we do dirs. */
n = findnode (dirlist, p->key);
if (n != NULL)
return (0);
/* otherwise, call dorecusion for this list of files. */
filelist = (List *) p->data;
save_dirlist = dirlist;
dirlist = NULL;
if (strcmp(p->key, ".") != 0)
{
if (getwd (savewd) == NULL)
error (1, 0, "could not get working directory: %s", savewd);
if (chdir (p->key) < 0)
error (1, errno, "could not chdir to %s", p->key);
save_update_dir = xstrdup (update_dir);
if (*update_dir != '\0')
(void) strcat (update_dir, "/");
(void) strcat (update_dir, p->key);
}
err += do_recursion (frame->fileproc, frame->filesdoneproc,
frame->direntproc, frame->dirleaveproc,
frame->flags, frame->which, frame->aflag,
frame->readlock, frame->dosrcs);
if (save_update_dir != NULL)
{
(void) strcpy (update_dir, save_update_dir);
free (save_update_dir);
if (chdir (savewd) < 0)
error (1, errno, "could not chdir to %s", savewd);
}
dirlist = save_dirlist;
filelist = NULL;
return(err);
} }

View File

@ -12,14 +12,11 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)release.c 1.21 92/02/29"; static char rcsid[] = "$CVSid: @(#)release.c 1.23 94/09/21 $";
USE(rcsid)
#endif #endif
#if __STDC__ static void release_delete PROTO((char *dir));
static void release_delete (char *dir);
#else
static void release_delete ();
#endif /* __STDC__ */
static char *release_usage[] = static char *release_usage[] =
{ {
@ -49,7 +46,7 @@ release (argc, argv)
if (argc == -1) if (argc == -1)
usage (release_usage); usage (release_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "Qdq")) != -1) while ((c = getopt (argc, argv, "Qdq")) != -1)
{ {
switch (c) switch (c)
{ {
@ -116,7 +113,7 @@ release (argc, argv)
continue; continue;
} }
val.dptr[val.dsize] = '\0'; val.dptr[val.dsize] = '\0';
if ((cp = index (val.dptr, '#')) != NULL) /* Strip out a comment */ if ((cp = strchr (val.dptr, '#')) != NULL) /* Strip out a comment */
{ {
do do
{ {
@ -128,7 +125,7 @@ release (argc, argv)
margv = modargv; margv = modargv;
optind = 1; optind = 1;
while (gnu_getopt (margc, margv, CVSMODULE_OPTS) != -1) while (getopt (margc, margv, CVSMODULE_OPTS) != -1)
/* do nothing */ ; /* do nothing */ ;
margc -= optind; margc -= optind;
margv += optind; margv += optind;
@ -159,7 +156,7 @@ release (argc, argv)
c = 0; c = 0;
while (fgets (line, sizeof (line), fp)) while (fgets (line, sizeof (line), fp))
{ {
if (index ("MARCZ", *line)) if (strchr ("MARCZ", *line))
c++; c++;
(void) printf (line); (void) printf (line);
} }
@ -211,7 +208,11 @@ release_delete (dir)
"Parent dir on a different disk, delete of %s aborted", dir); "Parent dir on a different disk, delete of %s aborted", dir);
return; return;
} }
run_setup ("%s -r", RM); /*
* XXX - shouldn't this just delete the CVS-controlled files and, perhaps,
* the files that would normally be ignored and leave everything else?
*/
run_setup ("%s -fr", RM);
run_arg (dir); run_arg (dir);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0) if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
error (0, retcode == -1 ? errno : 0, error (0, retcode == -1 ? errno : 0,

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Remove a File * Remove a File
* *
@ -18,26 +18,24 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)remove.c 1.34 92/04/10"; static char rcsid[] = "$CVSid: @(#)remove.c 1.39 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static int remove_fileproc PROTO((char *file, char *update_dir,
static int remove_fileproc (char *file, char *update_dir,
char *repository, List *entries, char *repository, List *entries,
List *srcfiles); List *srcfiles));
static Dtype remove_dirproc (char *dir, char *repos, char *update_dir); static Dtype remove_dirproc PROTO((char *dir, char *repos, char *update_dir));
#else
static Dtype remove_dirproc ();
static int remove_fileproc ();
#endif
static int force;
static int local; static int local;
static int removed_files; static int removed_files;
static int auto_removed_files; static int existing_files;
static char *remove_usage[] = static char *remove_usage[] =
{ {
"Usage: %s %s [-lR] [files...]\n", "Usage: %s %s [-flR] [files...]\n",
"\t-f\tDelete the file before removing it.\n",
"\t-l\tProcess this directory only (not recursive).\n", "\t-l\tProcess this directory only (not recursive).\n",
"\t-R\tProcess directories recursively.\n", "\t-R\tProcess directories recursively.\n",
NULL NULL
@ -54,10 +52,13 @@ cvsremove (argc, argv)
usage (remove_usage); usage (remove_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "lR")) != -1) while ((c = getopt (argc, argv, "flR")) != -1)
{ {
switch (c) switch (c)
{ {
case 'f':
force = 1;
break;
case 'l': case 'l':
local = 1; local = 1;
break; break;
@ -76,15 +77,18 @@ cvsremove (argc, argv)
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc, err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
(int (*) ()) NULL, argc, argv, local, (int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1); W_LOCAL, 0, 1, (char *) NULL, 1, 0);
if (removed_files) if (removed_files)
error (0, 0, "use '%s commit' to remove %s permanently", program_name, error (0, 0, "use '%s commit' to remove %s permanently", program_name,
(removed_files == 1) ? "this file" : "these files"); (removed_files == 1) ? "this file" : "these files");
else
if (!auto_removed_files) if (existing_files)
error (0, 0, "no files removed; use `%s' to remove the file first", error (0, 0,
RM); ((existing_files == 1) ?
"%d file exists; use `%s' to remove it first" :
"%d files exist; use `%s' to remove them first"),
existing_files, RM);
return (err); return (err);
} }
@ -104,24 +108,28 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
char fname[PATH_MAX]; char fname[PATH_MAX];
Vers_TS *vers; Vers_TS *vers;
/*
* If unlinking the file works, good. If not, the "unremoved"
* error will indicate problems.
*/
if (force)
(void) unlink (file);
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL, vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
file, 0, 0, entries, srcfiles); file, 0, 0, entries, srcfiles);
if (vers->ts_user != NULL) if (vers->ts_user != NULL)
{ {
freevers_ts (&vers); existing_files++;
return (0); if (!quiet)
error (0, 0, "file `%s' still in working directory", file);
} }
else if (vers->vn_user == NULL)
if (vers->vn_user == NULL)
{ {
if (!quiet) if (!quiet)
error (0, 0, "nothing known about %s", file); error (0, 0, "nothing known about `%s'", file);
freevers_ts (&vers);
return (0);
} }
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
{ {
/* /*
* It's a file that has been added, but not commited yet. So, * It's a file that has been added, but not commited yet. So,
@ -134,13 +142,12 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG); (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
(void) unlink_file (fname); (void) unlink_file (fname);
if (!quiet) if (!quiet)
error (0, 0, "removed `%s'.", file); error (0, 0, "removed `%s'", file);
auto_removed_files++;
} }
else if (vers->vn_user[0] == '-') else if (vers->vn_user[0] == '-')
{ {
freevers_ts (&vers); if (!quiet)
return (0); error (0, 0, "file `%s' already scheduled for removal", file);
} }
else else
{ {
@ -148,12 +155,10 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
(void) strcpy (fname, "-"); (void) strcpy (fname, "-");
(void) strcat (fname, vers->vn_user); (void) strcat (fname, vers->vn_user);
Register (entries, file, fname, vers->ts_rcs, vers->options, Register (entries, file, fname, vers->ts_rcs, vers->options,
vers->tag, vers->date); vers->tag, vers->date, vers->ts_conflict);
if (!quiet) if (!quiet)
{ error (0, 0, "scheduling `%s' for removal", file);
error (0, 0, "scheduling %s for removal", file); removed_files++;
removed_files++;
}
} }
freevers_ts (&vers); freevers_ts (&vers);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Name of Repository * Name of Repository
* *
@ -13,7 +13,8 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)repos.c 1.28 92/03/31"; static char rcsid[] = "$CVSid: @(#)repos.c 1.32 94/09/23 $";
USE(rcsid)
#endif #endif
char * char *
@ -112,7 +113,7 @@ Name_Repository (dir, update_dir)
error (1, errno, "cannot read %s", CVSADM_REP); error (1, errno, "cannot read %s", CVSADM_REP);
} }
(void) fclose (fpin); (void) fclose (fpin);
if ((cp = rindex (repos, '\n')) != NULL) if ((cp = strrchr (repos, '\n')) != NULL)
*cp = '\0'; /* strip the newline */ *cp = '\0'; /* strip the newline */
/* /*

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Rtag * Rtag
* *
@ -14,24 +14,18 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)rtag.c 1.57 92/04/10"; static char rcsid[] = "$CVSid: @(#)rtag.c 1.61 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype rtag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype rtag_dirproc (char *dir, char *repos, char *update_dir); static int rtag_fileproc PROTO((char *file, char *update_dir,
static int rtag_fileproc (char *file, char *update_dir,
char *repository, List * entries, char *repository, List * entries,
List * srcfiles); List * srcfiles));
static int rtag_proc (int *pargc, char *argv[], char *xwhere, static int rtag_proc PROTO((int *pargc, char *argv[], char *xwhere,
char *mwhere, char *mfile, int shorten, char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg); int local_specified, char *mname, char *msg));
static int rtag_delete (RCSNode *rcsfile); static int rtag_delete PROTO((RCSNode *rcsfile));
#else
static int rtag_proc ();
static int rtag_fileproc ();
static Dtype rtag_dirproc ();
static int rtag_delete ();
#endif /* __STDC__ */
static char *symtag; static char *symtag;
static char *numtag; static char *numtag;
@ -41,10 +35,11 @@ static int branch_mode; /* make an automagic "branch" tag */
static char *date; static char *date;
static int local; /* recursive by default */ static int local; /* recursive by default */
static int force_tag_match = 1; /* force by default */ static int force_tag_match = 1; /* force by default */
static int force_tag_move; /* don't move existing tags by default */
static char *rtag_usage[] = static char *rtag_usage[] =
{ {
"Usage: %s %s [-QaflRnq] [-b] [-d] [-r tag|-D date] tag modules...\n", "Usage: %s %s [-QaflRnqF] [-b] [-d] [-r tag|-D date] tag modules...\n",
"\t-Q\tReally quiet.\n", "\t-Q\tReally quiet.\n",
"\t-a\tClear tag from removed files that would not otherwise be tagged.\n", "\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
"\t-f\tForce a head revision match if tag/date not found.\n", "\t-f\tForce a head revision match if tag/date not found.\n",
@ -55,6 +50,7 @@ static char *rtag_usage[] =
"\t-d\tDelete the given Tag.\n", "\t-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n", "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-[rD]\tExisting tag or Date.\n", "\t-[rD]\tExisting tag or Date.\n",
"\t-F\tMove tag if it already exists\n",
NULL NULL
}; };
@ -73,7 +69,7 @@ rtag (argc, argv)
usage (rtag_usage); usage (rtag_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "anfQqlRdbr:D:")) != -1) while ((c = getopt (argc, argv, "FanfQqlRdbr:D:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -112,6 +108,9 @@ rtag (argc, argv)
free (date); free (date);
date = Make_Date (optarg); date = Make_Date (optarg);
break; break;
case 'F':
force_tag_move = 1;
break;
case '?': case '?':
default: default:
usage (rtag_usage); usage (rtag_usage);
@ -178,7 +177,7 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
char path[PATH_MAX]; char path[PATH_MAX];
/* if the portion of the module is a path, put the dir part on repos */ /* if the portion of the module is a path, put the dir part on repos */
if ((cp = rindex (mfile, '/')) != NULL) if ((cp = strrchr (mfile, '/')) != NULL)
{ {
*cp = '\0'; *cp = '\0';
(void) strcat (repository, "/"); (void) strcat (repository, "/");
@ -224,7 +223,7 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc, err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
(int (*) ()) NULL, *pargc - 1, argv + 1, local, (int (*) ()) NULL, *pargc - 1, argv + 1, local,
which, 0, 1, where, 1); which, 0, 1, where, 1, 1);
return (err); return (err);
} }
@ -304,40 +303,60 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
} }
else else
{ {
char *oversion; char *oversion;
/*
* As an enhancement for the case where a tag is being re-applied to
* a large body of a module, make one extra call to Version_Number to
* see if the tag is already set in the RCS file. If so, check to
* see if it needs to be moved. If not, do nothing. This will
* likely save a lot of time when simply moving the tag to the
* "current" head revisions of a module -- which I have found to be a
* typical tagging operation.
*/
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
oversion = RCS_getversion (rcsfile, symtag, (char *) 0, 1);
if (oversion != NULL)
{
int isbranch = RCS_isbranch (file, symtag, srcfiles);
/* /*
* As an enhancement for the case where a tag is being re-applied to * if versions the same and neither old or new are branches don't
* a large body of a module, make one extra call to Version_Number to * have to do anything
* see if the tag is already set in the RCS file. If so, check to */
* see if it needs to be moved. If not, do nothing. This will if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
* likely save a lot of time when simply moving the tag to the {
* "current" head revisions of a module -- which I have found to be a free (oversion);
* typical tagging operation. free (version);
*/ return (0);
oversion = RCS_getversion (rcsfile, symtag, (char *) 0, 1); }
if (oversion != NULL)
{ if (!force_tag_move) { /* we're NOT going to move the tag */
if (strcmp (version, oversion) == 0) if (update_dir[0])
{ (void) printf ("W %s/%s", update_dir, file);
free (version); else
free (oversion); (void) printf ("W %s", file);
return (0);
} (void) printf (" : %s already exists on %s %s",
free (oversion); symtag, isbranch ? "branch" : "version", oversion);
} (void) printf (" : NOT MOVING tag to %s %s\n",
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version; branch_mode ? "branch" : "version", rev);
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev); free (oversion);
free (version);
return (0);
}
free (oversion);
}
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
} }
run_arg (rcsfile->path); run_arg (rcsfile->path);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0) if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
{ {
if (!quiet) error (1, retcode == -1 ? errno : 0,
error (0, retcode == -1 ? errno : 0, "failed to set tag `%s' to revision `%s' in `%s'",
"failed to set tag `%s' to revision `%s' in `%s'", symtag, rev, rcsfile->path);
symtag, rev, rcsfile->path); free (version);
free (version); return (1);
return (1);
} }
free (version); free (version);
return (0); return (0);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Status Information * Status Information
*/ */
@ -11,23 +11,20 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)status.c 1.48 92/03/31"; static char rcsid[] = "$CVSid: @(#)status.c 1.56 94/10/07 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype status_dirproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype status_dirproc (char *dir, char *repos, char *update_dir); static int status_fileproc PROTO((char *file, char *update_dir,
static int status_fileproc (char *file, char *update_dir,
char *repository, List * entries, char *repository, List * entries,
List * srcfiles); List * srcfiles));
static int tag_list_proc (Node * p); static int tag_list_proc PROTO((Node * p, void *closure));
#else
static int tag_list_proc ();
static int status_fileproc ();
static Dtype status_dirproc ();
#endif /* __STDC__ */
static int local = 0; static int local = 0;
static int long_format = 0; static int long_format = 0;
static char *xfile;
static List *xsrcfiles;
static char *status_usage[] = static char *status_usage[] =
{ {
@ -50,7 +47,7 @@ status (argc, argv)
usage (status_usage); usage (status_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "vlR")) != -1) while ((c = getopt (argc, argv, "vlR")) != -1)
{ {
switch (c) switch (c)
{ {
@ -75,7 +72,7 @@ status (argc, argv)
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc, err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
(int (*) ()) NULL, argc, argv, local, (int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1); W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err); return (err);
} }
@ -97,7 +94,8 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
Vers_TS *vers; Vers_TS *vers;
status = Classify_File (file, (char *) NULL, (char *) NULL, (char *) NULL, status = Classify_File (file, (char *) NULL, (char *) NULL, (char *) NULL,
1, 0, repository, entries, srcfiles, &vers); 1, 0, repository, entries, srcfiles, &vers,
update_dir, 0);
switch (status) switch (status)
{ {
case T_UNKNOWN: case T_UNKNOWN:
@ -116,7 +114,10 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
sstat = "Locally Removed"; sstat = "Locally Removed";
break; break;
case T_MODIFIED: case T_MODIFIED:
sstat = "Locally Modified"; if (vers->ts_conflict)
sstat = "Unresolved Conflict";
else
sstat = "Locally Modified";
break; break;
case T_REMOVE_ENTRY: case T_REMOVE_ENTRY:
sstat = "Entry Invalid"; sstat = "Entry Invalid";
@ -136,20 +137,20 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
if (vers->ts_user == NULL) if (vers->ts_user == NULL)
(void) printf ("File: no file %s\t\tStatus: %s\n\n", file, sstat); (void) printf ("File: no file %s\t\tStatus: %s\n\n", file, sstat);
else else
(void) printf ("File: %-17.17s\tStatus: %s\n\n", file, sstat); (void) printf ("File: %-17s\tStatus: %s\n\n", file, sstat);
if (vers->vn_user == NULL) if (vers->vn_user == NULL)
(void) printf (" Version:\t\tNo entry for %s\n", file); (void) printf (" Working revision:\tNo entry for %s\n", file);
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0') else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
(void) printf (" Version:\t\tNew file!\n"); (void) printf (" Working revision:\tNew file!\n");
else else
(void) printf (" Version:\t\t%s\t%s\n", vers->vn_user, (void) printf (" Working revision:\t%s\t%s\n", vers->vn_user,
&vers->ts_rcs[25]); vers->ts_rcs);
if (vers->vn_rcs == NULL) if (vers->vn_rcs == NULL)
(void) printf (" RCS Version:\tNo revision control file\n"); (void) printf (" Repository revision:\tNo revision control file\n");
else else
(void) printf (" RCS Version:\t%s\t%s\n", vers->vn_rcs, (void) printf (" Repository revision:\t%s\t%s\n", vers->vn_rcs,
vers->srcfile->path); vers->srcfile->path);
if (vers->entdata) if (vers->entdata)
@ -161,36 +162,49 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
{ {
if (vers->vn_rcs == NULL) if (vers->vn_rcs == NULL)
(void) printf ( (void) printf (
" Sticky Tag:\t\t%s - MISSING from RCS file!\n", " Sticky Tag:\t\t%s - MISSING from RCS file!\n",
edata->tag); edata->tag);
else else
{ {
if (isdigit (edata->tag[0])) if (isdigit (edata->tag[0]))
(void) printf (" Sticky Tag:\t\t%s\n", edata->tag); (void) printf (" Sticky Tag:\t\t%s\n", edata->tag);
else else
(void) printf (" Sticky Tag:\t\t%s (%s: %s)\n", {
edata->tag, numdots (vers->vn_rcs) % 2 ? int isbranch = RCS_isbranch (file, edata->tag, srcfiles);
"revision" : "branch", vers->vn_rcs);
(void) printf (" Sticky Tag:\t\t%s (%s: %s)\n",
edata->tag,
isbranch ? "branch" : "revision",
isbranch ?
RCS_whatbranch(file, edata->tag, srcfiles) :
vers->vn_rcs);
}
} }
} }
else else
(void) printf (" Sticky Tag:\t\t(none)\n"); (void) printf (" Sticky Tag:\t\t(none)\n");
if (edata->date) if (edata->date)
(void) printf (" Sticky Date:\t%s\n", edata->date); (void) printf (" Sticky Date:\t\t%s\n", edata->date);
else else
(void) printf (" Sticky Date:\t(none)\n"); (void) printf (" Sticky Date:\t\t(none)\n");
if (edata->options && edata->options[0]) if (edata->options && edata->options[0])
(void) printf (" Sticky Options:\t%s\n", edata->options); (void) printf (" Sticky Options:\t%s\n", edata->options);
else else
(void) printf (" Sticky Options:\t(none)\n"); (void) printf (" Sticky Options:\t(none)\n");
if (long_format && vers->srcfile) if (long_format && vers->srcfile)
{ {
(void) printf ("\n Existing Tags:\n"); List *symbols = RCS_symbols(vers->srcfile);
if (vers->srcfile->symbols)
(void) walklist (vers->srcfile->symbols, tag_list_proc); (void) printf ("\n Existing Tags:\n");
if (symbols)
{
xfile = file;
xsrcfiles = srcfiles;
(void) walklist (symbols, tag_list_proc, NULL);
}
else else
(void) printf ("\tNo Tags Exist\n"); (void) printf ("\tNo Tags Exist\n");
} }
@ -220,11 +234,15 @@ status_dirproc (dir, repos, update_dir)
* Print out a tag and its type * Print out a tag and its type
*/ */
static int static int
tag_list_proc (p) tag_list_proc (p, closure)
Node *p; Node *p;
void *closure;
{ {
int isbranch = RCS_isbranch (xfile, p->key, xsrcfiles);
(void) printf ("\t%-25.25s\t(%s: %s)\n", p->key, (void) printf ("\t%-25.25s\t(%s: %s)\n", p->key,
numdots (p->data) % 2 ? "revision" : "branch", isbranch ? "branch" : "revision",
isbranch ? RCS_whatbranch(xfile, p->key, xsrcfiles) :
p->data); p->data);
return (0); return (0);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Tag * Tag
* *
@ -14,33 +14,31 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)tag.c 1.56 92/03/31"; static char rcsid[] = "$CVSid: @(#)tag.c 1.60 94/09/30 $";
USE(rcsid)
#endif #endif
#if __STDC__ static Dtype tag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static Dtype tag_dirproc (char *dir, char *repos, char *update_dir); static int tag_fileproc PROTO((char *file, char *update_dir,
static int tag_fileproc (char *file, char *update_dir,
char *repository, List * entries, char *repository, List * entries,
List * srcfiles); List * srcfiles));
#else
static int tag_fileproc ();
static Dtype tag_dirproc ();
#endif /* __STDC__ */
static char *symtag; static char *symtag;
static int delete; /* adding a tag by default */ static int delete; /* adding a tag by default */
static int branch_mode; /* make an automagic "branch" tag */ static int branch_mode; /* make an automagic "branch" tag */
static int local; /* recursive by default */ static int local; /* recursive by default */
static int force_tag_move; /* don't force tag to move by default */
static char *tag_usage[] = static char *tag_usage[] =
{ {
"Usage: %s %s [-QlRq] [-b] [-d] tag [files...]\n", "Usage: %s %s [-QlRqF] [-b] [-d] tag [files...]\n",
"\t-Q\tReally quiet.\n", "\t-Q\tReally quiet.\n",
"\t-l\tLocal directory only, not recursive.\n", "\t-l\tLocal directory only, not recursive.\n",
"\t-R\tProcess directories recursively.\n", "\t-R\tProcess directories recursively.\n",
"\t-q\tSomewhat quiet.\n", "\t-q\tSomewhat quiet.\n",
"\t-d\tDelete the given Tag.\n", "\t-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n", "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-F\tMove tag if it already exists\n",
NULL NULL
}; };
@ -56,7 +54,7 @@ tag (argc, argv)
usage (tag_usage); usage (tag_usage);
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "QqlRdb")) != -1) while ((c = getopt (argc, argv, "FQqlRdb")) != -1)
{ {
switch (c) switch (c)
{ {
@ -78,6 +76,9 @@ tag (argc, argv)
case 'b': case 'b':
branch_mode = 1; branch_mode = 1;
break; break;
case 'F':
force_tag_move = 1;
break;
case '?': case '?':
default: default:
usage (tag_usage); usage (tag_usage);
@ -100,7 +101,7 @@ tag (argc, argv)
/* start the recursion processor */ /* start the recursion processor */
err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc, err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
(int (*) ()) NULL, argc, argv, local, (int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1); W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err); return (err);
} }
@ -210,26 +211,47 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
* time when simply moving the tag to the "current" head revisions of a * time when simply moving the tag to the "current" head revisions of a
* module -- which I have found to be a typical tagging operation. * module -- which I have found to be a typical tagging operation.
*/ */
rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1); oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
if (oversion != NULL) if (oversion != NULL)
{ {
if (strcmp (version, oversion) == 0) int isbranch = RCS_isbranch (file, symtag, srcfiles);
{
free (oversion); /*
freevers_ts (&vers); * if versions the same and neither old or new are branches don't have
return (0); * to do anything
} */
free (oversion); if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
{
free (oversion);
freevers_ts (&vers);
return (0);
}
if (!force_tag_move) { /* we're NOT going to move the tag */
if (update_dir[0])
(void) printf ("W %s/%s", update_dir, file);
else
(void) printf ("W %s", file);
(void) printf (" : %s already exists on %s %s",
symtag, isbranch ? "branch" : "version", oversion);
(void) printf (" : NOT MOVING tag to %s %s\n",
branch_mode ? "branch" : "version", rev);
free (oversion);
freevers_ts (&vers);
return (0);
}
free (oversion);
} }
rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev); run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
run_arg (vers->srcfile->path); run_arg (vers->srcfile->path);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0) if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
{ {
if (!quiet) error (1, retcode == -1 ? errno : 0,
error (0, retcode == -1 ? errno : 0, "failed to set tag %s to revision %s in %s",
"failed to set tag %s to revision %s in %s", symtag, rev, vers->srcfile->path);
symtag, rev, vers->srcfile->path);
freevers_ts (&vers); freevers_ts (&vers);
return (1); return (1);
} }

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* "update" updates the version in the present directory with respect to the RCS * "update" updates the version in the present directory with respect to the RCS
* repository. The present version must have been created by "checkout". The * repository. The present version must have been created by "checkout". The
@ -36,39 +36,26 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)update.c 1.83 92/04/10"; static char rcsid[] = "$CVSid: @(#)update.c 1.95 94/10/22 $";
USE(rcsid)
#endif #endif
#if __STDC__ static int checkout_file PROTO((char *file, char *repository, List *entries,
static int checkout_file (char *file, char *repository, List *entries, List *srcfiles, Vers_TS *vers_ts, char *update_dir));
List *srcfiles, Vers_TS *vers_ts, char *update_dir); static int isemptydir PROTO((char *dir));
static int isemptydir (char *dir); static int merge_file PROTO((char *file, char *repository, List *entries,
static int merge_file (char *file, char *repository, List *entries, Vers_TS *vers, char *update_dir));
Vers_TS *vers, char *update_dir); static int scratch_file PROTO((char *file, char *repository, List * entries,
static int scratch_file (char *file, char *repository, List * entries, char *update_dir));
char *update_dir); static Dtype update_dirent_proc PROTO((char *dir, char *repository, char *update_dir));
static Dtype update_dirent_proc (char *dir, char *repository, char *update_dir); static int update_dirleave_proc PROTO((char *dir, int err, char *update_dir));
static int update_dirleave_proc (char *dir, int err, char *update_dir); static int update_file_proc PROTO((char *file, char *update_dir, char *repository,
static int update_file_proc (char *file, char *update_dir, char *repository, List * entries, List * srcfiles));
List * entries, List * srcfiles); static int update_filesdone_proc PROTO((int err, char *repository, char *update_dir));
static int update_filesdone_proc (int err, char *repository, char *update_dir); static int write_letter PROTO((char *file, int letter, char *update_dir));
static int write_letter (char *file, int letter, char *update_dir); static void ignore_files PROTO((List * ilist, char *update_dir));
static void ignore_files (List * ilist, char *update_dir); static void join_file PROTO((char *file, List *srcfiles, Vers_TS *vers_ts,
static void join_file (char *file, List *srcfiles, Vers_TS *vers_ts, char *update_dir, List *entries));
char *update_dir);
#else
static int update_file_proc ();
static int update_filesdone_proc ();
static Dtype update_dirent_proc ();
static int update_dirleave_proc ();
static int isemptydir ();
static int scratch_file ();
static int checkout_file ();
static int write_letter ();
static int merge_file ();
static void ignore_files ();
static void join_file ();
#endif /* __STDC__ */
static char *options = NULL; static char *options = NULL;
static char *tag = NULL; static char *tag = NULL;
@ -81,7 +68,7 @@ static int update_build_dirs = 0;
static int update_prune_dirs = 0; static int update_prune_dirs = 0;
static int pipeout = 0; static int pipeout = 0;
static List *ignlist = (List *) NULL; static List *ignlist = (List *) NULL;
static time_t last_register_time;
static char *update_usage[] = static char *update_usage[] =
{ {
"Usage:\n %s %s [-APQdflRpq] [-k kopt] [-r rev|-D date] [-j rev] [-I ign] [files...]\n", "Usage:\n %s %s [-APQdflRpq] [-k kopt] [-r rev|-D date] [-j rev] [-I ign] [files...]\n",
@ -121,7 +108,7 @@ update (argc, argv)
/* parse the args */ /* parse the args */
optind = 1; optind = 1;
while ((c = gnu_getopt (argc, argv, "ApPflRQqdk:r:D:j:I:")) != -1) while ((c = getopt (argc, argv, "ApPflRQqdk:r:D:j:I:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -192,7 +179,10 @@ update (argc, argv)
if (argc <= 0 && !pipeout) if (argc <= 0 && !pipeout)
{ {
if (update_build_dirs) if (update_build_dirs)
(void) unlink_file (CVSADM_ENTSTAT); {
if (unlink_file (CVSADM_ENTSTAT) < 0 && errno != ENOENT)
error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
}
/* keep the CVS/Tag file current with the specified arguments */ /* keep the CVS/Tag file current with the specified arguments */
if (aflag || tag || date) if (aflag || tag || date)
@ -256,14 +246,14 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
/* setup the join support */ /* setup the join support */
join_rev1 = xjoin_rev1; join_rev1 = xjoin_rev1;
join_rev2 = xjoin_rev2; join_rev2 = xjoin_rev2;
if (join_rev1 && (cp = index (join_rev1, ':')) != NULL) if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
{ {
*cp++ = '\0'; *cp++ = '\0';
date_rev1 = Make_Date (cp); date_rev1 = Make_Date (cp);
} }
else else
date_rev1 = (char *) NULL; date_rev1 = (char *) NULL;
if (join_rev2 && (cp = index (join_rev2, ':')) != NULL) if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
{ {
*cp++ = '\0'; *cp++ = '\0';
date_rev2 = Make_Date (cp); date_rev2 = Make_Date (cp);
@ -275,7 +265,18 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
err = start_recursion (update_file_proc, update_filesdone_proc, err = start_recursion (update_file_proc, update_filesdone_proc,
update_dirent_proc, update_dirleave_proc, update_dirent_proc, update_dirleave_proc,
argc, argv, local, which, aflag, 1, argc, argv, local, which, aflag, 1,
preload_update_dir, 1); preload_update_dir, 1, 0);
/* see if we need to sleep before returning */
if (last_register_time)
{
time_t now;
(void) time (&now);
if (now == last_register_time)
sleep (1); /* to avoid time-stamp races */
}
return (err); return (err);
} }
@ -303,7 +304,8 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
Vers_TS *vers; Vers_TS *vers;
status = Classify_File (file, tag, date, options, force_tag_match, status = Classify_File (file, tag, date, options, force_tag_match,
aflag, repository, entries, srcfiles, &vers); aflag, repository, entries, srcfiles, &vers,
update_dir, pipeout);
if (pipeout) if (pipeout)
{ {
/* /*
@ -351,13 +353,65 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
break; break;
case T_CONFLICT: /* old punt-type errors */ case T_CONFLICT: /* old punt-type errors */
retval = 1; retval = 1;
(void) write_letter (file, 'C', update_dir);
break; break;
case T_NEEDS_MERGE: /* needs merging */ case T_NEEDS_MERGE: /* needs merging */
retval = merge_file (file, repository, entries, retval = merge_file (file, repository, entries,
vers, update_dir); vers, update_dir);
break; break;
case T_MODIFIED: /* locally modified */ case T_MODIFIED: /* locally modified */
retval = write_letter (file, 'M', update_dir); retval = 0;
if (vers->ts_conflict)
{
char *filestamp;
int retcode;
/*
* If the timestamp has changed and no conflict indicators
* are found, it isn't a 'C' any more.
*/
filestamp = time_stamp (file);
retcode = strcmp (vers->ts_conflict, filestamp);
free (filestamp);
if (retcode)
{
/*
* If the timestamps differ, look for Conflict
* indicators to see if 'C' anyway.
*/
run_setup ("%s -s", GREP);
run_arg (RCS_MERGE_PAT);
run_arg (file);
retcode = run_exec (RUN_TTY, RUN_TTY,
RUN_TTY,RUN_NORMAL);
if (retcode == -1)
{
if (update_dir[0] == '\0')
error (1, errno,
"fork failed while examining conflict in `%s'",
file);
else
error (1, errno,
"fork failed while examining conflict in `%s/%s'",
update_dir, file);
}
}
if (!retcode)
{
(void) write_letter (file, 'C', update_dir);
retval = 1;
}
else
{
/* Reregister to clear conflict flag. */
Register (entries, file, vers->vn_rcs, vers->ts_rcs,
vers->options, vers->tag,
vers->date, (char *)0);
}
}
if (!retval)
retval = write_letter (file, 'M', update_dir);
break; break;
case T_CHECKOUT: /* needs checkout */ case T_CHECKOUT: /* needs checkout */
retval = checkout_file (file, repository, entries, srcfiles, retval = checkout_file (file, repository, entries, srcfiles,
@ -382,7 +436,7 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
/* only try to join if things have gone well thus far */ /* only try to join if things have gone well thus far */
if (retval == 0 && join_rev1) if (retval == 0 && join_rev1)
join_file (file, srcfiles, vers, update_dir); join_file (file, srcfiles, vers, update_dir, entries);
/* if this directory has an ignore list, add this file to it */ /* if this directory has an ignore list, add this file to it */
if (ignlist) if (ignlist)
@ -392,7 +446,8 @@ update_file_proc (file, update_dir, repository, entries, srcfiles)
p = getnode (); p = getnode ();
p->type = FILES; p->type = FILES;
p->key = xstrdup (file); p->key = xstrdup (file);
(void) addnode (ignlist, p); if (addnode (ignlist, p) != 0)
freenode (p);
} }
freevers_ts (&vers); freevers_ts (&vers);
@ -423,6 +478,14 @@ update_filesdone_proc (err, repository, update_dir)
run_arg (CVSADM); run_arg (CVSADM);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
} }
#ifdef CVSADM_ROOT
else
{
/* If there is no CVS/Root file, add one */
if (!isfile (CVSADM_ROOT))
Create_Root( (char *) NULL, CVSroot );
}
#endif /* CVSADM_ROOT */
return (err); return (err);
} }
@ -441,6 +504,14 @@ update_dirent_proc (dir, repository, update_dir)
char *repository; char *repository;
char *update_dir; char *update_dir;
{ {
if (ignore_directory (update_dir))
{
/* print the warm fuzzy message */
if (!quiet)
error (0, 0, "Ignoring %s", update_dir);
return R_SKIP_ALL;
}
if (!isdir (dir)) if (!isdir (dir))
{ {
/* if we aren't building dirs, blow it off */ /* if we aren't building dirs, blow it off */
@ -472,7 +543,8 @@ update_dirent_proc (dir, repository, update_dir)
char tmp[PATH_MAX]; char tmp[PATH_MAX];
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT); (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
(void) unlink_file (tmp); if (unlink_file (tmp) < 0 && errno != ENOENT)
error (1, errno, "cannot remove file %s", tmp);
} }
/* keep the CVS/Tag file current with the specified arguments */ /* keep the CVS/Tag file current with the specified arguments */
@ -515,7 +587,7 @@ update_dirleave_proc (dir, err, update_dir)
repository = Name_Repository ((char *) NULL, update_dir); repository = Name_Repository ((char *) NULL, update_dir);
if (fgets (line, sizeof (line), fp) != NULL) if (fgets (line, sizeof (line), fp) != NULL)
{ {
if ((cp = rindex (line, '\n')) != NULL) if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0'; *cp = '\0';
run_setup ("%s %s", line, repository); run_setup ("%s %s", line, repository);
(void) printf ("%s %s: Executing '", program_name, command_name); (void) printf ("%s %s: Executing '", program_name, command_name);
@ -534,6 +606,35 @@ update_dirleave_proc (dir, err, update_dir)
run_arg (CVSADM); run_arg (CVSADM);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
} }
#ifdef CVSADM_ROOT
else
{
/* If there is no CVS/Root file, add one */
if (!isreadable (CVSADM_ROOT))
{
if (isfile (CVSADM_ROOT))
{
error (0, 0, "bad permissions %s/%s deleteing it", update_dir,
CVSADM_ROOT);
if (unlink_file (CVSADM_ROOT) == -1)
{
error (0, errno, "delete failed for %s/%s",
update_dir, CVSADM_ROOT);
}
}
Create_Root( (char *) NULL, CVSroot );
}
else
{
char *root = Name_Root( (char *) NULL, update_dir);
if (root == NULL)
Create_Root( (char *) NULL, CVSroot );
else
free (root); /* all is well, release the storage */
}
}
#endif /* CVSADM_ROOT */
/* Prune empty dirs on the way out - if necessary */ /* Prune empty dirs on the way out - if necessary */
(void) chdir (".."); (void) chdir ("..");
@ -556,7 +657,7 @@ isemptydir (dir)
char *dir; char *dir;
{ {
DIR *dirp; DIR *dirp;
struct direct *dp; struct dirent *dp;
if ((dirp = opendir (dir)) == NULL) if ((dirp = opendir (dir)) == NULL)
{ {
@ -671,8 +772,12 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
force_tag_match, set_time, entries, srcfiles); force_tag_match, set_time, entries, srcfiles);
if (strcmp (xvers_ts->options, "-V4") == 0) if (strcmp (xvers_ts->options, "-V4") == 0)
xvers_ts->options[0] = '\0'; xvers_ts->options[0] = '\0';
(void) time (&last_register_time);
Register (entries, file, xvers_ts->vn_rcs, xvers_ts->ts_user, Register (entries, file, xvers_ts->vn_rcs, xvers_ts->ts_user,
xvers_ts->options, xvers_ts->tag, xvers_ts->date); xvers_ts->options, xvers_ts->tag, xvers_ts->date,
(char *)0); /* Clear conflict flag on fresh checkout */
/* fix up the vers structure, in case it is used by join */ /* fix up the vers structure, in case it is used by join */
if (join_rev1) if (join_rev1)
@ -727,7 +832,7 @@ checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir)
static int static int
write_letter (file, letter, update_dir) write_letter (file, letter, update_dir)
char *file; char *file;
char letter; int letter;
char *update_dir; char *update_dir;
{ {
if (!really_quiet) if (!really_quiet)
@ -791,11 +896,20 @@ merge_file (file, repository, entries, vers, update_dir)
rename_file (backup, file); rename_file (backup, file);
return (1); return (1);
} }
/* XXX - Might want to make sure that rcsmerge changed the file */
if (strcmp (vers->options, "-V4") == 0) if (strcmp (vers->options, "-V4") == 0)
vers->options[0] = '\0'; vers->options[0] = '\0';
Register (entries, file, vers->vn_rcs, vers->ts_rcs, vers->options, (void) time (&last_register_time);
vers->tag, vers->date); {
char *cp = 0;
if (status)
cp = time_stamp (file);
Register (entries, file, vers->vn_rcs, vers->ts_rcs, vers->options,
vers->tag, vers->date, cp);
if (cp)
free (cp);
}
/* fix up the vers structure, in case it is used by join */ /* fix up the vers structure, in case it is used by join */
if (join_rev1) if (join_rev1)
@ -805,6 +919,14 @@ merge_file (file, repository, entries, vers, update_dir)
vers->vn_user = xstrdup (vers->vn_rcs); vers->vn_user = xstrdup (vers->vn_rcs);
} }
if (!xcmp (backup, file))
{
printf ("%s already contains the differences between %s and %s\n",
user, vers->vn_user, vers->vn_rcs);
history_write ('G', update_dir, vers->vn_rcs, file, repository);
return (0);
}
/* possibly run GREP to see if there appear to be conflicts in the file */ /* possibly run GREP to see if there appear to be conflicts in the file */
run_setup ("%s -s", GREP); run_setup ("%s -s", GREP);
run_arg (RCS_MERGE_PAT); run_arg (RCS_MERGE_PAT);
@ -839,98 +961,216 @@ merge_file (file, repository, entries, vers, update_dir)
* (-j option) * (-j option)
*/ */
static void static void
join_file (file, srcfiles, vers, update_dir) join_file (file, srcfiles, vers, update_dir, entries)
char *file; char *file;
List *srcfiles; List *srcfiles;
Vers_TS *vers; Vers_TS *vers;
char *update_dir; char *update_dir;
List *entries;
{ {
char user[PATH_MAX]; char user[PATH_MAX];
char backup[PATH_MAX]; char backup[PATH_MAX];
char *rev, *baserev;
char *options; char *options;
int status; int status;
char *rev1;
char *rev2;
char *jrev1;
char *jrev2;
char *jdate1;
char *jdate2;
jrev1 = join_rev1;
jrev2 = join_rev2;
jdate1 = date_rev1;
jdate2 = date_rev2;
/* determine if we need to do anything at all */ /* determine if we need to do anything at all */
if (vers->vn_user == NULL || vers->srcfile == NULL || if (vers->srcfile == NULL ||
vers->srcfile->path == NULL) vers->srcfile->path == NULL)
{ {
return; return;
} }
/* special handling when two revisions are specified */ /* in all cases, use two revs. */
if (join_rev1 && join_rev2)
/* if only one rev is specified, it becomes the second rev */
if (jrev2 == NULL)
{ {
rev = RCS_getversion (vers->srcfile, join_rev2, date_rev2, 1); jrev2 = jrev1;
if (rev == NULL) jrev1 = NULL;
jdate2 = jdate1;
jdate1 = NULL;
}
/* convert the second rev spec, walking branches and dates. */
rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1);
if (rev2 == NULL)
{
if (!quiet)
{ {
if (!quiet && date_rev2 == NULL) if (jdate2 != NULL)
error (0, 0, error (0, 0,
"cannot find revision %s in file %s", join_rev2, file); "cannot find revision %s as of %s in file %s",
jrev2, jdate2, file);
else
error (0, 0,
"cannot find revision %s in file %s",
jrev2, file);
return; return;
} }
}
/* skip joining identical revs */
if (strcmp (rev2, vers->vn_user) == 0) /* no merge necessary */
{
free (rev2);
return;
}
baserev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1); if (jrev1 == NULL)
if (baserev == NULL) {
char *tst;
/* if the first rev is missing, then it is implied to be the
greatest common ancestor of both the join rev, and the
checked out rev. */
tst = vers->vn_user;
if (*tst == '!')
{ {
if (!quiet && date_rev1 == NULL) /* file was dead. merge anyway and pretend it's been
error (0, 0, added. */
"cannot find revision %s in file %s", join_rev1, file); ++tst;
free (rev); Register (entries, file, "0", vers->ts_user, vers->options,
return; vers->tag, (char *) 0, (char *) 0);
}
rev1 = gca (tst, rev2);
if (rev1 == NULL)
{
/* this should not be possible */
error (0, 0, "bad gca");
abort();
} }
/* tst = RCS_gettag (vers->srcfile, rev2, 1);
* nothing to do if: if (tst == NULL)
* second revision matches our BASE revision (vn_user) &&
* both revisions are on the same branch
*/
if (strcmp (vers->vn_user, rev) == 0 &&
numdots (baserev) == numdots (rev))
{ {
/* might be the same branch. take a real look */ /* this should not be possible. */
char *dot = rindex (baserev, '.'); error (0, 0, "cannot find gca");
int len = (dot - baserev) + 1; abort();
}
if (strncmp (baserev, rev, len) == 0) free (tst);
return;
/* these two cases are noops */
if (strcmp (rev1, rev2) == 0)
{
free (rev1);
free (rev2);
return;
} }
} }
else else
{ {
rev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1); /* otherwise, convert the first rev spec, walking branches and
if (rev == NULL) dates. */
return;
if (strcmp (rev, vers->vn_user) == 0) /* no merge necessary */
{
free (rev);
return;
}
baserev = RCS_whatbranch (file, join_rev1, srcfiles); rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1);
if (baserev) if (rev1 == NULL
&& !quiet)
{ {
char *cp; if (jdate1 != NULL)
error (0, 0,
/* we get a branch -- turn it into a revision, or NULL if trunk */ "cannot find revision %s as of %s in file %s",
if ((cp = rindex (baserev, '.')) == NULL) jrev1, jdate1, file);
{
free (baserev);
baserev = (char *) NULL;
}
else else
*cp = '\0'; error (0, 0,
"cannot find revision %s in file %s",
jrev1, file);
return;
} }
} }
if (baserev && strcmp (baserev, rev) == 0)
{
/* they match -> nothing to do */
free (rev);
free (baserev);
return;
}
/* OK, so we have a revision and possibly a base revision; continue on */ /* do the join */
#if 0
dome {
/* special handling when two revisions are specified */
if (join_rev1 && join_rev2)
{
rev = RCS_getversion (vers->srcfile, join_rev2, date_rev2, 1);
if (rev == NULL)
{
if (!quiet && date_rev2 == NULL)
error (0, 0,
"cannot find revision %s in file %s", join_rev2, file);
return;
}
baserev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1);
if (baserev == NULL)
{
if (!quiet && date_rev1 == NULL)
error (0, 0,
"cannot find revision %s in file %s", join_rev1, file);
free (rev);
return;
}
/*
* nothing to do if:
* second revision matches our BASE revision (vn_user) &&
* both revisions are on the same branch
*/
if (strcmp (vers->vn_user, rev) == 0 &&
numdots (baserev) == numdots (rev))
{
/* might be the same branch. take a real look */
char *dot = strrchr (baserev, '.');
int len = (dot - baserev) + 1;
if (strncmp (baserev, rev, len) == 0)
return;
}
}
else
{
rev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1);
if (rev == NULL)
return;
if (strcmp (rev, vers->vn_user) == 0) /* no merge necessary */
{
free (rev);
return;
}
baserev = RCS_whatbranch (file, join_rev1, srcfiles);
if (baserev)
{
char *cp;
/* we get a branch -- turn it into a revision, or NULL if trunk */
if ((cp = strrchr (baserev, '.')) == NULL)
{
free (baserev);
baserev = (char *) NULL;
}
else
*cp = '\0';
}
}
if (baserev && strcmp (baserev, rev) == 0)
{
/* they match -> nothing to do */
free (rev);
free (baserev);
return;
}
}
#endif
/* OK, so we have two revisions; continue on */
/* /*
* The users currently modified file is moved to a backup file name * The users currently modified file is moved to a backup file name
@ -951,13 +1191,15 @@ join_file (file, srcfiles, vers, update_dir)
options = vers->options; options = vers->options;
#ifdef HAVE_RCS5 #ifdef HAVE_RCS5
#if 0
if (*options == '\0') if (*options == '\0')
options = "-kk"; /* to ignore keyword expansions */ options = "-kk"; /* to ignore keyword expansions */
#endif
#endif #endif
/* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */ /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */
run_setup ("%s%s %s %s%s -r%s", Rcsbin, RCS_RCSMERGE, options, run_setup ("%s%s %s -r%s -r%s", Rcsbin, RCS_RCSMERGE, options,
baserev ? "-r" : "", baserev ? baserev : "", rev); rev1, rev2);
run_arg (vers->srcfile->path); run_arg (vers->srcfile->path);
status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
if (status != 0 if (status != 0
@ -967,14 +1209,28 @@ join_file (file, srcfiles, vers, update_dir)
) )
{ {
error (0, status == -1 ? errno : 0, error (0, status == -1 ? errno : 0,
"could not merge revision %s of %s", rev, user); "could not merge revision %s of %s", rev2, user);
error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
user, backup); user, backup);
rename_file (backup, file); rename_file (backup, file);
} }
free (rev); free (rev1);
if (baserev) free (rev2);
free (baserev);
#ifdef HAVE_RCS5
if (status == 1)
{
char *cp = 0;
if (status)
cp = time_stamp (file);
Register (entries, file, vers->vn_rcs, vers->ts_rcs, vers->options,
vers->tag, vers->date, cp);
if (cp)
free(cp);
}
#endif
return; return;
} }
@ -988,7 +1244,7 @@ ignore_files (ilist, update_dir)
char *update_dir; char *update_dir;
{ {
DIR *dirp; DIR *dirp;
struct direct *dp; struct dirent *dp;
struct stat sb; struct stat sb;
char *file; char *file;
char *xdir; char *xdir;
@ -1011,18 +1267,47 @@ ignore_files (ilist, update_dir)
continue; continue;
if (findnode (ilist, file) != NULL) if (findnode (ilist, file) != NULL)
continue; continue;
if (lstat (file, &sb) != -1)
{ if (
if (S_ISDIR (sb.st_mode)) #ifdef DT_DIR
continue; dp->d_type != DT_UNKNOWN ||
#ifdef S_IFLNK
if (S_ISLNK (sb.st_mode))
continue;
#endif #endif
} lstat(file, &sb) != -1)
{
if (
#ifdef DT_DIR
dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN &&
#endif
S_ISDIR(sb.st_mode))
{
char temp[PATH_MAX];
(void) sprintf (temp, "%s/%s", file, CVSADM);
if (isdir (temp))
continue;
}
#ifdef S_ISLNK
else if (
#ifdef DT_DIR
dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN &&
#endif
S_ISLNK(sb.st_mode))
{
continue;
}
#endif
}
if (ign_name (file)) if (ign_name (file))
continue; continue;
(void) write_letter (file, '?', xdir); (void) write_letter (file, '?', xdir);
} }
(void) closedir (dirp); (void) closedir (dirp);
} }
int
joining ()
{
return (join_rev1 != NULL);
}

View File

@ -3,16 +3,17 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)vers_ts.c 1.36 92/03/31"; static char rcsid[] = "$CVSid: @(#)vers_ts.c 1.45 94/10/07 $";
USE(rcsid)
#endif #endif
extern char *ctime (); /* XXX - should use gmtime/asctime */ #define ctime(X) do not use ctime, please
/* /*
* Fill in and return a Vers_TS structure "user" is the name of the local * Fill in and return a Vers_TS structure "user" is the name of the local
@ -39,7 +40,7 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
/* get a new Vers_TS struct */ /* get a new Vers_TS struct */
vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS)); vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
bzero ((char *) vers_ts, sizeof (*vers_ts)); memset ((char *) vers_ts, 0, sizeof (*vers_ts));
/* /*
* look up the entries file entry and fill in the version and timestamp * look up the entries file entry and fill in the version and timestamp
@ -63,6 +64,7 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
vers_ts->vn_user = xstrdup (entdata->version); vers_ts->vn_user = xstrdup (entdata->version);
vers_ts->ts_rcs = xstrdup (entdata->timestamp); vers_ts->ts_rcs = xstrdup (entdata->timestamp);
vers_ts->ts_conflict = xstrdup (entdata->conflict);
if (!tag) if (!tag)
{ {
if (!(sdtp && sdtp->aflag)) if (!(sdtp && sdtp->aflag))
@ -124,8 +126,10 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
else else
rcsdata = NULL; rcsdata = NULL;
} }
else else if (repository != NULL)
rcsdata = RCS_parse (user, repository); rcsdata = RCS_parse (user, repository);
else
rcsdata = NULL;
if (rcsdata != NULL) if (rcsdata != NULL)
{ {
@ -141,7 +145,7 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
else else
vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag, vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
vers_ts->date, force_tag_match); vers_ts->date, force_tag_match);
} }
/* /*
* If the source control file exists and has the requested revision, * If the source control file exists and has the requested revision,
@ -152,16 +156,19 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
{ {
struct utimbuf t; struct utimbuf t;
memset ((char *) &t, 0, sizeof (t));
if (vers_ts->vn_rcs && if (vers_ts->vn_rcs &&
(t.actime = t.modtime = RCS_getrevtime (rcsdata, vers_ts->vn_rcs, (t.actime = t.modtime = RCS_getrevtime (rcsdata,
(char *) 0, 0)) != -1) vers_ts->vn_rcs, (char *) 0, 0)) != -1)
(void) utime (user, &t); (void) utime (user, &t);
} }
} }
/* get user file time-stamp in ts_user */ /* get user file time-stamp in ts_user */
if (entries != (List *) NULL) if (entries != (List *) NULL)
vers_ts->ts_user = time_stamp (user); {
vers_ts->ts_user = time_stamp (user);
}
return (vers_ts); return (vers_ts);
} }
@ -184,13 +191,10 @@ time_stamp (file)
} }
else else
{ {
ts = xmalloc (51); /* 51 = 2 ctime strings + NULL */ ts = xmalloc (25);
cp = ctime (&sb.st_ctime); /* copy in the create time */ cp = asctime (gmtime (&sb.st_mtime)); /* copy in the modify time */
cp[24] = ' '; cp[24] = 0;
(void) strcpy (ts, cp); (void) strcpy (ts, cp);
cp = ctime (&sb.st_mtime); /* copy in the modify time */
cp[24] = '\0';
(void) strcat (ts, cp);
} }
return (ts); return (ts);
@ -219,6 +223,8 @@ freevers_ts (versp)
free ((*versp)->tag); free ((*versp)->tag);
if ((*versp)->date) if ((*versp)->date)
free ((*versp)->date); free ((*versp)->date);
if ((*versp)->ts_conflict)
free ((*versp)->ts_conflict);
free ((char *) *versp); free ((char *) *versp);
*versp = (Vers_TS *) NULL; *versp = (Vers_TS *) NULL;
} }

View File

@ -1,14 +1,18 @@
#! /bin/sh
: :
# #
# Copyright (c) 1992, Brian Berliner # Copyright (c) 1992, Brian Berliner
# #
# You may distribute under the terms of the GNU General Public License as # You may distribute under the terms of the GNU General Public License as
# specified in the README file that comes with the CVS 1.3 kit. # specified in the README file that comes with the CVS 1.4 kit.
# #
# @(#)cvsinit 1.1 92/03/31 # $CVSid: @(#)cvsinit.sh 1.1 94/10/22 $
# #
# This script should be run once to help you setup your site for CVS. # This script should be run once to help you setup your site for CVS.
# this line is edited by Makefile when creating cvsinit.inst
CVSLIB="xLIBDIRx"
# Make sure that the CVSROOT variable is set # Make sure that the CVSROOT variable is set
if [ "x$CVSROOT" = x ]; then if [ "x$CVSROOT" = x ]; then
echo "The CVSROOT environment variable is not set." echo "The CVSROOT environment variable is not set."
@ -155,9 +159,9 @@ else
for perlpath in `echo $PATH | sed -e 's/:/ /g'` x; do for perlpath in `echo $PATH | sed -e 's/:/ /g'` x; do
if [ -f $perlpath/perl ]; then if [ -f $perlpath/perl ]; then
echo "#!$perlpath/perl" > $CVSROOT/CVSROOT/log.pl echo "#!$perlpath/perl" > $CVSROOT/CVSROOT/log.pl
cat contrib/log.pl >> $CVSROOT/CVSROOT/log.pl cat $CVSLIB/contrib/log.pl >> $CVSROOT/CVSROOT/log.pl
chmod 755 $CVSROOT/CVSROOT/log.pl chmod 755 $CVSROOT/CVSROOT/log.pl
cp examples/loginfo $CVSROOT/CVSROOT/loginfo cp $CVSLIB/examples/loginfo $CVSROOT/CVSROOT/loginfo
break break
fi fi
done done
@ -207,13 +211,15 @@ for info in commitinfo rcsinfo editinfo; do
else else
echo "The $CVSROOT/CVSROOT/$info file does not exist." echo "The $CVSROOT/CVSROOT/$info file does not exist."
echo "Making a simple one for you..." echo "Making a simple one for you..."
sed -e 's/^\([^#]\)/#\1/' examples/$info > $CVSROOT/CVSROOT/$info sed -e 's/^\([^#]\)/#\1/' $CVSLIB/examples/$info > $CVSROOT/CVSROOT/$info
fi fi
(cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info) (cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info)
echo "" echo ""
fi fi
done done
# XXX - also add a stub for the cvsignore file
# Turn on history logging by default # Turn on history logging by default
if [ ! -f $CVSROOT/CVSROOT/history ]; then if [ ! -f $CVSROOT/CVSROOT/history ]; then
echo "Enabling CVS history logging..." echo "Enabling CVS history logging..."

View File

@ -1,5 +1,5 @@
# #
# commitinfo,v 1.2 1992/03/31 04:19:47 berliner Exp # $Id: commitinfo,v 1.2 1992/03/31 04:19:47 berliner Exp $
# #
# The "commitinfo" file is used to control pre-commit checks. # The "commitinfo" file is used to control pre-commit checks.
# The filter on the right is invoked with the repository and a list # The filter on the right is invoked with the repository and a list

View File

@ -1,5 +1,5 @@
# #
# editinfo,v 1.1 1992/03/21 06:49:39 berliner Exp # $Id: editinfo,v 1.1 1992/03/21 06:49:39 berliner Exp $
# #
# The "editinfo" file is used to allow verification of logging # The "editinfo" file is used to allow verification of logging
# information. It works best when a template (as specified in the # information. It works best when a template (as specified in the

View File

@ -1,5 +1,5 @@
# #
# @(#)loginfo 1.5 92/03/31 # $CVSid: @(#)loginfo 1.5 92/03/31 $
# #
# The "loginfo" file is used to control where "cvs commit" log information # The "loginfo" file is used to control where "cvs commit" log information
# is sent. The first entry on a line is a regular expression which is tested # is sent. The first entry on a line is a regular expression which is tested

View File

@ -1,6 +1,6 @@
# #
# CVS Modules file for Prisma sources # CVS Modules file for Prisma sources
# @(#)modules 1.5 92/03/31 # $CVSid: @(#)modules 1.5 92/03/31 $
# #
# Three different line formats are valid: # Three different line formats are valid:
# key -a aliases... # key -a aliases...

View File

@ -1,5 +1,5 @@
# #
# rcsinfo,v 1.3 1992/04/10 18:59:14 berliner Exp # $Id: rcsinfo,v 1.3 1992/04/10 18:59:14 berliner Exp $
# #
# The "rcsinfo" file is used to control templates with which the editor # The "rcsinfo" file is used to control templates with which the editor
# is invoked on commit and import. # is invoked on commit and import.

View File

@ -30,7 +30,7 @@
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */ static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif #endif
#ifdef emacs #if defined(emacs) || defined(HAVE_CONFIG_H)
#include "config.h" #include "config.h"
#ifdef static #ifdef static
/* actually, only want this if static is defined as "" /* actually, only want this if static is defined as ""
@ -43,7 +43,7 @@ lose
-- must know STACK_DIRECTION at compile-time -- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */ #endif /* STACK_DIRECTION undefined */
#endif /* static */ #endif /* static */
#endif /* emacs */ #endif /* emacs || HAVE_CONFIG_H*/
#if __STDC__ #if __STDC__
typedef void *pointer; /* generic pointer type */ typedef void *pointer; /* generic pointer type */

View File

@ -17,6 +17,10 @@
/* Written by David MacKenzie <djm@ai.mit.edu> */ /* Written by David MacKenzie <djm@ai.mit.edu> */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> #include <stdio.h>
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
#include <string.h> #include <string.h>

View File

@ -4,6 +4,10 @@
last edit: 11-Feb-1987 D A Gwyn last edit: 11-Feb-1987 D A Gwyn
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>

View File

@ -19,9 +19,13 @@
/* Brian Berliner added support for CVS */ /* Brian Berliner added support for CVS */
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)error.c 1.9 92/03/31"; static char rcsid[] = "$CVSid: @(#)error.c 1.13 94/09/30 $";
#endif /* not lint */ #endif /* not lint */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> #include <stdio.h>
/* turn on CVS support by default, since this is the CVS distribution */ /* turn on CVS support by default, since this is the CVS distribution */
@ -35,7 +39,7 @@ void Lock_Cleanup();
#endif /* __STDC__ */ #endif /* __STDC__ */
#endif /* CVS_SUPPORT */ #endif /* CVS_SUPPORT */
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
#if __STDC__ #if __STDC__
#include <stdarg.h> #include <stdarg.h>
@ -47,7 +51,7 @@ void Lock_Cleanup();
#else #else
#ifndef DOPRNT_MISSING #ifdef HAVE_DOPRNT
#define va_alist args #define va_alist args
#define va_dcl int args; #define va_dcl int args;
#else #else
@ -57,7 +61,7 @@ void Lock_Cleanup();
#endif #endif
#ifdef STDC_HEADERS #if STDC_HEADERS
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#else #else
@ -68,19 +72,7 @@ void exit ();
#endif /* __STDC__ */ #endif /* __STDC__ */
#endif #endif
#ifdef STRERROR_MISSING extern char *strerror ();
static char *
strerror (errnum)
int errnum;
{
extern char *sys_errlist[];
extern int sys_nerr;
if (errnum > 0 && errnum < sys_nerr)
return sys_errlist[errnum];
return "Unknown system error";
}
#endif /* STRERROR_MISSING */
/* Print the program name and error message MESSAGE, which is a printf-style /* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args. format string with optional args.
@ -88,7 +80,7 @@ strerror (errnum)
Exit with status STATUS if it is nonzero. */ Exit with status STATUS if it is nonzero. */
/* VARARGS */ /* VARARGS */
void void
#if !defined (VPRINTF_MISSING) && __STDC__ #if defined (HAVE_VPRINTF) && __STDC__
error (int status, int errnum, char *message, ...) error (int status, int errnum, char *message, ...)
#else #else
error (status, errnum, message, va_alist) error (status, errnum, message, va_alist)
@ -102,7 +94,7 @@ error (status, errnum, message, va_alist)
#ifdef CVS_SUPPORT #ifdef CVS_SUPPORT
extern char *command_name; extern char *command_name;
#endif #endif
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
va_list args; va_list args;
#endif #endif
@ -117,12 +109,12 @@ error (status, errnum, message, va_alist)
#else #else
fprintf (stderr, "%s: ", program_name); fprintf (stderr, "%s: ", program_name);
#endif #endif
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
VA_START (args, message); VA_START (args, message);
vfprintf (stderr, message, args); vfprintf (stderr, message, args);
va_end (args); va_end (args);
#else #else
#ifndef DOPRNT_MISSING #ifdef HAVE_DOPRNT
_doprnt (message, &args, stderr); _doprnt (message, &args, stderr);
#else #else
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8); fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
@ -149,7 +141,7 @@ error (status, errnum, message, va_alist)
Exit with status STATUS if it is nonzero. */ Exit with status STATUS if it is nonzero. */
/* VARARGS */ /* VARARGS */
void void
#if !defined (VPRINTF_MISSING) && __STDC__ #if defined (HAVE_VPRINTF) && __STDC__
fperror (FILE *fp, int status, int errnum, char *message, ...) fperror (FILE *fp, int status, int errnum, char *message, ...)
#else #else
fperror (fp, status, errnum, message, va_alist) fperror (fp, status, errnum, message, va_alist)
@ -161,17 +153,17 @@ fperror (fp, status, errnum, message, va_alist)
#endif #endif
{ {
extern char *program_name; extern char *program_name;
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
va_list args; va_list args;
#endif #endif
fprintf (fp, "%s: ", program_name); fprintf (fp, "%s: ", program_name);
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
VA_START (args, message); VA_START (args, message);
vfprintf (fp, message, args); vfprintf (fp, message, args);
va_end (args); va_end (args);
#else #else
#ifndef DOPRNT_MISSING #ifdef HAVE_DOPRNT
_doprnt (message, &args, fp); _doprnt (message, &args, fp);
#else #else
fprintf (fp, message, a1, a2, a3, a4, a5, a6, a7, a8); fprintf (fp, message, a1, a2, a3, a4, a5, a6, a7, a8);

View File

@ -18,6 +18,10 @@ Cambridge, MA 02139, USA. */
/* Modified slightly by Brian Berliner <berliner@sun.com> for CVS use */ /* Modified slightly by Brian Berliner <berliner@sun.com> for CVS use */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* IGNORE(@ */ /* IGNORE(@ */
/* #include <ansidecl.h> */ /* #include <ansidecl.h> */
/* @) */ /* @) */
@ -28,10 +32,6 @@ Cambridge, MA 02139, USA. */
extern int errno; extern int errno;
#endif #endif
#if !__STDC__
#define const
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if /* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */ it matches, nonzero if not. */
int int

View File

@ -1,6 +1,10 @@
/* ftruncate emulations that work on some System V's. /* ftruncate emulations that work on some System V's.
This file is in the public domain. */ This file is in the public domain. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>

View File

@ -1,39 +1,110 @@
%{ %{
/* 1.8 /*
** @(#)getdate.y 1.8 92/03/03
**
** Originally written by Steven M. Bellovin <smb@research.att.com> while ** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by ** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz ** a couple of people on Usenet. Completely overhauled by Rich $alz
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990; ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
** send any email to Rich. ** send any email to Rich.
** **
** This grammar has eight shift/reduce conflicts. ** This grammar has 10 shift/reduce conflicts.
** **
** This code is in the public domain and has no copyright. ** This code is in the public domain and has no copyright.
*/ */
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */ /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
/* SUPPRESS 288 on yyerrlab *//* Label unused */ /* SUPPRESS 288 on yyerrlab *//* Label unused */
#include "system.h" #ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
#include <config.h>
#else
#include "config.h"
#endif
#endif
/* Since the code of getdate.y is not included in the Emacs executable
itself, there is no need to #define static in this file. Even if
the code were included in the Emacs executable, it probably
wouldn't do any harm to #undef it here; this will only cause
problems if we try to write to a static variable, which I don't
think this code needs to do. */
#ifdef emacs
#undef static
#endif
#include <stdio.h>
#include <ctype.h> #include <ctype.h>
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) /* The code at the top of get_date which figures out the offset of the
#ifdef __GNUC__ current time zone checks various CPP symbols to see if special
#undef alloca /* might get redefined below */ tricks are need, but defaults to using the gettimeofday system call.
Include <sys/time.h> if that will be used. */
#if defined(vms)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif #endif
#endif #endif
extern struct tm *localtime(); #ifdef timezone
#undef timezone /* needed for sgi */
#endif
#if defined(HAVE_SYS_TIMEB_H)
#include <sys/timeb.h>
#else
/*
** We use the obsolete `struct timeb' as part of our interface!
** Since the system doesn't have it, we define it here;
** our callers must do likewise.
*/
struct timeb {
time_t time; /* Seconds since the epoch */
unsigned short millitm; /* Field not used */
short timezone; /* Minutes west of GMT */
short dstflag; /* Field not used */
};
#endif /* defined(HAVE_SYS_TIMEB_H) */
#endif /* defined(vms) */
#if defined (STDC_HEADERS) || defined (USG)
#include <string.h>
#endif
/* Some old versions of bison generate parsers that use bcopy.
That loses on systems that don't provide the function, so we have
to redefine it here. */
#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
#define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif
extern struct tm *gmtime();
extern struct tm *localtime();
#define yyparse getdate_yyparse #define yyparse getdate_yyparse
#define yylex getdate_yylex #define yylex getdate_yylex
#define yyerror getdate_yyerror #define yyerror getdate_yyerror
#if !defined(lint) && !defined(SABER) #if !defined(lint) && !defined(SABER)
static char RCS[] = "@(#)getdate.y 1.8 92/03/03"; static char RCS[] = "$CVSid: @(#)getdate.y 1.11 94/09/21 $";
#endif /* !defined(lint) && !defined(SABER) */ #endif /* !defined(lint) && !defined(SABER) */
static int yylex ();
static int yyerror ();
#define EPOCH 1970 #define EPOCH 1970
#define HOUR(x) ((time_t)(x) * 60) #define HOUR(x) ((time_t)(x) * 60)
@ -202,6 +273,18 @@ date : tUNUMBER '/' tUNUMBER {
yyDay = $3; yyDay = $3;
yyYear = $5; yyYear = $5;
} }
| tUNUMBER tSNUMBER tSNUMBER {
/* ISO 8601 format. yyyy-mm-dd. */
yyYear = $1;
yyMonth = -$2;
yyDay = -$3;
}
| tUNUMBER tMONTH tSNUMBER {
/* e.g. 17-JUN-1992. */
yyDay = $1;
yyMonth = $2;
yyYear = -$3;
}
| tMONTH tUNUMBER { | tMONTH tUNUMBER {
yyMonth = $1; yyMonth = $1;
yyDay = $2; yyDay = $2;
@ -263,25 +346,24 @@ number : tUNUMBER {
yyYear = $1; yyYear = $1;
else { else {
if($1>10000) { if($1>10000) {
time_t date_part;
date_part= $1/10000;
yyHaveDate++; yyHaveDate++;
yyDay= (date_part)%100; yyDay= ($1)%100;
yyMonth= (date_part/100)%100; yyMonth= ($1/100)%100;
yyYear = date_part/10000; yyYear = $1/10000;
}
yyHaveTime++;
if ($1 < 100) {
yyHour = $1;
yyMinutes = 0;
} }
else { else {
yyHour = $1 / 100; yyHaveTime++;
yyMinutes = $1 % 100; if ($1 < 100) {
} yyHour = $1;
yySeconds = 0; yyMinutes = 0;
yyMeridian = MER24; }
else {
yyHour = $1 / 100;
yyMinutes = $1 % 100;
}
yySeconds = 0;
yyMeridian = MER24;
}
} }
} }
; ;
@ -297,7 +379,7 @@ o_merid : /* NULL */ {
%% %%
/* Month and day table. */ /* Month and day table. */
static TABLE MonthDayTable[] = { static TABLE const MonthDayTable[] = {
{ "january", tMONTH, 1 }, { "january", tMONTH, 1 },
{ "february", tMONTH, 2 }, { "february", tMONTH, 2 },
{ "march", tMONTH, 3 }, { "march", tMONTH, 3 },
@ -326,7 +408,7 @@ static TABLE MonthDayTable[] = {
}; };
/* Time units table. */ /* Time units table. */
static TABLE UnitsTable[] = { static TABLE const UnitsTable[] = {
{ "year", tMONTH_UNIT, 12 }, { "year", tMONTH_UNIT, 12 },
{ "month", tMONTH_UNIT, 1 }, { "month", tMONTH_UNIT, 1 },
{ "fortnight", tMINUTE_UNIT, 14 * 24 * 60 }, { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
@ -341,7 +423,7 @@ static TABLE UnitsTable[] = {
}; };
/* Assorted relative-time words. */ /* Assorted relative-time words. */
static TABLE OtherTable[] = { static TABLE const OtherTable[] = {
{ "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
{ "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
{ "today", tMINUTE_UNIT, 0 }, { "today", tMINUTE_UNIT, 0 },
@ -367,7 +449,7 @@ static TABLE OtherTable[] = {
/* The timezone table. */ /* The timezone table. */
/* Some of these are commented out because a time_t can't store a float. */ /* Some of these are commented out because a time_t can't store a float. */
static TABLE TimezoneTable[] = { static TABLE const TimezoneTable[] = {
{ "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
{ "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
{ "utc", tZONE, HOUR( 0) }, { "utc", tZONE, HOUR( 0) },
@ -451,7 +533,7 @@ static TABLE TimezoneTable[] = {
}; };
/* Military timezone table. */ /* Military timezone table. */
static TABLE MilitaryTable[] = { static TABLE const MilitaryTable[] = {
{ "a", tZONE, HOUR( 1) }, { "a", tZONE, HOUR( 1) },
{ "b", tZONE, HOUR( 2) }, { "b", tZONE, HOUR( 2) },
{ "c", tZONE, HOUR( 3) }, { "c", tZONE, HOUR( 3) },
@ -484,7 +566,7 @@ static TABLE MilitaryTable[] = {
/* ARGSUSED */ /* ARGSUSED */
int static int
yyerror(s) yyerror(s)
char *s; char *s;
{ {
@ -514,6 +596,8 @@ ToSeconds(Hours, Minutes, Seconds, Meridian)
if (Hours < 1 || Hours > 12) if (Hours < 1 || Hours > 12)
return -1; return -1;
return ((Hours + 12) * 60L + Minutes) * 60L + Seconds; return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
default:
abort ();
} }
/* NOTREACHED */ /* NOTREACHED */
} }
@ -530,7 +614,7 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
MERIDIAN Meridian; MERIDIAN Meridian;
DSTMODE DSTmode; DSTMODE DSTmode;
{ {
static int DaysInMonth[12] = { static int DaysInMonth[12] = {
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}; };
time_t tod; time_t tod;
@ -624,7 +708,7 @@ LookupWord(buff)
{ {
register char *p; register char *p;
register char *q; register char *q;
register TABLE *tp; register const TABLE *tp;
int i; int i;
int abbrev; int abbrev;
@ -725,7 +809,7 @@ LookupWord(buff)
} }
int static int
yylex() yylex()
{ {
register char c; register char c;
@ -777,48 +861,62 @@ yylex()
} }
} }
#define TM_YEAR_ORIGIN 1900
/* Yield A - B, measured in seconds. */
static long
difftm (a, b)
struct tm *a, *b;
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
int days = (
/* difference in day of year */
a->tm_yday - b->tm_yday
/* + intervening leap days */
+ ((ay >> 2) - (by >> 2))
- (ay/100 - by/100)
+ ((ay/100 >> 2) - (by/100 >> 2))
/* + difference in years * 365 */
+ (long)(ay-by) * 365
);
return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ (a->tm_min - b->tm_min))
+ (a->tm_sec - b->tm_sec));
}
time_t time_t
get_date(p, now) get_date(p, now)
char *p; char *p;
struct timeb *now; struct timeb *now;
{ {
struct tm *tm; struct tm *tm, gmt;
struct timeb ftz; struct timeb ftz;
time_t Start; time_t Start;
time_t tod; time_t tod;
yyInput = p; yyInput = p;
if (now == NULL) { if (now == NULL) {
now = &ftz; now = &ftz;
#if defined(FTIME_MISSING)
(void)time(&ftz.time); (void)time(&ftz.time);
/* Set the timezone global. */
tzset(); if (! (tm = gmtime (&ftz.time)))
#if defined(HAVE_TIMEZONE) return -1;
tm = localtime(&ftz.time); gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
ftz.timezone = tm->tm_gmtoff / 60;
#else if (! (tm = localtime (&ftz.time)))
#if defined(timezone) return -1;
ftz.tzone = (int) timezone / 60;
#else ftz.timezone = difftm (&gmt, tm) / 60;
ftz.timezone = (int) timezone / 60; if(tm->tm_isdst)
#endif /* defined(timezone) */ ftz.timezone += 60;
#endif /* defined(HAVE_TIMEZONE) */
#else
(void)ftime(&ftz);
#endif /* defined(FTIME_MISSING) */
} }
tm = localtime(&now->time); tm = localtime(&now->time);
yyYear = tm->tm_year; yyYear = tm->tm_year;
yyMonth = tm->tm_mon + 1; yyMonth = tm->tm_mon + 1;
yyDay = tm->tm_mday; yyDay = tm->tm_mday;
#if defined(timezone)
yyTimezone = now->tzone;
#else
yyTimezone = now->timezone; yyTimezone = now->timezone;
#endif /* defined(timezone) */
yyDSTmode = DSTmaybe; yyDSTmode = DSTmaybe;
yyHour = 0; yyHour = 0;
yyMinutes = 0; yyMinutes = 0;
@ -865,6 +963,7 @@ get_date(p, now)
#if defined(TEST) #if defined(TEST)
/* ARGSUSED */ /* ARGSUSED */
int
main(ac, av) main(ac, av)
int ac; int ac;
char *av[]; char *av[];

View File

@ -1,10 +1,15 @@
/* Getopt for GNU. /* Getopt for GNU.
Copyright (C) 1987-1992 Free Software Foundation, Inc. NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
This program is free software; you can redistribute it and/or modify Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
it under the terms of the GNU General Public License as published by Free Software Foundation, Inc.
the Free Software Foundation; either version 2, or (at your option)
any later version. This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -13,73 +18,73 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !__STDC__ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const #define const
#endif #endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
/* This version of `getopt' appears to the caller like standard Unix `getopt' /* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments. to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of `argv' so that, As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order. all application programs are extended to handle flexible argument order.
Setting the environment variable _POSIX_OPTION_ORDER disables permutation. Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard. Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */ they can distinguish the relative order of options and other arguments. */
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)getopt.c 1.7 92/03/31"; static char rcsid[] = "$CVSid: @(#)getopt.c 1.10 94/09/21 $";
#endif #endif
#include <stdio.h> #include "getopt.h"
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#include <stdlib.h>
#else /* STDC_HEADERS or __GNU_LIBRARY__ */
char *getenv ();
char *malloc ();
#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#if !defined(bsdi) && !defined(__386BSD__)
#define alloca __builtin_alloca
#endif
#else /* not __GNUC__ */
#ifdef sparc
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif /* sparc */
#endif /* not __GNUC__ */
#if defined(USG) || defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#include <string.h>
#ifndef bcopy
#define bcopy(s, d, n) memcpy ((d), (s), (n))
#endif
#ifndef index
#define index strchr
#endif
#else /* USG or STDC_HEADERS or __GNU_LIBRARY__ */
#ifdef VMS
#include <string.h>
#else /* VMS */
#include <strings.h>
#endif /* VMS */
/* Declaring bcopy causes errors on systems whose declarations are different.
If the declaration is omitted, everything works fine. */
#endif /* USG or STDC_HEADERS or __GNU_LIBRARY__ */
/* For communication from `getopt' to the caller. /* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument, When `getopt' finds an option that takes an argument,
@ -87,7 +92,7 @@ char *alloca ();
Also, when `ordering' is RETURN_IN_ORDER, Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */ each non-option ARGV-element is returned here. */
char *optarg = 0; char *optarg = NULL;
/* Index in ARGV of the next element to be scanned. /* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller This is used for communication to and from the caller
@ -101,6 +106,7 @@ char *optarg = 0;
Otherwise, `optind' communicates from one call to the next Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */ how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0; int optind = 0;
/* The next char to be scanned in the option-element /* The next char to be scanned in the option-element
@ -117,17 +123,23 @@ static char *nextchar;
int opterr = 1; int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements. /* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything, If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable the default is REQUIRE_ORDER if the environment variable
_POSIX_OPTION_ORDER is defined, PERMUTE otherwise. POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options; REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen. stop option processing when the first non-option is seen.
This is what Unix does. This is what Unix does.
This mode of operation is selected by either setting the environment This mode of operation is selected by either setting the environment
variable POSIX_ME_HARDER, or using `+' as the first character variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters. of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan, PERMUTE is the default. We permute the contents of ARGV as we scan,
@ -151,28 +163,50 @@ static enum
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering; } ordering;
/* Describe the long-named options requested by the application. /* Value of POSIXLY_CORRECT environment variable. */
_GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an static char *posixly_correct;
element containing a name which is zero.
The field `has_arg' is 1 if the option takes an argument, #ifdef __GNU_LIBRARY__
2 if it takes an optional argument. */ /* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
struct option /* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (str, chr)
const char *str;
int chr;
{ {
char *name; while (*str)
int has_arg; {
int *flag; if (*str == chr)
int val; return (char *) str;
}; str++;
}
return 0;
}
const struct option *_getopt_long_options; /* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
#ifndef __STDC__
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
#endif /* not __STDC__ */
#endif /* __GNUC__ */
int _getopt_long_only = 0; #endif /* not __GNU_LIBRARY__ */
/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
Only valid when a long-named option was found. */
int option_index;
/* Handle permutation of arguments. */ /* Handle permutation of arguments. */
@ -185,32 +219,104 @@ static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV. /* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt) One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far. which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped. the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe `first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */ the new indices of the non-options in ARGV after they are moved. */
static void static void
exchange (argv) exchange (argv)
char **argv; char **argv;
{ {
int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); int bottom = first_nonopt;
char **temp = (char **) alloca (nonopts_size); int middle = last_nonopt;
int top = optind;
char *tem;
/* Interchange the two blocks of data in ARGV. */ /* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
bcopy (&argv[first_nonopt], temp, nonopts_size); while (top > middle && middle > bottom)
bcopy (&argv[last_nonopt], &argv[first_nonopt], {
(optind - last_nonopt) * sizeof (char *)); if (top - middle > middle - bottom)
bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size); {
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */ /* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt); first_nonopt += (optind - last_nonopt);
last_nonopt = optind; last_nonopt = optind;
} }
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (optstring)
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters /* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING. given in OPTSTRING.
@ -245,78 +351,67 @@ exchange (argv)
handling the non-option ARGV-elements. handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `+' instead of `-'. Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element. from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field `flag' field is nonzero, the value of the option's `val' field
otherwise. */ if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int int
gnu_getopt (argc, argv, optstring) _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc; int argc;
char **argv; char *const *argv;
const char *optstring; const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{ {
optarg = 0; optarg = NULL;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0) if (optind == 0)
optstring = _getopt_initialize (optstring);
if (nextchar == NULL || *nextchar == '\0')
{ {
first_nonopt = last_nonopt = optind = 1; /* Advance to the next ARGV-element. */
nextchar = 0;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIX_ME_HARDER") != 0)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == 0 || *nextchar == 0)
{
if (ordering == PERMUTE) if (ordering == PERMUTE)
{ {
/* If we have just processed some options following some non-options, /* If we have just processed some options following some non-options,
exchange them so that the options come first. */ exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind) if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange (argv); exchange ((char **) argv);
else if (last_nonopt != optind) else if (last_nonopt != optind)
first_nonopt = optind; first_nonopt = optind;
/* Now skip any additional non-options /* Skip any additional non-options
and extend the range of non-options previously skipped. */ and extend the range of non-options previously skipped. */
while (optind < argc while (optind < argc
&& (argv[optind][0] != '-' && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
|| argv[optind][1] == 0)
&& (_getopt_long_options == 0
|| argv[optind][0] != '+'
|| argv[optind][1] == 0))
optind++; optind++;
last_nonopt = optind; last_nonopt = optind;
} }
/* Special ARGV-element `--' means premature end of options. /* The special ARGV-element `--' means premature end of options.
Skip it like a null option, Skip it like a null option,
then exchange with previous non-options as if it were an option, then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */ then skip everything else like a non-option. */
@ -326,7 +421,7 @@ gnu_getopt (argc, argv, optstring)
optind++; optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind) if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange (argv); exchange ((char **) argv);
else if (first_nonopt == last_nonopt) else if (first_nonopt == last_nonopt)
first_nonopt = optind; first_nonopt = optind;
last_nonopt = argc; last_nonopt = argc;
@ -349,9 +444,7 @@ gnu_getopt (argc, argv, optstring)
/* If we have come to a non-option and did not permute it, /* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */ either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == 0) if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
&& (_getopt_long_options == 0
|| argv[optind][0] != '+' || argv[optind][1] == 0))
{ {
if (ordering == REQUIRE_ORDER) if (ordering == REQUIRE_ORDER)
return EOF; return EOF;
@ -360,32 +453,48 @@ gnu_getopt (argc, argv, optstring)
} }
/* We have found another option-ARGV-element. /* We have found another option-ARGV-element.
Start decoding its characters. */ Skip the initial punctuation. */
nextchar = argv[optind] + 1; nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
} }
if (_getopt_long_options != 0 /* Decode the current option-ARGV-element. */
&& (argv[optind][0] == '+'
|| (_getopt_long_only && argv[optind][0] == '-')) /* Check whether the ARGV-element is a long option.
)
If long_only and the ARGV-element has the form "-f", where f is
a valid short option, don't consider it an abbreviated form of
a long option that starts with f. Otherwise there would be no
way to give the -f short option.
On the other hand, if there's a long option "fubar" and
the ARGV-element is "-fu", do consider that an abbreviation of
the long option, just like "--fu", and not "-f" with arg "u".
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{ {
char *nameend;
const struct option *p; const struct option *p;
char *s = nextchar; const struct option *pfound = NULL;
int exact = 0; int exact = 0;
int ambig = 0; int ambig = 0;
const struct option *pfound = 0; int indfound;
int indfound = 0; int option_index;
while (*s && *s != '=') for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
s++; /* Do nothing. */ ;
/* Test all options for either exact match or abbreviated matches. */ /* Test all long options for either exact match
for (p = _getopt_long_options, option_index = 0; p->name; or abbreviated matches. */
p++, option_index++) for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar)) if (!strncmp (p->name, nextchar, nameend - nextchar))
{ {
if (s - nextchar == strlen (p->name)) if (nameend - nextchar == strlen (p->name))
{ {
/* Exact match found. */ /* Exact match found. */
pfound = p; pfound = p;
@ -393,39 +502,52 @@ gnu_getopt (argc, argv, optstring)
exact = 1; exact = 1;
break; break;
} }
else if (pfound == 0) else if (pfound == NULL)
{ {
/* First nonexact match found. */ /* First nonexact match found. */
pfound = p; pfound = p;
indfound = option_index; indfound = option_index;
} }
else else
/* Second nonexact match found. */ /* Second or later nonexact match found. */
ambig = 1; ambig = 1;
} }
if (ambig && !exact) if (ambig && !exact)
{ {
fprintf (stderr, "%s: option `%s' is ambiguous\n", if (opterr)
argv[0], argv[optind]); fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
optind++; optind++;
return '?'; return '?';
} }
if (pfound != 0) if (pfound != NULL)
{ {
option_index = indfound; option_index = indfound;
optind++; optind++;
if (*s) if (*nameend)
{ {
if (pfound->has_arg > 0) /* Don't test has_arg with >, because some C compilers don't
optarg = s + 1; allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
else else
{ {
fprintf (stderr, if (opterr)
"%s: option `%c%s' doesn't allow an argument\n", {
argv[0], argv[optind - 1][0], pfound->name); if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
return '?'; return '?';
} }
@ -436,13 +558,16 @@ gnu_getopt (argc, argv, optstring)
optarg = argv[optind++]; optarg = argv[optind++];
else else
{ {
fprintf (stderr, "%s: option `%s' requires an argument\n", if (opterr)
argv[0], argv[optind - 1]); fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
return '?'; return optstring[0] == ':' ? ':' : '?';
} }
} }
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag) if (pfound->flag)
{ {
*(pfound->flag) = pfound->val; *(pfound->flag) = pfound->val;
@ -450,43 +575,52 @@ gnu_getopt (argc, argv, optstring)
} }
return pfound->val; return pfound->val;
} }
/* Can't find it as a long option. If this is getopt_long_only,
and the option starts with '-' and is a valid short /* Can't find it as a long option. If this is not getopt_long_only,
option, then interpret it as a short option. Otherwise it's or the option starts with '--' or is not a valid short
an error. */ option, then it's an error.
if (_getopt_long_only == 0 || argv[optind][0] == '+' || Otherwise interpret it as a short option. */
index (optstring, *nextchar) == 0) if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
{ {
if (opterr != 0) if (opterr)
fprintf (stderr, "%s: unrecognized option `%c%s'\n", {
argv[0], argv[optind][0], nextchar); if (argv[optind][1] == '-')
nextchar += strlen (nextchar); /* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++; optind++;
return '?'; return '?';
} }
} }
/* Look at and handle the next option-character. */ /* Look at and handle the next short option-character. */
{ {
char c = *nextchar++; char c = *nextchar++;
char *temp = index (optstring, c); char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */ /* Increment `optind' when we start to process its last character. */
if (*nextchar == 0) if (*nextchar == '\0')
optind++; ++optind;
if (temp == 0 || c == ':') if (temp == NULL || c == ':')
{ {
if (opterr != 0) if (opterr)
{ {
if (c < 040 || c >= 0177) if (posixly_correct)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n", /* 1003.2 specifies the format of this message. */
argv[0], c); fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
else else
fprintf (stderr, "%s: unrecognized option `-%c'\n", fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
argv[0], c);
} }
optopt = c;
return '?'; return '?';
} }
if (temp[1] == ':') if (temp[1] == ':')
@ -494,19 +628,19 @@ gnu_getopt (argc, argv, optstring)
if (temp[2] == ':') if (temp[2] == ':')
{ {
/* This is an option that accepts an argument optionally. */ /* This is an option that accepts an argument optionally. */
if (*nextchar != 0) if (*nextchar != '\0')
{ {
optarg = nextchar; optarg = nextchar;
optind++; optind++;
} }
else else
optarg = 0; optarg = NULL;
nextchar = 0; nextchar = NULL;
} }
else else
{ {
/* This is an option that requires an argument. */ /* This is an option that requires an argument. */
if (*nextchar != 0) if (*nextchar != '\0')
{ {
optarg = nextchar; optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg, /* If we end this ARGV-element by taking the rest as an arg,
@ -515,21 +649,42 @@ gnu_getopt (argc, argv, optstring)
} }
else if (optind == argc) else if (optind == argc)
{ {
if (opterr != 0) if (opterr)
fprintf (stderr, "%s: option `-%c' requires an argument\n", {
argv[0], c); /* 1003.2 specifies the format of this message. */
c = '?'; fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
} }
else else
/* We already incremented `optind' once; /* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */ increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++]; optarg = argv[optind++];
nextchar = 0; nextchar = NULL;
} }
} }
return c; return c;
} }
} }
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST #ifdef TEST
@ -548,7 +703,7 @@ main (argc, argv)
{ {
int this_option_optind = optind ? optind : 1; int this_option_optind = optind ? optind : 1;
c = gnu_getopt (argc, argv, "abc:d:0123456789"); c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF) if (c == EOF)
break; break;

View File

@ -1,10 +1,10 @@
/* declarations for getopt /* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify it
it under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by the
the Free Software Foundation; either version 2, or (at your option) Free Software Foundation; either version 2, or (at your option) any
any later version. later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -13,9 +13,16 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* @(#)getopt.h 1.6 92/03/31 */ /* $CVSid: @(#)getopt.h 1.7 94/09/21 $ */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller. /* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument, When `getopt' finds an option that takes an argument,
@ -44,16 +51,21 @@ extern int optind;
extern int opterr; extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application. /* Describe the long-named options requested by the application.
_GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
element containing a name which is zero. of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is: The field `has_arg' is:
0 if the option does not take an argument, no_argument (or 0) if the option does not take an argument,
1 if the option requires an argument, required_argument (or 1) if the option requires an argument,
2 if the option takes an optional argument. optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is nonzero, it points to a variable that is set If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but to the value given in the field `val' when the option is found, but
left unchanged if the option is not found. left unchanged if the option is not found.
@ -66,37 +78,54 @@ extern int opterr;
struct option struct option
{ {
#if __STDC__
const char *name;
#else
char *name; char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg; int has_arg;
int *flag; int *flag;
int val; int val;
}; };
#if __STDC__ /* Names for the values of the `has_arg' field of `struct option'. */
extern const struct option *_getopt_long_options;
#else
extern struct option *_getopt_long_options;
#endif
/* If nonzero, '-' can introduce long-named options. #define no_argument 0
Set by getopt_long_only. */ #define required_argument 1
#define optional_argument 2
extern int _getopt_long_only;
/* The index in GETOPT_LONG_OPTIONS of the long-named option found.
Only valid when a long-named option has been found by the most
recent call to `getopt'. */
extern int option_index;
#if __STDC__ #if __STDC__
int gnu_getopt (int argc, char **argv, const char *shortopts); #if defined(__GNU_LIBRARY__)
int gnu_getopt_long (int argc, char **argv, const char *shortopts, /* Many other libraries have conflicting prototypes for getopt, with
const struct option *longopts, int *longind); differences in the consts, in stdlib.h. To avoid compilation
int gnu_getopt_long_only (int argc, char **argv, const char *shortopts, errors, only prototype getopt for the GNU C library. */
const struct option *longopts, int *longind); extern int getopt (int argc, char *const *argv, const char *shortopts);
#else #else /* not __GNU_LIBRARY__ */
int gnu_getopt (); extern int getopt ();
int gnu_getopt_long (); #endif /* not __GNU_LIBRARY__ */
int gnu_getopt_long_only (); extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif #endif
#endif /* _GETOPT_H */

View File

@ -1,10 +1,11 @@
/* Getopt for GNU. /* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987-1992 Free Software Foundation, Inc. Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify it
it under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by the
the Free Software Foundation; either version 2, or (at your option) Free Software Foundation; either version 2, or (at your option) any
any later version. later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -13,67 +14,84 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "getopt.h" #ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
#if !__STDC__ /* We use <config.h> instead of "config.h" so that a compilation
#define const using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif #endif
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) #include "getopt.h"
#include <stdlib.h>
#else /* STDC_HEADERS or __GNU_LIBRARY__ */
char *getenv ();
#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
#if !defined (NULL) #ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#else
char *getenv ();
#endif
#ifndef NULL
#define NULL 0 #define NULL 0
#endif #endif
int int
gnu_getopt_long (argc, argv, options, long_options, opt_index) getopt_long (argc, argv, options, long_options, opt_index)
int argc; int argc;
char **argv; char *const *argv;
const char *options; const char *options;
const struct option *long_options; const struct option *long_options;
int *opt_index; int *opt_index;
{ {
int val; return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
/* For strict POSIX compatibility, we must turn off long options. */
if (getenv ("POSIX_ME_HARDER") == 0)
_getopt_long_options = long_options;
val = gnu_getopt (argc, argv, options);
if (val == 0 && opt_index != NULL)
*opt_index = option_index;
return val;
} }
/* Like getopt_long, but '-' as well as '+' can indicate a long option. /* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' doesn't match a long option, If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option but does match a short option, it is parsed as a short option
instead. */ instead. */
int int
gnu_getopt_long_only (argc, argv, options, long_options, opt_index) getopt_long_only (argc, argv, options, long_options, opt_index)
int argc; int argc;
char **argv; char *const *argv;
const char *options; const char *options;
const struct option *long_options; const struct option *long_options;
int *opt_index; int *opt_index;
{ {
int val; return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
_getopt_long_options = long_options;
_getopt_long_only = 1;
val = gnu_getopt (argc, argv, options);
if (val == 0 && opt_index != NULL)
*opt_index = option_index;
return val;
} }
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST #ifdef TEST
#include <stdio.h> #include <stdio.h>
@ -89,7 +107,6 @@ main (argc, argv)
while (1) while (1)
{ {
int this_option_optind = optind ? optind : 1; int this_option_optind = optind ? optind : 1;
char *name = '\0';
int option_index = 0; int option_index = 0;
static struct option long_options[] = static struct option long_options[] =
{ {
@ -110,7 +127,7 @@ main (argc, argv)
switch (c) switch (c)
{ {
case 0: case 0:
printf ("option %s", (long_options[option_index]).name); printf ("option %s", long_options[option_index].name);
if (optarg) if (optarg)
printf (" with arg %s", optarg); printf (" with arg %s", optarg);
printf ("\n"); printf ("\n");
@ -144,6 +161,10 @@ main (argc, argv)
printf ("option c with value `%s'\n", optarg); printf ("option c with value `%s'\n", optarg);
break; break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?': case '?':
break; break;

View File

@ -19,6 +19,10 @@
of getwd() which is much faster than getcwd(). As a result, we use the of getwd() which is much faster than getcwd(). As a result, we use the
system's getwd() if it is available */ system's getwd() if it is available */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "system.h" #include "system.h"
/* Get the current working directory into PATHNAME */ /* Get the current working directory into PATHNAME */

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Polk's hash list manager. So cool. * Polk's hash list manager. So cool.
*/ */
@ -10,31 +10,32 @@
#include "cvs.h" #include "cvs.h"
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)hash.c 1.14 92/03/31"; static char rcsid[] = "$CVSid: @(#)hash.c 1.19 94/09/23 $";
USE(rcsid)
#endif #endif
/* global caches */ /* global caches */
static List *listcache = NULL; static List *listcache = NULL;
static Node *nodecache = NULL; static Node *nodecache = NULL;
#if __STDC__ static void freenode_mem PROTO((Node * p));
static void freenode_mem (Node * p);
#else
static void freenode_mem ();
#endif /* __STDC__ */
/* hash function */ /* hash function */
static int static int
hashp (key) hashp (key)
char *key; char *key;
{ {
register char *p; unsigned int h = 0;
register int n = 0; unsigned int g;
for (p = key; *p; p++) while (*key != 0)
n += *p; {
h = (h << 4) + *key++;
if ((g = h & 0xf0000000) != 0)
h = (h ^ (g >> 24)) ^ g;
}
return (n % HASHSIZE); return (h % HASHSIZE);
} }
/* /*
@ -60,7 +61,7 @@ getlist ()
{ {
/* make a new list from scratch */ /* make a new list from scratch */
list = (List *) xmalloc (sizeof (List)); list = (List *) xmalloc (sizeof (List));
bzero ((char *) list, sizeof (List)); memset ((char *) list, 0, sizeof (List));
node = getnode (); node = getnode ();
list->list = node; list->list = node;
node->type = HEADER; node->type = HEADER;
@ -130,7 +131,7 @@ getnode ()
} }
/* always make it clean */ /* always make it clean */
bzero ((char *) p, sizeof (Node)); memset ((char *) p, 0, sizeof (Node));
p->type = UNKNOWN; p->type = UNKNOWN;
return (p); return (p);
@ -247,7 +248,8 @@ addnode (list, p)
} }
/* /*
* look up an entry in hash list table * look up an entry in hash list table and return a pointer to the
* node. Return NULL on error or not found.
*/ */
Node * Node *
findnode (list, key) findnode (list, key)
@ -273,9 +275,10 @@ findnode (list, key)
* walk a list with a specific proc * walk a list with a specific proc
*/ */
int int
walklist (list, proc) walklist (list, proc, closure)
List *list; List *list;
int (*proc) (); int (*proc) ();
void *closure;
{ {
Node *head, *p; Node *head, *p;
int err = 0; int err = 0;
@ -285,7 +288,7 @@ walklist (list, proc)
head = list->list; head = list->list;
for (p = head->next; p != head; p = p->next) for (p = head->next; p != head; p = p->next)
err += proc (p); err += proc (p, closure);
return (err); return (err);
} }
@ -336,3 +339,61 @@ sortlist (list, comp)
} }
} }
} }
/* Debugging functions. Quite useful to call from within gdb. */
char *
nodetypestring (type)
Ntype type;
{
switch (type) {
case UNKNOWN: return("UNKNOWN");
case HEADER: return("HEADER");
case ENTRIES: return("ENTRIES");
case FILES: return("FILES");
case LIST: return("LIST");
case RCSNODE: return("RCSNODE");
case RCSVERS: return("RCSVERS");
case DIRS: return("DIRS");
case UPDATE: return("UPDATE");
case LOCK: return("LOCK");
case NDBMNODE: return("NDBMNODE");
}
return("<trash>");
}
int
printnode (node, closure)
Node *node;
void *closure;
{
if (node == NULL)
{
(void) printf("NULL node.\n");
return(0);
}
(void) printf("Node at 0x%p: type = %s, key = 0x%p = \"%s\", data = 0x%p, next = 0x%p, prev = 0x%p\n",
node, nodetypestring(node->type), node->key, node->key, node->data, node->next, node->prev);
return(0);
}
void
printlist (list)
List *list;
{
if (list == NULL)
{
(void) printf("NULL list.\n");
return;
}
(void) printf("List at 0x%p: list = 0x%p, HASHSIZE = %d, next = 0x%p\n",
list, list->list, HASHSIZE, list->next);
(void) walklist(list, printnode, NULL);
return;
}

View File

@ -1,10 +1,10 @@
/* @(#)hash.h 1.18 92/03/31 */ /* $CVSid: @(#)hash.h 1.23 94/10/07 $ */
/* /*
* Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1992, Brian Berliner and Jeff Polk
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
*/ */
/* /*
@ -51,27 +51,16 @@ struct entnode
char *options; char *options;
char *tag; char *tag;
char *date; char *date;
char *conflict;
}; };
typedef struct entnode Entnode; typedef struct entnode Entnode;
#if __STDC__ List *getlist PROTO((void));
List *getlist (void); Node *findnode PROTO((List * list, char *key));
Node *findnode (List * list, char *key); Node *getnode PROTO((void));
Node *getnode (void); int addnode PROTO((List * list, Node * p));
int addnode (List * list, Node * p); int walklist PROTO((List * list, int PROTO((*proc)) PROTO((Node *n, void *closure)), void *closure));
int walklist (List * list, int (*proc) ()); void dellist PROTO((List ** listp));
void dellist (List ** listp); void delnode PROTO((Node * p));
void delnode (Node * p); void freenode PROTO((Node * p));
void freenode (Node * p); void sortlist PROTO((List * list, int PROTO((*comp))()));
void sortlist (List * list, int (*comp) ());
#else
List *getlist ();
Node *findnode ();
Node *getnode ();
int addnode ();
int walklist ();
void dellist ();
void delnode ();
void freenode ();
void sortlist ();
#endif /* __STDC__ */

View File

@ -15,6 +15,10 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner * Copyright (c) 1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* A simple ndbm-emulator for CVS. It parses a text file of the format: * A simple ndbm-emulator for CVS. It parses a text file of the format:
* *
@ -18,7 +18,8 @@
#ifdef MY_NDBM #ifdef MY_NDBM
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)myndbm.c 1.5 92/03/31"; static char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
USE(rcsid)
#endif #endif
static void mydbm_load_file (); static void mydbm_load_file ();
@ -138,7 +139,7 @@ mydbm_load_file (fp, list)
for (cont = 0; fgets (line, sizeof (line), fp) != NULL;) for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
{ {
if ((cp = rindex (line, '\n')) != NULL) if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0'; /* strip the newline */ *cp = '\0'; /* strip the newline */
/* /*

View File

@ -1,4 +1,4 @@
/* @(#)myndbm.h 1.3 92/02/29 */ /* $CVSid: @(#)myndbm.h 1.4 94/09/21 $ */
#ifdef MY_NDBM #ifdef MY_NDBM
@ -27,18 +27,10 @@ typedef struct
#define dbm_firstkey mydbm_firstkey #define dbm_firstkey mydbm_firstkey
#define dbm_nextkey mydbm_nextkey #define dbm_nextkey mydbm_nextkey
#if __STDC__ DBM *mydbm_open PROTO((char *file, int flags, int mode));
DBM *mydbm_open (char *file, int flags, int mode); void mydbm_close PROTO((DBM * db));
void mydbm_close (DBM * db); datum mydbm_fetch PROTO((DBM * db, datum key));
datum mydbm_fetch (DBM * db, datum key); datum mydbm_firstkey PROTO((DBM * db));
datum mydbm_firstkey (DBM * db); datum mydbm_nextkey PROTO((DBM * db));
datum mydbm_nextkey (DBM * db);
#else
DBM *mydbm_open ();
void mydbm_close ();
datum mydbm_fetch ();
datum mydbm_firstkey ();
datum mydbm_nextkey ();
#endif /* __STDC__ */
#endif /* MY_NDBM */ #endif /* MY_NDBM */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* Definitions for data structures and routines for the regular /* Definitions for data structures and routines for the regular
expression library, version REPLACE-WITH-VERSION. expression library, version 0.12.
Copyright (C) 1985, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -20,7 +20,15 @@
#ifndef __REGEXP_LIBRARY_H__ #ifndef __REGEXP_LIBRARY_H__
#define __REGEXP_LIBRARY_H__ #define __REGEXP_LIBRARY_H__
/* POSIX says that <sys/types.h> must be included before <regex.h>. */ /* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
#ifdef VMS
/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
should be there. */
#include <stddef.h>
#endif
/* The following bits are used to determine the regexp syntax we /* The following bits are used to determine the regexp syntax we
recognize. The set/not-set meanings are chosen so that Emacs syntax recognize. The set/not-set meanings are chosen so that Emacs syntax
@ -45,17 +53,17 @@ typedef unsigned reg_syntax_t;
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket /* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions). expressions, of course).
If this bit is not set, then it depends: If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular ^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator; expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or $ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator. before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX now says that the behavior of * etc. in leading positions is POSIX draft 11.2 says that * etc. in leading positions is undefined.
undefined. We have already implemented a previous draft which We already implemented a previous draft which made those constructs
made those constructs invalid, so we may as well not change the code invalid, though, so we haven't changed the code back. */
back. */
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special /* If this bit is set, then special characters are always special
@ -67,16 +75,14 @@ typedef unsigned reg_syntax_t;
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or /* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. immediately after an alternation or begin-group operator. */
Furthermore, alternation cannot be first or last in an re, or
immediately follow another alternation or begin-group. */
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches a newline. /* If this bit is set, then . matches newline.
If not set, then it doesn't. */ If not set, then it doesn't. */
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then period doesn't match a null. /* If this bit is set, then . doesn't match NUL.
If not set, then it does. */ If not set, then it does. */
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
@ -89,7 +95,7 @@ typedef unsigned reg_syntax_t;
If not set, \{, \}, {, and } are literals. */ If not set, \{, \}, {, and } are literals. */
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators. /* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */ If not set, they are. */
#define RE_LIMITED_OPS (RE_INTERVALS << 1) #define RE_LIMITED_OPS (RE_INTERVALS << 1)
@ -97,104 +103,112 @@ typedef unsigned reg_syntax_t;
If not set, newline is literal. */ If not set, newline is literal. */
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, newline in the pattern is an ordinary character. /* If this bit is set, then `{...}' defines an interval, and \{ and \}
If not set, newline before ^ or after $ allows the ^ or $ to be an are literals.
anchor. */ If not set, then `\{...\}' defines an interval. */
#define RE_NEWLINE_ORDINARY (RE_NEWLINE_ALT << 1) #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is not set, then \{ and \} defines an interval,
and { and } are literals.
If set, then { and } defines an interval, and \{ and \} are literals. */
#define RE_NO_BK_BRACES (RE_NEWLINE_ORDINARY << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals. /* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */ If not set, \(...\) defines a group, and ( and ) are literals. */
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then back references (i.e., \<digit>) are not /* If this bit is set, then \<digit> matches <digit>.
recognized. If not set, then \<digit> is a back-reference. */
If not set, then they are. */
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal. /* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */ If not set, then \| is an alternation operator, and | is literal. */
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then you can't have empty alternatives. /* If this bit is set, then an ending range point collating higher
If not set, then you can. */ than the starting range point, as in [z-a], is invalid.
#define RE_NO_EMPTY_ALTS (RE_NO_BK_VBAR << 1) If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then you can't have empty groups. /* If this bit is set, then an unmatched ) is ordinary.
If not set, then you can. */ If not set, then an unmatched ) is invalid. */
#define RE_NO_EMPTY_GROUPS (RE_NO_EMPTY_ALTS << 1) #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, then an ending range point has to collate higher
than or equal to the starting range point.
If not set, then when the ending range point collates higher than the
starting range point, we consider such a range to be empty. */
#define RE_NO_EMPTY_RANGES (RE_NO_EMPTY_GROUPS << 1)
/* If this bit is set, then all back references must refer to a preceding
subexpression.
If not set, then a back reference to a nonexistent subexpression is
treated as literal characters. */
#define RE_NO_MISSING_BK_REF (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, then Regex considers an unmatched close-group
operator to be the ordinary character parenthesis.
If not set, then an unmatched close-group operator is invalid. */
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_MISSING_BK_REF << 1)
/* This global variable defines the particular regexp syntax to use (for /* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is some interfaces). When a regexp is compiled, the syntax used is
stored in the pattern buffer, so changing this does not affect stored in the pattern buffer, so changing this does not affect
already-compiled regexps. */ already-compiled regexps. */
extern reg_syntax_t obscure_syntax; extern reg_syntax_t re_syntax_options;
/* Define combinations of the above bits for the standard possibilities. /* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file.) */ (The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */ /* [[[begin syntaxes]]] */
#define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_EMACS 0
#define RE_SYNTAX_POSIX_AWK \
(RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_AWK \ #define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_SYNTAX_POSIX_AWK) (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_UNMATCHED_RIGHT_PAREN_ORD)
#define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
#define RE_SYNTAX_GREP \ #define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_NEWLINE_ALT) (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
#define RE_SYNTAX_EGREP \ #define RE_SYNTAX_EGREP \
(RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS | RE_NO_BK_VBAR) | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
#define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
#define RE_SYNTAX_POSIX_BASIC \ #define RE_SYNTAX_POSIX_BASIC \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
| RE_DOT_NOT_NULL | RE_INTERVALS | RE_LIMITED_OPS \
| RE_NEWLINE_ORDINARY | RE_NO_EMPTY_RANGES | RE_NO_MISSING_BK_REF) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
#define RE_SYNTAX_POSIX_EXTENDED \ #define RE_SYNTAX_POSIX_EXTENDED \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_INTERVALS | RE_NEWLINE_ORDINARY | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_NO_BK_PARENS | RE_NO_BK_REFS | RE_NO_BK_VBAR \
| RE_NO_EMPTY_ALTS | RE_NO_EMPTY_GROUPS | RE_NO_EMPTY_RANGES \
| RE_UNMATCHED_RIGHT_PAREN_ORD) | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */ /* [[[end syntaxes]]] */
/* Maximum number of duplicates an interval can allow. */ /* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
value, so remove any previous define. */
#ifdef RE_DUP_MAX
#undef RE_DUP_MAX #undef RE_DUP_MAX
#define RE_DUP_MAX ((1 << 15) - 1) #endif
#define RE_DUP_MAX ((1 << 15) - 1)
/* POSIX `cflags' bits (i.e., information for regcomp). */ /* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* If this bit is set, then use extended regular expression syntax. /* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */ If not set, then use basic regular expression syntax. */
@ -254,9 +268,6 @@ typedef enum
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t; } reg_errcode_t;
/* This data structure represents a compiled pattern. Before calling /* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap', the pattern compiler, the fields `buffer', `allocated', `fastmap',
@ -295,19 +306,28 @@ struct re_pattern_buffer
/* Number of subexpressions found by the compiler. */ /* Number of subexpressions found by the compiler. */
size_t re_nsub; size_t re_nsub;
/* Set to 1 by re_compile_fastmap if this pattern can match the /* Zero if this pattern cannot match the empty string, one else.
null string; 0 prevents the searcher from matching it with Well, in truth it's used only in `re_search_2', to see
the null string. Set to 2 if it might match the null string whether or not we should use the fastmap, so we don't set
either at the end of a search range or just before a this absolutely perfectly; see `re_compile_fastmap' (the
character listed in the fastmap. */ `duplicate' case). */
unsigned can_be_null : 2; unsigned can_be_null : 1;
/* Set to zero when regex_compile compiles a pattern; set to one /* If REGS_UNALLOCATED, allocate space in the `regs' structure
by re_compile_fastmap when it updates the fastmap, if any. */ for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#define REGS_UNALLOCATED 0
#define REGS_REALLOCATE 1
#define REGS_FIXED 2
unsigned regs_allocated : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned fastmap_accurate : 1; unsigned fastmap_accurate : 1;
/* If set, regexec reports only success or failure and does not /* If set, `re_match_2' does not return information about
return anything in pmatch. */ subexpressions. */
unsigned no_sub : 1; unsigned no_sub : 1;
/* If set, a beginning-of-line anchor doesn't match at the /* If set, a beginning-of-line anchor doesn't match at the
@ -320,10 +340,6 @@ struct re_pattern_buffer
/* If true, an anchor at a newline matches. */ /* If true, an anchor at a newline matches. */
unsigned newline_anchor : 1; unsigned newline_anchor : 1;
/* If set, re_match_2 assumes a non-null REGS argument is
initialized. If not set, REGS is initialized to the max of
RE_NREGS and re_nsub + 1 registers. */
unsigned caller_allocated_regs : 1;
/* [[[end pattern_buffer]]] */ /* [[[end pattern_buffer]]] */
}; };
@ -333,12 +349,8 @@ typedef struct re_pattern_buffer regex_t;
/* search.c (search_buffer) in Emacs needs this one opcode value. It is /* search.c (search_buffer) in Emacs needs this one opcode value. It is
defined both in `regex.c' and here. */ defined both in `regex.c' and here. */
#define RE_EXACTN_VALUE 1 #define RE_EXACTN_VALUE 1
/* Type for byte offsets within the string. POSIX mandates us defining /* Type for byte offsets within the string. POSIX mandates this. */
this. */
typedef int regoff_t; typedef int regoff_t;
@ -352,8 +364,9 @@ struct re_registers
}; };
/* If `caller_allocated_regs' is zero in the pattern buffer, re_match_2 /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
returns information about this many registers. */ `re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
#ifndef RE_NREGS #ifndef RE_NREGS
#define RE_NREGS 30 #define RE_NREGS 30
#endif #endif
@ -367,29 +380,41 @@ typedef struct
regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
} regmatch_t; } regmatch_t;
/* Declarations for routines. */ /* Declarations for routines. */
/* To avoid duplicating every routine declaration -- once with a
prototype (if we are ANSI), and once without (if we aren't) -- we
use the following macro to declare argument types. This
unfortunately clutters up the declarations a bit, but I think it's
worth it. */
#if __STDC__ #if __STDC__
/* Sets the current syntax to SYNTAX. You can also simply assign to the #define _RE_ARGS(args) args
`obscure_syntax' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t syntax); #else /* not __STDC__ */
#define _RE_ARGS(args) ()
#endif /* not __STDC__ */
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
/* Compile the regular expression PATTERN, with length LENGTH /* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `obscure_syntax', into the buffer and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */ BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern (const char *pattern, int length, extern const char *re_compile_pattern
struct re_pattern_buffer *buffer); _RE_ARGS ((const char *pattern, int length,
struct re_pattern_buffer *buffer));
/* Compile a fastmap for the compiled pattern in BUFFER; used to /* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an accelerate searches. Return 0 if successful and -2 if was an
internal error. */ internal error. */
extern int re_compile_fastmap (struct re_pattern_buffer *buffer); extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
/* Search in the string STRING (with length LENGTH) for the pattern /* Search in the string STRING (with length LENGTH) for the pattern
@ -397,78 +422,64 @@ extern int re_compile_fastmap (struct re_pattern_buffer *buffer);
characters. Return the starting position of the match, -1 for no characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */ information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern int re_search (struct re_pattern_buffer *buffer, extern int re_search
const char *string, int length, _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int start, int range, int length, int start, int range, struct re_registers *regs));
struct re_registers *regs);
/* Like `re_search', but search in the concatenation of STRING1 and /* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */ STRING2. Also, stop searching at index START + STOP. */
extern int re_search_2 (struct re_pattern_buffer *buffer, extern int re_search_2
const char *string1, int length1, _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
const char *string2, int length2, int length1, const char *string2, int length2,
int start, int range, int start, int range, struct re_registers *regs, int stop));
struct re_registers *regs,
int stop);
/* Like `re_search', but return how many characters in STRING the regexp /* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */ in BUFFER matched, starting at position START. */
extern int re_match (const struct re_pattern_buffer *buffer, extern int re_match
const char *string, int length, _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int start, struct re_registers *regs); int length, int start, struct re_registers *regs));
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ /* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern int re_match_2 (const struct re_pattern_buffer *buffer, extern int re_match_2
const char *string1, int length1, _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
const char *string2, int length2, int length1, const char *string2, int length2,
int start, int start, struct re_registers *regs, int stop));
struct re_registers *regs,
int stop);
#ifndef __386BSD__ /* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
unsigned num_regs, regoff_t *starts, regoff_t *ends));
/* 4.2 bsd compatibility. */ /* 4.2 bsd compatibility. */
#ifndef bsdi extern char *re_comp _RE_ARGS ((const char *));
extern const char *re_comp (const char *); extern int re_exec _RE_ARGS ((const char *));
#endif
extern int re_exec (const char *);
#endif
/* POSIX compatibility. */ /* POSIX compatibility. */
extern int regcomp (regex_t *preg, const char *pattern, int cflags); extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
extern int regexec (const regex_t *preg, const char *string, size_t nmatch, extern int regexec
regmatch_t pmatch[], int eflags); _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
extern size_t regerror (int errcode, const regex_t *preg, char *errbuf, regmatch_t pmatch[], int eflags));
size_t errbuf_size); extern size_t regerror
extern void regfree (regex_t *preg); _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
size_t errbuf_size));
extern void regfree _RE_ARGS ((regex_t *preg));
#else /* not __STDC__ */
/* Support old C compilers. */
#define const
extern reg_syntax_t re_set_syntax ();
extern char *re_compile_pattern ();
extern int re_search (), re_search_2 ();
extern int re_match (), re_match_2 ();
/* 4.2 BSD compatibility. */
extern char *re_comp ();
extern int re_exec ();
/* POSIX compatibility. */
extern int regcomp ();
extern int regexec ();
extern size_t regerror ();
extern void regfree ();
#endif /* not __STDC__ */
#endif /* not __REGEXP_LIBRARY_H__ */ #endif /* not __REGEXP_LIBRARY_H__ */
/* /*
Local variables: Local variables:

View File

@ -15,6 +15,10 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>

View File

@ -30,10 +30,14 @@
* must not themselves make calls to the signal handling * must not themselves make calls to the signal handling
* facilities. * facilities.
* *
* @(#)sighandle.c 1.9 92/03/31 * $CVSid: @(#)sighandle.c 1.13 94/10/07 $
* *
*************************************************************************/ *************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
@ -54,18 +58,14 @@ char *malloc();
#undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */ #undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
#endif #endif
#ifndef SIGTYPE
#define SIGTYPE void
#endif
/* Define the highest signal number (usually) */ /* Define the highest signal number (usually) */
#ifndef SIGMAX #ifndef SIGMAX
#define SIGMAX 32 #define SIGMAX 64
#endif #endif
/* Define linked list of signal handlers structure */ /* Define linked list of signal handlers structure */
struct SIG_hlist { struct SIG_hlist {
SIGTYPE (*handler)(); RETSIGTYPE (*handler)();
struct SIG_hlist *next; struct SIG_hlist *next;
}; };
@ -84,7 +84,7 @@ static struct sigaction *SIG_defaults;
#ifdef BSD_SIGNALS #ifdef BSD_SIGNALS
static struct sigvec *SIG_defaults; static struct sigvec *SIG_defaults;
#else #else
static SIGTYPE (**SIG_defaults)(); static RETSIGTYPE (**SIG_defaults)();
#endif #endif
#endif #endif
@ -112,11 +112,7 @@ static int SIG_init()
#ifdef POSIX #ifdef POSIX
(void) sigfillset(&sigset_test); (void) sigfillset(&sigset_test);
for (i = 1; sigismember(&sigset_test, i) == 1; i++) for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
#ifdef BROKEN_SIGISMEMBER
if ( i >= NSIG )
break
#endif
; ;
if (i < SIGMAX) if (i < SIGMAX)
i = SIGMAX; i = SIGMAX;
@ -133,8 +129,8 @@ static int SIG_init()
calloc(i, sizeof(struct sigvec)); calloc(i, sizeof(struct sigvec));
#else #else
if (!SIG_defaults) if (!SIG_defaults)
SIG_defaults = (SIGTYPE (**)()) SIG_defaults = (RETSIGTYPE (**)())
calloc(i, sizeof(SIGTYPE (**)())); calloc(i, sizeof(RETSIGTYPE (**)()));
#endif #endif
SIG_crSectMask = 0; SIG_crSectMask = 0;
#endif #endif
@ -149,7 +145,7 @@ static int SIG_init()
* they were registered. * they were registered.
*/ */
static SIGTYPE SIG_handle(sig) static RETSIGTYPE SIG_handle(sig)
int sig; int sig;
{ {
struct SIG_hlist *this; struct SIG_hlist *this;
@ -175,7 +171,7 @@ int sig;
int SIG_register(sig,fn) int SIG_register(sig,fn)
int sig; int sig;
SIGTYPE (*fn)(); RETSIGTYPE (*fn)();
{ {
int val; int val;
struct SIG_hlist *this; struct SIG_hlist *this;
@ -236,7 +232,7 @@ SIGTYPE (*fn)();
val = sigvec(sig, &vec, &SIG_defaults[sig]); val = sigvec(sig, &vec, &SIG_defaults[sig]);
#else #else
if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == if ((SIG_defaults[sig] = signal(sig, SIG_handle)) ==
(SIGTYPE (*)()) -1) (RETSIGTYPE (*)()) -1)
val = -1; val = -1;
#endif #endif
#endif #endif
@ -279,7 +275,7 @@ SIGTYPE (*fn)();
int SIG_deregister(sig,fn) int SIG_deregister(sig,fn)
int sig; int sig;
SIGTYPE (*fn)(); RETSIGTYPE (*fn)();
{ {
int val; int val;
struct SIG_hlist *this; struct SIG_hlist *this;
@ -341,7 +337,7 @@ SIGTYPE (*fn)();
#ifdef BSD_SIGNALS #ifdef BSD_SIGNALS
val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL); val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
#else #else
if (signal(sig, SIG_defaults[sig]) == (SIGTYPE (*)()) -1) if (signal(sig, SIG_defaults[sig]) == (RETSIGTYPE (*)()) -1)
val = -1; val = -1;
#endif #endif
#endif #endif

View File

@ -15,6 +15,10 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -15,14 +15,20 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if defined(STDC_HEADERS) || defined(USG) #ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if STDC_HEADERS || HAVE_STRING_H
#include <string.h> #include <string.h>
#ifndef index /* An ANSI string.h and pre-ANSI memory.h might conflict. */
#define index strchr #if !STDC_HEADERS && HAVE_MEMORY_H
#endif #include <memory.h>
#else #endif /* not STDC_HEADERS and HAVE_MEMORY_H */
#else /* not STDC_HJEADERS and not HAVE_STRING_H */
#include <strings.h> #include <strings.h>
#endif /* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#include <stdio.h> #include <stdio.h>
@ -43,7 +49,7 @@ strip_path (path)
int stripped = 0; int stripped = 0;
char *cp, *slash; char *cp, *slash;
for (cp = path; (slash = index(cp, '/')) != NULL; cp = slash) for (cp = path; (slash = strchr(cp, '/')) != NULL; cp = slash)
{ {
*slash = '\0'; *slash = '\0';
if ((!*cp && (cp != path || stripped)) || if ((!*cp && (cp != path || stripped)) ||

View File

@ -15,12 +15,21 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if defined(STDC_HEADERS) || defined(USG) #ifdef HAVE_CONFIG_H
#include <string.h> #include "config.h"
#else
#include <strings.h>
#endif #endif
#if STDC_HEADERS || HAVE_STRING_H
#include <string.h>
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
#if !STDC_HEADERS && HAVE_MEMORY_H
#include <memory.h>
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
#else /* not STDC_HJEADERS and not HAVE_STRING_H */
#include <strings.h>
/* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
/* Remove trailing slashes from PATH. */ /* Remove trailing slashes from PATH. */
void void

View File

@ -3,19 +3,24 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* Various useful functions for the CVS support code. * Various useful functions for the CVS support code.
*/ */
#include "cvs.h" #include "cvs.h"
#ifndef lint
static char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
USE(rcsid)
#endif
#ifdef _MINIX #ifdef _MINIX
#undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */ #undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
#endif #endif
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
#if __STDC__ #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
#include <stdarg.h> #include <stdarg.h>
#define VA_START(args, lastarg) va_start(args, lastarg) #define VA_START(args, lastarg) va_start(args, lastarg)
#else #else
@ -27,17 +32,24 @@
#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; #define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
#endif #endif
#ifndef lint /*
static char rcsid[] = "@(#)subr.c 1.52 92/03/31"; * I don't know of a convenient way to test this at configure time, or else
* I'd certainly do it there.
*/
#if defined(NeXT)
#define LOSING_TMPNAM_FUNCTION
#ifndef _POSIX_SOURCE
/*
* NeXT doesn't define these without _POSIX_SOURCE,
* but that changes a lot of things.
*/
#define WEXITSTATUS(x) ((x).w_retcode)
#define WTERMSIG(x) ((x).w_termsig)
#endif
#endif #endif
#if __STDC__ static void run_add_arg PROTO((char *s));
static void run_add_arg (char *s); static void run_init_prog PROTO((void));
static void run_init_prog (void);
#else
static void run_add_arg ();
static void run_init_prog ();
#endif /* __STDC__ */
extern char *getlogin (); extern char *getlogin ();
extern char *strtok (); extern char *strtok ();
@ -74,7 +86,7 @@ copy_file (from, to)
if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size) if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size)
error (1, errno, "cannot read file %s for copying", from); error (1, errno, "cannot read file %s for copying", from);
if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size
#ifndef FSYNC_MISSING #ifdef HAVE_FSYNC
|| fsync (fdout) == -1 || fsync (fdout) == -1
#endif #endif
) )
@ -88,11 +100,15 @@ copy_file (from, to)
error (1, errno, "cannot close %s", to); error (1, errno, "cannot close %s", to);
/* now, set the times for the copied file to match those of the original */ /* now, set the times for the copied file to match those of the original */
memset ((char *) &t, 0, sizeof (t));
t.actime = sb.st_atime; t.actime = sb.st_atime;
t.modtime = sb.st_mtime; t.modtime = sb.st_mtime;
(void) utime (to, &t); (void) utime (to, &t);
} }
/* FIXME-krp: these functions would benefit from caching the char * &
stat buf. */
/* /*
* Returns non-zero if the argument file is a directory, or is a symbolic * Returns non-zero if the argument file is a directory, or is a symbolic
* link which points to a directory. * link which points to a directory.
@ -202,25 +218,8 @@ make_directory (name)
{ {
struct stat buf; struct stat buf;
if (stat (name, &buf) == 0) if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode)))
{
if (S_ISDIR (buf.st_mode))
{
if (access (name, (R_OK | W_OK | X_OK)) == 0)
{
error (0, 0, "Directory %s already exists", name);
return;
}
else
{
error (0, 0,
"Directory %s already exists but is protected from you",
name);
}
}
else
error (0, 0, "%s already exists but is not a directory", name); error (0, 0, "%s already exists but is not a directory", name);
}
if (!noexec && mkdir (name, 0777) < 0) if (!noexec && mkdir (name, 0777) < 0)
error (1, errno, "cannot make directory %s", name); error (1, errno, "cannot make directory %s", name);
} }
@ -245,7 +244,7 @@ make_directories (name)
error (0, errno, "cannot make path to %s", name); error (0, errno, "cannot make path to %s", name);
return; return;
} }
if ((cp = rindex (name, '/')) == NULL) if ((cp = strrchr (name, '/')) == NULL)
return; return;
*cp = '\0'; *cp = '\0';
make_directories (name); make_directories (name);
@ -260,14 +259,12 @@ make_directories (name)
*/ */
char * char *
xmalloc (bytes) xmalloc (bytes)
int bytes; size_t bytes;
{ {
char *cp; char *cp;
if (bytes <= 0) if ((cp = malloc (bytes)) == NULL)
error (1, 0, "bad malloc size %d", bytes); error (1, 0, "can not allocate %lu bytes", (unsigned long) bytes);
if ((cp = malloc ((unsigned) bytes)) == NULL)
error (1, 0, "malloc failed");
return (cp); return (cp);
} }
@ -279,17 +276,17 @@ xmalloc (bytes)
char * char *
xrealloc (ptr, bytes) xrealloc (ptr, bytes)
char *ptr; char *ptr;
int bytes; size_t bytes;
{ {
char *cp; char *cp;
if (!ptr) if (!ptr)
return (xmalloc (bytes)); cp = malloc (bytes);
else
cp = realloc (ptr, bytes);
if (bytes <= 0) if (cp == NULL)
error (1, 0, "bad realloc size %d", bytes); error (1, 0, "can not reallocate %lu bytes", (unsigned long) bytes);
if ((cp = realloc (ptr, (unsigned) bytes)) == NULL)
error (1, 0, "realloc failed");
return (cp); return (cp);
} }
@ -320,7 +317,7 @@ xchmod (fname, writable)
int writable; int writable;
{ {
struct stat sb; struct stat sb;
int mode, oumask; mode_t mode, oumask;
if (stat (fname, &sb) < 0) if (stat (fname, &sb) < 0)
{ {
@ -399,9 +396,12 @@ unlink_file (f)
* Compare "file1" to "file2". Return non-zero if they don't compare exactly. * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
* *
* mallocs a buffer large enough to hold the entire file and does two reads to * mallocs a buffer large enough to hold the entire file and does two reads to
* load the buffer and calls bcmp to do the cmp. This is reasonable, since * load the buffer and calls memcmp to do the cmp. This is reasonable, since
* source files are typically not too large. * source files are typically not too large.
*/ */
/* richfix: this *could* exploit mmap. */
int int
xcmp (file1, file2) xcmp (file1, file2)
char *file1; char *file1;
@ -430,10 +430,10 @@ xcmp (file1, file2)
buf1 = xmalloc ((int) size); buf1 = xmalloc ((int) size);
buf2 = xmalloc ((int) size); buf2 = xmalloc ((int) size);
if (read (fd1, buf1, (int) size) != (int) size) if (read (fd1, buf1, (int) size) != (int) size)
error (1, errno, "cannot read file %s cor comparing", file1); error (1, errno, "cannot read file %s for comparing", file1);
if (read (fd2, buf2, (int) size) != (int) size) if (read (fd2, buf2, (int) size) != (int) size)
error (1, errno, "cannot read file %s for comparing", file2); error (1, errno, "cannot read file %s for comparing", file2);
ret = bcmp (buf1, buf2, (int) size); ret = memcmp(buf1, buf2, (int) size);
free (buf1); free (buf1);
free (buf2); free (buf2);
} }
@ -512,10 +512,10 @@ getcaller ()
static char uidname[20]; static char uidname[20];
struct passwd *pw; struct passwd *pw;
char *name; char *name;
int uid; uid_t uid;
uid = getuid (); uid = getuid ();
if (uid == 0) if (uid == (uid_t) 0)
{ {
/* super-user; try getlogin() to distinguish */ /* super-user; try getlogin() to distinguish */
if (((name = getenv("LOGNAME")) || (name = getenv("USER")) || if (((name = getenv("LOGNAME")) || (name = getenv("USER")) ||
@ -524,7 +524,7 @@ getcaller ()
} }
if ((pw = (struct passwd *) getpwuid (uid)) == NULL) if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
{ {
(void) sprintf (uidname, "uid%d", uid); (void) sprintf (uidname, "uid%d", (unsigned long) uid);
return (uidname); return (uidname);
} }
return (pw->pw_name); return (pw->pw_name);
@ -549,7 +549,7 @@ static int run_argc;
static int run_argc_allocated; static int run_argc_allocated;
/* VARARGS */ /* VARARGS */
#if !defined (VPRINTF_MISSING) && __STDC__ #if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
void void
run_setup (char *fmt,...) run_setup (char *fmt,...)
#else #else
@ -560,7 +560,7 @@ run_setup (fmt, va_alist)
#endif #endif
{ {
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
va_list args; va_list args;
#endif #endif
@ -581,7 +581,7 @@ run_setup (fmt, va_alist)
run_argc = 0; run_argc = 0;
/* process the varargs into run_prog */ /* process the varargs into run_prog */
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
VA_START (args, fmt); VA_START (args, fmt);
(void) vsprintf (run_prog, fmt, args); (void) vsprintf (run_prog, fmt, args);
va_end (args); va_end (args);
@ -602,7 +602,7 @@ run_arg (s)
} }
/* VARARGS */ /* VARARGS */
#if !defined (VPRINTF_MISSING) && __STDC__ #if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
void void
run_args (char *fmt,...) run_args (char *fmt,...)
#else #else
@ -613,7 +613,7 @@ run_args (fmt, va_alist)
#endif #endif
{ {
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
va_list args; va_list args;
#endif #endif
@ -621,7 +621,7 @@ run_args (fmt, va_alist)
run_init_prog (); run_init_prog ();
/* process the varargs into run_prog */ /* process the varargs into run_prog */
#ifndef VPRINTF_MISSING #ifdef HAVE_VPRINTF
VA_START (args, fmt); VA_START (args, fmt);
(void) vsprintf (run_prog, fmt, args); (void) vsprintf (run_prog, fmt, args);
va_end (args); va_end (args);
@ -668,7 +668,12 @@ run_exec (stin, stout, sterr, flags)
{ {
int shin, shout, sherr; int shin, shout, sherr;
int mode_out, mode_err; int mode_out, mode_err;
int status = -1; #if defined(NeXT) && !defined(_POSIX_SOURCE)
union wait status;
#else
int status;
#endif
int rc = -1;
int rerrno = 0; int rerrno = 0;
int pid, w; int pid, w;
@ -682,7 +687,7 @@ run_exec (stin, stout, sterr, flags)
struct sigvec vec, ivec, qvec; struct sigvec vec, ivec, qvec;
#else #else
SIGTYPE (*istat) (), (*qstat) (); RETSIGTYPE (*istat) (), (*qstat) ();
#endif #endif
#endif #endif
@ -733,11 +738,15 @@ run_exec (stin, stout, sterr, flags)
} }
} }
/* Make sure we don't flush this twice, once in the subprocess. */
fflush (stdout);
fflush (stderr);
/* The output files, if any, are now created. Do the fork and dups */ /* The output files, if any, are now created. Do the fork and dups */
#ifdef VFORK_MISSING #ifdef HAVE_VFORK
pid = fork ();
#else
pid = vfork (); pid = vfork ();
#else
pid = fork ();
#endif #endif
if (pid == 0) if (pid == 0)
{ {
@ -761,6 +770,7 @@ run_exec (stin, stout, sterr, flags)
/* dup'ing is done. try to run it now */ /* dup'ing is done. try to run it now */
(void) execvp (run_argv[0], run_argv); (void) execvp (run_argv[0], run_argv);
error (0, errno, "cannot exec %s", run_argv[0]);
_exit (127); _exit (127);
} }
else if (pid == -1) else if (pid == -1)
@ -790,7 +800,7 @@ run_exec (stin, stout, sterr, flags)
#ifdef BSD_SIGNALS #ifdef BSD_SIGNALS
if (flags & RUN_SIGIGNORE) if (flags & RUN_SIGIGNORE)
{ {
bzero ((char *) &vec, sizeof (vec)); memset ((char *) &vec, 0, sizeof (vec));
vec.sv_handler = SIG_IGN; vec.sv_handler = SIG_IGN;
(void) sigvec (SIGINT, &vec, &ivec); (void) sigvec (SIGINT, &vec, &ivec);
(void) sigvec (SIGQUIT, &vec, &qvec); (void) sigvec (SIGQUIT, &vec, &qvec);
@ -816,19 +826,19 @@ run_exec (stin, stout, sterr, flags)
#endif #endif
if (w == -1) if (w == -1)
{ {
status = -1; rc = -1;
rerrno = errno; rerrno = errno;
} }
else if (WIFEXITED (status)) else if (WIFEXITED (status))
status = WEXITSTATUS (status); rc = WEXITSTATUS (status);
else if (WIFSIGNALED (status)) else if (WIFSIGNALED (status))
{ {
if (WTERMSIG (status) == SIGPIPE) if (WTERMSIG (status) == SIGPIPE)
error (1, 0, "broken pipe"); error (1, 0, "broken pipe");
status = 2; rc = 2;
} }
else else
status = 1; rc = 1;
/* restore the signals */ /* restore the signals */
#ifdef POSIX #ifdef POSIX
@ -868,7 +878,7 @@ run_exec (stin, stout, sterr, flags)
out0: out0:
if (rerrno) if (rerrno)
errno = rerrno; errno = rerrno;
return (status); return (rc);
} }
void void
@ -910,3 +920,130 @@ get_date (date, now)
} }
#endif #endif
#endif #endif
/* Given two revisions, find their greatest common ancestor. If the
two input revisions exist, then rcs guarantees that the gca will
exist. */
char *
gca (rev1, rev2)
char *rev1;
char *rev2;
{
int dots;
char gca[PATH_MAX];
char *p[2];
int j[2];
if (rev1 == NULL || rev2 == NULL)
{
error (0, 0, "sanity failure in gca");
abort();
}
/* walk the strings, reading the common parts. */
gca[0] = '\0';
p[0] = rev1;
p[1] = rev2;
do
{
int i;
char c[2];
char *s[2];
for (i = 0; i < 2; ++i)
{
/* swap out the dot */
s[i] = strchr (p[i], '.');
if (s[i] != NULL) {
c[i] = *s[i];
}
/* read an int */
j[i] = atoi (p[i]);
/* swap back the dot... */
if (s[i] != NULL) {
*s[i] = c[i];
p[i] = s[i] + 1;
}
else
{
/* or mark us at the end */
p[i] = NULL;
}
}
/* use the lowest. */
(void) sprintf (gca + strlen (gca), "%d.",
j[0] < j[1] ? j[0] : j[1]);
} while (j[0] == j[1]
&& p[0] != NULL
&& p[1] != NULL);
/* back up over that last dot. */
gca[strlen(gca) - 1] = '\0';
/* numbers differ, or we ran out of strings. we're done with the
common parts. */
dots = numdots (gca);
if (dots == 0)
{
/* revisions differ in trunk major number. */
char *q;
char *s;
s = (j[0] < j[1]) ? p[0] : p[1];
if (s == NULL)
{
/* we only got one number. this is strange. */
error (0, 0, "bad revisions %s or %s", rev1, rev2);
abort();
}
else
{
/* we have a minor number. use it. */
q = gca + strlen (gca);
*q++ = '.';
for ( ; *s != '.' && *s != '\0'; )
*q++ = *s++;
*q = '\0';
}
}
else if ((dots & 1) == 0)
{
/* if we have an even number of dots, then we have a branch.
remove the last number in order to make it a revision. */
char *s;
s = strrchr(gca, '.');
*s = '\0';
}
return (xstrdup (gca));
}
#ifdef LOSING_TMPNAM_FUNCTION
char *tmpnam(char *s)
{
static char value[L_tmpnam+1];
if (s){
strcpy(s,"/tmp/cvsXXXXXX");
mktemp(s);
return s;
}else{
strcpy(value,"/tmp/cvsXXXXXX");
mktemp(s);
return value;
}
}
#endif

View File

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* @(#)system.h 1.14 92/04/10 */ /* $CVSid: @(#)system.h 1.18 94/09/25 $ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -52,16 +52,13 @@
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif #endif
#if defined(MKFIFO_MISSING) #if !defined(HAVE_MKFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0)) #define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif #endif
#ifdef POSIX #if defined(POSIX) || defined(HAVE_UNISTD_H)
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX pathconf ("/", _PC_PATH_MAX)
#endif
#else #else
off_t lseek (); off_t lseek ();
#endif #endif
@ -72,7 +69,7 @@ off_t lseek ();
#include <time.h> #include <time.h>
#endif #endif
#ifdef TIMEB_H_MISSING #ifndef HAVE_SYS_TIMEB_H
struct timeb { struct timeb {
time_t time; /* Seconds since the epoch */ time_t time; /* Seconds since the epoch */
unsigned short millitm; /* Field not used */ unsigned short millitm; /* Field not used */
@ -87,29 +84,66 @@ struct timeb {
#include <sys/timeb.h> #include <sys/timeb.h>
#endif #endif
#if defined(FTIME_MISSING) && !defined(HAVE_TIMEZONE) #if !defined(HAVE_FTIME) && !defined(HAVE_TIMEZONE)
#if !defined(timezone) #if !defined(timezone)
extern char *timezone(); extern long timezone;
#endif #endif
#endif #endif
#ifndef POSIX
/*
** MAXPATHLEN and PATH_MAX
**
** On most systems MAXPATHLEN is defined in sys/param.h to be 1024. Of
** those that this is not true, again most define PATH_MAX in limits.h
** or sys/limits.h which usually gets included by limits.h. On the few
** remaining systems that neither statement is true, _POSIX_PATH_MAX
** is defined.
**
** So:
** 1. If PATH_MAX is defined just use it.
** 2. If MAXPATHLEN is defined but not PATH_MAX, then define
** PATH_MAX in terms of MAXPATHLEN.
** 3. If neither is defined, include limits.h and check for
** PATH_MAX again.
** 4. If PATH_MAX is still not defined but _POSIX_PATH_MAX is,
** then define PATH_MAX in terms of _POSIX_PATH_MAX.
** 5. And if even _POSIX_PATH_MAX doesn't exist just put in
** a reasonable value.
**
** This works on:
** Sun Sparc 10 SunOS 4.1.3 & Solaris 1.2
** HP 9000/700 HP/UX 8.07 & HP/UX 9.01
** Tektronix XD88/10 UTekV 3.2e
** IBM RS6000 AIX 3.2
** Dec Alpha OSF 1 ????
** Intel 386 BSDI BSD/386
** Apollo Domain 10.4
** NEC SVR4
*/
/* On MOST systems this will get you MAXPATHLEN */
#include <sys/param.h> #include <sys/param.h>
#endif
#ifndef _POSIX_PATH_MAX #ifndef PATH_MAX
#define _POSIX_PATH_MAX 255 # ifdef MAXPATHLEN
#endif # define PATH_MAX MAXPATHLEN
# else
# include <limits.h>
# ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
# else
# define PATH_MAX 1024
# endif /* _POSIX_PATH_MAX */
# endif /* PATH_MAX */
# endif /* MAXPATHLEN */
#endif /* PATH_MAX */
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX _POSIX_PATH_MAX
#endif
#endif
#ifdef POSIX
#ifdef HAVE_UTIME_H
#include <utime.h> #include <utime.h>
#else #else
#ifndef ALTOS #ifndef ALTOS
@ -122,29 +156,33 @@ struct utimbuf
int utime (); int utime ();
#endif #endif
#if defined(USG) || defined(STDC_HEADERS) #if STDC_HEADERS || HAVE_STRING_H
#include <string.h> #include <string.h>
#ifndef STDC_HEADERS /* An ANSI string.h and pre-ANSI memory.h might conflict. */
#if !STDC_HEADERS && HAVE_MEMORY_H
#include <memory.h> #include <memory.h>
#endif #endif /* not STDC_HEADERS and HAVE_MEMORY_H */
#ifndef index #ifndef index
#define index strchr #define index strchr
#endif #endif /* index */
#ifndef rindex #ifndef rindex
#define rindex strrchr #define rindex strrchr
#endif #endif /* rindex */
#ifndef bcopy
#define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif
#ifndef bzero
#define bzero(s, n) (void) memset ((s), 0, (n))
#endif
#ifndef bcmp #ifndef bcmp
#define bcmp(s1, s2, n) memcmp((s1), (s2), (n)) #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
#endif #endif /* bcmp */
#else
#ifndef bzero
#define bzero(s, n) memset ((s), 0, (n))
#endif /* bzero */
#else /* not STDC_HJEADERS and not HAVE_STRING_H */
#include <strings.h> #include <strings.h>
#endif /* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#include <errno.h> #include <errno.h>
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
@ -157,34 +195,24 @@ char *calloc ();
extern int errno; extern int errno;
#endif #endif
#ifdef __GNUC__
#ifdef bsdi
#define alloca __builtin_alloca
#endif
#else
#ifdef sparc
#include <alloca.h>
#else
#ifndef _AIX
/* AIX alloca decl has to be the first thing in the file, bletch! */
char *alloca ();
#endif
#endif
#endif
#if defined(USG) || defined(POSIX) #if defined(USG) || defined(POSIX)
#include <fcntl.h>
char *getcwd (); char *getcwd ();
#else #else
#include <sys/file.h>
char *getwd (); char *getwd ();
#endif #endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
#include <sys/file.h>
#endif
#ifndef SEEK_SET #ifndef SEEK_SET
#define SEEK_SET 0 #define SEEK_SET 0
#define SEEK_CUR 1 #define SEEK_CUR 1
#define SEEK_END 2 #define SEEK_END 2
#endif #endif
#ifndef F_OK #ifndef F_OK
#define F_OK 0 #define F_OK 0
#define X_OK 1 #define X_OK 1
@ -192,23 +220,23 @@ char *getwd ();
#define R_OK 4 #define R_OK 4
#endif #endif
#ifdef DIRENT /* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(DIRENT) || defined(_POSIX_VERSION)
#include <dirent.h> #include <dirent.h>
#ifdef direct #define NLENGTH(dirent) (strlen((dirent)->d_name))
#undef direct #else /* not (DIRENT or _POSIX_VERSION) */
#endif #define dirent direct
#define direct dirent #define NLENGTH(dirent) ((dirent)->d_namlen)
#else #ifdef HAVE_SYS_NDIR_H
#ifdef SYSNDIR
#include <sys/ndir.h> #include <sys/ndir.h>
#else #endif
#ifdef NDIR #ifdef HAVE_SYS_DIR_H
#include <ndir.h>
#else /* must be BSD */
#include <sys/dir.h> #include <sys/dir.h>
#endif #endif
#endif #ifdef HAVE_NDIR_H
#endif #include <ndir.h>
#endif
#endif /* not (DIRENT or _POSIX_VERSION) */
/* Convert B 512-byte blocks to kilobytes if K is nonzero, /* Convert B 512-byte blocks to kilobytes if K is nonzero,
otherwise return it unchanged. */ otherwise return it unchanged. */
@ -218,6 +246,17 @@ char *getwd ();
#define lstat stat #define lstat stat
#endif #endif
#ifndef SIGTYPE /*
#define SIGTYPE void * Some UNIX distributions don't include these in their stat.h Defined here
* because "config.h" is always included last.
*/
#ifndef S_IWRITE
#define S_IWRITE 0000200 /* write permission, owner */
#endif #endif
#ifndef S_IWGRP
#define S_IWGRP 0000020 /* write permission, grougroup */
#endif
#ifndef S_IWOTH
#define S_IWOTH 0000002 /* write permission, other */
#endif

View File

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef POSIX #ifdef HAVE_SYS_WAIT_H
#include <sys/types.h> /* For pid_t. */ #include <sys/types.h> /* For pid_t. */
#include <sys/wait.h> #include <sys/wait.h>
#else #else

View File

@ -15,6 +15,10 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> #include <stdio.h>
/* Read one line from standard input /* Read one line from standard input

View File

@ -1,5 +1,5 @@
.\" .\"
.\" @(#)mkmodules.1 1.3 92/01/30 .\" $CVSid: @(#)mkmodules.1 1.3 92/01/30 $
.\" .\"
.TH MKMODULES 1 "12 October 1991" .TH MKMODULES 1 "12 October 1991"
.SH "NAME" .SH "NAME"

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner * Copyright (c) 1989-1992, Brian Berliner
* *
* You may distribute under the terms of the GNU General Public License as * You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.3 kit. * specified in the README file that comes with the CVS 1.4 kit.
* *
* mkmodules * mkmodules
* *
@ -13,11 +13,9 @@
#include "cvs.h" #include "cvs.h"
#undef PATH_MAX
#define PATH_MAX 1024 /* max number of bytes in pathname */
#ifndef lint #ifndef lint
static char rcsid[] = "@(#)mkmodules.c 1.39 92/03/31"; static char rcsid[] = "$CVSid: @(#)mkmodules.c 1.45 94/09/30 $";
USE(rcsid)
#endif #endif
#ifndef DBLKSIZ #ifndef DBLKSIZ
@ -30,30 +28,16 @@ char *Rcsbin = RCSBIN_DFLT;
int noexec = 0; /* Here only to satisfy use in subr.c */ int noexec = 0; /* Here only to satisfy use in subr.c */
int trace = 0; /* Here only to satisfy use in subr.c */ int trace = 0; /* Here only to satisfy use in subr.c */
#if __STDC__ static int checkout_file PROTO((char *file, char *temp));
static int checkout_file (char *file, char *temp); static void make_tempfile PROTO((char *temp));
static void make_tempfile (char *temp); static void mkmodules_usage PROTO((void));
static void mkmodules_usage (void); static void rename_rcsfile PROTO((char *temp, char *real));
static void rename_rcsfile (char *temp, char *real);
#ifndef MY_NDBM #ifndef MY_NDBM
static void rename_dbmfile (char *temp); static void rename_dbmfile PROTO((char *temp));
static void write_dbmfile (char *temp); static void write_dbmfile PROTO((char *temp));
#endif /* !MY_NDBM */ #endif /* !MY_NDBM */
#else /* !__STDC__ */
static void make_tempfile ();
static int checkout_file ();
static void rename_rcsfile ();
static void mkmodules_usage ();
#ifndef MY_NDBM
static void write_dbmfile ();
static void rename_dbmfile ();
#endif /* !MY_NDBM */
#endif /* __STDC__ */
int int
main (argc, argv) main (argc, argv)
@ -62,15 +46,34 @@ main (argc, argv)
{ {
extern char *getenv (); extern char *getenv ();
char temp[PATH_MAX]; char temp[PATH_MAX];
char *cp; char *cp, *last, *fname;
#ifdef MY_NDBM #ifdef MY_NDBM
DBM *db; DBM *db;
#endif #endif
FILE *fp;
char line[512];
static struct _checkout_file {
char *filename;
char *errormsg;
} *fileptr, filelist[] = {
{CVSROOTADM_LOGINFO,
"no logging of 'cvs commit' messages is done without a %s file"},
{CVSROOTADM_RCSINFO,
"a %s file can be used to configure 'cvs commit' templates"},
{CVSROOTADM_EDITINFO,
"a %s file can be used to validate log messages"},
{CVSROOTADM_COMMITINFO,
"a %s file can be used to configure 'cvs commit' checking"},
{CVSROOTADM_IGNORE,
"a %s file can be used to specify files to ignore"},
{CVSROOTADM_CHECKOUTLIST,
"a %s file can specify extra CVSROOT files to auto-checkout"},
{NULL, NULL}};
/* /*
* Just save the last component of the path for error messages * Just save the last component of the path for error messages
*/ */
if ((program_name = rindex (argv[0], '/')) == NULL) if ((program_name = strrchr (argv[0], '/')) == NULL)
program_name = argv[0]; program_name = argv[0];
else else
program_name++; program_name++;
@ -127,7 +130,7 @@ main (argc, argv)
/* NOTREACHED */ /* NOTREACHED */
default: default:
error (0, 0, error (0, 0,
"'cvs checkout' is less functional without a %s file", "'cvs checkout' is less functional without a %s file",
CVSROOTADM_MODULES); CVSROOTADM_MODULES);
break; break;
@ -135,57 +138,63 @@ main (argc, argv)
(void) unlink_file (temp); (void) unlink_file (temp);
/* /* Checkout the files that need it in CVSROOT dir */
* Now, check out the "loginfo" file, so that it is always up-to-date in for (fileptr = filelist; fileptr && fileptr->filename; fileptr++) {
* the CVSROOT directory. make_tempfile (temp);
*/ if (checkout_file (fileptr->filename, temp) == 0)
make_tempfile (temp); rename_rcsfile (temp, fileptr->filename);
if (checkout_file (CVSROOTADM_LOGINFO, temp) == 0) #if 0
rename_rcsfile (temp, CVSROOTADM_LOGINFO); /*
else * If there was some problem other than the file not existing,
error (0, 0, * checkout_file already printed a real error message. If the
"no logging of 'cvs commit' messages is done without a %s file", * file does not exist, it is harmless--it probably just means
CVSROOTADM_LOGINFO); * that the repository was created with an old version of CVS
(void) unlink_file (temp); * which didn't have so many files in CVSROOT.
*/
else if (fileptr->errormsg)
error (0, 0, fileptr->errormsg, fileptr->filename);
#endif
(void) unlink_file (temp);
}
/* /* Use 'fopen' instead of 'open_file' because we want to ignore error */
* Now, check out the "rcsinfo" file, so that it is always up-to-date in fp = fopen (CVSROOTADM_CHECKOUTLIST, "r");
* the CVSROOT directory. if (fp)
*/ {
make_tempfile (temp); /*
if (checkout_file (CVSROOTADM_RCSINFO, temp) == 0) * File format:
rename_rcsfile (temp, CVSROOTADM_RCSINFO); * [<whitespace>]<filename><whitespace><error message><end-of-line>
else */
error (0, 0, for (; fgets (line, sizeof (line), fp) != NULL;)
"a %s file can be used to configure 'cvs commit' templates", {
CVSROOTADM_RCSINFO); if ((last = strrchr (line, '\n')) != NULL)
(void) unlink_file (temp); *last = '\0'; /* strip the newline */
/* /* Skip leading white space. */
* Now, check out the "editinfo" file, so that it is always up-to-date in for (fname = line; *fname && isspace(*fname); fname++)
* the CVSROOT directory. ;
*/
make_tempfile (temp); /* Find end of filename. */
if (checkout_file (CVSROOTADM_EDITINFO, temp) == 0) for (cp = fname; *cp && !isspace(*cp); cp++)
rename_rcsfile (temp, CVSROOTADM_EDITINFO); ;
else *cp = '\0';
error (0, 0,
"a %s file can be used to validate log messages", make_tempfile (temp);
CVSROOTADM_EDITINFO); if (checkout_file (fname, temp) == 0)
(void) unlink_file (temp); {
rename_rcsfile (temp, fname);
}
else
{
for (cp++; cp < last && *last && isspace(*last); cp++)
;
if (cp < last && *cp)
error (0, 0, cp, fname);
}
}
(void) fclose (fp);
}
/*
* Now, check out the "commitinfo" file, so that it is always up-to-date
* in the CVSROOT directory.
*/
make_tempfile (temp);
if (checkout_file (CVSROOTADM_COMMITINFO, temp) == 0)
rename_rcsfile (temp, CVSROOTADM_COMMITINFO);
else
error (0, 0,
"a %s file can be used to configure 'cvs commit' checking",
CVSROOTADM_COMMITINFO);
(void) unlink_file (temp);
return (0); return (0);
} }
@ -251,7 +260,7 @@ write_dbmfile (temp)
error (1, errno, "cannot open dbm file %s for creation", temp); error (1, errno, "cannot open dbm file %s for creation", temp);
for (cont = 0; fgets (line, sizeof (line), fp) != NULL;) for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
{ {
if ((cp = rindex (line, '\n')) != NULL) if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0'; /* strip the newline */ *cp = '\0'; /* strip the newline */
/* /*
@ -370,8 +379,15 @@ rename_rcsfile (temp, real)
char *real; char *real;
{ {
char bak[50]; char bak[50];
struct stat statbuf;
char rcs[PATH_MAX];
/* Set "x" bits if set in original. */
(void) sprintf (rcs, "%s%s", real, RCSEXT);
statbuf.st_mode = 0; /* in case rcs file doesn't exist, but it should... */
(void) stat (rcs, &statbuf);
if (chmod (temp, 0444) < 0) /* chmod 444 "temp" */ if (chmod (temp, 0444 | (statbuf.st_mode & 0111)) < 0)
error (0, errno, "warning: cannot chmod %s", temp); error (0, errno, "warning: cannot chmod %s", temp);
(void) sprintf (bak, "%s%s", BAKPREFIX, real); (void) sprintf (bak, "%s%s", BAKPREFIX, real);
(void) unlink_file (bak); /* rm .#loginfo */ (void) unlink_file (bak); /* rm .#loginfo */