Index: libsvn_fs/fs-loader.c =================================================================== --- libsvn_fs/fs-loader.c (revision 1453607) +++ libsvn_fs/fs-loader.c (working copy) @@ -58,6 +58,17 @@ #define FS_TYPE_FILENAME "fs-type" +#define ENSURE(expr) \ + do { \ + if (!(expr)) \ + SVN_ERR(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, \ + "%s: %s: %s", _("Incorrect parameters given"), \ + _("Ensure expression false"), #expr)); \ + } while (0) + +#define ENSURE_VTABLE(obj, func) \ + ENSURE(obj && obj->vtable && obj->vtable->func) + /* A pool common to all FS objects. See the documentation on the open/create functions in fs-loader.h and for svn_fs_initialize(). */ static apr_pool_t *common_pool; @@ -508,6 +519,8 @@ const char * svn_fs_path(svn_fs_t *fs, apr_pool_t *pool) { + if (!fs) + return NULL; return apr_pstrdup(pool, fs->path); } @@ -633,6 +646,7 @@ svn_revnum_t revision, apr_pool_t *scratch_pool) { + ENSURE_VTABLE(fs, verify_rev); SVN_ERR(fs->vtable->verify_rev(fs, revision, scratch_pool)); return SVN_NO_ERROR; @@ -644,6 +658,7 @@ void *baton, apr_pool_t *pool) { + ENSURE_VTABLE(fs, freeze); SVN_ERR(fs->vtable->freeze(fs, freeze_body, baton, pool)); return SVN_NO_ERROR; @@ -657,6 +672,7 @@ { fs_library_vtable_t *vtable; + ENSURE(fs); SVN_ERR(get_library_vtable(&vtable, SVN_FS_TYPE_BDB, fs->pool)); /* Create the FS directory and write out the fsap-name file. */ @@ -674,6 +690,7 @@ { fs_library_vtable_t *vtable; + ENSURE(fs); SVN_ERR(fs_library_vtable(&vtable, path, fs->pool)); SVN_MUTEX__WITH_LOCK(common_pool_lock, vtable->open_fs(fs, path, fs->pool, common_pool)); @@ -710,6 +727,7 @@ svn_fs_set_berkeley_errcall(svn_fs_t *fs, void (*handler)(const char *errpfx, char *msg)) { + ENSURE_VTABLE(fs, bdb_set_errcall); return svn_error_trace(fs->vtable->bdb_set_errcall(fs, handler)); } @@ -733,6 +751,7 @@ svn_fs_begin_txn2(svn_fs_txn_t **txn_p, svn_fs_t *fs, svn_revnum_t rev, apr_uint32_t flags, apr_pool_t *pool) { + ENSURE_VTABLE(fs, begin_txn); return svn_error_trace(fs->vtable->begin_txn(txn_p, fs, rev, flags, pool)); } @@ -754,7 +773,11 @@ svn_fs_root_t *txn_root; svn_fs_t *fs; const char *fs_path; +#endif + + ENSURE(new_rev); +#ifdef PACK_AFTER_EVERY_COMMIT *new_rev = SVN_INVALID_REVNUM; SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); fs = svn_fs_root_fs(txn_root); @@ -761,6 +784,7 @@ fs_path = svn_fs_path(fs, pool); #endif + ENSURE_VTABLE(txn, commit); err = txn->vtable->commit(conflict_p, new_rev, txn, pool); #ifdef SVN_DEBUG @@ -796,6 +820,7 @@ svn_error_t * svn_fs_abort_txn(svn_fs_txn_t *txn, apr_pool_t *pool) { + ENSURE_VTABLE(txn, abort); return svn_error_trace(txn->vtable->abort(txn, pool)); } @@ -802,6 +827,7 @@ svn_error_t * svn_fs_purge_txn(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool) { + ENSURE_VTABLE(fs, purge_txn); return svn_error_trace(fs->vtable->purge_txn(fs, txn_id, pool)); } @@ -808,6 +834,7 @@ svn_error_t * svn_fs_txn_name(const char **name_p, svn_fs_txn_t *txn, apr_pool_t *pool) { + ENSURE(txn); *name_p = apr_pstrdup(pool, txn->id); return SVN_NO_ERROR; } @@ -815,6 +842,8 @@ svn_revnum_t svn_fs_txn_base_revision(svn_fs_txn_t *txn) { + if (!txn) + return SVN_INVALID_REVNUM; return txn->base_rev; } @@ -822,6 +851,7 @@ svn_fs_open_txn(svn_fs_txn_t **txn, svn_fs_t *fs, const char *name, apr_pool_t *pool) { + ENSURE_VTABLE(fs, open_txn); return svn_error_trace(fs->vtable->open_txn(txn, fs, name, pool)); } @@ -829,6 +859,7 @@ svn_fs_list_transactions(apr_array_header_t **names_p, svn_fs_t *fs, apr_pool_t *pool) { + ENSURE_VTABLE(fs, list_transactions); return svn_error_trace(fs->vtable->list_transactions(names_p, fs, pool)); } @@ -836,6 +867,7 @@ svn_fs_txn_prop(svn_string_t **value_p, svn_fs_txn_t *txn, const char *propname, apr_pool_t *pool) { + ENSURE_VTABLE(txn, get_prop); return svn_error_trace(txn->vtable->get_prop(value_p, txn, propname, pool)); } @@ -842,6 +874,7 @@ svn_error_t * svn_fs_txn_proplist(apr_hash_t **table_p, svn_fs_txn_t *txn, apr_pool_t *pool) { + ENSURE_VTABLE(txn, get_proplist); return svn_error_trace(txn->vtable->get_proplist(table_p, txn, pool)); } @@ -849,6 +882,7 @@ svn_fs_change_txn_prop(svn_fs_txn_t *txn, const char *name, const svn_string_t *value, apr_pool_t *pool) { + ENSURE_VTABLE(txn, change_prop); return svn_error_trace(txn->vtable->change_prop(txn, name, value, pool)); } @@ -856,6 +890,7 @@ svn_fs_change_txn_props(svn_fs_txn_t *txn, const apr_array_header_t *props, apr_pool_t *pool) { + ENSURE_VTABLE(txn, change_props); return svn_error_trace(txn->vtable->change_props(txn, props, pool)); } @@ -866,9 +901,11 @@ svn_fs_revision_root(svn_fs_root_t **root_p, svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) { + apr_pool_t *subpool; + ENSURE_VTABLE(fs, revision_root); /* We create a subpool for each root object to allow us to implement svn_fs_close_root. */ - apr_pool_t *subpool = svn_pool_create(pool); + subpool = svn_pool_create(pool); return svn_error_trace(fs->vtable->revision_root(root_p, fs, rev, subpool)); } @@ -875,9 +912,11 @@ svn_error_t * svn_fs_txn_root(svn_fs_root_t **root_p, svn_fs_txn_t *txn, apr_pool_t *pool) { + apr_pool_t *subpool; + ENSURE_VTABLE(txn, root); /* We create a subpool for each root object to allow us to implement svn_fs_close_root. */ - apr_pool_t *subpool = svn_pool_create(pool); + subpool = svn_pool_create(pool); return svn_error_trace(txn->vtable->root(root_p, txn, subpool)); } @@ -884,12 +923,15 @@ void svn_fs_close_root(svn_fs_root_t *root) { - svn_pool_destroy(root->pool); + if (root) + svn_pool_destroy(root->pool); } svn_fs_t * svn_fs_root_fs(svn_fs_root_t *root) { + if (!root) + return NULL; return root->fs; } @@ -896,6 +938,8 @@ svn_boolean_t svn_fs_is_txn_root(svn_fs_root_t *root) { + if (!root) + return FALSE; return root->is_txn_root; } @@ -902,6 +946,8 @@ svn_boolean_t svn_fs_is_revision_root(svn_fs_root_t *root) { + if (!root) + return FALSE; return !root->is_txn_root; } @@ -908,6 +954,8 @@ const char * svn_fs_txn_root_name(svn_fs_root_t *root, apr_pool_t *pool) { + if (!root) + return NULL; return root->is_txn_root ? apr_pstrdup(pool, root->txn) : NULL; } @@ -914,6 +962,8 @@ svn_revnum_t svn_fs_txn_root_base_revision(svn_fs_root_t *root) { + if (!root) + return SVN_INVALID_REVNUM; return root->is_txn_root ? root->rev : SVN_INVALID_REVNUM; } @@ -920,6 +970,8 @@ svn_revnum_t svn_fs_revision_root_revision(svn_fs_root_t *root) { + if (!root) + return SVN_INVALID_REVNUM; return root->is_txn_root ? SVN_INVALID_REVNUM : root->rev; } @@ -927,6 +979,7 @@ svn_fs_paths_changed2(apr_hash_t **changed_paths_p, svn_fs_root_t *root, apr_pool_t *pool) { + ENSURE_VTABLE(root, paths_changed); return root->vtable->paths_changed(changed_paths_p, root, pool); } @@ -937,6 +990,7 @@ apr_hash_t *changed_paths_new_structs; apr_hash_index_t *hi; + ENSURE(changed_paths_p); SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool)); *changed_paths_p = apr_hash_make(pool); for (hi = apr_hash_first(pool, changed_paths_new_structs); @@ -964,6 +1018,7 @@ svn_fs_check_path(svn_node_kind_t *kind_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, check_path); return svn_error_trace(root->vtable->check_path(kind_p, root, path, pool)); } @@ -971,6 +1026,7 @@ svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_history); return svn_error_trace(root->vtable->node_history(history_p, root, path, pool)); } @@ -981,6 +1037,8 @@ { svn_node_kind_t kind; + ENSURE_VTABLE(root, check_path); + ENSURE(is_dir); SVN_ERR(root->vtable->check_path(&kind, root, path, pool)); *is_dir = (kind == svn_node_dir); return SVN_NO_ERROR; @@ -992,6 +1050,8 @@ { svn_node_kind_t kind; + ENSURE_VTABLE(root, check_path); + ENSURE(is_file); SVN_ERR(root->vtable->check_path(&kind, root, path, pool)); *is_file = (kind == svn_node_file); return SVN_NO_ERROR; @@ -1001,6 +1061,7 @@ svn_fs_node_id(const svn_fs_id_t **id_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_id); return svn_error_trace(root->vtable->node_id(id_p, root, path, pool)); } @@ -1008,6 +1069,7 @@ svn_fs_node_created_rev(svn_revnum_t *revision, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_created_rev); return svn_error_trace(root->vtable->node_created_rev(revision, root, path, pool)); } @@ -1016,6 +1078,7 @@ svn_fs_node_origin_rev(svn_revnum_t *revision, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_origin_rev); return svn_error_trace(root->vtable->node_origin_rev(revision, root, path, pool)); } @@ -1024,6 +1087,7 @@ svn_fs_node_created_path(const char **created_path, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_created_path); return svn_error_trace(root->vtable->node_created_path(created_path, root, path, pool)); } @@ -1032,6 +1096,7 @@ svn_fs_node_prop(svn_string_t **value_p, svn_fs_root_t *root, const char *path, const char *propname, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_prop); return svn_error_trace(root->vtable->node_prop(value_p, root, path, propname, pool)); } @@ -1040,6 +1105,7 @@ svn_fs_node_proplist(apr_hash_t **table_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, node_proplist); return svn_error_trace(root->vtable->node_proplist(table_p, root, path, pool)); } @@ -1049,6 +1115,7 @@ const char *name, const svn_string_t *value, apr_pool_t *pool) { + ENSURE_VTABLE(root, change_node_prop); return svn_error_trace(root->vtable->change_node_prop(root, path, name, value, pool)); } @@ -1058,6 +1125,7 @@ const char *path1, svn_fs_root_t *root2, const char *path2, apr_pool_t *pool) { + ENSURE_VTABLE(root1, props_changed); return svn_error_trace(root1->vtable->props_changed(changed_p, root1, path1, root2, path2, @@ -1068,6 +1136,7 @@ svn_fs_copied_from(svn_revnum_t *rev_p, const char **path_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, copied_from); return svn_error_trace(root->vtable->copied_from(rev_p, path_p, root, path, pool)); } @@ -1076,6 +1145,7 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, const char **path_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, closest_copy); return svn_error_trace(root->vtable->closest_copy(root_p, path_p, root, path, pool)); } @@ -1090,6 +1160,7 @@ apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + ENSURE_VTABLE(root, get_mergeinfo); return svn_error_trace(root->vtable->get_mergeinfo( catalog, root, paths, inherit, include_descendants, adjust_inherited_mergeinfo, result_pool, scratch_pool)); @@ -1103,6 +1174,7 @@ svn_boolean_t include_descendants, apr_pool_t *pool) { + ENSURE_VTABLE(root, get_mergeinfo); return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths, inherit, include_descendants, @@ -1115,6 +1187,7 @@ const char *target_path, svn_fs_root_t *ancestor_root, const char *ancestor_path, apr_pool_t *pool) { + ENSURE_VTABLE(target_root, merge); return svn_error_trace(target_root->vtable->merge(conflict_p, source_root, source_path, target_root, target_path, @@ -1126,6 +1199,7 @@ svn_fs_dir_entries(apr_hash_t **entries_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, dir_entries); return svn_error_trace(root->vtable->dir_entries(entries_p, root, path, pool)); } @@ -1133,6 +1207,7 @@ svn_error_t * svn_fs_make_dir(svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, make_dir); SVN_ERR(svn_fs__path_valid(path, pool)); return svn_error_trace(root->vtable->make_dir(root, path, pool)); } @@ -1140,6 +1215,7 @@ svn_error_t * svn_fs_delete(svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, delete_node); return svn_error_trace(root->vtable->delete_node(root, path, pool)); } @@ -1147,6 +1223,7 @@ svn_fs_copy(svn_fs_root_t *from_root, const char *from_path, svn_fs_root_t *to_root, const char *to_path, apr_pool_t *pool) { + ENSURE_VTABLE(to_root, copy); SVN_ERR(svn_fs__path_valid(to_path, pool)); return svn_error_trace(to_root->vtable->copy(from_root, from_path, to_root, to_path, pool)); @@ -1156,6 +1233,7 @@ svn_fs_revision_link(svn_fs_root_t *from_root, svn_fs_root_t *to_root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(to_root, revision_link); return svn_error_trace(to_root->vtable->revision_link(from_root, to_root, path, pool)); } @@ -1164,6 +1242,7 @@ svn_fs_file_length(svn_filesize_t *length_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, file_length); return svn_error_trace(root->vtable->file_length(length_p, root, path, pool)); } @@ -1176,19 +1255,24 @@ svn_boolean_t force, apr_pool_t *pool) { + ENSURE_VTABLE(root, file_checksum); SVN_ERR(root->vtable->file_checksum(checksum, kind, root, path, pool)); - if (force && (*checksum == NULL || (*checksum)->kind != kind)) + if (force) { - svn_stream_t *contents, *checksum_contents; + ENSURE(checksum); + if (*checksum == NULL || (*checksum)->kind != kind) + { + svn_stream_t *contents, *checksum_contents; - SVN_ERR(svn_fs_file_contents(&contents, root, path, pool)); - checksum_contents = svn_stream_checksummed2(contents, checksum, NULL, - kind, TRUE, pool); + SVN_ERR(svn_fs_file_contents(&contents, root, path, pool)); + checksum_contents = svn_stream_checksummed2(contents, checksum, NULL, + kind, TRUE, pool); - /* This will force a read of any remaining data (which is all of it in - this case) and dump the checksum into checksum->digest. */ - SVN_ERR(svn_stream_close(checksum_contents)); + /* This will force a read of any remaining data (which is all of it in + this case) and dump the checksum into checksum->digest. */ + SVN_ERR(svn_stream_close(checksum_contents)); + } } return SVN_NO_ERROR; @@ -1202,6 +1286,7 @@ { svn_checksum_t *md5sum; + ENSURE(digest); SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE, pool)); memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE); @@ -1213,6 +1298,7 @@ svn_fs_file_contents(svn_stream_t **contents, svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, file_contents); return svn_error_trace(root->vtable->file_contents(contents, root, path, pool)); } @@ -1225,6 +1311,7 @@ void* baton, apr_pool_t *pool) { + ENSURE(root && root->vtable); /* if the FS doesn't implement this function, report a "failed" attempt */ if (root->vtable->try_process_file_contents == NULL) { @@ -1241,6 +1328,7 @@ svn_error_t * svn_fs_make_file(svn_fs_root_t *root, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(root, make_file); SVN_ERR(svn_fs__path_valid(path, pool)); return svn_error_trace(root->vtable->make_file(root, path, pool)); } @@ -1253,6 +1341,8 @@ { svn_checksum_t *base, *result; + ENSURE_VTABLE(root, apply_textdelta); + /* TODO: If we ever rev this API, we should make the supplied checksums svn_checksum_t structs. */ SVN_ERR(svn_checksum_parse_hex(&base, svn_checksum_md5, base_checksum, @@ -1276,6 +1366,8 @@ { svn_checksum_t *result; + ENSURE_VTABLE(root, apply_text); + /* TODO: If we ever rev this API, we should make the supplied checksum an svn_checksum_t struct. */ SVN_ERR(svn_checksum_parse_hex(&result, svn_checksum_md5, result_checksum, @@ -1290,6 +1382,7 @@ const char *path1, svn_fs_root_t *root2, const char *path2, apr_pool_t *pool) { + ENSURE_VTABLE(root1, contents_changed); return svn_error_trace(root1->vtable->contents_changed(changed_p, root1, path1, root2, path2, @@ -1299,6 +1392,7 @@ svn_error_t * svn_fs_youngest_rev(svn_revnum_t *youngest_p, svn_fs_t *fs, apr_pool_t *pool) { + ENSURE_VTABLE(fs, youngest_rev); return svn_error_trace(fs->vtable->youngest_rev(youngest_p, fs, pool)); } @@ -1305,6 +1399,7 @@ svn_error_t * svn_fs_deltify_revision(svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool) { + ENSURE_VTABLE(fs, deltify); return svn_error_trace(fs->vtable->deltify(fs, revision, pool)); } @@ -1312,6 +1407,7 @@ svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, apr_pool_t *pool) { + ENSURE_VTABLE(fs, revision_prop); return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev, propname, pool)); } @@ -1320,6 +1416,7 @@ svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) { + ENSURE_VTABLE(fs, revision_proplist); return svn_error_trace(fs->vtable->revision_proplist(table_p, fs, rev, pool)); } @@ -1329,6 +1426,7 @@ const svn_string_t *const *old_value_p, const svn_string_t *value, apr_pool_t *pool) { + ENSURE_VTABLE(fs, change_rev_prop); return svn_error_trace(fs->vtable->change_rev_prop(fs, rev, name, old_value_p, value, pool)); @@ -1349,6 +1447,7 @@ svn_fs_root_t *target_root, const char *target_path, apr_pool_t *pool) { + ENSURE_VTABLE(target_root, get_file_delta_stream); return svn_error_trace(target_root->vtable->get_file_delta_stream( stream_p, source_root, source_path, @@ -1358,6 +1457,7 @@ svn_error_t * svn_fs_get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool) { + ENSURE(fs); /* If you change this, consider changing svn_fs__identifier(). */ *uuid = apr_pstrdup(pool, fs->uuid); return SVN_NO_ERROR; @@ -1366,6 +1466,7 @@ svn_error_t * svn_fs_set_uuid(svn_fs_t *fs, const char *uuid, apr_pool_t *pool) { + ENSURE_VTABLE(fs, set_uuid); if (! uuid) { uuid = svn_uuid_generate(pool); @@ -1427,6 +1528,7 @@ (SVN_ERR_INCORRECT_PARAMS, NULL, _("Negative expiration date passed to svn_fs_lock")); + ENSURE_VTABLE(fs, lock); return svn_error_trace(fs->vtable->lock(lock, fs, path, token, comment, is_dav_comment, expiration_date, current_rev, steal_lock, pool)); @@ -1435,6 +1537,7 @@ svn_error_t * svn_fs_generate_lock_token(const char **token, svn_fs_t *fs, apr_pool_t *pool) { + ENSURE_VTABLE(fs, generate_lock_token); return svn_error_trace(fs->vtable->generate_lock_token(token, fs, pool)); } @@ -1442,6 +1545,7 @@ svn_fs_unlock(svn_fs_t *fs, const char *path, const char *token, svn_boolean_t break_lock, apr_pool_t *pool) { + ENSURE_VTABLE(fs, unlock); return svn_error_trace(fs->vtable->unlock(fs, path, token, break_lock, pool)); } @@ -1450,6 +1554,7 @@ svn_fs_get_lock(svn_lock_t **lock, svn_fs_t *fs, const char *path, apr_pool_t *pool) { + ENSURE_VTABLE(fs, get_lock); return svn_error_trace(fs->vtable->get_lock(lock, fs, path, pool)); } @@ -1462,6 +1567,7 @@ (depth == svn_depth_files) || (depth == svn_depth_immediates) || (depth == svn_depth_infinity)); + ENSURE_VTABLE(fs, get_locks); return svn_error_trace(fs->vtable->get_locks(fs, path, depth, get_locks_func, get_locks_baton, pool)); @@ -1485,6 +1591,7 @@ svn_fs_history_t *history, svn_boolean_t cross_copies, apr_pool_t *pool) { + ENSURE_VTABLE(history, prev); return svn_error_trace(history->vtable->prev(prev_history_p, history, cross_copies, pool)); } @@ -1493,6 +1600,7 @@ svn_fs_history_location(const char **path, svn_revnum_t *revision, svn_fs_history_t *history, apr_pool_t *pool) { + ENSURE_VTABLE(history, location); return svn_error_trace(history->vtable->location(path, revision, history, pool)); } @@ -1518,6 +1626,8 @@ svn_string_t * svn_fs_unparse_id(const svn_fs_id_t *id, apr_pool_t *pool) { + if (!id || !id->vtable || !id->vtable->unparse) + return NULL; return id->vtable->unparse(id, pool); } @@ -1524,6 +1634,8 @@ svn_boolean_t svn_fs_check_related(const svn_fs_id_t *a, const svn_fs_id_t *b) { + if (!a || !a->vtable || !a->vtable->compare) + return FALSE; return (a->vtable->compare(a, b) != -1); } @@ -1530,6 +1642,8 @@ int svn_fs_compare_ids(const svn_fs_id_t *a, const svn_fs_id_t *b) { + if (!a || !a->vtable || !a->vtable->compare) + return -1; return a->vtable->compare(a, b); }