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