📄 commit.c
字号:
} } /* Remove the subpool. */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}static svn_error_t *reconcile_errors(svn_error_t *commit_err, svn_error_t *unlock_err, svn_error_t *bump_err, svn_error_t *cleanup_err, apr_pool_t *pool){ svn_error_t *err; /* Early release (for good behavior). */ if (! (commit_err || unlock_err || bump_err || cleanup_err)) return SVN_NO_ERROR; /* If there was a commit error, start off our error chain with that. */ if (commit_err) { commit_err = svn_error_quick_wrap (commit_err, _("Commit failed (details follow):")); err = commit_err; } /* Else, create a new "general" error that will lead off the errors that follow. */ else err = svn_error_create(SVN_ERR_BASE, NULL, _("Commit succeeded, but other errors follow:")); /* If there was an unlock error... */ if (unlock_err) { /* Wrap the error with some headers. */ unlock_err = svn_error_quick_wrap (unlock_err, _("Error unlocking locked dirs (details follow):")); /* Append this error to the chain. */ svn_error_compose(err, unlock_err); } /* If there was a bumping error... */ if (bump_err) { /* Wrap the error with some headers. */ bump_err = svn_error_quick_wrap (bump_err, _("Error bumping revisions post-commit (details follow):")); /* Append this error to the chain. */ svn_error_compose(err, bump_err); } /* If there was a cleanup error... */ if (cleanup_err) { /* Wrap the error with some headers. */ cleanup_err = svn_error_quick_wrap (cleanup_err, _("Error in post-commit clean-up (details follow):")); /* Append this error to the chain. */ svn_error_compose(err, cleanup_err); } return err;}/* Return TRUE if one of the first PROCESSED items in COMMIT_ITEMS is a parent of PATH, return FALSE otherwise. */static svn_boolean_thave_processed_parent(apr_array_header_t *commit_items, int processed, const char *path, apr_pool_t *pool){ int i; for (i = 0; i < processed && i < commit_items->nelts; ++i) { svn_client_commit_item2_t *item = APR_ARRAY_IDX(commit_items, i, svn_client_commit_item2_t *); if (svn_path_is_child(item->path, path, pool)) return TRUE; } return FALSE;}/* Remove redundancies by removing duplicates from NONRECURSIVE_TARGETS, * and removing any target that either is, a decendant of, a path in * RECURSIVE_TARGETS. Return the result in *PUNIQUE_TARGETS. */static svn_error_t *remove_redundancies(apr_array_header_t **punique_targets, const apr_array_header_t *nonrecursive_targets, const apr_array_header_t *recursive_targets, apr_pool_t *pool){ apr_pool_t *temp_pool; apr_array_header_t *abs_recursive_targets = NULL; apr_array_header_t *abs_targets; apr_array_header_t *rel_targets; int i; if ((nonrecursive_targets->nelts <= 0) || (! punique_targets)) { /* No targets or no place to store our work means this function really has nothing to do. */ if (punique_targets) *punique_targets = NULL; return SVN_NO_ERROR; } /* Initialize our temporary pool. */ temp_pool = svn_pool_create(pool); /* Create our list of absolute paths for our "keepers" */ abs_targets = apr_array_make(temp_pool, nonrecursive_targets->nelts, sizeof(const char *)); /* Create our list of absolute paths for our recursive targets */ if (recursive_targets) { abs_recursive_targets = apr_array_make(temp_pool, recursive_targets->nelts, sizeof(const char *)); for (i = 0; i < recursive_targets->nelts; i++) { const char *rel_path = APR_ARRAY_IDX(recursive_targets, i, const char *); const char *abs_path; /* Get the absolute path for this target. */ SVN_ERR(svn_path_get_absolute(&abs_path, rel_path, temp_pool)); APR_ARRAY_PUSH(abs_recursive_targets, const char *) = abs_path; } } /* Create our list of untainted paths for our "keepers" */ rel_targets = apr_array_make(pool, nonrecursive_targets->nelts, sizeof(const char *)); /* For each target in our list we do the following: 1. Calculate its absolute path (ABS_PATH). 2. See if any of the keepers in RECURSIVE_TARGETS is a parent of, or is the same path as, ABS_PATH. If so, we ignore this target. If not, however, add this target's original path to REL_TARGETS. */ for (i = 0; i < nonrecursive_targets->nelts; i++) { const char *rel_path = APR_ARRAY_IDX(nonrecursive_targets, i, const char *); const char *abs_path; int j; svn_boolean_t keep_me; /* Get the absolute path for this target. */ SVN_ERR(svn_path_get_absolute(&abs_path, rel_path, temp_pool)); /* For each keeper in ABS_TARGETS, see if this target is the same as or a child of that keeper. */ keep_me = TRUE; if (abs_recursive_targets) { for (j = 0; j < abs_recursive_targets->nelts; j++) { const char *keeper = APR_ARRAY_IDX(abs_recursive_targets, j, const char *); /* Quit here if we find this path already in the keepers. */ if (strcmp(keeper, abs_path) == 0) { keep_me = FALSE; break; } /* Quit here if this path is a child of one of the keepers. */ if (svn_path_is_child(keeper, abs_path, temp_pool)) { keep_me = FALSE; break; } } } if (keep_me) { for (j = 0; j < abs_targets->nelts; j++) { const char *keeper = APR_ARRAY_IDX(abs_targets, j, const char *); /* Quit here if we find this path already in the keepers. */ if (strcmp(keeper, abs_path) == 0) { keep_me = FALSE; break; } } } /* If this is a new keeper, add its absolute path to ABS_TARGETS and its original path to REL_TARGETS. */ if (keep_me) { APR_ARRAY_PUSH(rel_targets, const char *) = rel_path; APR_ARRAY_PUSH(abs_targets, const char *) = abs_path; } } /* Destroy our temporary pool. */ svn_pool_destroy(temp_pool); /* Make sure we return the list of untainted keeper paths. */ *punique_targets = rel_targets; return SVN_NO_ERROR;}/* Adjust relative targets. If there is an empty string in REL_TARGETS * get the actual target anchor point. It is likely that this is one dir up * from BASE_DIR, therefor we need to prepend the name part of the actual * target to all paths in REL_TARGETS. Return the new anchor in *PBASE_DIR, * and the adjusted relative paths in *PREL_TARGETS. */static svn_error_t *adjust_rel_targets(const char **pbase_dir, apr_array_header_t **prel_targets, const char *base_dir, apr_array_header_t *rel_targets, apr_pool_t *pool){ const char *target; int i; svn_boolean_t anchor_one_up = FALSE; apr_array_header_t *new_rel_targets; for (i = 0; i < rel_targets->nelts; i++) { target = APR_ARRAY_IDX(rel_targets, i, const char *); if (target[0] == '\0') { anchor_one_up = TRUE; break; } } /* Default to not doing anything */ new_rel_targets = rel_targets; if (anchor_one_up) { const char *parent_dir, *name; SVN_ERR(svn_wc_get_actual_target(base_dir, &parent_dir, &name, pool)); if (*name) { /* Our new "grandfather directory" is the parent directory of the former one. */ base_dir = apr_pstrdup(pool, parent_dir); new_rel_targets = apr_array_make(pool, rel_targets->nelts, sizeof(name)); for (i = 0; i < rel_targets->nelts; i++) { target = APR_ARRAY_IDX(rel_targets, i, const char *); target = svn_path_join(name, target, pool); APR_ARRAY_PUSH(new_rel_targets, const char *) = target; } } } *pbase_dir = base_dir; *prel_targets = new_rel_targets; return SVN_NO_ERROR;}/* For all lock tokens in ALL_TOKENS for URLs under BASE_URL, add them to a new hashtable allocated in POOL. *RESULT is set to point to this new hash table. *RESULT will be keyed on const char * URI-decoded paths relative to BASE_URL. The lock tokens will not be duplicated. */static svn_error_t *collect_lock_tokens(apr_hash_t **result, apr_hash_t *all_tokens, const char *base_url, apr_pool_t *pool){ apr_hash_index_t *hi; size_t base_len = strlen(base_url); *result = apr_hash_make(pool); for (hi = apr_hash_first(pool, all_tokens); hi; hi = apr_hash_next(hi)) { const void *key; void *val; const char *url; const char *token; apr_hash_this(hi, &key, NULL, &val); url = key; token = val; if (strncmp(base_url, url, base_len) == 0 && (url[base_len] == '\0' || url[base_len] == '/')) { if (url[base_len] == '\0') url = ""; else url = svn_path_uri_decode(url + base_len + 1, pool); apr_hash_set(*result, url, APR_HASH_KEY_STRING, token); } } return SVN_NO_ERROR;}svn_error_t *svn_client_commit3(svn_commit_info_t **commit_info_p, const apr_array_header_t *targets, svn_boolean_t recurse, svn_boolean_t keep_locks, svn_client_ctx_t *ctx, apr_pool_t *pool){ const svn_delta_editor_t *editor; void *edit_baton; svn_ra_session_t *ra_session; const char *log_msg; const char *base_dir; const char *base_url; const char *target; apr_array_header_t *rel_targets; apr_array_header_t *dirs_to_lock; apr_array_header_t *dirs_to_lock_recursive; svn_boolean_t lock_base_dir_recursive = FALSE; apr_hash_t *committables, *lock_tokens, *tempfiles = NULL, *digests; svn_wc_adm_access_t *base_dir_access; apr_array_header_t *commit_items; svn_error_t *cmt_err = SVN_NO_ERROR, *unlock_err = SVN_NO_ERROR; svn_error_t *bump_err = SVN_NO_ERROR, *cleanup_err = SVN_NO_ERROR; svn_boolean_t commit_in_progress = FALSE; const char *display_dir = ""; int i; /* Committing URLs doesn't make sense, so error if it's tried. */ for (i = 0; i < targets->nelts; i++) { target = APR_ARRAY_IDX(targets, i, const char *); if (svn_path_is_url(target)) return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, NULL, _("'%s' is a URL, but URLs cannot be commit targets"), target); } /* Condense the target list. */ SVN_ERR(svn_path_condense_targets(&base_dir, &rel_targets, targets, recurse, pool)); /* No targets means nothing to commit, so just return. */ if (! base_dir) return SVN_NO_ERROR; /* Prepare an array to accumulate dirs to lock */ dirs_to_lock = apr_array_make(pool, 1, sizeof(target)); dirs_to_lock_recursive = apr_array_make(pool, 1, sizeof(target)); /* If we calculated only a base_dir and no relative targets, this must mean that we are being asked to commit (effectively) a single path. */ if ((! rel_targets) || (! rel_targets->nelts)) { const char *parent_dir, *name; SVN_ERR(svn_wc_get_actual_target(base_dir, &parent_dir, &name, pool)); if (*name) { svn_node_kind_t kind; /* Our new "grandfather directory" is the parent directory of the former one. */ base_dir = apr_pstrdup(pool, parent_dir); /* Make the array if it wasn't already created. */ if (! rel_targets) rel_targets = apr_array_make(pool, targets->nelts, sizeof(name)); /* Now, push this name as a relative path to our new base directory. */ APR_ARRAY_PUSH(rel_targets, const char *) = name; target = svn_path_join(base_dir, name, pool); SVN_ERR(svn_io_check_path(target, &kind, pool)); /* If the final target is a dir, we want to recursively lock it */ if (kind == svn_node_dir) { if (recurse) APR_ARRAY_PUSH(dirs_to_lock_recursive, const char *) = target; else APR_ARRAY_PUSH(dirs_to_lock, const char *) = target;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -