mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-15 15:06:42 +00:00
Merge rev 1.28 (CAN-2005-0753 / FreeBSD-SA-05:05.cvs fixes),
rev 1.27 ("iso8601" option keyword) revs 1.12/1.10/1.5/1.4 ($CVSHeader$ support) rev 1.2 ($CVS_LOCAL_BRANCH_NUM support for local commit feature of cvsup) into version 1.11.22. Note rev 1.21 ("-D date" checkout bug relating to 1.1.1.1 vs 1.1 revisions), rev 1.13 (allow -D'date' with -r'branch' on a checkout), rev 1.6 (use xstrdup rather than strdup) are fixed in the vendor sources
This commit is contained in:
parent
688d0df11b
commit
d0d4f2ef9b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175278
@ -1,5 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 1992, Brian Berliner and Jeff Polk
|
||||
* Copyright (C) 1986-2005 The Free Software Foundation, Inc.
|
||||
*
|
||||
* Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
|
||||
* and others.
|
||||
*
|
||||
* Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
|
||||
* Portions 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 source distribution.
|
||||
@ -303,8 +309,8 @@ RCS_parse (file, repos)
|
||||
}
|
||||
else if (! existence_error (errno))
|
||||
{
|
||||
free ( rcsfile );
|
||||
error (0, errno, "cannot open %s", rcsfile);
|
||||
free (rcsfile);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -500,8 +506,13 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
|
||||
RCS_addaccess expects nothing but spaces. FIXME:
|
||||
It would be easy and more efficient to change
|
||||
RCS_addaccess. */
|
||||
rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1,
|
||||
(size_t *) NULL);
|
||||
if (rdata->access)
|
||||
{
|
||||
error (0, 0,
|
||||
"Duplicate `access' keyword found in RCS file.");
|
||||
free (rdata->access);
|
||||
}
|
||||
rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1, NULL);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -511,8 +522,15 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
|
||||
if (STREQ (key, "locks"))
|
||||
{
|
||||
if (value != NULL)
|
||||
rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0,
|
||||
(size_t *) NULL);
|
||||
{
|
||||
if (rdata->locks_data)
|
||||
{
|
||||
error (0, 0,
|
||||
"Duplicate `locks' keyword found in RCS file.");
|
||||
free (rdata->locks_data);
|
||||
}
|
||||
rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
|
||||
}
|
||||
if (! rcsbuf_getkey (&rcsbuf, &key, &value))
|
||||
{
|
||||
error (1, 0, "premature end of file reading %s", rcsfile);
|
||||
@ -529,8 +547,16 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
|
||||
if (STREQ (RCSSYMBOLS, key))
|
||||
{
|
||||
if (value != NULL)
|
||||
rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0,
|
||||
(size_t *) NULL);
|
||||
{
|
||||
if (rdata->symbols_data)
|
||||
{
|
||||
error (0, 0,
|
||||
"Duplicate `%s' keyword found in RCS file.",
|
||||
RCSSYMBOLS);
|
||||
free (rdata->symbols_data);
|
||||
}
|
||||
rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -554,8 +580,14 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
|
||||
|
||||
if (STREQ (key, "comment"))
|
||||
{
|
||||
rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0,
|
||||
(size_t *) NULL);
|
||||
if (rdata->comment)
|
||||
{
|
||||
error (0, 0,
|
||||
"warning: duplicate key `%s' in RCS file `%s'",
|
||||
key, rcsfile);
|
||||
free (rdata->comment);
|
||||
}
|
||||
rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
|
||||
continue;
|
||||
}
|
||||
if (rdata->other == NULL)
|
||||
@ -589,14 +621,9 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
|
||||
q->key = vnode->version;
|
||||
|
||||
/* add the nodes to the list */
|
||||
if (addnode (rdata->versions, q) != 0)
|
||||
{
|
||||
#if 0
|
||||
purify_printf("WARNING: Adding duplicate version: %s (%s)\n",
|
||||
q->key, rcsfile);
|
||||
freenode (q);
|
||||
#endif
|
||||
}
|
||||
if (addnode (rdata->versions, q))
|
||||
error (1, 0, "Multiple %s revision deltas found in `%s'",
|
||||
q->key, rcsfile);
|
||||
}
|
||||
|
||||
/* Here KEY and VALUE are whatever caused getdelta to return NULL. */
|
||||
@ -750,10 +777,10 @@ RCS_fully_parse (rcs)
|
||||
break;
|
||||
|
||||
vers = findnode (rcs->versions, key);
|
||||
if (vers == NULL)
|
||||
if (!vers)
|
||||
error (1, 0,
|
||||
"mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, key);
|
||||
"Delta text %s without revision information in `%s'.",
|
||||
key, rcs->path);
|
||||
|
||||
vnode = vers->data;
|
||||
|
||||
@ -2077,6 +2104,8 @@ do_symbols (list, val)
|
||||
char *cp = val;
|
||||
char *tag, *rev;
|
||||
|
||||
assert (cp);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* skip leading whitespace */
|
||||
@ -2119,6 +2148,8 @@ do_locks (list, val)
|
||||
char *cp = val;
|
||||
char *user, *rev;
|
||||
|
||||
assert (cp);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* skip leading whitespace */
|
||||
@ -2303,6 +2334,12 @@ RCS_tag2rev (rcs, tag)
|
||||
* the 0 in some other position -- <dan@gasboy.com>
|
||||
*/
|
||||
pa = strrchr (rev, '.');
|
||||
if (!pa)
|
||||
/* This might happen, for instance, if an RCS file only contained
|
||||
* revisions 2.x and higher, and REV == "1".
|
||||
*/
|
||||
error (1, 0, "revision `%s' does not exist", tag);
|
||||
|
||||
pb = xmalloc (strlen (rev) + 3);
|
||||
*pa++ = 0;
|
||||
(void) sprintf (pb, "%s.%d.%s", rev, RCS_MAGIC_BRANCH, pa);
|
||||
@ -2889,8 +2926,9 @@ RCS_getbranchpoint (rcs, target)
|
||||
|
||||
vp = findnode (rcs->versions, branch);
|
||||
if (vp == NULL)
|
||||
{
|
||||
{
|
||||
error (0, 0, "%s: can't find branch point %s", rcs->path, target);
|
||||
free (branch);
|
||||
return NULL;
|
||||
}
|
||||
rev = vp->data;
|
||||
@ -3024,6 +3062,8 @@ RCS_getdate (rcs, date, force_tag_match)
|
||||
{
|
||||
char *date_1_1 = vers->date;
|
||||
|
||||
assert (p->data != NULL);
|
||||
|
||||
vers = p->data;
|
||||
if (RCS_datecmp (vers->date, date_1_1) != 0)
|
||||
return xstrdup ("1.1");
|
||||
@ -3292,7 +3332,7 @@ translate_symtag (rcs, tag)
|
||||
if (rcs->symbols_data != NULL)
|
||||
{
|
||||
size_t len;
|
||||
char *cp;
|
||||
char *cp, *last;
|
||||
|
||||
/* Look through the RCS symbols information. This is like
|
||||
do_symbols, but we don't add the information to a list. In
|
||||
@ -3301,8 +3341,16 @@ translate_symtag (rcs, tag)
|
||||
|
||||
len = strlen (tag);
|
||||
cp = rcs->symbols_data;
|
||||
/* Keeping track of LAST below isn't strictly necessary, now that tags
|
||||
* should be parsed for validity before they are accepted, but tags
|
||||
* with spaces used to cause the code below to loop indefintely, so
|
||||
* I have corrected for that. Now, in the event that I missed
|
||||
* something, the server cannot be hung. -DRP
|
||||
*/
|
||||
last = NULL;
|
||||
while ((cp = strchr (cp, tag[0])) != NULL)
|
||||
{
|
||||
if (cp == last) break;
|
||||
if ((cp == rcs->symbols_data || whitespace (cp[-1]))
|
||||
&& strncmp (cp, tag, len) == 0
|
||||
&& cp[len] == ':')
|
||||
@ -3325,6 +3373,7 @@ translate_symtag (rcs, tag)
|
||||
++cp;
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
last = cp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3452,6 +3501,8 @@ RCS_isdead (rcs, tag)
|
||||
Node *p;
|
||||
RCSVers *version;
|
||||
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
|
||||
|
||||
@ -3931,6 +3982,13 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
|
||||
if (*snl == '\n')
|
||||
++cnl;
|
||||
|
||||
/* If the log message did not end in a newline, increment
|
||||
* the newline count so we have space for the extra leader.
|
||||
* Failure to do so results in a buffer overrun.
|
||||
*/
|
||||
if (loglen && snl[-1] != '\n')
|
||||
++cnl;
|
||||
|
||||
date = printable_date (ver->date);
|
||||
sub = xrealloc (sub,
|
||||
(sublen
|
||||
@ -3939,6 +3997,10 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
|
||||
+ strlen (date)
|
||||
+ strlen (ver->author)
|
||||
+ loglen
|
||||
/* Use CNL + 2 below: One leader for each log
|
||||
* line, plus the Revision/Author/Date line,
|
||||
* plus a trailing blank line.
|
||||
*/
|
||||
+ (cnl + 2) * leader_len
|
||||
+ 20));
|
||||
if (expand != KFLAG_V)
|
||||
@ -3978,6 +4040,14 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
|
||||
++slnl;
|
||||
memcpy (sub + sublen, sl, slnl - sl);
|
||||
sublen += slnl - sl;
|
||||
if (slnl == logend && slnl[-1] != '\n')
|
||||
{
|
||||
/* There was no EOL at the end of the log message. Add
|
||||
* one.
|
||||
*/
|
||||
sub[sublen] = '\n';
|
||||
++sublen;
|
||||
}
|
||||
sl = slnl;
|
||||
}
|
||||
}
|
||||
@ -4096,7 +4166,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
|
||||
Otherwise, if WORKFILE is NULL, check out the revision to SOUT. If
|
||||
SOUT is RUN_TTY, then write the contents of the revision to
|
||||
standard output. When using SOUT, the output is generally a
|
||||
temporary file; don't bother to get the file modes correct.
|
||||
temporary file; don't bother to get the file modes correct. When
|
||||
NOEXEC is set, WORKFILEs are not written but SOUTs are.
|
||||
|
||||
REV is the numeric revision to check out. It may be NULL, which
|
||||
means to check out the head of the default branch.
|
||||
@ -4171,7 +4242,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
|
||||
|
||||
assert (rev == NULL || isdigit ((unsigned char) *rev));
|
||||
|
||||
if (noexec && workfile != NULL)
|
||||
if (noexec && !server_active && workfile != NULL)
|
||||
return 0;
|
||||
|
||||
assert (sout == RUN_TTY || workfile == NULL);
|
||||
@ -4201,10 +4272,23 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
|
||||
gothead = 0;
|
||||
if (! rcsbuf_getrevnum (&rcsbuf, &key))
|
||||
error (1, 0, "unexpected EOF reading %s", rcs->path);
|
||||
|
||||
if (!STREQ (rcs->head, key))
|
||||
error (1, 0, "Expected head revision %s, found %s.",
|
||||
rcs->head, key);
|
||||
|
||||
while (rcsbuf_getkey (&rcsbuf, &key, &value))
|
||||
{
|
||||
if (STREQ (key, "log"))
|
||||
{
|
||||
if (log)
|
||||
{
|
||||
error (0, 0,
|
||||
"Duplicate log keyword found for head revision in RCS file.");
|
||||
free (log);
|
||||
}
|
||||
log = rcsbuf_valcopy (&rcsbuf, value, 0, &loglen);
|
||||
}
|
||||
else if (STREQ (key, "text"))
|
||||
{
|
||||
gothead = 1;
|
||||
@ -4704,6 +4788,7 @@ RCS_findlock_or_tip (rcs)
|
||||
char *user = getcaller();
|
||||
Node *lock, *p;
|
||||
List *locklist;
|
||||
char *defaultrev = NULL;
|
||||
|
||||
/* Find unique delta locked by caller. This code is very similar
|
||||
to the code in RCS_unlock -- perhaps it could be abstracted
|
||||
@ -4749,7 +4834,17 @@ RCS_findlock_or_tip (rcs)
|
||||
those error checks are to make users lock before a checkin, and we do
|
||||
that in other ways if at all anyway (e.g. rcslock.pl). */
|
||||
|
||||
p = findnode (rcs->versions, RCS_getbranch (rcs, rcs->branch, 0));
|
||||
defaultrev = RCS_getbranch (rcs, rcs->branch, 0);
|
||||
p = findnode (rcs->versions, defaultrev);
|
||||
if (defaultrev != NULL)
|
||||
free (defaultrev);
|
||||
if (!p)
|
||||
{
|
||||
error (0, 0, "RCS file `%s' does not contain its default revision.",
|
||||
rcs->path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
@ -4863,6 +4958,8 @@ RCS_addbranch (rcs, branch)
|
||||
Node *marker;
|
||||
RCSVers *branchnode;
|
||||
|
||||
assert (branch);
|
||||
|
||||
/* Append to end by default. */
|
||||
marker = NULL;
|
||||
|
||||
@ -4981,18 +5078,21 @@ RCS_addbranch (rcs, branch)
|
||||
or zero for success. */
|
||||
|
||||
int
|
||||
RCS_checkin (rcs, workfile_in, message, rev, flags)
|
||||
RCS_checkin (rcs, workfile_in, message, rev, citime, flags)
|
||||
RCSNode *rcs;
|
||||
const char *workfile_in;
|
||||
const char *message;
|
||||
const char *rev;
|
||||
time_t citime;
|
||||
int flags;
|
||||
{
|
||||
RCSVers *delta, *commitpt;
|
||||
Deltatext *dtext;
|
||||
Node *nodep;
|
||||
char *tmpfile, *changefile;
|
||||
char *diffopts;
|
||||
int dargc = 0;
|
||||
size_t darg_allocated = 0;
|
||||
char **dargv = NULL;
|
||||
size_t bufsize;
|
||||
int status, checkin_quiet;
|
||||
struct tm *ftm;
|
||||
@ -5014,6 +5114,7 @@ RCS_checkin (rcs, workfile_in, message, rev, flags)
|
||||
{
|
||||
char *p;
|
||||
int extlen = strlen (RCSEXT);
|
||||
assert (rcs->path);
|
||||
workfile = xstrdup (last_component (rcs->path));
|
||||
p = workfile + (strlen (workfile) - extlen);
|
||||
assert (strncmp (p, RCSEXT, extlen) == 0);
|
||||
@ -5048,6 +5149,8 @@ RCS_checkin (rcs, workfile_in, message, rev, flags)
|
||||
}
|
||||
modtime = ws.st_mtime;
|
||||
}
|
||||
else if (flags & RCS_FLAGS_USETIME)
|
||||
modtime = citime;
|
||||
else
|
||||
(void) time (&modtime);
|
||||
ftm = gmtime (&modtime);
|
||||
@ -5289,6 +5392,7 @@ workfile);
|
||||
if (dots == 0)
|
||||
{
|
||||
tip = xstrdup (rcs->head);
|
||||
assert (tip != NULL);
|
||||
if (atoi (tip) != atoi (branch))
|
||||
{
|
||||
newrev = (char *) xrealloc (newrev, strlen (newrev) + 3);
|
||||
@ -5418,9 +5522,10 @@ workfile);
|
||||
|
||||
/* Diff options should include --binary if the RCS file has -kb set
|
||||
in its `expand' field. */
|
||||
diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
|
||||
? "-a -n --binary"
|
||||
: "-a -n");
|
||||
run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
|
||||
run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
|
||||
if (rcs->expand && STREQ (rcs->expand, "b"))
|
||||
run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary");
|
||||
|
||||
if (STREQ (commitpt->version, rcs->head) &&
|
||||
numdots (delta->version) == 1)
|
||||
@ -5443,7 +5548,8 @@ workfile);
|
||||
memset (commitpt->text, 0, sizeof (Deltatext));
|
||||
|
||||
bufsize = 0;
|
||||
switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
|
||||
switch (diff_exec (workfile, tmpfile, NULL, NULL,
|
||||
dargc, dargv, changefile))
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
@ -5491,7 +5597,8 @@ workfile);
|
||||
/* This file is not being inserted at the head, but on a side
|
||||
branch somewhere. Make a diff from the previous revision
|
||||
to the working file. */
|
||||
switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
|
||||
switch (diff_exec (tmpfile, workfile, NULL, NULL,
|
||||
dargc, dargv, changefile))
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
@ -5518,6 +5625,9 @@ workfile);
|
||||
}
|
||||
}
|
||||
|
||||
run_arg_free_p (dargc, dargv);
|
||||
free (dargv);
|
||||
|
||||
/* Update DELTA linkage. It is important not to do this before
|
||||
the very end of RCS_checkin; if an error arises that forces
|
||||
us to abort checking in, we must not have malformed deltas
|
||||
@ -5590,7 +5700,13 @@ workfile);
|
||||
|
||||
freedeltatext (dtext);
|
||||
if (status != 0)
|
||||
{
|
||||
/* If delta has not been added to a List, then freeing the Node key
|
||||
* won't free delta->version.
|
||||
*/
|
||||
if (delta->version) free (delta->version);
|
||||
free_rcsvers_contents (delta);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -6292,7 +6408,12 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
|
||||
/* A range consisting of a branch number means the latest revision
|
||||
on that branch. */
|
||||
if (RCS_isbranch (rcs, rev1) && STREQ (rev1, rev2))
|
||||
rev1 = rev2 = RCS_getbranch (rcs, rev1, 0);
|
||||
{
|
||||
char *tmp = RCS_getbranch (rcs, rev1, 0);
|
||||
free (rev1);
|
||||
free (rev2);
|
||||
rev1 = rev2 = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure REV1 and REV2 are ordered correctly (in the
|
||||
@ -6580,6 +6701,10 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
|
||||
}
|
||||
else
|
||||
{
|
||||
int dargc = 0;
|
||||
size_t darg_allocated = 0;
|
||||
char **dargv = NULL;
|
||||
|
||||
beforefile = cvs_temp_name();
|
||||
status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
|
||||
(RCSCHECKOUTPROC)0, NULL);
|
||||
@ -6587,7 +6712,12 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
|
||||
goto delrev_done;
|
||||
|
||||
outfile = cvs_temp_name();
|
||||
status = diff_exec (beforefile, afterfile, NULL, NULL, "-an", outfile);
|
||||
run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
|
||||
run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
|
||||
status = diff_exec (beforefile, afterfile, NULL, NULL,
|
||||
dargc, dargv, outfile);
|
||||
run_arg_free_p (dargc, dargv);
|
||||
free (dargv);
|
||||
|
||||
if (status == 2)
|
||||
{
|
||||
@ -6685,7 +6815,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
|
||||
delrev_done:
|
||||
if (rev1 != NULL)
|
||||
free (rev1);
|
||||
if (rev2 != NULL)
|
||||
if (rev2 && rev2 != rev1)
|
||||
free (rev2);
|
||||
if (branchpoint != NULL)
|
||||
free (branchpoint);
|
||||
@ -7046,6 +7176,7 @@ apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers)
|
||||
};
|
||||
struct deltafrag *dfhead;
|
||||
struct deltafrag *df;
|
||||
int err;
|
||||
|
||||
dfhead = NULL;
|
||||
for (p = diffbuf; p != NULL && p < diffbuf + difflen; )
|
||||
@ -7111,33 +7242,39 @@ apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers)
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
for (df = dfhead; df != NULL;)
|
||||
{
|
||||
unsigned int ln;
|
||||
|
||||
switch (df->type)
|
||||
{
|
||||
case FRAG_ADD:
|
||||
if (! linevector_add (lines, df->new_lines, df->len, addvers,
|
||||
df->pos))
|
||||
return 0;
|
||||
break;
|
||||
case FRAG_DELETE:
|
||||
if (df->pos > lines->nlines
|
||||
|| df->pos + df->nlines > lines->nlines)
|
||||
return 0;
|
||||
if (delvers != NULL)
|
||||
for (ln = df->pos; ln < df->pos + df->nlines; ++ln)
|
||||
lines->vector[ln]->vers = delvers;
|
||||
linevector_delete (lines, df->pos, df->nlines);
|
||||
break;
|
||||
}
|
||||
/* Once an error is encountered, just free the rest of the list and
|
||||
* return.
|
||||
*/
|
||||
if (!err)
|
||||
switch (df->type)
|
||||
{
|
||||
case FRAG_ADD:
|
||||
if (! linevector_add (lines, df->new_lines, df->len, addvers,
|
||||
df->pos))
|
||||
err = 1;
|
||||
break;
|
||||
case FRAG_DELETE:
|
||||
if (df->pos > lines->nlines
|
||||
|| df->pos + df->nlines > lines->nlines)
|
||||
return 0;
|
||||
if (delvers != NULL)
|
||||
for (ln = df->pos; ln < df->pos + df->nlines; ++ln)
|
||||
lines->vector[ln]->vers = delvers;
|
||||
linevector_delete (lines, df->pos, df->nlines);
|
||||
break;
|
||||
}
|
||||
|
||||
df = df->next;
|
||||
free (dfhead);
|
||||
dfhead = df;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return !err;
|
||||
}
|
||||
|
||||
/* Apply an RCS change text to a buffer. The function name starts
|
||||
@ -7255,12 +7392,18 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
struct linevector trunklines;
|
||||
int foundhead;
|
||||
|
||||
assert (version);
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf_local);
|
||||
rcsbuf = &rcsbuf_local;
|
||||
}
|
||||
|
||||
assert (rcsbuf);
|
||||
|
||||
if (log) *log = NULL;
|
||||
|
||||
ishead = 1;
|
||||
vers = NULL;
|
||||
prev_vers = NULL;
|
||||
@ -7288,6 +7431,13 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
if (! rcsbuf_getrevnum (rcsbuf, &key))
|
||||
error (1, 0, "unexpected EOF reading RCS file %s", rcs->path);
|
||||
|
||||
/* look up the revision */
|
||||
node = findnode (rcs->versions, key);
|
||||
if (!node)
|
||||
error (1, 0,
|
||||
"Delta text %s without revision information in `%s'.",
|
||||
key, rcs->path);
|
||||
|
||||
if (next != NULL && ! STREQ (next, key))
|
||||
{
|
||||
/* This is not the next version we need. It is a branch
|
||||
@ -7299,13 +7449,6 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
{
|
||||
isnext = 1;
|
||||
|
||||
/* look up the revision */
|
||||
node = findnode (rcs->versions, key);
|
||||
if (node == NULL)
|
||||
error (1, 0,
|
||||
"mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, key);
|
||||
|
||||
/* Stash the previous version. */
|
||||
prev_vers = vers;
|
||||
|
||||
@ -7331,6 +7474,12 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
&& STREQ (key, "log")
|
||||
&& STREQ (branchversion, version))
|
||||
{
|
||||
if (*log != NULL)
|
||||
{
|
||||
error (0, 0, "Duplicate `log' keyword in RCS file (`%s').",
|
||||
rcs->path);
|
||||
free (*log);
|
||||
}
|
||||
*log = rcsbuf_valcopy (rcsbuf, value, 0, loglen);
|
||||
}
|
||||
|
||||
@ -7412,6 +7561,9 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
if (vers->branches == NULL)
|
||||
error (1, 0, "missing expected branches in %s",
|
||||
rcs->path);
|
||||
if (!cpversion)
|
||||
error (1, 0, "Invalid revision number in `%s'.",
|
||||
rcs->path);
|
||||
*cpversion = '.';
|
||||
++cpversion;
|
||||
cpversion = strchr (cpversion, '.');
|
||||
@ -7797,9 +7949,10 @@ RCS_getdeltatext (rcs, fp, rcsbuf)
|
||||
}
|
||||
|
||||
p = findnode (rcs->versions, num);
|
||||
if (p == NULL)
|
||||
error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, num);
|
||||
if (!p)
|
||||
error (1, 0,
|
||||
"Delta text %s without revision information in `%s'.",
|
||||
num, rcs->path);
|
||||
|
||||
d = (Deltatext *) xmalloc (sizeof (Deltatext));
|
||||
d->version = xstrdup (num);
|
||||
@ -8064,31 +8217,65 @@ RCS_putdtree (rcs, rev, fp)
|
||||
RCSVers *versp;
|
||||
Node *p, *branch;
|
||||
|
||||
/* Previously, this function used a recursive implementation, but
|
||||
if the trunk has a huge number of revisions and the program
|
||||
stack is not big, a stack overflow could occur, so this
|
||||
nonrecursive version was developed to be more safe. */
|
||||
Node *branchlist, *onebranch;
|
||||
List *branches;
|
||||
List *onebranchlist;
|
||||
|
||||
if (rev == NULL)
|
||||
return;
|
||||
|
||||
/* Find the delta node for this revision. */
|
||||
p = findnode (rcs->versions, rev);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (1, 0,
|
||||
"error parsing repository file %s, file may be corrupt.",
|
||||
rcs->path);
|
||||
}
|
||||
|
||||
versp = p->data;
|
||||
branches = getlist();
|
||||
|
||||
/* Print the delta node and recurse on its `next' node. This prints
|
||||
the trunk. If there are any branches printed on this revision,
|
||||
print those trunks as well. */
|
||||
putdelta (versp, fp);
|
||||
RCS_putdtree (rcs, versp->next, fp);
|
||||
if (versp->branches != NULL)
|
||||
for (; rev != NULL;)
|
||||
{
|
||||
branch = versp->branches->list;
|
||||
for (p = branch->next; p != branch; p = p->next)
|
||||
RCS_putdtree (rcs, p->key, fp);
|
||||
/* Find the delta node for this revision. */
|
||||
p = findnode (rcs->versions, rev);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (1, 0,
|
||||
"error parsing repository file %s, file may be corrupt.",
|
||||
rcs->path);
|
||||
}
|
||||
|
||||
versp = p->data;
|
||||
|
||||
/* Print the delta node and go for its `next' node. This
|
||||
prints the trunk. If there are any branches printed on this
|
||||
revision, mark we have some. */
|
||||
putdelta (versp, fp);
|
||||
/* Store branch information into branch list so to write its
|
||||
trunk afterwards */
|
||||
if (versp->branches != NULL)
|
||||
{
|
||||
branch = getnode();
|
||||
branch->data = versp->branches;
|
||||
|
||||
addnode(branches, branch);
|
||||
}
|
||||
|
||||
rev = versp->next;
|
||||
}
|
||||
|
||||
/* If there are any branches printed on this revision,
|
||||
print those trunks as well. */
|
||||
branchlist = branches->list;
|
||||
for (branch = branchlist->next;
|
||||
branch != branchlist;
|
||||
branch = branch->next)
|
||||
{
|
||||
onebranchlist = (List *)(branch->data);
|
||||
onebranch = onebranchlist->list;
|
||||
for (p = onebranch->next; p != onebranch; p = p->next)
|
||||
RCS_putdtree (rcs, p->key, fp);
|
||||
|
||||
branch->data = NULL; /* so to prevent its freeing on dellist */
|
||||
}
|
||||
|
||||
dellist(&branches);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -8193,6 +8380,11 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
|
||||
}
|
||||
|
||||
np = findnode (rcs->versions, dtext->version);
|
||||
if (!np)
|
||||
error (1, 0,
|
||||
"Delta text %s without revision information in `%s'.",
|
||||
dtext->version, rcs->path);
|
||||
|
||||
dadmin = np->data;
|
||||
|
||||
/* If this revision has been outdated, just skip it. */
|
||||
@ -8480,6 +8672,28 @@ rcs_internal_unlockfile (fp, rcsfile)
|
||||
real solution is to check each call to fprintf rather than waiting
|
||||
until the end like this. */
|
||||
error (1, errno, "error writing to lock file %s", rcs_lockfile);
|
||||
|
||||
/* Flush and sync the file, or the user may be told the commit completed,
|
||||
* while a server crash/power failure could still cause the data to be
|
||||
* lost.
|
||||
*
|
||||
* Invoking rename(",<file>," , "<file>,v") on Linux and almost all UNIXs
|
||||
* only flushes the inode for the target file to disk, it does not
|
||||
* guarantee flush of the kernel buffers allocated for the ,<file>,.
|
||||
* Depending upon the load on the machine, the Linux kernel's flush daemon
|
||||
* process may not flush for a while. In the meantime the CVS transaction
|
||||
* could have been declared committed to the end CVS user (CVS process has
|
||||
* returned the final "OK"). If the machine crashes prior to syncing the
|
||||
* changes to disk, the committed transaction can be lost.
|
||||
*/
|
||||
if (fflush (fp) != 0)
|
||||
error (1, errno, "error flushing file `%s' to kernel buffers",
|
||||
rcs_lockfile);
|
||||
#ifdef HAVE_FSYNC
|
||||
if (fsync (rcs_lockfd) < 0)
|
||||
error (1, errno, "error fsyncing file `%s'", rcs_lockfile);
|
||||
#endif
|
||||
|
||||
if (fclose (fp) == EOF)
|
||||
error (1, errno, "error closing lock file %s", rcs_lockfile);
|
||||
rcs_lockfd = -1;
|
||||
@ -8534,6 +8748,8 @@ RCS_rewrite (rcs, newdtext, insertpt)
|
||||
FILE *fin, *fout;
|
||||
struct rcsbuffer rcsbufin;
|
||||
|
||||
assert (rcs);
|
||||
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user