00001
00002
00003
00004
00005
00006
00007
00008 #include <unistd.h>
00009 #include <stdio.h>
00010 #include <fcntl.h>
00011 #include <time.h>
00012
00013 #include <subversion-1/svn_delta.h>
00014 #include <subversion-1/svn_ra.h>
00015
00016 #include "revert.h"
00017 #include "waa.h"
00018 #include "est_ops.h"
00019 #include "racallback.h"
00020 #include "warnings.h"
00021 #include "resolve.h"
00022 #include "checksum.h"
00023 #include "props.h"
00024 #include "helper.h"
00025 #include "url.h"
00026 #include "update.h"
00027 #include "cp_mv.h"
00028 #include "status.h"
00029
00030
00138 enum rev___dir_change_flag_e {
00139 NOT_CHANGED=0,
00140 REVERT_MTIME=1,
00141 SET_CURRENT=2,
00142 GET_TSTAMP=0x1000,
00143 };
00144
00145
00147 static int number_reverted=0;
00148 static svn_revnum_t last_rev;
00149
00150
00151 #define REV___GETFILE_MAX_CACHE (4)
00152
00153
00182 int rev__get_text_to_stream( char *loc_url, svn_revnum_t revision,
00183 const char *decoder,
00184 svn_stream_t *output,
00185 struct estat *sts_for_manber,
00186 struct estat *output_sts,
00187 apr_hash_t **props,
00188 apr_pool_t *pool)
00189 {
00190 int status;
00191 svn_error_t *status_svn;
00192 svn_string_t *prop_val;
00193 struct encoder_t *encoder;
00194 char *relative_url, *utf8_url;
00195 apr_hash_t *properties;
00196 char target_rev[10];
00197
00198
00199 encoder=NULL;
00200 status=0;
00201 DEBUGP("getting file %s@%s from %s", loc_url,
00202 hlp__rev_to_string(revision), current_url->url);
00203
00204
00205 if (strncmp(loc_url, "./", 2) == 0)
00206 {
00207
00208 relative_url=loc_url+2;
00209 }
00210 else
00211 {
00212
00213
00214
00215
00216
00217 if (strncmp(current_url->url, loc_url, current_url->urllen) == 0 &&
00218 loc_url[current_url->urllen] == '/')
00219 loc_url += current_url->urllen+1;
00220
00221
00222
00223
00224 }
00225
00226 STOPIF( hlp__local2utf8(loc_url, &utf8_url, -1), NULL);
00227 DEBUGP("Got utf8=%s", utf8_url);
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 if (sts_for_manber)
00238 STOPIF( cs__new_manber_filter(sts_for_manber,
00239 output, &output, pool), NULL);
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 if (decoder == DECODER_UNKNOWN)
00275 {
00276 STOPIF_SVNERR_TEXT( svn_ra_get_file,
00277 (current_url->session,
00278 utf8_url, revision,
00279 NULL,
00280 &revision, &properties,
00281 pool),
00282 "Fetching entry \"%s/%s\"@%s",
00283 current_url->url,
00284 loc_url, hlp__rev_to_string(revision));
00285
00286 prop_val=apr_hash_get(properties, propval_updatepipe, APR_HASH_KEY_STRING);
00287 decoder=prop_val ? prop_val->data : NULL;
00288 }
00289
00290
00291
00292
00293 if (decoder)
00294 {
00295 snprintf(target_rev, sizeof(target_rev),
00296 "%llu", (t_ull)revision);
00297 setenv(FSVS_EXP_TARGET_REVISION, target_rev, 1);
00298
00299 STOPIF( hlp__encode_filter(output, decoder, 1,
00300 loc_url, &output, &encoder, pool), NULL);
00301 if (output_sts)
00302 encoder->output_md5= &(output_sts->md5);
00303 }
00304
00305
00306 STOPIF_SVNERR_TEXT( svn_ra_get_file,
00307 (current_url->session,
00308 utf8_url, revision,
00309 output,
00310 &revision, &properties,
00311 pool),
00312 "Fetching entry %s/%s@%s",
00313 current_url->url,
00314 loc_url, hlp__rev_to_string(revision));
00315 DEBUGP("got revision %llu", (t_ull)revision);
00316
00317
00318 STOPIF_SVNERR( svn_stream_close, (output));
00319 output=NULL;
00320
00321 if (output_sts)
00322 {
00323 output_sts->repos_rev = revision;
00324 STOPIF( prp__set_from_aprhash( output_sts, properties,
00325 ONLY_KEEP_USERDEF, NULL, pool), NULL);
00326 }
00327
00328 if (props)
00329 *props=properties;
00330
00331
00332 ex:
00333 return status;
00334 }
00335
00336
00350 int rev__get_text_to_tmpfile(char *loc_url, svn_revnum_t revision,
00351 char *encoder,
00352 char *filename_base, char **filename,
00353 struct estat *sts_for_manber,
00354 struct estat *output_sts, apr_hash_t **props,
00355 apr_pool_t *pool)
00356 {
00357 int status;
00358 apr_file_t *apr_f;
00359 svn_stream_t *output;
00360
00361
00362 status=0;
00363
00364 STOPIF( waa__get_tmp_name( filename_base, filename, &apr_f, pool), NULL);
00365 output=svn_stream_from_aprfile(apr_f, pool);
00366
00367 STOPIF( rev__get_text_to_stream( loc_url, revision, encoder,
00368 output, sts_for_manber, output_sts, props, pool), NULL);
00369
00370
00371 STOPIF( apr_file_close(apr_f), NULL);
00372
00373 ex:
00374 return status;
00375 }
00376
00377
00381 int rev__get_text_into_buffer(char *loc_url, svn_revnum_t revision,
00382 const char *decoder,
00383 svn_stringbuf_t **output,
00384 struct estat *sts_for_manber,
00385 struct estat *output_sts,
00386 apr_hash_t **props,
00387 apr_pool_t *pool)
00388 {
00389 int status;
00390 svn_stringbuf_t *string;
00391 svn_stream_t *stream;
00392
00393 status=0;
00394 string=svn_stringbuf_create("", pool);
00395 stream=svn_stream_from_stringbuf(string, pool);
00396
00397 STOPIF( rev__get_text_to_stream(loc_url, revision,
00398 decoder, stream, sts_for_manber, output_sts, props, pool), NULL);
00399
00400 *output=string;
00401 ex:
00402 return status;
00403 }
00404
00405
00417 int rev__install_file(struct estat *sts, svn_revnum_t revision,
00418 char *decoder,
00419 apr_pool_t *pool)
00420 {
00421 int status;
00422 char *filename;
00423 char *filename_tmp;
00424 apr_hash_t *props;
00425 svn_stream_t *stream;
00426 apr_file_t *a_stream;
00427 apr_pool_t *subpool;
00428 char *special_data;
00429 char *url;
00430 svn_revnum_t rev_to_take;
00431
00432
00433 BUG_ON(!pool);
00434 STOPIF( ops__build_path(&filename, sts), NULL);
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 STOPIF( waa__mkdir(filename, 0), NULL);
00445
00446
00447 STOPIF( apr_pool_create(&subpool, pool),
00448 "Creating the filehandle pool");
00449
00450
00451
00452
00453
00454 STOPIF( waa__delete_byext(filename, WAA__FILE_MD5s_EXT, 1), NULL);
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 STOPIF( waa__get_tmp_name( filename, &filename_tmp, &a_stream, subpool),
00466 NULL);
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 stream=svn_stream_from_aprfile(a_stream, subpool);
00477
00478
00479 if (sts->url)
00480 {
00481 url=filename+2;
00482 rev_to_take=sts->repos_rev;
00483 current_url=sts->url;
00484 }
00485 else if (sts->flags & RF___IS_COPY)
00486 {
00487 STOPIF( cm__get_source( sts, filename, &url, &rev_to_take, 0), NULL);
00488 STOPIF( url__find( url, ¤t_url), NULL);
00489 }
00490 else
00491 BUG("cannot get file %s", filename);
00492
00493 if (revision == 0)
00494 {
00495
00496 STOPIF( up__fetch_decoder(sts), NULL);
00497 decoder=sts->decoder;
00498 }
00499 else
00500 {
00501
00502 rev_to_take=revision;
00503 decoder=DECODER_UNKNOWN;
00504 }
00505
00506
00507 STOPIF( url__open_session(NULL, NULL), NULL);
00508
00509
00510
00511 STOPIF( rev__get_text_to_stream( url, rev_to_take, decoder,
00512 stream, sts, NULL, &props, pool), NULL);
00513
00514
00515 if (apr_hash_get(props, propname_special, APR_HASH_KEY_STRING))
00516 {
00517 STOPIF( ops__read_special_entry( a_stream, &special_data,
00518 0, NULL, filename_tmp, subpool), NULL);
00519
00520
00521 STOPIF( up__handle_special(sts, filename_tmp,
00522 special_data, subpool), NULL);
00523 }
00524 else
00525 {
00526
00527
00528
00529 sts->st.mode = (sts->st.mode & ~S_IFMT) | S_IFREG;
00530 sts->local_mode_packed=sts->new_rev_mode_packed=
00531 MODE_T_to_PACKED(sts->st.mode);
00532 }
00533
00534
00535 STOPIF( prp__set_from_aprhash(sts, props, STORE_IN_FS,
00536 NULL, subpool), NULL);
00537
00538
00539
00540
00541
00542 sts->remote_status |= FS_META_CHANGED;
00543 DEBUGP("setting meta-data");
00544 STOPIF( up__set_meta_data(sts, filename_tmp), NULL);
00545
00546 STOPIF( apr_file_close(a_stream), NULL);
00547
00548
00549 DEBUGP("rename to %s", filename);
00550
00551 STOPIF_CODE_ERR( rename(filename_tmp, filename)==-1, errno,
00552 "Cannot rename '%s' to '%s'", filename_tmp, filename);
00553
00554
00555 STOPIF( hlp__lstat( filename, &(sts->st)),
00556 "Cannot lstat('%s')", filename);
00557
00558
00559 sts->url=current_url;
00560
00561
00562 sts->parent->to_be_sorted=1;
00563
00564 apr_pool_destroy(subpool);
00565 subpool=NULL;
00566
00567
00568 ex:
00569
00570
00571 if (status)
00572 unlink(filename_tmp);
00573
00574 return status;
00575 }
00576
00577
00584 int rev__merge(struct estat *sts,
00585 const char *file1,
00586 const char *common,
00587 const char *file2)
00588 {
00589 int status;
00590 pid_t pid;
00591 char *output;
00592 int hdl;
00593 struct sstat_t stat;
00594 int retval;
00595
00596
00597 STOPIF( ops__build_path(&output, sts), NULL);
00598
00599
00600 STOPIF( hlp__lstat(file2, &stat), NULL);
00601
00602
00603 pid=fork();
00604 STOPIF_CODE_ERR( pid == -1, errno, "Cannot fork()" );
00605 if (pid == 0)
00606 {
00607
00608
00609
00610
00611
00612
00613
00614 hdl=open(output, O_WRONLY | O_CREAT, 0700);
00615 STOPIF_CODE_ERR( hdl == -1, errno,
00616 "Cannot open merge output \"%s\"", output);
00617 STOPIF_CODE_ERR( dup2(hdl, STDOUT_FILENO) == -1, errno,
00618 "Cannot dup2");
00619
00620
00621
00622
00623 setenv(FSVS_EXP_CURR_ENTRY, output+2, 1);
00624
00625 STOPIF_CODE_ERR( execlp( opt__get_string(OPT__MERGE_PRG),
00626 opt__get_string(OPT__MERGE_PRG),
00627 opt__get_string(OPT__MERGE_OPT),
00628 file1, common, file2,
00629 NULL) == -1, errno,
00630 "Starting the merge program \"%s\" failed",
00631 opt__get_string(OPT__MERGE_PRG));
00632
00633 }
00634
00635 STOPIF_CODE_ERR( pid != waitpid(pid, &retval, 0), errno, "waitpid");
00636
00637 DEBUGP("merge returns %d (signal %d)",
00638 WEXITSTATUS(retval), WTERMSIG(retval));
00639
00640
00641 STOPIF_CODE_ERR( WIFSIGNALED(retval) || !WIFEXITED(retval), EINVAL,
00642 "\"%s\" quits by signal %d.",
00643 opt__get_string(OPT__MERGE_PRG),
00644 WTERMSIG(retval));
00645
00646 if (WEXITSTATUS(retval) == 0)
00647 {
00648 DEBUGP("Remove temporary files.");
00649
00650
00651 if (unlink(file1) == -1) status=errno;
00652 if (unlink(file2) == -1) status=errno;
00653 if (unlink(common) == -1) status=errno;
00654 STOPIF(status, "Removing one or more temporary files "
00655 "(merge of \"%s\") failed", output);
00656 }
00657 else
00658 {
00659 DEBUGP("non-zero return");
00660 STOPIF_CODE_ERR( WEXITSTATUS(retval) != 1, EINVAL,
00661 "\"%s\" exited with error code %d",
00662 opt__get_string(OPT__MERGE_PRG),
00663 WEXITSTATUS(retval));
00664
00665 STOPIF( res__mark_conflict(sts,
00666 file1, file2, common, NULL), NULL);
00667
00668
00669 }
00670
00671
00672 sts->st.mtim.tv_sec=time(NULL);
00673
00674
00675
00676 STOPIF( up__set_meta_data(sts, NULL), NULL);
00677 sts->st=stat;
00678
00679
00680 ex:
00681 return status;
00682 }
00683
00684
00687 int rev__get_props(struct estat *sts,
00688 char *utf8_path,
00689 svn_revnum_t revision,
00690 apr_pool_t *pool)
00691 {
00692 int status;
00693 svn_error_t *status_svn;
00694 apr_hash_t *props;
00695 char *filename;
00696
00697
00698 if (!utf8_path)
00699 {
00700 STOPIF( ops__build_path(&filename, sts), NULL);
00701 STOPIF( hlp__local2utf8(filename+2, &utf8_path, -1), NULL);
00702 }
00703
00704 STOPIF_SVNERR( svn_ra_get_file,
00705 (current_url->session,
00706 utf8_path,
00707 revision,
00708 NULL,
00709 NULL,
00710 &props,
00711 pool) );
00712 STOPIF( prp__set_from_aprhash(sts, props, STORE_IN_FS, NULL, pool), NULL);
00713
00714 ex:
00715 return status;
00716 }
00717
00718
00721 int rev___handle_dir_mtime(struct estat *dir,
00722 enum rev___dir_change_flag_e dir_flag)
00723 {
00724 int status;
00725 char *path;
00726
00727
00728
00729
00730
00731
00732
00733 status=0;
00734 DEBUGP("dir_flag says %X", dir_flag);
00735
00736
00737 if (dir_flag & SET_CURRENT) goto a;
00738 if (dir_flag & REVERT_MTIME) goto b;
00739 if (dir->remote_status & FS_META_CHANGED) goto c;
00740 if (dir_flag & GET_TSTAMP) goto d;
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 goto x;
00751
00752 a:
00753
00754
00755 time( & dir->st.mtim.tv_sec );
00756 b:
00757
00758 dir->remote_status |= FS_META_MTIME;
00759 c:
00760 STOPIF( up__set_meta_data(dir, NULL), NULL);
00761 d:
00762
00763 STOPIF( ops__build_path(&path, dir), NULL);
00764 STOPIF( hlp__lstat(path, &dir->st), NULL);
00765
00766
00767 if (dir->entry_status & FS_CHANGED)
00768 dir->flags |= RF_CHECK;
00769
00770 x:
00771
00772 ex:
00773 return status;
00774 }
00775
00776
00794 int rev___revert_to_base(struct estat *sts,
00795 enum rev___dir_change_flag_e *dir_change_flag,
00796 apr_pool_t *pool)
00797 {
00798 int status;
00799 svn_revnum_t wanted;
00800 struct estat copy;
00801 char *path;
00802
00803
00804 status=0;
00805 STOPIF( ops__build_path(&path, sts), NULL);
00806
00807
00808
00809
00810
00811 if ( (sts->flags & RF_UNVERSION))
00812 {
00813
00814 sts->flags &= ~RF_UNVERSION;
00815 DEBUGP("removing unversion on %s", path);
00816 }
00817 else if ( sts->flags & RF_ADD )
00818 {
00819
00820 sts->to_be_ignored=1;
00821 DEBUGP("removing add-flag on %s", path);
00822 }
00823 else if (!( (sts->flags & (RF_COPY_BASE | RF_COPY_SUB)) || sts->url ) )
00824 {
00825
00826
00827
00828
00829 printf("Cannot revert unknown entry \"%s\".\n", path);
00830 status=0;
00831 goto ex;
00832 }
00833 else
00834 {
00835
00836 DEBUGP("have an URL for %s", path);
00837
00838 if ( sts->flags & RF_CONFLICT )
00839 {
00840 *dir_change_flag |= REVERT_MTIME;
00841 STOPIF( res__remove_aux_files(sts), NULL);
00842 }
00843
00844
00845
00846 if (!opt_target_revisions_given &&
00847 !(sts->entry_status & FS__CHANGE_MASK))
00848 goto ex;
00849
00850
00851 wanted=opt_target_revisions_given ? opt_target_revision : sts->repos_rev;
00852
00853
00854
00855
00856
00857
00858
00859 if (sts->parent && (!number_reverted || last_rev != wanted))
00860 {
00861 if (opt__verbosity() > VERBOSITY_VERYQUIET)
00862 printf("Reverting to revision %s:\n", hlp__rev_to_string(wanted));
00863 last_rev=wanted;
00864 }
00865 number_reverted++;
00866
00867
00868
00869 copy=*sts;
00870
00871 DEBUGP("l_st=%s, r_st=%s, old=%p",
00872 st__status_string_fromint(sts->entry_status),
00873 st__status_string_fromint(sts->remote_status),
00874 sts->old);
00875
00876
00877 if (!S_ISDIR(sts->st.mode))
00878 {
00879 DEBUGP("file was changed, reverting");
00880
00881
00882
00883
00884
00885
00886
00887
00888 STOPIF( rev__install_file(sts, wanted, sts->decoder, pool),
00889 "Unable to revert entry '%s'", path);
00890 *dir_change_flag |= REVERT_MTIME;
00891 }
00892 else
00893 {
00894 #if 0
00895 if (sts->entry_status & FS_NEW)
00896 conflict();
00897 #endif
00898 if (sts->entry_status & FS_REMOVED)
00899 {
00900
00901 status = (mkdir(path, sts->st.mode & 07777) == -1) ? errno : 0;
00902 if (status == EEXIST)
00903 {
00904 DEBUGP("old=%p", sts->old);
00905 }
00906 DEBUGP("mkdir(%s) says %d", path, status);
00907 STOPIF(status, "Cannot create directory '%s'", path);
00908 *dir_change_flag |= REVERT_MTIME;
00909
00910
00911
00912 sts->remote_status |= FS_META_CHANGED;
00913 }
00914 else
00915 {
00916
00917
00918
00919
00920
00921
00922 sts->remote_status=sts->entry_status;
00923 }
00924
00925 STOPIF( up__set_meta_data(sts, NULL), NULL);
00926 if (sts->entry_status)
00927 sts->flags |= RF_CHECK;
00928 }
00929 }
00930
00931
00932
00933 sts->flags |= RF_PRINT;
00934
00935 ex:
00936 return status;
00937 }
00938
00939
00941 int rev___no_local_change(struct estat *sts)
00942 {
00943 sts->entry_status=0;
00944 return st__progress(sts);
00945 }
00946
00947
00964 int rev___local_revert(struct estat *dir,
00965 apr_pool_t *pool)
00966 {
00967 int status;
00968 int i, do_undo;
00969 struct estat *sts;
00970 apr_pool_t *subpool;
00971 enum rev___dir_change_flag_e dir_flag;
00972
00973
00974 status=0;
00975 subpool=NULL;
00976 dir_flag= NOT_CHANGED;
00977
00978 for(i=0; i<dir->entry_count; i++)
00979 {
00980 sts=dir->by_inode[i];
00981 STOPIF( apr_pool_create(&subpool, pool), "Cannot get a subpool");
00982
00983 do_undo = sts->do_this_entry &&
00984 (sts->entry_status & FS__CHANGE_MASK) &&
00985 ops__allowed_by_filter(sts);
00986
00987 DEBUGP("on %s: do_undo=%d, st=%s", sts->name, do_undo,
00988 st__status_string_fromint(sts->entry_status));
00989
00990 if (do_undo)
00991 STOPIF( rev___revert_to_base(sts, &dir_flag, subpool), NULL);
00992
00993 if (S_ISDIR(sts->st.mode) &&
00994 (sts->entry_status & FS_CHILD_CHANGED))
00995 STOPIF( rev___local_revert(sts, subpool), NULL);
00996
00997 if (do_undo)
00998 STOPIF( st__status(sts), NULL);
00999
01000
01001 apr_pool_destroy(subpool);
01002 subpool=NULL;
01003 }
01004
01005
01006
01007 STOPIF( ops__free_marked(dir, 0), NULL);
01008
01009
01010 if (!dir->parent)
01011 STOPIF( st__status(dir), NULL);
01012
01013
01014 STOPIF( rev___handle_dir_mtime(dir, dir_flag), NULL);
01015
01016 ex:
01017 return status;
01018 }
01019
01020
01024 int rev__work(struct estat *root, int argc, char *argv[])
01025 {
01026 int status;
01027 char **normalized;
01028 time_t delay_start;
01029 svn_revnum_t rev;
01030
01031
01032 status=0;
01033
01034 opt_recursive--;
01035
01036 if (!argc) ac__Usage_this();
01037
01038 STOPIF( waa__find_common_base(argc, argv, &normalized), NULL);
01039
01040 STOPIF( url__load_nonempty_list(NULL, 0), NULL);
01041
01042 if (opt_target_revisions_given)
01043 {
01044 STOPIF( wa__warn( WRN__MIXED_REV_WC, EINVAL,
01045 "Sorry, fsvs currently doesn't allow mixed revision working copies.\n"
01046 "Entries will still be compared against the BASE revision.\n"),
01047 NULL);
01048
01049
01050 action->local_callback=rev___no_local_change;
01051 }
01052 else
01053 {
01054
01055 action->local_callback=st__progress;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064 status=waa__read_or_build_tree(root, argc, normalized, argv, NULL, 1);
01065 if (status == -ENOENT)
01066 STOPIF(status,
01067 "!We know nothing about previous or current versions, as this tree\n"
01068 "was never checked in.\n"
01069 "If you need such an entry reverted, you could either write the needed\n"
01070 "patch (and send it to dev@fsvs.tigris.org), or try with a 'sync-repos'\n"
01071 "command before (if you know a good revision number)\n");
01072 else
01073 STOPIF(status, NULL);
01074
01075 STOPIF( st__progress_uninit(), NULL);
01076
01077
01078 if (opt_target_revisions_given)
01079 {
01080 while ( ! ( status=url__iterator(&rev) ) )
01081 {
01082 STOPIF( cb__record_changes(root, rev, current_url->pool), NULL);
01083 }
01084 STOPIF_CODE_ERR( status != EOF, status, NULL);
01085
01086 STOPIF( rev__do_changed(root, global_pool), NULL);
01087 }
01088 else
01089 {
01090
01091
01092
01093
01094
01095
01096
01097
01098 STOPIF( rev___local_revert(root, global_pool), NULL);
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 if (!opt_target_revisions_given)
01116 {
01117 delay_start=time(NULL);
01118 STOPIF( waa__output_tree(root), NULL);
01119 STOPIF( hlp__delay(delay_start, DELAY_REVERT), NULL);
01120 }
01121
01122 ex:
01123 return status;
01124 }
01125
01126
01131 int rev___undo_change(struct estat *sts,
01132 enum rev___dir_change_flag_e *dir_change_flag,
01133 apr_pool_t *pool)
01134 {
01135 int status;
01136 char *fn;
01137 const char *unique_name_mine,
01138 *unique_name_remote,
01139 *unique_name_common;
01140 char revnum[12];
01141 int j;
01142 struct estat *removed;
01143 struct sstat_t st;
01144
01145
01146 STOPIF( ops__build_path( &fn, sts), NULL);
01147 DEBUGP_dump_estat(sts);
01148
01149
01150
01151
01152
01153 unique_name_mine=NULL;
01154
01155
01156 if (sts->entry_status & FS_CHANGED)
01157 switch (opt__get_int(OPT__CONFLICT))
01158 {
01159 case CONFLICT_STOP:
01160 STOPIF( EBUSY, "!The entry %s has changed locally", fn);
01161 break;
01162
01163 case CONFLICT_LOCAL:
01164
01165 STOPIF_CODE_EPIPE( printf("Conflict for %s skipped.\n", fn), NULL);
01166 goto ex;
01167
01168 case CONFLICT_REMOTE:
01169
01170 break;
01171
01172 case CONFLICT_MERGE:
01173 case CONFLICT_BOTH:
01174
01175 STOPIF( hlp__rename_to_unique(fn, ".mine",
01176 &unique_name_mine, pool), NULL);
01177
01178 break;
01179
01180 default:
01181 BUG("unknown conflict resolution");
01182 }
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 removed=sts->old ? sts->old : sts;
01195 if (removed->remote_status & FS_REMOVED)
01196 {
01197
01198
01199
01200 if ((sts->entry_status & FS_REPLACED) != FS_REMOVED &&
01201 !unique_name_mine)
01202 {
01203
01204 if (TEST_PACKED(S_ISDIR, removed->old_rev_mode_packed))
01205 {
01206 STOPIF( up__rmdir(removed, sts->url), NULL);
01207 }
01208 else
01209 STOPIF( up__unlink(removed, fn), NULL);
01210 }
01211
01212 *dir_change_flag|=REVERT_MTIME;
01213 }
01214
01215
01216
01217 if (TEST_PACKED(S_ISGARBAGE, sts->local_mode_packed))
01218 {
01219 DEBUGP("cleaning garbage");
01220 STOPIF_CODE_ERR( unlink(fn) == -1, errno,
01221 "Cannot remove garbage entry %s", fn);
01222 }
01223
01224
01225
01226
01227
01228 sts->parent->to_be_sorted=1;
01229
01230 if ((sts->remote_status & FS_REPLACED) == FS_REMOVED)
01231 {
01232 sts->to_be_ignored=1;
01233 goto ex;
01234 }
01235 current_url=sts->url;
01236
01237 if (S_ISDIR(sts->st.mode))
01238 {
01239 *dir_change_flag|=REVERT_MTIME;
01240 STOPIF( waa__mkdir_mask(fn, 1, sts->st.mode), NULL);
01241
01242
01243
01244
01245
01246 }
01247 else if (sts->remote_status & (FS_CHANGED | FS_REPLACED))
01248
01249 {
01250 STOPIF( rev__install_file(sts, 0, sts->decoder, pool), NULL);
01251 *dir_change_flag|=REVERT_MTIME;
01252
01253
01254
01255 if (unique_name_mine)
01256 {
01257 *dir_change_flag|=SET_CURRENT;
01258
01259
01260
01261 snprintf(revnum, sizeof(revnum)-1,
01262 ".r%llu", (t_ull)sts->repos_rev);
01263 revnum[sizeof(revnum)-1]=0;
01264
01265 STOPIF( hlp__rename_to_unique(fn, revnum,
01266 &unique_name_remote, pool), NULL);
01267
01268
01269
01270 if (sts->flags & RF_CONFLICT)
01271 {
01272 STOPIF_CODE_EPIPE(
01273 printf("\"%s\" already marked as conflict.\n", fn),
01274 NULL);
01275 STOPIF( res__mark_conflict(sts,
01276 unique_name_mine, unique_name_remote, NULL), NULL);
01277 }
01278 else if (opt__get_int(OPT__CONFLICT) == CONFLICT_BOTH)
01279 {
01280 STOPIF( res__mark_conflict(sts,
01281 unique_name_mine, unique_name_remote, NULL), NULL);
01282
01283
01284
01285
01286 j=creat(fn, 0777);
01287 if (j != -1) j=close(j);
01288
01289 STOPIF_CODE_ERR(j == -1, errno,
01290 "Error creating \"%s\"", fn);
01291
01292
01293
01294 st=sts->st;
01295 STOPIF( up__set_meta_data(sts, fn), NULL);
01296 sts->st=st;
01297 }
01298 else if (opt__get_int(OPT__CONFLICT) == CONFLICT_MERGE)
01299 {
01300 STOPIF( rev__install_file(sts, sts->old_rev,
01301 NULL, pool), NULL);
01302
01303 snprintf(revnum, sizeof(revnum)-1,
01304 ".r%llu", (t_ull)sts->old_rev);
01305 revnum[sizeof(revnum)-1]=0;
01306
01307 STOPIF( hlp__rename_to_unique(fn, revnum,
01308 &unique_name_common, pool), NULL);
01309
01310 STOPIF( rev__merge(sts,
01311 unique_name_mine,
01312 unique_name_common,
01313 unique_name_remote), NULL);
01314 }
01315 else
01316 BUG("why a conflict?");
01317 }
01318 }
01319 else
01320 {
01321
01322
01323
01324 if (sts->remote_status & FS_PROPERTIES)
01325 STOPIF( rev__get_props(sts, NULL, sts->repos_rev, pool), NULL);
01326
01327 if (sts->remote_status & FS_META_CHANGED)
01328 {
01329
01330
01331
01332 STOPIF( up__set_meta_data(sts, fn), NULL);
01333 }
01334 }
01335
01336
01337 ex:
01338 return status;
01339 }
01340
01341
01344 int rev__do_changed(struct estat *dir,
01345 apr_pool_t *pool)
01346 {
01347 int status;
01348 int i;
01349 struct estat *sts;
01350 apr_pool_t *subpool;
01351 enum rev___dir_change_flag_e dir_flag;
01352
01353
01354 status=0;
01355 subpool=NULL;
01356 dir_flag= (dir->entry_status & FS_NEW) ||
01357 (dir->remote_status & FS_NEW) ? REVERT_MTIME : NOT_CHANGED;
01358
01359
01360
01361 if (!(dir->remote_status & FS_CHILD_CHANGED))
01362 DEBUGP("%s: no children changed", dir->name);
01363 else for(i=0; i<dir->entry_count; i++)
01364 {
01365 sts=dir->by_inode[i];
01366
01367 STOPIF( apr_pool_create(&subpool, pool), "Cannot get a subpool");
01368
01369 if (sts->remote_status & FS__CHANGE_MASK)
01370 STOPIF( rev___undo_change(sts, &dir_flag, subpool), NULL);
01371
01372
01373
01374
01375 if (S_ISDIR(sts->st.mode) &&
01376 (sts->remote_status & FS_REPLACED) != FS_REMOVED)
01377 {
01378 apr_pool_destroy(subpool);
01379 subpool=NULL;
01380 STOPIF( apr_pool_create(&subpool, pool), "subpool creation");
01381
01382 STOPIF( rev__do_changed(sts, subpool), NULL);
01383 }
01384
01385 STOPIF( st__rm_status(sts), NULL);
01386
01387 apr_pool_destroy(subpool);
01388 subpool=NULL;
01389 }
01390
01391
01392
01393 STOPIF( ops__free_marked(dir, 0), NULL);
01394
01395
01396 if (!dir->parent)
01397 STOPIF( st__rm_status(dir), NULL);
01398
01399
01400
01401
01402
01403
01404 if (dir->entry_status & FS__CHANGE_MASK)
01405 dir->flags |= RF_CHECK;
01406
01407 STOPIF( rev___handle_dir_mtime(dir, dir_flag), NULL);
01408
01409
01410 ex:
01411 return status;
01412 }
01413
01414
01415