blob: 92011368e70712898ed6b58b501b9be8d70e5967 [file] [log] [blame]
/* 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:
*/