blob: 6c6171fc76b6905885bed1757337d27e01689b2d [file] [log] [blame]
/* svn_repos.h : tools built on top of the filesystem.
*
* ====================================================================
* 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/.
* ====================================================================
*/
/* ==================================================================== */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef SVN_REPOS_H
#define SVN_REPOS_H
#include <apr_pools.h>
#include <apr_hash.h>
#include "svn_fs.h"
#include "svn_delta.h"
#include "svn_types.h"
#include "svn_error.h"
/* ---------------------------------------------------------------*/
/* The repository object. */
typedef struct svn_repos_t svn_repos_t;
/* Opening and creating repositories. */
/* Set *REPOS_P to a repository object for the repository at
PATH. Allocate *REPOS_P in POOL.
Acquires a shared lock on the repository, and attaches a cleanup
function to POOL to remove the lock. If no lock can be acquired,
returns error, with undefined effect on *REPOS_P. If an exclusive
lock is present, this blocks until it's gone. */
svn_error_t *svn_repos_open (svn_repos_t **repos_p,
const char *path,
apr_pool_t *pool);
/* Create a new Subversion repository at PATH, building the necessary
directory structure, creating the Berkeley DB filesystem
environment, and so on. Return the repository object in *REPOS_P,
allocated in POOL. */
svn_error_t *svn_repos_create (svn_repos_t **repos_p,
const char *path,
apr_pool_t *pool);
/* Close the Subversion repository object REPOS. */
svn_error_t *svn_repos_close (svn_repos_t *repos);
/* Destroy the Subversion repository found at PATH. Use POOL for any
necessary allocations. */
svn_error_t *svn_repos_delete (const char *path, apr_pool_t *pool);
/* Return the filesystem associated with repository object REPOS. */
svn_fs_t *svn_repos_fs (svn_repos_t *repos);
/* Repository Paths */
/* Return the top-level repository path allocated in POOL. */
const char *svn_repos_path (svn_repos_t *repos, apr_pool_t *pool);
/* Return the path to REPOS's Berkeley DB environment, allocated in
POOL. */
const char *svn_repos_db_env (svn_repos_t *repos, apr_pool_t *pool);
/* Return the path to REPOS's configuration directory, allocated in
POOL. */
const char *svn_repos_conf_dir (svn_repos_t *repos, apr_pool_t *pool);
/* Return path to REPOS's lock directory or db lockfile, respectively,
allocated in POOL. */
const char *svn_repos_lock_dir (svn_repos_t *repos, apr_pool_t *pool);
const char *svn_repos_db_lockfile (svn_repos_t *repos, apr_pool_t *pool);
/* Return the path to REPOS's hook directory, allocated in POOL. */
const char *svn_repos_hook_dir (svn_repos_t *repos, apr_pool_t *pool);
/* Return the path to REPOS's start-commit hook, pre-commit hook,
post-commit hook, read sentinel, and write sentinel programs,
respectively, allocated in POOL. */
const char *svn_repos_start_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
const char *svn_repos_pre_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
const char *svn_repos_post_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
const char *svn_repos_read_sentinel_hook (svn_repos_t *repos, apr_pool_t *pool);
const char *svn_repos_write_sentinel_hook (svn_repos_t *repos, apr_pool_t *pool);
/* ---------------------------------------------------------------*/
/*** Reporting the state of a working copy, for updates. */
/* Construct and return a REPORT_BATON that will be paired with some
svn_ra_reporter_t table. The table and baton are used to build a
transaction in the system; when the report is finished,
svn_repos_dir_delta is called on the transaction, driving
EDITOR/EDIT_BATON.
Specifically, the report will create a transaction made by
USERNAME, relative to FS_BASE in the filesystem. TARGET is a
single path component, used to limit the scope of the report to a
single entry of FS_BASE, or NULL if all of FS_BASE itself is the
main subject of the report.
TGT_PATH and REVNUM is the fs path/revision pair that is the
"target" of dir_delta. In other words, a tree delta will be
returned that transforms the transaction into TGT_PATH/REVNUM.
TEXT_DELTAS instructs the driver of the EDITOR to enable to disable
the generation of text deltas.
RECURSE instructs the driver of the EDITOR to send a recursive
delta (or not.)
All allocation for the context and collected state will occur in
POOL. */
svn_error_t *
svn_repos_begin_report (void **report_baton,
svn_revnum_t revnum,
const char *username,
svn_repos_t *repos,
const char *fs_base,
const char *target,
const char *tgt_path,
svn_boolean_t text_deltas,
svn_boolean_t recurse,
const svn_delta_edit_fns_t *editor,
void *edit_baton,
apr_pool_t *pool);
/* Given a REPORT_BATON constructed by svn_repos_begin_report(), this
routine will build REVISION:PATH into the current transaction.
This routine is called multiple times to create a transaction that
is a "mirror" of a working copy.
The first call of this in a given report usually passes an empty
PATH; that allows the reporter to set up the correct root revision
(useful when creating a txn, for example). */
svn_error_t *
svn_repos_set_path (void *report_baton,
const char *path,
svn_revnum_t revision);
/* Given a REPORT_BATON constructed by svn_repos_begin_report(), this
routine will remove PATH from the current fs transaction.
(This allows the reporter's driver to describe missing pieces of a
working copy, so that 'svn up' can recreate them.) */
svn_error_t *svn_repos_delete_path (void *report_baton,
const char *path);
/* Make the filesystem compare the transaction to a revision and have
it drive an update editor (using svn_repos_delta_dirs()). Then
abort the transaction. */
svn_error_t *svn_repos_finish_report (void *report_baton);
/* The report-driver is bailing, so abort the fs transaction. */
svn_error_t *svn_repos_abort_report (void *report_baton);
/* ---------------------------------------------------------------*/
/*** The magical dir_delta update routines. */
/* Use the provided EDITOR and EDIT_BATON to describe the changes
necessary for making a given node (and its descendants, if it a
directory) under SRC_ROOT look exactly like TGT_PATH under
TGT_ROOT. SRC_ENTRY is the node to update, and is either NULL or a
single path component. If SRC_ENTRY is NULL, then compute the
difference between the entire tree anchored at SRC_PARENT_DIR under
SRC_ROOT and TGT_PATH under TARGET_ROOT. Else, describe the
changes needed to update only that entry in SRC_PARENT_DIR.
Typically, callers of this function will use a TGT_PATH that is the
concatenation of SRC_PARENT_DIR and SRC_ENTRY.
SRC_ROOT and TGT_ROOT can both be either revision or transaction
roots. If TGT_ROOT is a revision, EDITOR's set_target_revision()
will be called with the TGT_ROOT's revision number, else it will
not be called at all.
SRC_REVS is a hash whose keys are character string paths, and whose
values are pointers to svn_revnum_t's, which describes the base
revisions of the items in the SRC_PARENT tree. This hash need only
contain the base revision for the top of that tree, and then those
paths that have a base revision that differs from that of their
parent directory.
If TEXT_DELTAS is FALSE, only a single NULL txdelta window will be
sent to the window handler returned by EDITOR->apply_textdelta().
USE_COPYFROM_ARGS determines whether or not the editor's add_file
and add_directory functions will be called with copyfrom_*
arguments. That is to say, if a node that needs to be added can be
optimized by simply copying another node that already exists in the
source tree, svn_repos_dir_delta might ask that such a copy take
place.
Before completing successfully, this function calls EDITOR's
close_edit(), so the caller should expect its EDIT_BATON to be
invalid after its use with this function.
Do any allocation necessary for the delta computation in POOL.
This function's maximum memory consumption is at most roughly
proportional to the greatest depth of the tree under TGT_ROOT, not
the total size of the delta.
*/
svn_error_t *
svn_repos_dir_delta (svn_fs_root_t *src_root,
const char *src_parent_dir,
const char *src_entry,
apr_hash_t *src_revs,
svn_fs_root_t *tgt_root,
const char *tgt_path,
const svn_delta_edit_fns_t *editor,
void *edit_baton,
svn_boolean_t text_deltas,
svn_boolean_t recurse,
svn_boolean_t use_copyfrom_args,
apr_pool_t *pool);
/* ---------------------------------------------------------------*/
/*** Finding particular revisions. */
/* Set *REVISION to the revision number in REPOS's filesystem that was
youngest at time TM. */
svn_error_t *
svn_repos_dated_revision (svn_revnum_t *revision,
svn_repos_t *repos,
apr_time_t tm,
apr_pool_t *pool);
/* 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);
/* ### other queries we can do someday --
* fetch the last revision created by <user>
(once usernames become revision properties!)
* fetch the last revision where <path> was modified
*/
/* ---------------------------------------------------------------*/
/*** Retrieving log messages. */
/* Invoke RECEIVER with RECEIVER_BATON on each log message from START
* to END in REPOS's fileystem. START may be greater or less than
* END; this just controls whether the log messages are processed in
* descending or ascending revision number order.
*
* If START or END is SVN_INVALID_REVNUM, it defaults to youngest.
*
* If PATHS is non-null and has one or more elements, then only show
* revisions in which at least one of PATHS was changed (i.e., if
* file, text or props changed; if dir, props changed or an entry was
* added or deleted). Each path is an (svn_stringbuf_t *)
* representing an absolute path in the repository.
*
* ### todo: need to consider whether the above directory behavior is
* most useful, or if we should actually treat _any_ node change in a
* directory as a visible change for purposes of log... i.e., show
* bubble-up. The reason this might be useful is so that running log
* on a directory would give a msg for every change under that dir,
* no matter how far down. See the thread started on the dev list by
* Lars Kellogg-Stedman <lars@larsshack.org> with the subject
* "Single repository, multiple projects?" for more. We may simple
* need to offer a few different semantics for PATHS.
*
* If DISCOVER_CHANGED_PATHS, then each call to RECEIVER passes a
* `const apr_hash_t *' for the receiver's CHANGED_PATHS argument; the
* hash's keys are all the paths committed in that revision.
* Otherwise, each call to RECEIVER passes null for CHANGED_PATHS.
*
* ### NOTE: PATHS and DISCOVER_CHANGED_PATHS are currently ignored,
* see http://subversion.tigris.org/issues/show_bug.cgi?id=562 for
* more information.
*
* If any invocation of RECEIVER returns error, return that error
* immediately and without wrapping it.
*
* See also the documentation for `svn_log_message_receiver_t'.
*
* Use POOL for temporary allocations. */
svn_error_t *
svn_repos_get_logs (svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
svn_boolean_t discover_changed_paths,
svn_log_message_receiver_t receiver,
void *receiver_baton,
apr_pool_t *pool);
/* ---------------------------------------------------------------*/
/*** Hook-sensitive wrappers for libsvn_fs routines. ***/
/* Like svn_fs_commit_txn(), but invoke the REPOS's pre- and
* post-commit hooks around the commit. Use TXN's pool for temporary
* allocations.
*
* CONFLICT_P, NEW_REV, and TXN are as in svn_fs_commit_txn(). */
svn_error_t *svn_repos_fs_commit_txn (const char **conflict_p,
svn_repos_t *repos,
svn_revnum_t *new_rev,
svn_fs_txn_t *txn);
/* Like svn_fs_begin_txn(), but use AUTHOR and LOG_MSG to set the
* corresponding properties on transaction *TXN_P. REPOS is the
* repository object which contains the filesystem. REV, *TXN_P, and
* POOL are as in svn_fs_begin_txn().
*
* Before a txn is created, the repository's start-commit hooks are
* run; if any of them fail, no txn is created, *TXN_P is
* unaffected, and SVN_ERR_REPOS_HOOK_FAILURE is returned.
*
* LOG_MSG may be NULL to indicate the message is not (yet) available.
* The caller will need to attach it to the transaction at a later time. */
svn_error_t *svn_repos_fs_begin_txn_for_commit (svn_fs_txn_t **txn_p,
svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
svn_string_t *log_msg,
apr_pool_t *pool);
/* Like svn_fs_begin_txn(), but use AUTHOR to set the corresponding
* property on transaction *TXN_P. REPOS is the repository object
* which contains the filesystem. REV, *TXN_P, and POOL are as in
* svn_fs_begin_txn().
*
* ### Someday: before a txn is created, some kind of read-hook could
* be called here. */
svn_error_t *svn_repos_fs_begin_txn_for_update (svn_fs_txn_t **txn_p,
svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
apr_pool_t *pool);
/* ---------------------------------------------------------------*/
/*** Data structures and editor things for repository inspection. ***/
/* As it turns out, the svn_repos_dir_delta() interface can be
* extremely useful for examining the repository, or more exactly,
* changes to the repository. svn_repos_dir_delta() allows for
* differences between two trees to be described using an editor.
*
* By using the specific editor found below in conjunction with
* svn_repos_dir_delta(), the description of how to transform one tree
* into another can be used to build an in-memory linked-list tree,
* which each node representing a repository node that was changed as a
* result of having svn_repos_dir_delta() drive that editor.
*/
typedef struct svn_repos_node_t
{
/* Node type (file, dir, etc.) */
enum svn_node_kind kind;
/* How this node entered the node tree: 'A'dd, 'D'elete, 'R'eplace */
char action;
/* Were there any textual mods? (files only) */
svn_boolean_t text_mod;
/* Where there any property mods? */
svn_boolean_t prop_mod;
/* The name of this node as it appears in its parent's entries list */
const char *name;
/* The filesystem revision and path where this was copied from (if any) */
svn_revnum_t copyfrom_rev;
const char *copyfrom_path;
/* Pointer to the next sibling of this node */
struct svn_repos_node_t *sibling;
/* Pointer to the first child of this node */
struct svn_repos_node_t *child;
} svn_repos_node_t;
/* Set *EDITOR and *EDIT_BATON to an editor that, when driven by
svn_repos_dir_delta(), builds an `svn_repos_node_t *' tree
representing the delta from BASE_ROOT to ROOT in REPOS's filesystem.
Invoke svn_repos_node_from_baton() on EDIT_BATON to obtain the root
node afterwards.
Note that the delta includes "bubbled-up" directories; that is,
many of the directory nodes will have no prop_mods.
Allocate the tree and its contents in NODE_POOL; do all other
allocation in POOL. */
svn_error_t *svn_repos_node_editor (const svn_delta_edit_fns_t **editor,
void **edit_baton,
svn_repos_t *repos,
svn_fs_root_t *base_root,
svn_fs_root_t *root,
apr_pool_t *node_pool,
apr_pool_t *pool);
/* Return the root node of the linked-list tree generated by driving
the editor created by svn_repos_node_editor() with
svn_repos_dir_delta(), which is stored in EDIT_BATON. This is only
really useful if used *after* the editor drive is completed. */
svn_repos_node_t *svn_repos_node_from_baton (void *edit_baton);
#endif /* SVN_REPOS_H */
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* ----------------------------------------------------------------
* local variables:
* eval: (load-file "../../tools/dev/svn-dev.el")
* end:
*/