?? delta.c
字號:
c->target_root, target_path, c->source_root, source_path, subpool)); else SVN_ERR(svn_fs_contents_changed(&changed, c->target_root, target_path, c->source_root, source_path, subpool)); } else { /* If there isn't a source path, this is an add, which necessarily has textual mods. */ } /* If there is a change, and the context indicates that we should care about it, then hand it off to a delta stream. */ if (changed) { svn_txdelta_stream_t *delta_stream = NULL; unsigned char source_digest[APR_MD5_DIGESTSIZE]; const char *source_hex_digest = NULL; if (c->text_deltas) { /* Get a delta stream turning an empty file into one having TARGET_PATH's contents. */ SVN_ERR(svn_fs_get_file_delta_stream (&delta_stream, source_path ? c->source_root : NULL, source_path ? source_path : NULL, c->target_root, target_path, subpool)); } if (source_path) { SVN_ERR(svn_fs_file_md5_checksum (source_digest, c->source_root, source_path, subpool)); source_hex_digest = svn_md5_digest_to_cstring(source_digest, subpool); } SVN_ERR(send_text_delta(c, file_baton, source_hex_digest, delta_stream, subpool)); } /* Cleanup. */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Generic directory deltafication routines. *//* Emit a delta to delete the entry named TARGET_ENTRY from DIR_BATON. */static svn_error_t *delete(struct context *c, void *dir_baton, const char *edit_path, apr_pool_t *pool){ return c->editor->delete_entry(edit_path, SVN_INVALID_REVNUM, dir_baton, pool);}/* If authorized, emit a delta to create the entry named TARGET_ENTRY at the location EDIT_PATH. If not authorized, indicate that EDIT_PATH is absent. Pass DIR_BATON through to editor functions that require it. */static svn_error_t *add_file_or_dir(struct context *c, void *dir_baton, const char *target_path, const char *edit_path, svn_node_kind_t tgt_kind, apr_pool_t *pool){ struct context *context = c; svn_boolean_t allowed; /* Sanity-check our input. */ assert(target_path && edit_path); if (c->authz_read_func) { SVN_ERR(c->authz_read_func(&allowed, c->target_root, target_path, c->authz_read_baton, pool)); if (!allowed) return absent_file_or_dir(c, dir_baton, edit_path, tgt_kind, pool); } if (tgt_kind == svn_node_dir) { void *subdir_baton; SVN_ERR(context->editor->add_directory(edit_path, dir_baton, NULL, SVN_INVALID_REVNUM, pool, &subdir_baton)); SVN_ERR(delta_dirs(context, subdir_baton, NULL, target_path, edit_path, pool)); SVN_ERR(context->editor->close_directory(subdir_baton, pool)); } else { void *file_baton; unsigned char digest[APR_MD5_DIGESTSIZE]; SVN_ERR(context->editor->add_file(edit_path, dir_baton, NULL, SVN_INVALID_REVNUM, pool, &file_baton)); SVN_ERR(delta_files(context, file_baton, NULL, target_path, pool)); SVN_ERR(svn_fs_file_md5_checksum(digest, context->target_root, target_path, pool)); SVN_ERR(context->editor->close_file (file_baton, svn_md5_digest_to_cstring(digest, pool), pool)); } return SVN_NO_ERROR;}/* If authorized, emit a delta to modify EDIT_PATH with the changes from SOURCE_PATH to TARGET_PATH. If not authorized, indicate that EDIT_PATH is absent. Pass DIR_BATON through to editor functions that require it. */static svn_error_t *replace_file_or_dir(struct context *c, void *dir_baton, const char *source_path, const char *target_path, const char *edit_path, svn_node_kind_t tgt_kind, apr_pool_t *pool){ svn_revnum_t base_revision = SVN_INVALID_REVNUM; svn_boolean_t allowed; /* Sanity-check our input. */ assert(target_path && source_path && edit_path); if (c->authz_read_func) { SVN_ERR(c->authz_read_func(&allowed, c->target_root, target_path, c->authz_read_baton, pool)); if (!allowed) return absent_file_or_dir(c, dir_baton, edit_path, tgt_kind, pool); } /* Get the base revision for the entry from the hash. */ base_revision = get_path_revision(c->source_root, source_path, pool); if (tgt_kind == svn_node_dir) { void *subdir_baton; SVN_ERR(c->editor->open_directory(edit_path, dir_baton, base_revision, pool, &subdir_baton)); SVN_ERR(delta_dirs(c, subdir_baton, source_path, target_path, edit_path, pool)); SVN_ERR(c->editor->close_directory(subdir_baton, pool)); } else { void *file_baton; unsigned char digest[APR_MD5_DIGESTSIZE]; SVN_ERR(c->editor->open_file(edit_path, dir_baton, base_revision, pool, &file_baton)); SVN_ERR(delta_files(c, file_baton, source_path, target_path, pool)); SVN_ERR(svn_fs_file_md5_checksum(digest, c->target_root, target_path, pool)); SVN_ERR(c->editor->close_file (file_baton, svn_md5_digest_to_cstring(digest, pool), pool)); } return SVN_NO_ERROR;}/* In directory DIR_BATON, indicate that EDIT_PATH (relative to the edit root) is absent by invoking C->editor->absent_directory or C->editor->absent_file (depending on TGT_KIND). */static svn_error_t *absent_file_or_dir(struct context *c, void *dir_baton, const char *edit_path, svn_node_kind_t tgt_kind, apr_pool_t *pool){ assert(edit_path); if (tgt_kind == svn_node_dir) SVN_ERR(c->editor->absent_directory(edit_path, dir_baton, pool)); else SVN_ERR(c->editor->absent_file(edit_path, dir_baton, pool)); return SVN_NO_ERROR;}/* Emit deltas to turn SOURCE_PATH into TARGET_PATH. Assume that DIR_BATON represents the directory we're constructing to the editor in the context C. */static svn_error_t *delta_dirs(struct context *c, void *dir_baton, const char *source_path, const char *target_path, const char *edit_path, apr_pool_t *pool){ apr_hash_t *s_entries = 0, *t_entries = 0; apr_hash_index_t *hi; apr_pool_t *subpool; assert(target_path); /* Compare the property lists. */ SVN_ERR(delta_proplists(c, source_path, target_path, change_dir_prop, dir_baton, pool)); /* Get the list of entries in each of source and target. */ SVN_ERR(svn_fs_dir_entries(&t_entries, c->target_root, target_path, pool)); if (source_path) SVN_ERR(svn_fs_dir_entries(&s_entries, c->source_root, source_path, pool)); /* Make a subpool for local allocations. */ subpool = svn_pool_create(pool); /* Loop over the hash of entries in the target, searching for its partner in the source. If we find the matching partner entry, use editor calls to replace the one in target with a new version if necessary, then remove that entry from the source entries hash. If we can't find a related node in the source, we use editor calls to add the entry as a new item in the target. Having handled all the entries that exist in target, any entries still remaining the source entries hash represent entries that no longer exist in target. Use editor calls to delete those entries from the target tree. */ for (hi = apr_hash_first(pool, t_entries); hi; hi = apr_hash_next(hi)) { const svn_fs_dirent_t *s_entry, *t_entry; const void *key; void *val; apr_ssize_t klen; const char *t_fullpath; const char *e_fullpath; const char *s_fullpath; svn_node_kind_t tgt_kind; /* Clear out our subpool for the next iteration... */ svn_pool_clear(subpool); /* KEY is the entry name in target, VAL the dirent */ apr_hash_this(hi, &key, &klen, &val); t_entry = val; tgt_kind = t_entry->kind; t_fullpath = svn_path_join(target_path, t_entry->name, subpool); e_fullpath = svn_path_join(edit_path, t_entry->name, subpool); /* Can we find something with the same name in the source entries hash? */ if (s_entries && ((s_entry = apr_hash_get(s_entries, key, klen)) != 0)) { int distance; svn_node_kind_t src_kind; s_fullpath = svn_path_join(source_path, t_entry->name, subpool); src_kind = s_entry->kind; if (c->recurse || (src_kind != svn_node_dir)) { /* Use svn_fs_compare_ids() to compare our current source and target ids. 0: means they are the same id, and this is a noop. -1: means they are unrelated, so we have to delete the old one and add the new one. 1: means the nodes are related through ancestry, so go ahead and do the replace directly. */ distance = svn_fs_compare_ids(s_entry->id, t_entry->id); if (distance == 0) { /* no-op */ } else if ((src_kind != tgt_kind) || ((distance == -1) && (! c->ignore_ancestry))) { SVN_ERR(delete(c, dir_baton, e_fullpath, subpool)); SVN_ERR(add_file_or_dir(c, dir_baton, t_fullpath, e_fullpath, tgt_kind, subpool)); } else { SVN_ERR(replace_file_or_dir(c, dir_baton, s_fullpath, t_fullpath, e_fullpath, tgt_kind, subpool)); } } /* Remove the entry from the source_hash. */ apr_hash_set(s_entries, key, APR_HASH_KEY_STRING, NULL); } else { if (c->recurse || (tgt_kind != svn_node_dir)) { SVN_ERR(add_file_or_dir(c, dir_baton, t_fullpath, e_fullpath, tgt_kind, subpool)); } } } /* All that is left in the source entries hash are things that need to be deleted. Delete them. */ if (s_entries) { for (hi = apr_hash_first(pool, s_entries); hi; hi = apr_hash_next(hi)) { const svn_fs_dirent_t *s_entry; const void *key; void *val; apr_ssize_t klen; const char *e_fullpath; svn_node_kind_t src_kind; /* Clear out our subpool for the next iteration... */ svn_pool_clear(subpool); /* KEY is the entry name in source, VAL the dirent */ apr_hash_this(hi, &key, &klen, &val); s_entry = val; src_kind = s_entry->kind; e_fullpath = svn_path_join(edit_path, s_entry->name, subpool); /* Do we actually want to delete the dir if we're non-recursive? */ if (c->recurse || (src_kind != svn_node_dir)) SVN_ERR(delete(c, dir_baton, e_fullpath, subpool)); } } /* Destroy local allocation subpool. */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -