Merge changes from 1.10.7 -> 1.11 into mainline. Note that the old
anoncvs no-password hack is gone and is replaced by the official version.
This commit is contained in:
parent
e0aa09eb34
commit
a152a7ef82
@ -54,7 +54,6 @@ Current local changes:
|
||||
- CVSREADONLYFS environment variable and global option -R to enable
|
||||
no-locking readonly mode (eg: cvs repo is a cdrom or mirror)
|
||||
- the verify message script can edit the submitted log message.
|
||||
- if pserver username is "anoncvs", implicitly use a password of "anoncvs".
|
||||
- CVSROOT/options file
|
||||
- Variable keyword expansion controls including custom keywords.
|
||||
- $ CVSHeader$ keyword - like Header, but with $CVSROOT stripped off.
|
||||
|
@ -7,9 +7,10 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# Usage: log.pl [[-m user] ...] [-s] -f logfile 'dirname file ...'
|
||||
# Usage: log.pl [-u user] [[-m mailto] ...] [-s] -f logfile 'dirname file ...'
|
||||
#
|
||||
# -m user - for each user to receive cvs log reports
|
||||
# -u user - $USER passed from loginfo
|
||||
# -m mailto - for each user to receive cvs log reports
|
||||
# (multiple -m's permitted)
|
||||
# -s - to prevent "cvs status -v" messages
|
||||
# -f logfile - for the logfile to append to (mandatory,
|
||||
@ -67,6 +68,8 @@ while (@ARGV) {
|
||||
|
||||
if ($arg eq '-m') {
|
||||
$users = "$users " . shift @ARGV;
|
||||
} elsif ($arg eq '-u') {
|
||||
$login = shift @ARGV;
|
||||
} elsif ($arg eq '-f') {
|
||||
($logfile) && die "Too many '-f' args";
|
||||
$logfile = shift @ARGV;
|
||||
@ -96,7 +99,9 @@ $year += 1900;
|
||||
|
||||
# get a login name for the guy doing the commit....
|
||||
#
|
||||
$login = getlogin || (getpwuid($<))[0] || "nobody";
|
||||
if ($login eq '') {
|
||||
$login = getlogin || (getpwuid($<))[0] || "nobody";
|
||||
}
|
||||
|
||||
# open log file for appending
|
||||
#
|
||||
|
@ -178,7 +178,12 @@ foreach sfile (SCCS/s.*)
|
||||
if ($status != 0) goto ERROR
|
||||
|
||||
# get file into current dir and get stats
|
||||
set date = `sccs prs -r$rev $file | grep "^D " | awk '{y=$3; if($3 < 100) {y+=1900};printf("%s %s", y, $4);exit;}'`
|
||||
set year = `echo $date | cut -c3-4`
|
||||
if ($year < 70) then
|
||||
# Y2K Bug, change century to 20
|
||||
set date = `echo $date | sed -e s/19/20/`
|
||||
endif
|
||||
set date = `sccs prs -r$rev $file | grep "^D " | awk '{printf("19%s %s", $3, $4); exit}'`
|
||||
set author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'`
|
||||
echo ""
|
||||
echo "==> file $file, rev=$rev, date=$date, author=$author"
|
||||
|
@ -44,6 +44,8 @@ void printf_output PARAMS((char const *, ...))
|
||||
;
|
||||
void flush_output PARAMS((void));
|
||||
|
||||
char * cvs_temp_name PARAMS((void));
|
||||
|
||||
/*
|
||||
* Internal data structures and macros for the diff3 program; includes
|
||||
* data structures for both diff3 diffs and normal diffs.
|
||||
@ -478,8 +480,6 @@ diff3_run (argc, argv, out, callbacks_arg)
|
||||
|
||||
free(content0);
|
||||
free(content1);
|
||||
free_diff_blocks(thread0);
|
||||
free_diff_blocks(thread1);
|
||||
free_diff3_blocks(diff3);
|
||||
|
||||
if (! callbacks || ! callbacks->write_output)
|
||||
@ -679,7 +679,7 @@ make_3way_diff (thread0, thread1)
|
||||
|
||||
struct diff3_block const *last_diff3;
|
||||
|
||||
static struct diff3_block const zero_diff3;
|
||||
static struct diff3_block const zero_diff3 = { 0 };
|
||||
|
||||
/* Initialization */
|
||||
result = 0;
|
||||
@ -768,6 +768,8 @@ make_3way_diff (thread0, thread1)
|
||||
tmpblock = using_to_diff3_block (using, last_using,
|
||||
base_water_thread, high_water_thread,
|
||||
last_diff3);
|
||||
free_diff_blocks(using[0]);
|
||||
free_diff_blocks(using[1]);
|
||||
|
||||
if (!tmpblock)
|
||||
diff3_fatal ("internal error: screwup in format of diff blocks");
|
||||
@ -1277,7 +1279,7 @@ read_diff (filea, fileb, output_placement)
|
||||
*ap++ = fileb;
|
||||
*ap = 0;
|
||||
|
||||
diffout = (char *)cvs_temp_name();
|
||||
diffout = cvs_temp_name ();
|
||||
|
||||
outfile_hold = outfile;
|
||||
callbacks_hold = callbacks;
|
||||
|
@ -193,8 +193,10 @@ Use
|
||||
.I editor
|
||||
to enter revision log information.
|
||||
Overrides the setting of the
|
||||
.SM CVSEDITOR
|
||||
and the
|
||||
.SM CVSEDITOR\c
|
||||
,
|
||||
.SM VISUAL\c
|
||||
, and
|
||||
.SM EDITOR
|
||||
environment variables.
|
||||
.TP
|
||||
@ -397,6 +399,11 @@ file; see
|
||||
Incorporate a set of updates from off-site into the source repository,
|
||||
as a ``vendor branch''. (Changes repository.)
|
||||
.TP
|
||||
.B init
|
||||
Initialize a repository by adding the CVSROOT subdirectory and some default
|
||||
control files. You must use this command or initialize the repository in
|
||||
some other way before you can use it.
|
||||
.TP
|
||||
.B log
|
||||
Display
|
||||
log information.
|
||||
@ -512,13 +519,6 @@ is available with these commands:
|
||||
.BR checkout ", " export ", "
|
||||
.BR rdiff ", " rtag ", and " update .
|
||||
.TP
|
||||
.B \-H
|
||||
Help; describe the options available for this command. This is the
|
||||
only option supported for
|
||||
.I all
|
||||
.B cvs
|
||||
commands.
|
||||
.TP
|
||||
\fB\-k\fP \fIkflag\fP
|
||||
Alter the default
|
||||
processing of keywords.
|
||||
@ -1723,7 +1723,7 @@ executes recursively through subdirectories; you can prevent this by
|
||||
using the standard \fB\-l\fP option, or specify the recursion
|
||||
explicitly by using \fB\-R\fP.
|
||||
.TP
|
||||
\fBupdate\fP [\fB\-Adf\|lPpQqR\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP|\fB\-D\fP \fIdate\fP] \fIfiles\|.\|.\|.\fP
|
||||
\fBupdate\fP [\fB\-ACdf\|lPpQqR\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP|\fB\-D\fP \fIdate\fP] \fIfiles\|.\|.\|.\fP
|
||||
.I Requires:
|
||||
repository, working directory.
|
||||
.br
|
||||
@ -1880,6 +1880,12 @@ Use
|
||||
.` "\-I !"
|
||||
to avoid ignoring any files at all.
|
||||
.SP
|
||||
Use the
|
||||
.` "\-C"
|
||||
option to overwrite locally modified files with clean copies from
|
||||
the repository (the modified file is saved in
|
||||
`\fB.#\fP\fIfile\fP\fB.\fP\fIrevision\fP', however).
|
||||
.SP
|
||||
The standard \fBcvs\fP command options \fB\-f\fP, \fB\-k\fP,
|
||||
\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, and \fB\-r\fP
|
||||
are also available with \fBupdate\fP.
|
||||
@ -2079,12 +2085,13 @@ and
|
||||
Specifies the program to use for recording log messages during
|
||||
.BR commit .
|
||||
If not set, the
|
||||
.SM VISUAL
|
||||
and
|
||||
.SM EDITOR
|
||||
environment variable is used instead.
|
||||
If
|
||||
.SM EDITOR
|
||||
is not set either, the default is
|
||||
.BR /usr/ucb/vi .
|
||||
environment variables are tried (in that order).
|
||||
If neither is set, a system-dependent default editor (e.g.,
|
||||
.BR vi )
|
||||
is used.
|
||||
.TP
|
||||
.SM CVS_IGNORE_REMOTE_ROOT
|
||||
If this variable is set then
|
||||
|
@ -17,8 +17,9 @@
|
||||
.\" General Public License for more details.
|
||||
.\"
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.\" $FreeBSD$
|
||||
.nh
|
||||
.TH CVSBUG 1 xVERSIONx "February 1993"
|
||||
.TH CVSBUG 8 xVERSIONx "February 1993"
|
||||
.SH NAME
|
||||
cvsbug \- send problem report (PR) about CVS to a central support site
|
||||
.SH SYNOPSIS
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* JT thinks BeOS is worth the trouble. */
|
||||
|
||||
/* CVS client-related stuff.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -64,7 +66,6 @@ extern char *strerror ();
|
||||
#if HAVE_KERBEROS
|
||||
#define CVS_PORT 1999
|
||||
|
||||
#if HAVE_KERBEROS
|
||||
#include <krb.h>
|
||||
|
||||
extern char *krb_realmofhost ();
|
||||
@ -78,8 +79,6 @@ static Key_schedule sched;
|
||||
|
||||
#endif /* HAVE_KERBEROS */
|
||||
|
||||
#endif /* HAVE_KERBEROS */
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
|
||||
#ifdef HAVE_GSSAPI_H
|
||||
@ -1119,7 +1118,7 @@ call_in_directory (pathname, func, data)
|
||||
strcpy (r, "/.");
|
||||
|
||||
Create_Admin (".", ".", repo, (char *) NULL,
|
||||
(char *) NULL, 0, 1);
|
||||
(char *) NULL, 0, 1, 1);
|
||||
|
||||
free (repo);
|
||||
}
|
||||
@ -1256,7 +1255,7 @@ warning: server is not creating directories one at a time");
|
||||
strcpy (r, reposdirname);
|
||||
|
||||
Create_Admin (dir, dir, repo,
|
||||
(char *)NULL, (char *)NULL, 0, 0);
|
||||
(char *)NULL, (char *)NULL, 0, 0, 1);
|
||||
free (repo);
|
||||
|
||||
b = strrchr (dir, '/');
|
||||
@ -1764,6 +1763,7 @@ update_entries (data_arg, ent_list, short_pathname, filename)
|
||||
}
|
||||
|
||||
free (mode_string);
|
||||
free (scratch_entries);
|
||||
free (entries_line);
|
||||
|
||||
/* The Mode, Mod-time, and Checksum responses should not carry
|
||||
@ -1851,7 +1851,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
|
||||
|
||||
if (use_gzip)
|
||||
{
|
||||
if (gunzip_and_write (fd, short_pathname, buf, size))
|
||||
if (gunzip_and_write (fd, short_pathname,
|
||||
(unsigned char *) buf, size))
|
||||
error (1, 0, "aborting due to compression error");
|
||||
}
|
||||
else if (write (fd, buf, size) != size)
|
||||
@ -2029,6 +2030,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
|
||||
|
||||
free (mode_string);
|
||||
free (buf);
|
||||
free (scratch_entries);
|
||||
free (entries_line);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2127,8 +2130,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
|
||||
if (file_timestamp)
|
||||
free (file_timestamp);
|
||||
|
||||
free (scratch_entries);
|
||||
}
|
||||
free (scratch_entries);
|
||||
free (entries_line);
|
||||
}
|
||||
|
||||
@ -2494,7 +2497,11 @@ handle_set_checkin_prog (args, len)
|
||||
{
|
||||
char *prog;
|
||||
struct save_prog *p;
|
||||
|
||||
read_line (&prog);
|
||||
if (strcmp (command_name, "export") == 0)
|
||||
return;
|
||||
|
||||
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
|
||||
p->next = checkin_progs;
|
||||
p->dir = xstrdup (args);
|
||||
@ -2509,7 +2516,11 @@ handle_set_update_prog (args, len)
|
||||
{
|
||||
char *prog;
|
||||
struct save_prog *p;
|
||||
|
||||
read_line (&prog);
|
||||
if (strcmp (command_name, "export") == 0)
|
||||
return;
|
||||
|
||||
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
|
||||
p->next = update_progs;
|
||||
p->dir = xstrdup (args);
|
||||
@ -2687,7 +2698,7 @@ send_repository (dir, repos, update_dir)
|
||||
{
|
||||
Node *n;
|
||||
n = getnode ();
|
||||
n->type = UNKNOWN;
|
||||
n->type = NT_UNKNOWN;
|
||||
n->key = xstrdup (update_dir);
|
||||
n->data = NULL;
|
||||
|
||||
@ -3598,19 +3609,15 @@ get_responses_and_close ()
|
||||
&& waitpid (rsh_pid, (int *) 0, 0) == -1)
|
||||
error (1, errno, "waiting for process %d", rsh_pid);
|
||||
|
||||
buf_free (to_server);
|
||||
buf_free (from_server);
|
||||
server_started = 0;
|
||||
|
||||
/* see if we need to sleep before returning */
|
||||
/* see if we need to sleep before returning to avoid time-stamp races */
|
||||
if (last_register_time)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
(void) time (&now);
|
||||
if (now != last_register_time) break;
|
||||
sleep (1); /* to avoid time-stamp races */
|
||||
}
|
||||
while (time ((time_t *) NULL) == last_register_time)
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
return errs;
|
||||
@ -3778,6 +3785,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
|
||||
int port_number;
|
||||
struct sockaddr_in client_sai;
|
||||
struct hostent *hostinfo;
|
||||
char no_passwd = 0; /* gets set if no password found */
|
||||
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
@ -3822,6 +3830,14 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
|
||||
|
||||
/* Get the password, probably from ~/.cvspass. */
|
||||
password = get_cvs_password ();
|
||||
|
||||
/* Send the empty string by default. This is so anonymous CVS
|
||||
access doesn't require client to have done "cvs login". */
|
||||
if (password == NULL)
|
||||
{
|
||||
no_passwd = 1;
|
||||
password = scramble ("");
|
||||
}
|
||||
|
||||
/* Announce that we're starting the authorization protocol. */
|
||||
if (send (sock, begin, strlen (begin), 0) < 0)
|
||||
@ -3845,8 +3861,8 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
|
||||
if (send (sock, end, strlen (end), 0) < 0)
|
||||
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
|
||||
|
||||
/* Paranoia. */
|
||||
memset (password, 0, strlen (password));
|
||||
/* Paranoia. */
|
||||
memset (password, 0, strlen (password));
|
||||
}
|
||||
|
||||
{
|
||||
@ -3939,20 +3955,28 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
|
||||
return;
|
||||
|
||||
rejected:
|
||||
error (0, 0,
|
||||
"authorization failed: server %s rejected access to %s for user %s",
|
||||
CVSroot_hostname, CVSroot_directory, CVSroot_username);
|
||||
|
||||
/* Output a special error message if authentication was attempted
|
||||
with no password -- the user should be made aware that they may
|
||||
have missed a step. */
|
||||
if (no_passwd)
|
||||
{
|
||||
error (0, 0,
|
||||
"used empty password; try \"cvs login\" with a real password");
|
||||
}
|
||||
|
||||
if (shutdown (sock, 2) < 0)
|
||||
{
|
||||
error (0, 0,
|
||||
"authorization failed: server %s rejected access",
|
||||
CVSroot_hostname);
|
||||
error (1, 0,
|
||||
error (0, 0,
|
||||
"shutdown() failed (server %s): %s",
|
||||
CVSroot_hostname,
|
||||
SOCK_STRERROR (SOCK_ERRNO));
|
||||
}
|
||||
|
||||
error (1, 0,
|
||||
"authorization failed: server %s rejected access",
|
||||
CVSroot_hostname);
|
||||
error_exit();
|
||||
}
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
|
||||
@ -4115,9 +4139,16 @@ connect_to_gserver (sock, hostinfo)
|
||||
if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
|
||||
{
|
||||
OM_uint32 message_context;
|
||||
OM_uint32 new_stat_min;
|
||||
|
||||
message_context = 0;
|
||||
gss_display_status (&stat_min, stat_maj, GSS_C_GSS_CODE,
|
||||
gss_display_status (&new_stat_min, stat_maj, GSS_C_GSS_CODE,
|
||||
GSS_C_NULL_OID, &message_context, &tok_out);
|
||||
error (0, 0, "GSSAPI authentication failed: %s",
|
||||
(char *) tok_out.value);
|
||||
|
||||
message_context = 0;
|
||||
gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
|
||||
GSS_C_NULL_OID, &message_context, &tok_out);
|
||||
error (1, 0, "GSSAPI authentication failed: %s",
|
||||
(char *) tok_out.value);
|
||||
@ -4141,7 +4172,29 @@ connect_to_gserver (sock, hostinfo)
|
||||
|
||||
recv_bytes (sock, cbuf, 2);
|
||||
need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
|
||||
assert (need <= sizeof buf);
|
||||
|
||||
if (need > sizeof buf)
|
||||
{
|
||||
int got;
|
||||
|
||||
/* This usually means that the server sent us an error
|
||||
message. Read it byte by byte and print it out.
|
||||
FIXME: This is a terrible error handling strategy.
|
||||
However, even if we fix the server, we will still
|
||||
want to do this to work with older servers. */
|
||||
buf[0] = cbuf[0];
|
||||
buf[1] = cbuf[1];
|
||||
got = recv (sock, buf + 2, sizeof buf - 2, 0);
|
||||
if (got < 0)
|
||||
error (1, 0, "recv() from server %s: %s",
|
||||
CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
|
||||
buf[got + 2] = '\0';
|
||||
if (buf[got + 1] == '\n')
|
||||
buf[got + 1] = '\0';
|
||||
error (1, 0, "error from server %s: %s", CVSroot_hostname,
|
||||
buf);
|
||||
}
|
||||
|
||||
recv_bytes (sock, buf, need);
|
||||
tok_in.length = need;
|
||||
}
|
||||
@ -4175,7 +4228,7 @@ send_variable_proc (node, closure)
|
||||
void
|
||||
start_server ()
|
||||
{
|
||||
int tofd, fromfd;
|
||||
int tofd, fromfd, rootless;
|
||||
char *log = getenv ("CVS_CLIENT_LOG");
|
||||
|
||||
|
||||
@ -4354,7 +4407,8 @@ the :server: access method is not supported by this port of CVS");
|
||||
stored_mode = NULL;
|
||||
}
|
||||
|
||||
if (strcmp (command_name, "init") != 0)
|
||||
rootless = (strcmp (command_name, "init") == 0);
|
||||
if (!rootless)
|
||||
{
|
||||
send_to_server ("Root ", 0);
|
||||
send_to_server (CVSroot_directory, 0);
|
||||
@ -4478,7 +4532,7 @@ the :server: access method is not supported by this port of CVS");
|
||||
}
|
||||
}
|
||||
|
||||
if (cvsencrypt)
|
||||
if (cvsencrypt && !rootless)
|
||||
{
|
||||
#ifdef ENCRYPTION
|
||||
/* Turn on encryption before turning on compression. We do
|
||||
@ -4525,7 +4579,7 @@ the :server: access method is not supported by this port of CVS");
|
||||
#endif /* ! ENCRYPTION */
|
||||
}
|
||||
|
||||
if (gzip_level)
|
||||
if (gzip_level && !rootless)
|
||||
{
|
||||
if (supported_request ("Gzip-stream"))
|
||||
{
|
||||
@ -4567,7 +4621,7 @@ the :server: access method is not supported by this port of CVS");
|
||||
}
|
||||
}
|
||||
|
||||
if (cvsauthenticate && ! cvsencrypt)
|
||||
if (cvsauthenticate && ! cvsencrypt && !rootless)
|
||||
{
|
||||
/* Turn on authentication after turning on compression, so
|
||||
that we can compress the authentication information. We
|
||||
@ -4598,7 +4652,7 @@ the :server: access method is not supported by this port of CVS");
|
||||
}
|
||||
|
||||
#ifdef FILENAMES_CASE_INSENSITIVE
|
||||
if (supported_request ("Case"))
|
||||
if (supported_request ("Case") && !rootless)
|
||||
send_to_server ("Case\012", 0);
|
||||
#endif
|
||||
|
||||
@ -4968,6 +5022,7 @@ struct send_data
|
||||
int build_dirs;
|
||||
int force;
|
||||
int no_contents;
|
||||
int backup_modified;
|
||||
};
|
||||
|
||||
static int send_fileproc PROTO ((void *callerdat, struct file_info *finfo));
|
||||
@ -5089,6 +5144,18 @@ warning: ignoring -k options due to server limitations");
|
||||
}
|
||||
else
|
||||
send_modified (filename, finfo->fullname, vers);
|
||||
|
||||
if (args->backup_modified)
|
||||
{
|
||||
char *bakname;
|
||||
bakname = backup_file (filename, vers->vn_user);
|
||||
/* This behavior is sufficiently unexpected to
|
||||
justify overinformativeness, I think. */
|
||||
if (! really_quiet)
|
||||
printf ("(Locally modified %s moved to %s)\n",
|
||||
filename, bakname);
|
||||
free (bakname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5197,9 +5264,6 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
||||
dir_exists = isdir (cvsadm_name);
|
||||
free (cvsadm_name);
|
||||
|
||||
/* initialize the ignore list for this directory */
|
||||
ignlist = getlist ();
|
||||
|
||||
/*
|
||||
* If there is an empty directory (e.g. we are doing `cvs add' on a
|
||||
* newly-created directory), the server still needs to know about it.
|
||||
@ -5215,6 +5279,9 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
||||
char *repos = Name_Repository (dir, update_dir);
|
||||
send_a_repository (dir, repos, update_dir);
|
||||
free (repos);
|
||||
|
||||
/* initialize the ignore list for this directory */
|
||||
ignlist = getlist ();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5239,6 +5306,29 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
||||
return (dir_exists ? R_PROCESS : R_SKIP_ALL);
|
||||
}
|
||||
|
||||
static int send_dirleave_proc PROTO ((void *, char *, int, char *, List *));
|
||||
|
||||
/*
|
||||
* send_dirleave_proc () is called back by the recursion code upon leaving
|
||||
* a directory. All it does is delete the ignore list if it hasn't already
|
||||
* been done (by send_filesdone_proc).
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
send_dirleave_proc (callerdat, dir, err, update_dir, entries)
|
||||
void *callerdat;
|
||||
char *dir;
|
||||
int err;
|
||||
char *update_dir;
|
||||
List *entries;
|
||||
{
|
||||
|
||||
/* Delete the ignore list if it hasn't already been done. */
|
||||
if (ignlist)
|
||||
dellist (&ignlist);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send each option in a string to the server, one by one.
|
||||
* This assumes that the options are separated by spaces, for example
|
||||
@ -5430,9 +5520,10 @@ send_files (argc, argv, local, aflag, flags)
|
||||
args.build_dirs = flags & SEND_BUILD_DIRS;
|
||||
args.force = flags & SEND_FORCE;
|
||||
args.no_contents = flags & SEND_NO_CONTENTS;
|
||||
args.backup_modified = flags & BACKUP_MODIFIED_FILES;
|
||||
err = start_recursion
|
||||
(send_fileproc, send_filesdoneproc,
|
||||
send_dirent_proc, (DIRLEAVEPROC)NULL, (void *) &args,
|
||||
send_dirent_proc, send_dirleave_proc, (void *) &args,
|
||||
argc, argv, local, W_LOCAL, aflag, 0, (char *)NULL, 0);
|
||||
if (err)
|
||||
error_exit ();
|
||||
|
@ -264,6 +264,7 @@ find_fileproc (callerdat, finfo)
|
||||
else
|
||||
error (0, 0, "use `%s add' to create an entry for %s",
|
||||
program_name, finfo->fullname);
|
||||
freevers_ts (&vers);
|
||||
return 1;
|
||||
}
|
||||
else if (vers->ts_user != NULL
|
||||
@ -285,6 +286,7 @@ find_fileproc (callerdat, finfo)
|
||||
cases. FIXME: we probably should be printing a message and
|
||||
returning 1 for many of those cases (but I'm not sure
|
||||
exactly which ones). */
|
||||
freevers_ts (&vers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -422,28 +424,12 @@ commit (argc, argv)
|
||||
/* some checks related to the "-F logfile" option */
|
||||
if (logfile)
|
||||
{
|
||||
int n, logfd;
|
||||
struct stat statbuf;
|
||||
size_t size = 0, len;
|
||||
|
||||
if (saved_message)
|
||||
error (1, 0, "cannot specify both a message and a log file");
|
||||
|
||||
/* FIXME: Why is this binary? Needs more investigation. */
|
||||
if ((logfd = CVS_OPEN (logfile, O_RDONLY | OPEN_BINARY)) < 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);
|
||||
|
||||
saved_message = xmalloc (statbuf.st_size + 1);
|
||||
|
||||
/* FIXME: Should keep reading until EOF, rather than assuming the
|
||||
first read gets the whole thing. */
|
||||
if ((n = read (logfd, saved_message, statbuf.st_size + 1)) < 0)
|
||||
error (1, errno, "cannot read log message from %s", logfile);
|
||||
|
||||
(void) close (logfd);
|
||||
saved_message[n] = '\0';
|
||||
get_file (logfile, logfile, "r", &saved_message, &size, &len);
|
||||
}
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
@ -474,11 +460,14 @@ commit (argc, argv)
|
||||
error (1, 0, "correct above errors first!");
|
||||
|
||||
if (find_args.argc == 0)
|
||||
{
|
||||
/* Nothing to commit. Exit now without contacting the
|
||||
server (note that this means that we won't print "?
|
||||
foo" for files which merit it, because we don't know
|
||||
what is in the CVSROOT/cvsignore file). */
|
||||
dellist (&find_args.ulist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now we keep track of which files we actually are going to
|
||||
operate on, and only work with those files in the future.
|
||||
@ -584,6 +573,8 @@ commit (argc, argv)
|
||||
previous versions of client/server CVS, but it probably is a Good
|
||||
Thing, or at least Not Such A Bad Thing. */
|
||||
send_file_names (find_args.argc, find_args.argv, 0);
|
||||
free (find_args.argv);
|
||||
dellist (&find_args.ulist);
|
||||
|
||||
send_to_server ("ci\012", 0);
|
||||
err = get_responses_and_close ();
|
||||
@ -673,16 +664,11 @@ commit (argc, argv)
|
||||
Lock_Cleanup ();
|
||||
dellist (&mulist);
|
||||
|
||||
/* see if we need to sleep before returning to avoid time-stamp races */
|
||||
if (last_register_time)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
(void) time (&now);
|
||||
if (now != last_register_time) break;
|
||||
sleep (1); /* to avoid time-stamp races */
|
||||
}
|
||||
while (time ((time_t *) NULL) == last_register_time)
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
return (err);
|
||||
@ -795,6 +781,12 @@ check_fileproc (callerdat, finfo)
|
||||
|
||||
size_t cvsroot_len = strlen (CVSroot_directory);
|
||||
|
||||
if (!finfo->repository)
|
||||
{
|
||||
error (0, 0, "nothing known about `%s'", finfo->fullname);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (strncmp (finfo->repository, CVSroot_directory, cvsroot_len) == 0
|
||||
&& ISDIRSEP (finfo->repository[cvsroot_len])
|
||||
&& strncmp (finfo->repository + cvsroot_len + 1,
|
||||
@ -1291,6 +1283,8 @@ commit_fileproc (callerdat, finfo)
|
||||
{
|
||||
if (finfo->rcs == NULL)
|
||||
error (1, 0, "internal error: no parsed RCS file");
|
||||
if (ci->rev)
|
||||
free (ci->rev);
|
||||
ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
|
||||
err = Checkin ('A', finfo, finfo->rcs->path, ci->rev,
|
||||
ci->tag, ci->options, saved_message);
|
||||
@ -1401,6 +1395,8 @@ commit_fileproc (callerdat, finfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SIG_inCrSect ())
|
||||
SIG_endCrSect ();
|
||||
|
||||
return (err);
|
||||
}
|
||||
@ -1501,6 +1497,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
|
||||
cvs_output (": Executing '", 0);
|
||||
run_print (stdout);
|
||||
cvs_output ("'\n", 0);
|
||||
cvs_flushout ();
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
free (repos);
|
||||
}
|
||||
@ -1583,8 +1580,10 @@ commit_dirleaveproc (callerdat, dir, err, update_dir, entries)
|
||||
this being a confusing feature! */
|
||||
if (err == 0 && write_dirtag != NULL)
|
||||
{
|
||||
char *repos = Name_Repository (dir, update_dir);
|
||||
WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
|
||||
update_dir, Name_Repository (dir, update_dir));
|
||||
update_dir, repos);
|
||||
free (repos);
|
||||
}
|
||||
|
||||
return (err);
|
||||
@ -1752,6 +1751,9 @@ remove_file (finfo, tag, message)
|
||||
"failed to commit dead revision for `%s'", finfo->fullname);
|
||||
return (1);
|
||||
}
|
||||
/* At this point, the file has been committed as removed. We should
|
||||
probably tell the history file about it */
|
||||
history_write ('R', NULL, finfo->rcs->head, finfo->file, finfo->repository);
|
||||
|
||||
if (rev != NULL)
|
||||
free (rev);
|
||||
@ -1963,6 +1965,11 @@ checkaddfile (file, repository, tag, options, rcsnode)
|
||||
|
||||
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
|
||||
|
||||
/* Begin a critical section around the code that spans the
|
||||
first commit on the trunk of a file that's already been
|
||||
committed on a branch. */
|
||||
SIG_beginCrSect ();
|
||||
|
||||
if (RCS_setattic (rcsfile, 0))
|
||||
{
|
||||
retval = 1;
|
||||
@ -2045,74 +2052,76 @@ checkaddfile (file, repository, tag, options, rcsnode)
|
||||
newfile = 1;
|
||||
if (desc != NULL)
|
||||
free (desc);
|
||||
}
|
||||
|
||||
/* when adding a file for the first time, and using a tag, we need
|
||||
to create a dead revision on the trunk. */
|
||||
if (adding_on_branch && newfile)
|
||||
{
|
||||
char *tmp;
|
||||
FILE *fp;
|
||||
|
||||
/* move the new file out of the way. */
|
||||
fname = xmalloc (strlen (file) + sizeof (CVSADM)
|
||||
+ sizeof (CVSPREFIX) + 10);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
|
||||
rename_file (file, fname);
|
||||
|
||||
/* Create empty FILE. Can't use copy_file with a DEVNULL
|
||||
argument -- copy_file now ignores device files. */
|
||||
fp = fopen (file, "w");
|
||||
if (fp == NULL)
|
||||
error (1, errno, "cannot open %s for writing", file);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "cannot close %s", file);
|
||||
|
||||
tmp = xmalloc (strlen (file) + strlen (tag) + 80);
|
||||
/* commit a dead revision. */
|
||||
(void) sprintf (tmp, "file %s was initially added on branch %s.",
|
||||
file, tag);
|
||||
retcode = RCS_checkin (rcsfile, NULL, tmp, NULL,
|
||||
RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
|
||||
free (tmp);
|
||||
if (retcode != 0)
|
||||
{
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not create initial dead revision %s", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* put the new file back where it was */
|
||||
rename_file (fname, file);
|
||||
free (fname);
|
||||
|
||||
/* double-check that the file was written correctly */
|
||||
freercsnode (&rcsfile);
|
||||
rcsfile = RCS_parse (file, repository);
|
||||
if (rcsfile == NULL)
|
||||
{
|
||||
error (0, 0, "could not read %s", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
if (rcsnode != NULL)
|
||||
{
|
||||
assert (*rcsnode == NULL);
|
||||
*rcsnode = rcsfile;
|
||||
}
|
||||
|
||||
/* and lock it once again. */
|
||||
if (lock_RCS (file, rcsfile, NULL, repository))
|
||||
{
|
||||
error (0, 0, "cannot lock `%s'.", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* when adding a file for the first time, and using a tag, we need
|
||||
to create a dead revision on the trunk. */
|
||||
if (adding_on_branch)
|
||||
{
|
||||
if (newfile)
|
||||
{
|
||||
char *tmp;
|
||||
FILE *fp;
|
||||
|
||||
/* move the new file out of the way. */
|
||||
fname = xmalloc (strlen (file) + sizeof (CVSADM)
|
||||
+ sizeof (CVSPREFIX) + 10);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
|
||||
rename_file (file, fname);
|
||||
|
||||
/* Create empty FILE. Can't use copy_file with a DEVNULL
|
||||
argument -- copy_file now ignores device files. */
|
||||
fp = fopen (file, "w");
|
||||
if (fp == NULL)
|
||||
error (1, errno, "cannot open %s for writing", file);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "cannot close %s", file);
|
||||
|
||||
tmp = xmalloc (strlen (file) + strlen (tag) + 80);
|
||||
/* commit a dead revision. */
|
||||
(void) sprintf (tmp, "file %s was initially added on branch %s.",
|
||||
file, tag);
|
||||
retcode = RCS_checkin (rcsfile, NULL, tmp, NULL,
|
||||
RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
|
||||
free (tmp);
|
||||
if (retcode != 0)
|
||||
{
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not create initial dead revision %s", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* put the new file back where it was */
|
||||
rename_file (fname, file);
|
||||
free (fname);
|
||||
|
||||
/* double-check that the file was written correctly */
|
||||
freercsnode (&rcsfile);
|
||||
rcsfile = RCS_parse (file, repository);
|
||||
if (rcsfile == NULL)
|
||||
{
|
||||
error (0, 0, "could not read %s", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
if (rcsnode != NULL)
|
||||
*rcsnode = rcsfile;
|
||||
|
||||
/* and lock it once again. */
|
||||
if (lock_RCS (file, rcsfile, NULL, repository))
|
||||
{
|
||||
error (0, 0, "cannot lock `%s'.", rcs);
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* when adding with a tag, we need to stub a branch, if it
|
||||
doesn't already exist. */
|
||||
|
||||
@ -2197,6 +2206,8 @@ checkaddfile (file, repository, tag, options, rcsnode)
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
if (retval != 0 && SIG_inCrSect ())
|
||||
SIG_endCrSect ();
|
||||
free (rcs);
|
||||
return retval;
|
||||
}
|
||||
|
@ -395,6 +395,7 @@ extern List *root_directories;
|
||||
extern char *current_root;
|
||||
|
||||
extern char *emptydir_name PROTO ((void));
|
||||
extern int safe_location PROTO ((void));
|
||||
|
||||
extern int trace; /* Show all commands */
|
||||
extern int noexec; /* Don't modify disk anywhere */
|
||||
@ -507,7 +508,7 @@ void *valloc PROTO((size_t bytes));
|
||||
time_t get_date PROTO((char *date, struct timeb *now));
|
||||
extern int Create_Admin PROTO ((char *dir, char *update_dir,
|
||||
char *repository, char *tag, char *date,
|
||||
int nonbranch, int warn));
|
||||
int nonbranch, int warn, int dotemplate));
|
||||
extern int expand_at_signs PROTO ((char *, off_t, FILE *));
|
||||
|
||||
/* Locking subsystem (implemented in lock.c). */
|
||||
@ -533,7 +534,7 @@ void cat_module PROTO((int status));
|
||||
void check_entries PROTO((char *dir));
|
||||
void close_module PROTO((DBM * db));
|
||||
void copy_file PROTO((const char *from, const char *to));
|
||||
void fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
|
||||
void fperrmsg PROTO((FILE * fp, int status, int errnum, char *message,...));
|
||||
void free_names PROTO((int *pargc, char *argv[]));
|
||||
|
||||
extern int ign_name PROTO ((char *name));
|
||||
@ -554,6 +555,7 @@ void make_directories PROTO((const char *name));
|
||||
void make_directory PROTO((const char *name));
|
||||
extern int mkdir_if_needed PROTO ((char *name));
|
||||
void rename_file PROTO((const char *from, const char *to));
|
||||
char *backup_file PROTO((const char *file, const char *suffix));
|
||||
/* Expand wildcards in each element of (ARGC,ARGV). This is according to the
|
||||
files which exist in the current directory, and accordingly to OS-specific
|
||||
conventions regarding wildcard syntax. It might be desirable to change the
|
||||
@ -585,7 +587,7 @@ void do_editor PROTO((char *dir, char **messagep,
|
||||
|
||||
void do_verify PROTO((char **messagep, char *repository));
|
||||
|
||||
typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where,
|
||||
typedef int (*CALLBACKPROC) PROTO((int argc, char *argv[], char *where,
|
||||
char *mwhere, char *mfile, int shorten, int local_specified,
|
||||
char *omodule, char *msg));
|
||||
|
||||
@ -644,6 +646,7 @@ int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
|
||||
int dosrcs));
|
||||
void SIG_beginCrSect PROTO((void));
|
||||
void SIG_endCrSect PROTO((void));
|
||||
int SIG_inCrSect PROTO((void));
|
||||
void read_cvsrc PROTO((int *argc, char ***argv, char *cmdname));
|
||||
|
||||
char *make_message_rcslegal PROTO((char *message));
|
||||
@ -861,6 +864,7 @@ extern int cvsremove PROTO((int argc, char **argv));
|
||||
extern int rtag PROTO((int argc, char **argv));
|
||||
extern int cvsstatus PROTO((int argc, char **argv));
|
||||
extern int cvstag PROTO((int argc, char **argv));
|
||||
extern int version PROTO((int argc, char **argv));
|
||||
|
||||
extern unsigned long int lookup_command_attribute PROTO((char *));
|
||||
|
||||
@ -877,6 +881,8 @@ extern void tag_check_valid PROTO ((char *, int, char **, int, int, char *));
|
||||
extern void tag_check_valid_join PROTO ((char *, int, char **, int, int,
|
||||
char *));
|
||||
|
||||
#include "server.h"
|
||||
|
||||
/* From server.c and documented there. */
|
||||
extern void cvs_output PROTO ((const char *, size_t));
|
||||
extern void cvs_output_binary PROTO ((char *, size_t));
|
||||
@ -884,7 +890,3 @@ extern void cvs_outerr PROTO ((const char *, size_t));
|
||||
extern void cvs_flusherr PROTO ((void));
|
||||
extern void cvs_flushout PROTO ((void));
|
||||
extern void cvs_output_tagged PROTO ((char *, char *));
|
||||
|
||||
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
|
||||
#include "server.h"
|
||||
#endif
|
||||
|
@ -55,9 +55,13 @@ copy_file (from, to)
|
||||
|
||||
if (isdevice (from))
|
||||
{
|
||||
#if defined(HAVE_MKNOD) && defined(HAVE_ST_RDEV)
|
||||
if (stat (from, &sb) < 0)
|
||||
error (1, errno, "cannot stat %s", from);
|
||||
mknod (to, sb.st_mode, sb.st_rdev);
|
||||
#else
|
||||
error (1, 0, "cannot copy device files on this system (%s)", from);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -624,10 +628,15 @@ xcmp (file1, file2)
|
||||
numbers match. */
|
||||
if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
|
||||
{
|
||||
#ifdef HAVE_ST_RDEV
|
||||
if (sb1.st_rdev == sb2.st_rdev)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
#else
|
||||
error (1, 0, "cannot compare device files on this system (%s and %s)",
|
||||
file1, file2);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((fd1 = open (file1, O_RDONLY)) < 0)
|
||||
|
@ -268,12 +268,22 @@ import (argc, argv)
|
||||
client_import_setup (repository);
|
||||
err = import_descend (message, argv[1], argc - 2, argv + 2);
|
||||
client_import_done ();
|
||||
if (message)
|
||||
free (message);
|
||||
free (repository);
|
||||
free (vbranch);
|
||||
free (vhead);
|
||||
send_to_server ("import\012", 0);
|
||||
err += get_responses_and_close ();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!safe_location ())
|
||||
{
|
||||
error (1, 0, "attempt to import the repository");
|
||||
}
|
||||
|
||||
/*
|
||||
* Make all newly created directories writable. Should really use a more
|
||||
* sophisticated security mechanism here.
|
||||
@ -455,9 +465,12 @@ import_descend (message, vtag, targc, targv)
|
||||
}
|
||||
else if (
|
||||
#ifdef DT_DIR
|
||||
dp->d_type == DT_LNK || dp->d_type == DT_UNKNOWN &&
|
||||
dp->d_type == DT_LNK
|
||||
|| (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
|
||||
#else
|
||||
islink (dp->d_name)
|
||||
#endif
|
||||
islink (dp->d_name))
|
||||
)
|
||||
{
|
||||
add_log ('L', dp->d_name);
|
||||
err++;
|
||||
@ -727,8 +740,8 @@ add_rev (message, rcs, vfile, vers)
|
||||
{
|
||||
if (!noexec)
|
||||
{
|
||||
fperror (logfp, 0, status == -1 ? ierrno : 0,
|
||||
"ERROR: Check-in of %s failed", rcs->path);
|
||||
fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
|
||||
"ERROR: Check-in of %s failed", rcs->path);
|
||||
error (0, status == -1 ? ierrno : 0,
|
||||
"ERROR: Check-in of %s failed", rcs->path);
|
||||
}
|
||||
@ -767,8 +780,8 @@ add_tags (rcs, vfile, vtag, targc, targv)
|
||||
if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
"ERROR: Failed to set tag %s in %s", vtag, rcs->path);
|
||||
fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
"ERROR: Failed to set tag %s in %s", vtag, rcs->path);
|
||||
error (0, retcode == -1 ? ierrno : 0,
|
||||
"ERROR: Failed to set tag %s in %s", vtag, rcs->path);
|
||||
return (1);
|
||||
@ -791,9 +804,9 @@ add_tags (rcs, vfile, vtag, targc, targv)
|
||||
else
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
"WARNING: Couldn't add tag %s to %s", targv[i],
|
||||
rcs->path);
|
||||
fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
"WARNING: Couldn't add tag %s to %s", targv[i],
|
||||
rcs->path);
|
||||
error (0, retcode == -1 ? ierrno : 0,
|
||||
"WARNING: Couldn't add tag %s to %s", targv[i],
|
||||
rcs->path);
|
||||
@ -1056,7 +1069,14 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
stat the file before opening it. -twp */
|
||||
|
||||
if (CVS_LSTAT (userfile, &sb) < 0)
|
||||
error (1, errno, "cannot lstat %s", user);
|
||||
{
|
||||
/* not fatal, continue import */
|
||||
if (add_logfp != NULL)
|
||||
fperrmsg (add_logfp, 0, errno,
|
||||
"ERROR: cannot lstat file %s", userfile);
|
||||
error (0, errno, "cannot lstat file %s", userfile);
|
||||
goto read_error;
|
||||
}
|
||||
file_type = sb.st_mode & S_IFMT;
|
||||
|
||||
fpuser = NULL;
|
||||
@ -1071,8 +1091,8 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
{
|
||||
/* not fatal, continue import */
|
||||
if (add_logfp != NULL)
|
||||
fperror (add_logfp, 0, errno,
|
||||
"ERROR: cannot read file %s", userfile);
|
||||
fperrmsg (add_logfp, 0, errno,
|
||||
"ERROR: cannot read file %s", userfile);
|
||||
error (0, errno, "ERROR: cannot read file %s", userfile);
|
||||
goto read_error;
|
||||
}
|
||||
@ -1204,12 +1224,18 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
case S_IFREG: break;
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
#ifdef HAVE_ST_RDEV
|
||||
if (fprintf (fprcs, "special\t%s %lu;\012",
|
||||
(file_type == S_IFCHR
|
||||
? "character"
|
||||
: "block"),
|
||||
(unsigned long) sb.st_rdev) < 0)
|
||||
goto write_error;
|
||||
#else
|
||||
error (0, 0,
|
||||
"can't import %s: unable to import device files on this system",
|
||||
userfile);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
error (0, 0,
|
||||
@ -1255,12 +1281,18 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
case S_IFREG: break;
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
#ifdef HAVE_ST_RDEV
|
||||
if (fprintf (fprcs, "special\t%s %lu;\012",
|
||||
(file_type == S_IFCHR
|
||||
? "character"
|
||||
: "block"),
|
||||
(unsigned long) sb.st_rdev) < 0)
|
||||
goto write_error;
|
||||
#else
|
||||
error (0, 0,
|
||||
"can't import %s: unable to import device files on this system",
|
||||
userfile);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
error (0, 0,
|
||||
@ -1379,8 +1411,8 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
{
|
||||
ierrno = errno;
|
||||
if (add_logfp != NULL)
|
||||
fperror (add_logfp, 0, ierrno,
|
||||
"WARNING: cannot change mode of file %s", rcs);
|
||||
fperrmsg (add_logfp, 0, ierrno,
|
||||
"WARNING: cannot change mode of file %s", rcs);
|
||||
error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
|
||||
err++;
|
||||
}
|
||||
@ -1399,14 +1431,14 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
if (fclose (fpuser) < 0)
|
||||
error (0, errno, "cannot close %s", user);
|
||||
if (add_logfp != NULL)
|
||||
fperror (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
|
||||
fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
|
||||
error (0, ierrno, "ERROR: cannot write file %s", rcs);
|
||||
if (ierrno == ENOSPC)
|
||||
{
|
||||
if (CVS_UNLINK (rcs) < 0)
|
||||
error (0, errno, "cannot remove %s", rcs);
|
||||
if (add_logfp != NULL)
|
||||
fperror (add_logfp, 0, 0, "ERROR: out of space - aborting");
|
||||
fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
|
||||
error (1, 0, "ERROR: out of space - aborting");
|
||||
}
|
||||
read_error:
|
||||
@ -1515,7 +1547,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
||||
return (0);
|
||||
if (save_cwd (&cwd))
|
||||
{
|
||||
fperror (logfp, 0, 0, "ERROR: cannot get working directory");
|
||||
fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -1546,7 +1578,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
||||
if ( CVS_CHDIR (dir) < 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
|
||||
fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
|
||||
error (0, ierrno, "ERROR: cannot chdir to %s", repository);
|
||||
err = 1;
|
||||
goto out;
|
||||
@ -1561,9 +1593,9 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
||||
(void) sprintf (rcs, "%s%s", repository, RCSEXT);
|
||||
if (isfile (repository) || isfile(rcs))
|
||||
{
|
||||
fperror (logfp, 0, 0,
|
||||
"ERROR: %s is a file, should be a directory!",
|
||||
repository);
|
||||
fperrmsg (logfp, 0, 0,
|
||||
"ERROR: %s is a file, should be a directory!",
|
||||
repository);
|
||||
error (0, 0, "ERROR: %s is a file, should be a directory!",
|
||||
repository);
|
||||
err = 1;
|
||||
@ -1572,8 +1604,8 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
||||
if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, ierrno,
|
||||
"ERROR: cannot mkdir %s -- not added", repository);
|
||||
fperrmsg (logfp, 0, ierrno,
|
||||
"ERROR: cannot mkdir %s -- not added", repository);
|
||||
error (0, ierrno,
|
||||
"ERROR: cannot mkdir %s -- not added", repository);
|
||||
err = 1;
|
||||
|
@ -177,8 +177,12 @@ lock_name (repository, name)
|
||||
assert (CVSroot_directory != NULL);
|
||||
assert (strncmp (repository, CVSroot_directory,
|
||||
strlen (CVSroot_directory)) == 0);
|
||||
short_repos = repository + strlen (CVSroot_directory);
|
||||
assert (*short_repos++ == '/');
|
||||
short_repos = repository + strlen (CVSroot_directory) + 1;
|
||||
|
||||
if (strcmp (repository, CVSroot_directory) == 0)
|
||||
short_repos = ".";
|
||||
else
|
||||
assert (short_repos[-1] == '/');
|
||||
|
||||
retval = xmalloc (strlen (lock_dir)
|
||||
+ strlen (short_repos)
|
||||
@ -762,8 +766,8 @@ set_lock (lock, will_wait)
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
error (0, errno,
|
||||
"failed to create lock directory in repository `%s'",
|
||||
lock->repository);
|
||||
"failed to create lock directory for `%s' (%s)",
|
||||
lock->repository, masterlock);
|
||||
return (L_ERROR);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
#ifdef AUTH_CLIENT_SUPPORT /* This covers the rest of the file. */
|
||||
|
||||
#ifdef HAVE_GETPASSPHRASE
|
||||
#define GETPASS getpassphrase
|
||||
#else
|
||||
#define GETPASS getpass
|
||||
#endif
|
||||
|
||||
/* There seems to be very little agreement on which system header
|
||||
getpass is declared in. With a lot of fancy autoconfiscation,
|
||||
we could perhaps detect this, but for now we'll just rely on
|
||||
@ -22,7 +28,7 @@
|
||||
varadic, believe it or not). On Cray, getpass will be declared
|
||||
in either stdlib.h or unistd.h. */
|
||||
#ifndef _CRAY
|
||||
extern char *getpass ();
|
||||
extern char *GETPASS ();
|
||||
#endif
|
||||
|
||||
#ifndef CVS_PASSWORD_FILE
|
||||
@ -144,7 +150,7 @@ login (argc, argv)
|
||||
fflush (stdout);
|
||||
|
||||
passfile = construct_cvspass_filename ();
|
||||
typed_password = getpass ("CVS password: ");
|
||||
typed_password = GETPASS ("CVS password: ");
|
||||
typed_password = scramble (typed_password);
|
||||
|
||||
/* Force get_cvs_password() to use this one (when the client
|
||||
@ -291,21 +297,19 @@ login (argc, argv)
|
||||
}
|
||||
|
||||
/* Returns the _scrambled_ password. The server must descramble
|
||||
before hashing and comparing. */
|
||||
before hashing and comparing. If password file not found, or
|
||||
password not found in the file, just return NULL. */
|
||||
char *
|
||||
get_cvs_password ()
|
||||
{
|
||||
int found_it = 0;
|
||||
int root_len;
|
||||
char *password;
|
||||
char *linebuf = (char *) NULL;
|
||||
char *password = NULL;
|
||||
char *linebuf = NULL;
|
||||
size_t linebuf_len;
|
||||
FILE *fp;
|
||||
char *passfile;
|
||||
int line_length;
|
||||
int anoncvs;
|
||||
|
||||
anoncvs = (strcmp(CVSroot_username, "anoncvs") == 0);
|
||||
|
||||
/* If someone (i.e., login()) is calling connect_to_pserver() out of
|
||||
context, then assume they have supplied the correct, scrambled
|
||||
@ -344,15 +348,10 @@ get_cvs_password ()
|
||||
|
||||
passfile = construct_cvspass_filename ();
|
||||
fp = CVS_FOPEN (passfile, "r");
|
||||
if (fp == NULL)
|
||||
if (fp == NULL)
|
||||
{
|
||||
if (anoncvs) {
|
||||
free (passfile);
|
||||
return strdup("Ay=0=h<Z"); /* scrambled "anoncvs" */
|
||||
}
|
||||
error (0, errno, "could not open %s", passfile);
|
||||
free (passfile);
|
||||
error (1, 0, "use \"cvs login\" to log in first");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
root_len = strlen (CVSroot_original);
|
||||
@ -371,7 +370,6 @@ get_cvs_password ()
|
||||
error (0, errno, "cannot read %s", passfile);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "cannot close %s", passfile);
|
||||
free (passfile);
|
||||
|
||||
if (found_it)
|
||||
{
|
||||
@ -379,25 +377,19 @@ get_cvs_password ()
|
||||
char *tmp;
|
||||
|
||||
strtok (linebuf, " ");
|
||||
password = strtok (NULL, "\n");
|
||||
tmp = strtok (NULL, "\n");
|
||||
if (tmp == NULL)
|
||||
error (1, 0, "bad entry in %s for %s", passfile, CVSroot_original);
|
||||
|
||||
/* Give it permanent storage. */
|
||||
tmp = xstrdup (password);
|
||||
memset (password, 0, strlen (password));
|
||||
free (linebuf);
|
||||
return tmp;
|
||||
password = xstrdup (tmp);
|
||||
memset (tmp, 0, strlen (password));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (linebuf)
|
||||
free (linebuf);
|
||||
if (anoncvs)
|
||||
return strdup("Ay=0=h<Z"); /* scrambled "anoncvs" */
|
||||
error (0, 0, "cannot find password");
|
||||
error (1, 0, "use \"cvs login\" to log in first");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
|
||||
if (linebuf)
|
||||
free (linebuf);
|
||||
free (passfile);
|
||||
return password;
|
||||
}
|
||||
|
||||
static const char *const logout_usage[] =
|
||||
@ -407,7 +399,7 @@ static const char *const logout_usage[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Remove any entry for the CVSRoot repository found in "CVS/.cvspass". */
|
||||
/* Remove any entry for the CVSRoot repository found in .cvspass. */
|
||||
int
|
||||
logout (argc, argv)
|
||||
int argc;
|
||||
@ -415,7 +407,7 @@ logout (argc, argv)
|
||||
{
|
||||
char *passfile;
|
||||
FILE *fp;
|
||||
char *tmp_name;
|
||||
char *tmp_name = NULL;
|
||||
FILE *tmp_fp;
|
||||
char *linebuf = (char *) NULL;
|
||||
size_t linebuf_len;
|
||||
@ -510,6 +502,10 @@ logout (argc, argv)
|
||||
error (0, errno, "cannot remove %s", tmp_name);
|
||||
chmod (passfile, 0600);
|
||||
}
|
||||
|
||||
if (tmp_name)
|
||||
free (tmp_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,6 @@ do_editor (dir, messagep, repository, changes)
|
||||
char *fname;
|
||||
struct stat pre_stbuf, post_stbuf;
|
||||
int retcode = 0;
|
||||
char *p;
|
||||
|
||||
if (noexec || reuse_log_message)
|
||||
return;
|
||||
@ -218,7 +217,6 @@ do_editor (dir, messagep, repository, changes)
|
||||
{
|
||||
FILE *tfp;
|
||||
char buf[1024];
|
||||
char *p;
|
||||
size_t n;
|
||||
size_t nwrite;
|
||||
|
||||
@ -233,9 +231,9 @@ do_editor (dir, messagep, repository, changes)
|
||||
{
|
||||
while (!feof (tfp))
|
||||
{
|
||||
char *p = buf;
|
||||
n = fread (buf, 1, sizeof buf, tfp);
|
||||
nwrite = n;
|
||||
p = buf;
|
||||
while (nwrite > 0)
|
||||
{
|
||||
n = fwrite (p, 1, nwrite, fp);
|
||||
@ -317,7 +315,8 @@ do_editor (dir, messagep, repository, changes)
|
||||
|
||||
if (*messagep)
|
||||
{
|
||||
p = *messagep;
|
||||
size_t message_len = post_stbuf.st_size + 1;
|
||||
size_t offset = 0;
|
||||
while (1)
|
||||
{
|
||||
line_length = getline (&line, &line_chars_allocated, fp);
|
||||
@ -329,8 +328,11 @@ do_editor (dir, messagep, repository, changes)
|
||||
}
|
||||
if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
|
||||
continue;
|
||||
(void) strcpy (p, line);
|
||||
p += line_length;
|
||||
if (offset + line_length >= message_len)
|
||||
expand_string (messagep, &message_len,
|
||||
offset + line_length + 1);
|
||||
(void) strcpy (*messagep + offset, line);
|
||||
offset += line_length;
|
||||
}
|
||||
}
|
||||
if (fclose (fp) < 0)
|
||||
@ -816,7 +818,7 @@ logfile_write (repository, filter, message, logfp, changes)
|
||||
}
|
||||
|
||||
len = fmt_end - fmt_begin;
|
||||
str_list_format = xmalloc (sizeof (char) * (len + 1));
|
||||
str_list_format = xmalloc (len + 1);
|
||||
strncpy (str_list_format, fmt_begin, len);
|
||||
str_list_format[len] = '\0';
|
||||
|
||||
|
@ -115,30 +115,31 @@ static const struct cmd
|
||||
{ "history", "hi", "his", history },
|
||||
{ "import", "im", "imp", import },
|
||||
{ "init", NULL, NULL, init },
|
||||
#ifdef SERVER_SUPPORT
|
||||
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
|
||||
{ "kserver", NULL, NULL, server }, /* placeholder */
|
||||
#endif
|
||||
{ "log", "lo", "rlog", cvslog },
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
{ "login", "logon", "lgn", login },
|
||||
{ "logout", NULL, NULL, logout },
|
||||
#ifdef SERVER_SUPPORT
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
|
||||
{ "pserver", NULL, NULL, server }, /* placeholder */
|
||||
#endif
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
{ "rdiff", "patch", "pa", patch },
|
||||
{ "release", "re", "rel", release },
|
||||
{ "remove", "rm", "delete", cvsremove },
|
||||
{ "status", "st", "stat", cvsstatus },
|
||||
{ "rtag", "rt", "rfreeze", rtag },
|
||||
{ "tag", "ta", "freeze", cvstag },
|
||||
{ "unedit", NULL, NULL, unedit },
|
||||
{ "update", "up", "upd", update },
|
||||
{ "watch", NULL, NULL, watch },
|
||||
{ "watchers", NULL, NULL, watchers },
|
||||
#ifdef SERVER_SUPPORT
|
||||
{ "server", NULL, NULL, server },
|
||||
#endif
|
||||
{ "status", "st", "stat", cvsstatus },
|
||||
{ "tag", "ta", "freeze", cvstag },
|
||||
{ "unedit", NULL, NULL, unedit },
|
||||
{ "update", "up", "upd", update },
|
||||
{ "version", "ve", "ver", version },
|
||||
{ "watch", NULL, NULL, watch },
|
||||
{ "watchers", NULL, NULL, watchers },
|
||||
{ NULL, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
@ -183,7 +184,7 @@ static const char *const usg[] =
|
||||
version control means. */
|
||||
|
||||
"For CVS updates and additional information, see\n",
|
||||
" Cyclic Software at http://www.cyclic.com/ or\n",
|
||||
" the CVS home page at http://www.cvshome.org/ or\n",
|
||||
" Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n",
|
||||
NULL,
|
||||
};
|
||||
@ -203,15 +204,24 @@ static const char *const cmd_usage[] =
|
||||
" history Show repository access history\n",
|
||||
" import Import sources into CVS, using vendor branches\n",
|
||||
" init Create a CVS repository if it doesn't exist\n",
|
||||
#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
|
||||
" kserver Kerberos server mode\n",
|
||||
#endif
|
||||
" log Print out history information for files\n",
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
" login Prompt for password for authenticating server.\n",
|
||||
" logout Removes entry in .cvspass for remote repository.\n",
|
||||
" login Prompt for password for authenticating server\n",
|
||||
" logout Removes entry in .cvspass for remote repository\n",
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
|
||||
" pserver Password server mode\n",
|
||||
#endif
|
||||
" rdiff Create 'patch' format diffs between releases\n",
|
||||
" release Indicate that a Module is no longer in use\n",
|
||||
" remove Remove an entry from the repository\n",
|
||||
" rtag Add a symbolic tag to a module\n",
|
||||
#ifdef SERVER_SUPPORT
|
||||
" server Server mode\n",
|
||||
#endif
|
||||
" status Display status information on checked out files\n",
|
||||
" tag Add a symbolic tag to checked out version of files\n",
|
||||
" unedit Undo an edit command\n",
|
||||
@ -349,6 +359,7 @@ lookup_command_attribute (cmd_name)
|
||||
(strcmp (cmd_name, "log") != 0) &&
|
||||
(strcmp (cmd_name, "noop") != 0) &&
|
||||
(strcmp (cmd_name, "watchers") != 0) &&
|
||||
(strcmp (cmd_name, "release") != 0) &&
|
||||
(strcmp (cmd_name, "status") != 0))
|
||||
{
|
||||
ret |= CVS_CMD_MODIFIES_REPOSITORY;
|
||||
@ -368,6 +379,11 @@ main_cleanup (sig)
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
#ifdef SIGABRT
|
||||
case SIGABRT:
|
||||
name = "abort";
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
case SIGHUP:
|
||||
name = "hangup";
|
||||
@ -411,8 +427,6 @@ main (argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char *CVSroot = CVSROOT_DFLT;
|
||||
extern char *version_string;
|
||||
extern char *config_string;
|
||||
char *cp, *end;
|
||||
const struct cmd *cm;
|
||||
int c, err = 0;
|
||||
@ -424,6 +438,7 @@ main (argc, argv)
|
||||
int help = 0; /* Has the user asked for help? This
|
||||
lets us support the `cvs -H cmd'
|
||||
convention to give help for cmd. */
|
||||
static const char short_options[] = "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU";
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", 0, NULL, 'H'},
|
||||
@ -504,7 +519,7 @@ main (argc, argv)
|
||||
opterr = 0;
|
||||
|
||||
while ((c = getopt_long
|
||||
(argc, argv, "+f", NULL, NULL))
|
||||
(argc, argv, short_options, long_options, &option_index))
|
||||
!= EOF)
|
||||
{
|
||||
if (c == 'f')
|
||||
@ -521,7 +536,7 @@ main (argc, argv)
|
||||
opterr = 1;
|
||||
|
||||
while ((c = getopt_long
|
||||
(argc, argv, "+QqgrwtnRlvb:T:e:d:Hfz:s:xaU", long_options, &option_index))
|
||||
(argc, argv, short_options, long_options, &option_index))
|
||||
!= EOF)
|
||||
{
|
||||
switch (c)
|
||||
@ -574,14 +589,11 @@ main (argc, argv)
|
||||
logoff = 1;
|
||||
break;
|
||||
case 'v':
|
||||
/* Having the year here is a good idea, so people have
|
||||
some idea of how long ago their version of CVS was
|
||||
released. */
|
||||
(void) fputs (version_string, stdout);
|
||||
(void) fputs (config_string, stdout);
|
||||
(void) fputs ("\n", stdout);
|
||||
version (0, (char **) NULL);
|
||||
(void) fputs ("\n", stdout);
|
||||
(void) fputs ("\
|
||||
Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
Copyright (c) 1989-2000 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
Jeff Polk, and other authors\n", stdout);
|
||||
(void) fputs ("\n", stdout);
|
||||
(void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
|
||||
@ -625,9 +637,9 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
case 'z':
|
||||
#ifdef CLIENT_SUPPORT
|
||||
gzip_level = atoi (optarg);
|
||||
if (gzip_level <= 0 || gzip_level > 9)
|
||||
if (gzip_level < 0 || gzip_level > 9)
|
||||
error (1, 0,
|
||||
"gzip compression level must be between 1 and 9");
|
||||
"gzip compression level must be between 0 and 9");
|
||||
#endif
|
||||
/* If no CLIENT_SUPPORT, we just silently ignore the gzip
|
||||
level, so that users can have it in their .cvsrc and not
|
||||
@ -685,7 +697,10 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
}
|
||||
|
||||
if (!cm->fullname)
|
||||
usage (cmd_usage); /* no match */
|
||||
{
|
||||
fprintf (stderr, "Unknown command: `%s'\n\n", command_name);
|
||||
usage (cmd_usage);
|
||||
}
|
||||
else
|
||||
command_name = cm->fullname; /* Global pointer for later use */
|
||||
|
||||
@ -799,25 +814,23 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
|
||||
#ifndef DONT_USE_SIGNALS
|
||||
/* make sure we clean up on error */
|
||||
#ifdef SIGABRT
|
||||
(void) SIG_register (SIGABRT, main_cleanup);
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
(void) SIG_register (SIGHUP, main_cleanup);
|
||||
(void) SIG_register (SIGHUP, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
(void) SIG_register (SIGINT, main_cleanup);
|
||||
(void) SIG_register (SIGINT, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) SIG_register (SIGQUIT, main_cleanup);
|
||||
(void) SIG_register (SIGQUIT, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
(void) SIG_register (SIGPIPE, main_cleanup);
|
||||
(void) SIG_register (SIGPIPE, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
(void) SIG_register (SIGTERM, main_cleanup);
|
||||
(void) SIG_register (SIGTERM, Lock_Cleanup);
|
||||
#endif
|
||||
#endif /* !DONT_USE_SIGNALS */
|
||||
|
||||
@ -912,7 +925,7 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
{
|
||||
Node *n;
|
||||
n = getnode ();
|
||||
n->type = UNKNOWN;
|
||||
n->type = NT_UNKNOWN;
|
||||
n->key = xstrdup (CVSroot);
|
||||
n->data = NULL;
|
||||
|
||||
@ -955,11 +968,8 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
current_root);
|
||||
|
||||
/*
|
||||
* Check to see if we can write into the history file. If not,
|
||||
* we assume that we can't work in the repository.
|
||||
* BUT, only if the history file exists.
|
||||
* Check to see if the repository exists.
|
||||
*/
|
||||
|
||||
if (!client_active)
|
||||
{
|
||||
char *path;
|
||||
@ -967,8 +977,7 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
|
||||
path = xmalloc (strlen (CVSroot_directory)
|
||||
+ sizeof (CVSROOTADM)
|
||||
+ 20
|
||||
+ sizeof (CVSROOTADM_HISTORY));
|
||||
+ 20);
|
||||
(void) sprintf (path, "%s/%s", CVSroot_directory, CVSROOTADM);
|
||||
if (!isaccessible (path, R_OK | X_OK))
|
||||
{
|
||||
@ -979,14 +988,6 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
error (1, save_errno, "%s", path);
|
||||
}
|
||||
}
|
||||
(void) strcat (path, "/");
|
||||
(void) strcat (path, CVSROOTADM_HISTORY);
|
||||
if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK))
|
||||
{
|
||||
save_errno = errno;
|
||||
error (0, 0, "Sorry, you don't have read/write access to the history file");
|
||||
error (1, save_errno, "%s", path);
|
||||
}
|
||||
free (path);
|
||||
}
|
||||
|
||||
@ -995,12 +996,17 @@ Copyright (c) 1989-1998 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
/* FIXME (njc): should we always set this with the CVSROOT from the command line? */
|
||||
if (cvs_update_env)
|
||||
{
|
||||
static char *prev;
|
||||
char *env;
|
||||
env = xmalloc (strlen (CVSROOT_ENV) + strlen (CVSroot)
|
||||
+ 1 + 1);
|
||||
(void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot);
|
||||
(void) putenv (env);
|
||||
/* do not free env, as putenv has control of it */
|
||||
/* do not free env yet, as putenv has control of it */
|
||||
/* but do free the previous value, if any */
|
||||
if (prev != NULL)
|
||||
free (prev);
|
||||
prev = env;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -283,14 +283,23 @@ static const char *const config_contents[] = {
|
||||
"# Set this to \"no\" if pserver shouldn't check system users/passwords\n",
|
||||
"#SystemAuth=no\n",
|
||||
"\n",
|
||||
"# Put CVS lock files in this directory rather than directly in the repository.\n",
|
||||
"#LockDir=/var/lock/cvs\n",
|
||||
"\n",
|
||||
#ifdef PRESERVE_PERMISSIONS_SUPPORT
|
||||
"# Set `PreservePermissions' to `yes' to save file status information\n",
|
||||
"# in the repository.\n",
|
||||
"#PreservePermissions=no\n",
|
||||
"\n",
|
||||
#endif
|
||||
"# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top\n",
|
||||
"# level of the new working directory when using the `cvs checkout'\n",
|
||||
"# command.\n",
|
||||
"#TopLevelAdmin=no\n",
|
||||
"\n",
|
||||
"# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the\n",
|
||||
"# history file, or a subset as needed (ie `TMAR' logs all write operations)\n",
|
||||
"#LogHistory=TOFEWGCMAR\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -375,6 +384,9 @@ mkmodules (dir)
|
||||
size_t line_allocated = 0;
|
||||
const struct admin_file *fileptr;
|
||||
|
||||
if (noexec)
|
||||
return 0;
|
||||
|
||||
if (save_cwd (&cwd))
|
||||
error_exit ();
|
||||
|
||||
@ -868,6 +880,9 @@ init (argc, argv)
|
||||
if ( CVS_CHDIR (adm) < 0)
|
||||
error (1, errno, "cannot change to directory %s", adm);
|
||||
|
||||
/* Make Emptydir so it's there if we need it */
|
||||
mkdir_if_needed (CVSNULLREPOS);
|
||||
|
||||
/* 80 is long enough for all the administrative file names, plus
|
||||
"/" and so on. */
|
||||
info = xmalloc (strlen (adm) + 80);
|
||||
@ -929,6 +944,29 @@ init (argc, argv)
|
||||
fp = open_file (info, "w");
|
||||
if (fclose (fp) < 0)
|
||||
error (1, errno, "cannot close %s", info);
|
||||
|
||||
/* Make the new history file world-writeable, since every CVS
|
||||
user will need to be able to write to it. We use chmod()
|
||||
because xchmod() is too shy. */
|
||||
chmod (info, 0666);
|
||||
}
|
||||
|
||||
/* Make an empty val-tags file to prevent problems creating it later. */
|
||||
strcpy (info, adm);
|
||||
strcat (info, "/");
|
||||
strcat (info, CVSROOTADM_VALTAGS);
|
||||
if (!isfile (info))
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = open_file (info, "w");
|
||||
if (fclose (fp) < 0)
|
||||
error (1, errno, "cannot close %s", info);
|
||||
|
||||
/* Make the new val-tags file world-writeable, since every CVS
|
||||
user will need to be able to write to it. We use chmod()
|
||||
because xchmod() is too shy. */
|
||||
chmod (info, 0666);
|
||||
}
|
||||
|
||||
free (info);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,8 +10,10 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* String which indicates a conflict if it occurs at the start of a line. */
|
||||
#define RCS_MERGE_PAT ">>>>>>> "
|
||||
/* Strings which indicate a conflict if they occur at the start of a line. */
|
||||
#define RCS_MERGE_PAT_1 "<<<<<<< "
|
||||
#define RCS_MERGE_PAT_2 "=======\n"
|
||||
#define RCS_MERGE_PAT_3 ">>>>>>> "
|
||||
|
||||
#define RCSEXT ",v"
|
||||
#define RCSPAT "*,v"
|
||||
@ -229,7 +231,9 @@ int RCS_delete_revs PROTO ((RCSNode *, char *, char *, int));
|
||||
void RCS_addaccess PROTO ((RCSNode *, char *));
|
||||
void RCS_delaccess PROTO ((RCSNode *, char *));
|
||||
char *RCS_getaccess PROTO ((RCSNode *));
|
||||
RETSIGTYPE rcs_cleanup PROTO ((void));
|
||||
void RCS_rewrite PROTO ((RCSNode *, Deltatext *, char *));
|
||||
void RCS_abandon PROTO ((RCSNode *));
|
||||
int rcs_change_text PROTO ((const char *, char *, size_t, const char *,
|
||||
size_t, char **, size_t *));
|
||||
void RCS_setincexc PROTO ((const char *arg));
|
||||
|
@ -174,6 +174,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
|
||||
seems to be handled somewhere (else) but why should
|
||||
it be a separate case? Needs investigation... */
|
||||
just_subdirs = 1;
|
||||
free (root);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -591,7 +592,7 @@ do_recursion (frame)
|
||||
/* Add it to our list. */
|
||||
|
||||
Node *n = getnode ();
|
||||
n->type = UNKNOWN;
|
||||
n->type = NT_UNKNOWN;
|
||||
n->key = xstrdup (this_root);
|
||||
|
||||
if (addnode (root_directories, n))
|
||||
@ -1016,7 +1017,7 @@ but CVS uses %s for its own purposes; skipping %s directory",
|
||||
/* Add it to our list. */
|
||||
|
||||
Node *n = getnode ();
|
||||
n->type = UNKNOWN;
|
||||
n->type = NT_UNKNOWN;
|
||||
n->key = xstrdup (this_root);
|
||||
|
||||
if (addnode (root_directories, n))
|
||||
@ -1133,6 +1134,7 @@ addfile (listp, dir, file)
|
||||
char *file;
|
||||
{
|
||||
Node *n;
|
||||
List *fl;
|
||||
|
||||
/* add this dir. */
|
||||
addlist (listp, dir);
|
||||
@ -1145,7 +1147,9 @@ addfile (listp, dir, file)
|
||||
}
|
||||
|
||||
n->type = DIRS;
|
||||
addlist ((List **) &n->data, file);
|
||||
fl = (List *) n->data;
|
||||
addlist (&fl, file);
|
||||
n->data = (char *) fl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1205,6 +1209,7 @@ unroll_files_proc (p, closure)
|
||||
}
|
||||
|
||||
dirlist = save_dirlist;
|
||||
filelist = NULL;
|
||||
if (filelist)
|
||||
dellist (&filelist);
|
||||
return(err);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -96,6 +96,7 @@ static char *tag_update_dir;
|
||||
static char *join_rev1, *date_rev1;
|
||||
static char *join_rev2, *date_rev2;
|
||||
static int aflag = 0;
|
||||
static int toss_local_changes = 0;
|
||||
static int force_tag_match = 1;
|
||||
static int update_build_dirs = 0;
|
||||
static int update_prune_dirs = 0;
|
||||
@ -112,6 +113,7 @@ static const char *const update_usage[] =
|
||||
" [-I ign] [-W spec] [files...]\n",
|
||||
"\t-A\tReset any sticky tags/date/kopts.\n",
|
||||
"\t-P\tPrune empty directories.\n",
|
||||
"\t-C\tOverwrite locally modified files with clean repository copies.\n",
|
||||
"\t-d\tBuild directories, like checkout does.\n",
|
||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||
"\t-l\tLocal directory only, no recursion.\n",
|
||||
@ -147,13 +149,16 @@ update (argc, argv)
|
||||
|
||||
/* parse the args */
|
||||
optind = 0;
|
||||
while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
|
||||
while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
aflag = 1;
|
||||
break;
|
||||
case 'C':
|
||||
toss_local_changes = 1;
|
||||
break;
|
||||
case 'I':
|
||||
ign_add (optarg, 0);
|
||||
break;
|
||||
@ -254,6 +259,8 @@ update (argc, argv)
|
||||
send_arg("-f");
|
||||
if (aflag)
|
||||
send_arg("-A");
|
||||
if (toss_local_changes)
|
||||
send_arg("-C");
|
||||
if (update_prune_dirs)
|
||||
send_arg("-P");
|
||||
client_prune_dirs = update_prune_dirs;
|
||||
@ -268,28 +275,35 @@ update (argc, argv)
|
||||
option_with_arg ("-j", join_rev2);
|
||||
wrap_send ();
|
||||
|
||||
/* If the server supports the command "update-patches", that means
|
||||
that it knows how to handle the -u argument to update, which
|
||||
means to send patches instead of complete files.
|
||||
|
||||
We don't send -u if failed_patches != NULL, so that the
|
||||
server doesn't try to send patches which will just fail
|
||||
again. At least currently, the client also clobbers the
|
||||
file and tells the server it is lost, which also will get
|
||||
a full file instead of a patch, but it seems clean to omit
|
||||
-u. */
|
||||
if (failed_patches == NULL)
|
||||
if (failed_patches_count == 0)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
|
||||
/* If the server supports the command "update-patches", that
|
||||
means that it knows how to handle the -u argument to update,
|
||||
which means to send patches instead of complete files.
|
||||
|
||||
We don't send -u if failed_patches != NULL, so that the
|
||||
server doesn't try to send patches which will just fail
|
||||
again. At least currently, the client also clobbers the
|
||||
file and tells the server it is lost, which also will get
|
||||
a full file instead of a patch, but it seems clean to omit
|
||||
-u. */
|
||||
if (supported_request ("update-patches"))
|
||||
send_arg ("-u");
|
||||
}
|
||||
|
||||
if (failed_patches == NULL)
|
||||
{
|
||||
if (update_build_dirs)
|
||||
flags |= SEND_BUILD_DIRS;
|
||||
|
||||
if (toss_local_changes) {
|
||||
flags |= SEND_NO_CONTENTS;
|
||||
flags |= BACKUP_MODIFIED_FILES;
|
||||
}
|
||||
|
||||
/* If noexec, probably could be setting SEND_NO_CONTENTS.
|
||||
Same caveats as for "cvs status" apply. */
|
||||
send_files (argc, argv, local, aflag,
|
||||
update_build_dirs ? SEND_BUILD_DIRS : 0);
|
||||
|
||||
send_files (argc, argv, local, aflag, flags);
|
||||
send_file_names (argc, argv, SEND_EXPAND_WILD);
|
||||
}
|
||||
else
|
||||
@ -313,11 +327,9 @@ update (argc, argv)
|
||||
send_files (failed_patches_count, failed_patches, local,
|
||||
aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
|
||||
send_file_names (failed_patches_count, failed_patches, 0);
|
||||
free_names (&failed_patches_count, failed_patches);
|
||||
}
|
||||
|
||||
failed_patches = NULL;
|
||||
failed_patches_count = 0;
|
||||
|
||||
send_to_server ("update\012", 0);
|
||||
|
||||
status = get_responses_and_close ();
|
||||
@ -336,13 +348,15 @@ update (argc, argv)
|
||||
conflict-and-patch-failed case. */
|
||||
|
||||
if (status != 0
|
||||
&& (failed_patches == NULL || pass > 1))
|
||||
&& (failed_patches_count == 0 || pass > 1))
|
||||
{
|
||||
if (failed_patches_count > 0)
|
||||
free_names (&failed_patches_count, failed_patches);
|
||||
return status;
|
||||
}
|
||||
|
||||
++pass;
|
||||
} while (failed_patches != NULL);
|
||||
} while (failed_patches_count > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -368,15 +382,20 @@ update (argc, argv)
|
||||
error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_clear_entstat (".", Name_Repository (NULL, NULL));
|
||||
{
|
||||
char *repos = Name_Repository (NULL, NULL);
|
||||
server_clear_entstat (".", repos);
|
||||
free (repos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* keep the CVS/Tag file current with the specified arguments */
|
||||
if (aflag || tag || date)
|
||||
{
|
||||
WriteTag ((char *) NULL, tag, date, 0,
|
||||
".", Name_Repository (NULL, NULL));
|
||||
char *repos = Name_Repository (NULL, NULL);
|
||||
WriteTag ((char *) NULL, tag, date, 0, ".", repos);
|
||||
free (repos);
|
||||
rewrite_tag = 1;
|
||||
nonbranch = 0;
|
||||
}
|
||||
@ -486,17 +505,11 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
|
||||
argc, argv, local, which, aflag, 1,
|
||||
preload_update_dir, 1);
|
||||
|
||||
/* see if we need to sleep before returning */
|
||||
/* see if we need to sleep before returning to avoid time-stamp races */
|
||||
if (last_register_time)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
(void) time (&now);
|
||||
if (now != last_register_time) break;
|
||||
sleep (1); /* to avoid time-stamp races */
|
||||
}
|
||||
while (time ((time_t *) NULL) == last_register_time)
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
return (err);
|
||||
@ -643,54 +656,82 @@ update_fileproc (callerdat, finfo)
|
||||
break;
|
||||
case T_MODIFIED: /* locally modified */
|
||||
retval = 0;
|
||||
if (vers->ts_conflict)
|
||||
{
|
||||
char *filestamp;
|
||||
int retcode;
|
||||
|
||||
/*
|
||||
* If the timestamp has changed and no conflict indicators
|
||||
* are found, it isn't a 'C' any more.
|
||||
*/
|
||||
if (toss_local_changes)
|
||||
{
|
||||
char *bakname;
|
||||
bakname = backup_file (finfo->file, vers->vn_user);
|
||||
/* This behavior is sufficiently unexpected to
|
||||
justify overinformativeness, I think. */
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
retcode = vers->ts_conflict[0] != '=';
|
||||
else {
|
||||
filestamp = time_stamp (finfo->file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
}
|
||||
if ((! really_quiet) && (! server_active))
|
||||
#else /* ! SERVER_SUPPORT */
|
||||
if (! really_quiet)
|
||||
#endif /* SERVER_SUPPORT */
|
||||
(void) printf ("(Locally modified %s moved to %s)\n",
|
||||
finfo->file, bakname);
|
||||
free (bakname);
|
||||
|
||||
/* The locally modified file is still present, but
|
||||
it will be overwritten by the repository copy
|
||||
after this. */
|
||||
status = T_CHECKOUT;
|
||||
retval = checkout_file (finfo, vers, 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vers->ts_conflict)
|
||||
{
|
||||
char *filestamp;
|
||||
int retcode;
|
||||
|
||||
/*
|
||||
* If the timestamp has changed and no
|
||||
* conflict indicators are found, it isn't a
|
||||
* 'C' any more.
|
||||
*/
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
retcode = vers->ts_conflict[0] != '=';
|
||||
else
|
||||
{
|
||||
filestamp = time_stamp (finfo->file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
}
|
||||
#else
|
||||
filestamp = time_stamp (finfo->file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
filestamp = time_stamp (finfo->file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
#endif
|
||||
|
||||
if (retcode)
|
||||
{
|
||||
/* The timestamps differ. But if there are conflict
|
||||
markers print 'C' anyway. */
|
||||
retcode = !file_has_markers (finfo);
|
||||
}
|
||||
if (retcode)
|
||||
{
|
||||
/* The timestamps differ. But if there
|
||||
are conflict markers print 'C' anyway. */
|
||||
retcode = !file_has_markers (finfo);
|
||||
}
|
||||
|
||||
if (!retcode)
|
||||
{
|
||||
write_letter (finfo, 'C');
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reregister to clear conflict flag. */
|
||||
Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
|
||||
vers->options, vers->tag,
|
||||
vers->date, (char *)0);
|
||||
}
|
||||
}
|
||||
if (!retval)
|
||||
{
|
||||
write_letter (finfo, 'M');
|
||||
retval = 0;
|
||||
}
|
||||
if (!retcode)
|
||||
{
|
||||
write_letter (finfo, 'C');
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reregister to clear conflict flag. */
|
||||
Register (finfo->entries, finfo->file,
|
||||
vers->vn_rcs, vers->ts_rcs,
|
||||
vers->options, vers->tag,
|
||||
vers->date, (char *)0);
|
||||
}
|
||||
}
|
||||
if (!retval)
|
||||
{
|
||||
write_letter (finfo, 'M');
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef SERVER_SUPPORT
|
||||
case T_PATCH: /* needs patch */
|
||||
@ -930,7 +971,8 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
||||
/* This is a guess. We will rewrite it later
|
||||
via WriteTag. */
|
||||
0,
|
||||
0);
|
||||
0,
|
||||
1);
|
||||
rewrite_tag = 1;
|
||||
nonbranch = 0;
|
||||
Subdir_Register (entries, (char *) NULL, dir);
|
||||
@ -1016,6 +1058,10 @@ update_dirleave_proc (callerdat, dir, err, update_dir, entries)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
/* Delete the ignore list if it hasn't already been done. */
|
||||
if (ignlist)
|
||||
dellist (&ignlist);
|
||||
|
||||
/* If we set the tag or date for a new subdirectory in
|
||||
update_dirent_proc, and we're now done with that subdirectory,
|
||||
undo the tag/date setting. Note that we know that the tag and
|
||||
@ -1061,6 +1107,7 @@ update_dirleave_proc (callerdat, dir, err, update_dir, entries)
|
||||
cvs_output (": Executing '", 0);
|
||||
run_print (stdout);
|
||||
cvs_output ("'\n", 0);
|
||||
cvs_flushout ();
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
}
|
||||
else if (ferror (fp))
|
||||
@ -2051,7 +2098,7 @@ join_file (finfo, vers)
|
||||
Vers_TS *vers;
|
||||
{
|
||||
char *backup;
|
||||
char *options;
|
||||
char *t_options;
|
||||
int status;
|
||||
|
||||
char *rev1;
|
||||
@ -2286,6 +2333,13 @@ join_file (finfo, vers)
|
||||
|
||||
xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
|
||||
|
||||
/* Reset any keyword expansion option. Otherwise, when a
|
||||
command like `cvs update -kk -jT1 -jT2' creates a new file
|
||||
(because a file had the T2 tag, but not T1), the subsequent
|
||||
commit of that just-added file effectively would set the
|
||||
admin `-kk' option for that file in the repository. */
|
||||
options = NULL;
|
||||
|
||||
/* FIXME: If checkout_file fails, we should arrange to
|
||||
return a non-zero exit status. */
|
||||
status = checkout_file (finfo, xvers, 1, 0, 1);
|
||||
@ -2328,11 +2382,11 @@ join_file (finfo, vers)
|
||||
|
||||
if (jdate2 != NULL)
|
||||
error (0, 0,
|
||||
"file %s is present in revision %s as of %s",
|
||||
"file %s does not exist, but is present in revision %s as of %s",
|
||||
finfo->fullname, jrev2, jdate2);
|
||||
else
|
||||
error (0, 0,
|
||||
"file %s is present in revision %s",
|
||||
"file %s does not exist, but is present in revision %s",
|
||||
finfo->fullname, jrev2);
|
||||
|
||||
/* FIXME: Should we arrange to return a non-zero exit status? */
|
||||
@ -2374,10 +2428,10 @@ join_file (finfo, vers)
|
||||
copy_file (finfo->file, backup);
|
||||
xchmod (finfo->file, 1);
|
||||
|
||||
options = vers->options;
|
||||
t_options = vers->options;
|
||||
#if 0
|
||||
if (*options == '\0')
|
||||
options = "-kk"; /* to ignore keyword expansions */
|
||||
if (*t_options == '\0')
|
||||
t_options = "-kk"; /* to ignore keyword expansions */
|
||||
#endif
|
||||
|
||||
/* If the source of the merge is the same as the working file
|
||||
@ -2395,12 +2449,12 @@ join_file (finfo, vers)
|
||||
/* This is because of the worry below about $Name. If that
|
||||
isn't a problem, I suspect this code probably works for
|
||||
text files too. */
|
||||
&& (strcmp (options, "-kb") == 0
|
||||
&& (strcmp (t_options, "-kb") == 0
|
||||
|| wrap_merge_is_copy (finfo->file)))
|
||||
{
|
||||
/* FIXME: what about nametag? What does RCS_merge do with
|
||||
$Name? */
|
||||
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
|
||||
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
|
||||
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
|
||||
status = 2;
|
||||
else
|
||||
@ -2424,7 +2478,7 @@ join_file (finfo, vers)
|
||||
print. */
|
||||
write_letter (finfo, 'U');
|
||||
}
|
||||
else if (strcmp (options, "-kb") == 0
|
||||
else if (strcmp (t_options, "-kb") == 0
|
||||
|| wrap_merge_is_copy (finfo->file)
|
||||
|| special_file_mismatch (finfo, rev1, rev2))
|
||||
{
|
||||
@ -2434,7 +2488,7 @@ join_file (finfo, vers)
|
||||
the two files, and let them resolve it. It is possible
|
||||
that we should require a "touch foo" or similar step before
|
||||
we allow a checkin. */
|
||||
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
|
||||
if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
|
||||
RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
|
||||
status = 2;
|
||||
else
|
||||
@ -2465,7 +2519,7 @@ join_file (finfo, vers)
|
||||
}
|
||||
else
|
||||
status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
|
||||
options, rev1, rev2);
|
||||
t_options, rev1, rev2);
|
||||
|
||||
if (status != 0 && status != 1)
|
||||
{
|
||||
@ -2496,9 +2550,9 @@ join_file (finfo, vers)
|
||||
(void) time (&last_register_time);
|
||||
cp = time_stamp (finfo->file);
|
||||
}
|
||||
Register (finfo->entries, finfo->file, vers->vn_rcs,
|
||||
"Result of merge", vers->options, vers->tag,
|
||||
vers->date, cp);
|
||||
Register (finfo->entries, finfo->file,
|
||||
vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge",
|
||||
vers->options, vers->tag, vers->date, cp);
|
||||
if (cp)
|
||||
free(cp);
|
||||
}
|
||||
@ -2546,8 +2600,8 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
dev_t rev1_dev, rev2_dev;
|
||||
char *rev1_symlink = NULL;
|
||||
char *rev2_symlink = NULL;
|
||||
List *rev1_hardlinks;
|
||||
List *rev2_hardlinks;
|
||||
List *rev1_hardlinks = NULL;
|
||||
List *rev2_hardlinks = NULL;
|
||||
int check_uids, check_gids, check_modes;
|
||||
int result;
|
||||
|
||||
@ -2576,6 +2630,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev1_symlink = xreadlink (finfo->file);
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_ST_RDEV
|
||||
if (CVS_LSTAT (finfo->file, &sb) < 0)
|
||||
error (1, errno, "could not get file information for %s",
|
||||
finfo->file);
|
||||
@ -2584,6 +2639,10 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev1_mode = sb.st_mode;
|
||||
if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
|
||||
rev1_dev = sb.st_rdev;
|
||||
#else
|
||||
error (1, 0, "cannot handle device files on this system (%s)",
|
||||
finfo->file);
|
||||
#endif
|
||||
}
|
||||
rev1_hardlinks = list_linked_files_on_disk (finfo->file);
|
||||
}
|
||||
@ -2649,6 +2708,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev2_symlink = xreadlink (finfo->file);
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_ST_RDEV
|
||||
if (CVS_LSTAT (finfo->file, &sb) < 0)
|
||||
error (1, errno, "could not get file information for %s",
|
||||
finfo->file);
|
||||
@ -2657,6 +2717,10 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev2_mode = sb.st_mode;
|
||||
if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
|
||||
rev2_dev = sb.st_rdev;
|
||||
#else
|
||||
error (1, 0, "cannot handle device files on this system (%s)",
|
||||
finfo->file);
|
||||
#endif
|
||||
}
|
||||
rev2_hardlinks = list_linked_files_on_disk (finfo->file);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user