/* Callback for log messages: implements svn_log_entry_receiver_t and accumulates revision metadata into a chronologically ordered list stored in the baton. */ static svn_error_t * fr_log_message_receiver(void *baton, svn_log_entry_t *log_entry, apr_pool_t *pool) { struct fr_log_message_baton *lmb = baton; struct rev *rev; apr_hash_index_t *hi; rev = apr_palloc(lmb->pool, sizeof(*rev)); rev->revision = log_entry->revision; rev->path = lmb->path; rev->next = lmb->eldest; lmb->eldest = rev; /* Duplicate log_entry revprops into rev->props */ rev->props = apr_hash_make(lmb->pool); for (hi = apr_hash_first(pool, log_entry->revprops); hi; hi = apr_hash_next(hi)) { void *val; const void *key; apr_hash_this(hi, &key, NULL, &val); apr_hash_set(rev->props, apr_pstrdup(lmb->pool, key), APR_HASH_KEY_STRING, svn_string_dup(val, lmb->pool)); } return prev_log_path(&lmb->path, &lmb->action, &lmb->copyrev, log_entry->changed_paths2, lmb->path, svn_node_file, log_entry->revision, lmb->pool); }
static svn_error_t * gls_log_receiver(void *baton, svn_log_entry_t *log_entry, apr_pool_t *pool) { struct gls_log_receiver_baton *lrb = baton; const char *current_path = lrb->last_path; const char *prev_path; svn_revnum_t copyfrom_rev; /* If we're done, ignore this invocation. */ if (lrb->done) return SVN_NO_ERROR; /* Figure out at which repository path our object of interest lived in the previous revision, and if its current location is the result of copy since then. */ SVN_ERR(prev_log_path(&prev_path, NULL, ©from_rev, log_entry->changed_paths2, current_path, lrb->kind, log_entry->revision, pool)); /* If we've run off the end of the path's history, we need to report our final segment (and then, we're done). */ if (! prev_path) { lrb->done = TRUE; return maybe_crop_and_send_segment(current_path, lrb->start_rev, log_entry->revision, lrb->range_end, lrb->receiver, lrb->receiver_baton, pool); } /* If there was a copy operation of interest... */ if (SVN_IS_VALID_REVNUM(copyfrom_rev)) { /* ...then report the segment between this revision and the last-reported revision. */ SVN_ERR(maybe_crop_and_send_segment(current_path, lrb->start_rev, log_entry->revision, lrb->range_end, lrb->receiver, lrb->receiver_baton, pool)); lrb->range_end = log_entry->revision - 1; /* And if there was a revision gap, we need to report that, too. */ if (log_entry->revision - copyfrom_rev > 1) { SVN_ERR(maybe_crop_and_send_segment(NULL, lrb->start_rev, copyfrom_rev + 1, lrb->range_end, lrb->receiver, lrb->receiver_baton, pool)); lrb->range_end = copyfrom_rev; } /* Update our state variables. */ lrb->last_path = apr_pstrdup(lrb->pool, prev_path); } return SVN_NO_ERROR; }
/* Callback for log messages: implements svn_log_entry_receiver_t and accumulates revision metadata into a chronologically ordered list stored in the baton. */ static svn_error_t * fr_log_message_receiver(void *baton, svn_log_entry_t *log_entry, apr_pool_t *pool) { struct fr_log_message_baton *lmb = baton; struct rev *rev; rev = apr_palloc(lmb->pool, sizeof(*rev)); rev->revision = log_entry->revision; rev->path = lmb->path; rev->next = lmb->eldest; lmb->eldest = rev; /* Duplicate log_entry revprops into rev->props */ rev->props = svn_prop_hash_dup(log_entry->revprops, lmb->pool); return prev_log_path(&lmb->path, &lmb->action, &lmb->copyrev, log_entry->changed_paths2, lmb->path, svn_node_file, log_entry->revision, lmb->pool); }
/* Implements svn_log_entry_receiver_t; helper for slow_get_locations. As input, takes log_receiver_baton (defined above) and attempts to "fill in" locations in the baton over the course of many iterations. */ static svn_error_t * log_receiver(void *baton, svn_log_entry_t *log_entry, apr_pool_t *pool) { struct log_receiver_baton *lrb = baton; apr_pool_t *hash_pool = apr_hash_pool_get(lrb->locations); const char *current_path = lrb->last_path; const char *prev_path; /* No paths were changed in this revision. Nothing to do. */ if (! log_entry->changed_paths2) return SVN_NO_ERROR; /* If we've run off the end of the path's history, there's nothing to do. (This should never happen with a properly functioning server, since we'd get no more log messages after the one where path was created. But a malfunctioning server shouldn't cause us to trigger an assertion failure.) */ if (! current_path) return SVN_NO_ERROR; /* If we haven't found our peg path yet, and we are now looking at a revision equal to or older than the peg revision, then our "current" path is our peg path. */ if ((! lrb->peg_path) && (log_entry->revision <= lrb->peg_revision)) lrb->peg_path = apr_pstrdup(lrb->pool, current_path); /* Determine the paths for any of the revisions for which we haven't gotten paths already. */ while (lrb->location_revisions->nelts) { svn_revnum_t next = APR_ARRAY_IDX(lrb->location_revisions, lrb->location_revisions->nelts - 1, svn_revnum_t); if (log_entry->revision <= next) { apr_hash_set(lrb->locations, apr_pmemdup(hash_pool, &next, sizeof(next)), sizeof(next), apr_pstrdup(hash_pool, current_path)); apr_array_pop(lrb->location_revisions); } else break; } /* Figure out at which repository path our object of interest lived in the previous revision. */ SVN_ERR(prev_log_path(&prev_path, NULL, NULL, log_entry->changed_paths2, current_path, lrb->kind, log_entry->revision, pool)); /* Squirrel away our "next place to look" path (suffer the strcmp hit to save on allocations). */ if (! prev_path) lrb->last_path = NULL; else if (strcmp(prev_path, current_path) != 0) lrb->last_path = apr_pstrdup(lrb->pool, prev_path); return SVN_NO_ERROR; }