📄 serve.c
字号:
SVN_CMD_ERR(svn_fs_revision_root(&root, b->fs, rev, pool));
/* Fetch the directory properties if requested. */
if (want_props)
SVN_CMD_ERR(get_props(&props, root, full_path, pool));
/* Fetch the directory entries if requested. */
if (want_contents)
{
SVN_CMD_ERR(svn_fs_dir_entries(&entries, root, full_path, pool));
/* Transform the hash table's FS entries into dirents. This probably
* belongs in libsvn_repos. */
subpool = svn_pool_create(pool);
for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
{
apr_hash_this(hi, &key, NULL, &val);
name = key;
fsent = val;
file_path = svn_path_join(full_path, name, subpool);
entry = apr_pcalloc(pool, sizeof(*entry));
/* kind */
entry->kind = fsent->kind;
/* size */
if (entry->kind == svn_node_dir)
entry->size = 0;
else
SVN_CMD_ERR(svn_fs_file_length(&entry->size, root, file_path,
subpool));
/* has_props */
SVN_CMD_ERR(svn_fs_node_proplist(&file_props, root, file_path,
subpool));
entry->has_props = (apr_hash_count(file_props) > 0) ? TRUE : FALSE;
/* created_rev, last_author, time */
SVN_CMD_ERR(svn_repos_get_committed_info(&entry->created_rev, &cdate,
&cauthor, root, file_path,
subpool));
entry->last_author = apr_pstrdup(pool, cauthor);
if (cdate)
SVN_CMD_ERR(svn_time_from_cstring(&entry->time, cdate, subpool));
else
entry->time = (time_t) -1;
/* Store the entry. */
apr_hash_set(entries, name, APR_HASH_KEY_STRING, entry);
svn_pool_clear(subpool);
}
svn_pool_destroy(subpool);
}
/* Write out response. */
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(r(!", "success", rev));
SVN_ERR(write_proplist(conn, pool, props));
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(!"));
if (want_contents)
{
for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
{
apr_hash_this(hi, &key, NULL, &val);
name = key;
entry = val;
cdate = (entry->time == (time_t) -1) ? NULL
: svn_time_to_cstring(entry->time, pool);
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "cwnbr(?c)(?c)", name,
kind_word(entry->kind),
(apr_uint64_t) entry->size,
entry->has_props, entry->created_rev,
cdate, entry->last_author));
}
}
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
return SVN_NO_ERROR;
}
static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
const char *target;
svn_boolean_t recurse;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cb", &rev, &target,
&recurse));
target = svn_path_canonicalize(target, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
if (!SVN_IS_VALID_REVNUM(rev))
SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
return accept_report(conn, pool, b, rev, target, NULL, TRUE, recurse, FALSE);
}
static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
const char *target;
const char *switch_url, *switch_path;
svn_boolean_t recurse;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbc", &rev, &target,
&recurse, &switch_url));
target = svn_path_canonicalize(target, pool);
switch_url = svn_path_canonicalize(switch_url, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
if (!SVN_IS_VALID_REVNUM(rev))
SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repos_url, pool),
svn_path_uri_decode(switch_url, pool),
&switch_path, pool));
return accept_report(conn, pool, b, rev, target, switch_path, TRUE, recurse,
TRUE);
}
static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
const char *target;
svn_boolean_t recurse;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cb?(?r)",
&target, &recurse, &rev));
target = svn_path_canonicalize(target, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
if (!SVN_IS_VALID_REVNUM(rev))
SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
return accept_report(conn, pool, b, rev, target, NULL, FALSE, recurse,
FALSE);
}
static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
const char *target, *versus_url, *versus_path;
svn_boolean_t recurse, ignore_ancestry;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbc", &rev, &target,
&recurse, &ignore_ancestry, &versus_url));
target = svn_path_canonicalize(target, pool);
versus_url = svn_path_canonicalize(versus_url, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
if (!SVN_IS_VALID_REVNUM(rev))
SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repos_url, pool),
svn_path_uri_decode(versus_url, pool),
&versus_path, pool));
return accept_report(conn, pool, b, rev, target, versus_path, TRUE, recurse,
ignore_ancestry);
}
/* Send a log entry to the client. */
static svn_error_t *log_receiver(void *baton, apr_hash_t *changed_paths,
svn_revnum_t rev, const char *author,
const char *date, const char *message,
apr_pool_t *pool)
{
log_baton_t *b = baton;
svn_ra_svn_conn_t *conn = b->conn;
apr_hash_index_t *h;
const void *key;
void *val;
const char *path;
svn_log_changed_path_t *change;
char action[2];
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "(!"));
if (changed_paths)
{
for (h = apr_hash_first(pool, changed_paths); h; h = apr_hash_next(h))
{
apr_hash_this(h, &key, NULL, &val);
path = key;
change = val;
action[0] = change->action;
action[1] = '\0';
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "cw(?cr)", path, action,
change->copyfrom_path,
change->copyfrom_rev));
}
}
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)r(?c)(?c)(?c)", rev, author,
date, message));
return SVN_NO_ERROR;
}
static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
svn_error_t *err, *write_err;
server_baton_t *b = baton;
svn_revnum_t start_rev, end_rev;
const char *full_path;
svn_boolean_t changed_paths, strict_node;
apr_array_header_t *paths, *full_paths;
svn_ra_svn_item_t *elt;
int i;
log_baton_t lb;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb", &paths,
&start_rev, &end_rev, &changed_paths,
&strict_node));
full_paths = apr_array_make(pool, paths->nelts, sizeof(const char *));
for (i = 0; i < paths->nelts; i++)
{
elt = &((svn_ra_svn_item_t *) paths->elts)[i];
if (elt->kind != SVN_RA_SVN_STRING)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Log path entry not a string");
full_path = svn_path_join(b->fs_path,
svn_path_canonicalize(elt->u.string->data,
pool),
pool);
*((const char **) apr_array_push(full_paths)) = full_path;
}
SVN_ERR(trivial_auth_request(conn, pool, b));
/* Get logs. (Can't report errors back to the client at this point.) */
lb.fs_path = b->fs_path;
lb.conn = conn;
err = svn_repos_get_logs2(b->repos, full_paths, start_rev, end_rev,
changed_paths, strict_node, NULL, NULL,
log_receiver, &lb, pool);
write_err = svn_ra_svn_write_word(conn, pool, "done");
if (write_err)
{
svn_error_clear(err);
return write_err;
}
SVN_CMD_ERR(err);
SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
return SVN_NO_ERROR;
}
static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
svn_revnum_t rev;
const char *path, *full_path;
svn_fs_root_t *root;
svn_node_kind_t kind;
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)", &path, &rev));
path = svn_path_canonicalize(path, pool);
SVN_ERR(trivial_auth_request(conn, pool, b));
if (!SVN_IS_VALID_REVNUM(rev))
SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
full_path = svn_path_join(b->fs_path, path, pool);
SVN_CMD_ERR(svn_fs_revision_root(&root, b->fs, rev, pool));
SVN_CMD_ERR(svn_fs_check_path(&kind, root, full_path, pool));
SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "w", kind_word(kind)));
return SVN_NO_ERROR;
}
static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
svn_error_t *err, *write_err;
server_baton_t *b = baton;
svn_revnum_t revision;
apr_array_header_t *location_revisions, *loc_revs_proto;
svn_ra_svn_item_t *elt;
int i;
const char *relative_path;
svn_revnum_t peg_revision;
apr_hash_t *fs_locations;
apr_hash_index_t *iter;
const char *abs_path;
const void *iter_key;
void *iter_value;
/* Parse the arguments. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "crl", &relative_path,
&peg_revision,
&loc_revs_proto));
relative_path = svn_path_canonicalize(relative_path, pool);
abs_path = svn_path_join(b->fs_path, relative_path, pool);
location_revisions = apr_array_make(pool, loc_revs_proto->nelts,
sizeof(svn_revnum_t));
for (i = 0; i < loc_revs_proto->nelts; i++)
{
elt = &APR_ARRAY_IDX(loc_revs_proto, i, svn_ra_svn_item_t);
if (elt->kind != SVN_RA_SVN_NUMBER)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
"Get-locations location revisions entry "
"not a revision number");
revision = (svn_revnum_t)(elt->u.number);
APR_ARRAY_PUSH(location_revisions, svn_revnum_t) = revision;
}
SVN_ERR(trivial_auth_request(conn, pool, b));
/* All the parameters are fine - let's perform the query against the
* repository. */
/* We store both err and write_err here, so the client will get
* the "done" even if there was an error in fetching the results. */
err = svn_repos_trace_node_locations(b->fs, &fs_locations, abs_path,
peg_revision, location_revisions,
NULL, NULL, pool);
/* Now, write the results to the connection. */
if (!err)
{
if (fs_locations)
{
for (iter = apr_hash_first(pool, fs_locations); iter;
iter = apr_hash_next(iter))
{
apr_hash_this(iter, &iter_key, NULL, &iter_value);
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "rc",
*(const svn_revnum_t *)iter_key,
(const char *)iter_value));
}
}
}
write_err = svn_ra_svn_write_word(conn, pool, "done");
if (write_err)
{
svn_error_clear(err);
return write_err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -