svn_error_t * svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root, apr_pool_t *pool) { apr_hash_t *changed_paths_new_structs; apr_hash_index_t *hi; SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool)); *changed_paths_p = apr_hash_make(pool); for (hi = apr_hash_first(pool, changed_paths_new_structs); hi; hi = apr_hash_next(hi)) { const void *vkey; apr_ssize_t klen; void *vval; svn_fs_path_change2_t *val; svn_fs_path_change_t *change; apr_hash_this(hi, &vkey, &klen, &vval); val = vval; change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = val->node_rev_id; change->change_kind = val->change_kind; change->text_mod = val->text_mod; change->prop_mod = val->prop_mod; apr_hash_set(*changed_paths_p, vkey, klen, change); } return SVN_NO_ERROR; }
static PyObject *fs_root_paths_changed(FileSystemRootObject *self) { apr_pool_t *temp_pool; apr_hash_t *changed_paths; const char *key; apr_ssize_t klen; apr_hash_index_t *idx; PyObject *ret; temp_pool = Pool(NULL); if (temp_pool == NULL) return NULL; #if ONLY_SINCE_SVN(1, 6) RUN_SVN_WITH_POOL(temp_pool, svn_fs_paths_changed2(&changed_paths, self->root, temp_pool)); #else RUN_SVN_WITH_POOL(temp_pool, svn_fs_paths_changed(&changed_paths, self->root, temp_pool)); #endif ret = PyDict_New(); if (ret == NULL) { apr_pool_destroy(temp_pool); return NULL; } for (idx = apr_hash_first(temp_pool, changed_paths); idx != NULL; idx = apr_hash_next(idx)) { PyObject *py_val; #if ONLY_SINCE_SVN(1, 6) svn_fs_path_change2_t *val; #else svn_fs_path_change_t *val; #endif apr_hash_this(idx, (const void **)&key, &klen, (void **)&val); #if ONLY_SINCE_SVN(1, 6) py_val = py_fs_path_change2(val); #else py_val = py_fs_path_change(val); #endif if (py_val == NULL) { apr_pool_destroy(temp_pool); PyObject_Del(ret); return NULL; } if (PyDict_SetItemString(ret, key, py_val) != 0) { apr_pool_destroy(temp_pool); PyObject_Del(ret); Py_DECREF(py_val); return NULL; } Py_DECREF(py_val); } apr_pool_destroy(temp_pool); return ret; }
/* Build the node-origins index any newly added items introduced in REVISION in FS. Set *COUNT to the number of new items found. */ static svn_error_t * index_revision_adds(int *count, svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool) { svn_fs_root_t *root; apr_hash_t *changes; apr_hash_index_t *hi; apr_pool_t *subpool; *count = 0; SVN_ERR(svn_fs_revision_root(&root, fs, revision, pool)); SVN_ERR(svn_fs_paths_changed2(&changes, root, pool)); /* No paths changed in this revision? Nothing to do. */ if (apr_hash_count(changes) == 0) return SVN_NO_ERROR; subpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) { const void *path; void *val; svn_fs_path_change2_t *change; svn_pool_clear(subpool); apr_hash_this(hi, &path, NULL, &val); change = val; if ((change->change_kind == svn_fs_path_change_add) || (change->change_kind == svn_fs_path_change_replace)) { if (! (change->copyfrom_path && SVN_IS_VALID_REVNUM(change->copyfrom_rev))) { svn_revnum_t origin; SVN_ERR(svn_fs_node_origin_rev(&origin, root, path, subpool)); (*count)++; } } } svn_pool_destroy(subpool); return SVN_NO_ERROR; }
static svn_error_t * do_resources(const dav_svn_repos *repos, svn_fs_root_t *root, svn_revnum_t revision, ap_filter_t *output, apr_bucket_brigade *bb, apr_pool_t *pool) { apr_hash_t *changes; apr_hash_t *sent = apr_hash_make(pool); apr_hash_index_t *hi; apr_pool_t *subpool = svn_pool_create(pool); /* Fetch the paths changed in this revision. This will contain everything except otherwise-unchanged parent directories of added and deleted things. Also, note that deleted things don't merit responses of their own -- they are considered modifications to their parent. */ SVN_ERR(svn_fs_paths_changed2(&changes, root, pool)); for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) { const void *key; void *val; const char *path; svn_fs_path_change2_t *change; svn_boolean_t send_self; svn_boolean_t send_parent; svn_pool_clear(subpool); apr_hash_this(hi, &key, NULL, &val); path = key; change = val; /* Figure out who needs to get sent. */ switch (change->change_kind) { case svn_fs_path_change_delete: send_self = FALSE; send_parent = TRUE; break; case svn_fs_path_change_add: case svn_fs_path_change_replace: send_self = TRUE; send_parent = TRUE; break; case svn_fs_path_change_modify: default: send_self = TRUE; send_parent = FALSE; break; } if (send_self) { /* If we haven't already sent this path, send it (and then remember that we sent it). */ if (! apr_hash_get(sent, path, APR_HASH_KEY_STRING)) { svn_node_kind_t kind; SVN_ERR(svn_fs_check_path(&kind, root, path, subpool)); SVN_ERR(send_response(repos, root, path, kind == svn_node_dir, output, bb, subpool)); apr_hash_set(sent, path, APR_HASH_KEY_STRING, (void *)1); } } if (send_parent) { /* If it hasn't already been sent, send the parent directory (and then remember that you sent it). Allocate parent in pool, not subpool, because it stays in the sent hash afterwards. */ const char *parent = svn_path_dirname(path, pool); if (! apr_hash_get(sent, parent, APR_HASH_KEY_STRING)) { SVN_ERR(send_response(repos, root, parent, TRUE, output, bb, subpool)); apr_hash_set(sent, parent, APR_HASH_KEY_STRING, (void *)1); } } } svn_pool_destroy(subpool); return SVN_NO_ERROR; }
/* Inspect the data and/or prop reps of revision REVNUM in FS. Store * reference count tallies in passed hashes (allocated in RESULT_POOL). * * If PROP_REPS or DATA_REPS is NULL, the respective kind of reps are not * tallied. * * Print progress report to STDERR unless QUIET is true. * * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * process_one_revision(svn_fs_t *fs, svn_revnum_t revnum, svn_boolean_t quiet, apr_hash_t *prop_reps, apr_hash_t *data_reps, apr_hash_t *both_reps, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_root_t *rev_root; apr_hash_t *paths_changed; apr_hash_index_t *hi; if (! quiet) SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "processing r%ld\n", revnum)); /* Get the changed paths. */ SVN_ERR(svn_fs_revision_root(&rev_root, fs, revnum, scratch_pool)); SVN_ERR(svn_fs_paths_changed2(&paths_changed, rev_root, scratch_pool)); /* Iterate them. */ /* ### use iterpool? */ for (hi = apr_hash_first(scratch_pool, paths_changed); hi; hi = apr_hash_next(hi)) { const char *path; const svn_fs_path_change2_t *change; const svn_fs_id_t *node_rev_id1, *node_rev_id2; const svn_fs_id_t *the_id; node_revision_t *node_rev; path = svn__apr_hash_index_key(hi); change = svn__apr_hash_index_val(hi); if (! quiet) SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "processing r%ld:%s\n", revnum, path)); if (change->change_kind == svn_fs_path_change_delete) /* Can't ask for reps of PATH at REVNUM if the path no longer exists * at that revision! */ continue; /* Okay, we have two node_rev id's for this change: the txn one and * the revision one. We'll use the latter. */ node_rev_id1 = change->node_rev_id; SVN_ERR(svn_fs_node_id(&node_rev_id2, rev_root, path, scratch_pool)); SVN_ERR_ASSERT(svn_fs_fs__id_txn_id(node_rev_id1) != NULL); SVN_ERR_ASSERT(svn_fs_fs__id_rev(node_rev_id2) != SVN_INVALID_REVNUM); the_id = node_rev_id2; /* Get the node_rev using the chosen node_rev_id. */ SVN_ERR(svn_fs_fs__get_node_revision(&node_rev, fs, the_id, scratch_pool)); /* Maybe record the sha1's. */ SVN_ERR(record(prop_reps, node_rev->prop_rep, result_pool)); SVN_ERR(record(data_reps, node_rev->data_rep, result_pool)); SVN_ERR(record(both_reps, node_rev->prop_rep, result_pool)); SVN_ERR(record(both_reps, node_rev->data_rep, result_pool)); } return SVN_NO_ERROR; }