| /* rev_hunt.c --- routines to hunt down particular fs revisions and |
| * their properties. |
| * |
| * ==================================================================== |
| * Copyright (c) 2000-2002 CollabNet. All rights reserved. |
| * |
| * This software is licensed as described in the file COPYING, which |
| * you should have received as part of this distribution. The terms |
| * are also available at http://subversion.tigris.org/license-1.html. |
| * If newer versions of this license are posted there, you may use a |
| * newer version instead, at your option. |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals. For exact contribution history, see the revision |
| * history and logs, available at http://subversion.tigris.org/. |
| * ==================================================================== |
| */ |
| |
| |
| #include <string.h> |
| #include "svn_pools.h" |
| #include "svn_error.h" |
| #include "svn_fs.h" |
| #include "svn_repos.h" |
| #include "svn_string.h" |
| #include "svn_time.h" |
| #include "repos.h" |
| |
| |
| |
| /* Note: this binary search assumes that the datestamp properties on |
| each revision are in chronological order. That is if revision A > |
| revision B, then A's datestamp is younger then B's datestamp. |
| |
| If some moron comes along and sets a bogus datestamp, this routine |
| might not work right. |
| |
| ### todo: you know, we *could* have svn_fs_change_rev_prop() do |
| some semantic checking when it's asked to change special reserved |
| svn: properties. It could prevent such a problem. */ |
| |
| |
| /* helper for svn_repos_dated_revision(). |
| |
| Set *TM to the apr_time_t datestamp on revision REV in FS. */ |
| static svn_error_t * |
| get_time (apr_time_t *tm, |
| svn_fs_t *fs, |
| svn_revnum_t rev, |
| apr_pool_t *pool) |
| { |
| svn_string_t *date_str; |
| |
| SVN_ERR (svn_fs_revision_prop (&date_str, fs, rev, SVN_PROP_REVISION_DATE, |
| pool)); |
| if (! date_str) |
| return svn_error_createf |
| (SVN_ERR_FS_GENERAL, 0, NULL, pool, |
| "failed to find tm on revision %ld", rev); |
| |
| *tm = svn_time_from_nts (date_str->data); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| |
| svn_error_t * |
| svn_repos_dated_revision (svn_revnum_t *revision, |
| svn_repos_t *repos, |
| apr_time_t tm, |
| apr_pool_t *pool) |
| { |
| svn_revnum_t rev_mid, rev_top, rev_bot, rev_latest; |
| apr_time_t this_time; |
| svn_fs_t *fs = repos->fs; |
| |
| /* Initialize top and bottom values of binary search. */ |
| SVN_ERR (svn_fs_youngest_rev (&rev_latest, fs, pool)); |
| rev_bot = 0; |
| rev_top = rev_latest; |
| |
| while (rev_bot <= rev_top) |
| { |
| rev_mid = (rev_top + rev_bot) / 2; |
| SVN_ERR (get_time (&this_time, fs, rev_mid, pool)); |
| |
| if (this_time > tm)/* we've overshot */ |
| { |
| apr_time_t previous_time; |
| |
| if ((rev_mid - 1) < 0) |
| { |
| *revision = 0; |
| break; |
| } |
| |
| /* see if time falls between rev_mid and rev_mid-1: */ |
| SVN_ERR (get_time (&previous_time, fs, rev_mid - 1, pool)); |
| if (previous_time <= tm) |
| { |
| *revision = rev_mid - 1; |
| break; |
| } |
| |
| rev_top = rev_mid - 1; |
| } |
| |
| else if (this_time < tm) /* we've undershot */ |
| { |
| apr_time_t next_time; |
| |
| if ((rev_mid + 1) > rev_latest) |
| { |
| *revision = rev_latest; |
| break; |
| } |
| |
| /* see if time falls between rev_mid and rev_mid+1: */ |
| SVN_ERR (get_time (&next_time, fs, rev_mid + 1, pool)); |
| if (next_time > tm) |
| { |
| *revision = rev_mid + 1; |
| break; |
| } |
| |
| rev_bot = rev_mid + 1; |
| } |
| |
| else |
| { |
| *revision = rev_mid; /* exact match! */ |
| break; |
| } |
| } |
| |
| return SVN_NO_ERROR; |
| } |
| |
| |
| |
| |
| /* Given a ROOT/PATH within some filesystem, return three pieces of |
| information allocated in POOL: |
| |
| - set *COMMITTED_REV to the revision in which the object was |
| last modified. (In fs parlance, this is the revision in which |
| the particular node-rev-id was 'created'.) |
| |
| - set *COMMITTED_DATE to the date of said revision. |
| |
| - set *LAST_AUTHOR to the author of said revision. |
| */ |
| svn_error_t * |
| svn_repos_get_committed_info (svn_revnum_t *committed_rev, |
| svn_string_t **committed_date, |
| svn_string_t **last_author, |
| svn_fs_root_t *root, |
| const svn_string_t *path, |
| apr_pool_t *pool) |
| { |
| svn_fs_t *fs = svn_fs_root_fs (root); |
| |
| /* Get the CR field out of the node's skel. */ |
| SVN_ERR (svn_fs_node_created_rev (committed_rev, root, path->data, pool)); |
| |
| /* Get the date property of this revision. */ |
| SVN_ERR (svn_fs_revision_prop (committed_date, fs, *committed_rev, |
| SVN_PROP_REVISION_DATE, pool)); |
| |
| /* Get the author property of this revision. */ |
| SVN_ERR (svn_fs_revision_prop (last_author, fs, *committed_rev, |
| SVN_PROP_REVISION_AUTHOR, pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| |
| |
| |
| |
| /* |
| * local variables: |
| * eval: (load-file "../../tools/dev/svn-dev.el") |
| * end: |
| */ |