00001
00002
00003
00004
00005
00006
00007
00008
00040 #include <apr_md5.h>
00041 #include <apr_pools.h>
00042 #include <apr_user.h>
00043 #include <apr_file_io.h>
00044 #include <subversion-1/svn_delta.h>
00045 #include <subversion-1/svn_ra.h>
00046 #include <subversion-1/svn_error.h>
00047 #include <subversion-1/svn_string.h>
00048 #include <subversion-1/svn_time.h>
00049
00050 #include <sys/types.h>
00051 #include <unistd.h>
00052 #include <ctype.h>
00053 #include <time.h>
00054 #include <fcntl.h>
00055
00056
00057 #include "global.h"
00058 #include "helper.h"
00059 #include "url.h"
00060 #include "status.h"
00061 #include "racallback.h"
00062 #include "props.h"
00063 #include "checksum.h"
00064 #include "revert.h"
00065 #include "warnings.h"
00066 #include "est_ops.h"
00067 #include "waa.h"
00068 #include "commit.h"
00069 #include "racallback.h"
00070
00071
00072
00073 static char *filename,
00074 *filename_tmp=NULL;
00075 static unsigned tmp_len=0;
00076
00077
00083 int up__fetch_decoder(struct estat *sts)
00084 {
00085 int status, st2;
00086 hash_t db;
00087 datum value;
00088
00089
00090 db=NULL;
00091 status=0;
00092
00093 if (!action->needs_decoder ||
00094 sts->decoder) goto ex;
00095
00096 status=prp__open_byestat(sts, GDBM_READER, &db);
00097 if (status == ENOENT)
00098 status=0;
00099 else
00100 {
00101 STOPIF(status, NULL);
00102
00103
00104
00105
00106 if (prp__get(db, propval_updatepipe, &value) == 0)
00107 STOPIF( hlp__strdup( &sts->decoder, value.dptr), NULL);
00108 }
00109
00110 ex:
00111 if (db)
00112 {
00113 st2=hsh__close(db, status);
00114 if (!status) STOPIF(st2, NULL);
00115 }
00116 return status;
00117 }
00118
00119
00129 int up__parse_prop(struct estat *sts,
00130 const char *utf8_name,
00131 const svn_string_t *utf8_value,
00132 int *not_handled,
00133 apr_pool_t *pool)
00134 {
00135 char *cp, *loc_name, *loc_value;
00136 int i,status;
00137 apr_uid_t uid;
00138 apr_gid_t gid;
00139 apr_time_t at;
00140 svn_error_t *status_svn;
00141
00142
00143
00144
00145
00146
00147
00148 STOPIF( hlp__utf82local(utf8_name, &loc_name, -1), NULL);
00149
00150 status=0;
00151 if (!utf8_value)
00152 {
00153 DEBUGP("got NULL property for %s: %s", sts->name, loc_name);
00154
00155 loc_value=NULL;
00156 }
00157 else
00158 {
00159 STOPIF( hlp__utf82local(utf8_value->data, &loc_value, -1), NULL);
00160 DEBUGP("got property for %s: %s=%s",
00161 sts->name, loc_name, loc_value);
00162 }
00163
00164
00165
00166
00167 if (0 == strcmp(utf8_name, propname_owner))
00168 {
00169
00170
00171 i=strtoul(utf8_value->data, &cp, 0);
00172 if (cp == utf8_value->data)
00173 STOPIF( wa__warn(WRN__META_USER_INVALID, EINVAL,
00174 "cannot read uid in %s", loc_value),
00175 NULL);
00176 else
00177 {
00178 cp=hlp__skip_ws(cp);
00179 if (*cp)
00180 {
00181 status=hlp__get_uid(cp, &uid, pool);
00182 if (status == APR_SUCCESS)
00183 i=uid;
00184
00185 status=0;
00186 }
00187
00188 if (sts->st.uid != i)
00189 {
00190 sts->remote_status |= FS_META_OWNER;
00191 if (!action->is_compare)
00192 {
00193 sts->st.uid = i;
00194 DEBUGP("marking owner %s to %d",
00195 loc_value, sts->st.uid);
00196 }
00197 }
00198 }
00199 }
00200 else if (0 == strcmp(utf8_name, propname_group))
00201 {
00202 i=strtoul(utf8_value->data, &cp, 0);
00203 if (cp == utf8_value->data)
00204 STOPIF( wa__warn(WRN__META_USER_INVALID, EINVAL,
00205 "cannot read gid in %s", loc_value),
00206 NULL);
00207 else
00208 {
00209
00210 cp=hlp__skip_ws(cp);
00211 if (*cp)
00212 {
00213 status=hlp__get_gid(cp, &gid, pool);
00214 if (status == APR_SUCCESS)
00215 i=gid;
00216 status=0;
00217 }
00218
00219 if (sts->st.gid != i)
00220 {
00221 sts->remote_status |= FS_META_GROUP;
00222 if (!action->is_compare)
00223 {
00224 sts->st.gid = i;
00225 DEBUGP("marking group %s to %d",
00226 loc_value, sts->st.gid);
00227 }
00228 }
00229 }
00230 }
00231 else if (0 == strcmp(utf8_name, propname_mtime))
00232 {
00233 status_svn=svn_time_from_cstring(&at, utf8_value->data, pool);
00234 if (status_svn)
00235 STOPIF( wa__warn(WRN__META_MTIME_INVALID, EINVAL,
00236 "modification time string invalid: %s", loc_value),
00237 NULL);
00238 else
00239 {
00240 if (sts->st.mtim.tv_sec != apr_time_sec(at) ||
00241 sts->st.mtim.tv_nsec != apr_time_usec(at) * 1000)
00242 {
00243 sts->remote_status |= FS_META_MTIME;
00244
00245 if (!action->is_compare)
00246 {
00247
00248
00249
00250
00251 {
00252 sts->st.mtim.tv_sec=apr_time_sec(at);
00253
00254 sts->st.mtim.tv_nsec=apr_time_usec(at) * 1000;
00255 }
00256 DEBUGP("marking mtime \"%s\" to %24.24s",
00257 loc_value,
00258 ctime(& (sts->st.mtim.tv_sec) ));
00259 }
00260 }
00261 }
00262 }
00263 else if (0 == strcmp(utf8_name, propname_umode))
00264 {
00265 i=strtoul(utf8_value->data, &cp, 0);
00266 if (*cp || i>07777)
00267 STOPIF( wa__warn(WRN__META_UMASK_INVALID, EINVAL,
00268 "no valid permissions found in %s", loc_value),
00269 NULL);
00270 else
00271 {
00272 if ((sts->st.mode & 07777) != i)
00273 {
00274 sts->remote_status |= FS_META_UMODE;
00275 if (!action->is_compare)
00276 {
00277 sts->st.mode = (sts->st.mode & ~07777) | i;
00278 DEBUGP("marking mode \"%s\" to 0%o",
00279 loc_value, sts->st.mode & 07777);
00280 }
00281 }
00282 }
00283 }
00284 else if (0 == strcmp(utf8_name, propname_special) &&
00285 0 == strcmp(utf8_value->data, propval_special))
00286 {
00287 if (TEST_PACKED(S_ISANYSPECIAL, sts->new_rev_mode_packed))
00288 {
00289 DEBUGP("already marked as special");
00290 }
00291 else
00292 {
00293
00294
00295 if (!(S_ISLNK(PACKED_to_MODE_T(sts->new_rev_mode_packed)) ||
00296 S_ISCHR(PACKED_to_MODE_T(sts->new_rev_mode_packed)) ||
00297 S_ISBLK(PACKED_to_MODE_T(sts->new_rev_mode_packed))) )
00298 {
00299 sts->st.mode = (sts->st.mode & ~S_IFMT) | S_IFANYSPECIAL;
00300 sts->new_rev_mode_packed = MODE_T_to_PACKED(sts->st.mode);
00301 }
00302 DEBUGP("this is a special node");
00303 }
00304 }
00305 else if (0 == strcmp(utf8_name, propname_origmd5))
00306 {
00307
00308
00309
00310 BUG_ON(S_ISDIR(sts->st.mode));
00311 STOPIF( cs__char2md5( utf8_value->data, NULL, sts->md5), NULL);
00312 DEBUGP("got a orig-md5: %s", cs__md5tohex_buffered(sts->md5));
00313 sts->has_orig_md5=1;
00314 }
00315 else
00316 {
00317 if (strcmp(utf8_name, propval_updatepipe) == 0)
00318 {
00319 if (action->needs_decoder)
00320 {
00321
00322
00323
00324
00325
00326 STOPIF( hlp__strdup( &sts->decoder, utf8_value->data), NULL);
00327 sts->decoder_is_correct=1;
00328 DEBUGP("got a decoder: %s", sts->decoder);
00329 }
00330 }
00331
00332
00333 if (!hlp__is_special_property_name(utf8_name))
00334 {
00335 sts->remote_status |= FS_PROPERTIES;
00336
00337 DEBUGP("property %s: %s=%s",
00338 sts->name,
00339 loc_name, loc_value);
00340 if (not_handled) *not_handled=1;
00341 }
00342 }
00343
00344
00345 ex:
00346 return status;
00347
00348 #if 0
00349 inval:
00350
00351
00352
00353 status=ops__build_path(&cp, sts);
00354 STOPIF(EINVAL, "incorrect utf8_value for property %s ignored: "
00355 "file %s: \"%s\"",
00356 name,
00357 status == 0 ? cp : sts->name,
00358 utf8_value->data);
00359 #endif
00360 }
00361
00362
00366 int up__unlink(struct estat *sts, char *filename)
00367 {
00368 int status;
00369
00370
00371 status=0;
00372 if (!filename)
00373 STOPIF( ops__build_path(&filename, sts), NULL );
00374
00375
00376 if (sts->entry_status & FS_CHANGED)
00377 STOPIF_CODE_ERR(1, EBUSY,
00378 "File %s has been changed - won't remove", filename);
00379
00380 if (unlink(filename) == -1)
00381 {
00382 status=errno;
00383
00384 if (status == ENOENT) status=0;
00385 }
00386 else
00387 {
00388 STOPIF( waa__delete_byext(filename, WAA__FILE_MD5s_EXT, 1), NULL);
00389 STOPIF( waa__delete_byext(filename, WAA__PROP_EXT, 1), NULL);
00390 }
00391
00392 DEBUGP("unlink(%s)", filename);
00393
00394 ex:
00395 return status;
00396 }
00397
00398
00412 int up__rmdir(struct estat *sts, struct url_t *url)
00413 {
00414 int status, i, has_others;
00415 struct estat *cur;
00416 char *path;
00417
00418
00419 status=0;
00420 has_others=0;
00421
00422
00423 for(i=0; i<sts->entry_count; i++)
00424 {
00425 cur=sts->by_inode[i];
00426
00427 if (url && cur->url != url)
00428 has_others++;
00429 else
00430 {
00431
00432
00433
00434
00435
00436 status=up__unlink(cur, NULL);
00437 if (status == EISDIR)
00438 status=up__rmdir(cur, url);
00439
00440 STOPIF( status, "unlink of %s failed", cur->name);
00441 }
00442 }
00443
00444 if (!has_others)
00445 {
00446 STOPIF( ops__build_path(&path, sts), NULL );
00447 status = rmdir(path) == -1 ? errno : 0;
00448
00449 DEBUGP("removing %s: %d", path, status);
00450 if (status == ENOENT) status=0;
00451 STOPIF( status, "Cannot remove directory %s", path);
00452 }
00453
00454 ex:
00455 return status;
00456 }
00457
00458
00520 int up__set_meta_data(struct estat *sts, char *filename)
00521 {
00522 struct timeval tv[2];
00523 int status;
00524 mode_t current_mode;
00525
00526
00527 status=0;
00528 current_mode= PACKED_to_MODE_T(sts->new_rev_mode_packed);
00529
00530 if (!filename)
00531 STOPIF( ops__build_path(&filename, sts), NULL );
00532
00533 DEBUGP_dump_estat(sts);
00534
00535
00536
00537
00538
00539 if (CHOWN_BOOL || !S_ISLNK(current_mode))
00540 {
00541 if (sts->remote_status & (FS_META_OWNER | FS_META_GROUP))
00542 {
00543 DEBUGP("setting %s to %d.%d",
00544 filename, sts->st.uid, sts->st.gid);
00545 status=CHOWN_FUNC(filename, sts->st.uid, sts->st.gid);
00546 if (status == -1)
00547 {
00548 STOPIF( wa__warn( errno==EPERM ? WRN__CHOWN_EPERM : WRN__CHOWN_OTHER,
00549 errno, "Cannot chown \"%s\" to %d:%d",
00550 filename, sts->st.uid, sts->st.gid),
00551 NULL );
00552 }
00553 }
00554 }
00555 else
00556 {
00557 DEBUGP("a symlink, but no lchown: %s", filename);
00558 }
00559
00560
00561
00562 if (!S_ISLNK(current_mode))
00563 {
00564 if (sts->remote_status & FS_META_UMODE)
00565 {
00566
00567
00568
00569 DEBUGP("setting %s's mode to 0%o",
00570 filename, sts->st.mode & 07777);
00571 status=chmod(filename, sts->st.mode & 07777);
00572 if (status == -1)
00573 {
00574 STOPIF( wa__warn( errno == EPERM ? WRN__CHMOD_EPERM : WRN__CHMOD_OTHER,
00575 errno, "Cannot chmod \"%s\" to 0%3o",
00576 filename, sts->st.mode & 07777 ),
00577 NULL );
00578 }
00579 }
00580 }
00581
00582 if (UTIMES_BOOL || !S_ISLNK(current_mode))
00583 {
00584 if (sts->remote_status & FS_META_MTIME)
00585 {
00586
00587 tv[1].tv_sec =sts->st.mtim.tv_sec;
00588 tv[1].tv_usec=sts->st.mtim.tv_nsec/1000;
00589
00590
00591
00592 tv[0].tv_sec =sts->st.mtim.tv_sec;
00593 tv[0].tv_usec=sts->st.mtim.tv_nsec/1000;
00594 DEBUGP("setting %s's mtime %24.24s",
00595 filename, ctime(& (sts->st.mtim.tv_sec) ));
00596 STOPIF_CODE_ERR( UTIMES_FUNC(filename, tv) == -1,
00597 errno, "utimes(%s)", filename);
00598 }
00599 }
00600 else
00601 {
00602 DEBUGP("a symlink, but no lutimes: %s", filename);
00603 }
00604
00605 STOPIF( hlp__lstat(filename, & sts->st), NULL);
00606
00607 ex:
00608 return status;
00609 }
00610
00611
00618 int up__handle_special(struct estat *sts,
00619 char *path,
00620 char *data,
00621 apr_pool_t *pool)
00622 {
00623 int status;
00624 char *cp;
00625
00626
00627 STOPIF( ops__string_to_dev(sts, data, &cp), NULL);
00628 STOPIF( hlp__utf82local(cp, &cp, -1), NULL);
00629
00630
00631 sts->new_rev_mode_packed=sts->local_mode_packed;
00632
00633 sts->stringbuf_tgt=NULL;
00634 DEBUGP("special %s has mode 0%o", path, sts->st.mode);
00635
00636
00637
00638 switch (PACKED_to_MODE_T(sts->new_rev_mode_packed) & S_IFMT)
00639 {
00640 case S_IFBLK:
00641 case S_IFCHR:
00642 STOPIF_CODE_ERR( mknod(path, sts->st.mode, sts->st.rdev) == -1,
00643 errno, "mknod(%s)", path) ;
00644 break;
00645
00646 case S_IFLNK:
00647 STOPIF_CODE_ERR( symlink(cp, path) == -1,
00648 errno, "symlink(%s, %s)", cp, path);
00649 break;
00650
00651 default:
00652 STOPIF_CODE_ERR(1, EINVAL,
00653 "what kind of node is this??? (mode=0%o)", sts->st.mode);
00654 }
00655
00656 ex:
00657 return status;
00658 }
00659
00660
00661
00662 svn_error_t *up__set_target_revision(void *edit_baton,
00663 svn_revnum_t rev,
00664 apr_pool_t *pool)
00665 {
00666 struct estat *sts=edit_baton;
00667 int status;
00668
00669
00670 status=0;
00671
00672
00673
00674 target_revision=rev;
00675 sts->repos_rev=rev;
00676
00677 RETURN_SVNERR(status);
00678 }
00679
00680
00681 svn_error_t *up__open_root(void *edit_baton,
00682 svn_revnum_t base_revision,
00683 apr_pool_t *dir_pool UNUSED,
00684 void **root_baton)
00685 {
00686 struct estat *sts=edit_baton;
00687
00688 sts->repos_rev=base_revision;
00689 *root_baton=sts;
00690
00691 return SVN_NO_ERROR;
00692 }
00693
00694
00695 svn_error_t *up__add_directory(const char *utf8_path,
00696 void *parent_baton,
00697 const char *utf8_copy_path,
00698 svn_revnum_t copy_rev,
00699 apr_pool_t *dir_pool UNUSED,
00700 void **child_baton)
00701 {
00702 struct estat *dir=parent_baton;
00703 struct estat *sts;
00704 int status;
00705 char* path;
00706
00707
00708 STOPIF( cb__add_entry(dir, utf8_path, &path, utf8_copy_path,
00709 copy_rev, S_IFDIR, NULL, 1,
00710 child_baton), NULL );
00711 sts=(struct estat*)*child_baton;
00712
00713 if (!action->is_compare)
00714 {
00715
00716
00717
00718 STOPIF_CODE_ERR( mkdir(path, 0700) == -1, errno,
00719 "mkdir(%s)", path);
00720
00721
00722 STOPIF( hlp__lstat(path, &(sts->st)),
00723 "lstat(%s)", path);
00724 }
00725
00726 status=0;
00727
00728 ex:
00729 RETURN_SVNERR(status);
00730 }
00731
00732
00733
00734 svn_error_t *up__change_dir_prop(void *dir_baton,
00735 const char *utf8_name,
00736 const svn_string_t *value,
00737 apr_pool_t *pool)
00738 {
00739 struct estat *sts=dir_baton;
00740 int status;
00741
00742 status=0;
00743 if (!sts->url || url__current_has_precedence(sts->url))
00744 STOPIF( up__parse_prop(sts, utf8_name, value, NULL, pool), NULL);
00745
00746 ex:
00747 RETURN_SVNERR(status);
00748 }
00749
00750
00751 svn_error_t *up__close_directory(
00752 void *dir_baton,
00753 apr_pool_t *pool)
00754 {
00755 struct estat *sts=dir_baton;
00756 int status;
00757
00758
00759 STOPIF( ops__build_path(&filename, sts), NULL);
00760
00761 STOPIF( up__set_meta_data(sts, filename), NULL);
00762
00763 STOPIF( hlp__lstat( filename, &(sts->st)),
00764 "Cannot lstat('%s')", filename);
00765
00766 STOPIF( st__status(sts), NULL);
00767
00768
00769 sts->flags |= RF_CHECK;
00770
00771 ex:
00772 RETURN_SVNERR(status);
00773 }
00774
00775
00777 svn_error_t *up__absent_directory(const char *utf8_path,
00778 void *parent_baton,
00779 apr_pool_t *pool)
00780 {
00781 struct estat *dir UNUSED =parent_baton;
00782
00783 DEBUGP("in %s", __PRETTY_FUNCTION__);
00784
00785 return SVN_NO_ERROR;
00786 }
00787
00788
00789 svn_error_t *up__add_file(const char *utf8_path,
00790 void *parent_baton,
00791 const char *utf8_copy_path,
00792 svn_revnum_t copy_rev,
00793 apr_pool_t *file_pool,
00794 void **file_baton)
00795 {
00796 struct estat *dir=parent_baton;
00797 int status;
00798
00799 STOPIF( cb__add_entry(dir, utf8_path, NULL, utf8_copy_path, copy_rev,
00800 S_IFREG, NULL, 1, file_baton), NULL);
00801
00802 ex:
00803 RETURN_SVNERR(status);
00804 }
00805
00806
00807 svn_error_t *up__apply_textdelta(void *file_baton,
00808 const char *base_checksum,
00809 apr_pool_t *pool,
00810 svn_txdelta_window_handler_t *handler,
00811 void **handler_baton)
00812 {
00813 struct estat *sts=file_baton;
00814 svn_stream_t *svn_s_src, *svn_s_tgt;
00815 int status;
00816 char *cp;
00817 char* fn_utf8;
00818 apr_file_t *source, *target;
00819 struct encoder_t *encoder;
00820 svn_stringbuf_t *stringbuf_src;
00821
00822
00823 stringbuf_src=NULL;
00824 encoder=NULL;
00825 STOPIF( ops__build_path(&filename, sts), NULL);
00826
00827 if (action->is_compare)
00828 {
00829
00830
00831 cp="";
00832 goto into_stringbufs;
00833 }
00834
00835 STOPIF_CODE_ERR( sts->entry_status & FS_CHANGED, EBUSY,
00836 "file '%s' was changed locally and cannot be updated", filename);
00837 #if 0
00838
00839
00840
00841 STOPIF_CODE_ERR( sts->entry_status & FS_REMOVED, ENOENT,
00842 "file '%s' was deleted locally", filename);
00843 #endif
00844
00845 status=strlen(filename)+10;
00846 if (status > tmp_len)
00847 {
00848
00849 status= (status+1024) & ~(1024-1);
00850 STOPIF( hlp__realloc( &filename_tmp, status), NULL);
00851
00852 tmp_len=status;
00853 }
00854
00855 strcpy(filename_tmp, filename);
00856 strcat(filename_tmp, ".up.tmp");
00857
00858 DEBUGP("target is %s (0%o),", filename, sts->st.mode);
00859 DEBUGP(" temp is %s", filename_tmp);
00860
00861 if (!S_ISREG(sts->st.mode))
00862 {
00863
00864 if (S_ISLNK(sts->st.mode))
00865 {
00866 STOPIF( ops__link_to_string(sts, filename, &cp),
00867 NULL);
00868 STOPIF( hlp__local2utf8(cp, &cp, -1), NULL);
00869 }
00870 else
00871 cp=ops__dev_to_filedata(sts);
00872
00873 into_stringbufs:
00874 stringbuf_src=svn_stringbuf_create(cp, pool);
00875 sts->stringbuf_tgt=svn_stringbuf_create("", pool);
00876
00877 svn_s_src=svn_stream_from_stringbuf(stringbuf_src, pool);
00878 svn_s_tgt=svn_stream_from_stringbuf(sts->stringbuf_tgt, pool);
00879 status=0;
00880 }
00881 else
00882 {
00906
00907
00908
00909
00910
00911
00912 STOPIF( apr_pool_create(&(sts->filehandle_pool), global_pool),
00913 "Creating the filehandle pool");
00914
00915
00916
00917 STOPIF( apr_file_open(&source,
00918 (sts->remote_status & (FS_NEW|FS_CHANGED|FS_REMOVED)) ?
00919 "/dev/null" : filename,
00920 APR_READ, 0, sts->filehandle_pool),
00921 NULL);
00922
00923
00924
00925 STOPIF( apr_file_open(&target, filename_tmp,
00926 APR_WRITE | APR_CREATE | APR_TRUNCATE,
00927 APR_UREAD | APR_UWRITE, sts->filehandle_pool),
00928 NULL);
00929
00930 svn_s_src=svn_stream_from_aprfile(source, sts->filehandle_pool);
00931 svn_s_tgt=svn_stream_from_aprfile(target, sts->filehandle_pool);
00932
00933
00934 if (!action->is_import_export)
00935 STOPIF( cs__new_manber_filter(sts, svn_s_tgt, &svn_s_tgt,
00936 sts->filehandle_pool),
00937 NULL);
00938
00939 if (sts->decoder)
00940 {
00941 STOPIF( hlp__encode_filter(svn_s_tgt, sts->decoder, 1,
00942 filename, &svn_s_tgt, &encoder, sts->filehandle_pool), NULL);
00943
00944 encoder->output_md5= &(sts->md5);
00945 }
00946 }
00947
00948 STOPIF( hlp__local2utf8(filename, &fn_utf8, -1), NULL );
00949 svn_txdelta_apply(svn_s_src, svn_s_tgt,
00950 action->is_compare ? NULL : sts->md5,
00951 fn_utf8, pool,
00952 handler, handler_baton);
00953
00954
00955 sts->remote_status |= FS_CHANGED;
00956
00957 ex:
00958 RETURN_SVNERR(status);
00959 }
00960
00961
00962 svn_error_t *up__change_file_prop(void *file_baton,
00963 const char *utf8_name,
00964 const svn_string_t *value,
00965 apr_pool_t *pool)
00966 {
00967 struct estat *sts=file_baton;
00968 int status;
00969
00970 status=0;
00971 if (!sts->url || url__current_has_precedence(sts->url))
00972 STOPIF( up__parse_prop(sts, utf8_name, value, NULL, pool), NULL);
00973
00974
00975 BUG_ON(sts->remote_status & FS_CHANGED,
00976 "Entry has already been fetched, properties too late!");
00977 ex:
00978 RETURN_SVNERR(status);
00979 }
00980
00981
00982 svn_error_t *up__close_file(void *file_baton,
00983 const char *text_checksum,
00984 apr_pool_t *pool)
00985 {
00986 struct estat *sts=file_baton;
00987 int status;
00988
00989 if (action->is_compare && text_checksum)
00990 {
00991 if (memcmp(text_checksum, sts->md5, sizeof(sts->md5)) != 0)
00992 sts->remote_status |= FS_CHANGED;
00993 }
00994 else
00995 {
00996
00997 DEBUGP("close file (0%o): md5=%s",
00998 sts->st.mode, cs__md5tohex_buffered(sts->md5));
00999
01000
01001 BUG_ON(!sts->st.mode);
01002
01003 if (S_ISREG(sts->st.mode))
01004 {
01005 status=0;
01006
01007
01008
01009 if (sts->filehandle_pool)
01010 apr_pool_destroy(sts->filehandle_pool);
01011 sts->filehandle_pool=NULL;
01012
01013
01014
01015
01016 }
01017 else
01018 {
01019 DEBUGP("closing special file");
01020 sts->stringbuf_tgt->data[ sts->stringbuf_tgt->len ]=0;
01021 STOPIF( up__handle_special(sts, filename_tmp,
01022 sts->stringbuf_tgt->data, pool), NULL);
01023 }
01024
01025
01026
01027 STOPIF( up__set_meta_data(sts, filename_tmp), NULL);
01028
01029
01030 STOPIF_CODE_ERR( rename(filename_tmp, filename)==-1, errno,
01031 "Cannot rename '%s' to '%s'", filename_tmp, filename);
01032
01033
01034 STOPIF( hlp__lstat( filename, &(sts->st)),
01035 "Cannot lstat('%s')", filename);
01036 }
01037
01038
01039 STOPIF( st__status(sts), NULL);
01040
01041 ex:
01042 RETURN_SVNERR(status);
01043 }
01044
01045
01047 svn_error_t *up__absent_file(const char *utf8_path,
01048 void *parent_baton,
01049 apr_pool_t *pool)
01050 {
01051 struct estat *dir UNUSED=parent_baton;
01052
01053 DEBUGP("in %s", __PRETTY_FUNCTION__);
01054 return SVN_NO_ERROR;
01055 }
01056
01057
01058 svn_error_t *up__close_edit(void *edit_baton,
01059 apr_pool_t *pool)
01060 {
01061 struct estat *sts UNUSED=edit_baton;
01062
01063 return SVN_NO_ERROR;
01064 }
01065
01066
01068 svn_error_t *up__abort_edit(void *edit_baton,
01069 apr_pool_t *pool)
01070 {
01071 struct estat *sts UNUSED=edit_baton;
01072
01073 return SVN_NO_ERROR;
01074 }
01075
01076
01077
01078
01079
01080
01081
01082 int ac___up_set_paths(struct estat *dir,
01083 const svn_ra_reporter2_t *reporter,
01084 void *report_baton,
01085 apr_pool_t *pool)
01086 {
01087 int status, i;
01088 struct estat *sts;
01089 svn_error_t *status_svn;
01090 char *fn;
01091
01092
01093 status=0;
01094 for(i=0; i<dir->entry_count; i++)
01095 {
01096 sts=dir->by_inode[i];
01097 if (S_ISDIR(sts->st.mode))
01098 STOPIF( ac___up_set_paths(sts, reporter, report_baton, pool),
01099 NULL);
01100 else
01101 if (sts->entry_status & (FS_CHANGED | FS_REMOVED))
01102 {
01103 STOPIF( ops__build_path(&fn, sts), NULL );
01104 DEBUGP(" changed: %s", fn);
01105
01106 STOPIF_SVNERR( reporter->delete_path,
01107 (report_baton, fn+2, pool));
01108 }
01109 }
01110
01111 ex:
01112 return status;
01113 }
01114
01115
01121 int up__work(struct estat *root, int argc, char *argv[])
01122 {
01123 int status;
01124 svn_error_t *status_svn;
01125 svn_revnum_t rev;
01126 time_t delay_start;
01127
01128
01129 status=0;
01130 status_svn=NULL;
01131 STOPIF( waa__find_base(root, &argc, &argv), NULL);
01132
01133 STOPIF( url__load_nonempty_list(NULL, 0), NULL);
01134
01135 STOPIF_CODE_ERR(!urllist_count, EINVAL,
01136 "There's no URL defined");
01137
01138 STOPIF( url__mark_todo(), NULL);
01139
01140 STOPIF_CODE_ERR( argc != 0, EINVAL,
01141 "Cannot do partial updates!");
01142
01143
01144 opt__set_int(OPT__CHANGECHECK, PRIO_MUSTHAVE,
01145 opt__get_int(OPT__CHANGECHECK) | CHCHECK_FILE);
01146
01147
01148
01149 STOPIF( waa__read_or_build_tree(root, argc, argv, argv, NULL, 0), NULL);
01150
01151 while ( ! ( status=url__iterator(&rev) ) )
01152 {
01153 STOPIF( cb__record_changes(root, rev, global_pool), NULL);
01154
01155 if (action->is_compare)
01156 {
01157
01158 if (opt__get_int(OPT__VERBOSE) > VERBOSITY_VERYQUIET)
01159 printf("Remote-status against revision\t%ld.\n", rev);
01160 }
01161 else
01162 {
01163
01164 DEBUGP("setting revision to %llu", (t_ull)rev);
01165 STOPIF( ci__set_revision(root, rev), NULL);
01166
01167 if (opt__get_int(OPT__VERBOSE) > VERBOSITY_VERYQUIET)
01168 printf("Updating %s to revision\t%ld.\n",
01169 current_url->url, rev);
01170 }
01171 }
01172 STOPIF_CODE_ERR( status != EOF, status, NULL);
01173 status=0;
01174
01175 if (action->is_compare)
01176 {
01177 }
01178 else
01179 {
01180 DEBUGP("fetching from repository");
01181 STOPIF( rev__do_changed(root, global_pool), NULL);
01182
01183
01184
01185 delay_start=time(NULL);
01186 STOPIF( waa__output_tree(root), NULL);
01187 STOPIF( url__output_list(), NULL);
01188 STOPIF( hlp__delay(delay_start, DELAY_UPDATE), NULL);
01189 }
01190
01191
01192 ex:
01193 STOP_HANDLE_SVNERR(status_svn);
01194 ex2:
01195 return status;
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223