Deleted Added
full compact
rcscmds.c (107487) rcscmds.c (128269)
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
4 *
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
7 *
8 * The functions in this file provide an interface for performing
9 * operations directly on RCS files.
10 *
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
4 *
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
7 *
8 * The functions in this file provide an interface for performing
9 * operations directly on RCS files.
10 *
11 * $FreeBSD: head/contrib/cvs/src/rcscmds.c 107487 2002-12-02 03:17:49Z peter $
11 * $FreeBSD: head/contrib/cvs/src/rcscmds.c 128269 2004-04-15 01:17:28Z peter $
12 */
13
14#include "cvs.h"
15#include <assert.h>
16#include <stdio.h>
17#include "diffrun.h"
18
19/* This file, rcs.h, and rcs.c, together sometimes known as the "RCS

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

48 RCS and CVS must preserve the current ability to import/export it
49 (preferably improved--magic branches are currently a roadblock).
50 See doc/RCSFILES in the CVS distribution for documentation of this
51 file format.
52
53 On a related note, see the comments at diff_exec, later in this file,
54 for more on the diff library. */
55
12 */
13
14#include "cvs.h"
15#include <assert.h>
16#include <stdio.h>
17#include "diffrun.h"
18
19/* This file, rcs.h, and rcs.c, together sometimes known as the "RCS

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

48 RCS and CVS must preserve the current ability to import/export it
49 (preferably improved--magic branches are currently a roadblock).
50 See doc/RCSFILES in the CVS distribution for documentation of this
51 file format.
52
53 On a related note, see the comments at diff_exec, later in this file,
54 for more on the diff library. */
55
56static void RCS_output_diff_options PROTO ((char *, char *, char *, char *));
56static void RCS_output_diff_options PROTO ((const char *, const char *,
57 const char *, const char *));
57
58
59/* Stuff to deal with passing arguments the way libdiff.a wants to deal
60 with them. This is a crufty interface; there is no good reason for it
61 to resemble a command line rather than something closer to "struct
62 log_data" in log.c. */
63
64/* First call call_diff_setup to setup any initial arguments. The

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

71 Finally, call call_diff or call_diff3 to produce the diffs. */
72
73static char **call_diff_argv;
74static int call_diff_argc;
75static int call_diff_argc_allocated;
76
77static void call_diff_add_arg PROTO ((const char *));
78static void call_diff_setup PROTO ((const char *prog));
58
59
60/* Stuff to deal with passing arguments the way libdiff.a wants to deal
61 with them. This is a crufty interface; there is no good reason for it
62 to resemble a command line rather than something closer to "struct
63 log_data" in log.c. */
64
65/* First call call_diff_setup to setup any initial arguments. The

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

72 Finally, call call_diff or call_diff3 to produce the diffs. */
73
74static char **call_diff_argv;
75static int call_diff_argc;
76static int call_diff_argc_allocated;
77
78static void call_diff_add_arg PROTO ((const char *));
79static void call_diff_setup PROTO ((const char *prog));
79static int call_diff PROTO ((char *out));
80static int call_diff PROTO ((const char *out));
80static int call_diff3 PROTO ((char *out));
81
82static void call_diff_write_output PROTO((const char *, size_t));
83static void call_diff_flush_output PROTO((void));
84static void call_diff_write_stdout PROTO((const char *));
85static void call_diff_error PROTO((const char *, const char *, const char *));
86
87/* VARARGS */

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

201static struct diff_callbacks call_diff_file_callbacks =
202{
203 (void (*) PROTO((const char *, size_t))) NULL,
204 (void (*) PROTO((void))) NULL,
205 call_diff_write_stdout,
206 call_diff_error
207};
208
81static int call_diff3 PROTO ((char *out));
82
83static void call_diff_write_output PROTO((const char *, size_t));
84static void call_diff_flush_output PROTO((void));
85static void call_diff_write_stdout PROTO((const char *));
86static void call_diff_error PROTO((const char *, const char *, const char *));
87
88/* VARARGS */

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

202static struct diff_callbacks call_diff_file_callbacks =
203{
204 (void (*) PROTO((const char *, size_t))) NULL,
205 (void (*) PROTO((void))) NULL,
206 call_diff_write_stdout,
207 call_diff_error
208};
209
210
211
209static int
210call_diff (out)
212static int
213call_diff (out)
211 char *out;
214 const char *out;
212{
213 if (out == RUN_TTY)
214 return diff_run (call_diff_argc, call_diff_argv, NULL,
215 &call_diff_stdout_callbacks);
216 else
217 return diff_run (call_diff_argc, call_diff_argv, out,
218 &call_diff_file_callbacks);
219}
220
215{
216 if (out == RUN_TTY)
217 return diff_run (call_diff_argc, call_diff_argv, NULL,
218 &call_diff_stdout_callbacks);
219 else
220 return diff_run (call_diff_argc, call_diff_argv, out,
221 &call_diff_file_callbacks);
222}
223
224
225
221static int
222call_diff3 (out)
223 char *out;
224{
225 if (out == RUN_TTY)
226 return diff3_run (call_diff_argc, call_diff_argv, NULL,
227 &call_diff_stdout_callbacks);
228 else
229 return diff3_run (call_diff_argc, call_diff_argv, out,
230 &call_diff_file_callbacks);
231}
232
233
234
235/* Merge revisions REV1 and REV2. */
236
237int
238RCS_merge(rcs, path, workfile, options, rev1, rev2)
239 RCSNode *rcs;
226static int
227call_diff3 (out)
228 char *out;
229{
230 if (out == RUN_TTY)
231 return diff3_run (call_diff_argc, call_diff_argv, NULL,
232 &call_diff_stdout_callbacks);
233 else
234 return diff3_run (call_diff_argc, call_diff_argv, out,
235 &call_diff_file_callbacks);
236}
237
238
239
240/* Merge revisions REV1 and REV2. */
241
242int
243RCS_merge(rcs, path, workfile, options, rev1, rev2)
244 RCSNode *rcs;
240 char *path;
241 char *workfile;
242 char *options;
243 char *rev1;
244 char *rev2;
245 const char *path;
246 const char *workfile;
247 const char *options;
248 const char *rev1;
249 const char *rev2;
245{
246 char *xrev1, *xrev2;
247 char *tmp1, *tmp2;
248 char *diffout = NULL;
249 int retval;
250
251 if (options != NULL && options[0] != '\0')
252 assert (options[0] == '-' && options[1] == 'k');

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

305
306 call_diff_arg ("-L");
307 call_diff_arg (workfile);
308 call_diff_arg ("-L");
309 call_diff_arg (xrev1);
310 call_diff_arg ("-L");
311 call_diff_arg (xrev2);
312
250{
251 char *xrev1, *xrev2;
252 char *tmp1, *tmp2;
253 char *diffout = NULL;
254 int retval;
255
256 if (options != NULL && options[0] != '\0')
257 assert (options[0] == '-' && options[1] == 'k');

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

310
311 call_diff_arg ("-L");
312 call_diff_arg (workfile);
313 call_diff_arg ("-L");
314 call_diff_arg (xrev1);
315 call_diff_arg ("-L");
316 call_diff_arg (xrev2);
317
318 call_diff_arg ("--");
313 call_diff_arg (workfile);
314 call_diff_arg (tmp1);
315 call_diff_arg (tmp2);
316
317 retval = call_diff3 (diffout);
318
319 if (retval == 1)
320 cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);

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

373 This used to exec rcsdiff, but now calls RCS_checkout and diff_exec.
374
375 An issue is what timezone is used for the dates which appear in the
376 diff output. rcsdiff uses the -z flag, which is not presently
377 processed by CVS diff, but I'm not sure exactly how hard to worry
378 about this--any such features are undocumented in the context of
379 CVS, and I'm not sure how important to users. */
380int
319 call_diff_arg (workfile);
320 call_diff_arg (tmp1);
321 call_diff_arg (tmp2);
322
323 retval = call_diff3 (diffout);
324
325 if (retval == 1)
326 cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);

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

379 This used to exec rcsdiff, but now calls RCS_checkout and diff_exec.
380
381 An issue is what timezone is used for the dates which appear in the
382 diff output. rcsdiff uses the -z flag, which is not presently
383 processed by CVS diff, but I'm not sure exactly how hard to worry
384 about this--any such features are undocumented in the context of
385 CVS, and I'm not sure how important to users. */
386int
381RCS_exec_rcsdiff (rcsfile, opts, options, rev1, rev2, label1, label2, workfile)
387RCS_exec_rcsdiff(rcsfile, opts, options, rev1, rev1_cache, rev2,
388 label1, label2, workfile )
382 RCSNode *rcsfile;
389 RCSNode *rcsfile;
383 char *opts;
384 char *options;
385 char *rev1;
386 char *rev2;
387 char *label1;
388 char *label2;
389 char *workfile;
390 const char *opts;
391 const char *options;
392 const char *rev1;
393 const char *rev1_cache;
394 const char *rev2;
395 const char *label1;
396 const char *label2;
397 const char *workfile;
390{
398{
391 char *tmpfile1;
392 char *tmpfile2;
393 char *use_file2;
399 char *tmpfile1 = NULL;
400 char *tmpfile2 = NULL;
401 const char *use_file1, *use_file2;
394 int status, retval;
395
402 int status, retval;
403
396 tmpfile1 = cvs_temp_name ();
397 tmpfile2 = NULL;
398
399 cvs_output ("\
400===================================================================\n\
401RCS file: ", 0);
402 cvs_output (rcsfile->path, 0);
403 cvs_output ("\n", 1);
404
405 /* Historically, `cvs diff' has expanded the $Name keyword to the
406 empty string when checking out revisions. This is an accident,
407 but no one has considered the issue thoroughly enough to determine
408 what the best behavior is. Passing NULL for the `nametag' argument
409 preserves the existing behavior. */
410
411 cvs_output ("retrieving revision ", 0);
412 cvs_output (rev1, 0);
413 cvs_output ("\n", 1);
404
405 cvs_output ("\
406===================================================================\n\
407RCS file: ", 0);
408 cvs_output (rcsfile->path, 0);
409 cvs_output ("\n", 1);
410
411 /* Historically, `cvs diff' has expanded the $Name keyword to the
412 empty string when checking out revisions. This is an accident,
413 but no one has considered the issue thoroughly enough to determine
414 what the best behavior is. Passing NULL for the `nametag' argument
415 preserves the existing behavior. */
416
417 cvs_output ("retrieving revision ", 0);
418 cvs_output (rev1, 0);
419 cvs_output ("\n", 1);
414 status = RCS_checkout (rcsfile, NULL, rev1, NULL, options, tmpfile1,
415 (RCSCHECKOUTPROC)0, NULL);
416 if (status > 0)
420
421 if (rev1_cache != NULL)
422 use_file1 = rev1_cache;
423 else
417 {
424 {
418 retval = status;
419 goto error_return;
425 tmpfile1 = cvs_temp_name();
426 status = RCS_checkout (rcsfile, NULL, rev1, NULL, options, tmpfile1,
427 (RCSCHECKOUTPROC)0, NULL);
428 if (status > 0)
429 {
430 retval = status;
431 goto error_return;
432 }
433 else if (status < 0)
434 {
435 error( 0, errno,
436 "cannot check out revision %s of %s", rev1, rcsfile->path );
437 retval = 1;
438 goto error_return;
439 }
440 use_file1 = tmpfile1;
420 }
441 }
421 else if (status < 0)
422 {
423 error (0, errno,
424 "cannot check out revision %s of %s", rev1, rcsfile->path);
425 retval = 1;
426 goto error_return;
427 }
428
429 if (rev2 == NULL)
430 {
431 assert (workfile != NULL);
432 use_file2 = workfile;
433 }
434 else
435 {

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

449 error (0, errno,
450 "cannot check out revision %s of %s", rev2, rcsfile->path);
451 return 1;
452 }
453 use_file2 = tmpfile2;
454 }
455
456 RCS_output_diff_options (opts, rev1, rev2, workfile);
442
443 if (rev2 == NULL)
444 {
445 assert (workfile != NULL);
446 use_file2 = workfile;
447 }
448 else
449 {

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

463 error (0, errno,
464 "cannot check out revision %s of %s", rev2, rcsfile->path);
465 return 1;
466 }
467 use_file2 = tmpfile2;
468 }
469
470 RCS_output_diff_options (opts, rev1, rev2, workfile);
457 status = diff_exec (tmpfile1, use_file2, label1, label2, opts, RUN_TTY);
471 status = diff_exec( use_file1, use_file2, label1, label2, opts, RUN_TTY );
458 if (status >= 0)
459 {
460 retval = status;
461 goto error_return;
462 }
463 else if (status < 0)
464 {
465 error (0, errno,
472 if (status >= 0)
473 {
474 retval = status;
475 goto error_return;
476 }
477 else if (status < 0)
478 {
479 error (0, errno,
466 "cannot diff %s and %s", tmpfile1, use_file2);
480 "cannot diff %s and %s", use_file1, use_file2);
467 retval = 1;
468 goto error_return;
469 }
470
471 error_return:
472 {
481 retval = 1;
482 goto error_return;
483 }
484
485 error_return:
486 {
473 int save_noexec = noexec;
474 noexec = 0;
475 if (unlink_file (tmpfile1) < 0)
487 /* Call CVS_UNLINK() below rather than unlink_file to avoid the check
488 * for noexec.
489 */
490 if( tmpfile1 != NULL )
476 {
491 {
477 if (!existence_error (errno))
478 error (0, errno, "cannot remove temp file %s", tmpfile1);
492 if( CVS_UNLINK( tmpfile1 ) < 0 )
493 {
494 if( !existence_error( errno ) )
495 error( 0, errno, "cannot remove temp file %s", tmpfile1 );
496 }
497 free( tmpfile1 );
479 }
498 }
480 noexec = save_noexec;
481 }
482 free (tmpfile1);
483 if (tmpfile2 != NULL)
484 {
485 int save_noexec = noexec;
486 noexec = 0;
487 if (unlink_file (tmpfile2) < 0)
499 if( tmpfile2 != NULL )
488 {
500 {
489 if (!existence_error (errno))
490 error (0, errno, "cannot remove temp file %s", tmpfile2);
501 if( CVS_UNLINK( tmpfile2 ) < 0 )
502 {
503 if( !existence_error( errno ) )
504 error( 0, errno, "cannot remove temp file %s", tmpfile2 );
505 }
506 free (tmpfile2);
491 }
507 }
492 noexec = save_noexec;
493 free (tmpfile2);
494 }
495
496 return retval;
497}
498
499
508 }
509
510 return retval;
511}
512
513
514
500/* Show differences between two files. This is the start of a diff library.
501
502 Some issues:
503
504 * Should option parsing be part of the library or the caller? The
505 former allows the library to add options without changing the callers,
506 but it causes various problems. One is that something like --brief really
507 wants special handling in CVS, and probably the caller should retain

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

528 OUT is a filename to send the diffs to, or RUN_TTY to send them to
529 stdout. Error messages go to stderr. Return value is 0 for
530 success, -1 for a failure which set errno, 1 for success (and some
531 differences were found), or >1 for a failure which printed a
532 message on stderr. */
533
534int
535diff_exec (file1, file2, label1, label2, options, out)
515/* Show differences between two files. This is the start of a diff library.
516
517 Some issues:
518
519 * Should option parsing be part of the library or the caller? The
520 former allows the library to add options without changing the callers,
521 but it causes various problems. One is that something like --brief really
522 wants special handling in CVS, and probably the caller should retain

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

543 OUT is a filename to send the diffs to, or RUN_TTY to send them to
544 stdout. Error messages go to stderr. Return value is 0 for
545 success, -1 for a failure which set errno, 1 for success (and some
546 differences were found), or >1 for a failure which printed a
547 message on stderr. */
548
549int
550diff_exec (file1, file2, label1, label2, options, out)
536 char *file1;
537 char *file2;
538 char *label1;
539 char *label2;
540 char *options;
541 char *out;
551 const char *file1;
552 const char *file2;
553 const char *label1;
554 const char *label2;
555 const char *options;
556 const char *out;
542{
543 char *args;
544
545#ifdef PRESERVE_PERMISSIONS_SUPPORT
546 /* If either file1 or file2 are special files, pretend they are
547 /dev/null. Reason: suppose a file that represents a block
548 special device in one revision becomes a regular file. CVS
549 must find the `difference' between these files, but a special

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

594/* Print the options passed to DIFF, in the format used by rcsdiff.
595 The rcsdiff code that produces this output is extremely hairy, and
596 it is not clear how rcsdiff decides which options to print and
597 which not to print. The code below reproduces every rcsdiff run
598 that I have seen. */
599
600static void
601RCS_output_diff_options (opts, rev1, rev2, workfile)
557{
558 char *args;
559
560#ifdef PRESERVE_PERMISSIONS_SUPPORT
561 /* If either file1 or file2 are special files, pretend they are
562 /dev/null. Reason: suppose a file that represents a block
563 special device in one revision becomes a regular file. CVS
564 must find the `difference' between these files, but a special

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

609/* Print the options passed to DIFF, in the format used by rcsdiff.
610 The rcsdiff code that produces this output is extremely hairy, and
611 it is not clear how rcsdiff decides which options to print and
612 which not to print. The code below reproduces every rcsdiff run
613 that I have seen. */
614
615static void
616RCS_output_diff_options (opts, rev1, rev2, workfile)
602 char *opts;
603 char *rev1;
604 char *rev2;
605 char *workfile;
617 const char *opts;
618 const char *rev1;
619 const char *rev2;
620 const char *workfile;
606{
607 char *tmp;
608
609 tmp = (char *) xmalloc (strlen (opts) + strlen (rev1) + 10);
610
611 sprintf (tmp, "diff%s -r%s", opts, rev1);
612 cvs_output (tmp, 0);
613 free (tmp);

--- 14 unchanged lines hidden ---
621{
622 char *tmp;
623
624 tmp = (char *) xmalloc (strlen (opts) + strlen (rev1) + 10);
625
626 sprintf (tmp, "diff%s -r%s", opts, rev1);
627 cvs_output (tmp, 0);
628 free (tmp);

--- 14 unchanged lines hidden ---