?? delta.c
字號:
SVN_ERR(authz_root_check(tgt_root, authz_root_path, authz_read_func, authz_read_baton, pool)); SVN_ERR(editor->open_root(edit_baton, rootrev, pool, &root_baton)); SVN_ERR(delta_dirs(&c, root_baton, src_fullpath, tgt_fullpath, "", pool)); } cleanup: /* Make sure we close the root directory if we opened one above. */ if (root_baton) SVN_ERR(editor->close_directory(root_baton, pool)); /* Close the edit. */ SVN_ERR(editor->close_edit(edit_baton, pool)); /* All's well that ends well. */ return SVN_NO_ERROR;}/* Retrieving the base revision from the path/revision hash. */static svn_revnum_t get_path_revision(svn_fs_root_t *root, const char *path, apr_pool_t *pool){ svn_revnum_t revision; svn_error_t *err; /* Easy out -- if ROOT is a revision root, we can use the revision that it's a root of. */ if (svn_fs_is_revision_root(root)) return svn_fs_revision_root_revision(root); /* Else, this must be a transaction root, so ask the filesystem in what revision this path was created. */ if ((err = svn_fs_node_created_rev(&revision, root, path, pool))) { revision = SVN_INVALID_REVNUM; svn_error_clear(err); } /* If we don't get back a valid revision, this path is mutable in the transaction. We should probably examine the node on which it is based, doable by querying for the node-id of the path, and then examining that node-id's predecessor. ### This predecessor determination isn't exposed via the FS public API right now, so for now, we'll just return the SVN_INVALID_REVNUM. */ return revision;}/* proplist_change_fn_t property changing functions. *//* Call the directory property-setting function of C->editor to set the property NAME to given VALUE on the OBJECT passed to this function. */static svn_error_t *change_dir_prop(struct context *c, void *object, const char *name, const svn_string_t *value, apr_pool_t *pool){ return c->editor->change_dir_prop(object, name, value, pool);}/* Call the file property-setting function of C->editor to set the property NAME to given VALUE on the OBJECT passed to this function. */static svn_error_t *change_file_prop(struct context *c, void *object, const char *name, const svn_string_t *value, apr_pool_t *pool){ return c->editor->change_file_prop(object, name, value, pool);}/* Constructing deltas for properties of files and directories. *//* Generate the appropriate property editing calls to turn the properties of SOURCE_PATH into those of TARGET_PATH. If SOURCE_PATH is NULL, this is an add, so assume the target starts with no properties. Pass OBJECT on to the editor function wrapper CHANGE_FN. */static svn_error_t *delta_proplists(struct context *c, const char *source_path, const char *target_path, proplist_change_fn_t *change_fn, void *object, apr_pool_t *pool){ apr_hash_t *s_props = 0; apr_hash_t *t_props = 0; apr_pool_t *subpool; apr_array_header_t *prop_diffs; int i; /* Sanity-check our input. */ assert(target_path); /* Make a subpool for local allocations. */ subpool = svn_pool_create(pool); /* If we're supposed to send entry props for all non-deleted items, here we go! */ if (c->entry_props) { svn_revnum_t committed_rev = SVN_INVALID_REVNUM; svn_string_t *cr_str = NULL; svn_string_t *committed_date = NULL; svn_string_t *last_author = NULL; /* Get the CR and two derivative props. ### check for error returns. */ SVN_ERR(svn_fs_node_created_rev(&committed_rev, c->target_root, target_path, subpool)); if (SVN_IS_VALID_REVNUM(committed_rev)) { svn_fs_t *fs = svn_fs_root_fs(c->target_root); apr_hash_t *r_props; const char *uuid; /* Transmit the committed-rev. */ cr_str = svn_string_createf(subpool, "%ld", committed_rev); SVN_ERR(change_fn(c, object, SVN_PROP_ENTRY_COMMITTED_REV, cr_str, subpool)); SVN_ERR(svn_fs_revision_proplist(&r_props, fs, committed_rev, pool)); /* Transmit the committed-date. */ committed_date = apr_hash_get(r_props, SVN_PROP_REVISION_DATE, APR_HASH_KEY_STRING); if (committed_date || source_path) { SVN_ERR(change_fn(c, object, SVN_PROP_ENTRY_COMMITTED_DATE, committed_date, subpool)); } /* Transmit the last-author. */ last_author = apr_hash_get(r_props, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING); if (last_author || source_path) { SVN_ERR(change_fn(c, object, SVN_PROP_ENTRY_LAST_AUTHOR, last_author, subpool)); } /* Transmit the UUID. */ SVN_ERR(svn_fs_get_uuid(fs, &uuid, subpool)); if (uuid || source_path) { SVN_ERR(change_fn(c, object, SVN_PROP_ENTRY_UUID, svn_string_create(uuid, subpool), subpool)); } } } if (source_path) { svn_boolean_t changed; /* Is this deltification worth our time? */ SVN_ERR(svn_fs_props_changed(&changed, c->target_root, target_path, c->source_root, source_path, subpool)); if (! changed) goto cleanup; /* If so, go ahead and get the source path's properties. */ SVN_ERR(svn_fs_node_proplist(&s_props, c->source_root, source_path, subpool)); } else { s_props = apr_hash_make(subpool); } /* Get the target path's properties */ SVN_ERR(svn_fs_node_proplist(&t_props, c->target_root, target_path, subpool)); /* Now transmit the differences. */ SVN_ERR(svn_prop_diffs(&prop_diffs, t_props, s_props, subpool)); for (i = 0; i < prop_diffs->nelts; i++) { const svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t); SVN_ERR(change_fn(c, object, pc->name, pc->value, subpool)); } cleanup: /* Destroy local subpool. */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Constructing deltas for file contents. *//* Change the contents of FILE_BATON in C->editor, according to the text delta from DELTA_STREAM. Pass BASE_CHECKSUM along to C->editor->apply_textdelta. */static svn_error_t *send_text_delta(struct context *c, void *file_baton, const char *base_checksum, svn_txdelta_stream_t *delta_stream, apr_pool_t *pool){ svn_txdelta_window_handler_t delta_handler; void *delta_handler_baton; /* Get a handler that will apply the delta to the file. */ SVN_ERR(c->editor->apply_textdelta (file_baton, base_checksum, pool, &delta_handler, &delta_handler_baton)); if (c->text_deltas && delta_stream) { /* Deliver the delta stream to the file. */ SVN_ERR(svn_txdelta_send_txstream(delta_stream, delta_handler, delta_handler_baton, pool)); } else { /* The caller doesn't want text delta data. Just send a single NULL window. */ SVN_ERR(delta_handler(NULL, delta_handler_baton)); } return SVN_NO_ERROR;}svn_error_t *svn_repos__compare_files(svn_boolean_t *changed_p, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, const char *path2, apr_pool_t *pool){ svn_filesize_t size1, size2; unsigned char digest1[APR_MD5_DIGESTSIZE], digest2[APR_MD5_DIGESTSIZE]; svn_stream_t *stream1, *stream2; char *buf1, *buf2; apr_size_t len1, len2; /* If the filesystem claims the things haven't changed, then they haven't changed. */ SVN_ERR(svn_fs_contents_changed(changed_p, root1, path1, root2, path2, pool)); if (!*changed_p) return SVN_NO_ERROR; /* From this point on, assume things haven't changed. */ *changed_p = FALSE; /* So, things have changed. But we need to know if the two sets of file contents are actually different. If they have differing sizes, then we know they differ. */ SVN_ERR(svn_fs_file_length(&size1, root1, path1, pool)); SVN_ERR(svn_fs_file_length(&size2, root2, path2, pool)); if (size1 != size2) { *changed_p = TRUE; return SVN_NO_ERROR; } /* Same sizes, huh? Well, if their checksums differ, we know they differ. */ SVN_ERR(svn_fs_file_md5_checksum(digest1, root1, path1, pool)); SVN_ERR(svn_fs_file_md5_checksum(digest2, root2, path2, pool)); if (! svn_md5_digests_match(digest1, digest2)) { *changed_p = TRUE; return SVN_NO_ERROR; } /* Same sizes, same checksums. Chances are reallllly good that they don't differ, but to be absolute sure, we need to compare bytes. */ SVN_ERR(svn_fs_file_contents(&stream1, root1, path1, pool)); SVN_ERR(svn_fs_file_contents(&stream2, root2, path2, pool)); buf1 = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE); buf2 = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE); do { len1 = len2 = SVN__STREAM_CHUNK_SIZE; SVN_ERR(svn_stream_read(stream1, buf1, &len1)); SVN_ERR(svn_stream_read(stream2, buf2, &len2)); if (len1 != len2 || memcmp(buf1, buf2, len1)) { *changed_p = TRUE; return SVN_NO_ERROR; } } while (len1 > 0); return SVN_NO_ERROR;}/* Make the appropriate edits on FILE_BATON to change its contents and properties from those in SOURCE_PATH to those in TARGET_PATH. */static svn_error_t *delta_files(struct context *c, void *file_baton, const char *source_path, const char *target_path, apr_pool_t *pool){ apr_pool_t *subpool; svn_boolean_t changed = TRUE; /* Sanity-check our input. */ assert(target_path); /* Make a subpool for local allocations. */ subpool = svn_pool_create(pool); /* Compare the files' property lists. */ SVN_ERR(delta_proplists(c, source_path, target_path, change_file_prop, file_baton, subpool)); if (source_path) { /* Is this delta calculation worth our time? If we are ignoring ancestry, then our editor implementor isn't concerned by the theoretical differences between "has contents which have not changed with respect to" and "has the same actual contents as". We'll do everything we can to avoid transmitting even an empty text-delta in that case. */ if (c->ignore_ancestry) SVN_ERR(svn_repos__compare_files(&changed,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -