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