00001 /**
00002 * @copyright
00003 * ====================================================================
00004 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
00005 *
00006 * This software is licensed as described in the file COPYING, which
00007 * you should have received as part of this distribution. The terms
00008 * are also available at http://subversion.tigris.org/license-1.html.
00009 * If newer versions of this license are posted there, you may use a
00010 * newer version instead, at your option.
00011 *
00012 * This software consists of voluntary contributions made by many
00013 * individuals. For exact contribution history, see the revision
00014 * history and logs, available at http://subversion.tigris.org/.
00015 * ====================================================================
00016 * @endcopyright
00017 *
00018 * @file svn_repos.h
00019 * @brief tools built on top of the filesystem.
00020 */
00021
00022
00023 #ifndef SVN_REPOS_H
00024 #define SVN_REPOS_H
00025
00026 #include <apr_pools.h>
00027 #include <apr_hash.h>
00028 #include "svn_fs.h"
00029 #include "svn_delta.h"
00030 #include "svn_types.h"
00031 #include "svn_error.h"
00032
00033
00034 #ifdef __cplusplus
00035 extern "C" {
00036 #endif /* __cplusplus */
00037
00038 /* ---------------------------------------------------------------*/
00039
00040
00041 /** Callback type for checking authorization on paths produced by (at
00042 * least) svn_repos_dir_delta().
00043 *
00044 * Set @a *allowed to TRUE to indicate that some operation is
00045 * authorized for @a path in @a root, or set it to FALSE to indicate
00046 * unauthorized (presumably according to state stored in @a baton).
00047 *
00048 * Do not assume @a pool has any lifetime beyond this call.
00049 *
00050 * The exact operation being authorized depends on the callback
00051 * implementation. For read authorization, for example, the caller
00052 * would implement an instance that does read checking, and pass it as
00053 * a parameter named [perhaps] 'authz_read_func'. The receiver of
00054 * that parameter might also take another parameter named
00055 * 'authz_write_func', which although sharing this type, would be a
00056 * different implementation.
00057 *
00058 * Note: If someday we want more sophisticated authorization states
00059 * than just yes/no, @a allowed can become an enum type.
00060 */
00061 typedef svn_error_t *(*svn_repos_authz_func_t) (svn_boolean_t *allowed,
00062 svn_fs_root_t *root,
00063 const char *path,
00064 void *baton,
00065 apr_pool_t *pool);
00066
00067
00068
00069 /** The repository object. */
00070 typedef struct svn_repos_t svn_repos_t;
00071
00072 /* Opening and creating repositories. */
00073
00074
00075 /** Find the root path of the repository that contains @a path.
00076 *
00077 * If a repository was found, the path to the root of the repository
00078 * is returned, else @c NULL. The pointer to the returned path may be
00079 * equal to @a path argument.
00080 */
00081 const char *svn_repos_find_root_path (const char *path,
00082 apr_pool_t *pool);
00083
00084 /** Set @a *repos_p to a repository object for the repository at @a path.
00085 *
00086 * Allocate @a *repos_p in @a pool.
00087 *
00088 * Acquires a shared lock on the repository, and attaches a cleanup
00089 * function to @a pool to remove the lock. If no lock can be acquired,
00090 * returns error, with undefined effect on @a *repos_p. If an exclusive
00091 * lock is present, this blocks until it's gone.
00092 */
00093 svn_error_t *svn_repos_open (svn_repos_t **repos_p,
00094 const char *path,
00095 apr_pool_t *pool);
00096
00097 /** Create a new Subversion repository at @a path, building the necessary
00098 * directory structure, creating the Berkeley DB filesystem environment,
00099 * and so on. Return the (open) repository object in @a *repos_p,
00100 * allocated in @a pool.
00101 *
00102 * @a config is a client configuration hash of @c svn_config_t * items
00103 * keyed on config category names, and may be NULL.
00104 *
00105 * @a fs_config is passed to the filesystem, and may be NULL.
00106 *
00107 * @a unused_1 and @a unused_2 are not used and should be NULL.
00108 */
00109 svn_error_t *svn_repos_create (svn_repos_t **repos_p,
00110 const char *path,
00111 const char *unused_1,
00112 const char *unused_2,
00113 apr_hash_t *config,
00114 apr_hash_t *fs_config,
00115 apr_pool_t *pool);
00116
00117 /** Destroy the Subversion repository found at @a path, using @a pool for any
00118 * necessary allocations.
00119 */
00120 svn_error_t *svn_repos_delete (const char *path, apr_pool_t *pool);
00121
00122 /** Return the filesystem associated with repository object @a repos. */
00123 svn_fs_t *svn_repos_fs (svn_repos_t *repos);
00124
00125
00126 /** Make a hot copy of the Subversion repository found at @a src_path
00127 * to @a dst_path.
00128 *
00129 * @copydoc svn_fs_hotcopy_berkeley()
00130 */
00131 svn_error_t * svn_repos_hotcopy (const char *src_path,
00132 const char *dst_path,
00133 svn_boolean_t clean_logs,
00134 apr_pool_t *pool);
00135
00136 /** Run database recovery procedures on the repository at @a path,
00137 * returning the database to a consistent state. Use @a pool for all
00138 * allocation.
00139 *
00140 * Acquires an @a exclusive lock on the repository, recovers the
00141 * database, and releases the lock. If an exclusive lock can't be
00142 * acquired, returns error.
00143 */
00144 svn_error_t *svn_repos_recover (const char *path, apr_pool_t *pool);
00145
00146
00147 /** This function is a wrapper around svn_fs_berkeley_logfiles(),
00148 * returning log file paths relative to the root of the repository.
00149 *
00150 * @copydoc svn_fs_berkeley_logfiles()
00151 */
00152 svn_error_t *svn_repos_db_logfiles (apr_array_header_t **logfiles,
00153 const char *path,
00154 svn_boolean_t only_unused,
00155 apr_pool_t *pool);
00156
00157
00158
00159 /* Repository Paths */
00160
00161 /** Return the top-level repository path allocated in @a pool. */
00162 const char *svn_repos_path (svn_repos_t *repos, apr_pool_t *pool);
00163
00164 /** Return the path to @a repos's Berkeley DB environment, allocated in
00165 * @a pool.
00166 */
00167 const char *svn_repos_db_env (svn_repos_t *repos, apr_pool_t *pool);
00168
00169 /** Return path to @a repos's config directory, allocated in @a pool. */
00170 const char *svn_repos_conf_dir (svn_repos_t *repos, apr_pool_t *pool);
00171
00172 /** Return path to @a repos's svnserve.conf, allocated in @a pool. */
00173 const char *svn_repos_svnserve_conf (svn_repos_t *repos, apr_pool_t *pool);
00174
00175 /** Return path to @a repos's lock directory, allocated in @a pool. */
00176 const char *svn_repos_lock_dir (svn_repos_t *repos, apr_pool_t *pool);
00177
00178 /** Return path to @a repos's db lockfile, allocated in @a pool. */
00179 const char *svn_repos_db_lockfile (svn_repos_t *repos, apr_pool_t *pool);
00180
00181 /** Return path to @a repos's db logs lockfile, allocated in @a pool. */
00182 const char *svn_repos_db_logs_lockfile (svn_repos_t *repos, apr_pool_t *pool);
00183
00184 /** Return the path to @a repos's hook directory, allocated in @a pool. */
00185 const char *svn_repos_hook_dir (svn_repos_t *repos, apr_pool_t *pool);
00186
00187 /** Return the path to @a repos's start-commit hook, allocated in @a pool. */
00188 const char *svn_repos_start_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
00189
00190 /** Return the path to @a repos's pre-commit hook, allocated in @a pool. */
00191 const char *svn_repos_pre_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
00192
00193 /** Return the path to @a repos's post-commit hook, allocated in @a pool. */
00194 const char *svn_repos_post_commit_hook (svn_repos_t *repos, apr_pool_t *pool);
00195
00196 /** Return the path to @a repos's pre-revprop-change hook, allocated in
00197 * @a pool.
00198 */
00199 const char *svn_repos_pre_revprop_change_hook (svn_repos_t *repos,
00200 apr_pool_t *pool);
00201
00202 /** Return the path to @a repos's post-revprop-change hook, allocated in
00203 * @a pool.
00204 */
00205 const char *svn_repos_post_revprop_change_hook (svn_repos_t *repos,
00206 apr_pool_t *pool);
00207
00208
00209
00210 /* ---------------------------------------------------------------*/
00211
00212 /* Reporting the state of a working copy, for updates. */
00213
00214
00215 /** Construct and return a @a report_baton that will be paired with some
00216 * @c svn_ra_reporter_t table. The table and baton are used to build a
00217 * transaction in the system; when the report is finished,
00218 * @c svn_repos_dir_delta is called on the transaction, driving
00219 * @a editor/@a edit_baton.
00220 *
00221 * Specifically, the report will create a transaction made by @a username,
00222 * relative to @a fs_base in the filesystem. @a target is a single path
00223 * component, used to limit the scope of the report to a single entry of
00224 * @a fs_base, or "" if all of @a fs_base itself is the main subject of
00225 * the report.
00226 *
00227 * @a tgt_path and @a revnum is the fs path/revision pair that is the
00228 * "target" of @c dir_delta. In other words, a tree delta will be
00229 * returned that transforms the transaction into @a tgt_path/@a revnum.
00230 * @a tgt_path may (indeed, should) be @c NULL when the source and target
00231 * paths of the report are the same. That is, @a tgt_path should *only*
00232 * be specified when specifying that the resultant editor drive be one
00233 * that transforms the reported hierarchy into a pristine tree of
00234 * @a tgt_path at revision @a revnum. Else, a @c NULL value for @a tgt_path
00235 * will indicate that the editor should be driven in such a way as to
00236 * transform the reported hierarchy to revision @a revnum, preserving the
00237 * reported hierarchy.
00238 *
00239 * @a text_deltas instructs the driver of the @a editor to enable
00240 * the generation of text deltas.
00241 *
00242 * @a recurse instructs the driver of the @a editor to send a recursive
00243 * delta (or not.)
00244 *
00245 * @a ignore_ancestry instructs the driver to ignore node ancestry
00246 * when determining how to transmit differences.
00247 *
00248 * The @a authz_read_func and @a authz_read_baton are passed along to
00249 * @c svn_repos_dir_delta(); see that function for how they are used.
00250 *
00251 * All allocation for the context and collected state will occur in
00252 * @a pool.
00253 */
00254 svn_error_t *
00255 svn_repos_begin_report (void **report_baton,
00256 svn_revnum_t revnum,
00257 const char *username,
00258 svn_repos_t *repos,
00259 const char *fs_base,
00260 const char *target,
00261 const char *tgt_path,
00262 svn_boolean_t text_deltas,
00263 svn_boolean_t recurse,
00264 svn_boolean_t ignore_ancestry,
00265 const svn_delta_editor_t *editor,
00266 void *edit_baton,
00267 svn_repos_authz_func_t authz_read_func,
00268 void *authz_read_baton,
00269 apr_pool_t *pool);
00270
00271
00272 /** Given a @a report_baton constructed by @c svn_repos_begin_report(), this
00273 * routine will build @a revision:@a path into the current transaction.
00274 * This routine is called multiple times to create a transaction that
00275 * is a "mirror" of a working copy.
00276 *
00277 * The first call of this in a given report usually passes an empty
00278 * @a path; that allows the reporter to set up the correct root revision
00279 * (useful when creating a txn, for example).
00280 *
00281 * If @a start_empty is set and @a path is a directory, then remove
00282 * all children and props of the freshly-linked directory. This is
00283 * for 'low confidence' client reporting.
00284 *
00285 * All temporary allocations are done in @a pool.
00286 */
00287 svn_error_t *svn_repos_set_path (void *report_baton,
00288 const char *path,
00289 svn_revnum_t revision,
00290 svn_boolean_t start_empty,
00291 apr_pool_t *pool);
00292
00293
00294 /** Given a @a report_baton constructed by @c svn_repos_begin_report(),
00295 * this routine will build @a revision:@a link_path into the current
00296 * transaction at @a path. Note that while @a path is relative to the
00297 * anchor/target used in the creation of the @a report_baton, @a link_path
00298 * is an absolute filesystem path!
00299 *
00300 * If @a start_empty is set and @a path is a directory, then remove
00301 * all children and props of the freshly-linked directory. This is
00302 * for 'low confidence' client reporting.
00303 *
00304 * All temporary allocations are done in @a pool.
00305 */
00306 svn_error_t *svn_repos_link_path (void *report_baton,
00307 const char *path,
00308 const char *link_path,
00309 svn_revnum_t revision,
00310 svn_boolean_t start_empty,
00311 apr_pool_t *pool);
00312
00313 /** Given a @a report_baton constructed by @c svn_repos_begin_report(),
00314 * this routine will remove @a path from the current fs transaction.
00315 *
00316 * (This allows the reporter's driver to describe missing pieces of a
00317 * working copy, so that 'svn up' can recreate them.)
00318 *
00319 * All temporary allocations are done in @a pool.
00320 */
00321 svn_error_t *svn_repos_delete_path (void *report_baton,
00322 const char *path,
00323 apr_pool_t *pool);
00324
00325 /** Make the filesystem compare the transaction to a revision and have
00326 * it drive an update editor (using @c svn_repos_delta_dirs()), then
00327 * abort the transaction. If an error occurs during the driving of
00328 * the editor, we do NOT abort the edit; that responsibility belongs
00329 * to the caller, if it happens at all. The fs transaction will be
00330 * aborted even if the editor drive fails, so the caller does not need
00331 * to clean up.
00332 */
00333 svn_error_t *svn_repos_finish_report (void *report_baton,
00334 apr_pool_t *pool);
00335
00336
00337 /** The report-driver is bailing, so abort the fs transaction. This
00338 * function can be called anytime before @c svn_repos_finish_report() is
00339 * called. No other reporting functions should be called after calling
00340 * this function.
00341 */
00342 svn_error_t *svn_repos_abort_report (void *report_baton,
00343 apr_pool_t *pool);
00344
00345
00346 /* ---------------------------------------------------------------*/
00347
00348 /* The magical dir_delta update routines. */
00349
00350 /** Use the provided @a editor and @a edit_baton to describe the changes
00351 * necessary for making a given node (and its descendants, if it is a
00352 * directory) under @a src_root look exactly like @a tgt_path under
00353 * @a tgt_root. @a src_entry is the node to update. If @a src_entry
00354 * is empty, then compute the difference between the entire tree
00355 * anchored at @a src_parent_dir under @a src_root and @a tgt_path
00356 * under @a target_root. Else, describe the changes needed to update
00357 * only that entry in @a src_parent_dir. Typically, callers of this
00358 * function will use a @a tgt_path that is the concatenation of @a
00359 * src_parent_dir and @a src_entry.
00360 *
00361 * @a src_root and @a tgt_root can both be either revision or transaction
00362 * roots. If @a tgt_root is a revision, @a editor's @c set_target_revision()
00363 * will be called with the @a tgt_root's revision number, else it will
00364 * not be called at all.
00365 *
00366 * If @a authz_read_func is non-null, invoke it before any call to
00367 *
00368 * @a editor->open_root
00369 * @a editor->add_directory
00370 * @a editor->open_directory
00371 * @a editor->add_file
00372 * @a editor->open_file
00373 *
00374 * passing @a tgt_root, the same path that would be passed to the
00375 * editor function in question, and @a authz_read_baton. If the
00376 * @a *allowed parameter comes back TRUE, then proceed with the planned
00377 * editor call; else if FALSE, then invoke @a editor->absent_file or
00378 * @a editor->absent_directory as appropriate, except if the planned
00379 * editor call was open_root, throw SVN_ERR_AUTHZ_ROOT_UNREADABLE.
00380 *
00381 * If @a text_deltas is @c FALSE, send a single @c NULL txdelta window to
00382 * the window handler returned by @a editor->apply_textdelta().
00383 *
00384 * If @a entry_props is @c TRUE, accompany each opened/added entry with
00385 * propchange editor calls that relay special "entry props" (this
00386 * is typically used only for working copy updates).
00387 *
00388 * @a ignore_ancestry instructs the function to ignore node ancestry
00389 * when determining how to transmit differences.
00390 *
00391 * Before completing successfully, this function calls @a editor's
00392 * @c close_edit(), so the caller should expect its @a edit_baton to be
00393 * invalid after its use with this function.
00394 *
00395 * Do any allocation necessary for the delta computation in @a pool.
00396 * This function's maximum memory consumption is at most roughly
00397 * proportional to the greatest depth of the tree under @a tgt_root, not
00398 * the total size of the delta.
00399 */
00400 svn_error_t *
00401 svn_repos_dir_delta (svn_fs_root_t *src_root,
00402 const char *src_parent_dir,
00403 const char *src_entry,
00404 svn_fs_root_t *tgt_root,
00405 const char *tgt_path,
00406 const svn_delta_editor_t *editor,
00407 void *edit_baton,
00408 svn_repos_authz_func_t authz_read_func,
00409 void *authz_read_baton,
00410 svn_boolean_t text_deltas,
00411 svn_boolean_t recurse,
00412 svn_boolean_t entry_props,
00413 svn_boolean_t ignore_ancestry,
00414 apr_pool_t *pool);
00415
00416 /** Use the provided @a editor and @a edit_baton to describe the
00417 * skeletal changes made in a particular filesystem @a root
00418 * (revision or transaction).
00419 *
00420 * The @a editor passed to this function should be aware of the fact
00421 * that calls to its change_dir_prop(), change_file_prop(), and
00422 * apply_textdelta() functions will not contain meaningful data, and
00423 * merely serve as indications that properties or textual contents
00424 * were changed.
00425 *
00426 * NOTE: this editor driver passes SVN_INVALID_REVNUM for all
00427 * revision parameters in the editor interface except the copyfrom
00428 * parameter of the add_file() and add_directory() editor functions.
00429 *
00430 * ### TODO: This ought to take an svn_repos_authz_func_t too.
00431 * The only reason it doesn't yet is the difficulty of implementing
00432 * that correctly, plus lack of strong present need -- it's currently
00433 * only used in creating a DAV MERGE response, in 'svnadmin dump', and
00434 * in svnlook.
00435 */
00436 svn_error_t *
00437 svn_repos_replay (svn_fs_root_t *root,
00438 const svn_delta_editor_t *editor,
00439 void *edit_baton,
00440 apr_pool_t *pool);
00441
00442
00443 /* ---------------------------------------------------------------*/
00444
00445 /* Making commits. */
00446
00447 /** Return an @a editor and @a edit_baton to commit changes to @a session->fs,
00448 * beginning at location 'rev:@a base_path', where "rev" is the argument
00449 * given to @c open_root(). Store @a user as the author of the commit and
00450 * @a log_msg as the commit message.
00451 *
00452 * @a repos is a previously opened repository. @a repos_url is the decoded
00453 * URL to the base of the repository, and is used to check copyfrom paths.
00454 *
00455 * Calling @a (*editor)->close_edit completes the commit. Before
00456 * @c close_edit returns, but after the commit has succeeded, it will
00457 * invoke @a callback with the new revision number, the commit date (as a
00458 * <tt>const char *</tt>), commit author (as a <tt>const char *</tt>), and
00459 * @a callback_baton as arguments. If @a callback returns an error, that
00460 * error will be returned from @c close_edit, otherwise if there was a
00461 * post-commit hook failure, then that error will be returned and will
00462 * have code SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED.
00463 */
00464 svn_error_t *svn_repos_get_commit_editor (const svn_delta_editor_t **editor,
00465 void **edit_baton,
00466 svn_repos_t *repos,
00467 const char *repos_url,
00468 const char *base_path,
00469 const char *user,
00470 const char *log_msg,
00471 svn_commit_callback_t callback,
00472 void *callback_baton,
00473 apr_pool_t *pool);
00474
00475
00476 /* ---------------------------------------------------------------*/
00477
00478 /* Finding particular revisions. */
00479
00480 /** Set @a *revision to the revision number in @a repos's filesystem that was
00481 * youngest at time @a tm.
00482 */
00483 svn_error_t *
00484 svn_repos_dated_revision (svn_revnum_t *revision,
00485 svn_repos_t *repos,
00486 apr_time_t tm,
00487 apr_pool_t *pool);
00488
00489
00490 /** Given a @a root/@a path within some filesystem, return three pieces of
00491 * information allocated in @a pool:
00492 *
00493 * - set @a *committed_rev to the revision in which the object was
00494 * last modified. (In fs parlance, this is the revision in which
00495 * the particular node-rev-id was 'created'.)
00496 *
00497 * - set @a *committed_date to the date of said revision, or @c NULL
00498 * if not available.
00499 *
00500 * - set @a *last_author to the author of said revision, or @c NULL
00501 * if not available.
00502 */
00503 svn_error_t *
00504 svn_repos_get_committed_info (svn_revnum_t *committed_rev,
00505 const char **committed_date,
00506 const char **last_author,
00507 svn_fs_root_t *root,
00508 const char *path,
00509 apr_pool_t *pool);
00510
00511
00512 /** Callback type for use with svn_repos_history(). @a path and @a
00513 * revision represent interesting history locations in the lifetime
00514 * of the path passed to svn_repos_history(). @a baton is the same
00515 * baton given to svn_repos_history(). @a pool is provided for the
00516 * convenience of the implementor, who should not expect it to live
00517 * longer than a single callback call.
00518 */
00519 typedef svn_error_t *(*svn_repos_history_func_t) (void *baton,
00520 const char *path,
00521 svn_revnum_t revision,
00522 apr_pool_t *pool);
00523
00524 /** Call @a history_func (with @a history_baton) for each interesting
00525 * history location in the lifetime of @a path in @a fs, from the
00526 * youngest of @a end and @ start to the oldest. Only cross
00527 * filesystem copy history if @a cross_copies is @c TRUE. And do all
00528 * of this in @a pool.
00529 */
00530 svn_error_t *
00531 svn_repos_history (svn_fs_t *fs,
00532 const char *path,
00533 svn_repos_history_func_t history_func,
00534 void *history_baton,
00535 svn_revnum_t start,
00536 svn_revnum_t end,
00537 svn_boolean_t cross_copies,
00538 apr_pool_t *pool);
00539
00540 /* ### other queries we can do someday --
00541
00542 * fetch the last revision created by <user>
00543 (once usernames become revision properties!)
00544 * fetch the last revision where <path> was modified
00545
00546 */
00547
00548
00549
00550 /* ---------------------------------------------------------------*/
00551
00552 /* Retrieving log messages. */
00553
00554
00555 /** Invoke @a receiver with @a receiver_baton on each log message from
00556 * @a start to @a end in @a repos's filesystem. @a start may be greater
00557 * or less than @a end; this just controls whether the log messages are
00558 * processed in descending or ascending revision number order.
00559 *
00560 * If @a start or @a end is @c SVN_INVALID_REVNUM, it defaults to youngest.
00561 *
00562 * If @a paths is non-null and has one or more elements, then only show
00563 * revisions in which at least one of @a paths was changed (i.e., if
00564 * file, text or props changed; if dir, props changed or an entry was
00565 * added or deleted). Each path is an <tt>const char *</tt> representing
00566 * an absolute path in the repository.
00567 *
00568 * ### todo: need to consider whether the above directory behavior is
00569 * most useful, or if we should actually treat _any_ node change in a
00570 * directory as a visible change for purposes of log... i.e., show
00571 * bubble-up. The reason this might be useful is so that running log
00572 * on a directory would give a msg for every change under that dir,
00573 * no matter how far down. See the thread started on the dev list by
00574 * Lars Kellogg-Stedman <lars@larsshack.org> with the subject
00575 * "Single repository, multiple projects?" for more. We may simple
00576 * need to offer a few different semantics for @a paths.
00577 *
00578 * If @a discover_changed_paths, then each call to @a receiver passes a
00579 * <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths
00580 * argument; the hash's keys are all the paths committed in that revision.
00581 * Otherwise, each call to @a receiver passes null for @a changed_paths.
00582 *
00583 * If @a strict_node_history is set, copy history (if any exists) will
00584 * not be traversed while harvesting revision logs for each path.
00585 *
00586 * If any invocation of @a receiver returns error, return that error
00587 * immediately and without wrapping it.
00588 *
00589 * If @a start or @a end is a non-existent revision, return the error
00590 * @c SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a receiver.
00591 *
00592 * See also the documentation for @c svn_log_message_receiver_t.
00593 *
00594 * Use @a pool for temporary allocations.
00595 */
00596 svn_error_t *
00597 svn_repos_get_logs (svn_repos_t *repos,
00598 const apr_array_header_t *paths,
00599 svn_revnum_t start,
00600 svn_revnum_t end,
00601 svn_boolean_t discover_changed_paths,
00602 svn_boolean_t strict_node_history,
00603 svn_log_message_receiver_t receiver,
00604 void *receiver_baton,
00605 apr_pool_t *pool);
00606
00607
00608 /* ---------------------------------------------------------------*/
00609
00610 /**
00611 * @defgroup svn_repos_hook_wrappers Hook-sensitive wrappers for libsvn_fs
00612 * routines.
00613 * @{
00614 */
00615
00616 /** Like @c svn_fs_commit_txn(), but invoke the @a repos's pre- and
00617 * post-commit hooks around the commit. Use @a pool for any necessary
00618 * allocations.
00619 *
00620 * If the pre-commit hook or svn_fs_commit_txn() fails, throw the
00621 * original error to caller. If an error occurs when running the
00622 * post-commit hook, return the original error wrapped with
00623 * SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED. If the caller sees this
00624 * error, it knows that the commit succeeded anyway.
00625 *
00626 * @a conflict_p, @a new_rev, and @a txn are as in @c svn_fs_commit_txn().
00627 */
00628 svn_error_t *svn_repos_fs_commit_txn (const char **conflict_p,
00629 svn_repos_t *repos,
00630 svn_revnum_t *new_rev,
00631 svn_fs_txn_t *txn,
00632 apr_pool_t *pool);
00633
00634 /** Like @c svn_fs_begin_txn(), but use @a author and @a log_msg to set the
00635 * corresponding properties on transaction @a *txn_p. @a repos is the
00636 * repository object which contains the filesystem. @a rev, @a *txn_p, and
00637 * @a pool are as in @c svn_fs_begin_txn().
00638 *
00639 * Before a txn is created, the repository's start-commit hooks are
00640 * run; if any of them fail, no txn is created, @a *txn_p is unaffected,
00641 * and @c SVN_ERR_REPOS_HOOK_FAILURE is returned.
00642 *
00643 * @a log_msg may be @c NULL to indicate the message is not (yet) available.
00644 * The caller will need to attach it to the transaction at a later time.
00645 */
00646 svn_error_t *svn_repos_fs_begin_txn_for_commit (svn_fs_txn_t **txn_p,
00647 svn_repos_t *repos,
00648 svn_revnum_t rev,
00649 const char *author,
00650 const char *log_msg,
00651 apr_pool_t *pool);
00652
00653
00654 /** Like @c svn_fs_begin_txn(), but use @a author to set the corresponding
00655 * property on transaction @a *txn_p. @a repos is the repository object
00656 * which contains the filesystem. @a rev, @a *txn_p, and @a pool are as in
00657 * @c svn_fs_begin_txn().
00658 *
00659 * ### Someday: before a txn is created, some kind of read-hook could
00660 * be called here.
00661 */
00662 svn_error_t *svn_repos_fs_begin_txn_for_update (svn_fs_txn_t **txn_p,
00663 svn_repos_t *repos,
00664 svn_revnum_t rev,
00665 const char *author,
00666 apr_pool_t *pool);
00667
00668
00669 /** Like @c svn_fs_change_rev_prop(), but invoke the @a repos's pre- and
00670 * post-revprop-change hooks around the change. Use @a pool for
00671 * temporary allocations.
00672 *
00673 * @a rev is the revision whose property to change, @a name is the
00674 * name of the property, and @a new_value is the new value of the
00675 * property. @a author is the authenticated username of the person
00676 * changing the property value, or null if not available.
00677 */
00678 svn_error_t *svn_repos_fs_change_rev_prop (svn_repos_t *repos,
00679 svn_revnum_t rev,
00680 const char *author,
00681 const char *name,
00682 const svn_string_t *new_value,
00683 apr_pool_t *pool);
00684
00685
00686 /* ---------------------------------------------------------------*/
00687
00688 /* Prop-changing wrappers for libsvn_fs routines. */
00689
00690 /* NOTE: svn_repos_fs_change_rev_prop() also exists, but is located
00691 above with the hook-related functions. */
00692
00693
00694 /** Validating wrapper for @c svn_fs_change_node_prop() (which see for
00695 * argument descriptions).
00696 */
00697 svn_error_t *svn_repos_fs_change_node_prop (svn_fs_root_t *root,
00698 const char *path,
00699 const char *name,
00700 const svn_string_t *value,
00701 apr_pool_t *pool);
00702
00703 /** Validating wrapper for @c svn_fs_change_txn_prop() (which see for
00704 * argument descriptions).
00705 */
00706 svn_error_t *svn_repos_fs_change_txn_prop (svn_fs_txn_t *txn,
00707 const char *name,
00708 const svn_string_t *value,
00709 apr_pool_t *pool);
00710
00711 /** @} */
00712
00713 /* ---------------------------------------------------------------*/
00714
00715 /**
00716 * @defgroup svn_repos_inspection Data structures and editor things for
00717 * repository inspection.
00718 * @{
00719 *
00720 * As it turns out, the @c svn_repos_dir_delta() interface can be
00721 * extremely useful for examining the repository, or more exactly,
00722 * changes to the repository. @c svn_repos_dir_delta() allows for
00723 * differences between two trees to be described using an editor.
00724 *
00725 * By using the specific editor found below in conjunction with
00726 * @c svn_repos_dir_delta(), the description of how to transform one tree
00727 * into another can be used to build an in-memory linked-list tree,
00728 * which each node representing a repository node that was changed as a
00729 * result of having @c svn_repos_dir_delta() drive that editor.
00730 */
00731
00732 /** A node in the repository. */
00733 typedef struct svn_repos_node_t
00734 {
00735 /** Node type (file, dir, etc.) */
00736 svn_node_kind_t kind;
00737
00738 /** How this node entered the node tree: 'A'dd, 'D'elete, 'R'eplace */
00739 char action;
00740
00741 /** Were there any textual mods? (files only) */
00742 svn_boolean_t text_mod;
00743
00744 /** Where there any property mods? */
00745 svn_boolean_t prop_mod;
00746
00747 /** The name of this node as it appears in its parent's entries list */
00748 const char *name;
00749
00750 /** The filesystem revision where this was copied from (if any) */
00751 svn_revnum_t copyfrom_rev;
00752
00753 /** The filesystem path where this was copied from (if any) */
00754 const char *copyfrom_path;
00755
00756 /** Pointer to the next sibling of this node */
00757 struct svn_repos_node_t *sibling;
00758
00759 /** Pointer to the first child of this node */
00760 struct svn_repos_node_t *child;
00761
00762 /** Pointer to the parent of this node */
00763 struct svn_repos_node_t *parent;
00764
00765 } svn_repos_node_t;
00766
00767
00768 /** Set @a *editor and @a *edit_baton to an editor that, when driven by
00769 * @c svn_repos_dir_delta(), builds an <tt>svn_repos_node_t *</tt> tree
00770 * representing the delta from @a base_root to @a root in @a repos's
00771 * filesystem.
00772 *
00773 * Invoke @c svn_repos_node_from_baton() on @a edit_baton to obtain the root
00774 * node afterwards.
00775 *
00776 * Note that the delta includes "bubbled-up" directories; that is,
00777 * many of the directory nodes will have no prop_mods.
00778 *
00779 * Allocate the tree and its contents in @a node_pool; do all other
00780 * allocation in @a pool.
00781 */
00782 svn_error_t *svn_repos_node_editor (const svn_delta_editor_t **editor,
00783 void **edit_baton,
00784 svn_repos_t *repos,
00785 svn_fs_root_t *base_root,
00786 svn_fs_root_t *root,
00787 apr_pool_t *node_pool,
00788 apr_pool_t *pool);
00789
00790 /** Return the root node of the linked-list tree generated by driving
00791 * the editor created by @c svn_repos_node_editor() with
00792 * @c svn_repos_dir_delta(), which is stored in @a edit_baton. This is
00793 * only really useful if used *after* the editor drive is completed.
00794 */
00795 svn_repos_node_t *svn_repos_node_from_baton (void *edit_baton);
00796
00797 /** @} */
00798
00799 /* ---------------------------------------------------------------*/
00800
00801 /**
00802 * @defgroup svn_repos_dump_load Dumping and loading filesystem data
00803 * @{
00804 *
00805 * The filesystem 'dump' format contains nothing but the abstract
00806 * structure of the filesystem -- independent of any internal node-id
00807 * schema or database back-end. All of the data in the dumpfile is
00808 * acquired by public function calls into svn_fs.h. Similarly, the
00809 * parser which reads the dumpfile is able to reconstruct the
00810 * filesystem using only public svn_fs.h routines.
00811 *
00812 * Thus the dump/load feature's main purpose is for *migrating* data
00813 * from one svn filesystem to another -- presumably two filesystems
00814 * which have different internal implementations.
00815 *
00816 * If you simply want to backup your filesystem, you're probably
00817 * better off using the built-in facilities of the DB backend (using
00818 * Berkeley DB's hot-backup feature, for example.)
00819 *
00820 * For a description of the dumpfile format, see
00821 * /trunk/notes/fs_dumprestore.txt.
00822 */
00823
00824 /* The RFC822-style headers in our dumpfile format. */
00825 #define SVN_REPOS_DUMPFILE_MAGIC_HEADER "SVN-fs-dump-format-version"
00826 #define SVN_REPOS_DUMPFILE_FORMAT_VERSION 2
00827 #define SVN_REPOS_DUMPFILE_UUID "UUID"
00828 #define SVN_REPOS_DUMPFILE_CONTENT_LENGTH "Content-length"
00829
00830 #define SVN_REPOS_DUMPFILE_REVISION_NUMBER "Revision-number"
00831
00832 #define SVN_REPOS_DUMPFILE_NODE_PATH "Node-path"
00833 #define SVN_REPOS_DUMPFILE_NODE_KIND "Node-kind"
00834 #define SVN_REPOS_DUMPFILE_NODE_ACTION "Node-action"
00835 #define SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH "Node-copyfrom-path"
00836 #define SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV "Node-copyfrom-rev"
00837 #define SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_CHECKSUM "Text-copy-source-md5"
00838 #define SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM "Text-content-md5"
00839
00840 #define SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH "Prop-content-length"
00841 #define SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH "Text-content-length"
00842
00843 /** The different "actions" attached to nodes in the dumpfile. */
00844 enum svn_node_action
00845 {
00846 svn_node_action_change,
00847 svn_node_action_add,
00848 svn_node_action_delete,
00849 svn_node_action_replace
00850 };
00851
00852 /** The different policies for processing the UUID in the dumpfile. */
00853 enum svn_repos_load_uuid
00854 {
00855 svn_repos_load_uuid_default,
00856 svn_repos_load_uuid_ignore,
00857 svn_repos_load_uuid_force
00858 };
00859
00860 /** Dump the contents of the filesystem within already-open @a repos into
00861 * writable @a dumpstream. Begin at revision @a start_rev, and dump every
00862 * revision up through @a end_rev. Use @a pool for all allocation. If
00863 * non-@c NULL, send feedback to @a feedback_stream. @a dumpstream can be
00864 * @c NULL for the purpose of verifying the repository.
00865 *
00866 * If @a start_rev is @c SVN_INVALID_REVNUM, then start dumping at revision
00867 * 0. If @a end_rev is @c SVN_INVALID_REVNUM, then dump through the @c HEAD
00868 * revision.
00869 *
00870 * If @a incremental is @c TRUE, the first revision dumped will be a diff
00871 * against the previous revision (usually it looks like a full dump of
00872 * the tree).
00873 *
00874 * If @a cancel_func is not @c NULL, it is called periodically with
00875 * @a cancel_baton as argument to see if the client wishes to cancel
00876 * the dump.
00877 */
00878 svn_error_t *svn_repos_dump_fs (svn_repos_t *repos,
00879 svn_stream_t *dumpstream,
00880 svn_stream_t *feedback_stream,
00881 svn_revnum_t start_rev,
00882 svn_revnum_t end_rev,
00883 svn_boolean_t incremental,
00884 svn_cancel_func_t cancel_func,
00885 void *cancel_baton,
00886 apr_pool_t *pool);
00887
00888
00889 /** Read and parse dumpfile-formatted @a dumpstream, reconstructing
00890 * filesystem revisions in already-open @a repos, handling uuids
00891 * in accordance with @a uuid_action.
00892 *
00893 * Read and parse dumpfile-formatted @a dumpstream, reconstructing
00894 * filesystem revisions in already-open @a repos. Use @a pool for all
00895 * allocation. If non-@c NULL, send feedback to @a feedback_stream.
00896 *
00897 * If the dumpstream contains copy history that is unavailable in the
00898 * repository, an error will be thrown.
00899 *
00900 * The repository's UUID will be updated iff
00901 * the dumpstream contains a UUID and
00902 * @a uuid_action is not equal to @c svn_repos_load_uuid_ignore and
00903 * either the repository contains no revisions or
00904 * @a uuid_action is equal to @c svn_repos_load_uuid_force.
00905 *
00906 * If the dumpstream contains no UUID, then @a uuid_action is
00907 * ignored and the repository UUID is not touched.
00908 *
00909 * If @a cancel_func is not @c NULL, it is called periodically with
00910 * @a cancel_baton as argument to see if the client wishes to cancel
00911 * the load.
00912 */
00913 svn_error_t *svn_repos_load_fs (svn_repos_t *repos,
00914 svn_stream_t *dumpstream,
00915 svn_stream_t *feedback_stream,
00916 enum svn_repos_load_uuid uuid_action,
00917 const char *parent_dir,
00918 svn_cancel_func_t cancel_func,
00919 void *cancel_baton,
00920 apr_pool_t *pool);
00921
00922
00923 /** A vtable that is driven by @c svn_repos_parse_dumpstream. */
00924 typedef struct svn_repos_parse_fns_t
00925 {
00926 /** The parser has discovered a new revision record within the
00927 * parsing session represented by @a parse_baton. All the headers are
00928 * placed in @a headers (allocated in @a pool), which maps <tt>const
00929 * char *</tt> header-name ==> <tt>const char *</tt> header-value.
00930 * The @a revision_baton received back (also allocated in @a pool)
00931 * represents the revision.
00932 */
00933 svn_error_t *(*new_revision_record) (void **revision_baton,
00934 apr_hash_t *headers,
00935 void *parse_baton,
00936 apr_pool_t *pool);
00937
00938 /** The parser has discovered a new uuid record within the parsing
00939 * session represented by @a parse_baton. The uuid's value is
00940 * @a uuid, and it is allocated in @a pool.
00941 */
00942 svn_error_t *(*uuid_record) (const char *uuid,
00943 void *parse_baton,
00944 apr_pool_t *pool);
00945
00946 /** The parser has discovered a new node record within the current
00947 * revision represented by @a revision_baton. All the headers are
00948 * placed in @a headers as above, allocated in @a pool. The
00949 * @a node_baton received back is allocated in @a pool and represents
00950 * the node.
00951 */
00952 svn_error_t *(*new_node_record) (void **node_baton,
00953 apr_hash_t *headers,
00954 void *revision_baton,
00955 apr_pool_t *pool);
00956
00957 /** For a given @a revision_baton, set a property @a name to @a value. */
00958 svn_error_t *(*set_revision_property) (void *revision_baton,
00959 const char *name,
00960 const svn_string_t *value);
00961
00962 /** For a given @a node_baton, set a property @a name to @a value. */
00963 svn_error_t *(*set_node_property) (void *node_baton,
00964 const char *name,
00965 const svn_string_t *value);
00966
00967 /** For a given @a node_baton, remove all properties. */
00968 svn_error_t *(*remove_node_props) (void *node_baton);
00969
00970 /** For a given @a node_baton, receive a writable @a stream capable of
00971 * receiving the node's fulltext. After writing the fulltext, call
00972 * the stream's @c close() function.
00973 *
00974 * If a @c NULL is returned instead of a stream, the vtable is
00975 * indicating that no text is desired, and the parser will not
00976 * attempt to send it.
00977 */
00978 svn_error_t *(*set_fulltext) (svn_stream_t **stream,
00979 void *node_baton);
00980
00981 /** The parser has reached the end of the current node represented by
00982 * @a node_baton, it can be freed.
00983 */
00984 svn_error_t *(*close_node) (void *node_baton);
00985
00986 /** The parser has reached the end of the current revision
00987 * represented by @a revision_baton. In other words, there are no more
00988 * changed nodes within the revision. The baton can be freed.
00989 */
00990 svn_error_t *(*close_revision) (void *revision_baton);
00991
00992 } svn_repos_parser_fns_t;
00993
00994
00995
00996 /** Read and parse dumpfile-formatted @a stream, calling callbacks in
00997 * @a parse_fns/@a parse_baton, and using @a pool for allocations.
00998 *
00999 * If @a cancel_func is not @c NULL, it is called periodically with
01000 * @a cancel_baton as argument to see if the client wishes to cancel
01001 * the dump.
01002 *
01003 * This parser has built-in knowledge of the dumpfile format, but only
01004 * in a general sense:
01005 *
01006 * * it recognizes revision and node records by looking for either
01007 * a REVISION_NUMBER or NODE_PATH headers.
01008 *
01009 * * it recognizes the CONTENT-LENGTH headers, so it knows if and
01010 * how to suck up the content body.
01011 *
01012 * * it knows how to parse a content body into two parts: props
01013 * and text, and pass the pieces to the vtable.
01014 *
01015 * This is enough knowledge to make it easy on vtable implementors,
01016 * but still allow expansion of the format: most headers are ignored.
01017 */
01018 svn_error_t *
01019 svn_repos_parse_dumpstream (svn_stream_t *stream,
01020 const svn_repos_parser_fns_t *parse_fns,
01021 void *parse_baton,
01022 svn_cancel_func_t cancel_func,
01023 void *cancel_baton,
01024 apr_pool_t *pool);
01025
01026
01027 /** Set @a *parser and @a *parse_baton to a vtable parser which commits new
01028 * revisions to the fs in @a repos. The constructed parser will treat
01029 * UUID records in a manner consistent with @a uuid_action. Use @a pool
01030 * to operate on the fs.
01031 *
01032 * If @a use_history is set, then the parser will require relative
01033 * 'copyfrom' history to exist in the repository when it encounters
01034 * nodes that are added-with-history.
01035 *
01036 * If @a parent_dir is not null, then the parser will reparent all the
01037 * loaded nodes, from root to @a parent_dir. The directory @a parent_dir
01038 * must be an existing directory in the repository.
01039 *
01040 * Print all parsing feedback to @a outstream (if non-@c NULL).
01041 *
01042 */
01043 svn_error_t *
01044 svn_repos_get_fs_build_parser (const svn_repos_parser_fns_t **parser,
01045 void **parse_baton,
01046 svn_repos_t *repos,
01047 svn_boolean_t use_history,
01048 enum svn_repos_load_uuid uuid_action,
01049 svn_stream_t *outstream,
01050 const char *parent_dir,
01051 apr_pool_t *pool);
01052 /** @} */
01053
01054 #ifdef __cplusplus
01055 }
01056 #endif /* __cplusplus */
01057
01058 #endif /* SVN_REPOS_H */
1.2.14 written by Dimitri van Heesch,
© 1997-2002