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 */