update.c File Reference

update action. More...

#include <apr_md5.h>
#include <apr_pools.h>
#include <apr_user.h>
#include <apr_file_io.h>
#include <subversion-1/svn_delta.h>
#include <subversion-1/svn_ra.h>
#include <subversion-1/svn_error.h>
#include <subversion-1/svn_string.h>
#include <subversion-1/svn_time.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include "global.h"
#include "helper.h"
#include "url.h"
#include "status.h"
#include "racallback.h"
#include "props.h"
#include "checksum.h"
#include "revert.h"
#include "warnings.h"
#include "est_ops.h"
#include "waa.h"
#include "commit.h"
Include dependency graph for update.c:

Go to the source code of this file.

Functions

int up__fetch_decoder (struct estat *sts)
 Prefetch update-pipe property.
int up__parse_prop (struct estat *sts, const char *utf8_name, const svn_string_t *utf8_value, int *not_handled, apr_pool_t *pool)
 -.
int up__unlink (struct estat *sts, char *filename)
 -.
int up__rmdir (struct estat *sts, struct url_t *url)
 Recursively delete a directory structure.
int up__set_meta_data (struct estat *sts, char *filename)
 -.
int up__handle_special (struct estat *sts, char *path, char *data, apr_pool_t *pool)
 Handling non-file non-directory entries.
svn_error_t * up__set_target_revision (void *edit_baton, svn_revnum_t rev, apr_pool_t *pool)
svn_error_t * up__open_root (void *edit_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool UNUSED, void **root_baton)
svn_error_t * up__add_directory (const char *utf8_path, void *parent_baton, const char *utf8_copy_path, svn_revnum_t copy_rev, apr_pool_t *dir_pool UNUSED, void **child_baton)
svn_error_t * up__change_dir_prop (void *dir_baton, const char *utf8_name, const svn_string_t *value, apr_pool_t *pool)
svn_error_t * up__close_directory (void *dir_baton, apr_pool_t *pool)
svn_error_t * up__absent_directory (const char *utf8_path, void *parent_baton, apr_pool_t *pool)
 FSVS GCOV MARK: up__absent_directory should not be executed.
svn_error_t * up__add_file (const char *utf8_path, void *parent_baton, const char *utf8_copy_path, svn_revnum_t copy_rev, apr_pool_t *file_pool, void **file_baton)
svn_error_t * up__apply_textdelta (void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **handler_baton)
svn_error_t * up__change_file_prop (void *file_baton, const char *utf8_name, const svn_string_t *value, apr_pool_t *pool)
svn_error_t * up__close_file (void *file_baton, const char *text_checksum, apr_pool_t *pool)
svn_error_t * up__absent_file (const char *utf8_path, void *parent_baton, apr_pool_t *pool)
 FSVS GCOV MARK: up__absent_file should not be executed.
svn_error_t * up__close_edit (void *edit_baton, apr_pool_t *pool)
svn_error_t * up__abort_edit (void *edit_baton, apr_pool_t *pool)
 FSVS GCOV MARK: up__abort_edit should not be executed.
int ac___up_set_paths (struct estat *dir, const svn_ra_reporter2_t *reporter, void *report_baton, apr_pool_t *pool)
int up__work (struct estat *root, int argc, char *argv[])
 Main update action.

Variables

static char * filename
static char * filename_tmp = NULL
static unsigned tmp_len = 0

Detailed Description

update action.

When we've loaded the "old" version from disk, we fetch the new values from the repository.

Todo:
Could be made a bit faster. Either with multiple threads, or changing the subversion API to get all text-base changes in full-text. For a small change fsvs could query whole new trees with an "old" update.

Definition in file update.c.


Function Documentation

int ac___up_set_paths ( struct estat dir,
const svn_ra_reporter2_t *  reporter,
void *  report_baton,
apr_pool_t *  pool 
)

Definition at line 1098 of file update.c.

References estat::by_inode, DEBUGP, estat::entry_count, estat::entry_status, FS_CHANGED, FS_REMOVED, sstat_t::mode, ops__build_path(), estat::st, STOPIF, and STOPIF_SVNERR.

Here is the call graph for this function:

svn_error_t* up__abort_edit ( void *  edit_baton,
apr_pool_t *  pool 
)

FSVS GCOV MARK: up__abort_edit should not be executed.

Definition at line 1084 of file update.c.

References UNUSED.

svn_error_t* up__absent_directory ( const char *  utf8_path,
void *  parent_baton,
apr_pool_t *  pool 
)

FSVS GCOV MARK: up__absent_directory should not be executed.

Definition at line 793 of file update.c.

References DEBUGP, and UNUSED.

svn_error_t* up__absent_file ( const char *  utf8_path,
void *  parent_baton,
apr_pool_t *  pool 
)

FSVS GCOV MARK: up__absent_file should not be executed.

Definition at line 1063 of file update.c.

References DEBUGP, and UNUSED.

svn_error_t* up__add_directory ( const char *  utf8_path,
void *  parent_baton,
const char *  utf8_copy_path,
svn_revnum_t  copy_rev,
apr_pool_t *dir_pool  UNUSED,
void **  child_baton 
)

Definition at line 711 of file update.c.

References action, cb__add_entry(), hlp__lstat(), actionlist_t::is_compare, RETURN_SVNERR, estat::st, STOPIF, and STOPIF_CODE_ERR.

Here is the call graph for this function:

svn_error_t* up__add_file ( const char *  utf8_path,
void *  parent_baton,
const char *  utf8_copy_path,
svn_revnum_t  copy_rev,
apr_pool_t *  file_pool,
void **  file_baton 
)

Definition at line 805 of file update.c.

References cb__add_entry(), RETURN_SVNERR, and STOPIF.

Here is the call graph for this function:

svn_error_t* up__apply_textdelta ( void *  file_baton,
const char *  base_checksum,
apr_pool_t *  pool,
svn_txdelta_window_handler_t *  handler,
void **  handler_baton 
)

File handle pools.

This is a bit complicated.

With the file:/// protocol, the source and destination filehandles are not closed by the subversion libraries; with svn+ssh:/// they are.

If we just do a apr_file_close(), we get the error EBADF (bad filehandle), and would accordingly die.

If we don't do it (and let apr_pool_cleanup close it), the close may just fall into the next second, and our (in up__close_file) cached ctime is wrong - so we'd mark this entry as changed.

One solution would be to do a apr_file_close(), and ignore EBADF; this is a bit unclean.

So we go the other route: we simply define a subpool, where we allocate the handles in, and clear that later. That has the additional advantage that the struct estat could possibly be shrinked in the future.

Definition at line 823 of file update.c.

References action, cs__new_manber_filter(), DEBUGP, estat::decoder, estat::entry_status, estat::filehandle_pool, filename, filename_tmp, FS_CHANGED, FS_NEW, FS_REMOVED, global_pool, hlp__encode_filter(), hlp__local2utf8(), hlp__realloc(), actionlist_t::is_compare, actionlist_t::is_import_export, estat::md5, sstat_t::mode, ops__build_path(), ops__dev_to_filedata(), ops__link_to_string(), encoder_t::output_md5, estat::remote_status, RETURN_SVNERR, estat::st, STOPIF, STOPIF_CODE_ERR, estat::stringbuf_tgt, and tmp_len.

Here is the call graph for this function:

svn_error_t* up__change_dir_prop ( void *  dir_baton,
const char *  utf8_name,
const svn_string_t *  value,
apr_pool_t *  pool 
)

Definition at line 750 of file update.c.

References RETURN_SVNERR, STOPIF, up__parse_prop(), estat::url, and url__current_has_precedence().

Here is the call graph for this function:

svn_error_t* up__change_file_prop ( void *  file_baton,
const char *  utf8_name,
const svn_string_t *  value,
apr_pool_t *  pool 
)

Definition at line 978 of file update.c.

References BUG_ON, FS_CHANGED, estat::remote_status, RETURN_SVNERR, STOPIF, up__parse_prop(), estat::url, and url__current_has_precedence().

Here is the call graph for this function:

svn_error_t* up__close_directory ( void *  dir_baton,
apr_pool_t *  pool 
)

Definition at line 767 of file update.c.

References filename, estat::flags, hlp__lstat(), ops__build_path(), RETURN_SVNERR, RF_CHECK, estat::st, st__status, STOPIF, and up__set_meta_data().

Here is the call graph for this function:

svn_error_t* up__close_edit ( void *  edit_baton,
apr_pool_t *  pool 
)

Definition at line 1074 of file update.c.

References UNUSED.

svn_error_t* up__close_file ( void *  file_baton,
const char *  text_checksum,
apr_pool_t *  pool 
)
int up__fetch_decoder ( struct estat sts  ) 

Prefetch update-pipe property.

In case we're updating an existing file, we won't get all properties sent - only changed. So we have to look for existing properties if we need them.

Definition at line 99 of file update.c.

References action, estat::decoder, hlp__strdup(), hsh__close(), actionlist_t::needs_decoder, propval_updatepipe, prp__get(), prp__open_byestat(), and STOPIF.

Referenced by cb___open_file(), and rev__install_file().

Here is the call graph for this function:

Here is the caller graph for this function:

int up__handle_special ( struct estat sts,
char *  path,
char *  data,
apr_pool_t *  pool 
)

Handling non-file non-directory entries.

We know it's a special file, but not more; we have to take the filedata and retrieve the type.

After this call sts->st.mode and sts->new_rev_mode_packed are set to the current value.

Definition at line 634 of file update.c.

References DEBUGP, hlp__utf82local(), estat::local_mode_packed, sstat_t::mode, estat::new_rev_mode_packed, ops__string_to_dev(), PACKED_to_MODE_T, sstat_t::rdev, estat::st, STOPIF, STOPIF_CODE_ERR, and estat::stringbuf_tgt.

Referenced by rev__install_file(), and up__close_file().

Here is the call graph for this function:

Here is the caller graph for this function:

svn_error_t* up__open_root ( void *  edit_baton,
svn_revnum_t  base_revision,
apr_pool_t *dir_pool  UNUSED,
void **  root_baton 
)

Definition at line 697 of file update.c.

References estat::repos_rev.

int up__parse_prop ( struct estat sts,
const char *  utf8_name,
const svn_string_t *  utf8_value,
int *  not_handled,
apr_pool_t *  pool 
)

-.

Parse subversion properties for the given entry.

If not_handled is not NULL, it gets set to 1 if this property is not handled; so the caller knows that he has to to write the property into some other storage if he wants to keep it.

Note:
not_handled does not get set to 0; pre-populating is left to the caller.

Definition at line 145 of file update.c.

References action, BUG_ON, cs__char2md5(), cs__md5tohex_buffered(), DEBUGP, estat::decoder, estat::decoder_is_correct, FS_META_GROUP, FS_META_MTIME, FS_META_OWNER, FS_META_UMODE, FS_PROPERTIES, sstat_t::gid, estat::has_orig_md5, hlp__get_gid(), hlp__get_uid(), hlp__is_special_property_name(), hlp__skip_ws(), hlp__strdup(), hlp__utf82local(), actionlist_t::is_compare, estat::md5, sstat_t::mode, MODE_T_to_PACKED, sstat_t::mtim, estat::name, actionlist_t::needs_decoder, estat::new_rev_mode_packed, ops__build_path(), PACKED_to_MODE_T, propname_group, propname_mtime, propname_origmd5, propname_owner, propname_special, propname_umode, propval_special, propval_updatepipe, estat::remote_status, S_IFANYSPECIAL, S_ISANYSPECIAL, estat::st, STOPIF, TEST_PACKED, sstat_t::uid, wa__warn(), WRN__META_MTIME_INVALID, WRN__META_UMASK_INVALID, and WRN__META_USER_INVALID.

Referenced by cb___store_prop(), prp__set_from_aprhash(), up__change_dir_prop(), and up__change_file_prop().

Here is the call graph for this function:

Here is the caller graph for this function:

int up__rmdir ( struct estat sts,
struct url_t url 
)

Recursively delete a directory structure.

Only non-changed, known entries, so we don't remove changed data.

If an entry does not exist (ENOENT), it is ignored.

Only entries that are registered from URLs given on the command line (with -u) are removed.

If children that belong to other URLs are found we don't remove the directory.

Todo:
conflict

Definition at line 428 of file update.c.

References estat::by_inode, DEBUGP, estat::entry_count, estat::name, ops__build_path(), STOPIF, up__rmdir(), up__unlink(), and estat::url.

Referenced by rev___undo_change(), and up__rmdir().

Here is the call graph for this function:

Here is the caller graph for this function:

int up__set_meta_data ( struct estat sts,
char *  filename 
)

-.

The file has current properties, which we'd like to replace with the saved. But all not-set properties should not be modified.

And all settings should be saved in the waa-area _with the current values_, so that this entry won't be seen as modified.

The easy way: We set what we can, and do a stat() afterwards to capture the current setting.
This has a small race condition: If another process changes the meta-data after setting and before querying, we don't see that it was changed.

How it was done previously: We stored a copy of the wanted things, and copy what we set.
So there's no race-condition, except that we change meta-data a process has just changed.

Since svn 1.3.0 we no longer get all properties on an update, only these that are different to the reported version. That means that most times we'll get only the mtime as changed.

Now, if the file has a unix-mode other than 0600 or an owner which is not equal to the current user, we wouldn't set that because the change mask didn't tell to.
So the file would retain the values of the temporary file, which are 0600 and the current user and group.

The new strategy is: write all values. If there are no properties set for a file, we'll just write the values it currently has - so no problem.
With one exception: the ctime will change, and so we'll believe that it has changed next time. So we fetch the real, current values afterwards.

Meta-data-only changes happen too often, see this case:

  • We're at rev N.
  • We commit an entry and get rev M for this entry. The directory still has N, because there might be other new entries in-between.
  • We want to update to T.
  • We're sending to subversion directory is at N, file is at M,
  • and we get back file has changed, properties ... [svn:entry:committed-rev = M]. Basically we're saying we have file at M, and get back changed, last change happened at M. (Will file a bug report.)

So we get a meta-data change, update the meta-data (currently - will change that soon), and have another ctime (but don't update the entries' meta-data), so find the entry as changed ...

Current solution: read back the entries' meta-data after changing it.

Another thought - if we have different meta-data locally, that's possibly something worth preserving. If the owner has changed in the repository and locally, we'd have to flag a conflict! Furthermore the root entry gets no properties, so it gets set to owner 0.0, mode 0600 ... which is not right either.

Definition at line 536 of file update.c.

References CHOWN_BOOL, CHOWN_FUNC, DEBUGP, DEBUGP_dump_estat(), FS_META_GROUP, FS_META_MTIME, FS_META_OWNER, FS_META_UMODE, sstat_t::gid, hlp__lstat(), sstat_t::mode, sstat_t::mtim, estat::new_rev_mode_packed, ops__build_path(), PACKED_to_MODE_T, estat::remote_status, estat::st, STOPIF, STOPIF_CODE_ERR, sstat_t::uid, UTIMES_BOOL, UTIMES_FUNC, wa__warn(), WRN__CHMOD_EPERM, WRN__CHMOD_OTHER, WRN__CHOWN_EPERM, and WRN__CHOWN_OTHER.

Referenced by rev___handle_dir_mtime(), rev___revert_to_base(), rev___undo_change(), rev__install_file(), rev__merge(), up__close_directory(), and up__close_file().

Here is the call graph for this function:

Here is the caller graph for this function:

svn_error_t* up__set_target_revision ( void *  edit_baton,
svn_revnum_t  rev,
apr_pool_t *  pool 
)

Definition at line 678 of file update.c.

References estat::repos_rev, RETURN_SVNERR, and target_revision.

int up__unlink ( struct estat sts,
char *  filename 
)

-.

Remove a (non-dir) file. Must return errors silently.

Definition at line 382 of file update.c.

References DEBUGP, estat::entry_status, FS_CHANGED, ops__build_path(), STOPIF, STOPIF_CODE_ERR, waa__delete_byext(), WAA__FILE_MD5s_EXT, and WAA__PROP_EXT.

Referenced by rev___undo_change(), and up__rmdir().

Here is the call graph for this function:

Here is the caller graph for this function:

int up__work ( struct estat root,
int  argc,
char *  argv[] 
)

Variable Documentation

char* filename [static]
char * filename_tmp = NULL [static]

Definition at line 90 of file update.c.

Referenced by rev__install_file(), up__apply_textdelta(), and up__close_file().

unsigned tmp_len = 0 [static]

Definition at line 91 of file update.c.

Referenced by up__apply_textdelta().


Generated for fsvs by  doxygen 1.6.1