Deleted Added
full compact
rcs.c (109660) rcs.c (128269)
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 *
4 * You may distribute under the terms of the GNU General Public License as
5 * specified in the README file that comes with the CVS source distribution.
6 *
7 * The routines contained in this file do all the rcs file parsing and
8 * manipulation
9 *
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 *
4 * You may distribute under the terms of the GNU General Public License as
5 * specified in the README file that comes with the CVS source distribution.
6 *
7 * The routines contained in this file do all the rcs file parsing and
8 * manipulation
9 *
10 * $FreeBSD: head/contrib/cvs/src/rcs.c 109660 2003-01-21 22:01:38Z peter $
10 * $FreeBSD: head/contrib/cvs/src/rcs.c 128269 2004-04-15 01:17:28Z peter $
11 */
12
13#include <assert.h>
14#include "cvs.h"
15#include "edit.h"
16#include "hardlink.h"
17
18/* These need to be source after cvs.h or HAVE_MMAP won't be set... */

--- 40 unchanged lines hidden (view full) ---

59 int at_string;
60 /* The number of embedded '@' characters in an '@' string. If
61 this is non-zero, we must search the string for pairs of '@'
62 and convert them to a single '@'. */
63 int embedded_at;
64};
65
66static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
11 */
12
13#include <assert.h>
14#include "cvs.h"
15#include "edit.h"
16#include "hardlink.h"
17
18/* These need to be source after cvs.h or HAVE_MMAP won't be set... */

--- 40 unchanged lines hidden (view full) ---

59 int at_string;
60 /* The number of embedded '@' characters in an '@' string. If
61 this is non-zero, we must search the string for pairs of '@'
62 and convert them to a single '@'. */
63 int embedded_at;
64};
65
66static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
67static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
67static char *RCS_getdatebranch PROTO((RCSNode * rcs, const char *date,
68 const char *branch));
68static void rcsbuf_open PROTO ((struct rcsbuffer *, FILE *fp,
69 const char *filename, unsigned long pos));
70static void rcsbuf_close PROTO ((struct rcsbuffer *));
71static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
72 char **valp));
73static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
74#ifndef HAVE_MMAP
75static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,

--- 46 unchanged lines hidden (view full) ---

122static int putsymbol_proc PROTO ((Node *, void *));
123static void RCS_copydeltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *,
124 FILE *, Deltatext *, char *));
125static int count_delta_actions PROTO ((Node *, void *));
126static void putdeltatext PROTO ((FILE *, Deltatext *));
127
128static FILE *rcs_internal_lockfile PROTO ((char *));
129static void rcs_internal_unlockfile PROTO ((FILE *, char *));
69static void rcsbuf_open PROTO ((struct rcsbuffer *, FILE *fp,
70 const char *filename, unsigned long pos));
71static void rcsbuf_close PROTO ((struct rcsbuffer *));
72static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
73 char **valp));
74static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
75#ifndef HAVE_MMAP
76static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,

--- 46 unchanged lines hidden (view full) ---

123static int putsymbol_proc PROTO ((Node *, void *));
124static void RCS_copydeltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *,
125 FILE *, Deltatext *, char *));
126static int count_delta_actions PROTO ((Node *, void *));
127static void putdeltatext PROTO ((FILE *, Deltatext *));
128
129static FILE *rcs_internal_lockfile PROTO ((char *));
130static void rcs_internal_unlockfile PROTO ((FILE *, char *));
130static char *rcs_lockfilename PROTO ((char *));
131static char *rcs_lockfilename PROTO ((const char *));
131
132/* The RCS file reading functions are called a lot, and they do some
133 string comparisons. This macro speeds things up a bit by skipping
134 the function call when the first characters are different. It
135 evaluates its arguments multiple times. */
132
133/* The RCS file reading functions are called a lot, and they do some
134 string comparisons. This macro speeds things up a bit by skipping
135 the function call when the first characters are different. It
136 evaluates its arguments multiple times. */
136#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
137#define STREQ(a, b) (*(char *)(a) == *(char *)(b) && strcmp ((a), (b)) == 0)
137
138static char * getfullCVSname PROTO ((char *, char **));
139
140/*
141 * We don't want to use isspace() from the C library because:
142 *
143 * 1. The definition of "whitespace" in RCS files includes ASCII
144 * backspace, but the C locale doesn't.

--- 19 unchanged lines hidden (view full) ---

164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
165};
166
167#define whitespace(c) (spacetab[(unsigned char)c] != 0)
168
169static char *rcs_lockfile;
170static int rcs_lockfd = -1;
171
138
139static char * getfullCVSname PROTO ((char *, char **));
140
141/*
142 * We don't want to use isspace() from the C library because:
143 *
144 * 1. The definition of "whitespace" in RCS files includes ASCII
145 * backspace, but the C locale doesn't.

--- 19 unchanged lines hidden (view full) ---

165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
166};
167
168#define whitespace(c) (spacetab[(unsigned char)c] != 0)
169
170static char *rcs_lockfile;
171static int rcs_lockfd = -1;
172
173
174
175/*
176 * char *
177 * locate_rcs ( const char* file, const char *repository , int *inattic )
178 *
179 * Find an RCS file in the repository, case insensitively when the cased name
180 * doesn't exist, we are running as the server, and a client has asked us to
181 * ignore case.
182 *
183 * Most parts of CVS will want to rely instead on RCS_parse which calls this
184 * function and is called by recurse.c which then puts the result in useful
185 * places like the rcs field of struct file_info.
186 *
187 * INPUTS
188 *
189 * repository the repository (including the directory)
190 * file the filename within that directory (without RCSEXT).
191 * inattic NULL or a pointer to the output boolean
192 *
193 * OUTPUTS
194 *
195 * inattic If this input was non-null, the destination will be
196 * set to true if the file was found in the attic or
197 * false if not. If no RCS file is found, this value
198 * is undefined.
199 *
200 * RETURNS
201 *
202 * a newly-malloc'd array containing the absolute pathname of the RCS
203 * file that was found or NULL when none was found.
204 *
205 * ERRORS
206 *
207 * errno can be set by the return value of the final call to
208 * locate_file_in_dir(). This should resolve to the system's existence error
209 * value (sometime ENOENT) if the Attic directory did not exist and ENOENT if
210 * the Attic was found but no matching files were found in the Attic or its
211 * parent.
212 */
213static char *
214locate_rcs (repository, file, inattic)
215 const char *repository;
216 const char *file;
217 int *inattic;
218{
219 char *retval;
220
221 /* First, try to find the file as cased. */
222 retval = xmalloc (strlen (repository)
223 + sizeof (CVSATTIC)
224 + strlen (file)
225 + sizeof (RCSEXT)
226 + 3);
227 sprintf (retval, "%s/%s%s", repository, file, RCSEXT);
228 if (isreadable (retval))
229 {
230 if (inattic)
231 *inattic = 0;
232 return retval;
233 }
234 sprintf (retval, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
235 if (isreadable (retval))
236 {
237 if (inattic)
238 *inattic = 1;
239 return retval;
240 }
241 free (retval);
242
243 return NULL;
244}
245
246
247
172/* A few generic thoughts on error handling, in particular the
173 printing of unexpected characters that we find in the RCS file
174 (that is, why we use '\x%x' rather than %c or some such).
175
176 * Avoiding %c means we don't have to worry about what is printable
177 and other such stuff. In error handling, often better to keep it
178 simple.
179

--- 14 unchanged lines hidden (view full) ---

194 the current behavior). */
195RCSNode *
196RCS_parse (file, repos)
197 const char *file;
198 const char *repos;
199{
200 RCSNode *rcs;
201 FILE *fp;
248/* A few generic thoughts on error handling, in particular the
249 printing of unexpected characters that we find in the RCS file
250 (that is, why we use '\x%x' rather than %c or some such).
251
252 * Avoiding %c means we don't have to worry about what is printable
253 and other such stuff. In error handling, often better to keep it
254 simple.
255

--- 14 unchanged lines hidden (view full) ---

270 the current behavior). */
271RCSNode *
272RCS_parse (file, repos)
273 const char *file;
274 const char *repos;
275{
276 RCSNode *rcs;
277 FILE *fp;
202 RCSNode *retval;
278 RCSNode *retval = NULL;
203 char *rcsfile;
279 char *rcsfile;
280 int inattic;
204
205 /* We're creating a new RCSNode, so there is no hope of finding it
206 in the cache. */
207 rcsbuf_cache_close ();
208
281
282 /* We're creating a new RCSNode, so there is no hope of finding it
283 in the cache. */
284 rcsbuf_cache_close ();
285
209 rcsfile = xmalloc (strlen (repos) + strlen (file)
210 + sizeof (RCSEXT) + sizeof (CVSATTIC) + 10);
211 (void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
212 if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL)
286 if ((rcsfile = locate_rcs (repos, file, &inattic)) == NULL)
213 {
287 {
214 rcs = RCS_parsercsfile_i(fp, rcsfile);
215 if (rcs != NULL)
216 rcs->flags |= VALID;
217
218 retval = rcs;
219 goto out;
288 /* Handle the error cases */
220 }
289 }
221 else if (! existence_error (errno))
290 else if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL)
222 {
291 {
223 error (0, errno, "cannot open %s", rcsfile);
224 retval = NULL;
225 goto out;
226 }
227
228 (void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
229 if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL)
230 {
231 rcs = RCS_parsercsfile_i(fp, rcsfile);
232 if (rcs != NULL)
292 rcs = RCS_parsercsfile_i(fp, rcsfile);
293 if (rcs != NULL)
233 {
234 rcs->flags |= INATTIC;
294 {
235 rcs->flags |= VALID;
295 rcs->flags |= VALID;
296 if ( inattic )
297 rcs->flags |= INATTIC;
236 }
237
298 }
299
300 free ( rcsfile );
238 retval = rcs;
301 retval = rcs;
239 goto out;
240 }
241 else if (! existence_error (errno))
242 {
302 }
303 else if (! existence_error (errno))
304 {
305 free ( rcsfile );
243 error (0, errno, "cannot open %s", rcsfile);
306 error (0, errno, "cannot open %s", rcsfile);
244 retval = NULL;
245 goto out;
246 }
307 }
247#if defined (SERVER_SUPPORT) && !defined (FILENAMES_CASE_INSENSITIVE)
248 else if (ign_case)
249 {
250 int status;
251 char *found_path;
252
308
253 /* The client might be asking for a file which we do have
254 (which the client doesn't know about), but for which the
255 filename case differs. We only consider this case if the
256 regular CVS_FOPENs fail, because fopen_case is such an
257 expensive call. */
258 (void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
259 status = fopen_case (rcsfile, "rb", &fp, &found_path);
260 if (status == 0)
261 {
262 rcs = RCS_parsercsfile_i (fp, rcsfile);
263 if (rcs != NULL)
264 rcs->flags |= VALID;
265
266 free (rcs->path);
267 rcs->path = found_path;
268 retval = rcs;
269 goto out;
270 }
271 else if (! existence_error (status))
272 {
273 error (0, status, "cannot open %s", rcsfile);
274 retval = NULL;
275 goto out;
276 }
277
278 (void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
279 status = fopen_case (rcsfile, "rb", &fp, &found_path);
280 if (status == 0)
281 {
282 rcs = RCS_parsercsfile_i (fp, rcsfile);
283 if (rcs != NULL)
284 {
285 rcs->flags |= INATTIC;
286 rcs->flags |= VALID;
287 }
288
289 free (rcs->path);
290 rcs->path = found_path;
291 retval = rcs;
292 goto out;
293 }
294 else if (! existence_error (status))
295 {
296 error (0, status, "cannot open %s", rcsfile);
297 retval = NULL;
298 goto out;
299 }
300 }
301#endif
302 retval = NULL;
303
304 out:
305 free (rcsfile);
306
307 return retval;
308}
309
310/*
311 * Parse a specific rcsfile.
312 */
313RCSNode *
314RCS_parsercsfile (rcsfile)
309 return retval;
310}
311
312/*
313 * Parse a specific rcsfile.
314 */
315RCSNode *
316RCS_parsercsfile (rcsfile)
315 char *rcsfile;
317 const char *rcsfile;
316{
317 FILE *fp;
318 RCSNode *rcs;
319
320 /* We're creating a new RCSNode, so there is no hope of finding it
321 in the cache. */
322 rcsbuf_cache_close ();
323

--- 5 unchanged lines hidden (view full) ---

329 }
330
331 rcs = RCS_parsercsfile_i (fp, rcsfile);
332
333 return (rcs);
334}
335
336
318{
319 FILE *fp;
320 RCSNode *rcs;
321
322 /* We're creating a new RCSNode, so there is no hope of finding it
323 in the cache. */
324 rcsbuf_cache_close ();
325

--- 5 unchanged lines hidden (view full) ---

331 }
332
333 rcs = RCS_parsercsfile_i (fp, rcsfile);
334
335 return (rcs);
336}
337
338
339
337/*
338 */
339static RCSNode *
340RCS_parsercsfile_i (fp, rcsfile)
341 FILE *fp;
342 const char *rcsfile;
343{
344 RCSNode *rdata;
345 struct rcsbuffer rcsbuf;
346 char *key, *value;
347
348 /* make a node */
349 rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
340/*
341 */
342static RCSNode *
343RCS_parsercsfile_i (fp, rcsfile)
344 FILE *fp;
345 const char *rcsfile;
346{
347 RCSNode *rdata;
348 struct rcsbuffer rcsbuf;
349 char *key, *value;
350
351 /* make a node */
352 rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
350 memset ((char *) rdata, 0, sizeof (RCSNode));
353 memset ((char *)rdata, 0, sizeof (RCSNode));
351 rdata->refcount = 1;
352 rdata->path = xstrdup (rcsfile);
353
354 /* Process HEAD, BRANCH, and EXPAND keywords from the RCS header.
355
356 Most cvs operations on the main branch don't need any more
357 information. Those that do call RCS_reparsercsfile to parse
358 the rest of the header and the deltas. */
359
360 rcsbuf_open (&rcsbuf, fp, rcsfile, 0);
361
362 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
363 goto l_error;
364 if (STREQ (key, RCSDESC))
365 goto l_error;
366
367 if (STREQ (RCSHEAD, key) && value != NULL)
354 rdata->refcount = 1;
355 rdata->path = xstrdup (rcsfile);
356
357 /* Process HEAD, BRANCH, and EXPAND keywords from the RCS header.
358
359 Most cvs operations on the main branch don't need any more
360 information. Those that do call RCS_reparsercsfile to parse
361 the rest of the header and the deltas. */
362
363 rcsbuf_open (&rcsbuf, fp, rcsfile, 0);
364
365 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
366 goto l_error;
367 if (STREQ (key, RCSDESC))
368 goto l_error;
369
370 if (STREQ (RCSHEAD, key) && value != NULL)
368 rdata->head = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *) NULL);
371 rdata->head = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
369
370 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
371 goto l_error;
372 if (STREQ (key, RCSDESC))
373 goto l_error;
374
375 if (STREQ (RCSBRANCH, key) && value != NULL)
376 {
377 char *cp;
378
372
373 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
374 goto l_error;
375 if (STREQ (key, RCSDESC))
376 goto l_error;
377
378 if (STREQ (RCSBRANCH, key) && value != NULL)
379 {
380 char *cp;
381
379 rdata->branch = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *) NULL);
382 rdata->branch = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
380 if ((numdots (rdata->branch) & 1) != 0)
381 {
382 /* turn it into a branch if it's a revision */
383 cp = strrchr (rdata->branch, '.');
384 *cp = '\0';
385 }
386 }
387
388 /* Look ahead for expand, stopping when we see desc or a revision
389 number. */
390 while (1)
391 {
392 char *cp;
393
394 if (STREQ (RCSEXPAND, key))
395 {
396 rdata->expand = rcsbuf_valcopy (&rcsbuf, value, 0,
383 if ((numdots (rdata->branch) & 1) != 0)
384 {
385 /* turn it into a branch if it's a revision */
386 cp = strrchr (rdata->branch, '.');
387 *cp = '\0';
388 }
389 }
390
391 /* Look ahead for expand, stopping when we see desc or a revision
392 number. */
393 while (1)
394 {
395 char *cp;
396
397 if (STREQ (RCSEXPAND, key))
398 {
399 rdata->expand = rcsbuf_valcopy (&rcsbuf, value, 0,
397 (size_t *) NULL);
400 (size_t *)NULL);
398 break;
399 }
400
401 for (cp = key;
401 break;
402 }
403
404 for (cp = key;
402 (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
405 (isdigit ((unsigned char)*cp) || *cp == '.') && *cp != '\0';
403 cp++)
404 /* do nothing */ ;
405 if (*cp == '\0')
406 break;
407
408 if (STREQ (RCSDESC, key))
409 break;
410

--- 8 unchanged lines hidden (view full) ---

419 return rdata;
420
421l_error:
422 error (0, 0, "`%s' does not appear to be a valid rcs file",
423 rcsfile);
424 rcsbuf_close (&rcsbuf);
425 freercsnode (&rdata);
426 fclose (fp);
406 cp++)
407 /* do nothing */ ;
408 if (*cp == '\0')
409 break;
410
411 if (STREQ (RCSDESC, key))
412 break;
413

--- 8 unchanged lines hidden (view full) ---

422 return rdata;
423
424l_error:
425 error (0, 0, "`%s' does not appear to be a valid rcs file",
426 rcsfile);
427 rcsbuf_close (&rcsbuf);
428 freercsnode (&rdata);
429 fclose (fp);
427 return (NULL);
430 return NULL;
428}
429
430
431}
432
433
434
431/* Do the real work of parsing an RCS file.
432
433 On error, die with a fatal error; if it returns at all it was successful.
434
435 If PFP is NULL, close the file when done. Otherwise, leave it open
436 and store the FILE * in *PFP. */
437void
438RCS_reparsercsfile (rdata, pfp, rcsbufp)

--- 136 unchanged lines hidden (view full) ---

575 and its value). This is what getdelta expects to receive. */
576
577 while ((vnode = getdelta (&rcsbuf, rcsfile, &key, &value)) != NULL)
578 {
579 /* get the node */
580 q = getnode ();
581 q->type = RCSVERS;
582 q->delproc = rcsvers_delproc;
435/* Do the real work of parsing an RCS file.
436
437 On error, die with a fatal error; if it returns at all it was successful.
438
439 If PFP is NULL, close the file when done. Otherwise, leave it open
440 and store the FILE * in *PFP. */
441void
442RCS_reparsercsfile (rdata, pfp, rcsbufp)

--- 136 unchanged lines hidden (view full) ---

579 and its value). This is what getdelta expects to receive. */
580
581 while ((vnode = getdelta (&rcsbuf, rcsfile, &key, &value)) != NULL)
582 {
583 /* get the node */
584 q = getnode ();
585 q->type = RCSVERS;
586 q->delproc = rcsvers_delproc;
583 q->data = (char *) vnode;
587 q->data = vnode;
584 q->key = vnode->version;
585
586 /* add the nodes to the list */
587 if (addnode (rdata->versions, q) != 0)
588 {
589#if 0
590 purify_printf("WARNING: Adding duplicate version: %s (%s)\n",
591 q->key, rcsfile);

--- 35 unchanged lines hidden (view full) ---

627 atomic, or that kind of thing). If there is an error, print a message
628 and return 1. On success, return 0. */
629int
630RCS_setattic (rcs, toattic)
631 RCSNode *rcs;
632 int toattic;
633{
634 char *newpath;
588 q->key = vnode->version;
589
590 /* add the nodes to the list */
591 if (addnode (rdata->versions, q) != 0)
592 {
593#if 0
594 purify_printf("WARNING: Adding duplicate version: %s (%s)\n",
595 q->key, rcsfile);

--- 35 unchanged lines hidden (view full) ---

631 atomic, or that kind of thing). If there is an error, print a message
632 and return 1. On success, return 0. */
633int
634RCS_setattic (rcs, toattic)
635 RCSNode *rcs;
636 int toattic;
637{
638 char *newpath;
635 char *p;
639 const char *p;
636 char *q;
637
638 /* Some systems aren't going to let us rename an open file. */
639 rcsbuf_cache_close ();
640
641 /* Could make the pathname computations in this file, and probably
642 in other parts of rcs.c too, easier if the REPOS and FILE
643 arguments to RCS_parse got stashed in the RCSNode. */

--- 92 unchanged lines hidden (view full) ---

736 while (1)
737 {
738 char *key, *value;
739 Node *vers;
740 RCSVers *vnode;
741
742 /* Rather than try to keep track of how much information we
743 have read, just read to the end of the file. */
640 char *q;
641
642 /* Some systems aren't going to let us rename an open file. */
643 rcsbuf_cache_close ();
644
645 /* Could make the pathname computations in this file, and probably
646 in other parts of rcs.c too, easier if the REPOS and FILE
647 arguments to RCS_parse got stashed in the RCSNode. */

--- 92 unchanged lines hidden (view full) ---

740 while (1)
741 {
742 char *key, *value;
743 Node *vers;
744 RCSVers *vnode;
745
746 /* Rather than try to keep track of how much information we
747 have read, just read to the end of the file. */
744 if (! rcsbuf_getrevnum (&rcsbuf, &key))
748 if (!rcsbuf_getrevnum (&rcsbuf, &key))
745 break;
746
747 vers = findnode (rcs->versions, key);
748 if (vers == NULL)
749 error (1, 0,
750 "mismatch in rcs file %s between deltas and deltatexts (%s)",
751 rcs->path, key);
752
749 break;
750
751 vers = findnode (rcs->versions, key);
752 if (vers == NULL)
753 error (1, 0,
754 "mismatch in rcs file %s between deltas and deltatexts (%s)",
755 rcs->path, key);
756
753 vnode = (RCSVers *) vers->data;
757 vnode = vers->data;
754
755 while (rcsbuf_getkey (&rcsbuf, &key, &value))
756 {
758
759 while (rcsbuf_getkey (&rcsbuf, &key, &value))
760 {
757 if (! STREQ (key, "text"))
761 if (!STREQ (key, "text"))
758 {
759 Node *kv;
760
761 if (vnode->other == NULL)
762 vnode->other = getlist ();
763 kv = getnode ();
764 kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
765 kv->key = xstrdup (key);
766 kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
762 {
763 Node *kv;
764
765 if (vnode->other == NULL)
766 vnode->other = getlist ();
767 kv = getnode ();
768 kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
769 kv->key = xstrdup (key);
770 kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
767 (size_t *) NULL);
771 (size_t *)NULL);
768 if (addnode (vnode->other, kv) != 0)
769 {
770 error (0, 0,
771 "\
772warning: duplicate key `%s' in version `%s' of RCS file `%s'",
773 key, vnode->version, rcs->path);
774 freenode (kv);
775 }
776
777 continue;
778 }
779
772 if (addnode (vnode->other, kv) != 0)
773 {
774 error (0, 0,
775 "\
776warning: duplicate key `%s' in version `%s' of RCS file `%s'",
777 key, vnode->version, rcs->path);
778 freenode (kv);
779 }
780
781 continue;
782 }
783
780 if (! STREQ (vnode->version, rcs->head))
784 if (!STREQ (vnode->version, rcs->head))
781 {
782 unsigned long add, del;
783 char buf[50];
784 Node *kv;
785
786 /* This is a change text. Store the add and delete
787 counts. */
788 add = 0;

--- 82 unchanged lines hidden (view full) ---

871 next revision. */
872 break;
873 }
874 }
875
876 rcsbuf_cache (rcs, &rcsbuf);
877}
878
785 {
786 unsigned long add, del;
787 char buf[50];
788 Node *kv;
789
790 /* This is a change text. Store the add and delete
791 counts. */
792 add = 0;

--- 82 unchanged lines hidden (view full) ---

875 next revision. */
876 break;
877 }
878 }
879
880 rcsbuf_cache (rcs, &rcsbuf);
881}
882
883
884
879/*
880 * freercsnode - free up the info for an RCSNode
881 */
882void
883freercsnode (rnodep)
884 RCSNode **rnodep;
885{
886 if (rnodep == NULL || *rnodep == NULL)

--- 77 unchanged lines hidden (view full) ---

964
965/*
966 * rcsvers_delproc - free up an RCSVers type node
967 */
968static void
969rcsvers_delproc (p)
970 Node *p;
971{
885/*
886 * freercsnode - free up the info for an RCSNode
887 */
888void
889freercsnode (rnodep)
890 RCSNode **rnodep;
891{
892 if (rnodep == NULL || *rnodep == NULL)

--- 77 unchanged lines hidden (view full) ---

970
971/*
972 * rcsvers_delproc - free up an RCSVers type node
973 */
974static void
975rcsvers_delproc (p)
976 Node *p;
977{
972 free_rcsvers_contents ((RCSVers *) p->data);
978 free_rcsvers_contents (p->data);
973}
974
975/* These functions retrieve keys and values from an RCS file using a
976 buffer. We use this somewhat complex approach because it turns out
977 that for many common operations, CVS spends most of its time
978 reading keys, so it's worth doing some fairly hairy optimization. */
979
980/* The number of bytes we try to read each time we need more data. */

--- 1201 unchanged lines hidden (view full) ---

2182 * Returns the requested version number of the RCS file, satisfying tags and/or
2183 * dates, and walking branches, if necessary.
2184 *
2185 * The result is returned; null-string if error.
2186 */
2187char *
2188RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
2189 RCSNode *rcs;
979}
980
981/* These functions retrieve keys and values from an RCS file using a
982 buffer. We use this somewhat complex approach because it turns out
983 that for many common operations, CVS spends most of its time
984 reading keys, so it's worth doing some fairly hairy optimization. */
985
986/* The number of bytes we try to read each time we need more data. */

--- 1201 unchanged lines hidden (view full) ---

2188 * Returns the requested version number of the RCS file, satisfying tags and/or
2189 * dates, and walking branches, if necessary.
2190 *
2191 * The result is returned; null-string if error.
2192 */
2193char *
2194RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
2195 RCSNode *rcs;
2190 char *tag;
2191 char *date;
2196 const char *tag;
2197 const char *date;
2192 int force_tag_match;
2193 int *simple_tag;
2194{
2195 if (simple_tag != NULL)
2196 *simple_tag = 0;
2197
2198 /* make sure we have something to look at... */
2199 assert (rcs != NULL);

--- 16 unchanged lines hidden (view full) ---

2216 branch = xstrdup (tag);
2217
2218 /* Fetch the revision of branch as of date. */
2219 rev = RCS_getdatebranch (rcs, date, branch);
2220 free (branch);
2221 return (rev);
2222 }
2223 else if (tag)
2198 int force_tag_match;
2199 int *simple_tag;
2200{
2201 if (simple_tag != NULL)
2202 *simple_tag = 0;
2203
2204 /* make sure we have something to look at... */
2205 assert (rcs != NULL);

--- 16 unchanged lines hidden (view full) ---

2222 branch = xstrdup (tag);
2223
2224 /* Fetch the revision of branch as of date. */
2225 rev = RCS_getdatebranch (rcs, date, branch);
2226 free (branch);
2227 return (rev);
2228 }
2229 else if (tag)
2224 return (RCS_gettag (rcs, tag, force_tag_match, simple_tag));
2230 return RCS_gettag (rcs, tag, force_tag_match, simple_tag);
2225 else if (date)
2231 else if (date)
2226 return (RCS_getdate (rcs, date, force_tag_match));
2232 return RCS_getdate (rcs, date, force_tag_match);
2227 else
2233 else
2228 return (RCS_head (rcs));
2234 return RCS_head (rcs);
2229
2230}
2231
2235
2236}
2237
2238
2239
2232/*
2233 * Get existing revision number corresponding to tag or revision.
2234 * Similar to RCS_gettag but less interpretation imposed.
2235 * For example:
2236 * -- If tag designates a magic branch, RCS_tag2rev
2237 * returns the magic branch number.
2238 * -- If tag is a branch tag, returns the branch number, not
2239 * the revision of the head of the branch.

--- 89 unchanged lines hidden (view full) ---

2329 *
2330 * If the matched tag is a branch tag, find the head of the branch.
2331 *
2332 * Returns pointer to newly malloc'd string, or NULL.
2333 */
2334char *
2335RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
2336 RCSNode *rcs;
2240/*
2241 * Get existing revision number corresponding to tag or revision.
2242 * Similar to RCS_gettag but less interpretation imposed.
2243 * For example:
2244 * -- If tag designates a magic branch, RCS_tag2rev
2245 * returns the magic branch number.
2246 * -- If tag is a branch tag, returns the branch number, not
2247 * the revision of the head of the branch.

--- 89 unchanged lines hidden (view full) ---

2337 *
2338 * If the matched tag is a branch tag, find the head of the branch.
2339 *
2340 * Returns pointer to newly malloc'd string, or NULL.
2341 */
2342char *
2343RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
2344 RCSNode *rcs;
2337 char *symtag;
2345 const char *symtag;
2338 int force_tag_match;
2339 int *simple_tag;
2340{
2346 int force_tag_match;
2347 int *simple_tag;
2348{
2341 char *tag = symtag;
2342 int tag_allocated = 0;
2349 char *tag;
2343
2344 if (simple_tag != NULL)
2345 *simple_tag = 0;
2346
2347 /* make sure we have something to look at... */
2348 assert (rcs != NULL);
2349
2350 /* XXX this is probably not necessary, --jtc */
2351 if (rcs->flags & PARTIAL)
2352 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2353
2350
2351 if (simple_tag != NULL)
2352 *simple_tag = 0;
2353
2354 /* make sure we have something to look at... */
2355 assert (rcs != NULL);
2356
2357 /* XXX this is probably not necessary, --jtc */
2358 if (rcs->flags & PARTIAL)
2359 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2360
2354 /* If tag is "HEAD", special case to get head RCS revision */
2355 if (tag && STREQ (tag, TAG_HEAD))
2361 /* If symtag is "HEAD", special case to get head RCS revision */
2362 if (symtag && STREQ (symtag, TAG_HEAD))
2356#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
2357 if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
2358 return ((char *) NULL); /* head request for removed file */
2359 else
2360#endif
2363#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
2364 if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
2365 return ((char *) NULL); /* head request for removed file */
2366 else
2367#endif
2361 return (RCS_head (rcs));
2368 return RCS_head (rcs);
2362
2369
2363 if (!isdigit ((unsigned char) tag[0]))
2370 if (!isdigit ((unsigned char) symtag[0]))
2364 {
2365 char *version;
2366
2367 /* If we got a symbolic tag, resolve it to a numeric */
2371 {
2372 char *version;
2373
2374 /* If we got a symbolic tag, resolve it to a numeric */
2368 version = translate_symtag (rcs, tag);
2375 version = translate_symtag (rcs, symtag);
2369 if (version != NULL)
2370 {
2371 int dots;
2372 char *magic, *branch, *cp;
2373
2374 tag = version;
2376 if (version != NULL)
2377 {
2378 int dots;
2379 char *magic, *branch, *cp;
2380
2381 tag = version;
2375 tag_allocated = 1;
2376
2377 /*
2378 * If this is a magic revision, we turn it into either its
2379 * physical branch equivalent (if one exists) or into
2380 * its base revision, which we assume exists.
2381 */
2382 dots = numdots (tag);
2383 if (dots > 2 && (dots & 1) != 0)

--- 11 unchanged lines hidden (view full) ---

2395 /* it's magic. See if the branch exists */
2396 *cp = '\0'; /* turn it into a revision */
2397 (void) sprintf (magic, "%s.%s", tag, branch);
2398 branch = RCS_getbranch (rcs, magic, 1);
2399 free (magic);
2400 if (branch != NULL)
2401 {
2402 free (tag);
2382
2383 /*
2384 * If this is a magic revision, we turn it into either its
2385 * physical branch equivalent (if one exists) or into
2386 * its base revision, which we assume exists.
2387 */
2388 dots = numdots (tag);
2389 if (dots > 2 && (dots & 1) != 0)

--- 11 unchanged lines hidden (view full) ---

2401 /* it's magic. See if the branch exists */
2402 *cp = '\0'; /* turn it into a revision */
2403 (void) sprintf (magic, "%s.%s", tag, branch);
2404 branch = RCS_getbranch (rcs, magic, 1);
2405 free (magic);
2406 if (branch != NULL)
2407 {
2408 free (tag);
2403 return (branch);
2409 return branch;
2404 }
2410 }
2405 return (tag);
2411 return tag;
2406 }
2407 free (magic);
2408 }
2409 }
2410 else
2411 {
2412 /* The tag wasn't there, so return the head or NULL */
2413 if (force_tag_match)
2412 }
2413 free (magic);
2414 }
2415 }
2416 else
2417 {
2418 /* The tag wasn't there, so return the head or NULL */
2419 if (force_tag_match)
2414 return (NULL);
2420 return NULL;
2415 else
2421 else
2416 return (RCS_head (rcs));
2422 return RCS_head (rcs);
2417 }
2418 }
2423 }
2424 }
2425 else
2426 tag = xstrdup (symtag);
2419
2427
2428 /* tag is always allocated and numeric now. */
2429
2420 /*
2421 * numeric tag processing:
2422 * 1) revision number - just return it
2423 * 2) branch number - find head of branch
2424 */
2425
2426 /* strip trailing dots */
2427 while (tag[strlen (tag) - 1] == '.')
2428 tag[strlen (tag) - 1] = '\0';
2429
2430 if ((numdots (tag) & 1) == 0)
2431 {
2432 char *branch;
2433
2434 /* we have a branch tag, so we need to walk the branch */
2435 branch = RCS_getbranch (rcs, tag, force_tag_match);
2430 /*
2431 * numeric tag processing:
2432 * 1) revision number - just return it
2433 * 2) branch number - find head of branch
2434 */
2435
2436 /* strip trailing dots */
2437 while (tag[strlen (tag) - 1] == '.')
2438 tag[strlen (tag) - 1] = '\0';
2439
2440 if ((numdots (tag) & 1) == 0)
2441 {
2442 char *branch;
2443
2444 /* we have a branch tag, so we need to walk the branch */
2445 branch = RCS_getbranch (rcs, tag, force_tag_match);
2436 if (tag_allocated)
2437 free (tag);
2446 free (tag);
2438 return branch;
2439 }
2440 else
2441 {
2442 Node *p;
2443
2444 /* we have a revision tag, so make sure it exists */
2445 p = findnode (rcs->versions, tag);
2446 if (p != NULL)
2447 {
2448 /* We have found a numeric revision for the revision tag.
2449 To support expanding the RCS keyword Name, if
2450 SIMPLE_TAG is not NULL, tell the the caller that this
2451 is a simple tag which co will recognize. FIXME: Are
2452 there other cases in which we should set this? In
2453 particular, what if we expand RCS keywords internally
2454 without calling co? */
2455 if (simple_tag != NULL)
2456 *simple_tag = 1;
2447 return branch;
2448 }
2449 else
2450 {
2451 Node *p;
2452
2453 /* we have a revision tag, so make sure it exists */
2454 p = findnode (rcs->versions, tag);
2455 if (p != NULL)
2456 {
2457 /* We have found a numeric revision for the revision tag.
2458 To support expanding the RCS keyword Name, if
2459 SIMPLE_TAG is not NULL, tell the the caller that this
2460 is a simple tag which co will recognize. FIXME: Are
2461 there other cases in which we should set this? In
2462 particular, what if we expand RCS keywords internally
2463 without calling co? */
2464 if (simple_tag != NULL)
2465 *simple_tag = 1;
2457 if (! tag_allocated)
2458 tag = xstrdup (tag);
2459 return (tag);
2466 return tag;
2460 }
2461 else
2462 {
2463 /* The revision wasn't there, so return the head or NULL */
2467 }
2468 else
2469 {
2470 /* The revision wasn't there, so return the head or NULL */
2464 if (tag_allocated)
2465 free (tag);
2471 free (tag);
2466 if (force_tag_match)
2472 if (force_tag_match)
2467 return (NULL);
2473 return NULL;
2468 else
2474 else
2469 return (RCS_head (rcs));
2475 return RCS_head (rcs);
2470 }
2471 }
2472}
2473
2474/*
2475 * Return a "magic" revision as a virtual branch off of REV for the RCS file.
2476 * A "magic" revision is one which is unique in the RCS file. By unique, I
2477 * mean we return a revision which:

--- 208 unchanged lines hidden (view full) ---

2686/*
2687 * Get the head of the specified branch. If the branch does not exist,
2688 * return NULL or RCS_head depending on force_tag_match.
2689 * Returns NULL or a newly malloc'd string.
2690 */
2691char *
2692RCS_getbranch (rcs, tag, force_tag_match)
2693 RCSNode *rcs;
2476 }
2477 }
2478}
2479
2480/*
2481 * Return a "magic" revision as a virtual branch off of REV for the RCS file.
2482 * A "magic" revision is one which is unique in the RCS file. By unique, I
2483 * mean we return a revision which:

--- 208 unchanged lines hidden (view full) ---

2692/*
2693 * Get the head of the specified branch. If the branch does not exist,
2694 * return NULL or RCS_head depending on force_tag_match.
2695 * Returns NULL or a newly malloc'd string.
2696 */
2697char *
2698RCS_getbranch (rcs, tag, force_tag_match)
2699 RCSNode *rcs;
2694 char *tag;
2700 const char *tag;
2695 int force_tag_match;
2696{
2697 Node *p, *head;
2698 RCSVers *vn;
2699 char *xtag;
2700 char *nextvers;
2701 char *cp;
2702

--- 20 unchanged lines hidden (view full) ---

2723 if (p == NULL)
2724 {
2725 free (xtag);
2726 if (force_tag_match)
2727 return (NULL);
2728 else
2729 return (RCS_head (rcs));
2730 }
2701 int force_tag_match;
2702{
2703 Node *p, *head;
2704 RCSVers *vn;
2705 char *xtag;
2706 char *nextvers;
2707 char *cp;
2708

--- 20 unchanged lines hidden (view full) ---

2729 if (p == NULL)
2730 {
2731 free (xtag);
2732 if (force_tag_match)
2733 return (NULL);
2734 else
2735 return (RCS_head (rcs));
2736 }
2731 vn = (RCSVers *) p->data;
2737 vn = p->data;
2732 cp = vn->next;
2733 }
2734 free (xtag);
2735 if (cp == NULL)
2736 {
2737 if (force_tag_match)
2738 return (NULL);
2739 else

--- 16 unchanged lines hidden (view full) ---

2756 /* if the base revision didn't exist, return head or NULL */
2757 if (force_tag_match)
2758 return (NULL);
2759 else
2760 return (RCS_head (rcs));
2761 }
2762
2763 /* find the first element of the branch we are looking for */
2738 cp = vn->next;
2739 }
2740 free (xtag);
2741 if (cp == NULL)
2742 {
2743 if (force_tag_match)
2744 return (NULL);
2745 else

--- 16 unchanged lines hidden (view full) ---

2762 /* if the base revision didn't exist, return head or NULL */
2763 if (force_tag_match)
2764 return (NULL);
2765 else
2766 return (RCS_head (rcs));
2767 }
2768
2769 /* find the first element of the branch we are looking for */
2764 vn = (RCSVers *) p->data;
2770 vn = p->data;
2765 if (vn->branches == NULL)
2766 return (NULL);
2767 xtag = xmalloc (strlen (tag) + 1 + 1); /* 1 for the extra '.' */
2768 (void) strcpy (xtag, tag);
2769 (void) strcat (xtag, ".");
2770 head = vn->branches->list;
2771 for (p = head->next; p != head; p = p->next)
2772 if (strncmp (p->key, xtag, strlen (xtag)) == 0)

--- 17 unchanged lines hidden (view full) ---

2790 if (p == NULL)
2791 {
2792 /* a link in the chain is missing - return head or NULL */
2793 if (force_tag_match)
2794 return (NULL);
2795 else
2796 return (RCS_head (rcs));
2797 }
2771 if (vn->branches == NULL)
2772 return (NULL);
2773 xtag = xmalloc (strlen (tag) + 1 + 1); /* 1 for the extra '.' */
2774 (void) strcpy (xtag, tag);
2775 (void) strcat (xtag, ".");
2776 head = vn->branches->list;
2777 for (p = head->next; p != head; p = p->next)
2778 if (strncmp (p->key, xtag, strlen (xtag)) == 0)

--- 17 unchanged lines hidden (view full) ---

2796 if (p == NULL)
2797 {
2798 /* a link in the chain is missing - return head or NULL */
2799 if (force_tag_match)
2800 return (NULL);
2801 else
2802 return (RCS_head (rcs));
2803 }
2798 vn = (RCSVers *) p->data;
2804 vn = p->data;
2799 nextvers = vn->next;
2800 } while (nextvers != NULL);
2801
2802 /* we have the version in our hand, so go for it */
2803 return (xstrdup (vn->version));
2804}
2805
2806/* Returns the head of the branch which REV is on. REV can be a

--- 74 unchanged lines hidden (view full) ---

2881 *bp = '\0';
2882
2883 vp = findnode (rcs->versions, branch);
2884 if (vp == NULL)
2885 {
2886 error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2887 return NULL;
2888 }
2805 nextvers = vn->next;
2806 } while (nextvers != NULL);
2807
2808 /* we have the version in our hand, so go for it */
2809 return (xstrdup (vn->version));
2810}
2811
2812/* Returns the head of the branch which REV is on. REV can be a

--- 74 unchanged lines hidden (view full) ---

2887 *bp = '\0';
2888
2889 vp = findnode (rcs->versions, branch);
2890 if (vp == NULL)
2891 {
2892 error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2893 return NULL;
2894 }
2889 rev = (RCSVers *) vp->data;
2895 rev = vp->data;
2890
2891 *bp++ = '.';
2892 while (*bp && *bp != '.')
2893 ++bp;
2894 brlen = bp - branch;
2895
2896 vp = rev->branches->list->next;
2897 while (vp != rev->branches->list)

--- 42 unchanged lines hidden (view full) ---

2940
2941/*
2942 * Get the most recent revision, based on the supplied date, but use some
2943 * funky stuff and follow the vendor branch maybe
2944 */
2945char *
2946RCS_getdate (rcs, date, force_tag_match)
2947 RCSNode *rcs;
2896
2897 *bp++ = '.';
2898 while (*bp && *bp != '.')
2899 ++bp;
2900 brlen = bp - branch;
2901
2902 vp = rev->branches->list->next;
2903 while (vp != rev->branches->list)

--- 42 unchanged lines hidden (view full) ---

2946
2947/*
2948 * Get the most recent revision, based on the supplied date, but use some
2949 * funky stuff and follow the vendor branch maybe
2950 */
2951char *
2952RCS_getdate (rcs, date, force_tag_match)
2953 RCSNode *rcs;
2948 char *date;
2954 const char *date;
2949 int force_tag_match;
2950{
2951 char *cur_rev = NULL;
2952 char *retval = NULL;
2953 Node *p;
2954 RCSVers *vers = NULL;
2955
2956 /* make sure we have something to look at... */

--- 17 unchanged lines hidden (view full) ---

2974 if (p == NULL)
2975 {
2976 error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
2977 rcs->head);
2978 }
2979 while (p != NULL)
2980 {
2981 /* if the date of this one is before date, take it */
2955 int force_tag_match;
2956{
2957 char *cur_rev = NULL;
2958 char *retval = NULL;
2959 Node *p;
2960 RCSVers *vers = NULL;
2961
2962 /* make sure we have something to look at... */

--- 17 unchanged lines hidden (view full) ---

2980 if (p == NULL)
2981 {
2982 error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
2983 rcs->head);
2984 }
2985 while (p != NULL)
2986 {
2987 /* if the date of this one is before date, take it */
2982 vers = (RCSVers *) p->data;
2988 vers = p->data;
2983 if (RCS_datecmp (vers->date, date) <= 0)
2984 {
2985 cur_rev = vers->version;
2986 break;
2987 }
2988
2989 /* if there is a next version, find the node */
2990 if (vers->next != NULL)

--- 21 unchanged lines hidden (view full) ---

3012 1.1.1.1 version, then return 1.1. This happens when the first
3013 version of a file is created by a regular cvs add and commit,
3014 and there is a subsequent cvs import of the same file. */
3015 p = findnode (rcs->versions, "1.1.1.1");
3016 if (p)
3017 {
3018 char *date_1_1 = vers->date;
3019
2989 if (RCS_datecmp (vers->date, date) <= 0)
2990 {
2991 cur_rev = vers->version;
2992 break;
2993 }
2994
2995 /* if there is a next version, find the node */
2996 if (vers->next != NULL)

--- 21 unchanged lines hidden (view full) ---

3018 1.1.1.1 version, then return 1.1. This happens when the first
3019 version of a file is created by a regular cvs add and commit,
3020 and there is a subsequent cvs import of the same file. */
3021 p = findnode (rcs->versions, "1.1.1.1");
3022 if (p)
3023 {
3024 char *date_1_1 = vers->date;
3025
3020 vers = (RCSVers *) p->data;
3026 vers = p->data;
3021 if (RCS_datecmp (vers->date, date_1_1) != 0)
3022 return xstrdup ("1.1");
3023 }
3024 }
3025
3026 /* look on the vendor branch */
3027 retval = RCS_getdatebranch (rcs, date, CVSBRANCH);
3028
3029 /*
3030 * if we found a match, return it; otherwise, we return the first
3031 * revision on the trunk or NULL depending on force_tag_match and the
3032 * date of the first rev
3033 */
3034 if (retval != NULL)
3035 return (retval);
3036
3037 if (!force_tag_match ||
3038 (vers != NULL && RCS_datecmp (vers->date, date) <= 0))
3027 if (RCS_datecmp (vers->date, date_1_1) != 0)
3028 return xstrdup ("1.1");
3029 }
3030 }
3031
3032 /* look on the vendor branch */
3033 retval = RCS_getdatebranch (rcs, date, CVSBRANCH);
3034
3035 /*
3036 * if we found a match, return it; otherwise, we return the first
3037 * revision on the trunk or NULL depending on force_tag_match and the
3038 * date of the first rev
3039 */
3040 if (retval != NULL)
3041 return (retval);
3042
3043 if (!force_tag_match ||
3044 (vers != NULL && RCS_datecmp (vers->date, date) <= 0))
3039 return (xstrdup (vers->version));
3045 return xstrdup (vers->version);
3040 else
3046 else
3041 return (NULL);
3047 return NULL;
3042}
3043
3048}
3049
3050
3051
3044/*
3045 * Look up the last element on a branch that was put in before the specified
3046 * date (return the rev or NULL)
3047 */
3048static char *
3049RCS_getdatebranch (rcs, date, branch)
3050 RCSNode *rcs;
3052/*
3053 * Look up the last element on a branch that was put in before the specified
3054 * date (return the rev or NULL)
3055 */
3056static char *
3057RCS_getdatebranch (rcs, date, branch)
3058 RCSNode *rcs;
3051 char *date;
3052 char *branch;
3059 const char *date;
3060 const char *branch;
3053{
3054 char *cur_rev = NULL;
3055 char *cp;
3056 char *xbranch, *xrev;
3057 Node *p;
3058 RCSVers *vers;
3059
3060 /* look up the first revision on the branch */

--- 10 unchanged lines hidden (view full) ---

3071
3072 if (rcs->flags & PARTIAL)
3073 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3074
3075 p = findnode (rcs->versions, xrev);
3076 free (xrev);
3077 if (p == NULL)
3078 return (NULL);
3061{
3062 char *cur_rev = NULL;
3063 char *cp;
3064 char *xbranch, *xrev;
3065 Node *p;
3066 RCSVers *vers;
3067
3068 /* look up the first revision on the branch */

--- 10 unchanged lines hidden (view full) ---

3079
3080 if (rcs->flags & PARTIAL)
3081 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3082
3083 p = findnode (rcs->versions, xrev);
3084 free (xrev);
3085 if (p == NULL)
3086 return (NULL);
3079 vers = (RCSVers *) p->data;
3087 vers = p->data;
3080
3081 /* Tentatively use this revision, if it is early enough. */
3082 if (RCS_datecmp (vers->date, date) <= 0)
3083 cur_rev = vers->version;
3084
3085 /* If no branches list, return now. This is what happens if the branch
3086 is a (magic) branch with no revisions yet. */
3087 if (vers->branches == NULL)

--- 16 unchanged lines hidden (view full) ---

3104 return xstrdup (cur_rev);
3105 }
3106
3107 p = findnode (rcs->versions, p->key);
3108
3109 /* walk the next pointers until you find the end, or the date is too late */
3110 while (p != NULL)
3111 {
3088
3089 /* Tentatively use this revision, if it is early enough. */
3090 if (RCS_datecmp (vers->date, date) <= 0)
3091 cur_rev = vers->version;
3092
3093 /* If no branches list, return now. This is what happens if the branch
3094 is a (magic) branch with no revisions yet. */
3095 if (vers->branches == NULL)

--- 16 unchanged lines hidden (view full) ---

3112 return xstrdup (cur_rev);
3113 }
3114
3115 p = findnode (rcs->versions, p->key);
3116
3117 /* walk the next pointers until you find the end, or the date is too late */
3118 while (p != NULL)
3119 {
3112 vers = (RCSVers *) p->data;
3120 vers = p->data;
3113 if (RCS_datecmp (vers->date, date) <= 0)
3114 cur_rev = vers->version;
3115 else
3116 break;
3117
3118 /* if there is a next version, find the node */
3119 if (vers->next != NULL)
3120 p = findnode (rcs->versions, vers->next);
3121 else
3122 p = (Node *) NULL;
3123 }
3124
3125 /* Return whatever we found, which may be NULL. */
3126 return xstrdup (cur_rev);
3127}
3128
3121 if (RCS_datecmp (vers->date, date) <= 0)
3122 cur_rev = vers->version;
3123 else
3124 break;
3125
3126 /* if there is a next version, find the node */
3127 if (vers->next != NULL)
3128 p = findnode (rcs->versions, vers->next);
3129 else
3130 p = (Node *) NULL;
3131 }
3132
3133 /* Return whatever we found, which may be NULL. */
3134 return xstrdup (cur_rev);
3135}
3136
3137
3138
3129/*
3130 * Compare two dates in RCS format. Beware the change in format on January 1,
3131 * 2000, when years go from 2-digit to full format.
3132 */
3133int
3134RCS_datecmp (date1, date2)
3139/*
3140 * Compare two dates in RCS format. Beware the change in format on January 1,
3141 * 2000, when years go from 2-digit to full format.
3142 */
3143int
3144RCS_datecmp (date1, date2)
3135 char *date1, *date2;
3145 const char *date1, *date2;
3136{
3137 int length_diff = strlen (date1) - strlen (date2);
3138
3146{
3147 int length_diff = strlen (date1) - strlen (date2);
3148
3139 return (length_diff ? length_diff : strcmp (date1, date2));
3149 return length_diff ? length_diff : strcmp (date1, date2);
3140}
3141
3150}
3151
3152
3153
3142/* Look up revision REV in RCS and return the date specified for the
3143 revision minus FUDGE seconds (FUDGE will generally be one, so that the
3144 logically previous revision will be found later, or zero, if we want
3145 the exact date).
3146
3147 The return value is the date being returned as a time_t, or (time_t)-1
3148 on error (previously was documented as zero on error; I haven't checked
3149 the callers to make sure that they really check for (time_t)-1, but
3150 the latter is what this function really returns). If DATE is non-NULL,
3151 then it must point to MAXDATELEN characters, and we store the same
3152 return value there in DATEFORM format. */
3153time_t
3154RCS_getrevtime (rcs, rev, date, fudge)
3155 RCSNode *rcs;
3154/* Look up revision REV in RCS and return the date specified for the
3155 revision minus FUDGE seconds (FUDGE will generally be one, so that the
3156 logically previous revision will be found later, or zero, if we want
3157 the exact date).
3158
3159 The return value is the date being returned as a time_t, or (time_t)-1
3160 on error (previously was documented as zero on error; I haven't checked
3161 the callers to make sure that they really check for (time_t)-1, but
3162 the latter is what this function really returns). If DATE is non-NULL,
3163 then it must point to MAXDATELEN characters, and we store the same
3164 return value there in DATEFORM format. */
3165time_t
3166RCS_getrevtime (rcs, rev, date, fudge)
3167 RCSNode *rcs;
3156 char *rev;
3168 const char *rev;
3157 char *date;
3158 int fudge;
3159{
3160 char tdate[MAXDATELEN];
3161 struct tm xtm, *ftm;
3162 time_t revdate = 0;
3163 Node *p;
3164 RCSVers *vers;
3165
3166 /* make sure we have something to look at... */
3167 assert (rcs != NULL);
3168
3169 if (rcs->flags & PARTIAL)
3170 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3171
3172 /* look up the revision */
3173 p = findnode (rcs->versions, rev);
3174 if (p == NULL)
3175 return (-1);
3169 char *date;
3170 int fudge;
3171{
3172 char tdate[MAXDATELEN];
3173 struct tm xtm, *ftm;
3174 time_t revdate = 0;
3175 Node *p;
3176 RCSVers *vers;
3177
3178 /* make sure we have something to look at... */
3179 assert (rcs != NULL);
3180
3181 if (rcs->flags & PARTIAL)
3182 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3183
3184 /* look up the revision */
3185 p = findnode (rcs->versions, rev);
3186 if (p == NULL)
3187 return (-1);
3176 vers = (RCSVers *) p->data;
3188 vers = p->data;
3177
3178 /* split up the date */
3189
3190 /* split up the date */
3179 ftm = &xtm;
3180 (void) sscanf (vers->date, SDATEFORM, &ftm->tm_year, &ftm->tm_mon,
3181 &ftm->tm_mday, &ftm->tm_hour, &ftm->tm_min,
3182 &ftm->tm_sec);
3191 if (sscanf (vers->date, SDATEFORM, &xtm.tm_year, &xtm.tm_mon,
3192 &xtm.tm_mday, &xtm.tm_hour, &xtm.tm_min, &xtm.tm_sec) != 6)
3193 error (1, 0, "%s: invalid date for revision %s (%s)", rcs->path,
3194 rev, vers->date);
3183
3184 /* If the year is from 1900 to 1999, RCS files contain only two
3185 digits, and sscanf gives us a year from 0-99. If the year is
3186 2000+, RCS files contain all four digits and we subtract 1900,
3187 because the tm_year field should contain years since 1900. */
3188
3195
3196 /* If the year is from 1900 to 1999, RCS files contain only two
3197 digits, and sscanf gives us a year from 0-99. If the year is
3198 2000+, RCS files contain all four digits and we subtract 1900,
3199 because the tm_year field should contain years since 1900. */
3200
3189 if (ftm->tm_year > 1900)
3190 ftm->tm_year -= 1900;
3201 if (xtm.tm_year >= 100 && xtm.tm_year < 2000)
3202 error (0, 0, "%s: non-standard date format for revision %s (%s)",
3203 rcs->path, rev, vers->date);
3204 if (xtm.tm_year >= 1900)
3205 xtm.tm_year -= 1900;
3191
3192 /* put the date in a form getdate can grok */
3206
3207 /* put the date in a form getdate can grok */
3193 (void) sprintf (tdate, "%d/%d/%d GMT %d:%d:%d", ftm->tm_mon,
3194 ftm->tm_mday, ftm->tm_year + 1900, ftm->tm_hour,
3195 ftm->tm_min, ftm->tm_sec);
3208 (void) sprintf (tdate, "%d/%d/%d GMT %d:%d:%d", xtm.tm_mon,
3209 xtm.tm_mday, xtm.tm_year + 1900, xtm.tm_hour,
3210 xtm.tm_min, xtm.tm_sec);
3196
3197 /* turn it into seconds since the epoch */
3198 revdate = get_date (tdate, (struct timeb *) NULL);
3199 if (revdate != (time_t) -1)
3200 {
3201 revdate -= fudge; /* remove "fudge" seconds */
3202 if (date)
3203 {
3204 /* put an appropriate string into ``date'' if we were given one */
3205 ftm = gmtime (&revdate);
3206 (void) sprintf (date, DATEFORM,
3207 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
3208 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
3209 ftm->tm_min, ftm->tm_sec);
3210 }
3211 }
3211
3212 /* turn it into seconds since the epoch */
3213 revdate = get_date (tdate, (struct timeb *) NULL);
3214 if (revdate != (time_t) -1)
3215 {
3216 revdate -= fudge; /* remove "fudge" seconds */
3217 if (date)
3218 {
3219 /* put an appropriate string into ``date'' if we were given one */
3220 ftm = gmtime (&revdate);
3221 (void) sprintf (date, DATEFORM,
3222 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
3223 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
3224 ftm->tm_min, ftm->tm_sec);
3225 }
3226 }
3212 return (revdate);
3227 return revdate;
3213}
3214
3215List *
3216RCS_getlocks (rcs)
3217 RCSNode *rcs;
3218{
3219 assert(rcs != NULL);
3220

--- 218 unchanged lines hidden (view full) ---

3439
3440 if (rcs->flags & PARTIAL)
3441 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3442
3443 p = findnode (rcs->versions, tag);
3444 if (p == NULL)
3445 return (0);
3446
3228}
3229
3230List *
3231RCS_getlocks (rcs)
3232 RCSNode *rcs;
3233{
3234 assert(rcs != NULL);
3235

--- 218 unchanged lines hidden (view full) ---

3454
3455 if (rcs->flags & PARTIAL)
3456 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3457
3458 p = findnode (rcs->versions, tag);
3459 if (p == NULL)
3460 return (0);
3461
3447 version = (RCSVers *) p->data;
3462 version = p->data;
3448 return (version->dead);
3449}
3450
3451/* Return the RCS keyword expansion mode. For example "b" for binary.
3452 Returns a pointer into storage which is allocated and freed along with
3453 the rest of the RCS information; the caller should not modify this
3454 storage. Returns NULL if the RCS file does not specify a keyword
3455 expansion mode; for all other errors, die with a fatal error. */

--- 6 unchanged lines hidden (view full) ---

3462 assert (rcs != NULL);
3463 return rcs->expand;
3464}
3465
3466/* Set keyword expansion mode to EXPAND. For example "b" for binary. */
3467void
3468RCS_setexpand (rcs, expand)
3469 RCSNode *rcs;
3463 return (version->dead);
3464}
3465
3466/* Return the RCS keyword expansion mode. For example "b" for binary.
3467 Returns a pointer into storage which is allocated and freed along with
3468 the rest of the RCS information; the caller should not modify this
3469 storage. Returns NULL if the RCS file does not specify a keyword
3470 expansion mode; for all other errors, die with a fatal error. */

--- 6 unchanged lines hidden (view full) ---

3477 assert (rcs != NULL);
3478 return rcs->expand;
3479}
3480
3481/* Set keyword expansion mode to EXPAND. For example "b" for binary. */
3482void
3483RCS_setexpand (rcs, expand)
3484 RCSNode *rcs;
3470 char *expand;
3485 const char *expand;
3471{
3472 /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3473 about RCS_reparsercsfile. */
3474 assert (rcs != NULL);
3475 if (rcs->expand != NULL)
3476 free (rcs->expand);
3477 rcs->expand = xstrdup (expand);
3478}

--- 265 unchanged lines hidden (view full) ---

3744 free_value = 1;
3745 break;
3746
3747 case KEYWORD_CVSHEADER:
3748 case KEYWORD_HEADER:
3749 case KEYWORD_ID:
3750 case KEYWORD_LOCALID:
3751 {
3486{
3487 /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3488 about RCS_reparsercsfile. */
3489 assert (rcs != NULL);
3490 if (rcs->expand != NULL)
3491 free (rcs->expand);
3492 rcs->expand = xstrdup (expand);
3493}

--- 265 unchanged lines hidden (view full) ---

3759 free_value = 1;
3760 break;
3761
3762 case KEYWORD_CVSHEADER:
3763 case KEYWORD_HEADER:
3764 case KEYWORD_ID:
3765 case KEYWORD_LOCALID:
3766 {
3752 char *path;
3767 const char *path;
3753 int free_path;
3754 char *date;
3755 char *old_path;
3756
3757 old_path = NULL;
3758 if (kw == KEYWORD_HEADER ||
3759 (kw == KEYWORD_LOCALID &&
3760 keyword_local == KEYWORD_HEADER))

--- 15 unchanged lines hidden (view full) ---

3776 + 20);
3777
3778 sprintf (value, "%s %s %s %s %s%s%s",
3779 path, ver->version, date, ver->author,
3780 ver->state,
3781 locker != NULL ? " " : "",
3782 locker != NULL ? locker : "");
3783 if (free_path)
3768 int free_path;
3769 char *date;
3770 char *old_path;
3771
3772 old_path = NULL;
3773 if (kw == KEYWORD_HEADER ||
3774 (kw == KEYWORD_LOCALID &&
3775 keyword_local == KEYWORD_HEADER))

--- 15 unchanged lines hidden (view full) ---

3791 + 20);
3792
3793 sprintf (value, "%s %s %s %s %s%s%s",
3794 path, ver->version, date, ver->author,
3795 ver->state,
3796 locker != NULL ? " " : "",
3797 locker != NULL ? locker : "");
3798 if (free_path)
3784 free (path);
3799 /* If free_path is set then we know we allocated path
3800 * and we can discard the const.
3801 */
3802 free ((char *)path);
3785 if (old_path)
3786 free (old_path);
3787 free (date);
3788 free_value = 1;
3789 }
3790 break;
3791
3792 case KEYWORD_LOCKER:

--- 262 unchanged lines hidden (view full) ---

4055 free (ebufs->data);
4056 next = ebufs->next;
4057 free (ebufs);
4058 ebufs = next;
4059 }
4060 }
4061}
4062
3803 if (old_path)
3804 free (old_path);
3805 free (date);
3806 free_value = 1;
3807 }
3808 break;
3809
3810 case KEYWORD_LOCKER:

--- 262 unchanged lines hidden (view full) ---

4073 free (ebufs->data);
4074 next = ebufs->next;
4075 free (ebufs);
4076 ebufs = next;
4077 }
4078 }
4079}
4080
4081
4082
4063/* Check out a revision from an RCS file.
4064
4065 If PFN is not NULL, then ignore WORKFILE and SOUT. Call PFN zero
4066 or more times with the contents of the file. CALLERDAT is passed,
4067 uninterpreted, to PFN. (The current code will always call PFN
4068 exactly once for a non empty file; however, the current code
4069 assumes that it can hold the entire file contents in memory, which
4070 is not a good assumption, and might change in the future).

--- 23 unchanged lines hidden (view full) ---

4094
4095/* This function mimics the behavior of `rcs co' almost exactly. The
4096 chief difference is in its support for preserving file ownership,
4097 permissions, and special files across checkin and checkout -- see
4098 comments in RCS_checkin for some issues about this. -twp */
4099
4100int
4101RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
4083/* Check out a revision from an RCS file.
4084
4085 If PFN is not NULL, then ignore WORKFILE and SOUT. Call PFN zero
4086 or more times with the contents of the file. CALLERDAT is passed,
4087 uninterpreted, to PFN. (The current code will always call PFN
4088 exactly once for a non empty file; however, the current code
4089 assumes that it can hold the entire file contents in memory, which
4090 is not a good assumption, and might change in the future).

--- 23 unchanged lines hidden (view full) ---

4114
4115/* This function mimics the behavior of `rcs co' almost exactly. The
4116 chief difference is in its support for preserving file ownership,
4117 permissions, and special files across checkin and checkout -- see
4118 comments in RCS_checkin for some issues about this. -twp */
4119
4120int
4121RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
4102 RCSNode *rcs;
4103 char *workfile;
4104 char *rev;
4105 char *nametag;
4106 char *options;
4107 char *sout;
4108 RCSCHECKOUTPROC pfn;
4109 void *callerdat;
4122 RCSNode *rcs;
4123 const char *workfile;
4124 const char *rev;
4125 const char *nametag;
4126 const char *options;
4127 const char *sout;
4128 RCSCHECKOUTPROC pfn;
4129 void *callerdat;
4110{
4111 int free_rev = 0;
4112 enum kflag expand;
4113 FILE *fp, *ofp;
4114 struct stat sb;
4115 struct rcsbuffer rcsbuf;
4116 char *key;
4117 char *value;

--- 10 unchanged lines hidden (view full) ---

4128 int change_rcs_mode = 0;
4129 int special_file = 0;
4130 unsigned long devnum_long;
4131 dev_t devnum = 0;
4132#endif
4133
4134 if (trace)
4135 {
4130{
4131 int free_rev = 0;
4132 enum kflag expand;
4133 FILE *fp, *ofp;
4134 struct stat sb;
4135 struct rcsbuffer rcsbuf;
4136 char *key;
4137 char *value;

--- 10 unchanged lines hidden (view full) ---

4148 int change_rcs_mode = 0;
4149 int special_file = 0;
4150 unsigned long devnum_long;
4151 dev_t devnum = 0;
4152#endif
4153
4154 if (trace)
4155 {
4136 (void) fprintf (stderr, "%s-> checkout (%s, %s, %s, %s)\n",
4156 (void) fprintf (stderr, "%s-> RCS_checkout (%s, %s, %s, %s, %s)\n",
4137#ifdef SERVER_SUPPORT
4138 server_active ? "S" : " ",
4139#else
4140 "",
4141#endif
4142 rcs->path,
4143 rev != NULL ? rev : "",
4157#ifdef SERVER_SUPPORT
4158 server_active ? "S" : " ",
4159#else
4160 "",
4161#endif
4162 rcs->path,
4163 rev != NULL ? rev : "",
4164 nametag != NULL ? nametag : "",
4144 options != NULL ? options : "",
4145 (pfn != NULL ? "(function)"
4146 : (workfile != NULL
4147 ? workfile
4148 : (sout != RUN_TTY ? sout : "(stdout)"))));
4149 }
4150
4151 assert (rev == NULL || isdigit ((unsigned char) *rev));

--- 38 unchanged lines hidden (view full) ---

4190 break;
4191 }
4192 }
4193
4194 if (! gothead)
4195 {
4196 error (0, 0, "internal error: cannot find head text");
4197 if (free_rev)
4165 options != NULL ? options : "",
4166 (pfn != NULL ? "(function)"
4167 : (workfile != NULL
4168 ? workfile
4169 : (sout != RUN_TTY ? sout : "(stdout)"))));
4170 }
4171
4172 assert (rev == NULL || isdigit ((unsigned char) *rev));

--- 38 unchanged lines hidden (view full) ---

4211 break;
4212 }
4213 }
4214
4215 if (! gothead)
4216 {
4217 error (0, 0, "internal error: cannot find head text");
4218 if (free_rev)
4198 free (rev);
4219 /* It's okay to discard the const when free_rev is set, because
4220 * we know we allocated it in this function.
4221 */
4222 free ((char *)rev);
4199 return 1;
4200 }
4201
4202 rcsbuf_valpolish (&rcsbuf, value, 0, &len);
4203
4204 if (fstat (fileno (fp), &sb) < 0)
4205 error (1, errno, "cannot fstat %s", rcs->path);
4206

--- 69 unchanged lines hidden (view full) ---

4276 {
4277 RCSVers *vers;
4278 Node *info;
4279
4280 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4281 if (vp == NULL)
4282 error (1, 0, "internal error: no revision information for %s",
4283 rev == NULL ? rcs->head : rev);
4223 return 1;
4224 }
4225
4226 rcsbuf_valpolish (&rcsbuf, value, 0, &len);
4227
4228 if (fstat (fileno (fp), &sb) < 0)
4229 error (1, errno, "cannot fstat %s", rcs->path);
4230

--- 69 unchanged lines hidden (view full) ---

4300 {
4301 RCSVers *vers;
4302 Node *info;
4303
4304 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4305 if (vp == NULL)
4306 error (1, 0, "internal error: no revision information for %s",
4307 rev == NULL ? rcs->head : rev);
4284 vers = (RCSVers *) vp->data;
4308 vers = vp->data;
4285
4286 /* First we look for symlinks, which are simplest to handle. */
4287 info = findnode (vers->other_delta, "symlink");
4288 if (info != NULL)
4289 {
4290 char *dest;
4291
4292 if (pfn != NULL || (workfile == NULL && sout == RUN_TTY))

--- 8 unchanged lines hidden (view full) ---

4301 since we just want the file not to be there. (TODO: decide
4302 whether it should be considered an error for `dest' to exist
4303 at this point. If so, the unlink call should be removed and
4304 `symlink' should signal the error. -twp) */
4305 if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
4306 error (1, errno, "cannot remove %s", dest);
4307 if (symlink (info->data, dest) < 0)
4308 error (1, errno, "cannot create symbolic link from %s to %s",
4309
4310 /* First we look for symlinks, which are simplest to handle. */
4311 info = findnode (vers->other_delta, "symlink");
4312 if (info != NULL)
4313 {
4314 char *dest;
4315
4316 if (pfn != NULL || (workfile == NULL && sout == RUN_TTY))

--- 8 unchanged lines hidden (view full) ---

4325 since we just want the file not to be there. (TODO: decide
4326 whether it should be considered an error for `dest' to exist
4327 at this point. If so, the unlink call should be removed and
4328 `symlink' should signal the error. -twp) */
4329 if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
4330 error (1, errno, "cannot remove %s", dest);
4331 if (symlink (info->data, dest) < 0)
4332 error (1, errno, "cannot create symbolic link from %s to %s",
4309 dest, info->data);
4333 dest, (char *)info->data);
4310 if (free_value)
4311 free (value);
4312 if (free_rev)
4334 if (free_value)
4335 free (value);
4336 if (free_rev)
4313 free (rev);
4337 /* It's okay to discard the const when free_rev is set, because
4338 * we know we allocated it in this function.
4339 */
4340 free ((char *)rev);
4314 return 0;
4315 }
4316
4317 /* Next, we look at this file's hardlinks field, and see whether
4318 it is linked to any other file that has been checked out.
4319 If so, we don't do anything else -- just link it to that file.
4320
4321 If we are checking out a file to a pipe or temporary storage,

--- 24 unchanged lines hidden (view full) ---

4346
4347 If one of these conditions is not met, then
4348 workfile is the first one in its hardlink group to
4349 be checked out, and we must continue with a full
4350 checkout. */
4351
4352 if (uptodate_link != NULL)
4353 {
4341 return 0;
4342 }
4343
4344 /* Next, we look at this file's hardlinks field, and see whether
4345 it is linked to any other file that has been checked out.
4346 If so, we don't do anything else -- just link it to that file.
4347
4348 If we are checking out a file to a pipe or temporary storage,

--- 24 unchanged lines hidden (view full) ---

4373
4374 If one of these conditions is not met, then
4375 workfile is the first one in its hardlink group to
4376 be checked out, and we must continue with a full
4377 checkout. */
4378
4379 if (uptodate_link != NULL)
4380 {
4354 struct hardlink_info *hlinfo =
4355 (struct hardlink_info *) uptodate_link->data;
4381 struct hardlink_info *hlinfo = uptodate_link->data;
4356
4357 if (link (uptodate_link->key, workfile) < 0)
4358 error (1, errno, "cannot link %s to %s",
4359 workfile, uptodate_link->key);
4360 hlinfo->checked_out = 1; /* probably unnecessary */
4361 if (free_value)
4362 free (value);
4363 if (free_rev)
4382
4383 if (link (uptodate_link->key, workfile) < 0)
4384 error (1, errno, "cannot link %s to %s",
4385 workfile, uptodate_link->key);
4386 hlinfo->checked_out = 1; /* probably unnecessary */
4387 if (free_value)
4388 free (value);
4389 if (free_rev)
4364 free (rev);
4390 /* It's okay to discard the const when free_rev is set,
4391 * because we know we allocated it in this function.
4392 */
4393 free ((char *)rev);
4365 return 0;
4366 }
4367 }
4368 }
4369
4370 info = findnode (vers->other_delta, "owner");
4371 if (info != NULL)
4372 {

--- 16 unchanged lines hidden (view full) ---

4389 if (info != NULL)
4390 {
4391 /* If the size of `devtype' changes, fix the sscanf call also */
4392 char devtype[16];
4393
4394 if (sscanf (info->data, "%15s %lu",
4395 devtype, &devnum_long) < 2)
4396 error (1, 0, "%s:%s has bad `special' newphrase %s",
4394 return 0;
4395 }
4396 }
4397 }
4398
4399 info = findnode (vers->other_delta, "owner");
4400 if (info != NULL)
4401 {

--- 16 unchanged lines hidden (view full) ---

4418 if (info != NULL)
4419 {
4420 /* If the size of `devtype' changes, fix the sscanf call also */
4421 char devtype[16];
4422
4423 if (sscanf (info->data, "%15s %lu",
4424 devtype, &devnum_long) < 2)
4425 error (1, 0, "%s:%s has bad `special' newphrase %s",
4397 workfile, vers->version, info->data);
4426 workfile, vers->version, (char *)info->data);
4398 devnum = devnum_long;
4399 if (STREQ (devtype, "character"))
4400 special_file = S_IFCHR;
4401 else if (STREQ (devtype, "block"))
4402 special_file = S_IFBLK;
4403 else
4404 error (0, 0, "%s is a special file of unsupported type `%s'",
4427 devnum = devnum_long;
4428 if (STREQ (devtype, "character"))
4429 special_file = S_IFCHR;
4430 else if (STREQ (devtype, "block"))
4431 special_file = S_IFBLK;
4432 else
4433 error (0, 0, "%s is a special file of unsupported type `%s'",
4405 workfile, info->data);
4434 workfile, (char *)info->data);
4406 }
4407 }
4435 }
4436 }
4408#endif
4437#endif /* PRESERVE_PERMISSIONS_SUPPORT */
4409
4410 if (expand != KFLAG_O && expand != KFLAG_B)
4411 {
4412 char *newvalue;
4413
4414 /* Don't fetch the delta node again if we already have it. */
4415 if (vp == NULL)
4416 {
4417 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4418 if (vp == NULL)
4419 error (1, 0, "internal error: no revision information for %s",
4420 rev == NULL ? rcs->head : rev);
4421 }
4422
4438
4439 if (expand != KFLAG_O && expand != KFLAG_B)
4440 {
4441 char *newvalue;
4442
4443 /* Don't fetch the delta node again if we already have it. */
4444 if (vp == NULL)
4445 {
4446 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4447 if (vp == NULL)
4448 error (1, 0, "internal error: no revision information for %s",
4449 rev == NULL ? rcs->head : rev);
4450 }
4451
4423 expand_keywords (rcs, (RCSVers *) vp->data, nametag, log, loglen,
4452 expand_keywords (rcs, vp->data, nametag, log, loglen,
4424 expand, value, len, &newvalue, &len);
4425
4426 if (newvalue != value)
4427 {
4428 if (free_value)
4429 free (value);
4430 value = newvalue;
4431 free_value = 1;
4432 }
4433 }
4434
4435 if (free_rev)
4453 expand, value, len, &newvalue, &len);
4454
4455 if (newvalue != value)
4456 {
4457 if (free_value)
4458 free (value);
4459 value = newvalue;
4460 free_value = 1;
4461 }
4462 }
4463
4464 if (free_rev)
4436 free (rev);
4465 /* It's okay to discard the const when free_rev is set, because
4466 * we know we allocated it in this function.
4467 */
4468 free ((char *)rev);
4437
4438 if (log != NULL)
4439 {
4440 free (log);
4441 log = NULL;
4442 }
4443
4444 if (pfn != NULL)

--- 253 unchanged lines hidden (view full) ---

4698 p = findnode (rcs->versions, lock->key);
4699 if (p == NULL)
4700 {
4701 error (0, 0, "%s: can't unlock nonexistent revision %s",
4702 rcs->path,
4703 lock->key);
4704 return NULL;
4705 }
4469
4470 if (log != NULL)
4471 {
4472 free (log);
4473 log = NULL;
4474 }
4475
4476 if (pfn != NULL)

--- 253 unchanged lines hidden (view full) ---

4730 p = findnode (rcs->versions, lock->key);
4731 if (p == NULL)
4732 {
4733 error (0, 0, "%s: can't unlock nonexistent revision %s",
4734 rcs->path,
4735 lock->key);
4736 return NULL;
4737 }
4706 return (RCSVers *) p->data;
4738 return p->data;
4707 }
4708
4709 /* No existing lock. The RCS rule is that this is an error unless
4710 locking is nonstrict AND the file is owned by the current
4711 user. Trying to determine the latter is a portability nightmare
4712 in the face of NT, VMS, AFS, and other systems with non-unix-like
4713 ideas of users and owners. In the case of CVS, we should never get
4714 here (as long as the traditional behavior of making sure to call
4715 RCS_lock persists). Anyway, we skip the RCS error checks
4716 and just return the default branch or head. The reasoning is that
4717 those error checks are to make users lock before a checkin, and we do
4718 that in other ways if at all anyway (e.g. rcslock.pl). */
4719
4720 p = findnode (rcs->versions, RCS_getbranch (rcs, rcs->branch, 0));
4739 }
4740
4741 /* No existing lock. The RCS rule is that this is an error unless
4742 locking is nonstrict AND the file is owned by the current
4743 user. Trying to determine the latter is a portability nightmare
4744 in the face of NT, VMS, AFS, and other systems with non-unix-like
4745 ideas of users and owners. In the case of CVS, we should never get
4746 here (as long as the traditional behavior of making sure to call
4747 RCS_lock persists). Anyway, we skip the RCS error checks
4748 and just return the default branch or head. The reasoning is that
4749 those error checks are to make users lock before a checkin, and we do
4750 that in other ways if at all anyway (e.g. rcslock.pl). */
4751
4752 p = findnode (rcs->versions, RCS_getbranch (rcs, rcs->branch, 0));
4721 return (RCSVers *) p->data;
4753 return p->data;
4722}
4723
4724/* Revision number string, R, must contain a `.'.
4725 Return a newly-malloc'd copy of the prefix of R up
4726 to but not including the final `.'. */
4727
4728static char *
4729truncate_revnum (r)

--- 114 unchanged lines hidden (view full) ---

4844 nodep = findnode (rcs->versions, branchpoint);
4845 if (nodep == NULL)
4846 {
4847 error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
4848 free (branchpoint);
4849 return NULL;
4850 }
4851 free (branchpoint);
4754}
4755
4756/* Revision number string, R, must contain a `.'.
4757 Return a newly-malloc'd copy of the prefix of R up
4758 to but not including the final `.'. */
4759
4760static char *
4761truncate_revnum (r)

--- 114 unchanged lines hidden (view full) ---

4876 nodep = findnode (rcs->versions, branchpoint);
4877 if (nodep == NULL)
4878 {
4879 error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
4880 free (branchpoint);
4881 return NULL;
4882 }
4883 free (branchpoint);
4852 branchnode = (RCSVers *) nodep->data;
4884 branchnode = nodep->data;
4853
4854 /* If BRANCH was a full branch number, make sure it is higher than MAX. */
4855 if ((numdots (branch) & 1) == 1)
4856 {
4857 if (branchnode->branches == NULL)
4858 {
4859 /* We have to create the first branch on this node, which means
4860 appending ".2" to the revision number. */

--- 83 unchanged lines hidden (view full) ---

4944 solution -- precisely because it diverges from RCS's behavior -- but
4945 it doesn't seem feasible to do this anywhere else in the code. [-twp]
4946
4947 Return value is -1 for error (and errno is set to indicate the
4948 error), positive for error (and an error message has been printed),
4949 or zero for success. */
4950
4951int
4885
4886 /* If BRANCH was a full branch number, make sure it is higher than MAX. */
4887 if ((numdots (branch) & 1) == 1)
4888 {
4889 if (branchnode->branches == NULL)
4890 {
4891 /* We have to create the first branch on this node, which means
4892 appending ".2" to the revision number. */

--- 83 unchanged lines hidden (view full) ---

4976 solution -- precisely because it diverges from RCS's behavior -- but
4977 it doesn't seem feasible to do this anywhere else in the code. [-twp]
4978
4979 Return value is -1 for error (and errno is set to indicate the
4980 error), positive for error (and an error message has been printed),
4981 or zero for success. */
4982
4983int
4952RCS_checkin (rcs, workfile, message, rev, flags)
4984RCS_checkin (rcs, workfile_in, message, rev, flags)
4953 RCSNode *rcs;
4985 RCSNode *rcs;
4954 char *workfile;
4955 char *message;
4956 char *rev;
4986 const char *workfile_in;
4987 const char *message;
4988 const char *rev;
4957 int flags;
4958{
4959 RCSVers *delta, *commitpt;
4960 Deltatext *dtext;
4961 Node *nodep;
4989 int flags;
4990{
4991 RCSVers *delta, *commitpt;
4992 Deltatext *dtext;
4993 Node *nodep;
4962 char *tmpfile, *changefile, *chtext;
4994 char *tmpfile, *changefile;
4963 char *diffopts;
4964 size_t bufsize;
4995 char *diffopts;
4996 size_t bufsize;
4965 int buflen, chtextlen;
4966 int status, checkin_quiet, allocated_workfile;
4997 int status, checkin_quiet;
4967 struct tm *ftm;
4968 time_t modtime;
4969 int adding_branch = 0;
4998 struct tm *ftm;
4999 time_t modtime;
5000 int adding_branch = 0;
5001 char *workfile = xstrdup (workfile_in);
4970#ifdef PRESERVE_PERMISSIONS_SUPPORT
4971 struct stat sb;
4972#endif
4973
4974 commitpt = NULL;
4975
4976 if (rcs->flags & PARTIAL)
4977 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
4978
4979 /* Get basename of working file. Is there a library function to
4980 do this? I couldn't find one. -twp */
5002#ifdef PRESERVE_PERMISSIONS_SUPPORT
5003 struct stat sb;
5004#endif
5005
5006 commitpt = NULL;
5007
5008 if (rcs->flags & PARTIAL)
5009 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5010
5011 /* Get basename of working file. Is there a library function to
5012 do this? I couldn't find one. -twp */
4981 allocated_workfile = 0;
4982 if (workfile == NULL)
4983 {
4984 char *p;
4985 int extlen = strlen (RCSEXT);
4986 workfile = xstrdup (last_component (rcs->path));
4987 p = workfile + (strlen (workfile) - extlen);
4988 assert (strncmp (p, RCSEXT, extlen) == 0);
4989 *p = '\0';
5013 if (workfile == NULL)
5014 {
5015 char *p;
5016 int extlen = strlen (RCSEXT);
5017 workfile = xstrdup (last_component (rcs->path));
5018 p = workfile + (strlen (workfile) - extlen);
5019 assert (strncmp (p, RCSEXT, extlen) == 0);
5020 *p = '\0';
4990 allocated_workfile = 1;
4991 }
4992
4993 /* If the filename is a symbolic link, follow it and replace it
4994 with the destination of the link. We need to do this before
4995 calling rcs_internal_lockfile, or else we won't put the lock in
4996 the right place. */
4997 resolve_symlink (&(rcs->path));
4998

--- 140 unchanged lines hidden (view full) ---

5139
5140 /* Don't need to xstrdup NEWREV because it's already dynamic, and
5141 not used for anything else. (Don't need to free it, either.) */
5142 rcs->head = newrev;
5143 delta->version = xstrdup (newrev);
5144 nodep = getnode();
5145 nodep->type = RCSVERS;
5146 nodep->delproc = rcsvers_delproc;
5021 }
5022
5023 /* If the filename is a symbolic link, follow it and replace it
5024 with the destination of the link. We need to do this before
5025 calling rcs_internal_lockfile, or else we won't put the lock in
5026 the right place. */
5027 resolve_symlink (&(rcs->path));
5028

--- 140 unchanged lines hidden (view full) ---

5169
5170 /* Don't need to xstrdup NEWREV because it's already dynamic, and
5171 not used for anything else. (Don't need to free it, either.) */
5172 rcs->head = newrev;
5173 delta->version = xstrdup (newrev);
5174 nodep = getnode();
5175 nodep->type = RCSVERS;
5176 nodep->delproc = rcsvers_delproc;
5147 nodep->data = (char *) delta;
5177 nodep->data = delta;
5148 nodep->key = delta->version;
5149 (void) addnode (rcs->versions, nodep);
5150
5151 dtext->version = xstrdup (newrev);
5152 bufsize = 0;
5153#ifdef PRESERVE_PERMISSIONS_SUPPORT
5154 if (preserve_perms && !S_ISREG (sb.st_mode))
5155 /* Pretend file is empty. */

--- 163 unchanged lines hidden (view full) ---

5319 delta->version = xstrdup (newrev);
5320 }
5321 else
5322 /* Just increment the tip number to get the new revision. */
5323 delta->version = increment_revnum (tip);
5324 }
5325
5326 nodep = findnode (rcs->versions, tip);
5178 nodep->key = delta->version;
5179 (void) addnode (rcs->versions, nodep);
5180
5181 dtext->version = xstrdup (newrev);
5182 bufsize = 0;
5183#ifdef PRESERVE_PERMISSIONS_SUPPORT
5184 if (preserve_perms && !S_ISREG (sb.st_mode))
5185 /* Pretend file is empty. */

--- 163 unchanged lines hidden (view full) ---

5349 delta->version = xstrdup (newrev);
5350 }
5351 else
5352 /* Just increment the tip number to get the new revision. */
5353 delta->version = increment_revnum (tip);
5354 }
5355
5356 nodep = findnode (rcs->versions, tip);
5327 commitpt = (RCSVers *) nodep->data;
5357 commitpt = nodep->data;
5328
5329 free (branch);
5330 free (newrev);
5331 free (tip);
5332 }
5333
5334 assert (delta->version != NULL);
5335

--- 12 unchanged lines hidden (view full) ---

5348 the end of addbranch in ci.c in RCS 5.7, it calls
5349 removelock only if it is our own lock, not someone
5350 else's). */
5351
5352 if (!adding_branch)
5353 {
5354 error (0, 0, "%s: revision %s locked by %s",
5355 rcs->path,
5358
5359 free (branch);
5360 free (newrev);
5361 free (tip);
5362 }
5363
5364 assert (delta->version != NULL);
5365

--- 12 unchanged lines hidden (view full) ---

5378 the end of addbranch in ci.c in RCS 5.7, it calls
5379 removelock only if it is our own lock, not someone
5380 else's). */
5381
5382 if (!adding_branch)
5383 {
5384 error (0, 0, "%s: revision %s locked by %s",
5385 rcs->path,
5356 nodep->key, nodep->data);
5386 nodep->key, (char *)nodep->data);
5357 status = 1;
5358 goto checkin_done;
5359 }
5360 }
5361 else
5362 delnode (nodep);
5363 }
5364

--- 13 unchanged lines hidden (view full) ---

5378 : "-ko"),
5379 tmpfile,
5380 (RCSCHECKOUTPROC)0, NULL);
5381 if (status != 0)
5382 error (1, 0,
5383 "could not check out revision %s of `%s'",
5384 commitpt->version, rcs->path);
5385
5387 status = 1;
5388 goto checkin_done;
5389 }
5390 }
5391 else
5392 delnode (nodep);
5393 }
5394

--- 13 unchanged lines hidden (view full) ---

5408 : "-ko"),
5409 tmpfile,
5410 (RCSCHECKOUTPROC)0, NULL);
5411 if (status != 0)
5412 error (1, 0,
5413 "could not check out revision %s of `%s'",
5414 commitpt->version, rcs->path);
5415
5386 bufsize = buflen = 0;
5387 chtext = NULL;
5388 chtextlen = 0;
5416 bufsize = 0;
5389 changefile = cvs_temp_name();
5390
5391 /* Diff options should include --binary if the RCS file has -kb set
5392 in its `expand' field. */
5393 diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
5394 ? "-a -n --binary"
5395 : "-a -n");
5396

--- 117 unchanged lines hidden (view full) ---

5514 }
5515
5516 /* Add DELTA to RCS->VERSIONS. */
5517 if (rcs->versions == NULL)
5518 rcs->versions = getlist();
5519 nodep = getnode();
5520 nodep->type = RCSVERS;
5521 nodep->delproc = rcsvers_delproc;
5417 changefile = cvs_temp_name();
5418
5419 /* Diff options should include --binary if the RCS file has -kb set
5420 in its `expand' field. */
5421 diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
5422 ? "-a -n --binary"
5423 : "-a -n");
5424

--- 117 unchanged lines hidden (view full) ---

5542 }
5543
5544 /* Add DELTA to RCS->VERSIONS. */
5545 if (rcs->versions == NULL)
5546 rcs->versions = getlist();
5547 nodep = getnode();
5548 nodep->type = RCSVERS;
5549 nodep->delproc = rcsvers_delproc;
5522 nodep->data = (char *) delta;
5550 nodep->data = delta;
5523 nodep->key = delta->version;
5524 (void) addnode (rcs->versions, nodep);
5525
5526 /* Write the new RCS file, inserting the new delta at COMMITPT. */
5527 if (!checkin_quiet)
5528 {
5529 cvs_output ("new revision: ", 14);
5530 cvs_output (delta->version, 0);

--- 16 unchanged lines hidden (view full) ---

5547 if (unlink_file (changefile) < 0)
5548 error (0, errno, "cannot remove %s", changefile);
5549 free (changefile);
5550
5551 if (!checkin_quiet)
5552 cvs_output ("done\n", 5);
5553
5554 checkin_done:
5551 nodep->key = delta->version;
5552 (void) addnode (rcs->versions, nodep);
5553
5554 /* Write the new RCS file, inserting the new delta at COMMITPT. */
5555 if (!checkin_quiet)
5556 {
5557 cvs_output ("new revision: ", 14);
5558 cvs_output (delta->version, 0);

--- 16 unchanged lines hidden (view full) ---

5575 if (unlink_file (changefile) < 0)
5576 error (0, errno, "cannot remove %s", changefile);
5577 free (changefile);
5578
5579 if (!checkin_quiet)
5580 cvs_output ("done\n", 5);
5581
5582 checkin_done:
5555 if (allocated_workfile)
5556 free (workfile);
5583 free (workfile);
5557
5558 if (commitpt != NULL && commitpt->text != NULL)
5559 {
5560 freedeltatext (commitpt->text);
5561 commitpt->text = NULL;
5562 }
5563
5564 freedeltatext (dtext);
5565 if (status != 0)
5566 free_rcsvers_contents (delta);
5567
5568 return status;
5569}
5570
5584
5585 if (commitpt != NULL && commitpt->text != NULL)
5586 {
5587 freedeltatext (commitpt->text);
5588 commitpt->text = NULL;
5589 }
5590
5591 freedeltatext (dtext);
5592 if (status != 0)
5593 free_rcsvers_contents (delta);
5594
5595 return status;
5596}
5597
5571/* This structure is passed between RCS_cmp_file and cmp_file_buffer. */
5572
5598
5599
5600/* This structure is passed between RCS_cmp_file and cmp_file_buffer. */
5573struct cmp_file_data
5574{
5575 const char *filename;
5576 FILE *fp;
5577 int different;
5578};
5579
5601struct cmp_file_data
5602{
5603 const char *filename;
5604 FILE *fp;
5605 int different;
5606};
5607
5580/* Compare the contents of revision REV of RCS file RCS with the
5581 contents of the file FILENAME. OPTIONS is a string for the keyword
5608/* Compare the contents of revision REV1 of RCS file RCS with the
5609 contents of REV2 if given, otherwise, compare with the contents of
5610 the file FILENAME. OPTIONS is a string for the keyword
5582 expansion options. Return 0 if the contents of the revision are
5583 the same as the contents of the file, 1 if they are different. */
5611 expansion options. Return 0 if the contents of the revision are
5612 the same as the contents of the file, 1 if they are different. */
5584
5585int
5613int
5586RCS_cmp_file (rcs, rev, options, filename)
5614RCS_cmp_file (rcs, rev1, rev1_cache, rev2, options, filename)
5587 RCSNode *rcs;
5615 RCSNode *rcs;
5588 char *rev;
5589 char *options;
5616 const char *rev1;
5617 char **rev1_cache;
5618 const char *rev2;
5619 const char *options;
5590 const char *filename;
5591{
5592 int binary;
5620 const char *filename;
5621{
5622 int binary;
5593 FILE *fp;
5594 struct cmp_file_data data;
5595 int retcode;
5596
5597 if (options != NULL && options[0] != '\0')
5598 binary = STREQ (options, "-kb");
5599 else
5600 {
5601 char *expand;
5602
5603 expand = RCS_getexpand (rcs);

--- 11 unchanged lines hidden (view full) ---

5615 so calling it simplifies RCS_cmp_file. We *could* just yank
5616 the delta node out of the version tree and look for device
5617 numbers, but writing to disk and calling xcmp is a better
5618 abstraction (therefore probably more robust). -twp */
5619
5620 if (preserve_perms)
5621 {
5622 char *tmp;
5623
5624 if (options != NULL && options[0] != '\0')
5625 binary = STREQ (options, "-kb");
5626 else
5627 {
5628 char *expand;
5629
5630 expand = RCS_getexpand (rcs);

--- 11 unchanged lines hidden (view full) ---

5642 so calling it simplifies RCS_cmp_file. We *could* just yank
5643 the delta node out of the version tree and look for device
5644 numbers, but writing to disk and calling xcmp is a better
5645 abstraction (therefore probably more robust). -twp */
5646
5647 if (preserve_perms)
5648 {
5649 char *tmp;
5650 int retcode;
5623
5624 tmp = cvs_temp_name();
5625 retcode = RCS_checkout(rcs, NULL, rev, NULL, options, tmp, NULL, NULL);
5626 if (retcode != 0)
5627 return 1;
5628
5629 retcode = xcmp (tmp, filename);
5630 if (CVS_UNLINK (tmp) < 0)
5631 error (0, errno, "cannot remove %s", tmp);
5632 free (tmp);
5633 return retcode;
5634 }
5635 else
5636#endif
5637 {
5651
5652 tmp = cvs_temp_name();
5653 retcode = RCS_checkout(rcs, NULL, rev, NULL, options, tmp, NULL, NULL);
5654 if (retcode != 0)
5655 return 1;
5656
5657 retcode = xcmp (tmp, filename);
5658 if (CVS_UNLINK (tmp) < 0)
5659 error (0, errno, "cannot remove %s", tmp);
5660 free (tmp);
5661 return retcode;
5662 }
5663 else
5664#endif
5665 {
5638 fp = CVS_FOPEN (filename, binary ? FOPEN_BINARY_READ : "r");
5666 FILE *fp;
5667 struct cmp_file_data data;
5668 const char *use_file1;
5669 char *tmpfile = NULL;
5670
5671 if (rev2 != NULL)
5672 {
5673 /* Open & cache rev1 */
5674 tmpfile = cvs_temp_name();
5675 if (RCS_checkout (rcs, NULL, rev1, NULL, options, tmpfile,
5676 (RCSCHECKOUTPROC)0, NULL))
5677 error (1, errno,
5678 "cannot check out revision %s of %s",
5679 rev1, rcs->path);
5680 use_file1 = tmpfile;
5681 if (rev1_cache != NULL)
5682 *rev1_cache = tmpfile;
5683 }
5684 else
5685 use_file1 = filename;
5686
5687 fp = CVS_FOPEN (use_file1, binary ? FOPEN_BINARY_READ : "r");
5639 if (fp == NULL)
5640 /* FIXME-update-dir: should include update_dir in message. */
5688 if (fp == NULL)
5689 /* FIXME-update-dir: should include update_dir in message. */
5641 error (1, errno, "cannot open file %s for comparing", filename);
5690 error (1, errno, "cannot open file %s for comparing", use_file1);
5642
5691
5643 data.filename = filename;
5692 data.filename = use_file1;
5644 data.fp = fp;
5645 data.different = 0;
5646
5693 data.fp = fp;
5694 data.different = 0;
5695
5647 retcode = RCS_checkout (rcs, (char *) NULL, rev, (char *) NULL,
5648 options, RUN_TTY, cmp_file_buffer,
5649 (void *) &data);
5696 if (RCS_checkout (rcs, (char *)NULL, rev2 ? rev2 : rev1,
5697 (char *)NULL, options, RUN_TTY, cmp_file_buffer,
5698 (void *)&data ))
5699 error (1, errno,
5700 "cannot check out revision %s of %s",
5701 rev2 ? rev2 : rev1, rcs->path);
5650
5651 /* If we have not yet found a difference, make sure that we are at
5652 the end of the file. */
5702
5703 /* If we have not yet found a difference, make sure that we are at
5704 the end of the file. */
5653 if (! data.different)
5705 if (!data.different)
5654 {
5655 if (getc (fp) != EOF)
5656 data.different = 1;
5657 }
5658
5659 fclose (fp);
5706 {
5707 if (getc (fp) != EOF)
5708 data.different = 1;
5709 }
5710
5711 fclose (fp);
5712 if (rev1_cache == NULL && tmpfile)
5713 {
5714 if (CVS_UNLINK (tmpfile ) < 0)
5715 error (0, errno, "cannot remove %s", tmpfile);
5716 free (tmpfile);
5717 }
5660
5718
5661 if (retcode != 0)
5662 return 1;
5663
5664 return data.different;
5665 }
5666}
5667
5719 return data.different;
5720 }
5721}
5722
5723
5724
5668/* This is a subroutine of RCS_cmp_file. It is passed to
5669 RCS_checkout. */
5725/* This is a subroutine of RCS_cmp_file. It is passed to
5726 RCS_checkout. */
5670
5671#define CMP_BUF_SIZE (8 * 1024)
5672
5673static void
5674cmp_file_buffer (callerdat, buffer, len)
5675 void *callerdat;
5676 const char *buffer;
5677 size_t len;
5678{
5727#define CMP_BUF_SIZE (8 * 1024)
5728
5729static void
5730cmp_file_buffer (callerdat, buffer, len)
5731 void *callerdat;
5732 const char *buffer;
5733 size_t len;
5734{
5679 struct cmp_file_data *data = (struct cmp_file_data *) callerdat;
5735 struct cmp_file_data *data = (struct cmp_file_data *)callerdat;
5680 char *filebuf;
5681
5682 /* If we've already found a difference, we don't need to check
5683 further. */
5684 if (data->different)
5685 return;
5686
5687 filebuf = xmalloc (len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len);

--- 22 unchanged lines hidden (view full) ---

5710
5711 buffer += checklen;
5712 len -= checklen;
5713 }
5714
5715 free (filebuf);
5716}
5717
5736 char *filebuf;
5737
5738 /* If we've already found a difference, we don't need to check
5739 further. */
5740 if (data->different)
5741 return;
5742
5743 filebuf = xmalloc (len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len);

--- 22 unchanged lines hidden (view full) ---

5766
5767 buffer += checklen;
5768 len -= checklen;
5769 }
5770
5771 free (filebuf);
5772}
5773
5774
5775
5718/* For RCS file RCS, make symbolic tag TAG point to revision REV.
5719 This validates that TAG is OK for a user to use. Return value is
5720 -1 for error (and errno is set to indicate the error), positive for
5721 error (and an error message has been printed), or zero for success. */
5722
5723int
5724RCS_settag (rcs, tag, rev)
5725 RCSNode *rcs;

--- 112 unchanged lines hidden (view full) ---

5838/* FIXME-twp: if a lock owned by someone else is broken, should this
5839 send mail to the lock owner? Prompt user? It seems like such an
5840 obscure situation for CVS as almost not worth worrying much
5841 about. */
5842
5843int
5844RCS_lock (rcs, rev, lock_quiet)
5845 RCSNode *rcs;
5776/* For RCS file RCS, make symbolic tag TAG point to revision REV.
5777 This validates that TAG is OK for a user to use. Return value is
5778 -1 for error (and errno is set to indicate the error), positive for
5779 error (and an error message has been printed), or zero for success. */
5780
5781int
5782RCS_settag (rcs, tag, rev)
5783 RCSNode *rcs;

--- 112 unchanged lines hidden (view full) ---

5896/* FIXME-twp: if a lock owned by someone else is broken, should this
5897 send mail to the lock owner? Prompt user? It seems like such an
5898 obscure situation for CVS as almost not worth worrying much
5899 about. */
5900
5901int
5902RCS_lock (rcs, rev, lock_quiet)
5903 RCSNode *rcs;
5846 char *rev;
5904 const char *rev;
5847 int lock_quiet;
5848{
5849 List *locks;
5850 Node *p;
5851 char *user;
5852 char *xrev = NULL;
5853
5854 if (rcs->flags & PARTIAL)

--- 47 unchanged lines hidden (view full) ---

5902 /* Break the lock. */
5903 if (!lock_quiet)
5904 {
5905 cvs_output (rev, 0);
5906 cvs_output (" unlocked\n", 0);
5907 }
5908 delnode (p);
5909#else
5905 int lock_quiet;
5906{
5907 List *locks;
5908 Node *p;
5909 char *user;
5910 char *xrev = NULL;
5911
5912 if (rcs->flags & PARTIAL)

--- 47 unchanged lines hidden (view full) ---

5960 /* Break the lock. */
5961 if (!lock_quiet)
5962 {
5963 cvs_output (rev, 0);
5964 cvs_output (" unlocked\n", 0);
5965 }
5966 delnode (p);
5967#else
5910 error (1, 0, "Revision %s is already locked by %s", xrev, p->data);
5968 error (1, 0, "Revision %s is already locked by %s", xrev, (char *)p->data);
5911#endif
5912 }
5913
5914 /* Create a new lock. */
5915 p = getnode();
5916 p->key = xrev; /* already xstrdupped */
5917 p->data = xstrdup (getcaller());
5918 (void) addnode_at_front (locks, p);

--- 99 unchanged lines hidden (view full) ---

6018 {
6019 /* If the revision is locked by someone else, notify
6020 them. Note that this shouldn't ever happen if RCS_unlock
6021 is called with a NULL revision, since that means "whatever
6022 revision is currently locked by the caller." */
6023 char *repos, *workfile;
6024 if (!unlock_quiet)
6025 error (0, 0, "\
5969#endif
5970 }
5971
5972 /* Create a new lock. */
5973 p = getnode();
5974 p->key = xrev; /* already xstrdupped */
5975 p->data = xstrdup (getcaller());
5976 (void) addnode_at_front (locks, p);

--- 99 unchanged lines hidden (view full) ---

6076 {
6077 /* If the revision is locked by someone else, notify
6078 them. Note that this shouldn't ever happen if RCS_unlock
6079 is called with a NULL revision, since that means "whatever
6080 revision is currently locked by the caller." */
6081 char *repos, *workfile;
6082 if (!unlock_quiet)
6083 error (0, 0, "\
6026%s: revision %s locked by %s; breaking lock", rcs->path, xrev, lock->data);
6084%s: revision %s locked by %s; breaking lock", rcs->path, xrev, (char *)lock->data);
6027 repos = xstrdup (rcs->path);
6028 workfile = strrchr (repos, '/');
6029 *workfile++ = '\0';
6030 notify_do ('C', workfile, user, NULL, NULL, repos);
6031 free (repos);
6032 }
6033
6034 delnode (lock);

--- 288 unchanged lines hidden (view full) ---

6323 before = xstrdup (branchpoint);
6324 *bp = '.';
6325 }
6326 }
6327 else if (! STREQ (rev1, branchpoint))
6328 {
6329 /* Walk deltas from BRANCHPOINT on, looking for REV1. */
6330 nodep = findnode (rcs->versions, branchpoint);
6085 repos = xstrdup (rcs->path);
6086 workfile = strrchr (repos, '/');
6087 *workfile++ = '\0';
6088 notify_do ('C', workfile, user, NULL, NULL, repos);
6089 free (repos);
6090 }
6091
6092 delnode (lock);

--- 288 unchanged lines hidden (view full) ---

6381 before = xstrdup (branchpoint);
6382 *bp = '.';
6383 }
6384 }
6385 else if (! STREQ (rev1, branchpoint))
6386 {
6387 /* Walk deltas from BRANCHPOINT on, looking for REV1. */
6388 nodep = findnode (rcs->versions, branchpoint);
6331 revp = (RCSVers *) nodep->data;
6389 revp = nodep->data;
6332 while (revp->next != NULL && ! STREQ (revp->next, rev1))
6333 {
6390 while (revp->next != NULL && ! STREQ (revp->next, rev1))
6391 {
6334 revp = (RCSVers *) nodep->data;
6392 revp = nodep->data;
6335 nodep = findnode (rcs->versions, revp->next);
6336 }
6337 if (revp->next == NULL)
6338 {
6339 error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, rev1);
6340 goto delrev_done;
6341 }
6342 if (rev1_inclusive)

--- 27 unchanged lines hidden (view full) ---

6370 /* If any revision between REV1 and REV2 is locked or is a branch point,
6371 we can't delete that revision and must abort. */
6372 after = NULL;
6373 next = rev1;
6374 found = 0;
6375 while (!found && next != NULL)
6376 {
6377 nodep = findnode (rcs->versions, next);
6393 nodep = findnode (rcs->versions, revp->next);
6394 }
6395 if (revp->next == NULL)
6396 {
6397 error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, rev1);
6398 goto delrev_done;
6399 }
6400 if (rev1_inclusive)

--- 27 unchanged lines hidden (view full) ---

6428 /* If any revision between REV1 and REV2 is locked or is a branch point,
6429 we can't delete that revision and must abort. */
6430 after = NULL;
6431 next = rev1;
6432 found = 0;
6433 while (!found && next != NULL)
6434 {
6435 nodep = findnode (rcs->versions, next);
6378 revp = (RCSVers *) nodep->data;
6436 revp = nodep->data;
6379
6380 if (rev2 != NULL)
6381 found = STREQ (revp->version, rev2);
6382 next = revp->next;
6383
6384 if ((!found && next != NULL) || rev2_inclusive || rev2 == NULL)
6385 {
6386 if (findnode (RCS_getlocks (rcs), revp->version))

--- 87 unchanged lines hidden (view full) ---

6474 RCS_exec_rcsdiff with some changes, like being able
6475 to suppress diagnostic messages and to direct output. */
6476
6477 if (after != NULL)
6478 {
6479 char *diffbuf;
6480 size_t bufsize, len;
6481
6437
6438 if (rev2 != NULL)
6439 found = STREQ (revp->version, rev2);
6440 next = revp->next;
6441
6442 if ((!found && next != NULL) || rev2_inclusive || rev2 == NULL)
6443 {
6444 if (findnode (RCS_getlocks (rcs), revp->version))

--- 87 unchanged lines hidden (view full) ---

6532 RCS_exec_rcsdiff with some changes, like being able
6533 to suppress diagnostic messages and to direct output. */
6534
6535 if (after != NULL)
6536 {
6537 char *diffbuf;
6538 size_t bufsize, len;
6539
6482#if defined (__CYGWIN32__) || defined (_WIN32)
6540#if defined (WOE32) && !defined (__CYGWIN32__)
6483 /* FIXME: This is an awful kludge, but at least until I have
6484 time to work on it a little more and test it, I'd rather
6485 give a fatal error than corrupt the file. I think that we
6486 need to use "-kb" and "--binary" and "rb" to get_file
6487 (probably can do it always, not just for binary files, if
6488 we are consistent between the RCS_checkout and the diff). */
6489 {
6490 char *expand = RCS_getexpand (rcs);
6491 if (expand != NULL && STREQ (expand, "b"))
6492 error (1, 0,
6493 "admin -o not implemented yet for binary on this system");
6494 }
6541 /* FIXME: This is an awful kludge, but at least until I have
6542 time to work on it a little more and test it, I'd rather
6543 give a fatal error than corrupt the file. I think that we
6544 need to use "-kb" and "--binary" and "rb" to get_file
6545 (probably can do it always, not just for binary files, if
6546 we are consistent between the RCS_checkout and the diff). */
6547 {
6548 char *expand = RCS_getexpand (rcs);
6549 if (expand != NULL && STREQ (expand, "b"))
6550 error (1, 0,
6551 "admin -o not implemented yet for binary on this system");
6552 }
6495#endif
6553#endif /* WOE32 */
6496
6497 afterfile = cvs_temp_name();
6498 status = RCS_checkout (rcs, NULL, after, NULL, "-ko", afterfile,
6499 (RCSCHECKOUTPROC)0, NULL);
6500 if (status > 0)
6501 goto delrev_done;
6502
6503 if (before == NULL)

--- 38 unchanged lines hidden (view full) ---

6542
6543 diffbuf = NULL;
6544 bufsize = 0;
6545 get_file (outfile, outfile, "r", &diffbuf, &bufsize, &len);
6546 }
6547
6548 /* Save the new change text in after's delta node. */
6549 nodep = findnode (rcs->versions, after);
6554
6555 afterfile = cvs_temp_name();
6556 status = RCS_checkout (rcs, NULL, after, NULL, "-ko", afterfile,
6557 (RCSCHECKOUTPROC)0, NULL);
6558 if (status > 0)
6559 goto delrev_done;
6560
6561 if (before == NULL)

--- 38 unchanged lines hidden (view full) ---

6600
6601 diffbuf = NULL;
6602 bufsize = 0;
6603 get_file (outfile, outfile, "r", &diffbuf, &bufsize, &len);
6604 }
6605
6606 /* Save the new change text in after's delta node. */
6607 nodep = findnode (rcs->versions, after);
6550 revp = (RCSVers *) nodep->data;
6608 revp = nodep->data;
6551
6552 assert (revp->text == NULL);
6553
6554 revp->text = (Deltatext *) xmalloc (sizeof (Deltatext));
6555 memset ((Deltatext *) revp->text, 0, sizeof (Deltatext));
6556 revp->text->version = xstrdup (revp->version);
6557 revp->text->text = diffbuf;
6558 revp->text->len = len;

--- 11 unchanged lines hidden (view full) ---

6570 /* Walk through the revisions (again) to mark each one as
6571 outdated. (FIXME: would it be safe to use the `dead' field for
6572 this? Doubtful.) */
6573 for (next = rev1;
6574 next != NULL && (after == NULL || ! STREQ (next, after));
6575 next = revp->next)
6576 {
6577 nodep = findnode (rcs->versions, next);
6609
6610 assert (revp->text == NULL);
6611
6612 revp->text = (Deltatext *) xmalloc (sizeof (Deltatext));
6613 memset ((Deltatext *) revp->text, 0, sizeof (Deltatext));
6614 revp->text->version = xstrdup (revp->version);
6615 revp->text->text = diffbuf;
6616 revp->text->len = len;

--- 11 unchanged lines hidden (view full) ---

6628 /* Walk through the revisions (again) to mark each one as
6629 outdated. (FIXME: would it be safe to use the `dead' field for
6630 this? Doubtful.) */
6631 for (next = rev1;
6632 next != NULL && (after == NULL || ! STREQ (next, after));
6633 next = revp->next)
6634 {
6635 nodep = findnode (rcs->versions, next);
6578 revp = (RCSVers *) nodep->data;
6636 revp = nodep->data;
6579 revp->outdated = 1;
6580 }
6581
6582 /* Update delta links. If BEFORE == NULL, we're changing the
6583 head of the tree and don't need to update any `next' links. */
6584 if (before != NULL)
6585 {
6586 /* If REV1 is the first node on its branch, then BEFORE is its

--- 7 unchanged lines hidden (view full) ---

6594
6595 if (rev1 == NULL)
6596 /* beforep's ->next field already should be equal to after,
6597 which I think is always NULL in this case. */
6598 ;
6599 else if (STREQ (rev1, branchpoint))
6600 {
6601 nodep = findnode (rcs->versions, before);
6637 revp->outdated = 1;
6638 }
6639
6640 /* Update delta links. If BEFORE == NULL, we're changing the
6641 head of the tree and don't need to update any `next' links. */
6642 if (before != NULL)
6643 {
6644 /* If REV1 is the first node on its branch, then BEFORE is its

--- 7 unchanged lines hidden (view full) ---

6652
6653 if (rev1 == NULL)
6654 /* beforep's ->next field already should be equal to after,
6655 which I think is always NULL in this case. */
6656 ;
6657 else if (STREQ (rev1, branchpoint))
6658 {
6659 nodep = findnode (rcs->versions, before);
6602 revp = (RCSVers *) nodep->data;
6660 revp = nodep->data;
6603 nodep = revp->branches->list->next;
6604 while (nodep != revp->branches->list &&
6605 ! STREQ (nodep->key, rev1))
6606 nodep = nodep->next;
6607 assert (nodep != revp->branches->list);
6608 if (after == NULL)
6609 delnode (nodep);
6610 else
6611 {
6612 free (nodep->key);
6613 nodep->key = xstrdup (after);
6614 }
6615 }
6616 else
6617 {
6618 nodep = findnode (rcs->versions, before);
6661 nodep = revp->branches->list->next;
6662 while (nodep != revp->branches->list &&
6663 ! STREQ (nodep->key, rev1))
6664 nodep = nodep->next;
6665 assert (nodep != revp->branches->list);
6666 if (after == NULL)
6667 delnode (nodep);
6668 else
6669 {
6670 free (nodep->key);
6671 nodep->key = xstrdup (after);
6672 }
6673 }
6674 else
6675 {
6676 nodep = findnode (rcs->versions, before);
6619 beforep = (RCSVers *) nodep->data;
6677 beforep = nodep->data;
6620 free (beforep->next);
6621 beforep->next = xstrdup (after);
6622 }
6623 }
6624
6625 status = 0;
6626
6627 delrev_done:

--- 540 unchanged lines hidden (view full) ---

7168
7169 On error, give a fatal error. */
7170
7171void
7172RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
7173 RCSNode *rcs;
7174 FILE *fp;
7175 struct rcsbuffer *rcsbuf;
6678 free (beforep->next);
6679 beforep->next = xstrdup (after);
6680 }
6681 }
6682
6683 status = 0;
6684
6685 delrev_done:

--- 540 unchanged lines hidden (view full) ---

7226
7227 On error, give a fatal error. */
7228
7229void
7230RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
7231 RCSNode *rcs;
7232 FILE *fp;
7233 struct rcsbuffer *rcsbuf;
7176 char *version;
7234 const char *version;
7177 enum rcs_delta_op op;
7178 char **text;
7179 size_t *len;
7180 char **log;
7181 size_t *loglen;
7182{
7183 struct rcsbuffer rcsbuf_local;
7184 char *branchversion;

--- 61 unchanged lines hidden (view full) ---

7246 if (node == NULL)
7247 error (1, 0,
7248 "mismatch in rcs file %s between deltas and deltatexts (%s)",
7249 rcs->path, key);
7250
7251 /* Stash the previous version. */
7252 prev_vers = vers;
7253
7235 enum rcs_delta_op op;
7236 char **text;
7237 size_t *len;
7238 char **log;
7239 size_t *loglen;
7240{
7241 struct rcsbuffer rcsbuf_local;
7242 char *branchversion;

--- 61 unchanged lines hidden (view full) ---

7304 if (node == NULL)
7305 error (1, 0,
7306 "mismatch in rcs file %s between deltas and deltatexts (%s)",
7307 rcs->path, key);
7308
7309 /* Stash the previous version. */
7310 prev_vers = vers;
7311
7254 vers = (RCSVers *) node->data;
7312 vers = node->data;
7255 next = vers->next;
7256
7257 /* Compare key and trunkversion now, because key points to
7258 storage controlled by rcsbuf_getkey. */
7259 if (STREQ (branchversion, key))
7260 isversion = 1;
7261 else
7262 isversion = 0;

--- 552 unchanged lines hidden (view full) ---

7815
7816/* putlock_proc is like putsymbol_proc, but key and data are reversed. */
7817
7818static int
7819putlock_proc (symnode, fp)
7820 Node *symnode;
7821 void *fp;
7822{
7313 next = vers->next;
7314
7315 /* Compare key and trunkversion now, because key points to
7316 storage controlled by rcsbuf_getkey. */
7317 if (STREQ (branchversion, key))
7318 isversion = 1;
7319 else
7320 isversion = 0;

--- 552 unchanged lines hidden (view full) ---

7873
7874/* putlock_proc is like putsymbol_proc, but key and data are reversed. */
7875
7876static int
7877putlock_proc (symnode, fp)
7878 Node *symnode;
7879 void *fp;
7880{
7823 return fprintf ((FILE *) fp, "\n\t%s:%s", symnode->data, symnode->key);
7881 return fprintf ((FILE *) fp, "\n\t%s:%s", (char *)symnode->data, symnode->key);
7824}
7825
7826static int
7827putrcsfield_proc (node, vfp)
7828 Node *node;
7829 void *vfp;
7830{
7831 FILE *fp = (FILE *) vfp;

--- 179 unchanged lines hidden (view full) ---

8011 p = findnode (rcs->versions, rev);
8012 if (p == NULL)
8013 {
8014 error (1, 0,
8015 "error parsing repository file %s, file may be corrupt.",
8016 rcs->path);
8017 }
8018
7882}
7883
7884static int
7885putrcsfield_proc (node, vfp)
7886 Node *node;
7887 void *vfp;
7888{
7889 FILE *fp = (FILE *) vfp;

--- 179 unchanged lines hidden (view full) ---

8069 p = findnode (rcs->versions, rev);
8070 if (p == NULL)
8071 {
8072 error (1, 0,
8073 "error parsing repository file %s, file may be corrupt.",
8074 rcs->path);
8075 }
8076
8019 versp = (RCSVers *) p->data;
8077 versp = p->data;
8020
8021 /* Print the delta node and recurse on its `next' node. This prints
8022 the trunk. If there are any branches printed on this revision,
8023 print those trunks as well. */
8024 putdelta (versp, fp);
8025 RCS_putdtree (rcs, versp->next, fp);
8026 if (versp->branches != NULL)
8027 {

--- 100 unchanged lines hidden (view full) ---

8128 if (found && insertbefore)
8129 {
8130 putdeltatext (fout, newdtext);
8131 newdtext = NULL;
8132 insertpt = NULL;
8133 }
8134
8135 np = findnode (rcs->versions, dtext->version);
8078
8079 /* Print the delta node and recurse on its `next' node. This prints
8080 the trunk. If there are any branches printed on this revision,
8081 print those trunks as well. */
8082 putdelta (versp, fp);
8083 RCS_putdtree (rcs, versp->next, fp);
8084 if (versp->branches != NULL)
8085 {

--- 100 unchanged lines hidden (view full) ---

8186 if (found && insertbefore)
8187 {
8188 putdeltatext (fout, newdtext);
8189 newdtext = NULL;
8190 insertpt = NULL;
8191 }
8192
8193 np = findnode (rcs->versions, dtext->version);
8136 dadmin = (RCSVers *) np->data;
8194 dadmin = np->data;
8137
8138 /* If this revision has been outdated, just skip it. */
8139 if (dadmin->outdated)
8140 {
8141 freedeltatext (dtext);
8142 --actions;
8143 continue;
8144 }

--- 95 unchanged lines hidden (view full) ---

8240 to count the number of RCS revisions for which some special action
8241 is required. */
8242
8243static int
8244count_delta_actions (np, ignore)
8245 Node *np;
8246 void *ignore;
8247{
8195
8196 /* If this revision has been outdated, just skip it. */
8197 if (dadmin->outdated)
8198 {
8199 freedeltatext (dtext);
8200 --actions;
8201 continue;
8202 }

--- 95 unchanged lines hidden (view full) ---

8298 to count the number of RCS revisions for which some special action
8299 is required. */
8300
8301static int
8302count_delta_actions (np, ignore)
8303 Node *np;
8304 void *ignore;
8305{
8248 RCSVers *dadmin;
8306 RCSVers *dadmin = np->data;
8249
8307
8250 dadmin = (RCSVers *) np->data;
8251
8252 if (dadmin->outdated)
8253 return 1;
8254
8255 if (dadmin->text != NULL
8256 && (dadmin->text->log != NULL || dadmin->text->text != NULL))
8257 {
8258 return 1;
8259 }

--- 176 unchanged lines hidden (view full) ---

8436 char *tmp = rcs_lockfile;
8437 rcs_lockfile = NULL;
8438 free (tmp);
8439 }
8440}
8441
8442static char *
8443rcs_lockfilename (rcsfile)
8308 if (dadmin->outdated)
8309 return 1;
8310
8311 if (dadmin->text != NULL
8312 && (dadmin->text->log != NULL || dadmin->text->text != NULL))
8313 {
8314 return 1;
8315 }

--- 176 unchanged lines hidden (view full) ---

8492 char *tmp = rcs_lockfile;
8493 rcs_lockfile = NULL;
8494 free (tmp);
8495 }
8496}
8497
8498static char *
8499rcs_lockfilename (rcsfile)
8444 char *rcsfile;
8500 const char *rcsfile;
8445{
8446 char *lockfile, *lockp;
8501{
8502 char *lockfile, *lockp;
8447 char *rcsbase, *rcsp, *rcsend;
8503 const char *rcsbase, *rcsp, *rcsend;
8448 int rcslen;
8449
8450 /* Create the lockfile name. */
8451 rcslen = strlen (rcsfile);
8452 lockfile = (char *) xmalloc (rcslen + 10);
8453 rcsbase = last_component (rcsfile);
8454 rcsend = rcsfile + rcslen - sizeof(RCSEXT);
8455 for (lockp = lockfile, rcsp = rcsfile; rcsp < rcsbase; ++rcsp)

--- 91 unchanged lines hidden (view full) ---

8547 *
8548 * /dev/null is not statted but assumed to have been created on the Epoch.
8549 * At least using the POSIX.2 definition of patch, this should cause creation
8550 * of files on platforms such as Windoze where the null IO device isn't named
8551 * /dev/null to be parsed by patch properly.
8552 */
8553char *
8554make_file_label (path, rev, rcs)
8504 int rcslen;
8505
8506 /* Create the lockfile name. */
8507 rcslen = strlen (rcsfile);
8508 lockfile = (char *) xmalloc (rcslen + 10);
8509 rcsbase = last_component (rcsfile);
8510 rcsend = rcsfile + rcslen - sizeof(RCSEXT);
8511 for (lockp = lockfile, rcsp = rcsfile; rcsp < rcsbase; ++rcsp)

--- 91 unchanged lines hidden (view full) ---

8603 *
8604 * /dev/null is not statted but assumed to have been created on the Epoch.
8605 * At least using the POSIX.2 definition of patch, this should cause creation
8606 * of files on platforms such as Windoze where the null IO device isn't named
8607 * /dev/null to be parsed by patch properly.
8608 */
8609char *
8610make_file_label (path, rev, rcs)
8555 char *path;
8556 char *rev;
8611 const char *path;
8612 const char *rev;
8557 RCSNode *rcs;
8558{
8559 char datebuf[MAXDATELEN + 1];
8560 char *label;
8561
8562 label = (char *) xmalloc (strlen (path)
8563 + (rev == NULL ? 0 : strlen (rev) + 1)
8564 + MAXDATELEN

--- 6 unchanged lines hidden (view full) ---

8571 assert (strcmp(DEVNULL, path));
8572 RCS_getrevtime (rcs, rev, datebuf, 0);
8573 (void) date_to_internet (date, datebuf);
8574 (void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
8575 }
8576 else
8577 {
8578 struct stat sb;
8613 RCSNode *rcs;
8614{
8615 char datebuf[MAXDATELEN + 1];
8616 char *label;
8617
8618 label = (char *) xmalloc (strlen (path)
8619 + (rev == NULL ? 0 : strlen (rev) + 1)
8620 + MAXDATELEN

--- 6 unchanged lines hidden (view full) ---

8627 assert (strcmp(DEVNULL, path));
8628 RCS_getrevtime (rcs, rev, datebuf, 0);
8629 (void) date_to_internet (date, datebuf);
8630 (void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
8631 }
8632 else
8633 {
8634 struct stat sb;
8579 struct tm *wm = NULL;
8635 struct tm *wm;
8580
8581 if (strcmp(DEVNULL, path))
8582 {
8636
8637 if (strcmp(DEVNULL, path))
8638 {
8583 char *file = last_component (path);
8639 const char *file = last_component (path);
8584 if (CVS_STAT (file, &sb) < 0)
8640 if (CVS_STAT (file, &sb) < 0)
8585 error (0, 1, "could not get info for `%s'", path);
8586 else
8587 wm = gmtime (&sb.st_mtime);
8641 /* Assume that if the stat fails,then the later read for the
8642 * diff will too.
8643 */
8644 error (1, errno, "could not get info for `%s'", path);
8645 wm = gmtime (&sb.st_mtime);
8588 }
8589 else
8590 {
8591 time_t t = 0;
8592 wm = gmtime(&t);
8593 }
8594
8646 }
8647 else
8648 {
8649 time_t t = 0;
8650 wm = gmtime(&t);
8651 }
8652
8595 if (wm)
8596 {
8597 (void) tm_to_internet (datebuf, wm);
8598 (void) sprintf (label, "-L%s\t%s", path, datebuf);
8599 }
8653 (void) tm_to_internet (datebuf, wm);
8654 (void) sprintf (label, "-L%s\t%s", path, datebuf);
8600 }
8601 return label;
8602}
8603
8604void
8605RCS_setlocalid (arg)
8606 const char *arg;
8607{

--- 97 unchanged lines hidden ---
8655 }
8656 return label;
8657}
8658
8659void
8660RCS_setlocalid (arg)
8661 const char *arg;
8662{

--- 97 unchanged lines hidden ---