00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011 #include <poll.h>
00012 #include <alloca.h>
00013 #include <time.h>
00014 #include <fcntl.h>
00015 
00016 
00017 #include "global.h"
00018 #include "revert.h"
00019 #include "helper.h"
00020 #include "interface.h"
00021 #include "url.h"
00022 #include "status.h"
00023 #include "options.h"
00024 #include "est_ops.h"
00025 #include "ignore.h"
00026 #include "waa.h"
00027 #include "racallback.h"
00028 #include "cp_mv.h"
00029 #include "warnings.h"
00030 #include "diff.h"
00031 
00032 
00084 int cdiff_pipe=STDOUT_FILENO;
00085 pid_t cdiff_pid=0;
00086 
00087 
00089 #define META_DIFF_DELIMITER (0xf44fee31)
00090 
00091 #define META_DIFF_MAXLEN (256)
00092 
00093 
00105 int df___print_meta(char *format, ... )
00106 {
00107     int status;
00108     va_list va;
00109     char buf_old[META_DIFF_MAXLEN], 
00110              buf_new[META_DIFF_MAXLEN];
00111     int l1, l2;
00112 
00113 
00114     status=0;
00115     va_start(va, format);
00116 
00117     l1=vsnprintf(buf_old, META_DIFF_MAXLEN-1, format, va);
00118     DEBUGP("meta-diff: %s", buf_old);
00119 
00120     l2=0;
00121     while (va_arg(va, int) != META_DIFF_DELIMITER)
00122     {
00123         l2++;
00124         BUG_ON(l2>5, "Parameter list too long");
00125     }
00126 
00127     l2=vsnprintf(buf_new, META_DIFF_MAXLEN-1, format, va);
00128     DEBUGP("meta-diff: %s", buf_new);
00129 
00130     STOPIF_CODE_ERR( l1<0 || l2<0 || 
00131             l1>=META_DIFF_MAXLEN || l2>=META_DIFF_MAXLEN, EINVAL,
00132             "Printing meta-data strings format error");
00133 
00134         
00135     STOPIF_CODE_EPIPE( 
00136             printf( 
00137                 (l1 != l2 || strcmp(buf_new, buf_old) !=0) ? 
00138                 "-%s\n+%s\n" : " %s\n", 
00139                 buf_old, buf_new), NULL);
00140 
00141 ex:
00142     return status;
00143 }
00144 
00145 
00146 
00159 int df__do_diff(struct estat *sts, 
00160         svn_revnum_t rev1, 
00161         svn_revnum_t rev2, char *rev2_file)
00162 {
00163     int status;
00164     int ch_stat;
00165     static pid_t last_child=0;
00166     static char *last_tmp_file=NULL;
00167     static char *last_tmp_file2=NULL;
00168     pid_t tmp_pid;
00169     char *path, *disp_dest, *disp_source;
00170     int len_d, len_s;
00171     char *b1, *b2;
00172     struct estat sts_r2;
00173     char short_desc[10];
00174     char *new_mtime_string, *other_mtime_string;
00175     char *url_to_fetch, *other_url;
00176     int is_copy;
00177     int fdflags;
00178     apr_hash_t *props_r1, *props_r2;
00179 
00180 
00181     status=0;
00182 
00183     
00184     if (last_child)
00185     {
00186         
00187         tmp_pid=last_child;
00188         last_child=0;
00189         STOPIF_CODE_ERR( waitpid(tmp_pid, &ch_stat, 0) == -1, errno,
00190                 "Waiting for child gave an error");
00191         DEBUGP("child %d exitcode %d - status 0x%04X", 
00192                 tmp_pid, WEXITSTATUS(ch_stat), ch_stat);
00193 
00194         STOPIF_CODE_ERR( !WIFEXITED(ch_stat), EIO,
00195                 "!Child %d terminated abnormally", tmp_pid);
00196 
00197         if (WEXITSTATUS(ch_stat) == 1)
00198             DEBUGP("exit code 1 - file has changed.");
00199         else
00200         {
00201             STOPIF( wa__warn(WRN__DIFF_EXIT_STATUS, EIO,
00202                         "Child %d gave an exit status %d", 
00203                         tmp_pid, WEXITSTATUS(ch_stat)),
00204                     NULL);
00205         }
00206     }
00207 
00208     
00209 
00210 
00211 
00212 
00213 
00214     if (last_tmp_file)
00215     {
00216         STOPIF_CODE_ERR( unlink(last_tmp_file) == -1, errno,
00217                 "Cannot remove temporary file %s", last_tmp_file);
00218         last_tmp_file=NULL;
00219     }
00220 
00221     if (last_tmp_file2)
00222     {
00223         STOPIF_CODE_ERR( unlink(last_tmp_file2) == -1, errno,
00224                 "Cannot remove temporary file %s", last_tmp_file2);
00225         last_tmp_file2=NULL;
00226     }
00227 
00228     
00229     if (!sts) goto ex;
00230 
00231 
00232     STOPIF( ops__build_path( &path, sts), NULL);
00233 
00234 
00235     url_to_fetch=NULL;
00236     
00237     is_copy=sts->flags & RF___IS_COPY;
00238     if (is_copy)
00239     {
00240         
00241         STOPIF( cm__get_source(sts, NULL, &url_to_fetch, &rev1, 0), NULL);
00242         
00243 
00244         STOPIF( url__find(url_to_fetch, &sts->url), NULL);
00245     }
00246     else
00247         url_to_fetch=path+2;
00248 
00249     current_url = sts->url;
00250 
00251 
00252     
00253     STOPIF( url__open_session(NULL, NULL), NULL);
00254 
00255     
00256 
00257 
00258 
00259     
00260 
00261     
00262     sts_r2=*sts;
00263     if (rev2 != 0)
00264     {
00265         STOPIF( url__full_url(sts, &other_url), NULL);
00266 
00267         STOPIF( url__canonical_rev(current_url, &rev2), NULL);
00268         STOPIF( rev__get_text_to_tmpfile(other_url, rev2, DECODER_UNKNOWN,
00269                     NULL, &last_tmp_file2, 
00270                     NULL, &sts_r2, &props_r2, 
00271                     current_url->pool),
00272                 NULL);
00273     }
00274     else if (rev2_file)
00275     {
00276         DEBUGP("diff against %s", rev2_file);
00277         
00278         last_tmp_file2=rev2_file;
00279     }
00280 
00281     
00282     STOPIF( url__canonical_rev(current_url, &rev1), NULL);
00283     STOPIF( rev__get_text_to_tmpfile(url_to_fetch, rev1, DECODER_UNKNOWN,
00284                 NULL, &last_tmp_file, 
00285                 NULL, sts, &props_r1, 
00286                 current_url->pool), NULL);
00287 
00288     
00289 
00290     fflush(NULL);
00291 
00292 
00293     last_child=fork();
00294     STOPIF_CODE_ERR( last_child == -1, errno,
00295             "Cannot fork diff program");
00296 
00297     if (!last_child)
00298     {
00299         STOPIF( hlp__format_path(sts, path, &disp_dest), NULL);
00300 
00301         
00302         setenv(FSVS_EXP_CURR_ENTRY, path+2, 1);
00303 
00304         disp_source= is_copy ? url_to_fetch : disp_dest;
00305 
00306         len_d=strlen(disp_dest);
00307         len_s=strlen(disp_source);
00308 
00309 
00310         if (cdiff_pipe != STDOUT_FILENO)
00311         {
00312             STOPIF_CODE_ERR( dup2(cdiff_pipe, STDOUT_FILENO) == -1, errno,
00313                     "Redirect output");
00314 
00315             
00316             fdflags=fcntl(STDOUT_FILENO, F_GETFD);
00317             fdflags &= ~FD_CLOEXEC;
00318             
00319             fcntl(STDOUT_FILENO, F_SETFD, fdflags);
00320         }
00321 
00322 
00323         
00324 
00325         
00326         b1=malloc(len_s + 60 + 30);
00327         b2=malloc(len_d + 60 + 30);
00328 
00329         STOPIF( hlp__strdup( &new_mtime_string, 
00330                     ctime(& sts_r2.st.mtim.tv_sec)), NULL);
00331         STOPIF( hlp__strdup( &other_mtime_string, 
00332                     ctime(&sts->st.mtim.tv_sec)), NULL);
00333 
00334         sprintf(b1, "%s  \tRev. %llu  \t(%-24.24s)", 
00335                 disp_source, (t_ull) rev1, other_mtime_string);
00336 
00337         if (rev2 == 0)
00338         {
00339             sprintf(b2, "%s  \tLocal version  \t(%-24.24s)", 
00340                     disp_dest, new_mtime_string);
00341             strcpy(short_desc, "local");
00342         }
00343         else
00344         {
00345             sprintf(b2, "%s  \tRev. %llu  \t(%-24.24s)", 
00346                     disp_dest, (t_ull) rev2, new_mtime_string);
00347             sprintf(short_desc, "r%llu", (t_ull) rev2);
00348         }
00349 
00350 
00351         
00352         STOPIF_CODE_EPIPE( printf("diff -u %s.r%llu %s.%s\n", 
00353                     disp_source, (t_ull)rev1, 
00354                     disp_dest, short_desc),
00355                 "Diff header");
00356 
00357 
00358         if (opt__is_verbose() > 0) 
00359         {
00360             STOPIF( df___print_meta( "Mode: 0%03o",
00361                         sts->st.mode & 07777,
00362                         META_DIFF_DELIMITER,
00363                         sts_r2.st.mode & 07777), 
00364                     NULL);
00365             STOPIF( df___print_meta( "MTime: %.24s", 
00366                         other_mtime_string,
00367                         META_DIFF_DELIMITER,
00368                         new_mtime_string),
00369                     NULL);
00370             STOPIF( df___print_meta( "Owner: %d (%s)",
00371                         sts->st.uid, hlp__get_uname(sts->st.uid, "undefined"),
00372                         META_DIFF_DELIMITER,
00373                         sts_r2.st.uid, hlp__get_uname(sts_r2.st.uid, "undefined") ),
00374                     NULL);
00375             STOPIF( df___print_meta( "Group: %d (%s)", 
00376                         sts->st.gid, hlp__get_grname(sts->st.gid, "undefined"),
00377                         META_DIFF_DELIMITER,
00378                         sts_r2.st.gid, hlp__get_grname(sts_r2.st.gid, "undefined") ),
00379                     NULL);
00380         }
00381         fflush(NULL);
00382 
00383         
00384 
00385         
00386 
00387         execlp( opt__get_string(OPT__DIFF_PRG),
00388                 opt__get_string(OPT__DIFF_PRG),
00389                 opt__get_string(OPT__DIFF_OPT),
00390                 last_tmp_file, 
00391                 "--label", b1,
00392                 (rev2 != 0 ? last_tmp_file2 : 
00393                  rev2_file ? rev2_file : path),
00394                 "--label", b2,
00395                 opt__get_string(OPT__DIFF_EXTRA),
00396                 NULL);
00397         STOPIF_CODE_ERR( 1, errno, 
00398                 "Starting the diff program \"%s\" failed",
00399                 opt__get_string(OPT__DIFF_PRG));
00400     }
00401 
00402 ex:
00403     return status;
00404 }
00405 
00406 
00408 int df___cleanup(void)
00409 {
00410     int status;
00411     int ret;
00412 
00413 
00414     if (cdiff_pipe != STDOUT_FILENO)
00415         STOPIF_CODE_ERR( close(cdiff_pipe) == -1, errno,
00416                 "Cannot close colordiff pipe");
00417 
00418     if (cdiff_pid)
00419     {
00420         
00421 
00422 
00423 
00424 
00425 
00426         STOPIF_CODE_ERR( waitpid( cdiff_pid, &ret, 0) == -1, errno, 
00427                 "Can't wait");
00428         DEBUGP("child %d exitcode %d - status 0x%04X", 
00429                 cdiff_pid, WEXITSTATUS(ret), ret);
00430     }
00431 
00432     STOPIF( df__do_diff(NULL, 0, 0, 0), NULL);
00433 
00434 ex:
00435     return status;
00436 }
00437 
00438 
00440 
00445 static void df___signal(int sig)
00446 {
00447     DEBUGP("signal %d arrived!", sig);
00448     df___cleanup();
00449     exit(0);
00450 }
00451 
00452 
00455 int df___type_def_diff(struct estat *sts, svn_revnum_t rev, 
00456         apr_pool_t *pool)
00457 {
00458     int status;
00459     char *special_stg, *fn;
00460     apr_file_t *apr_f;
00461     apr_size_t wr_len, exp_len;
00462 
00463 
00464     status=0;
00465     special_stg=NULL;
00466     switch (sts->st.mode & S_IFMT)
00467     {
00468         case S_IFREG:
00469             STOPIF( df__do_diff(sts, rev, 0, NULL), NULL);
00470             break;
00471 
00472         case S_IFCHR:
00473         case S_IFBLK:
00474         case S_IFANYSPECIAL:
00475             special_stg=ops__dev_to_filedata(sts);
00476 
00477             
00478 
00479         case S_IFLNK:
00480             if (!special_stg)
00481                 STOPIF( ops__link_to_string(sts, NULL, &special_stg), NULL);
00482 
00483             STOPIF( ops__build_path( &fn, sts), NULL);
00484             STOPIF_CODE_EPIPE( printf("Special entry changed: %s\n", fn), NULL);
00485 
00486             
00487 
00488 
00489 
00490             STOPIF( waa__get_tmp_name(NULL, &fn, &apr_f, pool), NULL);
00491 
00492             wr_len=exp_len=strlen(special_stg);
00493             STOPIF( apr_file_write(apr_f, special_stg, &wr_len), NULL);
00494             STOPIF_CODE_ERR( wr_len != exp_len, ENOSPC, NULL);
00495 
00496             STOPIF( apr_file_close(apr_f), NULL);
00497 
00498 
00499             STOPIF( df__do_diff(sts, rev, 0, fn), NULL);
00500             break;
00501 
00502         default:
00503             BUG("type?");
00504     }
00505 
00506 ex:
00507     return status;
00508 }
00509 
00510 
00512 int df___direct_diff(struct estat *sts)
00513 {
00514     int status;
00515     svn_revnum_t rev1, rev2;
00516     char *fn;
00517 
00518 
00519     STOPIF( ops__build_path( &fn, sts), NULL);
00520 
00521     status=0;
00522     if (!S_ISDIR(sts->st.mode))
00523     {
00524         DEBUGP("doing %s", fn);
00525 
00526         
00527         rev1=sts->repos_rev;
00528         rev2=0;
00529         if ( (sts->entry_status & FS_REMOVED))
00530         {
00531             STOPIF_CODE_EPIPE( printf("Only in repository: %s\n", fn), NULL);
00532             goto ex;
00533         }
00534 
00535         if (sts->to_be_ignored) goto ex;
00536 
00537         if ( (sts->entry_status & FS_NEW) || !sts->url)
00538         {
00539             if (sts->flags & RF___IS_COPY)
00540             {
00541                 
00542             }
00543             else
00544             {
00545                 if (opt__is_verbose() > 0)
00546                     STOPIF_CODE_EPIPE( printf("Only in local filesystem: %s\n", 
00547                                 fn), NULL);
00548                 goto ex;
00549             }
00550         }
00551 
00552         
00553         if (sts->entry_status || opt_target_revisions_given)
00554         {
00555             DEBUGP("doing diff rev1=%llu", (t_ull)rev1);
00556             if (S_ISDIR(sts->st.mode))
00557             {
00558                 
00559             }
00560             else
00561             {               
00562                 
00563                 STOPIF( df___type_def_diff(sts, rev1, global_pool), NULL);
00564             }
00565         }
00566     }
00567     else
00568     {
00569         
00570     }
00571 
00572 ex:
00573     return status;
00574 }
00575 
00576 
00579 int df___cheap_colordiff(void)
00580 {
00581     int status;
00582     char *tmp;
00583     const int tmp_size=16384;
00584 
00585     status=0;
00586     tmp=alloca(tmp_size);
00587     while ( (status=read(STDIN_FILENO,tmp, tmp_size)) > 0 )
00588         if ( (status=write(STDOUT_FILENO, tmp, status)) == -1)
00589             break;
00590 
00591     if (status == -1)
00592     {
00593         STOPIF_CODE_ERR(errno != EPIPE, errno, 
00594                 "Getting or pushing diff data");
00595         status=0;
00596     }
00597 
00598 ex:
00599     return status;
00600 }
00601 
00602 
00608 int df___colordiff(int *handle, pid_t *cd_pid)
00609 {
00610     const char *program;
00611     int status;
00612     int pipes[2], fdflags, success[2];
00613 
00614     status=0;
00615     program=opt__get_int(OPT__COLORDIFF) ?
00616         opt__get_string(OPT__COLORDIFF) : 
00617         "colordiff";
00618 
00619     STOPIF_CODE_ERR( pipe(pipes) == -1, errno,
00620             "No more pipes");
00621     STOPIF_CODE_ERR( pipe(success) == -1, errno,
00622             "No more pipes, case 2");
00623 
00624     
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639     *cd_pid=fork();
00640     STOPIF_CODE_ERR( *cd_pid == -1, errno,
00641             "Cannot fork colordiff program");
00642 
00643     if (!*cd_pid)
00644     {
00645         close(success[0]);
00646 
00647         fdflags=fcntl(success[1], F_GETFD);
00648         fdflags |= FD_CLOEXEC;
00649         fcntl(success[1], F_SETFD, fdflags);
00650 
00651 
00652         STOPIF_CODE_ERR( 
00653                 ( dup2(pipes[0], STDIN_FILENO) |
00654                     close(pipes[1]) |
00655                     close(pipes[0]) ) == -1, errno,
00656                 "Redirecting IO didn't work");
00657 
00658         execlp( program, program, NULL);
00659 
00660 
00661         
00662 
00663         if (opt__get_int(OPT__COLORDIFF) != 0)
00664         {
00665             fdflags=errno;
00666             if (!fdflags) fdflags=EINVAL;
00667 
00668             
00669             write(success[1], &fdflags, sizeof(fdflags));
00670 
00671             STOPIF_CODE_ERR_GOTO(1, fdflags, quit,
00672                     "!Cannot start colordiff program \"%s\"", program);
00673         }
00674 
00675         close(success[1]);
00676 
00677         
00678         
00679 
00680         status=df___cheap_colordiff();
00681 
00682 quit:
00683         exit(status ? 1 : 0);
00684     }
00685 
00686     close(pipes[0]);
00687     close(success[1]);
00688 
00689     status=read(success[0], &fdflags, sizeof(fdflags));
00690     close(success[0]);
00691     STOPIF_CODE_ERR( status>0, fdflags,
00692             "!The colordiff program \"%s\" doesn't accept any data.\n"
00693             "Maybe it couldn't be started, or stopped unexpectedly?",
00694             opt__get_string(OPT__COLORDIFF) );  
00695 
00696 
00697     
00698 
00699 
00700 
00701     fdflags=fcntl(pipes[1], F_GETFD);
00702     fdflags |= FD_CLOEXEC;
00703     
00704     fcntl(pipes[1], F_SETFD, fdflags);
00705 
00706     *handle=pipes[1];
00707     DEBUGP("colordiff is %d", *cd_pid);
00708 
00709 ex:
00710     return status;
00711 }
00712 
00713 
00716 int df___diff_wc_remote(struct estat *entry, apr_pool_t *pool)
00717 {
00718     int status;
00719     struct estat **sts;
00720     int removed;
00721     char *fn, *special_stg;
00722     apr_pool_t *subpool;
00723 
00724 
00725     status=0;
00726     subpool=NULL;
00727     STOPIF( apr_pool_create(&subpool, pool), NULL);
00728 
00729     removed = 
00730         ( ((entry->remote_status & FS_REPLACED) == FS_REMOVED) ? 1 : 0 ) |
00731         ( ((entry->remote_status & FS_REPLACED) == FS_NEW) ? 2 : 0 ) |
00732         ( ((entry->entry_status  & FS_REPLACED) == FS_REMOVED) ? 2 : 0 );
00733 
00734     STOPIF( ops__build_path(&fn, entry), NULL);
00735     DEBUGP_dump_estat(entry);
00736 
00737     
00738 
00739     switch (removed)
00740     {
00741         case 3:
00742             
00743             break;
00744 
00745         case 1:
00746             
00747             STOPIF_CODE_EPIPE( printf("Only locally: %s\n", fn), NULL);
00748             break;
00749 
00750         case 2:
00751             
00752             STOPIF_CODE_EPIPE( printf("Only in the repository: %s\n", fn), NULL);
00753             break;
00754 
00755         case 0:
00756             
00757 
00758             if ((entry->local_mode_packed != entry->new_rev_mode_packed))
00759             {
00760                 
00761                 STOPIF_CODE_EPIPE( printf("Type changed from local %s to %s: %s\n", 
00762                             st__type_string(PACKED_to_MODE_T(entry->local_mode_packed)),
00763                             st__type_string(PACKED_to_MODE_T(entry->new_rev_mode_packed)),
00764                             fn), NULL);
00765                 
00766 
00767 
00768 
00769 
00770             }
00771             else if (entry->entry_status || entry->remote_status)
00772             {
00773                 
00774                 special_stg=NULL;
00775 
00776                 if (S_ISDIR(entry->st.mode))
00777                 {
00778                     
00779                     if (entry->entry_count)
00780                     {
00781                         sts=entry->by_inode;
00782                         while (*sts)
00783                         {
00784                             STOPIF( df___diff_wc_remote(*sts, subpool), NULL);
00785                             sts++;
00786                         }
00787                     }
00788                 }
00789                 else
00790                     STOPIF( df___type_def_diff(entry, entry->repos_rev, subpool), NULL);
00791             }
00792 
00793             break;
00794     }
00795 
00796 ex:
00797     
00798     if (subpool) apr_pool_destroy(subpool);
00799 
00800     return status;
00801 }
00802 
00803 
00805 int df___reset_remote_st(struct estat *sts)
00806 {
00807     sts->remote_status=0;
00808     return 0;
00809 }
00810 
00811 
00814 int df___repos_repos(struct estat *sts)
00815 {
00816     int status;
00817     char *fullpath, *path;
00818     struct estat **children;
00819 
00820 
00821     STOPIF( ops__build_path( &fullpath, sts), NULL);
00822     DEBUGP("%s: %s", fullpath, st__status_string_fromint(sts->remote_status));
00823 
00824     STOPIF( hlp__format_path( sts, fullpath, &path), NULL);
00825 
00826     if ((sts->remote_status & FS_REPLACED) == FS_REPLACED)
00827         STOPIF_CODE_EPIPE( 
00828                 printf("Completely replaced: %s\n", path), NULL);
00829     else if (sts->remote_status & FS_NEW)
00830         STOPIF_CODE_EPIPE( 
00831                 printf("Only in r%llu: %s\n", 
00832                     (t_ull)opt_target_revision2, path), NULL);
00833     else if ((sts->remote_status & FS_REPLACED) == FS_REMOVED)
00834         STOPIF_CODE_EPIPE( 
00835                 printf("Only in r%llu: %s\n", 
00836                     (t_ull)opt_target_revision, path), NULL);
00837     else if (sts->remote_status)
00838         switch (sts->st.mode & S_IFMT)
00839         {
00840             case S_IFDIR:
00841                 
00842                 if (sts->entry_count)
00843                 {
00844                     children=sts->by_inode;
00845                     while (*children)
00846                         STOPIF( df___repos_repos(*(children++)), NULL);
00847                 }
00848 
00849                 break;
00850 
00851                 
00852 
00853             case S_IFANYSPECIAL:
00854                 
00855             case S_IFLNK:
00856             case S_IFBLK:
00857             case S_IFCHR:
00858                 STOPIF_CODE_EPIPE( printf("Special entry changed: %s\n", 
00859                             path), NULL);
00860                 
00861 
00862             case S_IFREG:
00863                 STOPIF( df__do_diff(sts, 
00864                             opt_target_revision, opt_target_revision2, NULL), 
00865                         NULL);
00866                 break;
00867 
00868             default:
00869                 BUG("type?");
00870         }
00871 
00872 ex:
00873     return status;
00874 }
00875 
00876 
00884 int df__work(struct estat *root, int argc, char *argv[])
00885 {
00886     int status;
00887     int i, deinit;
00888     char **normalized;
00889     svn_revnum_t rev, base;
00890     char *norm_wcroot[2]= {".", NULL};
00891 
00892 
00893     status=0;
00894     deinit=1;
00895 
00896     STOPIF( waa__find_common_base(argc, argv, &normalized), NULL);
00897 
00898     STOPIF( url__load_nonempty_list(NULL, 0), NULL);
00899     STOPIF(ign__load_list(NULL), NULL);
00900 
00901     signal(SIGINT, df___signal);
00902     signal(SIGTERM, df___signal);
00903     signal(SIGHUP, df___signal);
00904     signal(SIGCHLD, SIG_DFL);
00905 
00906 
00907     
00908     if (( opt__get_int(OPT__COLORDIFF)==0 ||
00909                 opt__doesnt_say_off(opt__get_string(OPT__COLORDIFF)) ) &&
00910             (isatty(STDOUT_FILENO) || 
00911              opt__get_prio(OPT__COLORDIFF) > PRIO_PRE_CMDLINE) )
00912     {
00913         DEBUGP("trying to use colordiff");
00914         STOPIF( df___colordiff(&cdiff_pipe, &cdiff_pid), NULL);
00915     }
00916 
00917     
00918 
00919 
00920     STOPIF( url__mark_todo(), NULL);
00921 
00922     switch (opt_target_revisions_given)
00923     {
00924         case 0:
00925             
00926 
00927             action->local_callback=df___direct_diff;
00928             
00929 
00930             STOPIF( waa__read_or_build_tree(root, argc, 
00931                         normalized, argv, NULL, 1), NULL);
00932             break;
00933 
00934         case 1:
00935             
00936             
00937             action->local_callback=st__progress;
00938             action->local_uninit=st__progress_uninit;
00939             STOPIF( waa__read_or_build_tree(root, argc, normalized, argv, 
00940                         NULL, 1), NULL);
00941             
00942 
00943             
00944             while ( ! ( status=url__iterator(&rev) ) )
00945             {
00946                 STOPIF( cb__record_changes(root, rev, current_url->pool), NULL);
00947             }
00948             STOPIF_CODE_ERR( status != EOF, status, NULL);
00949 
00950             STOPIF( df___diff_wc_remote(root, current_url->pool), NULL);
00951             break;
00952 
00953         case 2:
00954             
00955 
00956 
00957 
00958             
00959 
00960             
00961             if (!argc)
00962                 normalized=norm_wcroot;
00963 
00964             while ( ! ( status=url__iterator(&rev) ) )
00965             {
00966                 STOPIF( url__canonical_rev(current_url, &opt_target_revision), NULL);
00967                 STOPIF( url__canonical_rev(current_url, &opt_target_revision2), NULL);
00968 
00969                 
00970 
00971                 current_url->current_rev=0;
00972                 action->repos_feedback=df___reset_remote_st;
00973                 STOPIF( cb__record_changes(root, opt_target_revision, 
00974                             current_url->pool), NULL);
00975 
00976                 
00977 
00978 
00979                 action->repos_feedback=NULL;
00980 
00981                 
00982 
00983                 base=current_url->current_rev;
00984                 current_url->current_rev=opt_target_revision2;
00985                 STOPIF( cb__record_changes_mixed(root, opt_target_revision2, 
00986                             normalized, base, current_url->pool), 
00987                         NULL);
00988             }
00989             STOPIF_CODE_ERR( status != EOF, status, NULL);
00990 
00991 
00992             
00993 
00994 
00995 
00996 
00997 
00998 
00999 
01000             
01001 
01002 
01003 
01004 
01005             
01006 
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014             STOPIF( df___repos_repos(root), NULL);
01015             status=0;
01016             break;
01017         default:
01018             BUG("what?");
01019     }
01020 
01021     STOPIF( df__do_diff(NULL, 0, 0, 0), NULL);
01022 
01023 ex:
01024     if (deinit)
01025     {
01026         deinit=0;
01027         i=df___cleanup();
01028         if (!status && i)
01029             STOPIF(i, NULL);
01030     }
01031 
01032     return status;
01033 }
01034