|
| 1 | +/* |
| 2 | + * model.c: the application state |
| 3 | + * |
| 4 | + * ==================================================================== |
| 5 | + * Licensed to the Apache Software Foundation (ASF) under one |
| 6 | + * or more contributor license agreements. See the NOTICE file |
| 7 | + * distributed with this work for additional information |
| 8 | + * regarding copyright ownership. The ASF licenses this file |
| 9 | + * to you under the Apache License, Version 2.0 (the |
| 10 | + * "License"); you may not use this file except in compliance |
| 11 | + * with the License. You may obtain a copy of the License at |
| 12 | + * |
| 13 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 14 | + * |
| 15 | + * Unless required by applicable law or agreed to in writing, |
| 16 | + * software distributed under the License is distributed on an |
| 17 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 18 | + * KIND, either express or implied. See the License for the |
| 19 | + * specific language governing permissions and limitations |
| 20 | + * under the License. |
| 21 | + * ==================================================================== |
| 22 | + */ |
| 23 | + |
| 24 | +#include <apr.h> |
| 25 | + |
| 26 | +#include "svn_client.h" |
| 27 | +#include "svn_cmdline.h" |
| 28 | +#include "svn_dirent_uri.h" |
| 29 | +#include "svn_ra.h" |
| 30 | +#include "svn_pools.h" |
| 31 | +#include "svn_error.h" |
| 32 | + |
| 33 | +#include "svnbrowse.h" |
| 34 | + |
| 35 | +svn_error_t * |
| 36 | +svn_browse__state_create(svn_browse__state_t **state_p, |
| 37 | + svn_ra_session_t *session, |
| 38 | + const char *relpath, |
| 39 | + svn_revnum_t revision, |
| 40 | + apr_pool_t *result_pool, |
| 41 | + apr_pool_t *scratch_pool) |
| 42 | +{ |
| 43 | + svn_browse__state_t *state = apr_pcalloc(result_pool, sizeof(*state)); |
| 44 | + svn_revnum_t fetched_revnum; |
| 45 | + apr_hash_t *dirents; |
| 46 | + apr_hash_index_t *hi; |
| 47 | + |
| 48 | + SVN_ERR(svn_ra_get_dir2(session, &dirents, &fetched_revnum, NULL, relpath, |
| 49 | + revision, SVN_DIRENT_ALL, scratch_pool)); |
| 50 | + |
| 51 | + state->relpath = apr_pstrdup(result_pool, relpath); |
| 52 | + state->revision = fetched_revnum; |
| 53 | + state->selection = 0; |
| 54 | + state->pool = result_pool; |
| 55 | + |
| 56 | + state->list = apr_array_make(result_pool, 0, sizeof(svn_browse__item_t *)); |
| 57 | + for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi)) |
| 58 | + { |
| 59 | + const char *name = apr_hash_this_key(hi); |
| 60 | + const svn_dirent_t *dirent = apr_hash_this_val(hi); |
| 61 | + |
| 62 | + svn_browse__item_t *item = apr_pcalloc(result_pool, sizeof(*item)); |
| 63 | + item->name = apr_pstrdup(result_pool, name); |
| 64 | + item->dirent = svn_dirent_dup(dirent, result_pool); |
| 65 | + |
| 66 | + APR_ARRAY_PUSH(state->list, svn_browse__item_t *) = item; |
| 67 | + } |
| 68 | + |
| 69 | + *state_p = state; |
| 70 | + return SVN_NO_ERROR; |
| 71 | +} |
| 72 | + |
| 73 | +svn_error_t * |
| 74 | +svn_browse__model_enter_path(svn_browse__model_t *ctx, const char *relpath, |
| 75 | + apr_pool_t *scratch_pool) |
| 76 | +{ |
| 77 | + svn_browse__state_t *newstate; |
| 78 | + apr_pool_t *state_pool = svn_pool_create(ctx->pool); |
| 79 | + |
| 80 | + SVN_ERR(svn_browse__state_create(&newstate, ctx->session, relpath, |
| 81 | + ctx->revision, state_pool, scratch_pool)); |
| 82 | + |
| 83 | + /* switch to the next state and nuke the previous one */ |
| 84 | + apr_pool_destroy(ctx->current->pool); |
| 85 | + ctx->current = newstate; |
| 86 | + |
| 87 | + return SVN_NO_ERROR; |
| 88 | +} |
| 89 | + |
| 90 | +svn_browse__item_t * |
| 91 | +svn_browse__model_get_selected_item(svn_browse__model_t *model) |
| 92 | +{ |
| 93 | + return APR_ARRAY_IDX(model->current->list, model->current->selection, |
| 94 | + svn_browse__item_t *); |
| 95 | +} |
| 96 | + |
| 97 | +svn_error_t * |
| 98 | +svn_browse__model_go_enter(svn_browse__model_t *model, apr_pool_t *scratch_pool) |
| 99 | +{ |
| 100 | + svn_browse__item_t *item = svn_browse__model_get_selected_item(model); |
| 101 | + const char *new_url = svn_relpath_join(model->current->relpath, item->name, |
| 102 | + scratch_pool); |
| 103 | + return svn_error_trace(svn_browse__model_enter_path(model, new_url, |
| 104 | + scratch_pool)); |
| 105 | +} |
| 106 | + |
| 107 | +svn_error_t * |
| 108 | +svn_browse__model_go_up(svn_browse__model_t *model, apr_pool_t *scratch_pool) |
| 109 | +{ |
| 110 | + const char *new_url = svn_relpath_dirname(model->current->relpath, |
| 111 | + scratch_pool); |
| 112 | + return svn_error_trace(svn_browse__model_enter_path(model, new_url, |
| 113 | + scratch_pool)); |
| 114 | +} |
| 115 | + |
| 116 | +svn_error_t * |
| 117 | +svn_browse__model_move_selection(svn_browse__model_t *model, int delta) |
| 118 | +{ |
| 119 | + model->current->selection += delta; |
| 120 | + |
| 121 | + if (model->current->selection >= model->current->list->nelts) |
| 122 | + model->current->selection = model->current->list->nelts - 1; |
| 123 | + |
| 124 | + if (model->current->selection < 0) |
| 125 | + model->current->selection = 0; |
| 126 | + |
| 127 | + return SVN_NO_ERROR; |
| 128 | +} |
| 129 | + |
| 130 | +svn_error_t * |
| 131 | +svn_browse__model_create(svn_browse__model_t **model_p, |
| 132 | + const char *url, |
| 133 | + svn_revnum_t revision, |
| 134 | + apr_pool_t *result_pool, |
| 135 | + apr_pool_t *scratch_pool) |
| 136 | +{ |
| 137 | + svn_browse__model_t *model = apr_pcalloc(result_pool, sizeof(*model)); |
| 138 | + svn_auth_baton_t *auth; |
| 139 | + svn_client_ctx_t *client; |
| 140 | + svn_ra_session_t *session; |
| 141 | + apr_pool_t *state_pool; |
| 142 | + svn_browse__state_t *state; |
| 143 | + const char *root, *relpath; |
| 144 | + |
| 145 | + /* Set up Authentication stuff. */ |
| 146 | + SVN_ERR(svn_cmdline_create_auth_baton2(&auth, FALSE, NULL, NULL, NULL, FALSE, |
| 147 | + FALSE, FALSE, FALSE, FALSE, FALSE, |
| 148 | + NULL, NULL, NULL, result_pool)); |
| 149 | + |
| 150 | + SVN_ERR(svn_client_create_context2(&client, NULL, result_pool)); |
| 151 | + client->auth_baton = auth; |
| 152 | + |
| 153 | + SVN_ERR(svn_client_open_ra_session2(&session, url, NULL, client, result_pool, |
| 154 | + scratch_pool)); |
| 155 | + |
| 156 | + SVN_ERR(svn_ra_get_repos_root2(session, &root, scratch_pool)); |
| 157 | + SVN_ERR(svn_ra_reparent(session, root, scratch_pool)); |
| 158 | + |
| 159 | + relpath = svn_uri_skip_ancestor(root, url, scratch_pool); |
| 160 | + |
| 161 | + /* the state should be in a separate pool so it's safe to free it */ |
| 162 | + state_pool = svn_pool_create(result_pool); |
| 163 | + SVN_ERR(svn_browse__state_create(&state, session, relpath, revision, |
| 164 | + state_pool, scratch_pool)); |
| 165 | + |
| 166 | + model->root = apr_pstrdup(result_pool, root); |
| 167 | + model->revision = revision; |
| 168 | + model->client = client; |
| 169 | + model->session = session; |
| 170 | + model->current = state; |
| 171 | + model->pool = result_pool; |
| 172 | + |
| 173 | + *model_p = model; |
| 174 | + return SVN_NO_ERROR; |
| 175 | +} |
0 commit comments