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
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
large after extended use.
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-*-
#
# 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>
#
# Clean up the history file. 10 Record types: MAR OFT WUCG

View File

@ -1,6 +1,6 @@
#!/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)
#

View File

@ -1,5 +1,5 @@
#! /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
# 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>
.TH CVSCHECK LOCAL "4 March 1991" FLUKE
.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>
.\" Full space in nroff; half space in troff
.de SP

View File

@ -1,5 +1,5 @@
#! /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

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"
.SH NAME
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
#
# Date: Tue, 6 Aug 91 13:27 EDT
@ -11,94 +15,134 @@
# now the output looks like this:
#
# **************************************
# date: Tuesday, August 6, 1991 @ 13:17
# author: samborn
# Date: Tuesday, August 6, 1991 @ 13:17
# Author: samborn
#
# Update of /elmer/cvs/CVSROOT.adm
# In directory astro:/home/samborn/CVSROOT.adm
#
# Modified Files:
# test3
#
# Added Files:
# test6
#
# Removed Files:
# test4
#
# Log Message:
# wow, what a test
#
# RCS: 1.4 /elmer/cvs/CVSROOT.adm/test3,v
# RCS: 1.1 /elmer/cvs/CVSROOT.adm/test6,v
# RCS: 1.1 /elmer/cvs/CVSROOT.adm/Attic/test4,v
# File: test.3 Status: Up-to-date
# Version: 1.4 Thu Apr 29 14:47:07 EDT 1993
# 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
#
$) = $(;
#
# parse command line arguments
#
@files = split(/ /,$ARGV[0]);
$logfile = $ARGV[1];
$cvsroot = $ENV{'CVSROOT'};
while (@ARGV) {
$arg = shift @ARGV;
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
#
@mos = (January,February,March,April,May,June,July,August,September,
October,November,December);
@days = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
#
# get login name
#
$login = getlogin || (getpwuid($<))[0] || "nobody";
#
# open log file for appending
#
if ((open(OUT, ">>" . $logfile)) != 1) {
die "Could not open logfile " . $logfile . "\n";
open(OUT, ">>" . $logfile) || die "Could not open(" . $logfile . "): $!\n";
if ($users) {
$mailcmd = "$mailcmd $users";
open(MAIL, $mailcmd) || die "Could not Exec($mailcmd): $!\n";
}
#
# Header
# print out the log Header
#
print OUT "\n";
print OUT "**************************************\n";
print OUT "date: " . $days[$wday] . ", " . $mos[$mon] . " " . $mday . ", 19" . $year .
" @ " . $hour . ":" . sprintf("%02d", $min) . "\n";
print OUT "author: " . $login . "\n";
print OUT "Date:\t$days[$wday] $mos[$mon] $mday, 19$year @ $hour:" . sprintf("%02d", $min) . "\n";
print OUT "Author:\t$login\n\n";
#
#print the stuff on stdin to the logfile
if (MAIL) {
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, "-");
while(<IN>) {
while (<IN>) {
print OUT $_;
if (MAIL) {
print MAIL $_;
}
}
close(IN);
print OUT "\n";
#
# after log information, do an 'cvs -Qn status' on each file in the arguments.
#
for $file (@files[1..$#files]) {
while (@files) {
$file = shift @files;
if ($file eq "-") {
print OUT "[input file was '-']\n";
if (MAIL) {
print MAIL "[input file was '-']\n";
}
last;
}
open(RCS,"-|") || exec 'cvs', '-Qn', 'status', $file;
open(RCS, "-|") || exec 'cvs', '-Qn', 'status', $file;
while (<RCS>) {
if (substr($_, 0, 7) eq " RCS") {
if (/^[ \t]*Version/ || /^File:/) {
print OUT;
if (MAIL) {
print MAIL;
}
}
close (RCS);
}
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
# 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

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)
* Release 1.02.

View File

@ -4,46 +4,50 @@ Installation of the pcl-cvs program
===================================
1. Edit the file `Makefile' to reflect the situation at your site.
The only things you have to change is the definition of
`lispdir' and `infodir'. The elisp files will be copied to
`lispdir', and the info file to `infodir'.
The only things you have to change is the definition of `lispdir'
and `infodir'. The elisp files will be copied to `lispdir', and
the info file to `infodir'.
2. Configure pcl-cvs.el
There are a couple of paths that you have to check to make
sure that they match you system. They appear early in the file
There are a couple of paths that you have to check to make sure
that they match you system. They appear early in the file
pcl-cvs.el.
*NOTE:* If your system is running emacs 18.57 or earlier
you MUST uncomment the line that says:
*NOTE:* If your system is running emacs 18.57 or earlier you
MUST uncomment the line that says:
(setq delete-exited-processes nil)
Setting `delete-exited-processes' to `nil' works around a bug
in emacs that causes it to dump core. The bug was fixed in
emacs 18.58.
Setting `delete-exited-processes' to `nil' works around a bug in
emacs that causes it to dump core. The bug was fixed in emacs
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
`.elc' into the directory you specified in step 1.
If you don't want to install the `.el' files but only the
`.elc' files (the byte-compiled files), you can type ``make
If you don't want to install the `.el' files but only the `.elc'
files (the byte-compiled files), you can type ``make
install_elc'' instead of ``make install''.
If you only want to create the compiled elisp files, but
don't want to install them, you can type `make elcfiles'
instead. This is what happens if you only type `make' without
parameters.
If you only want to create the compiled elisp files, but don't
want to install them, you can type `make elcfiles' instead.
This is what happens if you only type `make' without 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
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.
Installation of the on-line manual.
===================================
@ -65,8 +69,6 @@ Installation of the on-line manual.
* Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS.
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.
There is also a program which comes together with TeX, `dvips',
which you can use.

View File

@ -1,6 +1,6 @@
# Makefile,v 1.2 1992/04/07 20:49:07 berliner Exp
# Makefile for pcl-cvs release 1.02.
# Copyright (C) 1992 Per Cederqvist
# @(#) Id: dist-makefile,v 1.19 1993/05/31 22:43:45 ceder Exp
# Makefile for pcl-cvs release 1.05.
# Copyright (C) 1992, 1993 Per Cederqvist
#
# 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
@ -26,6 +26,10 @@ lispdir = /usr/local/lib/elisp
prefix=/usr/local
infodir = $(prefix)/info
# Used to byte-compile files.
EMACS=emacs
#
# The rest of this file should not need to be modified.
#
@ -33,8 +37,8 @@ infodir = $(prefix)/info
# Just in case...
SHELL = /bin/sh
ELFILES = pcl-cvs.el cookie.el elib-dll.el elib-node.el
ELCFILES = pcl-cvs.elc cookie.elc elib-dll.elc elib-node.elc
ELFILES = pcl-cvs.el pcl-cvs-lucid.el
ELCFILES = pcl-cvs.elc pcl-cvs-lucid.elc
INFOFILES = pcl-cvs
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 \
@ -45,7 +49,7 @@ INSTALL = install
INSTALL_DATA = $(INSTALL)
elcfiles:
emacs -batch -l ./compile-all.el -f compile-pcl-cvs
$(EMACS) -batch -l ./compile-all.el -f compile-pcl-cvs
all: elcfiles info
@ -66,6 +70,7 @@ info pcl-cvs: pcl-cvs.texinfo
makeinfo +fill-column=70 pcl-cvs.texinfo
pcl-cvs.dvi: 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 \
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
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.
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
;;;; This file byte-compiles all .el files in pcl-cvs release 1.02.
;;;; @(#) 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.05.
;;;;
;;;; 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
;;;; it under the terms of the GNU General Public License as published by
@ -21,14 +22,11 @@
;;;;
(setq elib-files '("elib-node"
"elib-dll"
"cookie"
"pcl-cvs"))
(setq files-to-compile '("pcl-cvs" "pcl-cvs-lucid"))
(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."
(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 ()
"Byte-compile all uncompiled files of elib.
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."
"Byte-compile all uncompiled files of pcl-cvs."
(interactive)
(setq load-path (append '(".") load-path))
;; Be sure to have . in load-path since a number of 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)
elib-files))
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"
"Run a 'cvs update' in the current working directory. Feed the
output to a *cvs* buffer and run cvs-mode on it.
If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
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-*-
@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 Copyright (C) 1992 Per Cederqvist
@ -62,12 +62,12 @@ Free Software Foundation instead of in the original English.
@sp
@center @titlefont{pcl-cvs - the Emacs Front-End to CVS}
@sp 2
@center release 1.02
@center release 1.05
@comment -release-
@sp 3
@center Per Cederqvist
@sp 3
@center last updated 29 Mar 1992
@center last updated 31 May 1993
@comment -date-
@comment The following two commands start the copyright page
@ -104,7 +104,7 @@ Free Software Foundation instead of in the original English.
@ifinfo
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
1.02 of pcl-cvs.
1.05 of pcl-cvs.
@end ifinfo
@comment -release-
@ -119,8 +119,7 @@ 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.
* 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.
* Concept Index:: List of concepts.
* Key Index:: List of keystrokes.
@ -155,9 +154,13 @@ Commands
* Editing files:: Loading files into Emacs.
* Getting info about files:: Display the log and status of files.
* Adding and removing files:: Adding and removing files
* Undoing changes:: Undoing changes
* Removing handled entries:: Uninteresting lines can easily be removed.
* Ignoring files:: Telling CVS to ignore generated files.
* Viewing differences:: Commands to @samp{diff} different versions.
* Emerge::
* Reverting your buffers:: Reverting your buffers
* Miscellaneous commands:: Miscellaneous commands
@end menu
@node Copying, Installation, Top, Top
@ -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
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
Type @samp{make install} in the source directory. This will
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
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.
@ -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
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
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
@comment node-name, next, previous, up
@ -736,11 +755,6 @@ on both the functionality and the documentation.@refill
@cindex Getting pcl-cvs
@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
@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
@ -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
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
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
@ -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:
@example
PCL-CVS release 1.02.
PCL-CVS release 1.05.
@comment -release-
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.
* Getting info about files:: Display the log and status of files.
* Adding and removing files:: Adding and removing files
* Undoing changes:: Undoing changes
* Removing handled entries:: Uninteresting lines can easily be removed.
* Ignoring files:: Telling CVS to ignore generated files.
* Viewing differences:: Commands to @samp{diff} different versions.
* Emerge::
* Reverting your buffers:: Reverting your buffers
* Miscellaneous commands:: Miscellaneous commands
@end menu
@node Updating the directory, Movement commands, Commands, Commands
@comment node-name, next, previous, up
@section Updating the directory
@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}
@ -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*}
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
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
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
@node Movement commands, Marking files, Updating the directory, Commands
@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 all files
@kindex u - unmark a file
@kindex U - unmark all files
@kindex ESC DEL - unmark all files
@kindex DEL - unmark previous file
@findex cvs-mark
@findex cvs-unmark
@findex cvs-mark-all-files
@findex cvs-unmark-all-files
@findex cvs-unmark-up
@findex cvs-mode-mark
@findex cvs-mode-unmark
@findex cvs-mode-mark-all-files
@findex cvs-mode-unmark-all-files
@findex cvs-mode-unmark-up
Pcl-cvs works on a set of @dfn{selected files} (@pxref{Selected files}).
You can mark and unmark files with these commands:
@ -1066,22 +1096,22 @@ You can mark and unmark files with these commands:
@item m
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.
(@code{cvs-mark}).
(@code{cvs-mode-mark}).
@item u
Unmark the file that the cursor is positioned on. If the cursor is on a
directory, all files in that directory will be unmarked.
(@code{cvs-unmark}).@refill
(@code{cvs-mode-unmark}).@refill
@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
Unmark @emph{all} files (@code{cvs-unmark-all-files}).
@item @key{ESC} @key{DEL}
Unmark @emph{all} files (@code{cvs-mode-unmark-all-files}).
@item @key{DEL}
Unmark the file on the previous line, and move point to that line
(@code{cvs-unmark-up}).
(@code{cvs-mode-unmark-up}).
@end table
@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
@cindex Committing changes
@cindex Ci
@findex cvs-commit
@findex cvs-mode-commit
@kindex c - commit files
@vindex cvs-erase-input-buffer (variable)
@vindex cvs-auto-revert-after-commit (variable)
@cindex Commit buffer
@cindex Edit buffer
@cindex Erasing commit message
@cindex Reverting buffers after commit
@table @kbd
@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
selected files (@pxref{Selected files}) (except those who lack the
"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
@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
message from the previous commit, but if the variable
@code{cvs-erase-input-buffer} is set to a non-nil value the buffer will
be erased. Point and mark will always be located around the entire
buffer so that you can easily erase it with @kbd{C-w}
@code{cvs-erase-input-buffer} is set to a non-@code{nil} value the
buffer will be erased. Point and mark will always be located around the
entire buffer so that you can easily erase it with @kbd{C-w}
(@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
@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 Dired
@cindex Invoking dired
@findex cvs-find-file
@findex cvs-find-file-other-window
@findex cvs-add-change-log-entry-other-window
@findex cvs-mode-find-file
@findex cvs-mode-find-file-other-window
@findex cvs-mode-add-change-log-entry-other-window
@kindex f - find file or directory
@kindex o - find file in other window
@kindex A - add ChangeLog entry
@ -1144,17 +1184,17 @@ Find the file that the cursor points to. Run @samp{dired}
@ifinfo
(@pxref{Dired,,,Emacs})
@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
Like @kbd{f}, but use another window
(@code{cvs-find-file-other-window}).@refill
(@code{cvs-mode-find-file-other-window}).@refill
@item A
Invoke @samp{add-change-log-entry-other-window} to edit a
@samp{ChangeLog} file. The @samp{ChangeLog} will be found in the
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
@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
@kindex l - run @samp{cvs log}
@kindex s - run @samp{cvs status}
@findex cvs-log
@findex cvs-status
@findex cvs-mode-log
@findex cvs-mode-status
Both of the following commands can be customized.
@xref{Customization}.@refill
@ -1174,14 +1214,14 @@ Both of the following commands can be customized.
@table @kbd
@item l
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
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
@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
@section Adding and removing files
@cindex Adding files
@ -1191,8 +1231,8 @@ temporary buffer (@code{cvs-status}).
@cindex Putting files under CVS control
@kindex a - add a file
@kindex r - remove a file
@findex cvs-add
@findex cvs-remove-file
@findex cvs-mode-add
@findex cvs-mode-remove-file
The following commands are available to make it easy to add and remove
files from the CVS repository.
@ -1201,7 +1241,7 @@ files from the CVS repository.
@item a
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
@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
repository.@refill
@ -1211,7 +1251,7 @@ them) to resurrect them.
Selected files that are neither @samp{Unknown} nor @samp{Removed} will
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
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
also be @samp{cvs remove}d. If the files were @samp{Unknown} they will
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
The command that is run is @code{cvs-remove-file}.
The command that is run is @code{cvs-mode-remove-file}.
@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
@section Removing handled entries
@cindex Expunging uninteresting entries
@ -1235,8 +1291,9 @@ The command that is run is @code{cvs-remove-file}.
@cindex Handled lines, removing them
@kindex x - remove processed entries
@kindex C-k - remove selected entries
@findex cvs-remove-handled
@findex cvs-acknowledge
@findex cvs-mode-remove-handled
@findex cvs-mode-acknowledge
@findex cvs-mode-ignore
@table @kbd
@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
overview of what needs to be done.
The command is called @code{cvs-remove-handled}. If
@samp{cvs-auto-remove-handled} is set to non-@samp{nil} this will
The command is called @code{cvs-mode-remove-handled}. If
@samp{cvs-auto-remove-handled} is set to non-@code{nil} this will
automatically be performed after every commit.@refill
@item C-k
This command can be used for lines that @samp{cvs-remove-handled} would
not delete, but that you want to delete (@code{cvs-acknowledge}).
This command can be used for lines that @samp{cvs-mode-remove-handled} would
not delete, but that you want to delete (@code{cvs-mode-acknowledge}).
@end table
@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,
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
@node Viewing differences, , Ignoring files, Commands
@node Viewing differences, Emerge, Ignoring files, Commands
@comment node-name, next, previous, up
@section Viewing differences
@cindex Diff
@ -1280,29 +1337,122 @@ This runs @code{cvs-ignore}.
@cindex Viewing differences
@kindex d - run @samp{cvs diff}
@kindex b - diff backup file
@findex cvs-diff-cvs
@findex cvs-diff-backup
@findex cvs-mode-diff-cvs
@findex cvs-mode-diff-backup
@vindex cvs-diff-ignore-marks (variable)
@table @kbd
@item d
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
flags to @samp{cvs diff}. (The function that does the job is
@code{cvs-diff-cvs}).@refill
flags to @samp{cvs diff}. 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-cvs}).@refill
@item b
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
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
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
@file{.#@var{FILE}.@var{VERSION}} and @file{@var{FILE}}. You can get a
context- or Unidiff by setting @samp{cvs-diff-flags} -
@pxref{Customization}. This command only works on files that have
status @samp{Conflict} or @samp{Merged}. The name of the command is
@code{cvs-diff-backup}. @refill
status @samp{Conflict} or @samp{Merged}.@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
@node Customization, Future enhancements, Commands, Top
@ -1310,11 +1460,17 @@ status @samp{Conflict} or @samp{Merged}. The name of the command is
@chapter Customization
@vindex cvs-erase-input-buffer (variable)
@vindex cvs-inhibit-copyright-message (variable)
@vindex cvs-cvs-diff-flags (variable)
@vindex cvs-diff-flags (variable)
@vindex cvs-diff-ignore-marks (variable)
@vindex cvs-log-flags (variable)
@vindex cvs-status-flags (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 Copyright message, getting rid of it
@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 Unidiff, how to get
@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
isn't present in this list, please tell me! @xref{Reporting bugs and
ideas} for info on how to reach me.@refill
isn't present in this list, please tell me! @xref{Bugs} for info on how
to reach me.@refill
@table @samp
@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}).
@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
should see this message at least once).
@item cvs-cvs-diff-flags
A list of strings to pass as arguments to the @samp{cvs diff} program.
This is used by @samp{cvs-diff-cvs} (key @kbd{d}, @pxref{Viewing
differences}). If you prefer the Unidiff format you could add this line
to your @file{.emacs} file:@refill
@item cvs-diff-flags
A list of strings to pass as arguments to the @samp{cvs diff} and
@samp{diff} programs. This is used by @samp{cvs-mode-diff-cvs} and
@samp{cvs-mode-diff-backup} (key @kbd{b}, @pxref{Viewing differences}). If
you prefer the Unidiff format you could add this line to your
@file{.emacs} file:@refill
@example
(setq cvs-cvs-diff-flags '("-u"))
(setq cvs-diff-flags '("-u"))
@end example
@item cvs-diff-flags
Like @samp{cvs-cvs-diff-flags}, but passed to @samp{diff}. This is used
by @samp{cvs-diff-backup} (key @kbd{b}, @pxref{Viewing differences}).
@item cvs-diff-ignore-marks
If this variable is non-@code{nil} or if a prefix argument is given (but
not both) to @samp{cvs-mode-diff-cvs} or @samp{cvs-mode-diff-backup}
marked files are not considered selected.
@item cvs-log-flags
List of strings to send to @samp{cvs log}. Used by @samp{cvs-log} (key
@kbd{l}, @pxref{Getting info about files}).
List of strings to send to @samp{cvs log}. Used by @samp{cvs-mode-log}
(key @kbd{l}, @pxref{Getting info about files}).
@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}).
@item cvs-auto-remove-handled
If this variable is set to any non-@samp{nil} value
@samp{cvs-remove-handled} will be called every time you check in files,
after the check-in is ready. @xref{Removing handled entries}.@refill
If this variable is set to any non-@code{nil} value
@samp{cvs-mode-remove-handled} will be called every time you check in
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
@node Future enhancements, Reporting bugs and ideas, Customization, Top
@node Future enhancements, Bugs, Customization, Top
@comment node-name, next, previous, up
@chapter Future enhancements
@cindex Enhancements
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
pcl-cvs:
be called complete. Below is my current wish-list for future releases
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
@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
Rewritten parser code. There are many situations where pcl-cvs will
fail to recognize the output from CVS. The situation could be greatly
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
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,
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
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
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
of making a good Emacs front end to CVS. See @xref{Reporting bugs and
ideas} for information about how to reach me.@refill
of making a good Emacs front end to CVS. See @xref{Bugs} for
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
@chapter Reporting bugs and ideas
@chapter Bugs (known and unknown)
@cindex Reporting bugs and ideas
@cindex Bugs, how to report them
@cindex Author, how to reach
@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
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
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
@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
# Contributed by Per Cederqvist <ceder@lysator.liu.se>.
# $Id: rcs-to-cvs,v 1.4 1994/09/21 07:23:16 berliner Exp $
# 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
#
# 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.
# You may distribute under the terms of the GNU General Public License.
#
#############################################################################
# #
# This script is used to check in sources that previously was under RCS or #
# no source control system. #
# #
# Usage: rcs-to-cvs repository #
# #
# The repository is the directory where the sources should #
# be deposited.
# #
# checkin traverses the current directory, ensuring that an #
# identical directory structure exists in the repository directory. It #
# then checks the files in in the following manner: #
# #
# 1) If the file doesn't yet exist, check it in #
# as revision 0.1 #
# #
# 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 #
# a file that has been modified on the trunk. #
# #
#
# Check in sources that previously were under RCS or no source control system.
#
# The repository is the directory where the sources should be deposited.
#
# Traverses the current directory, ensuring that an
# identical directory structure exists in the repository directory. It
# then checks the files in in the following manner:
#
# 1) If the file doesn't yet exist, check it in as revision 1.1
#
# 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
# a file that has been modified on the trunk.
#
# Bugs: doesn't put the files in branch 1.1.1
# doesn't put in release and vendor tags
#
#############################################################################
set vbose = 0
set message = ""
set cvsbin = /usr/gnu/bin
set rcsbin = /usr/gnu/bin
set grep = /bin/grep
set message_file = /usr/tmp/checkin.$$
set got_one = 0
usage="Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository"
vbose=0
message=""
message_file=/usr/tmp/checkin.$$
got_one=0
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
endif
while ( $#argv )
switch ( $argv[1] )
case -v:
set vbose = 1
breaksw
case -m:
fi
while [ $# -ne 0 ]; do
case "$1" in
-v)
vbose=1
;;
-m)
shift
echo $argv[1] > $message_file
set got_one = 1
breaksw
case -f:
echo $1 > $message_file
got_one=1
;;
-f)
shift
set message_file = $argv[1]
set got_one = 2
breaksw
default:
message_file=$1
got_one=2
;;
*)
break
endsw
esac
shift
end
if ( $#argv < 1 ) then
echo "Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository"
done
if [ $# -lt 1 ]; then
echo "$usage" >&2
exit 1
endif
set repository = $argv[1]
fi
repository=$1
shift
if ( ! $?CVSROOT ) then
echo "Please set the environmental variable CVSROOT to the root"
echo " of the tree you wish to update"
if [ -z "$CVSROOT" ]; then
echo "Please the environmental variable CVSROOT to the root" >&2
echo " of the tree you wish to update" >&2
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 "to be associated with this file (please remove these lines)">>$message_file
if ( $?EDITOR ) then
$EDITOR $message_file > /dev/tty
else
/usr/ucb/vi $message_file > /dev/tty
endif
set got_one = 1
endif
echo "to be associated with this directory (please remove these lines)">>$message_file
${EDITOR-/usr/ucb/vi} $message_file
got_one=1
fi
umask 22
set update_dir = ${CVSROOT}/${repository}
if ( -d SCCS ) then
echo SCCS files detected!
update_dir=${CVSROOT}/${repository}
[ ! -d ${update_dir} ] && mkdir $update_dir
if [ -d SCCS ]; then
echo SCCS files detected! >&2
exit 1
endif
if ( -d RCS ) then
$rcsbin/co RCS/* >& /dev/null
endif
foreach name ( * .[a-zA-Z0-9]* )
fi
if [ -d RCS ]; then
co RCS/*
fi
for name in * .[a-zA-Z0-9]*
do
case "$name" in
RCS | \* | .\[a-zA-Z0-9\]\* ) continue ;;
esac
echo $name
if ( "$name" == SCCS ) then
continue
endif
if ( "$name" == RCS ) then
continue
endif
if ( $vbose ) then
if [ $vbose -ne 0 ]; then
echo "Updating ${repository}/${name}"
endif
if ( -d "$name" ) then
if ( ! -d "${update_dir}/${name}" ) then
fi
if [ -d "$name" ]; then
if [ ! -d "${update_dir}/${name}" ]; then
echo "WARNING: Creating new directory ${repository}/${name}"
mkdir "${update_dir}/${name}"
if ( $status ) then
echo "ERROR: mkdir failed - aborting"
if [ $? -ne 0 ]; then
echo "ERROR: mkdir failed - aborting" >&2
exit 1
endif
endif
chdir "$name"
if ( $status ) then
echo "ERROR: Couldn\'t chdir to "$name" - aborting"
fi
fi
cd "$name"
if [ $? -ne 0 ]; then
echo "ERROR: Couldn\'t cd to $name - aborting" >&2
exit 1
endif
if ( $vbose ) then
rcs-to-cvs -v -f $message_file "${repository}/${name}"
fi
if [ $vbose -ne 0 ]; then
$0 -v -f $message_file "${repository}/${name}"
else
rcs-to-cvs -f $message_file "${repository}/${name}"
endif
if ( $status ) then
$0 -f $message_file "${repository}/${name}"
fi
if [ $? -ne 0 ]; then
exit 1
endif
chdir ..
fi
cd ..
else # if not directory
if ( ! -f "$name" ) then
echo "WARNING: "$name" is neither a regular file"
if [ ! -f "$name" ]; then
echo "WARNING: $name is neither a regular file"
echo " nor a directory - ignored"
continue
endif
set file = "${update_dir}/${name},v"
set new = 0
set comment = ""
grep -s '\$Log.*\$' "${name}"
if ( $status == 0 ) then # If $Log keyword
set myext = ${name:e}
set knownext = 0
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
endif
end
if ( $knownext == 0 ) then
echo For file ${file}:
fi
file="${update_dir}/${name},v"
comment=""
if grep -s '\$Log.*\$' "${name}"; then # If $Log keyword
myext=`echo $name | sed 's,.*\.,,'`
[ "$myext" = "$name" ] && myext=
case "$myext" in
c | csh | e | f | h | l | mac | me | mm | ms | p | r | red | s | sh | sl | cl | ml | el | tex | y | ye | yr | "" )
;;
* )
echo "For file ${file}:"
grep '\$Log.*\$' "${name}"
echo -n "Please insert a comment leader for file ${name} > "
set comment = $<
endif
endif
if ( ! -f "$file" ) then # If not exists in repository
if ( ! -f "${update_dir}/Attic/${name},v" ) then
read comment
;;
esac
fi
if [ ! -f "$file" ]; then # If not exists in repository
if [ ! -f "${update_dir}/Attic/${name},v" ]; then
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."
cp RCS/"${name}",v "$file"
else
if ( "${comment}" != "" ) then
$rcsbin/rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file"
endif
$rcsbin/ci -q -u0.1 -t${message_file} -m'.' "$file"
if ( $status ) then
echo "ERROR: Initial check-in of $file failed - aborting"
if [ -n "${comment}" ]; then
rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file"
fi
ci -q -u1.1 -t${message_file} -m'.' "$file"
if [ $? -ne 0 ]; then
echo "ERROR: Initial check-in of $file failed - aborting" >&2
exit 1
endif
set new = 1
endif
fi
fi
else
set file = "${update_dir}/Attic/${name},v"
file="${update_dir}/Attic/${name},v"
echo "WARNING: IGNORED: ${repository}/Attic/${name}"
continue
endif
fi
else # File existed
echo ERROR: File exists: Ignored: "$file"
echo "ERROR: File exists in repository: Ignored: $file"
continue
# set headbranch = `sed -n '/^head/p; /^branch/p; 2q' $file`
# if ( $#headbranch != 2 && $#headbranch != 4 ) then
# echo "ERROR: corrupted RCS file $file - aborting"
# endif
# set head = "$headbranch[2]"
# set branch = ""
# if ( $#headbranch == 4 ) then
# 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
fi
fi
done
[ $got_one -eq 1 ] && rm -f $message_file
exit 0

View File

@ -43,7 +43,7 @@
#
# 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

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -27,17 +27,13 @@
#include "cvs.h"
#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
#if __STDC__
static int add_directory (char *repository, char *dir);
static int build_entry (char *repository, char *user, char *options,
char *message, List * entries);
#else
static int add_directory ();
static int build_entry ();
#endif /* __STDC__ */
static int add_directory PROTO((char *repository, char *dir));
static int build_entry PROTO((char *repository, char *user, char *options,
char *message, List * entries, char *tag));
static char *add_usage[] =
{
@ -52,7 +48,7 @@ add (argc, argv)
int argc;
char *argv[];
{
char message[MAXMESGLEN];
char *message = NULL;
char *user;
int i;
char *repository;
@ -67,9 +63,8 @@ add (argc, argv)
usage (add_usage);
/* parse args */
message[0] = '\0';
optind = 1;
while ((c = gnu_getopt (argc, argv, "k:m:")) != -1)
while ((c = getopt (argc, argv, "k:m:")) != -1)
{
switch (c)
{
@ -80,14 +75,7 @@ add (argc, argv)
break;
case 'm':
if (strlen (optarg) >= sizeof (message))
{
error (0, 0, "warning: message too long; truncated!");
(void) strncpy (message, optarg, sizeof (message));
message[sizeof (message) - 1] = '\0';
}
else
(void) strcpy (message, optarg);
message = xstrdup (optarg);
break;
case '?':
default:
@ -111,7 +99,8 @@ add (argc, argv)
int begin_err = err;
user = argv[i];
if (index (user, '/') != NULL)
strip_trailing_slashes (user);
if (strchr (user, '/') != NULL)
{
error (0, 0,
"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 */
if (build_entry (repository, user, vers->options,
message, entries) != 0)
message, entries, vers->tag) != 0)
err++;
else if (!quiet)
else
{
added_files++;
error (0, 0, "scheduling file `%s' for addition",
user);
if (!quiet)
error (0, 0, "scheduling file `%s' for addition", user);
}
}
}
else
{
/*
* There is an RCS file already, so somebody else must've
* added it
@ -214,7 +202,7 @@ add (argc, argv)
(void) strcpy (vers->vn_user, tmp);
(void) sprintf (tmp, "Resurrected %s", user);
Register (entries, user, vers->vn_user, tmp, vers->options,
vers->tag, vers->date);
vers->tag, vers->date, vers->ts_conflict);
free (tmp);
/* 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",
(added_files == 1) ? "this file" : "these files");
dellist (&entries);
if (message)
free (message);
return (err);
}
@ -276,7 +268,7 @@ add_directory (repository, dir)
char message[PATH_MAX + 100];
char *tag, *date;
if (index (dir, '/') != NULL)
if (strchr (dir, '/') != NULL)
{
error (0, 0,
"directory %s not added; must be a direct sub-directory", dir);
@ -334,10 +326,12 @@ add_directory (repository, dir)
if (!isdir (rcsdir))
{
mode_t omask;
char line[MAXLINELEN];
Node *p;
List *ulist;
#if 0
char line[MAXLINELEN];
(void) printf ("Add directory %s to the repository (y/n) [n] ? ",
rcsdir);
(void) fflush (stdout);
@ -348,6 +342,8 @@ add_directory (repository, dir)
error (0, 0, "directory %s not added", rcsdir);
goto out;
}
#endif
omask = umask (2);
if (mkdir (rcsdir, 0777) < 0)
{
@ -389,12 +385,13 @@ add_directory (repository, dir)
* interrogating the user. Returns non-zero on error.
*/
static int
build_entry (repository, user, options, message, entries)
build_entry (repository, user, options, message, entries, tag)
char *repository;
char *user;
char *options;
char *message;
List *entries;
char *tag;
{
char fname[PATH_MAX];
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
* XXX - no they are not!
*/
(void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_OPT);
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);
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);
if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", fname);
@ -442,6 +440,6 @@ build_entry (repository, user, options, message, entries)
* and ,t files, but who cares).
*/
(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);
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -14,18 +14,14 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype admin_dirproc (char *dir, char *repos, char *update_dir);
static int admin_fileproc (char *file, char *update_dir,
static Dtype admin_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int admin_fileproc PROTO((char *file, char *update_dir,
char *repository, List *entries,
List *srcfiles);
#else
static int admin_fileproc ();
static Dtype admin_dirproc ();
#endif /* __STDC__ */
List *srcfiles));
static char *admin_usage[] =
{
@ -60,7 +56,7 @@ admin (argc, argv)
/* start the recursion processor */
err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
(int (*) ()) NULL, argc, argv, 0,
W_LOCAL, 0, 1, (char *) NULL, 1);
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err);
}

View File

@ -3,28 +3,25 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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"
#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
#if __STDC__
static void sticky_ck (char *file, int aflag, Vers_TS * vers, List * entries);
#else
static void sticky_ck ();
#endif /* __STDC__ */
static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers, List * entries));
/*
* Classify the state of a file
*/
Ctype
Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
entries, srcfiles, versp)
entries, srcfiles, versp, update_dir, pipeout)
char *file;
char *tag;
char *date;
@ -35,9 +32,18 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
List *entries;
List *srcfiles;
Vers_TS **versp;
char *update_dir;
int pipeout;
{
Vers_TS *vers;
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 */
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 */
if (!force_tag_match || !(vers->tag || vers->date))
if (!really_quiet)
error (0, 0, "nothing known about %s", file);
error (0, 0, "nothing known about %s", fullname);
ret = T_UNKNOWN;
}
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 (!really_quiet)
error (0, 0, "use `cvs add' to create an entry for %s",
file);
fullname);
ret = T_UNKNOWN;
}
}
@ -78,16 +84,26 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
}
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
* conflict list, only if it is indeed different from what we
* 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 */
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;
}
else
@ -107,7 +123,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
* entry
*/
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;
}
else
@ -126,7 +142,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet)
error (0, 0,
"conflict: %s created independently by second party",
file);
fullname);
ret = T_CONFLICT;
}
}
@ -169,7 +185,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet)
error (0, 0,
"conflict: removed %s was modified by second party",
file);
fullname);
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 */
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;
}
}
@ -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 */
if (!really_quiet)
error (0, 0, "warning: %s is not (any longer) pertinent",
file);
fullname);
ret = T_REMOVE_ENTRY;
}
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
*/
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;
}
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
* 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 */
if (!really_quiet)
error (0, 0,
"conflict: %s is modified but no longer in the repository",
file);
fullname);
ret = T_CONFLICT;
}
else
@ -228,7 +247,7 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
if (!really_quiet)
error (0, 0,
"warning: %s is not (any longer) pertinent",
file);
fullname);
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 (!really_quiet)
error (0, 0, "warning: %s was lost", file);
error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT;
}
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
* 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 (!really_quiet)
error (0, 0, "warning: %s was lost", file);
error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT;
}
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
{
if (No_Difference (file, vers, entries))
if (No_Difference (file, vers, entries,
repository, update_dir))
/* really modified, needs to merge */
ret = T_NEEDS_MERGE;
else
@ -352,6 +373,8 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
else
freevers_ts (&vers);
free (fullname);
/* return the status of the file */
return (ret);
}
@ -374,7 +397,7 @@ sticky_ck (file, aflag, vers, entries)
((entdate && !vers->date) || (!entdate && vers->date)))
{
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
*
* 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
*
@ -17,68 +17,46 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype check_direntproc (char *dir, char *repos, char *update_dir);
static int check_fileproc (char *file, char *update_dir, char *repository,
List * entries, List * srcfiles);
static int check_filesdoneproc (int err, char *repos, char *update_dir);
static int checkaddfile (char *file, char *repository, char *tag);
static Dtype commit_direntproc (char *dir, char *repos, char *update_dir);
static int commit_dirleaveproc (char *dir, int err, char *update_dir);
static int commit_fileproc (char *file, char *update_dir, char *repository,
List * entries, List * srcfiles);
static int commit_filesdoneproc (int err, char *repository, char *update_dir);
static int finaladd (char *file, char *revision, char *tag, char *repository,
List *entries);
static int findmaxrev (Node * p);
static int fsortcmp (Node * p, Node * q);
static int lock_RCS (char *user, char *rcs, char *rev, char *repository);
static int lock_filesdoneproc (int err, char *repository, char *update_dir);
static int lockrcsfile (char *file, char *repository, char *rev);
static int precommit_list_proc (Node * p);
static int precommit_proc (char *repository, char *filter);
static int remove_file (char *file, char *repository, char *tag,
List *entries);
static void fix_rcs_modes (char *rcs, char *user);
static void fixaddfile (char *file, char *repository);
static void fixbranch (char *file, char *repository, char *branch);
static void unlockrcs (char *file, char *repository);
static void ci_delproc (Node *p);
static void locate_rcs (char *file, char *repository, char *rcs);
#else
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__ */
static Dtype check_direntproc PROTO((char *dir, char *repos, char *update_dir));
static int check_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
static int checkaddfile PROTO((char *file, char *repository, char *tag,
List *srcfiles));
static Dtype commit_direntproc PROTO((char *dir, char *repos, char *update_dir));
static int commit_dirleaveproc PROTO((char *dir, int err, char *update_dir));
static int commit_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
static int commit_filesdoneproc PROTO((int err, char *repository, char *update_dir));
static int finaladd PROTO((char *file, char *revision, char *tag, char *options,
char *repository, List *entries));
static int findmaxrev PROTO((Node * p, void *closure));
static int fsortcmp PROTO((Node * p, Node * q));
static int lock_RCS PROTO((char *user, char *rcs, char *rev, char *repository));
static int lock_filesdoneproc PROTO((int err, char *repository, char *update_dir));
static int lockrcsfile PROTO((char *file, char *repository, char *rev));
static int precommit_list_proc PROTO((Node * p, void *closure));
static int precommit_proc PROTO((char *repository, char *filter));
static int remove_file PROTO((char *file, char *repository, char *tag,
char *message, List *entries, List *srcfiles));
static void fix_rcs_modes PROTO((char *rcs, char *user));
static void fixaddfile PROTO((char *file, char *repository));
static void fixbranch PROTO((char *file, char *repository, char *branch));
static void unlockrcs PROTO((char *file, char *repository));
static void ci_delproc PROTO((Node *p));
static void masterlist_delproc PROTO((Node *p));
static void locate_rcs PROTO((char *file, char *repository, char *rcs));
struct commit_info
{
Ctype status; /* as returned from Classify_File() */
char *rev; /* a numeric rev, if we know it */
char *tag; /* any sticky tag, or -r option */
char *options; /* Any sticky -k option */
};
struct master_lists
{
@ -86,6 +64,7 @@ struct master_lists
List *cilist; /* list with commit_info structs */
};
static int force_ci;
static int got_message;
static int run_module_prog = 1;
static int aflag;
@ -98,11 +77,12 @@ static char *message;
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-R\tProcess directories recursively.\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-r rev\tCommit to this branch or trunk revision.\n",
NULL
@ -136,10 +116,8 @@ commit (argc, argv)
}
#endif /* CVS_BADROOT */
message = xmalloc (MAXMESGLEN + 1);
message[0] = '\0'; /* Null message by default */
optind = 1;
while ((c = gnu_getopt (argc, argv, "nlRm:f:r:")) != -1)
while ((c = getopt (argc, argv, "nlRm:fF:r:")) != -1)
{
switch (c)
{
@ -152,14 +130,13 @@ commit (argc, argv)
#else
use_editor = FALSE;
#endif
if (strlen (optarg) >= (size_t) MAXMESGLEN)
if (message)
{
error (0, 0, "warning: message too long; truncated!");
(void) strncpy (message, optarg, MAXMESGLEN);
message[MAXMESGLEN] = '\0';
free (message);
message = NULL;
}
else
(void) strcpy (message, optarg);
message = xstrdup(optarg);
break;
case 'r':
if (tag)
@ -173,6 +150,10 @@ commit (argc, argv)
local = 0;
break;
case 'f':
force_ci = 1;
local = 1; /* also disable recursion */
break;
case 'F':
#ifdef FORCE_USE_EDITOR
use_editor = TRUE;
#else
@ -198,19 +179,26 @@ commit (argc, argv)
tag[strlen (tag) - 1] = '\0';
}
/* some checks related to the "-f logfile" option */
/* some checks related to the "-F logfile" option */
if (logfile)
{
int n, logfd;
struct stat statbuf;
if (*message)
if (message)
error (1, 0, "cannot specify both a message and a log file");
if ((logfd = open (logfile, O_RDONLY)) < 0 ||
(n = read (logfd, message, MAXMESGLEN)) < 0)
{
if ((logfd = open (logfile, O_RDONLY)) < 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);
}
(void) close (logfd);
message[n] = '\0';
}
@ -226,7 +214,8 @@ commit (argc, argv)
locklist = getlist ();
err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
(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);
if (Writer_Lock (locklist) != 0)
error (1, 0, "lock failed - giving up");
@ -241,7 +230,8 @@ commit (argc, argv)
*/
err = start_recursion (check_fileproc, check_filesdoneproc,
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)
{
Lock_Cleanup ();
@ -255,7 +245,7 @@ commit (argc, argv)
err = start_recursion (commit_fileproc, commit_filesdoneproc,
commit_direntproc, commit_dirleaveproc,
argc, argv, local, W_LOCAL, aflag, 0,
(char *) NULL, 1);
(char *) NULL, 1, 0);
/*
* Unlock all the dirs and clean up
@ -291,6 +281,7 @@ lock_filesdoneproc (err, repository, update_dir)
p = getnode ();
p->type = LOCK;
p->key = xstrdup (repository);
/* FIXME-KRP: this error condition should not simply be passed by. */
if (p->key == NULL || addnode (locklist, p) != 0)
freenode (p);
return (err);
@ -330,15 +321,23 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
{
status = Classify_File (file, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers);
if (status == T_UPTODATE)
entries, srcfiles, &vers, update_dir, 0);
if (status == T_UPTODATE || status == T_MODIFIED ||
status == T_ADDED)
{
Ctype xstatus;
freevers_ts (&vers);
status = Classify_File (file, tag, (char *) NULL,
xstatus = Classify_File (file, tag, (char *) NULL,
(char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers);
if (status == T_REMOVE_ENTRY)
entries, srcfiles, &vers, update_dir,
0);
if (xstatus == T_REMOVE_ENTRY)
status = T_MODIFIED;
else if (status == T_MODIFIED && xstatus == T_CONFLICT)
status = T_MODIFIED;
else
status = xstatus;
}
}
else
@ -352,21 +351,22 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
xtag = xstrdup (tag);
if ((numdots (xtag) & 1) != 0)
{
cp = rindex (xtag, '.');
cp = strrchr (xtag, '.');
*cp = '\0';
}
status = Classify_File (file, xtag, (char *) NULL,
(char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers);
entries, srcfiles, &vers, update_dir, 0);
if ((status == T_REMOVE_ENTRY || status == T_CONFLICT)
&& (cp = rindex (xtag, '.')) != NULL)
&& (cp = strrchr (xtag, '.')) != NULL)
{
/* pluck one more dot off the revision */
*cp = '\0';
freevers_ts (&vers);
status = Classify_File (file, xtag, (char *) NULL,
(char *) NULL, 1, aflag, repository,
entries, srcfiles, &vers);
entries, srcfiles, &vers, update_dir,
0);
if (status == T_UPTODATE || status == T_REMOVE_ENTRY)
status = T_MODIFIED;
}
@ -378,17 +378,30 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
}
else
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;
quiet = save_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)
{
case T_CHECKOUT:
case T_NEEDS_MERGE:
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);
freevers_ts (&vers);
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_ADDED, rcs file must not exist
* - 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 (vers->date)
{
if (update_dir[0] == '\0')
error (0, 0,
"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);
return (1);
}
if (status == T_MODIFIED && vers->tag &&
!RCS_isbranch (file, vers->tag, srcfiles))
{
if (update_dir[0] == '\0')
error (0, 0,
"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);
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 (update_dir[0] == '\0')
error (0, 0,
"cannot remove file `%s' which has a numeric sticky tag of `%s'",
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);
return (1);
}
@ -439,18 +535,28 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
locate_rcs (file, repository, rcs);
if (isreadable (rcs))
{
if (update_dir[0] == '\0')
error (0, 0,
"cannot add file `%s' when RCS file `%s' already exists",
file, rcs);
else
error (0, 0,
"cannot add file `%s/%s' when RCS file `%s' already exists",
update_dir, file, rcs);
freevers_ts (&vers);
return (1);
}
if (vers->tag && isdigit (*vers->tag) &&
numdots (vers->tag) > 1)
{
if (update_dir[0] == '\0')
error (0, 0,
"cannot add file `%s' with revision `%s'; must be on trunk",
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);
return (1);
}
@ -480,6 +586,7 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
ml->ulist = ulist;
ml->cilist = cilist;
p->data = (char *) ml;
p->delproc = masterlist_delproc;
(void) addnode (mulist, p);
}
@ -505,17 +612,21 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
else
ci->rev = (char *) NULL;
ci->tag = xstrdup (vers->tag);
ci->options = xstrdup(vers->options);
p->data = (char *) ci;
(void) addnode (cilist, p);
break;
case T_UNKNOWN:
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);
return (1);
case T_UPTODATE:
break;
default:
error (0, 0, "Unknown status 0x%x for `%s'", status, file);
error (0, 0, "CVS internal error: unknown status %d", status);
break;
}
@ -543,11 +654,15 @@ check_direntproc (dir, repos, update_dir)
* Walklist proc to run pre-commit checks
*/
static int
precommit_list_proc (p)
precommit_list_proc (p, closure)
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);
}
return (0);
}
@ -561,14 +676,28 @@ precommit_proc (repository, filter)
char *filter;
{
/* 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;
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);
(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));
}
@ -649,7 +778,7 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
if (use_editor && !got_message)
{
got_message = 1;
do_editor (update_dir, message, repository, ulist);
do_editor (update_dir, &message, repository, ulist);
}
p = findnode (cilist, file);
@ -662,15 +791,17 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
if (lockrcsfile (file, repository, ci->rev) != 0)
{
unlockrcs (file, repository);
return (1);
err = 1;
goto out;
}
}
else if (ci->status == T_ADDED)
{
if (checkaddfile (file, repository, ci->tag) != 0)
if (checkaddfile (file, repository, ci->tag, srcfiles) != 0)
{
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 */
maxrev = 0;
(void) walklist (entries, findmaxrev);
(void) walklist (entries, findmaxrev, NULL);
if (maxrev == 0)
maxrev = 1;
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 */
err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag,
err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag, ci->options,
repository, entries);
if (xrev)
free (xrev);
return (err);
}
if (ci->status == T_MODIFIED)
else if (ci->status == T_MODIFIED)
{
locate_rcs (file, repository, rcs);
err = Checkin ('M', file, repository, rcs, ci->rev, ci->tag,
message, entries);
ci->options, message, entries);
if (err != 0)
{
unlockrcs (file, repository);
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)
err = remove_file (file, repository, ci->tag, entries);
out:
if (err != 0)
{
/* on failure, remove the file from ulist */
p = findnode (ulist, file);
if (p)
delnode (p);
}
return (err);
}
@ -728,19 +866,16 @@ commit_filesdoneproc (err, repository, update_dir)
char *repository;
char *update_dir;
{
List *ulist, *cilist;
char *xtag = (char *) NULL;
Node *p;
List *ulist;
p = findnode (mulist, update_dir);
if (p != NULL)
{
ulist = ((struct master_lists *) p->data)->ulist;
cilist = ((struct master_lists *) p->data)->cilist;
}
else
if (p == NULL)
return (err);
ulist = ((struct master_lists *) p->data)->ulist;
got_message = 0;
/* 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);
Update_Logfile (repository, message, tag ? tag : xtag, (FILE *) 0, ulist);
dellist (&ulist);
dellist (&cilist);
if (xtag)
free (xtag);
@ -765,7 +898,7 @@ commit_filesdoneproc (err, repository, update_dir)
{
if (fgets (line, sizeof (line), fp) != NULL)
{
if ((cp = rindex (line, '\n')) != NULL)
if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0';
repository = Name_Repository ((char *) NULL, update_dir);
run_setup ("%s %s", line, repository);
@ -817,7 +950,7 @@ commit_direntproc (dir, repos, update_dir)
{
got_message = 1;
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);
}
return (R_PROCESS);
@ -844,15 +977,16 @@ commit_dirleaveproc (dir, err, update_dir)
* find the maximum major rev number in an entries file
*/
static int
findmaxrev (p)
findmaxrev (p, closure)
Node *p;
void *closure;
{
char *cp;
int thisrev;
Entnode *entdata;
entdata = (Entnode *) p->data;
cp = index (entdata->version, '.');
cp = strchr (entdata->version, '.');
if (cp != NULL)
*cp = '\0';
thisrev = atoi (entdata->version);
@ -870,18 +1004,23 @@ findmaxrev (p)
* link to keep it relative after we move it into the attic.
*/
static int
remove_file (file, repository, tag, entries)
remove_file (file, repository, tag, message, entries, srcfiles)
char *file;
char *repository;
char *tag;
char *message;
List *entries;
List *srcfiles;
{
int omask;
mode_t omask;
int retcode;
char rcs[PATH_MAX];
char tmp[PATH_MAX];
char *tmp;
retcode = 0;
locate_rcs (file, repository, rcs);
if (tag)
{
/* a symbolic tag is specified; just remove the tag from the file */
@ -894,17 +1033,25 @@ remove_file (file, repository, tag, entries)
"failed to remove tag `%s' from `%s'", tag, rcs);
return (1);
}
Scratch_Entry (entries, file);
return (0);
}
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);
omask = umask (2);
(void) mkdir (tmp, 0777);
(void) umask (omask);
(void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
if ((strcmp (rcs, tmp) == 0 || rename (rcs, tmp) != -1) ||
(!isreadable (rcs) && isreadable (tmp)))
{
@ -919,10 +1066,11 @@ remove_file (file, repository, tag, entries)
* Do the actual checkin for added files
*/
static int
finaladd (file, rev, tag, repository, entries)
finaladd (file, rev, tag, options, repository, entries)
char *file;
char *rev;
char *tag;
char *options;
char *repository;
List *entries;
{
@ -931,7 +1079,7 @@ finaladd (file, rev, tag, repository, entries)
char rcs[PATH_MAX];
locate_rcs (file, repository, rcs);
ret = Checkin ('A', file, repository, rcs, rev, tag,
ret = Checkin ('A', file, repository, rcs, rev, tag, options,
message, entries);
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
* at the committed revision.
*/
static int
checkaddfile (file, repository, tag)
checkaddfile (file, repository, tag, srcfiles)
char *file;
char *repository;
char *tag;
List *srcfiles;
{
FILE *fp;
char *cp;
char rcs[PATH_MAX];
char fname[PATH_MAX];
int omask;
mode_t omask;
int retcode = 0;
if (tag)
{
(void) sprintf(rcs, "%s/%s", repository, CVSATTIC);
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) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
}
@ -1045,7 +1196,7 @@ checkaddfile (file, repository, tag)
fp = open_file (fname, "r");
while (fgets (fname, sizeof (fname), fp) != NULL)
{
if ((cp = rindex (fname, '\n')) != NULL)
if ((cp = strrchr (fname, '\n')) != NULL)
*cp = '\0';
if (*fname)
run_arg (fname);
@ -1058,6 +1209,7 @@ checkaddfile (file, repository, tag)
"could not create %s", rcs);
return (1);
}
fix_rcs_modes (rcs, file);
return (0);
}
@ -1207,9 +1359,26 @@ ci_delproc (p)
free (ci->rev);
if (ci->tag)
free (ci->tag);
if (ci->options)
free (ci->options);
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.
*/

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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.
*
@ -14,7 +14,8 @@
#include "cvs.h"
#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
void
@ -31,9 +32,6 @@ Create_Admin (dir, repository, tag, date)
if (noexec)
return;
if (!isdir (repository))
error (1, 0, "there is no repository %s", repository);
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM);
else
@ -58,6 +56,11 @@ Create_Admin (dir, repository, tag, date)
(void) strcpy (tmp, CVSADM);
make_directory (tmp);
#ifdef CVSADM_ROOT
/* record the current cvs root for later use */
Create_Root (dir, CVSroot);
#endif /* CVSADM_ROOT */
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
else

View File

@ -2,7 +2,7 @@
.ds Rv \\$3
.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"
.\" Full space in nroff; half space in troff
.de SP
@ -181,8 +181,10 @@ Use
.I editor
to enter revision log information.
Overrides the setting of the
.SM CVSEDITOR
and the
.SM EDITOR
environment variable.
environment variables.
.TP
.B \-l
Do not log the
@ -206,7 +208,7 @@ activity. Particularly useful with
to explore the potential impact of an unfamiliar command.
.TP
.B \-r
Makes new working files files read-only.
Makes new working files read-only.
Same effect as if the
.SM CVSREAD
environment variable is set.
@ -388,7 +390,7 @@ same date (unless you explicitly override it; see the description of
the \fBupdate\fP command).
.B \-D
is available with the
.BR checkout ", " diff, ", " history ", " export ", "
.BR checkout ", " diff ", " history ", " export ", "
.BR rdiff ", " rtag ", and "
.B update
commands.
@ -437,7 +439,7 @@ options described in
.BR rcs ( 1 )
are available. The \fB\-k\fP option is available with the
.BR add ", " checkout ", " diff ", "
.RB rdiff ", and " update
.BR rdiff ", and " update
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
this option with the \fBcheckout\fP or \fBupdate\fP commands,
@ -911,6 +913,13 @@ changed; you can use the
option to limit
.B commit
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
.B commit
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
.B \-m
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.
.SP
The
@ -960,7 +969,8 @@ number of dots) with the
.B \-r
option.
To create a branch revision, one typically use the
.B \-b option of the
.B \-b
option of the
.BR rtag " or " tag
commands.
Then, either
@ -1144,7 +1154,7 @@ Report on checked-out modules.
.B \ \ \ \ \ \ \-T
Report on all tags.
.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
history. The types are indicated by single letters, which you may
specify in combination.
@ -1162,6 +1172,18 @@ added; and `R', when a file is removed.
.B \ \ \ \ \ \ \-e
Everything (all record types); equivalent to specifying
.` "\-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
.RS .5i
The options shown as \fB\-\fP\fIflags\fP constrain the report without
@ -1260,8 +1282,8 @@ CVS* cvslog.*
tags TAGS
\&.make.state .nse_depinfo
*~ #* .#* ,*
*.old *.bak *.orig *.rej .del\-*
*.a *.o *.Z *.elc *.ln core
*.old *.bak *.BAK *.orig *.rej .del\-*
*.a *.o *.so *.Z *.elc *.ln core
.fi
.ft P
.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
to enter one.
.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
Use
.` "\-b \fIbranch\fP"
@ -1481,7 +1508,7 @@ into the
.` "Attic"
directory (also within the source repository).
.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
.BR commit .
Use the
@ -1546,7 +1573,7 @@ option to have
.B rtag
look in the
.` "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
symbolic tag as development continues (and files get removed from the
up-coming distribution).
@ -1796,8 +1823,8 @@ CVS* cvslog.*
tags TAGS
\&.make.state .nse_depinfo
*~ #* .#* ,*
*.old *.bak *.orig *.rej .del\-*
*.a *.o *.Z *.elc *.ln core
*.old *.bak *.BAK *.orig *.rej .del\-*
*.a *.o *.so *.Z *.elc *.ln core
.fi
.ft P
.in -1i
@ -1881,7 +1908,7 @@ Records programs for piping
log entries.
.TP
CVSROOT/rcsinfo,v
Records pathnames to templates used dueing a
Records pathnames to templates used during a
.` "cvs commit"
operation.
.TP
@ -1946,10 +1973,15 @@ and
If not set, a compiled-in value is used; see the display from
.` "cvs \-v".
.TP
.SM EDITOR
.SM CVSEDITOR
Specifies the program to use for recording log messages during
.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 .
.SH "AUTHORS"
.TP

View File

@ -243,7 +243,7 @@ removed by this \fBcommit\fP invocation.
.SP
For `\|commitinfo\|', the rest of the line is a command-line template to
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.
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,
@ -254,7 +254,7 @@ should be loaded into the log message template.
.SP
For `\|editinfo\|', the rest of the line is a command-line template to
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.
The full path to the current log message template file is appended to the
template.

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -14,16 +14,13 @@
#include "cvs.h"
#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
#if __STDC__
static Node *AddEntryNode (List * list, char *name, char *version,
static Node *AddEntryNode PROTO((List * list, char *name, char *version,
char *timestamp, char *options, char *tag,
char *date);
#else
static Node *AddEntryNode ();
#endif /* __STDC__ */
char *date, char *conflict));
static FILE *entfile;
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
*/
static int
write_ent_proc (node)
write_ent_proc (node, closure)
Node *node;
void *closure;
{
Entnode *p;
p = (Entnode *) node->data;
if (fprintf (entfile, "/%s/%s/%s/%s/", node->key, p->version,
p->timestamp, p->options) == EOF)
if (fprintf (entfile, "/%s/%s/%s", node->key, p->version,
p->timestamp) == EOF)
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 (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 */
entfilename = CVSADM_ENTBAK;
entfile = open_file (entfilename, "w+");
(void) walklist (list, write_ent_proc);
(void) walklist (list, write_ent_proc, NULL);
if (fclose (entfile) == EOF)
error (1, errno, "error closing %s", entfilename);
@ -102,7 +108,7 @@ Scratch_Entry (list, fname)
* removing the old entry first, if necessary.
*/
void
Register (list, fname, vn, ts, options, tag, date)
Register (list, fname, vn, ts, options, tag, date, ts_conflict)
List *list;
char *fname;
char *vn;
@ -110,13 +116,19 @@ Register (list, fname, vn, ts, options, tag, date)
char *options;
char *tag;
char *date;
char *ts_conflict;
{
int should_write_file = !noexec;
Node *node;
if (trace)
(void) fprintf (stderr, "-> Register(%s, %s, %s, %s, %s %s)\n",
fname, vn, ts, options, tag ? tag : "",
date ? date : "");
{
(void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
fname, vn, ts,
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
options, tag ? tag : "", date ? date : "");
}
/* was it already there? */
if ((node = findnode (list, fname)) != NULL)
{
@ -124,21 +136,24 @@ Register (list, fname, vn, ts, options, tag, date)
delnode (node);
/* add the new one and re-write the file */
(void) AddEntryNode (list, fname, vn, ts, options, tag, date);
if (!noexec)
(void) AddEntryNode (list, fname, vn, ts, options, tag,
date, ts_conflict);
if (should_write_file)
write_entries (list);
}
else
{
/* 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 */
entfilename = CVSADM_ENT;
entfile = open_file (entfilename, "a");
(void) write_ent_proc (node);
(void) write_ent_proc (node, NULL);
if (fclose (entfile) == EOF)
error (1, errno, "error closing %s", entfilename);
}
@ -174,11 +189,14 @@ ParseEntries (aflag)
List *entries;
char line[MAXLINELEN];
char *cp, *user, *vn, *ts, *options;
char *tag_or_date, *tag, *date;
char *tag_or_date, *tag, *date, *ts_conflict;
char *dirtag, *dirdate;
int lineno = 0;
int do_rewrite = 0;
FILE *fpin;
vn = ts = options = tag = date = ts_conflict = 0;
/* get a fresh list... */
entries = getlist ();
@ -192,7 +210,7 @@ ParseEntries (aflag)
struct stickydirtag *sdtp;
sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
bzero ((char *) sdtp, sizeof (*sdtp));
memset ((char *) sdtp, 0, sizeof (*sdtp));
sdtp->aflag = aflag;
sdtp->tag = xstrdup (dirtag);
sdtp->date = xstrdup (dirdate);
@ -214,23 +232,23 @@ ParseEntries (aflag)
if (line[0] == '/')
{
user = line + 1;
if ((cp = index (user, '/')) == NULL)
if ((cp = strchr (user, '/')) == NULL)
continue;
*cp++ = '\0';
vn = cp;
if ((cp = index (vn, '/')) == NULL)
if ((cp = strchr (vn, '/')) == NULL)
continue;
*cp++ = '\0';
ts = cp;
if ((cp = index (ts, '/')) == NULL)
if ((cp = strchr (ts, '/')) == NULL)
continue;
*cp++ = '\0';
options = cp;
if ((cp = index (options, '/')) == NULL)
if ((cp = strchr (options, '/')) == NULL)
continue;
*cp++ = '\0';
tag_or_date = cp;
if ((cp = index (tag_or_date, '\n')) == NULL)
if ((cp = strchr (tag_or_date, '\n')) == NULL)
continue;
*cp = '\0';
tag = (char *) NULL;
@ -239,7 +257,40 @@ ParseEntries (aflag)
tag = tag_or_date + 1;
else if (*tag_or_date == 'D')
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
{
@ -254,6 +305,9 @@ ParseEntries (aflag)
}
}
if (do_rewrite && !noexec)
write_entries (entries);
/* clean up and return */
if (fpin)
(void) fclose (fpin);
@ -311,13 +365,13 @@ check_entries (dir)
continue;
}
rev = line;
if ((ts = index (line, '|')) == NULL)
if ((ts = strchr (line, '|')) == NULL)
continue;
*ts++ = '\0';
if ((user = rindex (ts, ' ')) == NULL)
if ((user = strrchr (ts, ' ')) == NULL)
continue;
*user++ = '\0';
if ((cp = index (user, '|')) == NULL)
if ((cp = strchr (user, '|')) == NULL)
continue;
*cp = '\0';
opt = "";
@ -368,6 +422,8 @@ Entries_delproc (node)
free (p->tag);
if (p->date)
free (p->date);
if (p->conflict)
free (p->conflict);
free ((char *) p);
}
@ -376,7 +432,7 @@ Entries_delproc (node)
* list
*/
static Node *
AddEntryNode (list, name, version, timestamp, options, tag, date)
AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
List *list;
char *name;
char *version;
@ -384,6 +440,7 @@ AddEntryNode (list, name, version, timestamp, options, tag, date)
char *options;
char *tag;
char *date;
char *conflict;
{
Node *p;
Entnode *entdata;
@ -404,6 +461,7 @@ AddEntryNode (list, name, version, timestamp, options, tag, date)
entdata->options = xstrdup (options);
if (entdata->options == NULL)
entdata->options = xstrdup ("");/* must be non-NULL */
entdata->conflict = xstrdup (conflict);
entdata->tag = xstrdup (tag);
entdata->date = xstrdup (date);
@ -452,7 +510,8 @@ WriteTag (dir, tag, date)
error (1, errno, "cannot close %s", tmp);
}
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 ((cp = rindex (line, '\n')) != NULL)
if ((cp = strrchr (line, '\n')) != NULL)
*cp = '\0';
if (*line == 'T' && tagp)
*tagp = xstrdup (line + 1);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -19,16 +19,12 @@
#include "cvs.h"
#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
#if __STDC__
static int find_dirs (char *dir, List * list, int checkadm);
static int find_rcs (char *dir, List * list);
#else
static int find_rcs ();
static int find_dirs ();
#endif /* __STDC__ */
static int find_dirs PROTO((char *dir, List * list, int checkadm));
static int find_rcs PROTO((char *dir, List * list));
static List *filelist;
@ -36,8 +32,9 @@ static List *filelist;
* add the key from entry on entries list to the files list
*/
static int
add_entries_proc (node)
add_entries_proc (node, closure)
Node *node;
void *closure;
{
Node *fnode;
@ -82,7 +79,7 @@ Find_Names (repository, which, aflag, optentries)
if (entries != NULL)
{
/* 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 (optentries != NULL)
@ -167,28 +164,21 @@ find_rcs (dir, list)
List *list;
{
Node *p;
CONST char *regex_err;
char line[50];
struct direct *dp;
struct dirent *dp;
DIR *dirp;
/* set up to read the dir */
if ((dirp = opendir (dir)) == NULL)
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 */
while ((dp = readdir (dirp)) != NULL)
{
if (re_exec (dp->d_name))
if (fnmatch (RCSPAT, dp->d_name, 0) == 0)
{
char *comma;
comma = rindex (dp->d_name, ','); /* strip the ,v */
comma = strrchr (dp->d_name, ','); /* strip the ,v */
*comma = '\0';
p = getnode ();
p->type = FILES;
@ -213,17 +203,10 @@ find_dirs (dir, list, checkadm)
int checkadm;
{
Node *p;
CONST char *regex_err;
char tmp[PATH_MAX];
char admdir[PATH_MAX];
struct direct *dp;
struct dirent *dp;
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 */
if ((dirp = opendir (dir)) == NULL)
return (1);
@ -234,27 +217,51 @@ find_dirs (dir, list, checkadm)
if (strcmp (dp->d_name, ".") == 0 ||
strcmp (dp->d_name, "..") == 0 ||
strcmp (dp->d_name, CVSATTIC) == 0 ||
strcmp (dp->d_name, CVSLCK) == 0 ||
re_exec (dp->d_name)) /* don't bother stating ,v files */
strcmp (dp->d_name, CVSLCK) == 0)
continue;
(void) sprintf (tmp, "%s/%s", dir, dp->d_name);
if (isdir (tmp))
#ifdef DT_DIR
if (dp->d_type != DT_DIR)
{
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
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)
{
/* we're either unknown or a symlink at this point */
if (dp->d_type == DT_LNK)
continue;
#endif
if (islink (tmp))
continue;
#ifdef DT_DIR
}
#endif
/* check for new style */
(void) sprintf (admdir, "%s/%s", tmp, CVSADM);
if (!isdir (admdir))
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
if (!isdir (tmp))
{
/* and old style */
(void) sprintf (admdir, "%s/%s", tmp, OCVSADM);
if (!isdir (admdir))
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, OCVSADM);
if (!isdir (tmp))
continue;
}
}
@ -266,7 +273,6 @@ find_dirs (dir, list, checkadm)
if (addnode (list, p) != 0)
freenode (p);
}
}
(void) closedir (dirp);
return (0);
}

View File

@ -179,7 +179,8 @@
#include "cvs.h"
#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
static struct hrec
@ -197,33 +198,18 @@ static struct hrec
} *hrec_head;
#if __STDC__
static char *fill_hrec (char *line, struct hrec * hr);
static int accept_hrec (struct hrec * hr, struct hrec * lr);
static int select_hrec (struct hrec * hr);
static int sort_order (CONST PTR l, CONST PTR r);
static int within (char *find, char *string);
static time_t date_and_time (char *date_str);
static void expand_modules (void);
static void read_hrecs (char *fname);
static void report_hrecs (void);
static void save_file (char *dir, char *name, char *module);
static void save_module (char *module);
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__ */
static char *fill_hrec PROTO((char *line, struct hrec * hr));
static int accept_hrec PROTO((struct hrec * hr, struct hrec * lr));
static int select_hrec PROTO((struct hrec * hr));
static int sort_order PROTO((CONST PTR l, CONST PTR r));
static int within PROTO((char *find, char *string));
static time_t date_and_time PROTO((char *date_str));
static void expand_modules PROTO((void));
static void read_hrecs PROTO((char *fname));
static void report_hrecs PROTO((void));
static void save_file PROTO((char *dir, char *name, char *module));
static void save_module PROTO((char *module));
static void save_user PROTO((char *name));
#define ALL_REC_TYPES "TOFWUCGMAR"
#define USER_INCREMENT 2
@ -247,6 +233,14 @@ static short repos_sort;
static short file_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 char since_rev[20]; /* Maxrev ~= 99.99.99.999 */
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",
" -t <tag> Since tag record placed in history file (by anyone).\n",
" -u <user> For user name (repeatable)\n",
" -z <tz> Output for time zone <tz> (e.g. -z -0700)\n",
NULL};
/* Sort routine for qsort:
@ -385,7 +380,7 @@ history (argc, argv)
usage (history_usg);
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)
{
@ -481,11 +476,47 @@ history (argc, argv)
char *cp;
for (cp = optarg; *cp; cp++)
if (!index (ALL_REC_TYPES, *cp))
error (1, 0, "%c is not a valid report type", cp);
if (!strchr (ALL_REC_TYPES, *cp))
error (1, 0, "%c is not a valid report type", *cp);
}
(void) strcpy (rec_types, optarg);
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 '?':
default:
usage (history_usg);
@ -508,7 +539,7 @@ history (argc, argv)
if (tag_report)
{
if (!index (rec_types, 'T'))
if (!strchr (rec_types, 'T'))
(void) strcat (rec_types, "T");
}
else if (extract)
@ -559,7 +590,7 @@ history (argc, argv)
save_user (getcaller ());
/* 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");
argc -= c;
@ -637,7 +668,7 @@ history_write (type, update_dir, revs, name, repository)
if (chdir (pw->pw_dir) < 0)
error (1, errno, "can't chdir(%s)", pw->pw_dir);
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);
i = strlen (homedir);
@ -837,16 +868,16 @@ fill_hrec (line, hr)
int off;
static int idx = 0;
bzero ((char *) hr, sizeof (*hr));
memset ((char *) hr, 0, sizeof (*hr));
while (isspace (*line))
line++;
if (!(rtn = index (line, '\n')))
if (!(rtn = strchr (line, '\n')))
return ("");
*rtn++ = '\0';
hr->type = line++;
(void) sscanf (line, "%x", &hr->date);
while (*line && index ("0123456789abcdefABCDEF", *line))
while (*line && strchr ("0123456789abcdefABCDEF", *line))
line++;
if (*line == '\0')
return (rtn);
@ -854,7 +885,7 @@ fill_hrec (line, hr)
line++;
NEXT_BAR (user);
NEXT_BAR (dir);
if ((cp = rindex (hr->dir, '*')) != NULL)
if ((cp = strrchr (hr->dir, '*')) != NULL)
{
*cp++ = '\0';
(void) sscanf (cp, "%x", &off);
@ -865,7 +896,7 @@ fill_hrec (line, hr)
NEXT_BAR (repos);
NEXT_BAR (rev);
hr->idx = idx++;
if (index ("FOT", *(hr->type)))
if (strchr ("FOT", *(hr->type)))
hr->mod = line;
NEXT_BAR (file); /* This returns ptr to next line or final '\0' */
@ -981,7 +1012,7 @@ within (find, string)
while (*string)
{
if (!(string = index (string, c)))
if (!(string = strchr (string, c)))
return (0);
string++;
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, matched appropriately.
*/
if (!index (rec_types, *(hr->type)))
if (!strchr (rec_types, *(hr->type)))
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 */
{
@ -1132,7 +1163,7 @@ select_hrec (hr)
}
else
{
if (index (cp, '/'))
if (strchr (cp, '/'))
{
(void) sprintf (cp2 = cmpfile, "%s/%s",
hr->repos, hr->file);
@ -1215,7 +1246,7 @@ report_hrecs ()
ty = *(lr->type);
(void) strcpy (repos, lr->repos);
if ((cp = rindex (repos, '/')) != NULL)
if ((cp = strrchr (repos, '/')) != NULL)
{
if (lr->mod && !strcmp (++cp, lr->mod))
{
@ -1253,12 +1284,21 @@ report_hrecs ()
continue;
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));
(void) printf ("%c %02d/%02d %02d:%02d %-*s", ty, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, user_len, lr->user);
(void) printf ("%c %02d/%02d %02d:%02d %s %-*s", ty, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tz_name,
user_len, lr->user);
(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))
{
@ -1266,7 +1306,7 @@ report_hrecs ()
}
}
(void) strcpy (repos, lr->repos);
if ((cp = rindex (repos, '/')) != NULL)
if ((cp = strrchr (repos, '/')) != NULL)
{
if (lr->mod && !strcmp (++cp, lr->mod))
{

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -13,30 +13,20 @@
#include "cvs.h"
#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
extern char *ctime ();
#if __STDC__
static int readers_exist (char *repository);
static int set_lock (char *lockdir, int will_wait, char *repository);
static void set_lockers_name (struct stat *statp);
static int set_writelock_proc (Node * p);
static int unlock_proc (Node * p);
static int write_lock (char *repository);
static void unlock (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 int readers_exist PROTO((char *repository));
static int set_lock PROTO((char *lockdir, int will_wait, char *repository));
static void set_lockers_name PROTO((struct stat *statp));
static int set_writelock_proc PROTO((Node * p, void *closure));
static int unlock_proc PROTO((Node * p, void *closure));
static int write_lock PROTO((char *repository));
static void unlock PROTO((char *repository));
static void lock_wait PROTO((char *repository));
static char lockers_name[20];
static char *repository;
@ -65,7 +55,7 @@ Lock_Cleanup ()
/* clean up multiple locks (if any) */
if (locklist != (List *) NULL)
{
(void) walklist (locklist, unlock_proc);
(void) walklist (locklist, unlock_proc, NULL);
locklist = (List *) NULL;
}
}
@ -74,8 +64,9 @@ Lock_Cleanup ()
* walklist proc for removing a list of locks
*/
static int
unlock_proc (p)
unlock_proc (p, closure)
Node *p;
void *closure;
{
unlock (p->key);
return (0);
@ -94,13 +85,15 @@ unlock (repository)
if (readlock[0] != '\0')
{
(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')
{
(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;
}
/*
* Since some systems don't define this...
*/
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
/*
* Create a lock file for readers
*/
@ -127,10 +127,18 @@ Reader_Lock (xrepository)
int err = 0;
FILE *fp;
char tmp[PATH_MAX];
#ifdef HAVE_LONG_FILE_NAMES
char hostname[MAXHOSTNAMELEN];
#endif
if (noexec)
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! */
if (repository != NULL)
{
@ -139,7 +147,13 @@ Reader_Lock (xrepository)
}
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) */
repository = xrepository;
@ -152,16 +166,24 @@ Reader_Lock (xrepository)
(void) SIG_register (SIGTERM, Lock_Cleanup);
/* 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)
{
error (0, errno, "cannot create read lock in repository `%s'",
xrepository);
readlock[0] = '\0';
(void) unlink (tmp);
if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
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 */
(void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
@ -218,7 +240,7 @@ Writer_Lock (list)
locklist = list; /* init for Lock_Cleanup */
(void) strcpy (lockers_name, "unknown");
(void) walklist (list, set_writelock_proc);
(void) walklist (list, set_writelock_proc, NULL);
switch (lock_error)
{
@ -247,8 +269,9 @@ Writer_Lock (list)
* walklist proc for setting write locks
*/
static int
set_writelock_proc (p)
set_writelock_proc (p, closure)
Node *p;
void *closure;
{
/* if some lock was not OK, just skip this one */
if (lock_error != L_OK)
@ -271,9 +294,23 @@ write_lock (repository)
int status;
FILE *fp;
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')
(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 */
(void) SIG_register (SIGHUP, Lock_Cleanup);
@ -283,15 +320,23 @@ write_lock (repository)
(void) SIG_register (SIGTERM, Lock_Cleanup);
/* 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)
{
error (0, errno, "cannot create write lock in repository `%s'",
repository);
(void) unlink (tmp);
if (unlink (tmp) < 0 && errno != ENOENT)
error (0, errno, "failed to remove lock %s", tmp);
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!) */
(void) sprintf (tmp, "%s/%s", repository, CVSLCK);
@ -318,7 +363,9 @@ write_lock (repository)
{
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 */
if (status == L_OK)
{
@ -349,9 +396,8 @@ readers_exist (repository)
{
char line[MAXLINELEN];
DIR *dirp;
struct direct *dp;
struct dirent *dp;
struct stat sb;
CONST char *regex_err;
int ret = 0;
#ifdef CVS_FUDGELOCKS
@ -361,43 +407,46 @@ readers_exist (repository)
if ((dirp = opendir (repository)) == NULL)
error (1, 0, "cannot open directory %s", repository);
(void) sprintf (line, "^%s.*", CVSRFL);
if ((regex_err = re_comp (line)) != NULL)
error (1, 0, "%s", regex_err);
errno = 0;
while ((dp = readdir (dirp)) != NULL)
{
(void) sprintf (line, "%s/%s", repository, dp->d_name);
if (re_exec (dp->d_name))
if (fnmatch (CVSRFLPAT, dp->d_name, 0) == 0)
{
#ifdef CVS_FUDGELOCKS
time_t now;
(void) time (&now);
#endif
/*
* 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.
*/
(void) sprintf (line, "%s/%s", repository, dp->d_name);
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)
{
(void) closedir (dirp);
if (closedir (dirp) < 0)
error (0, errno,
"error closing directory %s", repository);
goto again;
}
#endif
set_lockers_name (&sb);
}
#else
if (stat (line, &sb) != -1)
set_lockers_name (&sb);
#endif
ret = 1;
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);
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -15,17 +15,13 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype log_dirproc (char *dir, char *repository, char *update_dir);
static int log_fileproc (char *file, char *update_dir, char *repository,
List * entries, List * srcfiles);
#else
static int log_fileproc ();
static Dtype log_dirproc ();
#endif /* __STDC__ */
static Dtype log_dirproc PROTO((char *dir, char *repository, char *update_dir));
static int log_fileproc PROTO((char *file, char *update_dir, char *repository,
List * entries, List * srcfiles));
static char options[PATH_MAX];
@ -76,7 +72,7 @@ cvslog (argc, argv)
err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
(int (*) ()) NULL, argc, argv, local,
W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
(char *) NULL, 1);
(char *) NULL, 1, 0);
return (err);
}
@ -99,8 +95,25 @@ log_fileproc (file, update_dir, repository, entries, srcfiles)
p = findnode (srcfiles, file);
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)
error (0, 0, "nothing known about %s", file);
return (1);
}

View File

@ -3,36 +3,34 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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"
#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
#if __STDC__
static int find_type (Node * p);
static int fmt_proc (Node * p);
static int logfile_write (char *repository, char *filter, char *title,
/* this is slightly dangerous, since it could conflict with other systems'
* own prototype.
*/
#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,
List * changes);
static int rcsinfo_proc (char *repository, char *template);
static int title_proc (Node * p);
static int update_logfile_proc (char *repository, char *filter);
static void setup_tmpfile (FILE * xfp, char *xprefix, List * changes);
static int editinfo_proc (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__ */
List * changes));
static int rcsinfo_proc PROTO((char *repository, char *template));
static int title_proc PROTO((Node * p, void *closure));
static int update_logfile_proc PROTO((char *repository, char *filter));
static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes));
static int editinfo_proc PROTO((char *repository, char *template));
static FILE *fp;
static char *strlist;
@ -42,8 +40,7 @@ static Ctype type;
/*
* 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,
* 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 int col;
static void
@ -57,30 +54,30 @@ setup_tmpfile (xfp, xprefix, changes)
prefix = xprefix;
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, "%s\t", prefix);
col = 8;
(void) walklist (changes, fmt_proc);
(void) walklist (changes, fmt_proc, NULL);
(void) fprintf (fp, "\n");
}
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, "%s\t", prefix);
col = 8;
(void) walklist (changes, fmt_proc);
(void) walklist (changes, fmt_proc, NULL);
(void) fprintf (fp, "\n");
}
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, "%s\t", prefix);
col = 8;
(void) walklist (changes, fmt_proc);
(void) walklist (changes, fmt_proc, NULL);
(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
*/
static int
find_type (p)
find_type (p, closure)
Node *p;
void *closure;
{
if (p->data == (char *) type)
return (1);
@ -104,8 +102,9 @@ find_type (p)
* match the one we're looking for
*/
static int
fmt_proc (p)
fmt_proc (p, closure)
Node *p;
void *closure;
{
if (p->data == (char *) type)
{
@ -131,39 +130,38 @@ fmt_proc (p)
*
*/
void
do_editor (dir, message, repository, changes)
do_editor (dir, messagep, repository, changes)
char *dir;
char *message;
char **messagep;
char *repository;
List *changes;
{
static int reuse_log_message = 0;
char line[MAXLINELEN], fname[L_tmpnam+1];
char *orig_message;
struct stat pre_stbuf, post_stbuf;
int retcode = 0;
char *p;
if (noexec || reuse_log_message)
return;
orig_message = xstrdup (message); /* save it for later */
/* Create a temporary file */
(void) tmpnam (fname);
again:
if ((fp = fopen (fname, "w+")) == NULL)
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 (*orig_message)
if (*messagep)
{
(void) fprintf (fp, "%s", orig_message);
if (orig_message[strlen (orig_message) - 1] != '\n')
(void) fprintf (fp, "%s", *messagep);
if ((*messagep)[strlen (*messagep) - 1] != '\n')
(void) fprintf (fp, "\n");
}
else
(void) fprintf (fp, "\n");
if (repository != NULL)
/* tack templates on if necessary */
(void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc, 1);
@ -176,6 +174,7 @@ do_editor (dir, message, repository, changes)
if (dir != NULL)
(void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
dir, CVSEDITPREFIX);
if (changes != NULL)
setup_tmpfile (fp, CVSEDITPREFIX, changes);
(void) fprintf (fp,
"%s----------------------------------------------------------------------\n",
@ -189,6 +188,7 @@ do_editor (dir, message, repository, changes)
if (editinfo_editor)
free (editinfo_editor);
editinfo_editor = (char *) NULL;
if (repository != NULL)
(void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0);
/* run the editor */
@ -200,29 +200,47 @@ do_editor (dir, message, repository, changes)
editinfo_editor ? "Logfile verification 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");
*message = '\0';
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
{
*messagep = (char *) xmalloc (post_stbuf.st_size);
*messagep[0] = '\0';
}
/* !!! XXX FIXME: fgets is broken. This should not have any line
length limits. */
if (*messagep)
{
p = *messagep;
while (fgets (line, sizeof (line), fp) != NULL)
{
if (strncmp (line, CVSEDITPREFIX, sizeof (CVSEDITPREFIX) - 1) == 0)
continue;
if (((int) strlen (message) + (int) strlen (line)) >= MAXMESGLEN)
{
error (0, 0, "warning: log message truncated!");
break;
(void) strcpy (p, line);
p += strlen (line);
}
(void) strcat (message, line);
}
(void) fclose (fp);
if ((stat (fname, &post_stbuf) == 0 &&
pre_stbuf.st_mtime == post_stbuf.st_mtime) ||
(*message == '\0' || strcmp (message, "\n") == 0))
if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
*messagep == NULL ||
strcmp (*messagep, "\n") == 0)
{
for (;;)
{
(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) fflush (stdout);
*line = '\0';
@ -241,7 +259,6 @@ do_editor (dir, message, repository, changes)
(void) printf ("Unknown input\n");
}
}
free (orig_message);
(void) unlink_file (fname);
}
@ -303,6 +320,10 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
{
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 */
message = xmessage;
revision = xrevision;
@ -318,13 +339,13 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
strlist[0] = '\0';
type = T_TITLE;
(void) walklist (changes, title_proc);
(void) walklist (changes, title_proc, NULL);
type = T_ADDED;
(void) walklist (changes, title_proc);
(void) walklist (changes, title_proc, NULL);
type = T_MODIFIED;
(void) walklist (changes, title_proc);
(void) walklist (changes, title_proc, NULL);
type = T_REMOVED;
(void) walklist (changes, title_proc);
(void) walklist (changes, title_proc, NULL);
title = xmalloc (strlen (srepos) + strlen (strlist) + 1 + 2); /* for 's */
(void) sprintf (title, "'%s%s'", srepos, strlist);
@ -355,8 +376,9 @@ update_logfile_proc (repository, filter)
* concatenate each name onto strlist
*/
static int
title_proc (p)
title_proc (p, closure)
Node *p;
void *closure;
{
if (p->data == (char *) type)
{

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -23,7 +23,8 @@
#include "cvs.h"
#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
struct sortrec
@ -34,13 +35,8 @@ struct sortrec
char *comment;
};
#if __STDC__
static int sort_order (CONST PTR l, CONST PTR r);
static void save_d (char *k, int ks, char *d, int ds);
#else
static int sort_order ();
static void save_d ();
#endif /* __STDC__ */
static int sort_order PROTO((CONST PTR l, CONST PTR r));
static void save_d PROTO((char *k, int ks, char *d, int ds));
/*
@ -117,6 +113,13 @@ do_module (db, mname, m_type, msg, callback_proc, where,
if (getwd (cwd) == NULL)
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_path (mname);
@ -142,12 +145,20 @@ do_module (db, mname, m_type, msg, callback_proc, where,
val.dptr[val.dsize] = '\0';
/* If the line ends in a comment, strip it off */
if ((cp = index (val.dptr, '#')) != NULL)
if ((cp = strchr (val.dptr, '#')) != NULL)
{
do
*cp-- = '\0';
while (isspace (*cp));
}
else
{
/* Always strip trailing spaces */
cp = strchr (val.dptr, '\0');
while (cp > val.dptr && isspace(*--cp))
*cp = '\0';
}
value = val.dptr;
mwhere = xstrdup (mname);
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 */
(void) sprintf (file, "%s/%s", CVSroot, mname);
if ((acp = rindex (mname, '/')) != NULL)
if ((acp = strrchr (mname, '/')) != NULL)
{
*acp = '\0';
(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 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;
/* put the ' ' in a copy so we don't mess up the original */
value = strcpy (xvalue, mname);
slashp = rindex (value, '/');
slashp = strrchr (value, '/');
*slashp = ' ';
}
else
@ -218,7 +229,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
}
/* 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 */
*cp = '\0';
@ -240,7 +251,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
val.dptr[val.dsize] = '\0';
/* If the line ends in a comment, strip it off */
if ((cp2 = index (val.dptr, '#')) != NULL)
if ((cp2 = strchr (val.dptr, '#')) != NULL)
{
do
*cp2-- = '\0';
@ -282,7 +293,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
value = zvalue;
/* 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 */
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);
if (!isfile (nullrepos))
(void) mkdir (nullrepos, 0777);
if (!isdir (nullrepos))
error (1, 0, "there is no repository %s", nullrepos);
Create_Admin (".", nullrepos, (char *) NULL, (char *) NULL);
if (!noexec)
{
@ -363,7 +377,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
/* parse the args */
optind = 1;
while ((c = gnu_getopt (modargc, modargv, CVSMODULE_OPTS)) != -1)
while ((c = getopt (modargc, modargv, CVSMODULE_OPTS)) != -1)
{
switch (c)
{
@ -417,9 +431,16 @@ do_module (db, mname, m_type, msg, callback_proc, where,
int i;
for (i = 0; i < modargc; i++)
{
if (strcmp (mname, modargv[i]) == 0)
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)
free (mwhere);
free (zvalue);
@ -445,7 +466,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
{
char *next_opt;
cp = index (spec_opt, CVSMODULE_SPEC);
cp = strchr (spec_opt, CVSMODULE_SPEC);
if (cp != NULL)
{
/* save the beginning of the next arg */
@ -648,7 +669,7 @@ save_d (k, ks, d, ds)
s_rec->status = def_status;
/* 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) == ' ')
{
@ -665,7 +686,7 @@ save_d (k, ks, d, ds)
cp = s_rec->rest;
/* 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 == ' ')
*cp2 = '\0';
@ -748,13 +769,13 @@ cat_module (status)
optind = 1;
wid = 0;
while ((c = gnu_getopt (argc, argv, CVSMODULE_OPTS)) != -1)
while ((c = getopt (argc, argv, CVSMODULE_OPTS)) != -1)
{
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 */
}
else

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -17,14 +17,17 @@
#include "cvs.h"
#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
int
No_Difference (file, vers, entries)
No_Difference (file, vers, entries, repository, update_dir)
char *file;
Vers_TS *vers;
List *entries;
char *repository;
char *update_dir;
{
Node *p;
char tmp[L_tmpnam+1];
@ -58,7 +61,7 @@ No_Difference (file, vers, entries)
ts = time_stamp (file);
Register (entries, file,
vers->vn_user ? vers->vn_user : vers->vn_rcs, ts,
options, vers->tag, vers->date);
options, vers->tag, vers->date, (char *) 0);
free (ts);
/* update the entdata pointer in the vers_ts structure */
@ -72,14 +75,21 @@ No_Difference (file, vers, entries)
}
else
{
if (update_dir[0] == '\0')
error (0, retcode == -1 ? errno : 0,
"could not check out revision %s of %s", vers->vn_user, file);
"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 */
}
if (trace)
(void) fprintf (stderr, "-> unlink(%s)\n", tmp);
(void) unlink (tmp);
if (unlink (tmp) < 0)
error (0, errno, "could not remove %s", tmp);
free (options);
return (ret);
}

View File

@ -3,13 +3,14 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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"
#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
/*
@ -87,7 +88,7 @@ Parse_Info (infofile, repository, callproc, all)
value = cp;
/* strip the newline off the end of the value */
if ((cp = rindex (value, '\n')) != NULL)
if ((cp = strrchr (value, '\n')) != NULL)
*cp = '\0';
/*

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk
*
* 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
* manipulation
@ -11,36 +11,53 @@
#include "cvs.h"
#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
#if __STDC__
static char *RCS_getbranch (RCSNode * rcs, char *tag, int force_tag_match);
static char *RCS_getdatebranch (RCSNode * rcs, char *date, char *branch);
static int getrcskey (FILE * fp, char **keyp, char **valp);
static int parse_rcs_proc (Node * file);
static int checkmagic_proc (Node *p);
static void do_branches (List * list, char *val);
static void do_symbols (List * list, char *val);
static void null_delproc (Node * p);
static void rcsnode_delproc (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 RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, char *rcsfile));
static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
static int getrcskey PROTO((FILE * fp, char **keyp, char **valp));
static int parse_rcs_proc PROTO((Node * file, void *closure));
static int checkmagic_proc PROTO((Node *p, void *closure));
static void do_branches PROTO((List * list, char *val));
static void do_symbols PROTO((List * list, char *val));
static void null_delproc PROTO((Node * p));
static void rcsnode_delproc PROTO((Node * p));
static void rcsvers_delproc PROTO((Node * p));
static List *rcslist;
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
*/
@ -54,7 +71,7 @@ RCS_parsefiles (files, xrepos)
rcslist = getlist ();
/* 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 */
dellist (&rcslist);
@ -69,10 +86,10 @@ RCS_parsefiles (files, xrepos)
* Parse an rcs file into a node on the rcs list
*/
static int
parse_rcs_proc (file)
parse_rcs_proc (file, closure)
Node *file;
void *closure;
{
Node *p;
RCSNode *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 (rdata != (RCSNode *) NULL)
{
p = getnode ();
p->key = xstrdup (file->key);
p->delproc = rcsnode_delproc;
p->type = RCSNODE;
p->data = (char *) rdata;
(void) addnode (rcslist, p);
}
RCS_addnode (file->key, rdata, rcslist);
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
*/
@ -100,43 +132,46 @@ RCS_parse (file, repos)
char *repos;
{
RCSNode *rcs;
FILE *fp;
char rcsfile[PATH_MAX];
(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,
file, RCSEXT);
if (!isreadable (rcsfile))
return (NULL);
rcs = RCS_parsercsfile (rcsfile);
rcs = RCS_parsercsfile_i(fp, rcsfile);
if (rcs != NULL)
rcs->flags |= VALID;
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)
{
rcs->flags |= INATTIC;
rcs->flags |= VALID;
}
fclose (fp);
return (rcs);
}
rcs = RCS_parsercsfile (rcsfile);
if (rcs != NULL)
rcs->flags |= VALID;
return (rcs);
return (NULL);
}
/*
* Do the real work of parsing an RCS file
* Parse a specific rcsfile.
*/
RCSNode *
RCS_parsercsfile (rcsfile)
char *rcsfile;
{
Node *q, *r;
RCSNode *rdata;
RCSVers *vnode;
int n;
char *cp;
char *key, *value;
FILE *fp;
RCSNode *rcs;
/* open the rcsfile */
if ((fp = fopen (rcsfile, "r")) == NULL)
@ -145,9 +180,30 @@ RCS_parsercsfile (rcsfile)
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 */
rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
bzero ((char *) rdata, sizeof (RCSNode));
memset ((char *) rdata, 0, sizeof (RCSNode));
rdata->refcount = 1;
rdata->path = xstrdup (rcsfile);
rdata->versions = getlist ();
@ -161,14 +217,24 @@ RCS_parsercsfile (rcsfile)
{
/* 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 (!really_quiet)
{
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);
(void) fclose (fp);
return (NULL);
}
@ -184,7 +250,7 @@ RCS_parsercsfile (rcsfile)
if ((numdots (rdata->branch) & 1) != 0)
{
/* turn it into a branch if it's a revision */
cp = rindex (rdata->branch, '.');
cp = strrchr (rdata->branch, '.');
*cp = '\0';
}
continue;
@ -193,9 +259,7 @@ RCS_parsercsfile (rcsfile)
{
if (value != NULL)
{
/* if there are tags, set up the tag list */
rdata->symbols = getlist ();
do_symbols (rdata->symbols, value);
rdata->symbols_data = xstrdup(value);
continue;
}
}
@ -225,7 +289,7 @@ RCS_parsercsfile (rcsfile)
/* grab the value of the date from value */
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++;
(void) strcpy (date, valp);
@ -237,7 +301,7 @@ RCS_parsercsfile (rcsfile)
q->delproc = rcsvers_delproc;
r->delproc = null_delproc;
q->data = r->data = xmalloc (sizeof (RCSVers));
bzero (q->data, sizeof (RCSVers));
memset (q->data, 0, sizeof (RCSVers));
vnode = (RCSVers *) q->data;
/* fill in the version before we forget it */
@ -290,7 +354,6 @@ RCS_parsercsfile (rcsfile)
break;
}
(void) fclose (fp);
return (rdata);
}
@ -325,6 +388,8 @@ freercsnode (rnodep)
dellist (&(*rnodep)->dates);
if ((*rnodep)->symbols != (List *) NULL)
dellist (&(*rnodep)->symbols);
if ((*rnodep)->symbols_data != (char *) NULL)
free ((*rnodep)->symbols_data);
if ((*rnodep)->head != (char *) NULL)
free ((*rnodep)->head);
if ((*rnodep)->branch != (char *) NULL)
@ -405,14 +470,14 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL;
return (-1);
}
if (!isspace (c))
if (!whitespace (c))
break;
}
/* fill in key */
cur = key;
max = key + keysize;
while (!isspace (c) && c != ';')
while (!whitespace (c) && c != ';')
{
if (cur < max)
*cur++ = c;
@ -432,6 +497,14 @@ getrcskey (fp, keyp, valp)
return (-1);
}
}
if (cur >= max)
{
key = xrealloc (key, keysize + ALLOCINCR);
cur = key + keysize;
keysize += ALLOCINCR;
max = key + keysize;
}
*cur = '\0';
/* 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 */
if (white && isspace (c))
if (white && whitespace (c))
continue;
if (isspace (c))
if (whitespace (c))
{
/* make c a space and set white */
white = 1;
@ -568,7 +641,16 @@ getrcskey (fp, keyp, valp)
/* terminate the string */
if (cur)
{
if (cur >= max)
{
value = xrealloc (value, valsize + ALLOCINCR);
cur = value + valsize;
valsize += ALLOCINCR;
max = value + valsize;
}
*cur = '\0';
}
/* if the string is empty, make it null */
if (value && *value != '\0')
@ -594,7 +676,7 @@ do_symbols (list, val)
for (;;)
{
/* skip leading whitespace */
while (isspace (*cp))
while (whitespace (*cp))
cp++;
/* if we got to the end, we are done */
@ -603,10 +685,10 @@ do_symbols (list, val)
/* split it up into tag and rev */
tag = cp;
cp = index (cp, ':');
cp = strchr (cp, ':');
*cp++ = '\0';
rev = cp;
while (!isspace (*cp) && *cp != '\0')
while (!whitespace (*cp) && *cp != '\0')
cp++;
if (*cp != '\0')
*cp++ = '\0';
@ -634,7 +716,7 @@ do_branches (list, val)
for (;;)
{
/* skip leading whitespace */
while (isspace (*cp))
while (whitespace (*cp))
cp++;
/* if we got to the end, we are done */
@ -643,7 +725,7 @@ do_branches (list, val)
/* find the end of this branch */
branch = cp;
while (!isspace (*cp) && *cp != '\0')
while (!whitespace (*cp) && *cp != '\0')
cp++;
if (*cp != '\0')
*cp++ = '\0';
@ -686,7 +768,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
if (tagrev == NULL)
return ((char *) NULL);
if ((cp = rindex (tagrev, '.')) != NULL)
if ((cp = strrchr (tagrev, '.')) != NULL)
*cp = '\0';
rev = RCS_getdatebranch (rcs, date, 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 (rcs == NULL)
p = NULL;
else
p = findnode (rcs->symbols, tag);
else {
p = findnode (RCS_symbols(rcs), tag);
}
if (p != NULL)
{
int dots;
@ -750,7 +833,7 @@ RCS_gettag (rcs, tag, force_tag_match)
dots = numdots (tag);
if (dots > 2 && (dots & 1) != 0)
{
branch = rindex (tag, '.');
branch = strrchr (tag, '.');
cp = branch++ - 1;
while (*cp != '.')
cp--;
@ -874,7 +957,7 @@ RCS_magicrev (rcs, rev)
(void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
/* 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;
/* 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.
*/
static int
checkmagic_proc (p)
checkmagic_proc (p, closure)
Node *p;
void *closure;
{
if (strcmp (check_rev, p->data) == 0)
return (1);
@ -897,9 +981,9 @@ checkmagic_proc (p)
}
/*
* 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.
* Given a list of RCSNodes, returns non-zero if the specified
* revision number or symbolic tag resolves to a "branch" within the
* rcs file.
*/
int
RCS_isbranch (file, rev, srcfiles)
@ -907,7 +991,6 @@ RCS_isbranch (file, rev, srcfiles)
char *rev;
List *srcfiles;
{
int dots;
Node *p;
RCSNode *rcs;
@ -922,7 +1005,27 @@ RCS_isbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */
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)
return (0);
dots = numdots (p->data);
@ -933,7 +1036,7 @@ RCS_isbranch (file, rev, srcfiles)
if (dots > 2)
{
char *magic;
char *branch = rindex (p->data, '.');
char *branch = strrchr (p->data, '.');
char *cp = branch - 1;
while (*cp != '.')
cp--;
@ -972,7 +1075,7 @@ RCS_whatbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */
rcs = (RCSNode *) p->data;
p = findnode (rcs->symbols, rev);
p = findnode (RCS_symbols(rcs), rev);
if (p == NULL)
return ((char *) NULL);
dots = numdots (p->data);
@ -983,7 +1086,7 @@ RCS_whatbranch (file, rev, srcfiles)
if (dots > 2)
{
char *magic;
char *branch = rindex (p->data, '.');
char *branch = strrchr (p->data, '.');
char *cp = branch++ - 1;
while (*cp != '.')
cp--;
@ -1008,7 +1111,7 @@ RCS_whatbranch (file, rev, srcfiles)
* Get the head of the specified branch. If the branch does not exist,
* return NULL or RCS_head depending on force_tag_match
*/
static char *
char *
RCS_getbranch (rcs, tag, force_tag_match)
RCSNode *rcs;
char *tag;
@ -1025,7 +1128,7 @@ RCS_getbranch (rcs, tag, force_tag_match)
return ((char *) NULL);
/* 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 */
if (cp == NULL)
@ -1237,7 +1340,7 @@ RCS_getdatebranch (rcs, date, branch)
/* look up the first revision on the branch */
xrev = xstrdup (branch);
cp = rindex (xrev, '.');
cp = strrchr (xrev, '.');
if (cp == NULL)
{
free (xrev);
@ -1374,6 +1477,20 @@ RCS_getrevtime (rcs, rev, date, fudge)
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
* command line. This function returns malloc'ed space that can be used
@ -1439,7 +1556,7 @@ RCS_check_tag (tag)
if (!isgraph (*cp))
error (1, 0, "tag `%s' has non-visible graphic characters",
tag);
if (index (invalid, *cp))
if (strchr (invalid, *cp))
error (1, 0, "tag `%s' must not contain the characters `%s'",
tag, invalid);
}
@ -1447,3 +1564,4 @@ RCS_check_tag (tag)
else
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) 1989-1992, Brian Berliner
*
* 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
*/
@ -19,6 +19,7 @@
#define RCS_RCSMERGE "rcsmerge"
#define RCS_MERGE_PAT "^>>>>>>> " /* runs "grep" with this pattern */
#define RCSEXT ",v"
#define RCSPAT "*,v"
#define RCSHEAD "head"
#define RCSBRANCH "branch"
#define RCSSYMBOLS "symbols"
@ -39,6 +40,7 @@ struct rcsnode
char *path;
char *head;
char *branch;
char *symbols_data;
List *symbols;
List *versions;
List *dates;
@ -66,37 +68,23 @@ typedef struct rcsversnode RCSVers;
/*
* exported interfaces
*/
#if __STDC__
List *RCS_parsefiles (List * files, char *xrepos);
RCSNode *RCS_parse (char *file, char *repos);
RCSNode *RCS_parsercsfile (char *rcsfile);
char *RCS_check_kflag (char *arg);
char *RCS_getdate (RCSNode * rcs, char *date, int force_tag_match);
char *RCS_gettag (RCSNode * rcs, char *tag, int force_tag_match);
char *RCS_getversion (RCSNode * rcs, char *tag, char *date,
int force_tag_match);
char *RCS_magicrev (RCSNode *rcs, char *rev);
int RCS_isbranch (char *file, char *rev, List *srcfiles);
char *RCS_whatbranch (char *file, char *tag, List *srcfiles);
char *RCS_head (RCSNode * rcs);
int RCS_datecmp (char *date1, char *date2);
time_t RCS_getrevtime (RCSNode * rcs, char *rev, char *date, int fudge);
void RCS_check_tag (char *tag);
void freercsnode (RCSNode ** rnodep);
#else
List *RCS_parsefiles ();
RCSNode *RCS_parse ();
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__ */
List *RCS_parsefiles PROTO((List * files, char *xrepos));
RCSNode *RCS_parse PROTO((char *file, char *repos));
RCSNode *RCS_parsercsfile PROTO((char *rcsfile));
char *RCS_check_kflag PROTO((char *arg));
char *RCS_getdate PROTO((RCSNode * rcs, char *date, int force_tag_match));
char *RCS_gettag PROTO((RCSNode * rcs, char *tag, int force_tag_match));
char *RCS_getversion PROTO((RCSNode * rcs, char *tag, char *date,
int force_tag_match));
char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
int RCS_isbranch PROTO((char *file, char *rev, List *srcfiles));
int RCS_nodeisbranch PROTO((char *rev, RCSNode *rcs));
char *RCS_whatbranch PROTO((char *file, char *tag, List *srcfiles));
char *RCS_head PROTO((RCSNode * rcs));
int RCS_datecmp PROTO((char *date1, char *date2));
time_t RCS_getrevtime PROTO((RCSNode * rcs, char *rev, char *date, int fudge));
List *RCS_symbols PROTO((RCSNode *rcs));
void RCS_check_tag PROTO((char *tag));
void freercsnode PROTO((RCSNode ** rnodep));
void RCS_addnode PROTO((char *file, RCSNode *rcs, List *list));
char *RCS_getbranch PROTO((RCSNode * rcs, char *tag, int force_tag_match));

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk
*
* 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
*
@ -11,18 +11,15 @@
#include "cvs.h"
#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
#if __STDC__
static int do_dir_proc (Node * p);
static int do_file_proc (Node * p);
static void addlist (List ** listp, char *key);
#else
static int do_file_proc ();
static int do_dir_proc ();
static void addlist ();
#endif /* __STDC__ */
static int do_dir_proc PROTO((Node * p, void *closure));
static int do_file_proc PROTO((Node * p, void *closure));
static void addlist PROTO((List ** listp, char *key));
static int unroll_files_proc PROTO((Node *p, void *closure));
static void addfile PROTO((List **listp, char *dir, char *file));
/*
@ -41,17 +38,35 @@ static char update_dir[PATH_MAX];
static char *repository = NULL;
static List *entries = 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
* if present, otherwise the local directory is processed.
* Called to start a recursive command.
*
* 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
start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
argc, argv, local, which, aflag, readlock,
update_preload, dosrcs)
update_preload, dosrcs, wd_is_repos)
int (*fileproc) ();
int (*filesdoneproc) ();
Dtype (*direntproc) ();
@ -64,9 +79,12 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
int readlock;
char *update_preload;
int dosrcs;
int wd_is_repos; /* Set if caller has already cd'd to the repository */
{
int i, err = 0;
Dtype flags;
List *files_by_dir = NULL;
struct recursion_frame frame;
if (update_preload == NULL)
update_dir[0] = '\0';
@ -89,7 +107,8 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
if (srcfiles)
dellist (&srcfiles);
if (filelist)
dellist (&filelist);
dellist (&filelist); /* FIXME-krp: no longer correct. */
/* FIXME-krp: clean up files_by_dir */
if (dirlist)
dellist (&dirlist);
@ -111,139 +130,128 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
err += do_recursion (fileproc, filesdoneproc, direntproc,
dirleaveproc, flags, which, aflag,
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
* 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.
*/
/* look for args with /-s in them */
for (i = 0; i < argc; i++)
if (index (argv[i], '/') != NULL)
break;
{
/* if this argument is a directory, then add it to the list of
directories. */
/* 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]))
if (isdir(argv[i]))
addlist (&dirlist, argv[i]);
else
{
if (isdir (CVSADM) || isdir (OCVSADM))
{
char *repos;
/* otherwise, split argument into directory and component names. */
char *dir;
char *comp;
char tmp[PATH_MAX];
char *file_to_try;
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
{
char *cp;
char *dir = (char *) NULL;
char *comp = (char *) NULL;
char *oldupdate = (char *) NULL;
char savewd[PATH_MAX];
if (getwd (savewd) == NULL)
error (1, 0, "could not get working directory: %s", savewd);
for (i = 0; i < argc; i++)
{
/* split the arg into the dir and component parts */
dir = xstrdup (argv[i]);
if ((cp = rindex (dir, '/')) != NULL)
if ((comp = strrchr (dir, '/')) == NULL)
{
*cp = '\0';
comp = xstrdup (cp + 1);
oldupdate = xstrdup (update_dir);
if (update_dir[0] != '\0')
(void) strcat (update_dir, "/");
(void) strcat (update_dir, dir);
/* no dir component. What we have is an implied "./" */
comp = dir;
dir = xstrdup(".");
}
else
{
comp = xstrdup (dir);
if (dir)
free (dir);
dir = (char *) NULL;
char *p = comp;
*p++ = '\0';
comp = xstrdup (p);
}
/* chdir to the appropriate place if necessary */
if (dir && chdir (dir) < 0)
error (1, errno, "could not chdir to %s", dir);
/* if this argument exists as a file in the current
working directory tree, then add it to the files list. */
/* set up the list */
if (isdir (comp))
addlist (&dirlist, comp);
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;
char tmp[PATH_MAX];
repos = Name_Repository ((char *) NULL, update_dir);
/* 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, comp);
if (isdir(tmp))
addlist (&dirlist, argv[i]);
else
addlist (&filelist, comp);
free (repos);
addfile (&files_by_dir, dir, comp);
(void) sprintf (update_dir, "%s", save_update_dir);
free (save_update_dir);
}
else
addlist (&filelist, comp);
addfile (&files_by_dir, dir, comp);
}
else
error (1, 0, "no such directory `%s'", dir);
/* 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)
free (dir);
if (comp)
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);
}
@ -360,7 +368,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
srcfiles = (List *) NULL;
/* process the files */
err += walklist (filelist, do_file_proc);
err += walklist (filelist, do_file_proc, NULL);
/* unlock it */
if (readlock)
@ -378,7 +386,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
/* process the directories (if necessary) */
if (dirlist != NULL)
err += walklist (dirlist, do_dir_proc);
err += walklist (dirlist, do_dir_proc, NULL);
#ifdef notdef
else if (dirleaveproc != NULL)
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
*/
static int
do_file_proc (p)
do_file_proc (p, closure)
Node *p;
void *closure;
{
if (fileproc != NULL)
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)
*/
static int
do_dir_proc (p)
do_dir_proc (p, closure)
Node *p;
void *closure;
{
char *dir = p->key;
char savewd[PATH_MAX];
@ -508,7 +518,7 @@ do_dir_proc (p)
}
/* put back update_dir */
if ((cp = rindex (update_dir, '/')) != NULL)
if ((cp = strrchr (update_dir, '/')) != NULL)
*cp = '\0';
else
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
addlist (listp, key)
@ -531,5 +541,87 @@ addlist (listp, key)
p = getnode ();
p->type = FILES;
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
*
* 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
*
@ -18,26 +18,24 @@
#include "cvs.h"
#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
#if __STDC__
static int remove_fileproc (char *file, char *update_dir,
static int remove_fileproc PROTO((char *file, char *update_dir,
char *repository, List *entries,
List *srcfiles);
static Dtype remove_dirproc (char *dir, char *repos, char *update_dir);
#else
static Dtype remove_dirproc ();
static int remove_fileproc ();
#endif
List *srcfiles));
static Dtype remove_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int force;
static int local;
static int removed_files;
static int auto_removed_files;
static int existing_files;
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-R\tProcess directories recursively.\n",
NULL
@ -54,10 +52,13 @@ cvsremove (argc, argv)
usage (remove_usage);
optind = 1;
while ((c = gnu_getopt (argc, argv, "lR")) != -1)
while ((c = getopt (argc, argv, "flR")) != -1)
{
switch (c)
{
case 'f':
force = 1;
break;
case 'l':
local = 1;
break;
@ -76,15 +77,18 @@ cvsremove (argc, argv)
/* start the recursion processor */
err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
(int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1);
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
if (removed_files)
error (0, 0, "use '%s commit' to remove %s permanently", program_name,
(removed_files == 1) ? "this file" : "these files");
else
if (!auto_removed_files)
error (0, 0, "no files removed; use `%s' to remove the file first",
RM);
if (existing_files)
error (0, 0,
((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);
}
@ -104,24 +108,28 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
char fname[PATH_MAX];
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,
file, 0, 0, entries, srcfiles);
if (vers->ts_user != NULL)
{
freevers_ts (&vers);
return (0);
existing_files++;
if (!quiet)
error (0, 0, "file `%s' still in working directory", file);
}
if (vers->vn_user == NULL)
else if (vers->vn_user == NULL)
{
if (!quiet)
error (0, 0, "nothing known about %s", file);
freevers_ts (&vers);
return (0);
error (0, 0, "nothing known about `%s'", file);
}
if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
{
/*
* 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) unlink_file (fname);
if (!quiet)
error (0, 0, "removed `%s'.", file);
auto_removed_files++;
error (0, 0, "removed `%s'", file);
}
else if (vers->vn_user[0] == '-')
{
freevers_ts (&vers);
return (0);
if (!quiet)
error (0, 0, "file `%s' already scheduled for removal", file);
}
else
{
@ -148,13 +155,11 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
(void) strcpy (fname, "-");
(void) strcat (fname, vers->vn_user);
Register (entries, file, fname, vers->ts_rcs, vers->options,
vers->tag, vers->date);
vers->tag, vers->date, vers->ts_conflict);
if (!quiet)
{
error (0, 0, "scheduling %s for removal", file);
error (0, 0, "scheduling `%s' for removal", file);
removed_files++;
}
}
freevers_ts (&vers);
return (0);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -13,7 +13,8 @@
#include "cvs.h"
#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
char *
@ -112,7 +113,7 @@ Name_Repository (dir, update_dir)
error (1, errno, "cannot read %s", CVSADM_REP);
}
(void) fclose (fpin);
if ((cp = rindex (repos, '\n')) != NULL)
if ((cp = strrchr (repos, '\n')) != NULL)
*cp = '\0'; /* strip the newline */
/*

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -14,24 +14,18 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype rtag_dirproc (char *dir, char *repos, char *update_dir);
static int rtag_fileproc (char *file, char *update_dir,
static Dtype rtag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int rtag_fileproc PROTO((char *file, char *update_dir,
char *repository, List * entries,
List * srcfiles);
static int rtag_proc (int *pargc, char *argv[], char *xwhere,
List * srcfiles));
static int rtag_proc PROTO((int *pargc, char *argv[], char *xwhere,
char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg);
static int rtag_delete (RCSNode *rcsfile);
#else
static int rtag_proc ();
static int rtag_fileproc ();
static Dtype rtag_dirproc ();
static int rtag_delete ();
#endif /* __STDC__ */
int local_specified, char *mname, char *msg));
static int rtag_delete PROTO((RCSNode *rcsfile));
static char *symtag;
static char *numtag;
@ -41,10 +35,11 @@ static int branch_mode; /* make an automagic "branch" tag */
static char *date;
static int local; /* recursive 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[] =
{
"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-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",
@ -55,6 +50,7 @@ static char *rtag_usage[] =
"\t-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-[rD]\tExisting tag or Date.\n",
"\t-F\tMove tag if it already exists\n",
NULL
};
@ -73,7 +69,7 @@ rtag (argc, argv)
usage (rtag_usage);
optind = 1;
while ((c = gnu_getopt (argc, argv, "anfQqlRdbr:D:")) != -1)
while ((c = getopt (argc, argv, "FanfQqlRdbr:D:")) != -1)
{
switch (c)
{
@ -112,6 +108,9 @@ rtag (argc, argv)
free (date);
date = Make_Date (optarg);
break;
case 'F':
force_tag_move = 1;
break;
case '?':
default:
usage (rtag_usage);
@ -178,7 +177,7 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
char path[PATH_MAX];
/* 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';
(void) strcat (repository, "/");
@ -224,7 +223,7 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
/* start the recursion processor */
err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
(int (*) ()) NULL, *pargc - 1, argv + 1, local,
which, 0, 1, where, 1);
which, 0, 1, where, 1, 1);
return (err);
}
@ -315,25 +314,45 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
* "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)
{
if (strcmp (version, oversion) == 0)
int isbranch = RCS_isbranch (file, symtag, srcfiles);
/*
* if versions the same and neither old or new are branches don't
* have to do anything
*/
if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
{
free (version);
free (oversion);
free (version);
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);
free (version);
return (0);
}
free (oversion);
}
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
}
run_arg (rcsfile->path);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
error (1, retcode == -1 ? errno : 0,
"failed to set tag `%s' to revision `%s' in `%s'",
symtag, rev, rcsfile->path);
free (version);

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*/
@ -11,23 +11,20 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype status_dirproc (char *dir, char *repos, char *update_dir);
static int status_fileproc (char *file, char *update_dir,
static Dtype status_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int status_fileproc PROTO((char *file, char *update_dir,
char *repository, List * entries,
List * srcfiles);
static int tag_list_proc (Node * p);
#else
static int tag_list_proc ();
static int status_fileproc ();
static Dtype status_dirproc ();
#endif /* __STDC__ */
List * srcfiles));
static int tag_list_proc PROTO((Node * p, void *closure));
static int local = 0;
static int long_format = 0;
static char *xfile;
static List *xsrcfiles;
static char *status_usage[] =
{
@ -50,7 +47,7 @@ status (argc, argv)
usage (status_usage);
optind = 1;
while ((c = gnu_getopt (argc, argv, "vlR")) != -1)
while ((c = getopt (argc, argv, "vlR")) != -1)
{
switch (c)
{
@ -75,7 +72,7 @@ status (argc, argv)
/* start the recursion processor */
err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
(int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1);
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err);
}
@ -97,7 +94,8 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
Vers_TS *vers;
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)
{
case T_UNKNOWN:
@ -116,6 +114,9 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
sstat = "Locally Removed";
break;
case T_MODIFIED:
if (vers->ts_conflict)
sstat = "Unresolved Conflict";
else
sstat = "Locally Modified";
break;
case T_REMOVE_ENTRY:
@ -136,20 +137,20 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
if (vers->ts_user == NULL)
(void) printf ("File: no file %s\t\tStatus: %s\n\n", file, sstat);
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)
(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')
(void) printf (" Version:\t\tNew file!\n");
(void) printf (" Working revision:\tNew file!\n");
else
(void) printf (" Version:\t\t%s\t%s\n", vers->vn_user,
&vers->ts_rcs[25]);
(void) printf (" Working revision:\t%s\t%s\n", vers->vn_user,
vers->ts_rcs);
if (vers->vn_rcs == NULL)
(void) printf (" RCS Version:\tNo revision control file\n");
(void) printf (" Repository revision:\tNo revision control file\n");
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);
if (vers->entdata)
@ -168,18 +169,25 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
if (isdigit (edata->tag[0]))
(void) printf (" Sticky Tag:\t\t%s\n", edata->tag);
else
{
int isbranch = RCS_isbranch (file, edata->tag, srcfiles);
(void) printf (" Sticky Tag:\t\t%s (%s: %s)\n",
edata->tag, numdots (vers->vn_rcs) % 2 ?
"revision" : "branch", vers->vn_rcs);
edata->tag,
isbranch ? "branch" : "revision",
isbranch ?
RCS_whatbranch(file, edata->tag, srcfiles) :
vers->vn_rcs);
}
}
}
else
(void) printf (" Sticky Tag:\t\t(none)\n");
if (edata->date)
(void) printf (" Sticky Date:\t%s\n", edata->date);
(void) printf (" Sticky Date:\t\t%s\n", edata->date);
else
(void) printf (" Sticky Date:\t(none)\n");
(void) printf (" Sticky Date:\t\t(none)\n");
if (edata->options && edata->options[0])
(void) printf (" Sticky Options:\t%s\n", edata->options);
@ -188,9 +196,15 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
if (long_format && vers->srcfile)
{
List *symbols = RCS_symbols(vers->srcfile);
(void) printf ("\n Existing Tags:\n");
if (vers->srcfile->symbols)
(void) walklist (vers->srcfile->symbols, tag_list_proc);
if (symbols)
{
xfile = file;
xsrcfiles = srcfiles;
(void) walklist (symbols, tag_list_proc, NULL);
}
else
(void) printf ("\tNo Tags Exist\n");
}
@ -220,11 +234,15 @@ status_dirproc (dir, repos, update_dir)
* Print out a tag and its type
*/
static int
tag_list_proc (p)
tag_list_proc (p, closure)
Node *p;
void *closure;
{
int isbranch = RCS_isbranch (xfile, p->key, xsrcfiles);
(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);
return (0);
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -14,33 +14,31 @@
#include "cvs.h"
#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
#if __STDC__
static Dtype tag_dirproc (char *dir, char *repos, char *update_dir);
static int tag_fileproc (char *file, char *update_dir,
static Dtype tag_dirproc PROTO((char *dir, char *repos, char *update_dir));
static int tag_fileproc PROTO((char *file, char *update_dir,
char *repository, List * entries,
List * srcfiles);
#else
static int tag_fileproc ();
static Dtype tag_dirproc ();
#endif /* __STDC__ */
List * srcfiles));
static char *symtag;
static int delete; /* adding a tag by default */
static int branch_mode; /* make an automagic "branch" tag */
static int local; /* recursive by default */
static int force_tag_move; /* don't force tag to move by default */
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-l\tLocal directory only, not recursive.\n",
"\t-R\tProcess directories recursively.\n",
"\t-q\tSomewhat quiet.\n",
"\t-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-F\tMove tag if it already exists\n",
NULL
};
@ -56,7 +54,7 @@ tag (argc, argv)
usage (tag_usage);
optind = 1;
while ((c = gnu_getopt (argc, argv, "QqlRdb")) != -1)
while ((c = getopt (argc, argv, "FQqlRdb")) != -1)
{
switch (c)
{
@ -78,6 +76,9 @@ tag (argc, argv)
case 'b':
branch_mode = 1;
break;
case 'F':
force_tag_move = 1;
break;
case '?':
default:
usage (tag_usage);
@ -100,7 +101,7 @@ tag (argc, argv)
/* start the recursion processor */
err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
(int (*) ()) NULL, argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, 1);
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
return (err);
}
@ -210,24 +211,45 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
* 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 (vers->srcfile, version) : version;
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
if (oversion != NULL)
{
if (strcmp (version, oversion) == 0)
int isbranch = RCS_isbranch (file, symtag, srcfiles);
/*
* if versions the same and neither old or new are branches don't have
* to do anything
*/
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_arg (vers->srcfile->path);
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
error (1, retcode == -1 ? errno : 0,
"failed to set tag %s to revision %s in %s",
symtag, rev, vers->srcfile->path);
freevers_ts (&vers);

View File

@ -3,16 +3,17 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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"
#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
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
@ -39,7 +40,7 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
/* get a new Vers_TS struct */
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
@ -63,6 +64,7 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
vers_ts->vn_user = xstrdup (entdata->version);
vers_ts->ts_rcs = xstrdup (entdata->timestamp);
vers_ts->ts_conflict = xstrdup (entdata->conflict);
if (!tag)
{
if (!(sdtp && sdtp->aflag))
@ -124,8 +126,10 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
else
rcsdata = NULL;
}
else
else if (repository != NULL)
rcsdata = RCS_parse (user, repository);
else
rcsdata = NULL;
if (rcsdata != NULL)
{
@ -152,16 +156,19 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
{
struct utimbuf t;
memset ((char *) &t, 0, sizeof (t));
if (vers_ts->vn_rcs &&
(t.actime = t.modtime = RCS_getrevtime (rcsdata, vers_ts->vn_rcs,
(char *) 0, 0)) != -1)
(t.actime = t.modtime = RCS_getrevtime (rcsdata,
vers_ts->vn_rcs, (char *) 0, 0)) != -1)
(void) utime (user, &t);
}
}
/* get user file time-stamp in ts_user */
if (entries != (List *) NULL)
{
vers_ts->ts_user = time_stamp (user);
}
return (vers_ts);
}
@ -184,13 +191,10 @@ time_stamp (file)
}
else
{
ts = xmalloc (51); /* 51 = 2 ctime strings + NULL */
cp = ctime (&sb.st_ctime); /* copy in the create time */
cp[24] = ' ';
ts = xmalloc (25);
cp = asctime (gmtime (&sb.st_mtime)); /* copy in the modify time */
cp[24] = 0;
(void) strcpy (ts, cp);
cp = ctime (&sb.st_mtime); /* copy in the modify time */
cp[24] = '\0';
(void) strcat (ts, cp);
}
return (ts);
@ -219,6 +223,8 @@ freevers_ts (versp)
free ((*versp)->tag);
if ((*versp)->date)
free ((*versp)->date);
if ((*versp)->ts_conflict)
free ((*versp)->ts_conflict);
free ((char *) *versp);
*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 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
# 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
# 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
# @(#)modules 1.5 92/03/31
# $CVSid: @(#)modules 1.5 92/03/31 $
#
# Three different line formats are valid:
# 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
# is invoked on commit and import.

View File

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

View File

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

View File

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

View File

@ -19,9 +19,13 @@
/* Brian Berliner added support for CVS */
#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 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
/* turn on CVS support by default, since this is the CVS distribution */
@ -35,7 +39,7 @@ void Lock_Cleanup();
#endif /* __STDC__ */
#endif /* CVS_SUPPORT */
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
#if __STDC__
#include <stdarg.h>
@ -47,7 +51,7 @@ void Lock_Cleanup();
#else
#ifndef DOPRNT_MISSING
#ifdef HAVE_DOPRNT
#define va_alist args
#define va_dcl int args;
#else
@ -57,7 +61,7 @@ void Lock_Cleanup();
#endif
#ifdef STDC_HEADERS
#if STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else
@ -68,19 +72,7 @@ void exit ();
#endif /* __STDC__ */
#endif
#ifdef STRERROR_MISSING
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 */
extern char *strerror ();
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
@ -88,7 +80,7 @@ strerror (errnum)
Exit with status STATUS if it is nonzero. */
/* VARARGS */
void
#if !defined (VPRINTF_MISSING) && __STDC__
#if defined (HAVE_VPRINTF) && __STDC__
error (int status, int errnum, char *message, ...)
#else
error (status, errnum, message, va_alist)
@ -102,7 +94,7 @@ error (status, errnum, message, va_alist)
#ifdef CVS_SUPPORT
extern char *command_name;
#endif
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
va_list args;
#endif
@ -117,12 +109,12 @@ error (status, errnum, message, va_alist)
#else
fprintf (stderr, "%s: ", program_name);
#endif
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
VA_START (args, message);
vfprintf (stderr, message, args);
va_end (args);
#else
#ifndef DOPRNT_MISSING
#ifdef HAVE_DOPRNT
_doprnt (message, &args, stderr);
#else
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. */
/* VARARGS */
void
#if !defined (VPRINTF_MISSING) && __STDC__
#if defined (HAVE_VPRINTF) && __STDC__
fperror (FILE *fp, int status, int errnum, char *message, ...)
#else
fperror (fp, status, errnum, message, va_alist)
@ -161,17 +153,17 @@ fperror (fp, status, errnum, message, va_alist)
#endif
{
extern char *program_name;
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
va_list args;
#endif
fprintf (fp, "%s: ", program_name);
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
VA_START (args, message);
vfprintf (fp, message, args);
va_end (args);
#else
#ifndef DOPRNT_MISSING
#ifdef HAVE_DOPRNT
_doprnt (message, &args, fp);
#else
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 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* IGNORE(@ */
/* #include <ansidecl.h> */
/* @) */
@ -28,10 +32,6 @@ Cambridge, MA 02139, USA. */
extern int errno;
#endif
#if !__STDC__
#define const
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
int

View File

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

View File

@ -1,29 +1,98 @@
%{
/* 1.8
** @(#)getdate.y 1.8 92/03/03
**
/*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
** 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.
*/
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
/* 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>
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
#ifdef __GNUC__
#undef alloca /* might get redefined below */
/* The code at the top of get_date which figures out the offset of the
current time zone checks various CPP symbols to see if special
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
#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
@ -31,9 +100,11 @@ extern struct tm *localtime();
#define yyerror getdate_yyerror
#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) */
static int yylex ();
static int yyerror ();
#define EPOCH 1970
#define HOUR(x) ((time_t)(x) * 60)
@ -202,6 +273,18 @@ date : tUNUMBER '/' tUNUMBER {
yyDay = $3;
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 {
yyMonth = $1;
yyDay = $2;
@ -263,14 +346,12 @@ number : tUNUMBER {
yyYear = $1;
else {
if($1>10000) {
time_t date_part;
date_part= $1/10000;
yyHaveDate++;
yyDay= (date_part)%100;
yyMonth= (date_part/100)%100;
yyYear = date_part/10000;
yyDay= ($1)%100;
yyMonth= ($1/100)%100;
yyYear = $1/10000;
}
else {
yyHaveTime++;
if ($1 < 100) {
yyHour = $1;
@ -284,6 +365,7 @@ number : tUNUMBER {
yyMeridian = MER24;
}
}
}
;
o_merid : /* NULL */ {
@ -297,7 +379,7 @@ o_merid : /* NULL */ {
%%
/* Month and day table. */
static TABLE MonthDayTable[] = {
static TABLE const MonthDayTable[] = {
{ "january", tMONTH, 1 },
{ "february", tMONTH, 2 },
{ "march", tMONTH, 3 },
@ -326,7 +408,7 @@ static TABLE MonthDayTable[] = {
};
/* Time units table. */
static TABLE UnitsTable[] = {
static TABLE const UnitsTable[] = {
{ "year", tMONTH_UNIT, 12 },
{ "month", tMONTH_UNIT, 1 },
{ "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
@ -341,7 +423,7 @@ static TABLE UnitsTable[] = {
};
/* Assorted relative-time words. */
static TABLE OtherTable[] = {
static TABLE const OtherTable[] = {
{ "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
{ "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
{ "today", tMINUTE_UNIT, 0 },
@ -367,7 +449,7 @@ static TABLE OtherTable[] = {
/* The timezone table. */
/* 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 */
{ "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
{ "utc", tZONE, HOUR( 0) },
@ -451,7 +533,7 @@ static TABLE TimezoneTable[] = {
};
/* Military timezone table. */
static TABLE MilitaryTable[] = {
static TABLE const MilitaryTable[] = {
{ "a", tZONE, HOUR( 1) },
{ "b", tZONE, HOUR( 2) },
{ "c", tZONE, HOUR( 3) },
@ -484,7 +566,7 @@ static TABLE MilitaryTable[] = {
/* ARGSUSED */
int
static int
yyerror(s)
char *s;
{
@ -514,6 +596,8 @@ ToSeconds(Hours, Minutes, Seconds, Meridian)
if (Hours < 1 || Hours > 12)
return -1;
return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
default:
abort ();
}
/* NOTREACHED */
}
@ -624,7 +708,7 @@ LookupWord(buff)
{
register char *p;
register char *q;
register TABLE *tp;
register const TABLE *tp;
int i;
int abbrev;
@ -725,7 +809,7 @@ LookupWord(buff)
}
int
static int
yylex()
{
register char c;
@ -777,13 +861,36 @@ 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
get_date(p, now)
char *p;
struct timeb *now;
{
struct tm *tm;
struct tm *tm, gmt;
struct timeb ftz;
time_t Start;
time_t tod;
@ -791,34 +898,25 @@ get_date(p, now)
yyInput = p;
if (now == NULL) {
now = &ftz;
#if defined(FTIME_MISSING)
(void)time(&ftz.time);
/* Set the timezone global. */
tzset();
#if defined(HAVE_TIMEZONE)
tm = localtime(&ftz.time);
ftz.timezone = tm->tm_gmtoff / 60;
#else
#if defined(timezone)
ftz.tzone = (int) timezone / 60;
#else
ftz.timezone = (int) timezone / 60;
#endif /* defined(timezone) */
#endif /* defined(HAVE_TIMEZONE) */
#else
(void)ftime(&ftz);
#endif /* defined(FTIME_MISSING) */
if (! (tm = gmtime (&ftz.time)))
return -1;
gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
if (! (tm = localtime (&ftz.time)))
return -1;
ftz.timezone = difftm (&gmt, tm) / 60;
if(tm->tm_isdst)
ftz.timezone += 60;
}
tm = localtime(&now->time);
yyYear = tm->tm_year;
yyMonth = tm->tm_mon + 1;
yyDay = tm->tm_mday;
#if defined(timezone)
yyTimezone = now->tzone;
#else
yyTimezone = now->timezone;
#endif /* defined(timezone) */
yyDSTmode = DSTmaybe;
yyHour = 0;
yyMinutes = 0;
@ -865,6 +963,7 @@ get_date(p, now)
#if defined(TEST)
/* ARGSUSED */
int
main(ac, av)
int ac;
char *av[];

View File

@ -1,10 +1,10 @@
/* declarations for getopt
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
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
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.
When `getopt' finds an option that takes an argument,
@ -44,16 +51,21 @@ extern int optind;
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
_GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an
element containing a name which is zero.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
0 if the option does not take an argument,
1 if the option requires an argument,
2 if the option takes an optional argument.
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an 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
left unchanged if the option is not found.
@ -66,37 +78,54 @@ extern int opterr;
struct option
{
#if __STDC__
const char *name;
#else
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 *flag;
int val;
};
#if __STDC__
extern const struct option *_getopt_long_options;
#else
extern struct option *_getopt_long_options;
#endif
/* Names for the values of the `has_arg' field of `struct option'. */
/* If nonzero, '-' can introduce long-named options.
Set by getopt_long_only. */
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;
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if __STDC__
int gnu_getopt (int argc, char **argv, const char *shortopts);
int gnu_getopt_long (int argc, char **argv, const char *shortopts,
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* not __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
int gnu_getopt_long_only (int argc, char **argv, const char *shortopts,
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
#else
int gnu_getopt ();
int gnu_getopt_long ();
int gnu_getopt_long_only ();
/* 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 /* _GETOPT_H */

View File

@ -1,10 +1,11 @@
/* Getopt for GNU.
Copyright (C) 1987-1992 Free Software Foundation, Inc.
/* getopt_long and getopt_long_only entry points for GNU getopt.
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
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
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"
#if !__STDC__
#define const
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#include <stdlib.h>
#else /* STDC_HEADERS or __GNU_LIBRARY__ */
char *getenv ();
#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
#include "getopt.h"
#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
#endif
int
gnu_getopt_long (argc, argv, options, long_options, opt_index)
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char **argv;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
int val;
/* 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;
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '+' can indicate a long option.
If an option that starts with '-' doesn't match a long option,
/* Like getopt_long, but '-' as well as '--' can indicate 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
instead. */
int
gnu_getopt_long_only (argc, argv, options, long_options, opt_index)
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char **argv;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
int val;
_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;
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
#include <stdio.h>
@ -89,7 +107,6 @@ main (argc, argv)
while (1)
{
int this_option_optind = optind ? optind : 1;
char *name = '\0';
int option_index = 0;
static struct option long_options[] =
{
@ -110,7 +127,7 @@ main (argc, argv)
switch (c)
{
case 0:
printf ("option %s", (long_options[option_index]).name);
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
@ -144,6 +161,10 @@ main (argc, argv)
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;

View File

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

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk
*
* 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.
*/
@ -10,31 +10,32 @@
#include "cvs.h"
#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
/* global caches */
static List *listcache = NULL;
static Node *nodecache = NULL;
#if __STDC__
static void freenode_mem (Node * p);
#else
static void freenode_mem ();
#endif /* __STDC__ */
static void freenode_mem PROTO((Node * p));
/* hash function */
static int
hashp (key)
char *key;
{
register char *p;
register int n = 0;
unsigned int h = 0;
unsigned int g;
for (p = key; *p; p++)
n += *p;
while (*key != 0)
{
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 */
list = (List *) xmalloc (sizeof (List));
bzero ((char *) list, sizeof (List));
memset ((char *) list, 0, sizeof (List));
node = getnode ();
list->list = node;
node->type = HEADER;
@ -130,7 +131,7 @@ getnode ()
}
/* always make it clean */
bzero ((char *) p, sizeof (Node));
memset ((char *) p, 0, sizeof (Node));
p->type = UNKNOWN;
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 *
findnode (list, key)
@ -273,9 +275,10 @@ findnode (list, key)
* walk a list with a specific proc
*/
int
walklist (list, proc)
walklist (list, proc, closure)
List *list;
int (*proc) ();
void *closure;
{
Node *head, *p;
int err = 0;
@ -285,7 +288,7 @@ walklist (list, proc)
head = list->list;
for (p = head->next; p != head; p = p->next)
err += proc (p);
err += proc (p, closure);
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
*
* 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 *tag;
char *date;
char *conflict;
};
typedef struct entnode Entnode;
#if __STDC__
List *getlist (void);
Node *findnode (List * list, char *key);
Node *getnode (void);
int addnode (List * list, Node * p);
int walklist (List * list, int (*proc) ());
void dellist (List ** listp);
void delnode (Node * p);
void freenode (Node * p);
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__ */
List *getlist PROTO((void));
Node *findnode PROTO((List * list, char *key));
Node *getnode PROTO((void));
int addnode PROTO((List * list, Node * p));
int walklist PROTO((List * list, int PROTO((*proc)) PROTO((Node *n, void *closure)), void *closure));
void dellist PROTO((List ** listp));
void delnode PROTO((Node * p));
void freenode PROTO((Node * p));
void sortlist PROTO((List * list, int PROTO((*comp))()));

View File

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

View File

@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner
*
* 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:
*
@ -18,7 +18,8 @@
#ifdef MY_NDBM
#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
static void mydbm_load_file ();
@ -138,7 +139,7 @@ mydbm_load_file (fp, list)
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 */
/*

View File

@ -1,4 +1,4 @@
/* @(#)myndbm.h 1.3 92/02/29 */
/* $CVSid: @(#)myndbm.h 1.4 94/09/21 $ */
#ifdef MY_NDBM
@ -27,18 +27,10 @@ typedef struct
#define dbm_firstkey mydbm_firstkey
#define dbm_nextkey mydbm_nextkey
#if __STDC__
DBM *mydbm_open (char *file, int flags, int mode);
void mydbm_close (DBM * db);
datum mydbm_fetch (DBM * db, datum key);
datum mydbm_firstkey (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__ */
DBM *mydbm_open PROTO((char *file, int flags, int mode));
void mydbm_close PROTO((DBM * db));
datum mydbm_fetch PROTO((DBM * db, datum key));
datum mydbm_firstkey PROTO((DBM * db));
datum mydbm_nextkey PROTO((DBM * db));
#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
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

View File

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

View File

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

View File

@ -15,14 +15,20 @@
along with this program; if not, write to the Free Software
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>
#ifndef index
#define index strchr
#endif
#else
/* 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>
#endif
/* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#include <stdio.h>
@ -43,7 +49,7 @@ strip_path (path)
int stripped = 0;
char *cp, *slash;
for (cp = path; (slash = index(cp, '/')) != NULL; cp = slash)
for (cp = path; (slash = strchr(cp, '/')) != NULL; cp = slash)
{
*slash = '\0';
if ((!*cp && (cp != path || stripped)) ||

View File

@ -15,12 +15,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if defined(STDC_HEADERS) || defined(USG)
#include <string.h>
#else
#include <strings.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#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. */
void

View File

@ -3,19 +3,24 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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.
*/
#include "cvs.h"
#ifndef lint
static char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
USE(rcsid)
#endif
#ifdef _MINIX
#undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
#endif
#ifndef VPRINTF_MISSING
#if __STDC__
#ifdef HAVE_VPRINTF
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
#include <stdarg.h>
#define VA_START(args, lastarg) va_start(args, lastarg)
#else
@ -27,17 +32,24 @@
#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
#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
#if __STDC__
static void run_add_arg (char *s);
static void run_init_prog (void);
#else
static void run_add_arg ();
static void run_init_prog ();
#endif /* __STDC__ */
static void run_add_arg PROTO((char *s));
static void run_init_prog PROTO((void));
extern char *getlogin ();
extern char *strtok ();
@ -74,7 +86,7 @@ copy_file (from, to)
if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size)
error (1, errno, "cannot read file %s for copying", from);
if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size
#ifndef FSYNC_MISSING
#ifdef HAVE_FSYNC
|| fsync (fdout) == -1
#endif
)
@ -88,11 +100,15 @@ copy_file (from, to)
error (1, errno, "cannot close %s", to);
/* 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.modtime = sb.st_mtime;
(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
* link which points to a directory.
@ -202,25 +218,8 @@ make_directory (name)
{
struct stat buf;
if (stat (name, &buf) == 0)
{
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
if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode)))
error (0, 0, "%s already exists but is not a directory", name);
}
if (!noexec && mkdir (name, 0777) < 0)
error (1, errno, "cannot make directory %s", name);
}
@ -245,7 +244,7 @@ make_directories (name)
error (0, errno, "cannot make path to %s", name);
return;
}
if ((cp = rindex (name, '/')) == NULL)
if ((cp = strrchr (name, '/')) == NULL)
return;
*cp = '\0';
make_directories (name);
@ -260,14 +259,12 @@ make_directories (name)
*/
char *
xmalloc (bytes)
int bytes;
size_t bytes;
{
char *cp;
if (bytes <= 0)
error (1, 0, "bad malloc size %d", bytes);
if ((cp = malloc ((unsigned) bytes)) == NULL)
error (1, 0, "malloc failed");
if ((cp = malloc (bytes)) == NULL)
error (1, 0, "can not allocate %lu bytes", (unsigned long) bytes);
return (cp);
}
@ -279,17 +276,17 @@ xmalloc (bytes)
char *
xrealloc (ptr, bytes)
char *ptr;
int bytes;
size_t bytes;
{
char *cp;
if (!ptr)
return (xmalloc (bytes));
cp = malloc (bytes);
else
cp = realloc (ptr, bytes);
if (bytes <= 0)
error (1, 0, "bad realloc size %d", bytes);
if ((cp = realloc (ptr, (unsigned) bytes)) == NULL)
error (1, 0, "realloc failed");
if (cp == NULL)
error (1, 0, "can not reallocate %lu bytes", (unsigned long) bytes);
return (cp);
}
@ -320,7 +317,7 @@ xchmod (fname, writable)
int writable;
{
struct stat sb;
int mode, oumask;
mode_t mode, oumask;
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.
*
* 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.
*/
/* richfix: this *could* exploit mmap. */
int
xcmp (file1, file2)
char *file1;
@ -430,10 +430,10 @@ xcmp (file1, file2)
buf1 = xmalloc ((int) size);
buf2 = xmalloc ((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)
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 (buf2);
}
@ -512,10 +512,10 @@ getcaller ()
static char uidname[20];
struct passwd *pw;
char *name;
int uid;
uid_t uid;
uid = getuid ();
if (uid == 0)
if (uid == (uid_t) 0)
{
/* super-user; try getlogin() to distinguish */
if (((name = getenv("LOGNAME")) || (name = getenv("USER")) ||
@ -524,7 +524,7 @@ getcaller ()
}
if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
{
(void) sprintf (uidname, "uid%d", uid);
(void) sprintf (uidname, "uid%d", (unsigned long) uid);
return (uidname);
}
return (pw->pw_name);
@ -549,7 +549,7 @@ static int run_argc;
static int run_argc_allocated;
/* VARARGS */
#if !defined (VPRINTF_MISSING) && __STDC__
#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
void
run_setup (char *fmt,...)
#else
@ -560,7 +560,7 @@ run_setup (fmt, va_alist)
#endif
{
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
va_list args;
#endif
@ -581,7 +581,7 @@ run_setup (fmt, va_alist)
run_argc = 0;
/* process the varargs into run_prog */
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
VA_START (args, fmt);
(void) vsprintf (run_prog, fmt, args);
va_end (args);
@ -602,7 +602,7 @@ run_arg (s)
}
/* VARARGS */
#if !defined (VPRINTF_MISSING) && __STDC__
#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
void
run_args (char *fmt,...)
#else
@ -613,7 +613,7 @@ run_args (fmt, va_alist)
#endif
{
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
va_list args;
#endif
@ -621,7 +621,7 @@ run_args (fmt, va_alist)
run_init_prog ();
/* process the varargs into run_prog */
#ifndef VPRINTF_MISSING
#ifdef HAVE_VPRINTF
VA_START (args, fmt);
(void) vsprintf (run_prog, fmt, args);
va_end (args);
@ -668,7 +668,12 @@ run_exec (stin, stout, sterr, flags)
{
int shin, shout, sherr;
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 pid, w;
@ -682,7 +687,7 @@ run_exec (stin, stout, sterr, flags)
struct sigvec vec, ivec, qvec;
#else
SIGTYPE (*istat) (), (*qstat) ();
RETSIGTYPE (*istat) (), (*qstat) ();
#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 */
#ifdef VFORK_MISSING
pid = fork ();
#else
#ifdef HAVE_VFORK
pid = vfork ();
#else
pid = fork ();
#endif
if (pid == 0)
{
@ -761,6 +770,7 @@ run_exec (stin, stout, sterr, flags)
/* dup'ing is done. try to run it now */
(void) execvp (run_argv[0], run_argv);
error (0, errno, "cannot exec %s", run_argv[0]);
_exit (127);
}
else if (pid == -1)
@ -790,7 +800,7 @@ run_exec (stin, stout, sterr, flags)
#ifdef BSD_SIGNALS
if (flags & RUN_SIGIGNORE)
{
bzero ((char *) &vec, sizeof (vec));
memset ((char *) &vec, 0, sizeof (vec));
vec.sv_handler = SIG_IGN;
(void) sigvec (SIGINT, &vec, &ivec);
(void) sigvec (SIGQUIT, &vec, &qvec);
@ -816,19 +826,19 @@ run_exec (stin, stout, sterr, flags)
#endif
if (w == -1)
{
status = -1;
rc = -1;
rerrno = errno;
}
else if (WIFEXITED (status))
status = WEXITSTATUS (status);
rc = WEXITSTATUS (status);
else if (WIFSIGNALED (status))
{
if (WTERMSIG (status) == SIGPIPE)
error (1, 0, "broken pipe");
status = 2;
rc = 2;
}
else
status = 1;
rc = 1;
/* restore the signals */
#ifdef POSIX
@ -868,7 +878,7 @@ run_exec (stin, stout, sterr, flags)
out0:
if (rerrno)
errno = rerrno;
return (status);
return (rc);
}
void
@ -910,3 +920,130 @@ get_date (date, now)
}
#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
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/stat.h>
@ -52,16 +52,13 @@
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
#if defined(MKFIFO_MISSING)
#if !defined(HAVE_MKFIFO)
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
#endif
#ifdef POSIX
#if defined(POSIX) || defined(HAVE_UNISTD_H)
#include <unistd.h>
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX pathconf ("/", _PC_PATH_MAX)
#endif
#else
off_t lseek ();
#endif
@ -72,7 +69,7 @@ off_t lseek ();
#include <time.h>
#endif
#ifdef TIMEB_H_MISSING
#ifndef HAVE_SYS_TIMEB_H
struct timeb {
time_t time; /* Seconds since the epoch */
unsigned short millitm; /* Field not used */
@ -87,29 +84,66 @@ struct timeb {
#include <sys/timeb.h>
#endif
#if defined(FTIME_MISSING) && !defined(HAVE_TIMEZONE)
#if !defined(HAVE_FTIME) && !defined(HAVE_TIMEZONE)
#if !defined(timezone)
extern char *timezone();
extern long timezone;
#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>
#endif
#ifndef _POSIX_PATH_MAX
#define _POSIX_PATH_MAX 255
#endif
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX _POSIX_PATH_MAX
#endif
#endif
# ifdef MAXPATHLEN
# 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 */
#ifdef POSIX
#ifdef HAVE_UTIME_H
#include <utime.h>
#else
#ifndef ALTOS
@ -122,29 +156,33 @@ struct utimbuf
int utime ();
#endif
#if defined(USG) || defined(STDC_HEADERS)
#if STDC_HEADERS || HAVE_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>
#endif
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
#ifndef index
#define index strchr
#endif
#endif /* index */
#ifndef rindex
#define rindex strrchr
#endif
#ifndef bcopy
#define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif
#ifndef bzero
#define bzero(s, n) (void) memset ((s), 0, (n))
#endif
#endif /* rindex */
#ifndef bcmp
#define bcmp(s1, s2, n) memcmp((s1), (s2), (n))
#endif
#else
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
#endif /* bcmp */
#ifndef bzero
#define bzero(s, n) memset ((s), 0, (n))
#endif /* bzero */
#else /* not STDC_HJEADERS and not HAVE_STRING_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>
#ifdef STDC_HEADERS
@ -157,34 +195,24 @@ char *calloc ();
extern int errno;
#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)
#include <fcntl.h>
char *getcwd ();
#else
#include <sys/file.h>
char *getwd ();
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
#include <sys/file.h>
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#ifndef F_OK
#define F_OK 0
#define X_OK 1
@ -192,23 +220,23 @@ char *getwd ();
#define R_OK 4
#endif
#ifdef DIRENT
/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
#if defined(DIRENT) || defined(_POSIX_VERSION)
#include <dirent.h>
#ifdef direct
#undef direct
#endif
#define direct dirent
#else
#ifdef SYSNDIR
#define NLENGTH(dirent) (strlen((dirent)->d_name))
#else /* not (DIRENT or _POSIX_VERSION) */
#define dirent direct
#define NLENGTH(dirent) ((dirent)->d_namlen)
#ifdef HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#else
#ifdef NDIR
#include <ndir.h>
#else /* must be BSD */
#endif
#ifdef HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#ifdef HAVE_NDIR_H
#include <ndir.h>
#endif
#endif
#endif /* not (DIRENT or _POSIX_VERSION) */
/* Convert B 512-byte blocks to kilobytes if K is nonzero,
otherwise return it unchanged. */
@ -218,6 +246,17 @@ char *getwd ();
#define lstat stat
#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
#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
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/wait.h>
#else

View File

@ -15,6 +15,10 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
/* 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"
.SH "NAME"

View File

@ -3,7 +3,7 @@
* Copyright (c) 1989-1992, Brian Berliner
*
* 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
*
@ -13,11 +13,9 @@
#include "cvs.h"
#undef PATH_MAX
#define PATH_MAX 1024 /* max number of bytes in pathname */
#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
#ifndef DBLKSIZ
@ -30,30 +28,16 @@ char *Rcsbin = RCSBIN_DFLT;
int noexec = 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 (char *file, char *temp);
static void make_tempfile (char *temp);
static void mkmodules_usage (void);
static void rename_rcsfile (char *temp, char *real);
static int checkout_file PROTO((char *file, char *temp));
static void make_tempfile PROTO((char *temp));
static void mkmodules_usage PROTO((void));
static void rename_rcsfile PROTO((char *temp, char *real));
#ifndef MY_NDBM
static void rename_dbmfile (char *temp);
static void write_dbmfile (char *temp);
static void rename_dbmfile PROTO((char *temp));
static void write_dbmfile PROTO((char *temp));
#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
main (argc, argv)
@ -62,15 +46,34 @@ main (argc, argv)
{
extern char *getenv ();
char temp[PATH_MAX];
char *cp;
char *cp, *last, *fname;
#ifdef MY_NDBM
DBM *db;
#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
*/
if ((program_name = rindex (argv[0], '/')) == NULL)
if ((program_name = strrchr (argv[0], '/')) == NULL)
program_name = argv[0];
else
program_name++;
@ -135,57 +138,63 @@ main (argc, argv)
(void) unlink_file (temp);
/*
* Now, check out the "loginfo" file, so that it is always up-to-date in
* the CVSROOT directory.
*/
/* Checkout the files that need it in CVSROOT dir */
for (fileptr = filelist; fileptr && fileptr->filename; fileptr++) {
make_tempfile (temp);
if (checkout_file (CVSROOTADM_LOGINFO, temp) == 0)
rename_rcsfile (temp, CVSROOTADM_LOGINFO);
else
error (0, 0,
"no logging of 'cvs commit' messages is done without a %s file",
CVSROOTADM_LOGINFO);
if (checkout_file (fileptr->filename, temp) == 0)
rename_rcsfile (temp, fileptr->filename);
#if 0
/*
* If there was some problem other than the file not existing,
* checkout_file already printed a real error message. If the
* file does not exist, it is harmless--it probably just means
* that the repository was created with an old version of CVS
* 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 */
fp = fopen (CVSROOTADM_CHECKOUTLIST, "r");
if (fp)
{
/*
* Now, check out the "rcsinfo" file, so that it is always up-to-date in
* the CVSROOT directory.
* File format:
* [<whitespace>]<filename><whitespace><error message><end-of-line>
*/
make_tempfile (temp);
if (checkout_file (CVSROOTADM_RCSINFO, temp) == 0)
rename_rcsfile (temp, CVSROOTADM_RCSINFO);
else
error (0, 0,
"a %s file can be used to configure 'cvs commit' templates",
CVSROOTADM_RCSINFO);
(void) unlink_file (temp);
for (; fgets (line, sizeof (line), fp) != NULL;)
{
if ((last = strrchr (line, '\n')) != NULL)
*last = '\0'; /* strip the newline */
/*
* Now, check out the "editinfo" file, so that it is always up-to-date in
* the CVSROOT directory.
*/
make_tempfile (temp);
if (checkout_file (CVSROOTADM_EDITINFO, temp) == 0)
rename_rcsfile (temp, CVSROOTADM_EDITINFO);
else
error (0, 0,
"a %s file can be used to validate log messages",
CVSROOTADM_EDITINFO);
(void) unlink_file (temp);
/* Skip leading white space. */
for (fname = line; *fname && isspace(*fname); fname++)
;
/* Find end of filename. */
for (cp = fname; *cp && !isspace(*cp); cp++)
;
*cp = '\0';
/*
* 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);
if (checkout_file (fname, temp) == 0)
{
rename_rcsfile (temp, fname);
}
else
error (0, 0,
"a %s file can be used to configure 'cvs commit' checking",
CVSROOTADM_COMMITINFO);
(void) unlink_file (temp);
{
for (cp++; cp < last && *last && isspace(*last); cp++)
;
if (cp < last && *cp)
error (0, 0, cp, fname);
}
}
(void) fclose (fp);
}
return (0);
}
@ -251,7 +260,7 @@ write_dbmfile (temp)
error (1, errno, "cannot open dbm file %s for creation", temp);
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 */
/*
@ -370,8 +379,15 @@ rename_rcsfile (temp, real)
char *real;
{
char bak[50];
struct stat statbuf;
char rcs[PATH_MAX];
if (chmod (temp, 0444) < 0) /* chmod 444 "temp" */
/* 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 | (statbuf.st_mode & 0111)) < 0)
error (0, errno, "warning: cannot chmod %s", temp);
(void) sprintf (bak, "%s%s", BAKPREFIX, real);
(void) unlink_file (bak); /* rm .#loginfo */