summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/externals.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_wc/externals.c')
-rw-r--r--subversion/libsvn_wc/externals.c202
1 files changed, 114 insertions, 88 deletions
diff --git a/subversion/libsvn_wc/externals.c b/subversion/libsvn_wc/externals.c
index 3725b22..4cbd4f0 100644
--- a/subversion/libsvn_wc/externals.c
+++ b/subversion/libsvn_wc/externals.c
@@ -68,6 +68,7 @@
* the revision if the revision is found. Set REV_IDX to the index in
* LINE_PARTS where the revision specification starts. Remove from
* LINE_PARTS the element(s) that specify the revision.
+ * Set REV_STR to the element that specifies the revision.
* PARENT_DIRECTORY_DISPLAY and LINE are given to return a nice error
* string.
*
@@ -76,6 +77,7 @@
*/
static svn_error_t *
find_and_remove_externals_revision(int *rev_idx,
+ const char **rev_str,
const char **line_parts,
int num_line_parts,
svn_wc_external_item2_t *item,
@@ -137,6 +139,8 @@ find_and_remove_externals_revision(int *rev_idx,
line_parts[j] = line_parts[j+shift_count];
line_parts[num_line_parts-shift_count] = NULL;
+ *rev_str = apr_psprintf(pool, "-r%s", digits_ptr);
+
/* Found the revision, so leave the function immediately, do
* not continue looking for additional revisions. */
return SVN_NO_ERROR;
@@ -158,23 +162,29 @@ find_and_remove_externals_revision(int *rev_idx,
}
svn_error_t *
-svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
- const char *parent_directory,
+svn_wc__parse_externals_description(apr_array_header_t **externals_p,
+ apr_array_header_t **parser_infos_p,
+ const char *defining_directory,
const char *desc,
svn_boolean_t canonicalize_url,
apr_pool_t *pool)
{
int i;
apr_array_header_t *externals = NULL;
+ apr_array_header_t *parser_infos = NULL;
apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool);
- const char *parent_directory_display = svn_path_is_url(parent_directory) ?
- parent_directory : svn_dirent_local_style(parent_directory, pool);
+ const char *defining_directory_display = svn_path_is_url(defining_directory) ?
+ defining_directory : svn_dirent_local_style(defining_directory, pool);
/* If an error occurs halfway through parsing, *externals_p should stay
* untouched. So, store the list in a local var first. */
if (externals_p)
externals = apr_array_make(pool, 1, sizeof(svn_wc_external_item2_t *));
+ if (parser_infos_p)
+ parser_infos =
+ apr_array_make(pool, 1, sizeof(svn_wc__externals_parser_info_t *));
+
for (i = 0; i < lines->nelts; i++)
{
const char *line = APR_ARRAY_IDX(lines, i, const char *);
@@ -186,10 +196,12 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
const char *token1;
svn_boolean_t token0_is_url;
svn_boolean_t token1_is_url;
+ svn_wc__externals_parser_info_t *info = NULL;
/* Index into line_parts where the revision specification
started. */
int rev_idx = -1;
+ const char *rev_str = NULL;
if ((! line) || (line[0] == '#'))
continue;
@@ -209,6 +221,9 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
item->revision.kind = svn_opt_revision_unspecified;
item->peg_revision.kind = svn_opt_revision_unspecified;
+ if (parser_infos)
+ info = apr_pcalloc(pool, sizeof(*info));
+
/*
* There are six different formats of externals:
*
@@ -231,7 +246,7 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
(SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION, NULL,
_("Error parsing %s property on '%s': '%s'"),
SVN_PROP_EXTERNALS,
- parent_directory_display,
+ defining_directory_display,
line);
/* To make it easy to check for the forms, find and remove -r N
@@ -240,9 +255,10 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
set item->revision to the parsed revision. */
/* ### ugh. stupid cast. */
SVN_ERR(find_and_remove_externals_revision(&rev_idx,
+ &rev_str,
(const char **)line_parts,
num_line_parts, item,
- parent_directory_display,
+ defining_directory_display,
line, pool));
token0 = line_parts[0];
@@ -258,7 +274,7 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
"cannot use two absolute URLs ('%s' and '%s') in an external; "
"one must be a path where an absolute or relative URL is "
"checked out to"),
- SVN_PROP_EXTERNALS, parent_directory_display, token0, token1);
+ SVN_PROP_EXTERNALS, defining_directory_display, token0, token1);
if (0 == rev_idx && token1_is_url)
return svn_error_createf
@@ -266,7 +282,7 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
_("Invalid %s property on '%s': "
"cannot use a URL '%s' as the target directory for an external "
"definition"),
- SVN_PROP_EXTERNALS, parent_directory_display, token1);
+ SVN_PROP_EXTERNALS, defining_directory_display, token1);
if (1 == rev_idx && token0_is_url)
return svn_error_createf
@@ -274,9 +290,9 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
_("Invalid %s property on '%s': "
"cannot use a URL '%s' as the target directory for an external "
"definition"),
- SVN_PROP_EXTERNALS, parent_directory_display, token0);
+ SVN_PROP_EXTERNALS, defining_directory_display, token0);
- /* The appearence of -r N or -rN forces the type of external.
+ /* The appearance of -r N or -rN forces the type of external.
If -r is at the beginning of the line or the first token is
an absolute URL or if the second token is not an absolute
URL, then the URL supports peg revisions. */
@@ -290,12 +306,34 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
SVN_ERR(svn_opt_parse_path(&item->peg_revision, &item->url,
token0, pool));
item->target_dir = token1;
+
+ if (info)
+ {
+ info->format = svn_wc__external_description_format_2;
+
+ if (rev_str)
+ info->rev_str = apr_pstrdup(pool, rev_str);
+
+ if (item->peg_revision.kind != svn_opt_revision_unspecified)
+ info->peg_rev_str = strrchr(token0, '@');
+ }
}
else
{
item->target_dir = token0;
item->url = token1;
item->peg_revision = item->revision;
+
+ if (info)
+ {
+ info->format = svn_wc__external_description_format_1;
+
+ if (rev_str)
+ {
+ info->rev_str = apr_pstrdup(pool, rev_str);
+ info->peg_rev_str = info->rev_str;
+ }
+ }
}
SVN_ERR(svn_opt_resolve_revisions(&item->peg_revision,
@@ -316,7 +354,7 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
_("Invalid %s property on '%s': "
"target '%s' is an absolute path or involves '..'"),
SVN_PROP_EXTERNALS,
- parent_directory_display,
+ defining_directory_display,
item->target_dir);
if (canonicalize_url)
@@ -333,15 +371,34 @@ svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
if (externals)
APR_ARRAY_PUSH(externals, svn_wc_external_item2_t *) = item;
+ if (parser_infos)
+ APR_ARRAY_PUSH(parser_infos, svn_wc__externals_parser_info_t *) = info;
}
if (externals_p)
*externals_p = externals;
+ if (parser_infos_p)
+ *parser_infos_p = parser_infos;
return SVN_NO_ERROR;
}
svn_error_t *
+svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
+ const char *defining_directory,
+ const char *desc,
+ svn_boolean_t canonicalize_url,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_wc__parse_externals_description(externals_p,
+ NULL,
+ defining_directory,
+ desc,
+ canonicalize_url,
+ pool));
+}
+
+svn_error_t *
svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
apr_array_header_t *externals,
apr_pool_t *pool,
@@ -405,9 +462,10 @@ struct edit_baton
const apr_array_header_t *ext_patterns;
const char *diff3cmd;
- const char *url;
const char *repos_root_url;
const char *repos_uuid;
+ const char *old_repos_relpath;
+ const char *new_repos_relpath;
const char *record_ancestor_abspath;
const char *recorded_repos_relpath;
@@ -417,8 +475,6 @@ struct edit_baton
/* Introducing a new file external */
svn_boolean_t added;
- svn_wc_conflict_resolver_func2_t conflict_func;
- void *conflict_baton;
svn_cancel_func_t cancel_func;
void *cancel_baton;
svn_wc_notify_func2_t notify_func;
@@ -431,7 +487,7 @@ struct edit_baton
const svn_checksum_t *original_checksum;
/* What we are installing now */
- const char *new_pristine_abspath;
+ svn_wc__db_install_data_t *install_data;
svn_checksum_t *new_sha1_checksum;
svn_checksum_t *new_md5_checksum;
@@ -517,7 +573,8 @@ open_file(const char *path,
*file_baton = eb;
SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &eb->original_revision,
- NULL, NULL, NULL, &eb->changed_rev,
+ &eb->old_repos_relpath, NULL, NULL,
+ &eb->changed_rev,
&eb->changed_date, &eb->changed_author,
NULL, &eb->original_checksum, NULL, NULL,
&eb->had_props, NULL, NULL,
@@ -579,11 +636,12 @@ apply_textdelta(void *file_baton,
else
src_stream = svn_stream_empty(pool);
- SVN_ERR(svn_wc__open_writable_base(&dest_stream, &eb->new_pristine_abspath,
- &eb->new_md5_checksum,
- &eb->new_sha1_checksum,
- eb->db, eb->wri_abspath,
- eb->pool, pool));
+ SVN_ERR(svn_wc__db_pristine_prepare_install(&dest_stream,
+ &eb->install_data,
+ &eb->new_sha1_checksum,
+ &eb->new_md5_checksum,
+ eb->db, eb->wri_abspath,
+ eb->pool, pool));
svn_txdelta_apply(src_stream, dest_stream, NULL, eb->local_abspath, pool,
handler, handler_baton);
@@ -603,7 +661,7 @@ change_file_prop(void *file_baton,
propchange = apr_array_push(eb->propchanges);
propchange->name = apr_pstrdup(eb->pool, name);
- propchange->value = value ? svn_string_dup(value, eb->pool) : NULL;
+ propchange->value = svn_string_dup(value, eb->pool);
return SVN_NO_ERROR;
}
@@ -656,11 +714,11 @@ close_file(void *file_baton,
behavior to the pristine store. */
if (eb->new_sha1_checksum)
{
- SVN_ERR(svn_wc__db_pristine_install(eb->db, eb->new_pristine_abspath,
+ SVN_ERR(svn_wc__db_pristine_install(eb->install_data,
eb->new_sha1_checksum,
eb->new_md5_checksum, pool));
- eb->new_pristine_abspath = NULL;
+ eb->install_data = NULL;
}
/* Merge the changes */
@@ -677,8 +735,6 @@ close_file(void *file_baton,
const svn_checksum_t *original_checksum = NULL;
svn_boolean_t added = !SVN_IS_VALID_REVNUM(eb->original_revision);
- const char *repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url,
- eb->url, pool);
if (! added)
{
@@ -767,7 +823,6 @@ close_file(void *file_baton,
{
svn_node_kind_t disk_kind;
svn_boolean_t install_pristine = FALSE;
- const char *install_from = NULL;
SVN_ERR(svn_io_check_path(eb->local_abspath, &disk_kind, pool));
@@ -832,7 +887,7 @@ close_file(void *file_baton,
{
SVN_ERR(svn_wc__wq_build_file_install(&work_item, eb->db,
eb->local_abspath,
- install_from,
+ NULL,
eb->use_commit_times, TRUE,
pool, pool));
@@ -853,14 +908,14 @@ close_file(void *file_baton,
svn_wc_conflict_version_create2(
eb->repos_root_url,
eb->repos_uuid,
- repos_relpath,
+ eb->old_repos_relpath,
eb->original_revision,
svn_node_file,
pool),
svn_wc_conflict_version_create2(
eb->repos_root_url,
eb->repos_uuid,
- repos_relpath,
+ eb->new_repos_relpath,
*eb->target_revision,
svn_node_file,
pool),
@@ -878,7 +933,7 @@ close_file(void *file_baton,
eb->db,
eb->local_abspath,
eb->wri_abspath,
- repos_relpath,
+ eb->new_repos_relpath,
eb->repos_root_url,
eb->repos_uuid,
*eb->target_revision,
@@ -947,6 +1002,7 @@ close_edit(void *edit_baton,
if (!eb->file_closed)
{
+ apr_hash_t *wcroot_iprops = NULL;
/* The file wasn't updated, but its url or revision might have...
e.g. switch between branches for relative externals.
@@ -954,53 +1010,26 @@ close_edit(void *edit_baton,
investigating when we should and shouldn't update it...
and avoid hard to debug edge cases */
- svn_node_kind_t kind;
- const char *old_repos_relpath;
- svn_revnum_t changed_rev;
- apr_time_t changed_date;
- const char *changed_author;
- const svn_checksum_t *checksum;
- apr_hash_t *pristine_props;
- const char *repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url,
- eb->url, pool);
-
- SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, NULL, &old_repos_relpath,
- NULL, NULL, &changed_rev, &changed_date,
- &changed_author, NULL, &checksum, NULL,
- NULL, NULL, &pristine_props, NULL,
- eb->db, eb->local_abspath,
- pool, pool));
+ if (eb->iprops)
+ {
+ wcroot_iprops = apr_hash_make(pool);
+ svn_hash_sets(wcroot_iprops, eb->local_abspath, eb->iprops);
+ }
- if (kind != svn_node_file)
- return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
- _("Node '%s' is no existing file external"),
- svn_dirent_local_style(eb->local_abspath,
- pool));
-
- SVN_ERR(svn_wc__db_external_add_file(
- eb->db,
- eb->local_abspath,
- eb->wri_abspath,
- repos_relpath,
- eb->repos_root_url,
- eb->repos_uuid,
- *eb->target_revision,
- pristine_props,
- eb->iprops,
- eb->changed_rev,
- eb->changed_date,
- eb->changed_author,
- checksum,
- NULL /* clear dav props */,
- eb->record_ancestor_abspath,
- eb->recorded_repos_relpath,
- eb->recorded_peg_revision,
- eb->recorded_revision,
- FALSE, NULL,
- TRUE /* keep_recorded_info */,
- NULL /* conflict_skel */,
- NULL /* work_items */,
- pool));
+ SVN_ERR(svn_wc__db_op_bump_revisions_post_update(eb->db,
+ eb->local_abspath,
+ svn_depth_infinity,
+ eb->new_repos_relpath,
+ eb->repos_root_url,
+ eb->repos_uuid,
+ *eb->target_revision,
+ apr_hash_make(pool)
+ /* exclude_relpaths */,
+ wcroot_iprops,
+ TRUE /* empty update */,
+ eb->notify_func,
+ eb->notify_baton,
+ pool));
}
return SVN_NO_ERROR;
@@ -1024,8 +1053,6 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor,
const char *recorded_url,
const svn_opt_revision_t *recorded_peg_rev,
const svn_opt_revision_t *recorded_rev,
- svn_wc_conflict_resolver_func2_t conflict_func,
- void *conflict_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
@@ -1048,9 +1075,12 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor,
eb->name = svn_dirent_basename(eb->local_abspath, NULL);
eb->target_revision = target_revision;
- eb->url = apr_pstrdup(edit_pool, url);
eb->repos_root_url = apr_pstrdup(edit_pool, repos_root_url);
eb->repos_uuid = apr_pstrdup(edit_pool, repos_uuid);
+ eb->new_repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url, url, edit_pool);
+ eb->old_repos_relpath = eb->new_repos_relpath;
+
+ eb->original_revision = SVN_INVALID_REVNUM;
eb->iprops = iprops;
@@ -1074,8 +1104,6 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor,
else
eb->recorded_revision = SVN_INVALID_REVNUM; /* Not fixed/HEAD */
- eb->conflict_func = conflict_func;
- eb->conflict_baton = conflict_baton;
eb->cancel_func = cancel_func;
eb->cancel_baton = cancel_baton;
eb->notify_func = notify_func;
@@ -1445,10 +1473,8 @@ svn_wc__external_remove(svn_wc_context_t *wc_ctx,
else
{
SVN_ERR(svn_wc__db_base_remove(wc_ctx->db, local_abspath,
- FALSE /* keep_as_working */,
- TRUE /* queue_deletes */,
- FALSE /* remove_locks */,
- SVN_INVALID_REVNUM,
+ FALSE, TRUE, FALSE,
+ 0,
NULL, NULL, scratch_pool));
SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath,
cancel_func, cancel_baton,
@@ -1591,7 +1617,7 @@ svn_wc__resolve_relative_external_url(const char **resolved_url,
apr_pstrndup(scratch_pool, url, num_leading_slashes),
svn_relpath_canonicalize(url + num_leading_slashes,
scratch_pool),
- (char*)NULL);
+ SVN_VA_NULL);
}
else
{
@@ -1698,7 +1724,7 @@ svn_wc__resolve_relative_external_url(const char **resolved_url,
SVN_ERR(uri_scheme(&scheme, repos_root_url, scratch_pool));
*resolved_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool, scheme,
- ":", url, (char *)NULL),
+ ":", url, SVN_VA_NULL),
result_pool);
return SVN_NO_ERROR;
}