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 --- |