📄 serve.c
字号:
for (i = 0; i < dirent_fields_list->nelts; ++i) { elt = &APR_ARRAY_IDX(dirent_fields_list, i, svn_ra_svn_item_t); if (elt->kind != SVN_RA_SVN_WORD) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Dirent field not a string"); if (strcmp(SVN_RA_SVN_DIRENT_KIND, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_KIND; else if (strcmp(SVN_RA_SVN_DIRENT_SIZE, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_SIZE; else if (strcmp(SVN_RA_SVN_DIRENT_HAS_PROPS, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_HAS_PROPS; else if (strcmp(SVN_RA_SVN_DIRENT_CREATED_REV, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_CREATED_REV; else if (strcmp(SVN_RA_SVN_DIRENT_TIME, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_TIME; else if (strcmp(SVN_RA_SVN_DIRENT_LAST_AUTHOR, elt->u.word) == 0) dirent_fields |= SVN_DIRENT_LAST_AUTHOR; } } full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, pool), pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, full_path, FALSE)); if (!SVN_IS_VALID_REVNUM(rev)) SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool)); /* Fetch the root of the appropriate revision. */ 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; svn_pool_clear(subpool); file_path = svn_path_join(full_path, name, subpool); entry = apr_pcalloc(pool, sizeof(*entry)); if (dirent_fields & SVN_DIRENT_KIND) { /* kind */ entry->kind = fsent->kind; } if (dirent_fields & SVN_DIRENT_SIZE) { /* size */ if (entry->kind == svn_node_dir) entry->size = 0; else SVN_CMD_ERR(svn_fs_file_length(&entry->size, root, file_path, subpool)); } if (dirent_fields & SVN_DIRENT_HAS_PROPS) { /* 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; } if ((dirent_fields & SVN_DIRENT_LAST_AUTHOR) || (dirent_fields & SVN_DIRENT_TIME) || (dirent_fields & SVN_DIRENT_CREATED_REV)) { /* 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_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; svn_boolean_t text_deltas; /* Parse the arguments. */ if (params->nelts == 5) { /* Clients before 1.4 don't send the text_deltas boolean. */ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbc", &rev, &target, &recurse, &ignore_ancestry, &versus_url)); text_deltas = TRUE; } else { SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbcb", &rev, &target, &recurse, &ignore_ancestry, &versus_url, &text_deltas)); } 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, text_deltas, 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; apr_uint64_t limit; log_baton_t lb; /* Parse the arguments. */ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb?n", &paths, &start_rev, &end_rev, &changed_paths, &strict_node, &limit)); /* If we got an unspecified number then the user didn't send us anything, so we assume no limit. If it's larger than INT_MAX then someone is messing with us, since we know the svn client libraries will never send us anything that big, so play it safe and default to no limit. */ if (limit == SVN_RA_SVN_UNSPECIFIED_NUMBER || limit > INT_MAX) limit = 0; 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->data, 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->data; lb.conn = conn; err = svn_repos_get_logs3(b->repos, full_paths, start_rev, end_rev, (int) limit, changed_paths, strict_node, authz_check_access_cb_func(b), b, 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)); full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, pool), pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, full_path, FALSE)); if (!SVN_IS_VALID_REVNUM(rev)) SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, 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 *stat(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, *cdate; svn_fs_root_t *root; svn_dirent_t *dirent; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)", &path, &rev)); full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, pool), pool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -