diff options
Diffstat (limited to 'gnu/usr.bin/cvs/cvs/diff.c')
-rw-r--r-- | gnu/usr.bin/cvs/cvs/diff.c | 633 |
1 files changed, 0 insertions, 633 deletions
diff --git a/gnu/usr.bin/cvs/cvs/diff.c b/gnu/usr.bin/cvs/cvs/diff.c deleted file mode 100644 index 22fda750c30b6..0000000000000 --- a/gnu/usr.bin/cvs/cvs/diff.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS 1.4 kit. - * - * Difference - * - * Run diff against versions in the repository. Options that are specified are - * passed on directly to "rcsdiff". - * - * Without any file arguments, runs diff against all the currently modified - * files. - */ - -#include "cvs.h" - -#ifndef lint -static const char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $"; -USE(rcsid); -#endif - -static Dtype diff_dirproc PROTO((char *dir, char *pos_repos, char *update_dir)); -static int diff_filesdoneproc PROTO((int err, char *repos, char *update_dir)); -static int diff_dirleaveproc PROTO((char *dir, int err, char *update_dir)); -static int diff_file_nodiff PROTO((char *file, char *repository, List *entries, - List *srcfiles, Vers_TS *vers)); -static int diff_fileproc PROTO((char *file, char *update_dir, char *repository, - List * entries, List * srcfiles)); -static void diff_mark_errors PROTO((int err)); - -static char *diff_rev1, *diff_rev2; -static char *diff_date1, *diff_date2; -static char *use_rev1, *use_rev2; - -#ifdef SERVER_SUPPORT -/* Revision of the user file, if it is unchanged from something in the - repository and we want to use that fact. */ -static char *user_file_rev; -#endif - -static char *options; -static char opts[PATH_MAX]; -static int diff_errors; -static int empty_files = 0; - -static const char *const diff_usage[] = -{ - "Usage: %s %s [-lN] [rcsdiff-options]\n", -#ifdef CVS_DIFFDATE - " [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n", -#else - " [-r rev1 [-r rev2]] [files...] \n", -#endif - "\t-l\tLocal directory only, not recursive\n", - "\t-D d1\tDiff revision for date against working file.\n", - "\t-D d2\tDiff rev1/date1 against date2.\n", - "\t-N\tinclude diffs for added and removed files.\n", - "\t-r rev1\tDiff revision for rev1 against working file.\n", - "\t-r rev2\tDiff rev1/date1 against rev2.\n", - NULL -}; - -int -diff (argc, argv) - int argc; - char **argv; -{ - char tmp[50]; - int c, err = 0; - int local = 0; - int which; - - if (argc == -1) - usage (diff_usage); - - /* - * Note that we catch all the valid arguments here, so that we can - * intercept the -r arguments for doing revision diffs; and -l/-R for a - * non-recursive/recursive diff. - */ -#ifdef SERVER_SUPPORT - /* Need to be able to do this command more than once (according to - the protocol spec, even if the current client doesn't use it). */ - opts[0] = '\0'; -#endif - optind = 1; - while ((c = getopt (argc, argv, - "abcdefhilnpqtuw0123456789BHNQRTC:D:F:I:L:V:k:r:")) != -1) - { - switch (c) - { - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'h': case 'i': case 'n': case 'p': case 't': case 'u': - case 'w': case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': case 'B': - case 'H': case 'T': case 'Q': - (void) sprintf (tmp, " -%c", (char) c); - (void) strcat (opts, tmp); - if (c == 'Q') - { - quiet = 1; - really_quiet = 1; - c = 'q'; - } - break; - case 'C': case 'F': case 'I': case 'L': case 'V': -#ifndef CVS_DIFFDATE - case 'D': -#endif - (void) sprintf (tmp, " -%c%s", (char) c, optarg); - (void) strcat (opts, tmp); - break; - case 'R': - local = 0; - break; - case 'l': - local = 1; - break; - case 'q': - quiet = 1; - break; - case 'k': - if (options) - free (options); - options = RCS_check_kflag (optarg); - break; - case 'r': - if (diff_rev2 != NULL || diff_date2 != NULL) - error (1, 0, - "no more than two revisions/dates can be specified"); - if (diff_rev1 != NULL || diff_date1 != NULL) - diff_rev2 = optarg; - else - diff_rev1 = optarg; - break; -#ifdef CVS_DIFFDATE - case 'D': - if (diff_rev2 != NULL || diff_date2 != NULL) - error (1, 0, - "no more than two revisions/dates can be specified"); - if (diff_rev1 != NULL || diff_date1 != NULL) - diff_date2 = Make_Date (optarg); - else - diff_date1 = Make_Date (optarg); - break; -#endif - case 'N': - empty_files = 1; - break; - case '?': - default: - usage (diff_usage); - break; - } - } - argc -= optind; - argv += optind; - - /* make sure options is non-null */ - if (!options) - options = xstrdup (""); - -#ifdef CLIENT_SUPPORT - if (client_active) { - /* We're the client side. Fire up the remote server. */ - start_server (); - - ign_setup (); - - if (local) - send_arg("-l"); - if (empty_files) - send_arg("-N"); - send_option_string (opts); - if (diff_rev1) - option_with_arg ("-r", diff_rev1); - if (diff_date1) - client_senddate (diff_date1); - if (diff_rev2) - option_with_arg ("-r", diff_rev2); - if (diff_date2) - client_senddate (diff_date2); - -#if 0 -/* FIXME: We shouldn't have to send current files to diff two revs, but it - doesn't work yet and I haven't debugged it. So send the files -- - it's slower but it works. gnu@cygnus.com Apr94 */ - -/* Idea: often times the changed region of a file is relatively small. - It would be cool if the client could just divide the file into 4k - blocks or whatever and send hash values for the blocks. Send hash - values for blocks aligned with the beginning of the file and the - end of the file. Then the server can tell how much of the head and - tail of the file is unchanged. Well, hash collisions will screw - things up, but MD5 has 128 bits of hash value... */ - - /* Send the current files unless diffing two revs from the archive */ - if (diff_rev2 == NULL && diff_date2 == NULL) - send_files (argc, argv, local); - else - send_file_names (argc, argv); -#else - send_files (argc, argv, local, 0); -#endif - - if (fprintf (to_server, "diff\n") < 0) - error (1, errno, "writing to server"); - err = get_responses_and_close (); - free (options); - return (err); - } -#endif - - which = W_LOCAL; - if (diff_rev2 != NULL || diff_date2 != NULL) - which |= W_REPOS | W_ATTIC; - - wrap_setup (); - - /* start the recursion processor */ - err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc, - diff_dirleaveproc, argc, argv, local, - which, 0, 1, (char *) NULL, 1, 0); - - /* clean up */ - free (options); - return (err); -} - -/* - * Do a file diff - */ -/* ARGSUSED */ -static int -diff_fileproc (file, update_dir, repository, entries, srcfiles) - char *file; - char *update_dir; - char *repository; - List *entries; - List *srcfiles; -{ - int status, err = 2; /* 2 == trouble, like rcsdiff */ - Vers_TS *vers; - enum { - DIFF_ERROR, - DIFF_ADDED, - DIFF_REMOVED, - DIFF_NEITHER - } empty_file = DIFF_NEITHER; - char tmp[L_tmpnam+1]; - char *tocvsPath; - char fname[PATH_MAX]; - -#ifdef SERVER_SUPPORT - user_file_rev = 0; -#endif - vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL, - file, 1, 0, entries, srcfiles); - - if (diff_rev2 != NULL || diff_date2 != NULL) - { - /* Skip all the following checks regarding the user file; we're - not using it. */ - } - else if (vers->vn_user == NULL) - { - error (0, 0, "I know nothing about %s", file); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); - } - else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0') - { - if (empty_files) - empty_file = DIFF_ADDED; - else - { - error (0, 0, "%s is a new entry, no comparison available", file); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); - } - } - else if (vers->vn_user[0] == '-') - { - if (empty_files) - empty_file = DIFF_REMOVED; - else - { - error (0, 0, "%s was removed, no comparison available", file); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); - } - } - else - { - if (vers->vn_rcs == NULL && vers->srcfile == NULL) - { - error (0, 0, "cannot find revision control file for %s", file); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); - } - else - { - if (vers->ts_user == NULL) - { - error (0, 0, "cannot find %s", file); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); - } -#ifdef SERVER_SUPPORT - else if (!strcmp (vers->ts_user, vers->ts_rcs)) - { - /* The user file matches some revision in the repository - Diff against the repository (for remote CVS, we might not - have a copy of the user file around). */ - user_file_rev = vers->vn_user; - } -#endif - } - } - - if (empty_file == DIFF_NEITHER && diff_file_nodiff (file, repository, entries, srcfiles, vers)) - { - freevers_ts (&vers); - return (0); - } - -#ifdef DEATH_SUPPORT - /* FIXME: Check whether use_rev1 and use_rev2 are dead and deal - accordingly. */ -#endif - - /* Output an "Index:" line for patch to use */ - (void) fflush (stdout); - if (update_dir[0]) - (void) printf ("Index: %s/%s\n", update_dir, file); - else - (void) printf ("Index: %s\n", file); - (void) fflush (stdout); - - tocvsPath = wrap_tocvs_process_file(file); - if (tocvsPath) - { - /* Backup the current version of the file to CVS/,,filename */ - sprintf(fname,"%s/%s%s",CVSADM, CVSPREFIX, file); - if (unlink_file_dir (fname) < 0) - if (! existence_error (errno)) - error (1, errno, "cannot remove %s", file); - rename_file (file, fname); - /* Copy the wrapped file to the current directory then go to work */ - copy_file (tocvsPath, file); - } - - if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED) - { - (void) printf ("===================================================================\nRCS file: %s\n", - file); - (void) printf ("diff -N %s\n", file); - - if (empty_file == DIFF_ADDED) - { - run_setup ("%s %s %s %s", DIFF, opts, DEVNULL, file); - } - else - { - /* - * FIXME: Should be setting use_rev1 using the logic in - * diff_file_nodiff, and using that revision. This code - * is broken for "cvs diff -N -r foo". - */ - run_setup ("%s%s -p -q %s -r%s", Rcsbin, RCS_CO, - *options ? options : vers->options, vers->vn_rcs); - run_arg (vers->srcfile->path); - if (run_exec (RUN_TTY, tmpnam (tmp), RUN_TTY, RUN_REALLY) == -1) - { - (void) unlink (tmp); - error (1, errno, "fork failed during checkout of %s", - vers->srcfile->path); - } - - run_setup ("%s %s %s %s", DIFF, opts, tmp, DEVNULL); - } - } - else - { - if (use_rev2) - { - run_setup ("%s%s %s %s -r%s -r%s", Rcsbin, RCS_DIFF, - opts, *options ? options : vers->options, - use_rev1, use_rev2); - } - else - { - run_setup ("%s%s %s %s -r%s", Rcsbin, RCS_DIFF, opts, - *options ? options : vers->options, use_rev1); - } - run_arg (vers->srcfile->path); - } - - switch ((status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, - RUN_REALLY|RUN_COMBINED))) - { - case -1: /* fork failed */ - error (1, errno, "fork failed during rcsdiff of %s", - vers->srcfile->path); - case 0: /* everything ok */ - err = 0; - break; - default: /* other error */ - err = status; - break; - } - - if (tocvsPath) - { - if (unlink_file_dir (file) < 0) - if (! existence_error (errno)) - error (1, errno, "cannot remove %s", file); - - rename_file (fname,file); - if (unlink_file (tocvsPath) < 0) - error (1, errno, "cannot remove %s", file); - } - - if (empty_file == DIFF_REMOVED) - (void) unlink (tmp); - - (void) fflush (stdout); - freevers_ts (&vers); - diff_mark_errors (err); - return (err); -} - -/* - * Remember the exit status for each file. - */ -static void -diff_mark_errors (err) - int err; -{ - if (err > diff_errors) - diff_errors = err; -} - -/* - * Print a warm fuzzy message when we enter a dir - * - * Don't try to diff directories that don't exist! -- DW - */ -/* ARGSUSED */ -static Dtype -diff_dirproc (dir, pos_repos, update_dir) - char *dir; - char *pos_repos; - char *update_dir; -{ - /* XXX - check for dirs we don't want to process??? */ - - /* YES ... for instance dirs that don't exist!!! -- DW */ - if (!isdir (dir) ) - return (R_SKIP_ALL); - - if (!quiet) - error (0, 0, "Diffing %s", update_dir); - return (R_PROCESS); -} - -/* - * Concoct the proper exit status - done with files - */ -/* ARGSUSED */ -static int -diff_filesdoneproc (err, repos, update_dir) - int err; - char *repos; - char *update_dir; -{ - return (diff_errors); -} - -/* - * Concoct the proper exit status - leaving directories - */ -/* ARGSUSED */ -static int -diff_dirleaveproc (dir, err, update_dir) - char *dir; - int err; - char *update_dir; -{ - return (diff_errors); -} - -/* - * verify that a file is different 0=same 1=different - */ -static int -diff_file_nodiff (file, repository, entries, srcfiles, vers) - char *file; - char *repository; - List *entries; - List *srcfiles; - Vers_TS *vers; -{ - Vers_TS *xvers; - char tmp[L_tmpnam+1]; - - /* free up any old use_rev* variables and reset 'em */ - if (use_rev1) - free (use_rev1); - if (use_rev2) - free (use_rev2); - use_rev1 = use_rev2 = (char *) NULL; - - if (diff_rev1 || diff_date1) - { - /* special handling for TAG_HEAD */ - if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0) - use_rev1 = xstrdup (vers->vn_rcs); - else - { - xvers = Version_TS (repository, (char *) NULL, diff_rev1, - diff_date1, file, 1, 0, entries, srcfiles); - if (xvers->vn_rcs == NULL) - { - /* Don't gripe if it doesn't exist, just ignore! */ - if (! isfile (file)) - /* null statement */ ; - else if (diff_rev1) - error (0, 0, "tag %s is not in file %s", diff_rev1, file); - else - error (0, 0, "no revision for date %s in file %s", - diff_date1, file); - return (1); - } - use_rev1 = xstrdup (xvers->vn_rcs); - freevers_ts (&xvers); - } - } - if (diff_rev2 || diff_date2) - { - /* special handling for TAG_HEAD */ - if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0) - use_rev2 = xstrdup (vers->vn_rcs); - else - { - xvers = Version_TS (repository, (char *) NULL, diff_rev2, - diff_date2, file, 1, 0, entries, srcfiles); - if (xvers->vn_rcs == NULL) - { - /* Don't gripe if it doesn't exist, just ignore! */ - if (! isfile (file)) - /* null statement */ ; - else if (diff_rev1) - error (0, 0, "tag %s is not in file %s", diff_rev2, file); - else - error (0, 0, "no revision for date %s in file %s", - diff_date2, file); - return (1); - } - use_rev2 = xstrdup (xvers->vn_rcs); - freevers_ts (&xvers); - } - - /* now, see if we really need to do the diff */ - if (use_rev1 && use_rev2) { - return (strcmp (use_rev1, use_rev2) == 0); - } else { - error(0, 0, "No HEAD revision for file %s", file); - return (1); - } - } -#ifdef SERVER_SUPPORT - if (user_file_rev) - { - /* drop user_file_rev into first unused use_rev */ - if (!use_rev1) - use_rev1 = xstrdup (user_file_rev); - else if (!use_rev2) - use_rev2 = xstrdup (user_file_rev); - /* and if not, it wasn't needed anyhow */ - user_file_rev = 0; - } - - /* now, see if we really need to do the diff */ - if (use_rev1 && use_rev2) - { - return (strcmp (use_rev1, use_rev2) == 0); - } -#endif /* SERVER_SUPPORT */ - if (use_rev1 == NULL || strcmp (use_rev1, vers->vn_user) == 0) - { - if (strcmp (vers->ts_rcs, vers->ts_user) == 0 && - (!(*options) || strcmp (options, vers->options) == 0)) - { - return (1); - } - if (use_rev1 == NULL) - use_rev1 = xstrdup (vers->vn_user); - } - - /* - * with 0 or 1 -r option specified, run a quick diff to see if we - * should bother with it at all. - */ - run_setup ("%s%s -p -q %s -r%s", Rcsbin, RCS_CO, - *options ? options : vers->options, use_rev1); - run_arg (vers->srcfile->path); - switch (run_exec (RUN_TTY, tmpnam (tmp), RUN_TTY, RUN_REALLY)) - { - case 0: /* everything ok */ - if (xcmp (file, tmp) == 0) - { - (void) unlink (tmp); - return (1); - } - break; - case -1: /* fork failed */ - (void) unlink (tmp); - error (1, errno, "fork failed during checkout of %s", - vers->srcfile->path); - default: - break; - } - (void) unlink (tmp); - return (0); -} |