diff options
Diffstat (limited to 'gnu/usr.bin/cvs/cvs/patch.c')
-rw-r--r-- | gnu/usr.bin/cvs/cvs/patch.c | 615 |
1 files changed, 0 insertions, 615 deletions
diff --git a/gnu/usr.bin/cvs/cvs/patch.c b/gnu/usr.bin/cvs/cvs/patch.c deleted file mode 100644 index 560f4b4d3d25..000000000000 --- a/gnu/usr.bin/cvs/cvs/patch.c +++ /dev/null @@ -1,615 +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. - * - * Patch - * - * Create a Larry Wall format "patch" file between a previous release and the - * current head of a module, or between two releases. Can specify the - * release as either a date or a revision number. - */ - -#include "cvs.h" -#include "getline.h" - -#ifndef lint -static const char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $"; -USE(rcsid); -#endif - -static RETSIGTYPE patch_cleanup PROTO((void)); -static Dtype patch_dirproc PROTO((char *dir, char *repos, char *update_dir)); -static int patch_fileproc PROTO((char *file, char *update_dir, char *repository, - List * entries, List * srcfiles)); -static int patch_proc PROTO((int *pargc, char **argv, char *xwhere, - char *mwhere, char *mfile, int shorten, - int local_specified, char *mname, char *msg)); - -static int force_tag_match = 1; -static int patch_short = 0; -static int toptwo_diffs = 0; -static int local = 0; -static char *options = NULL; -static char *rev1 = NULL; -static char *rev2 = NULL; -static char *date1 = NULL; -static char *date2 = NULL; -static char tmpfile1[L_tmpnam+1], tmpfile2[L_tmpnam+1], tmpfile3[L_tmpnam+1]; -static int unidiff = 0; - -static const char *const patch_usage[] = -{ - "Usage: %s %s [-fl] [-c|-u] [-s|-t] [-V %%d]\n", - " -r rev|-D date [-r rev2 | -D date2] modules...\n", - "\t-f\tForce a head revision match if tag/date not found.\n", - "\t-l\tLocal directory only, not recursive\n", - "\t-c\tContext diffs (default)\n", - "\t-u\tUnidiff format.\n", - "\t-s\tShort patch - one liner per file.\n", - "\t-t\tTop two diffs - last change made to the file.\n", - "\t-D date\tDate.\n", - "\t-r rev\tRevision - symbolic or numeric.\n", - "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n", - NULL -}; - -int -patch (argc, argv) - int argc; - char **argv; -{ - register int i; - int c; - int err = 0; - DBM *db; - - if (argc == -1) - usage (patch_usage); - - optind = 1; - while ((c = getopt (argc, argv, "V:k:cuftsQqlRD:r:")) != -1) - { - switch (c) - { - case 'Q': - case 'q': -#ifdef SERVER_SUPPORT - /* The CVS 1.5 client sends these options (in addition to - Global_option requests), so we must ignore them. */ - if (!server_active) -#endif - error (1, 0, - "-q or -Q must be specified before \"%s\"", - command_name); - break; - case 'f': - force_tag_match = 0; - break; - case 'l': - local = 1; - break; - case 'R': - local = 0; - break; - case 't': - toptwo_diffs = 1; - break; - case 's': - patch_short = 1; - break; - case 'D': - if (rev2 != NULL || date2 != NULL) - error (1, 0, - "no more than two revisions/dates can be specified"); - if (rev1 != NULL || date1 != NULL) - date2 = Make_Date (optarg); - else - date1 = Make_Date (optarg); - break; - case 'r': - if (rev2 != NULL || date2 != NULL) - error (1, 0, - "no more than two revisions/dates can be specified"); - if (rev1 != NULL || date1 != NULL) - rev2 = optarg; - else - rev1 = optarg; - break; - case 'k': - if (options) - free (options); - options = RCS_check_kflag (optarg); - break; - case 'V': - if (atoi (optarg) <= 0) - error (1, 0, "must specify a version number to -V"); - if (options) - free (options); - options = xmalloc (strlen (optarg) + 1 + 2); /* for the -V */ - (void) sprintf (options, "-V%s", optarg); - break; - case 'u': - unidiff = 1; /* Unidiff */ - break; - case 'c': /* Context diff */ - unidiff = 0; - break; - case '?': - default: - usage (patch_usage); - break; - } - } - argc -= optind; - argv += optind; - - /* Sanity checks */ - if (argc < 1) - usage (patch_usage); - - if (toptwo_diffs && patch_short) - error (1, 0, "-t and -s options are mutually exclusive"); - if (toptwo_diffs && (date1 != NULL || date2 != NULL || - rev1 != NULL || rev2 != NULL)) - error (1, 0, "must not specify revisions/dates with -t option!"); - - if (!toptwo_diffs && (date1 == NULL && date2 == NULL && - rev1 == NULL && rev2 == NULL)) - error (1, 0, "must specify at least one revision/date!"); - if (date1 != NULL && date2 != NULL) - if (RCS_datecmp (date1, date2) >= 0) - error (1, 0, "second date must come after first date!"); - - /* if options is NULL, make it a NULL string */ - if (options == NULL) - 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 (force_tag_match) - send_arg("-f"); - if (toptwo_diffs) - send_arg("-t"); - if (patch_short) - send_arg("-s"); - if (unidiff) - send_arg("-u"); - - if (rev1) - option_with_arg ("-r", rev1); - if (date1) - client_senddate (date1); - if (rev2) - option_with_arg ("-r", rev2); - if (date2) - client_senddate (date2); - if (options[0] != '\0') - send_arg (options); - - { - int i; - for (i = 0; i < argc; ++i) - send_arg (argv[i]); - } - - if (fprintf (to_server, "rdiff\n") < 0) - error (1, errno, "writing to server"); - return get_responses_and_close (); - } -#endif - - /* clean up if we get a signal */ -#ifdef SIGHUP - (void) SIG_register (SIGHUP, patch_cleanup); -#endif -#ifdef SIGINT - (void) SIG_register (SIGINT, patch_cleanup); -#endif -#ifdef SIGQUIT - (void) SIG_register (SIGQUIT, patch_cleanup); -#endif -#ifdef SIGPIPE - (void) SIG_register (SIGPIPE, patch_cleanup); -#endif -#ifdef SIGTERM - (void) SIG_register (SIGTERM, patch_cleanup); -#endif - - db = open_module (); - for (i = 0; i < argc; i++) - err += do_module (db, argv[i], PATCH, "Patching", patch_proc, - (char *) NULL, 0, 0, 0, (char *) NULL); - close_module (db); - free (options); - patch_cleanup (); - return (err); -} - -/* - * callback proc for doing the real work of patching - */ -/* ARGSUSED */ -static char where[PATH_MAX]; -static int -patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified, - mname, msg) - int *pargc; - char **argv; - char *xwhere; - char *mwhere; - char *mfile; - int shorten; - int local_specified; - char *mname; - char *msg; -{ - int err = 0; - int which; - char repository[PATH_MAX]; - - (void) sprintf (repository, "%s/%s", CVSroot, argv[0]); - (void) strcpy (where, argv[0]); - - /* if mfile isn't null, we need to set up to do only part of the module */ - if (mfile != NULL) - { - char *cp; - char path[PATH_MAX]; - - /* if the portion of the module is a path, put the dir part on repos */ - if ((cp = strrchr (mfile, '/')) != NULL) - { - *cp = '\0'; - (void) strcat (repository, "/"); - (void) strcat (repository, mfile); - (void) strcat (where, "/"); - (void) strcat (where, mfile); - mfile = cp + 1; - } - - /* take care of the rest */ - (void) sprintf (path, "%s/%s", repository, mfile); - if (isdir (path)) - { - /* directory means repository gets the dir tacked on */ - (void) strcpy (repository, path); - (void) strcat (where, "/"); - (void) strcat (where, mfile); - } - else - { - int i; - - /* a file means muck argv */ - for (i = 1; i < *pargc; i++) - free (argv[i]); - argv[1] = xstrdup (mfile); - (*pargc) = 2; - } - } - - /* cd to the starting repository */ - if (chdir (repository) < 0) - { - error (0, errno, "cannot chdir to %s", repository); - return (1); - } - - if (force_tag_match) - which = W_REPOS | W_ATTIC; - else - which = W_REPOS; - - /* start the recursion processor */ - err = start_recursion (patch_fileproc, (FILESDONEPROC) NULL, patch_dirproc, - (DIRLEAVEPROC) NULL, *pargc - 1, argv + 1, local, - which, 0, 1, where, 1, 1); - - return (err); -} - -/* - * Called to examine a particular RCS file, as appropriate with the options - * that were set above. - */ -/* ARGSUSED */ -static int -patch_fileproc (file, update_dir, repository, entries, srcfiles) - char *file; - char *update_dir; - char *repository; - List *entries; - List *srcfiles; -{ - struct utimbuf t; - char *vers_tag, *vers_head; - char rcsspace[PATH_MAX]; - char *rcs = rcsspace; - Node *p; - RCSNode *rcsfile; - FILE *fp1, *fp2, *fp3; - int ret = 0; - int isattic = 0; - int retcode = 0; - char file1[PATH_MAX], file2[PATH_MAX], strippath[PATH_MAX]; - char *line1, *line2; - size_t line1_chars_allocated; - size_t line2_chars_allocated; - char *cp1, *cp2, *commap; - FILE *fp; - - /* find the parsed rcs file */ - p = findnode (srcfiles, file); - if (p == NULL) - return (1); - rcsfile = (RCSNode *) p->data; - if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC)) - isattic = 1; - - (void) sprintf (rcs, "%s%s", file, RCSEXT); - - /* if vers_head is NULL, may have been removed from the release */ - if (isattic && rev2 == NULL && date2 == NULL) - vers_head = NULL; - else - vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, 0); - - if (toptwo_diffs) - { - if (vers_head == NULL) - return (1); - - if (!date1) - date1 = xmalloc (50); /* plenty big :-) */ - *date1 = '\0'; - if (RCS_getrevtime (rcsfile, vers_head, date1, 1) == -1) - { - if (!really_quiet) - error (0, 0, "cannot find date in rcs file %s revision %s", - rcs, vers_head); - return (1); - } - } - vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, 0); - - if (vers_tag == NULL && (vers_head == NULL || isattic)) - return (0); /* nothing known about specified revs */ - - if (vers_tag && vers_head && strcmp (vers_head, vers_tag) == 0) - return (0); /* not changed between releases */ - - if (patch_short) - { - (void) printf ("File "); - if (vers_tag == NULL) - (void) printf ("%s is new; current revision %s\n", rcs, vers_head); - else if (vers_head == NULL) -#ifdef DEATH_SUPPORT - { - (void) printf ("%s is removed; not included in ", rcs); - if (rev2 != NULL) - (void) printf ("release tag %s", rev2); - else if (date2 != NULL) - (void) printf ("release date %s", date2); - else - (void) printf ("current release"); - (void) printf ("\n"); - } -#else - (void) printf ("%s is removed; not included in release %s\n", - rcs, rev2 ? rev2 : date2); -#endif - else - (void) printf ("%s changed from revision %s to %s\n", - rcs, vers_tag, vers_head); - return (0); - } - if ((fp1 = fopen (tmpnam (tmpfile1), "w+")) != NULL) - (void) fclose (fp1); - if ((fp2 = fopen (tmpnam (tmpfile2), "w+")) != NULL) - (void) fclose (fp2); - if ((fp3 = fopen (tmpnam (tmpfile3), "w+")) != NULL) - (void) fclose (fp3); - if (fp1 == NULL || fp2 == NULL || fp3 == NULL) - { - error (0, 0, "cannot create temporary files"); - ret = 1; - goto out; - } - if (vers_tag != NULL) - { - run_setup ("%s%s %s -p -q -r%s", Rcsbin, RCS_CO, options, vers_tag); - run_arg (rcsfile->path); - if ((retcode = run_exec (RUN_TTY, tmpfile1, RUN_TTY, RUN_NORMAL)) != 0) - { - if (!really_quiet) - error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "co of revision %s in %s failed", vers_tag, rcs); - ret = 1; - goto out; - } - memset ((char *) &t, 0, sizeof (t)); - if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag, - (char *) 0, 0)) != -1) - (void) utime (tmpfile1, &t); - } - else if (toptwo_diffs) - { - ret = 1; - goto out; - } - if (vers_head != NULL) - { - run_setup ("%s%s %s -p -q -r%s", Rcsbin, RCS_CO, options, vers_head); - run_arg (rcsfile->path); - if ((retcode = run_exec (RUN_TTY, tmpfile2, RUN_TTY, RUN_NORMAL)) != 0) - { - if (!really_quiet) - error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "co of revision %s in %s failed", vers_head, rcs); - ret = 1; - goto out; - } - if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head, - (char *) 0, 0)) != -1) - (void) utime (tmpfile2, &t); - } - run_setup ("%s -%c", DIFF, unidiff ? 'u' : 'c'); - run_arg (tmpfile1); - run_arg (tmpfile2); - - line1 = NULL; - line1_chars_allocated = 0; - line2 = NULL; - line2_chars_allocated = 0; - - switch (run_exec (RUN_TTY, tmpfile3, RUN_TTY, RUN_NORMAL)) - { - case -1: /* fork/wait failure */ - error (1, errno, "fork for diff failed on %s", rcs); - break; - case 0: /* nothing to do */ - break; - case 1: - /* - * The two revisions are really different, so read the first two - * lines of the diff output file, and munge them to include more - * reasonable file names that "patch" will understand. - */ - - /* 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); - - fp = open_file (tmpfile3, "r"); - if (getline (&line1, &line1_chars_allocated, fp) < 0 || - getline (&line2, &line2_chars_allocated, fp) < 0) - { - error (0, errno, "failed to read diff file header %s for %s", - tmpfile3, rcs); - ret = 1; - (void) fclose (fp); - goto out; - } - if (!unidiff) - { - if (strncmp (line1, "*** ", 4) != 0 || - strncmp (line2, "--- ", 4) != 0 || - (cp1 = strchr (line1, '\t')) == NULL || - (cp2 = strchr (line2, '\t')) == NULL) - { - error (0, 0, "invalid diff header for %s", rcs); - ret = 1; - (void) fclose (fp); - goto out; - } - } - else - { - if (strncmp (line1, "--- ", 4) != 0 || - strncmp (line2, "+++ ", 4) != 0 || - (cp1 = strchr (line1, '\t')) == NULL || - (cp2 = strchr (line2, '\t')) == NULL) - { - error (0, 0, "invalid unidiff header for %s", rcs); - ret = 1; - (void) fclose (fp); - goto out; - } - } - if (CVSroot != NULL) - (void) sprintf (strippath, "%s/", CVSroot); - else - (void) strcpy (strippath, REPOS_STRIP); - if (strncmp (rcs, strippath, strlen (strippath)) == 0) - rcs += strlen (strippath); - commap = strrchr (rcs, ','); - *commap = '\0'; - if (vers_tag != NULL) - { - (void) sprintf (file1, "%s%s%s:%s", update_dir, - update_dir[0] ? "/" : "", rcs, vers_tag); - } - else - { - (void) strcpy (file1, DEVNULL); - } - (void) sprintf (file2, "%s%s%s:%s", update_dir, - update_dir[0] ? "/" : "", rcs, - vers_head ? vers_head : "removed"); - if (unidiff) - { - (void) printf ("diff -u %s %s\n", file1, file2); - (void) printf ("--- %s%s+++ ", file1, cp1); - } - else - { - (void) printf ("diff -c %s %s\n", file1, file2); - (void) printf ("*** %s%s--- ", file1, cp1); - } - - if (update_dir[0] != '\0') - (void) printf ("%s/", update_dir); - (void) printf ("%s%s", rcs, cp2); - /* spew the rest of the diff out */ - while (getline (&line1, &line1_chars_allocated, fp) >= 0) - (void) fputs (line1, stdout); - (void) fclose (fp); - break; - default: - error (0, 0, "diff failed for %s", rcs); - } - out: - if (line1) - free (line1); - if (line2) - free (line2); - (void) unlink_file (tmpfile1); - (void) unlink_file (tmpfile2); - (void) unlink_file (tmpfile3); - return (ret); -} - -/* - * Print a warm fuzzy message - */ -/* ARGSUSED */ -static Dtype -patch_dirproc (dir, repos, update_dir) - char *dir; - char *repos; - char *update_dir; -{ - if (!quiet) - error (0, 0, "Diffing %s", update_dir); - return (R_PROCESS); -} - -/* - * Clean up temporary files - */ -static RETSIGTYPE -patch_cleanup () -{ - if (tmpfile1[0] != '\0') - (void) unlink_file (tmpfile1); - if (tmpfile2[0] != '\0') - (void) unlink_file (tmpfile2); - if (tmpfile3[0] != '\0') - (void) unlink_file (tmpfile3); -} |