This commit was generated by cvs2svn to compensate for changes in r7514,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Nate Williams 1995-03-31 07:45:33 +00:00
commit 789377fada
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=7515
78 changed files with 7160 additions and 4002 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,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,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

@ -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

@ -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.
* *
* 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

@ -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

@ -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,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,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,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

@ -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 */