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