/[cvs]/ccvs/src/rcscmds.c
ViewVC logotype

Diff of /ccvs/src/rcscmds.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.72 by dprice, Wed Jun 1 01:42:35 2005 UTC revision 1.72.4.1 by dprice, Tue Nov 29 23:44:19 2005 UTC
# Line 14  Line 14 
14   * operations directly on RCS files.   * operations directly on RCS files.
15   */   */
16    
17  #include "cvs.h"  #ifdef HAVE_CONFIG_H
18    # include <config.h>
19    #endif
20    
21    /* Standard headers.  */
22  #include <stdio.h>  #include <stdio.h>
23  #include "diffrun.h"  
24    /* GNULIB */
25  #include "quotearg.h"  #include "quotearg.h"
26    
27    /* CVS */
28    #include "difflib.h"
29    #include "cvs.h"
30    
31  /* This file, rcs.h, and rcs.c, together sometimes known as the "RCS  /* This file, rcs.h, and rcs.c, together sometimes known as the "RCS
32     library", are intended to define our interface to RCS files.     library", are intended to define our interface to RCS files.
33    
# Line 65  static void RCS_output_diff_options (int Line 74  static void RCS_output_diff_options (int
74     to resemble a command line rather than something closer to "struct     to resemble a command line rather than something closer to "struct
75     log_data" in log.c.  */     log_data" in log.c.  */
76    
 /* First call call_diff_setup to setup any initial arguments.  The  
    argument will be parsed into whitespace separated words and added  
    to the global call_diff_argv list.  
   
    Then, optionally, call call_diff_add_arg for each additional argument  
    that you'd like to pass to the diff library.  
   
    Finally, call call_diff or call_diff3 to produce the diffs.  */  
   
 static char **call_diff_argv;  
 static int call_diff_argc;  
 static size_t call_diff_arg_allocated;  
   
 static int call_diff (const char *out);  
 static int call_diff3 (char *out);  
   
 static void call_diff_write_output (const char *, size_t);  
 static void call_diff_flush_output (void);  
 static void call_diff_write_stdout (const char *);  
 static void call_diff_error (const char *, const char *, const char *);  
   
   
   
 /* VARARGS */  
 static void  
 call_diff_add_arg (const char *s)  
 {  
     TRACE (TRACE_DATA, "call_diff_add_arg (%s)", s);  
     run_add_arg_p (&call_diff_argc, &call_diff_arg_allocated, &call_diff_argv,  
                    s);  
 }  
   
   
   
 static void  
 call_diff_setup (const char *prog, int argc, char * const *argv)  
 {  
     int i;  
   
     /* clean out any malloc'ed values from call_diff_argv */  
     run_arg_free_p (call_diff_argc, call_diff_argv);  
     call_diff_argc = 0;  
   
     /* put each word into call_diff_argv, allocating it as we go */  
     call_diff_add_arg (prog);  
     for (i = 0; i < argc; i++)  
         call_diff_add_arg (argv[i]);  
 }  
   
   
   
 /* Callback function for the diff library to write data to the output  
    file.  This is used when we are producing output to stdout.  */  
   
 static void  
 call_diff_write_output (const char *text, size_t len)  
 {  
     if (len > 0)  
         cvs_output (text, len);  
 }  
   
 /* Call back function for the diff library to flush the output file.  
    This is used when we are producing output to stdout.  */  
   
 static void  
 call_diff_flush_output (void)  
 {  
     cvs_flushout ();  
 }  
   
 /* Call back function for the diff library to write to stdout.  */  
   
 static void  
 call_diff_write_stdout (const char *text)  
 {  
     cvs_output (text, 0);  
 }  
   
 /* Call back function for the diff library to write to stderr.  */  
   
 static void  
 call_diff_error (const char *format, const char *a1, const char *a2)  
 {  
     /* FIXME: Should we somehow indicate that this error is coming from  
        the diff library?  */  
     error (0, 0, format, a1, a2);  
 }  
   
 /* This set of callback functions is used if we are sending the diff  
    to stdout.  */  
   
 static struct diff_callbacks call_diff_stdout_callbacks =  
 {  
     call_diff_write_output,  
     call_diff_flush_output,  
     call_diff_write_stdout,  
     call_diff_error  
 };  
   
 /* This set of callback functions is used if we are sending the diff  
    to a file.  */  
   
 static struct diff_callbacks call_diff_file_callbacks =  
 {  
     NULL,  
     NULL,  
     call_diff_write_stdout,  
     call_diff_error  
 };  
   
   
   
 static int  
 call_diff (const char *out)  
 {  
     call_diff_add_arg (NULL);  
   
     if (out == RUN_TTY)  
         return diff_run( call_diff_argc, call_diff_argv, NULL,  
                          &call_diff_stdout_callbacks );  
     else  
         return diff_run( call_diff_argc, call_diff_argv, out,  
                          &call_diff_file_callbacks );  
 }  
   
   
   
 static int  
 call_diff3 (char *out)  
 {  
     if (out == RUN_TTY)  
         return diff3_run (call_diff_argc, call_diff_argv, NULL,  
                           &call_diff_stdout_callbacks);  
     else  
         return diff3_run (call_diff_argc, call_diff_argv, out,  
                           &call_diff_file_callbacks);  
 }  
   
   
   
 /* Merge revisions REV1 and REV2. */  
   
 int  
 RCS_merge (RCSNode *rcs, const char *path, const char *workfile,  
            const char *options, const char *rev1, const char *rev2)  
 {  
     char *xrev1, *xrev2;  
     char *tmp1, *tmp2;  
     char *diffout = NULL;  
     int retval;  
   
     if (options != NULL && options[0] != '\0')  
       assert (options[0] == '-' && options[1] == 'k');  
   
     cvs_output ("RCS file: ", 0);  
     cvs_output (rcs->print_path, 0);  
     cvs_output ("\n", 1);  
   
     /* Calculate numeric revision numbers from rev1 and rev2 (may be  
        symbolic).  
        FIXME - No they can't.  Both calls to RCS_merge are passing in  
        numeric revisions.  */  
     xrev1 = RCS_gettag (rcs, rev1, 0, NULL);  
     xrev2 = RCS_gettag (rcs, rev2, 0, NULL);  
     assert (xrev1 && xrev2);  
   
     /* Check out chosen revisions.  The error message when RCS_checkout  
        fails is not very informative -- it is taken verbatim from RCS 5.7,  
        and relies on RCS_checkout saying something intelligent upon failure. */  
     cvs_output ("retrieving revision ", 0);  
     cvs_output (xrev1, 0);  
     cvs_output ("\n", 1);  
   
     tmp1 = cvs_temp_name();  
     if (RCS_checkout (rcs, NULL, xrev1, rev1, options, tmp1, NULL, NULL))  
     {  
         cvs_outerr ("rcsmerge: co failed\n", 0);  
         exit (EXIT_FAILURE);  
     }  
   
     cvs_output ("retrieving revision ", 0);  
     cvs_output (xrev2, 0);  
     cvs_output ("\n", 1);  
   
     tmp2 = cvs_temp_name();  
     if (RCS_checkout (rcs, NULL, xrev2, rev2, options, tmp2, NULL, NULL))  
     {  
         cvs_outerr ("rcsmerge: co failed\n", 0);  
         exit (EXIT_FAILURE);  
     }  
   
     /* Merge changes. */  
     cvs_output ("Merging differences between ", 0);  
     cvs_output (xrev1, 0);  
     cvs_output (" and ", 0);  
     cvs_output (xrev2, 0);  
     cvs_output (" into ", 0);  
     cvs_output (workfile, 0);  
     cvs_output ("\n", 1);  
   
     /* Remember that the first word in the `call_diff_setup' string is used now  
        only for diagnostic messages -- CVS no longer forks to run diff3. */  
     diffout = cvs_temp_name();  
     call_diff_setup ("diff3", 0, NULL);  
     call_diff_add_arg ("-E");  
     call_diff_add_arg ("-am");  
   
     call_diff_add_arg ("-L");  
     call_diff_add_arg (workfile);  
     call_diff_add_arg ("-L");  
     call_diff_add_arg (xrev1);  
     call_diff_add_arg ("-L");  
     call_diff_add_arg (xrev2);  
   
     call_diff_add_arg ("--");  
     call_diff_add_arg (workfile);  
     call_diff_add_arg (tmp1);  
     call_diff_add_arg (tmp2);  
   
     retval = call_diff3 (diffout);  
   
     if (retval == 1)  
         cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);  
     else if (retval == 2)  
         exit (EXIT_FAILURE);  
   
     if (diffout)  
         copy_file (diffout, workfile);  
   
     /* Clean up. */  
     {  
         int save_noexec = noexec;  
         noexec = 0;  
         if (unlink_file (tmp1) < 0)  
         {  
             if (!existence_error (errno))  
                 error (0, errno, "cannot remove temp file %s", tmp1);  
         }  
         free (tmp1);  
         if (unlink_file (tmp2) < 0)  
         {  
             if (!existence_error (errno))  
                 error (0, errno, "cannot remove temp file %s", tmp2);  
         }  
         free (tmp2);  
         if (diffout)  
         {  
             if (unlink_file (diffout) < 0)  
             {  
                 if (!existence_error (errno))  
                     error (0, errno, "cannot remove temp file %s", diffout);  
             }  
             free (diffout);  
         }  
         free (xrev1);  
         free (xrev2);  
         noexec = save_noexec;  
     }  
77    
     return retval;  
 }  
78    
79  /* Diff revisions and/or files.  OPTS controls the format of the diff  /* Diff revisions and/or files.  OPTS controls the format of the diff
80     (it contains options such as "-w -c", &c), or "" for the default.     (it contains options such as "-w -c", &c), or "" for the default.

Legend:
Removed from v.1.72  
changed lines
  Added in v.1.72.4.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26