Author: danielsh
Date: Fri Sep 25 23:26:59 2015
New Revision: 1705385
URL: http://svn.apache.org/viewvc?rev=1705385&view=rev
Log:
On the patch-exec branch, sync with trunk@1705384.
* subversion/libsvn_client/patch.c
(init_patch_target): Update for removal of 'has_prop_changes' local variable.
Modified:
subversion/branches/patch-exec/ (props changed)
subversion/branches/patch-exec/subversion/include/svn_dav.h
subversion/branches/patch-exec/subversion/libsvn_client/client.h
subversion/branches/patch-exec/subversion/libsvn_client/patch.c
subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c
subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c
subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c
subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c
subversion/branches/patch-exec/subversion/libsvn_fs_x/ (props changed)
subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c
subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c
subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h
subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c
subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c
subversion/branches/patch-exec/subversion/libsvn_subr/auth.c
subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c
subversion/branches/patch-exec/subversion/mod_dav_svn/version.c
subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
subversion/branches/patch-exec/tools/dist/backport/merger.py
subversion/branches/patch-exec/tools/dist/backport/status.py
Propchange: subversion/branches/patch-exec/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Sep 25 23:26:59 2015
@@ -94,4 +94,4 @@
/subversion/branches/verify-at-commit:1462039-1462408
/subversion/branches/verify-keep-going:1439280-1546110
/subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1692717-1704588
+/subversion/trunk:1692717-1705384
Modified: subversion/branches/patch-exec/subversion/include/svn_dav.h
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/include/svn_dav.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/include/svn_dav.h (original)
+++ subversion/branches/patch-exec/subversion/include/svn_dav.h Fri Sep 25
23:26:59 2015
@@ -386,6 +386,15 @@ extern "C" {
#define SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS\
SVN_DAV_PROP_NS_DAV "svn/reverse-file-revs"
+/** Presence of this in a DAV header in an OPTIONS response indicates
+ * that the transmitter (in this case, the server) knows how to handle
+ * svndiff1 format encoding.
+ *
+ * @since New in 1.10.
+ */
+#define SVN_DAV_NS_DAV_SVN_SVNDIFF1\
+ SVN_DAV_PROP_NS_DAV "svn/svndiff1"
+
/** @} */
Modified: subversion/branches/patch-exec/subversion/libsvn_client/client.h
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_client/client.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/client.h (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/client.h Fri Sep 25
23:26:59 2015
@@ -1072,9 +1072,13 @@ svn_client__ensure_revprop_table(apr_has
EXPAND_KEYWORDS operates as per the EXPAND argument to
svn_subst_stream_translated, which see. If NORMALIZE_EOLS is TRUE and
LOCAL_ABSPATH requires translation, then normalize the line endings in
- *NORMAL_STREAM.
+ *NORMAL_STREAM to "\n" if the stream has svn:eol-style set.
- Uses SCRATCH_POOL for temporary allocations. */
+ Note that this IS NOT the repository normal form of the stream as that
+ would use "\r\n" if set to CRLF and "\r" if set to CR.
+
+ The stream is allocated in RESULT_POOL and temporary SCRATCH_POOL is
+ used for temporary allocations. */
svn_error_t *
svn_client__get_normalized_stream(svn_stream_t **normal_stream,
svn_wc_context_t *wc_ctx,
Modified: subversion/branches/patch-exec/subversion/libsvn_client/patch.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_client/patch.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/patch.c Fri Sep 25
23:26:59 2015
@@ -380,7 +380,7 @@ obtain_eol_and_keywords_for_file(apr_has
static svn_error_t *
resolve_target_path(patch_target_t *target,
const char *path_from_patchfile,
- const char *wcroot_abspath,
+ const char *root_abspath,
int strip_count,
svn_boolean_t has_text_changes,
svn_wc_context_t *wc_ctx,
@@ -413,7 +413,7 @@ resolve_target_path(patch_target_t *targ
if (svn_dirent_is_absolute(stripped_path))
{
- target->local_relpath = svn_dirent_is_child(wcroot_abspath,
+ target->local_relpath = svn_dirent_is_child(root_abspath,
stripped_path,
result_pool);
@@ -433,9 +433,9 @@ resolve_target_path(patch_target_t *targ
}
/* Make sure the path is secure to use. We want the target to be inside
- * of the working copy and not be fooled by symlinks it might contain. */
+ * the locked tree and not be fooled by symlinks it might contain. */
SVN_ERR(svn_dirent_is_under_root(&under_root,
- &target->local_abspath, wcroot_abspath,
+ &target->local_abspath, root_abspath,
target->local_relpath, result_pool));
if (! under_root)
@@ -486,19 +486,23 @@ resolve_target_path(patch_target_t *targ
if (target->locally_deleted)
{
const char *moved_to_abspath;
+ const char *op_root_abspath;
- SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
+ SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, &op_root_abspath,
wc_ctx, target->local_abspath,
result_pool, scratch_pool));
- /* ### BUG: moved_to_abspath contains the target where the op-root was
- ### moved to... not the target itself! */
if (moved_to_abspath)
{
target->local_abspath = moved_to_abspath;
- target->local_relpath = svn_dirent_skip_ancestor(wcroot_abspath,
- moved_to_abspath);
- SVN_ERR_ASSERT(target->local_relpath &&
- target->local_relpath[0] != '\0');
+ target->local_relpath = svn_dirent_skip_ancestor(root_abspath,
+ moved_to_abspath);
+
+ if (!target->local_relpath || target->local_relpath[0] == '\0')
+ {
+ /* The target path is outside of the patch area. Skip it. */
+ target->skipped = TRUE;
+ return SVN_NO_ERROR;
+ }
/* As far as we are concerned this target is not locally deleted. */
target->locally_deleted = FALSE;
@@ -544,7 +548,7 @@ readline_prop(void *baton, svn_stringbuf
svn_boolean_t *eof, apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- prop_read_baton_t *b = (prop_read_baton_t *)baton;
+ prop_read_baton_t *b = baton;
svn_stringbuf_t *str = NULL;
const char *c;
svn_boolean_t found_eof;
@@ -609,7 +613,8 @@ readline_prop(void *baton, svn_stringbuf
static svn_error_t *
tell_prop(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool)
{
- prop_read_baton_t *b = (prop_read_baton_t *)baton;
+ prop_read_baton_t *b = baton;
+
*offset = b->offset;
return SVN_NO_ERROR;
}
@@ -619,7 +624,8 @@ tell_prop(void *baton, apr_off_t *offset
static svn_error_t *
seek_prop(void *baton, apr_off_t offset, apr_pool_t *scratch_pool)
{
- prop_read_baton_t *b = (prop_read_baton_t *)baton;
+ prop_read_baton_t *b = baton;
+
b->offset = offset;
return SVN_NO_ERROR;
}
@@ -630,7 +636,8 @@ static svn_error_t *
write_prop(void *baton, const char *buf, apr_size_t len,
apr_pool_t *scratch_pool)
{
- svn_stringbuf_t *patched_value = (svn_stringbuf_t *)baton;
+ svn_stringbuf_t *patched_value = baton;
+
svn_stringbuf_appendbytes(patched_value, buf, len);
return SVN_NO_ERROR;
}
@@ -720,71 +727,15 @@ readline_file(void *baton, svn_stringbuf
svn_boolean_t *eof, apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- apr_file_t *file = (apr_file_t *)baton;
- svn_stringbuf_t *str = NULL;
- apr_size_t numbytes;
- char c;
- svn_boolean_t found_eof;
+ apr_file_t *file = baton;
- /* Read bytes into STR up to and including, but not storing,
- * the next EOL sequence. */
- *eol_str = NULL;
- numbytes = 1;
- found_eof = FALSE;
- while (!found_eof)
- {
- SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
- &found_eof, scratch_pool));
- if (numbytes != 1)
- {
- found_eof = TRUE;
- break;
- }
-
- if (c == '\n')
- {
- *eol_str = "\n";
- }
- else if (c == '\r')
- {
- *eol_str = "\r";
+ SVN_ERR(svn_io_file_readline(file, line, eol_str, eof, APR_SIZE_MAX,
+ result_pool, scratch_pool));
- if (!found_eof)
- {
- apr_off_t pos;
-
- /* Check for "\r\n" by peeking at the next byte. */
- pos = 0;
- SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
- SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
- &found_eof, scratch_pool));
- if (numbytes == 1 && c == '\n')
- {
- *eol_str = "\r\n";
- }
- else
- {
- /* Pretend we never peeked. */
- SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
- found_eof = FALSE;
- numbytes = 1;
- }
- }
- }
- else
- {
- if (str == NULL)
- str = svn_stringbuf_create_ensure(80, result_pool);
- svn_stringbuf_appendbyte(str, c);
- }
-
- if (*eol_str)
- break;
- }
-
- if (eof)
- *eof = found_eof;
- *line = str;
+ if (!(*line)->len)
+ *line = NULL;
+ else
+ *eof = FALSE;
return SVN_NO_ERROR;
}
@@ -795,7 +746,8 @@ readline_file(void *baton, svn_stringbuf
static svn_error_t *
tell_file(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool)
{
- apr_file_t *file = (apr_file_t *)baton;
+ apr_file_t *file = baton;
+
*offset = 0;
SVN_ERR(svn_io_file_seek(file, APR_CUR, offset, scratch_pool));
return SVN_NO_ERROR;
@@ -806,7 +758,8 @@ tell_file(void *baton, apr_off_t *offset
static svn_error_t *
seek_file(void *baton, apr_off_t offset, apr_pool_t *scratch_pool)
{
- apr_file_t *file = (apr_file_t *)baton;
+ apr_file_t *file = baton;
+
SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool));
return SVN_NO_ERROR;
}
@@ -817,7 +770,8 @@ static svn_error_t *
write_file(void *baton, const char *buf, apr_size_t len,
apr_pool_t *scratch_pool)
{
- apr_file_t *file = (apr_file_t *)baton;
+ apr_file_t *file = baton;
+
SVN_ERR(svn_io_file_write_full(file, buf, len, &len, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1010,7 +964,7 @@ contradictory_executability(const svn_pa
static svn_error_t *
init_patch_target(patch_target_t **patch_target,
const svn_patch_t *patch,
- const char *wcroot_abspath,
+ const char *root_abspath,
svn_wc_context_t *wc_ctx, int strip_count,
svn_boolean_t remove_tempfiles,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -1018,25 +972,6 @@ init_patch_target(patch_target_t **patch
patch_target_t *target;
target_content_t *content;
svn_boolean_t has_text_changes = FALSE;
- svn_boolean_t has_prop_changes = FALSE;
-
- {
- apr_hash_index_t *hi;
-
- for (hi = apr_hash_first(scratch_pool, patch->prop_patches);
- hi;
- hi = apr_hash_next(hi))
- {
- svn_prop_patch_t *prop_patch = apr_hash_this_val(hi);
- if (! has_prop_changes)
- has_prop_changes = prop_patch->hunks->nelts > 0;
- else
- break;
- }
- }
-
- if (patch->new_executable_p != svn_tristate_unknown)
- has_prop_changes = TRUE;
has_text_changes = ((patch->hunks && patch->hunks->nelts > 0)
|| patch->binary_patch);
@@ -1057,9 +992,12 @@ init_patch_target(patch_target_t **patch
target->kind_on_disk = svn_node_none;
target->content = content;
target->prop_targets = apr_hash_make(result_pool);
+ if (patch->new_executable_p != svn_tristate_unknown)
+ /* May also be set by apply_hunk(). */
+ target->has_prop_changes = TRUE;
SVN_ERR(resolve_target_path(target, choose_target_filename(patch),
- wcroot_abspath, strip_count, has_text_changes,
+ root_abspath, strip_count, has_text_changes,
wc_ctx, result_pool, scratch_pool));
*patch_target = target;
if (! target->skipped)
@@ -1137,7 +1075,7 @@ init_patch_target(patch_target_t **patch
if (svn_dirent_is_absolute(move_target_path))
{
- move_target_relpath = svn_dirent_is_child(wcroot_abspath,
+ move_target_relpath = svn_dirent_is_child(root_abspath,
move_target_path,
scratch_pool);
if (! move_target_relpath)
@@ -1155,7 +1093,7 @@ init_patch_target(patch_target_t **patch
/* Make sure the move target path is secure to use. */
SVN_ERR(svn_dirent_is_under_root(&under_root,
&target->move_target_abspath,
- wcroot_abspath,
+ root_abspath,
move_target_relpath, result_pool));
if (! under_root)
{
@@ -2397,7 +2335,6 @@ apply_one_patch(patch_target_t **patch_t
apr_hash_index_t *hash_index;
svn_linenum_t previous_offset = 0;
svn_boolean_t has_text_changes = FALSE;
- svn_boolean_t has_prop_changes = FALSE;
SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
remove_tempfiles, result_pool, scratch_pool));
@@ -2501,32 +2438,49 @@ apply_one_patch(patch_target_t **patch_t
}
else if (patch->binary_patch)
{
-#ifdef SVN_DEBUG
- svn_stream_t *tmp;
-
- /* ### Dummy code that just reads the two streams in the patch file */
- tmp = svn_diff_get_binary_diff_result_stream(patch->binary_patch,
- iterpool);
+ svn_stream_t *orig_stream;
+ svn_boolean_t same;
- SVN_ERR(svn_stream_copy3(tmp, svn_stream_empty(iterpool),
- NULL, NULL,
- iterpool));
+ if (target->file)
+ orig_stream = svn_stream_from_aprfile2(target->file, TRUE, iterpool);
+ else
+ orig_stream = svn_stream_empty(iterpool);
- tmp = svn_diff_get_binary_diff_original_stream(patch->binary_patch,
- iterpool);
+ SVN_ERR(svn_stream_contents_same2(
+ &same, orig_stream,
+ svn_diff_get_binary_diff_original_stream(patch->binary_patch,
+ iterpool),
+ iterpool));
+ svn_pool_clear(iterpool);
- SVN_ERR(svn_stream_copy3(tmp, svn_stream_empty(iterpool),
- NULL, NULL,
- iterpool));
+ if (same)
+ {
+ /* The file in the working copy is identical to the one expected by
+ the patch... So we can write the result stream; no fuzz,
+ just a 100% match */
+
+ SVN_ERR(svn_stream_copy3(
+ svn_diff_get_binary_diff_result_stream(patch->binary_patch,
+ iterpool),
+ svn_stream_from_aprfile2(target->patched_file, TRUE,
+ iterpool),
+ cancel_func, cancel_baton,
+ iterpool));
- /* ### TODO:
- - write the patched version and set has_text_changes = TRUE;
- - or: write+notify rejection
- - or: set skip (which also skips property changes)
+ has_text_changes = TRUE;
+ target->has_text_changes = TRUE;
+ }
+ else
+ {
+ /* ### TODO: Implement a proper reject of a binary patch
- Doing nothing just ignores the patchset (<= 1.9.x behaviour)
- */
-#endif
+ This should at least setup things for a proper notification,
+ and perhaps install a normal text conflict. Unlike normal unified
+ diff based patches we have all the versions we would need for
+ that in a much easier format than can be obtained from the patch
+ file. */
+ target->skipped = TRUE;
+ }
}
else if (target->move_target_abspath)
{
@@ -2545,12 +2499,12 @@ apply_one_patch(patch_target_t **patch_t
/* Copy any remaining lines to target. (read: all lines) */
SVN_ERR(copy_lines_to_target(target->content, 0, scratch_pool));
if (!target->content->eof)
- {
- /* We could not copy the entire target file to the temporary
- * file, and would truncate the target if we copied the
- * temporary file on top of it. Skip this target. */
- target->skipped = TRUE;
- }
+ {
+ /* We could not copy the entire target file to the temporary
+ * file, and would truncate the target if we copied the
+ * temporary file on top of it. Skip this target. */
+ target->skipped = TRUE;
+ }
has_text_changes = TRUE;
}
}
@@ -2570,8 +2524,6 @@ apply_one_patch(patch_target_t **patch_t
if (! strcmp(prop_name, SVN_PROP_SPECIAL))
target->is_special = TRUE;
- has_prop_changes = TRUE;
-
/* We'll store matched hunks in prop_content. */
prop_target = svn_hash_gets(target->prop_targets, prop_name);
@@ -2765,6 +2717,9 @@ apply_one_patch(patch_target_t **patch_t
/* Try to create missing parent directories for TARGET in the working copy
* rooted at ABS_WC_PATH, and add the parents to version control.
* If the parents cannot be created, mark the target as skipped.
+ *
+ * In dry run mode record missing parents in ALREADY_ADDED
+ *
* Use client context CTX. If DRY_RUN is true, do not create missing
* parents but issue notifications only.
* Use SCRATCH_POOL for temporary allocations. */
@@ -2773,6 +2728,7 @@ create_missing_parents(patch_target_t *t
const char *abs_wc_path,
svn_client_ctx_t *ctx,
svn_boolean_t dry_run,
+ apr_hash_t *already_added,
apr_pool_t *scratch_pool)
{
const char *local_abspath;
@@ -2861,17 +2817,25 @@ create_missing_parents(patch_target_t *t
scratch_pool);
if (dry_run)
{
- if (ctx->notify_func2)
+ if (!svn_hash_gets(already_added, local_abspath))
{
- /* Just do notification. */
- svn_wc_notify_t *notify;
- notify = svn_wc_create_notify(local_abspath,
- svn_wc_notify_add,
- iterpool);
- notify->kind = svn_node_dir;
- ctx->notify_func2(ctx->notify_baton2, notify,
- iterpool);
- }
+ svn_hash_sets(already_added,
+ apr_pstrdup(apr_hash_pool_get(already_added),
+ local_abspath),
+ "");
+
+ if (ctx->notify_func2)
+ {
+ /* Just do notification. */
+ svn_wc_notify_t *notify;
+ notify = svn_wc_create_notify(local_abspath,
+ svn_wc_notify_add,
+ iterpool);
+ notify->kind = svn_node_dir;
+ ctx->notify_func2(ctx->notify_baton2, notify,
+ iterpool);
+ }
+ }
}
else
{
@@ -2898,12 +2862,17 @@ create_missing_parents(patch_target_t *t
/* Install a patched TARGET into the working copy at ABS_WC_PATH.
* Use client context CTX to retrieve WC_CTX, and possibly doing
- * notifications. If DRY_RUN is TRUE, don't modify the working copy.
+ * notifications.
+ *
+ * Pass on ALREADY_ADDED to allow recording already added ancestors
+ * in dry-run mode.
+ *
+ * If DRY_RUN is TRUE, don't modify the working copy.
* Do temporary allocations in POOL. */
static svn_error_t *
install_patched_target(patch_target_t *target, const char *abs_wc_path,
svn_client_ctx_t *ctx, svn_boolean_t dry_run,
- apr_pool_t *pool)
+ apr_hash_t *already_added, apr_pool_t *pool)
{
if (target->deleted)
{
@@ -2952,7 +2921,7 @@ install_patched_target(patch_target_t *t
}
else
SVN_ERR(create_missing_parents(target, abs_wc_path, ctx,
- dry_run, pool));
+ dry_run, already_added, pool));
}
else
@@ -3350,7 +3319,7 @@ static svn_error_t *
apply_patches(/* The path to the patch file. */
const char *patch_abspath,
/* The abspath to the working copy the patch should be applied
to. */
- const char *abs_wc_path,
+ const char *root_abspath,
/* Indicates whether we're doing a dry run. */
svn_boolean_t dry_run,
/* Number of leading components to strip from patch target
paths. */
@@ -3372,6 +3341,7 @@ apply_patches(/* The path to the patch f
apr_pool_t *iterpool;
svn_patch_file_t *patch_file;
apr_array_header_t *targets_info;
+ apr_hash_t *already_added = apr_hash_make(scratch_pool);
/* Try to open the patch file. */
SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, scratch_pool));
@@ -3394,7 +3364,7 @@ apply_patches(/* The path to the patch f
{
patch_target_t *target;
- SVN_ERR(apply_one_patch(&target, patch, abs_wc_path,
+ SVN_ERR(apply_one_patch(&target, patch, root_abspath,
ctx->wc_ctx, strip_count,
ignore_whitespace, remove_tempfiles,
patch_func, patch_baton,
@@ -3418,21 +3388,28 @@ apply_patches(/* The path to the patch f
|| target->added
|| target->move_target_abspath
|| target->deleted)
- SVN_ERR(install_patched_target(target, abs_wc_path,
- ctx, dry_run, iterpool));
+ SVN_ERR(install_patched_target(target, root_abspath,
+ ctx, dry_run,
+ already_added, iterpool));
if (target->has_prop_changes && (!target->deleted))
SVN_ERR(install_patched_prop_targets(target, ctx,
dry_run, iterpool));
SVN_ERR(write_out_rejected_hunks(target, dry_run, iterpool));
+
+ if (target->added)
+ svn_hash_sets(already_added,
+ apr_pstrdup(scratch_pool,
+ target->local_abspath),
+ "");
}
SVN_ERR(send_patch_notification(target, ctx, iterpool));
if (target->deleted && !target->skipped)
{
SVN_ERR(check_ancestor_delete(target_info->local_abspath,
- targets_info, abs_wc_path,
+ targets_info, root_abspath,
dry_run, ctx,
scratch_pool, iterpool));
}
Modified: subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c
(original)
+++ subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c Fri Sep
25 23:26:59 2015
@@ -115,7 +115,7 @@ svn_diff__base85_decode_line(char *outpu
apr_pool_t *scratch_pool)
{
{
- apr_size_t expected_data = (output_len + 3) / 4 * 5;
+ apr_ssize_t expected_data = (output_len + 3) / 4 * 5;
if (base85_len != expected_data)
return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL,
Modified: subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c
(original)
+++ subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c Fri Sep
25 23:26:59 2015
@@ -85,6 +85,10 @@ struct svn_diff_hunk_t {
/* Number of lines of leading and trailing hunk context. */
svn_linenum_t leading_context;
svn_linenum_t trailing_context;
+
+ /* Did we see a 'file does not end with eol' marker in this hunk? */
+ svn_boolean_t original_no_final_eol;
+ svn_boolean_t modified_no_final_eol;
};
struct svn_diff_binary_patch_t {
@@ -623,7 +627,8 @@ parse_hunk_header(const char *header, sv
* Leading unidiff symbols ('+', '-', and ' ') are removed from the line,
* Any lines commencing with the VERBOTEN character are discarded.
* VERBOTEN should be '+' or '-', depending on which form of hunk text
- * is being read.
+ * is being read. NO_FINAL_EOL declares if the hunk contains a no final
+ * EOL marker.
*
* All other parameters are as in svn_diff_hunk_readline_original_text()
* and svn_diff_hunk_readline_modified_text().
@@ -635,6 +640,7 @@ hunk_readline_original_or_modified(apr_f
const char **eol,
svn_boolean_t *eof,
char verboten,
+ svn_boolean_t no_final_eol,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -642,13 +648,16 @@ hunk_readline_original_or_modified(apr_f
svn_boolean_t filtered;
apr_off_t pos;
svn_stringbuf_t *str;
+ const char *eol_p;
+
+ if (!eol)
+ eol = &eol_p;
if (range->current >= range->end)
{
/* We're past the range. Indicate that no bytes can be read. */
*eof = TRUE;
- if (eol)
- *eol = NULL;
+ *eol = NULL;
*stringbuf = svn_stringbuf_create_empty(result_pool);
return SVN_NO_ERROR;
}
@@ -671,6 +680,7 @@ hunk_readline_original_or_modified(apr_f
{
/* EOF, return an empty string. */
*stringbuf = svn_stringbuf_create_ensure(0, result_pool);
+ *eol = NULL;
}
else if (str->data[0] == '+' || str->data[0] == '-' || str->data[0] == ' ')
{
@@ -679,10 +689,34 @@ hunk_readline_original_or_modified(apr_f
}
else
{
- /* Return the line as-is. */
+ /* Return the line as-is. Handle as a chopped leading spaces */
*stringbuf = svn_stringbuf_dup(str, result_pool);
}
+ if (!filtered && *eof && !*eol && !no_final_eol && *str->data)
+ {
+ /* Ok, we miss a final EOL in the patch file, but didn't see a
+ no eol marker line.
+
+ We should report that we had an EOL or the patch code will
+ misbehave (and it knows nothing about no eol markers) */
+
+ if (eol != &eol_p)
+ {
+ apr_off_t start = 0;
+
+ SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool));
+
+ SVN_ERR(svn_io_file_readline(file, &str, eol, NULL, APR_SIZE_MAX,
+ scratch_pool, scratch_pool));
+
+ /* Every patch file that has hunks has at least one EOL*/
+ SVN_ERR_ASSERT(*eol != NULL);
+ }
+
+ *eof = FALSE;
+ /* Fall through to seek back to the right location */
+ }
SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
return SVN_NO_ERROR;
@@ -703,6 +737,9 @@ svn_diff_hunk_readline_original_text(svn
&hunk->original_text_range,
stringbuf, eol, eof,
hunk->patch->reverse ? '-' : '+',
+ hunk->patch->reverse
+ ? hunk->modified_no_final_eol
+ : hunk->original_no_final_eol,
result_pool, scratch_pool));
}
@@ -721,6 +758,9 @@ svn_diff_hunk_readline_modified_text(svn
&hunk->modified_text_range,
stringbuf, eol, eof,
hunk->patch->reverse ? '+' : '-',
+ hunk->patch->reverse
+ ? hunk->original_no_final_eol
+ : hunk->modified_no_final_eol,
result_pool, scratch_pool));
}
@@ -735,13 +775,16 @@ svn_diff_hunk_readline_diff_text(svn_dif
svn_stringbuf_t *line;
apr_size_t max_len;
apr_off_t pos;
+ const char *eol_p;
+
+ if (!eol)
+ eol = &eol_p;
if (hunk->diff_text_range.current >= hunk->diff_text_range.end)
{
/* We're past the range. Indicate that no bytes can be read. */
*eof = TRUE;
- if (eol)
- *eol = NULL;
+ *eol = NULL;
*stringbuf = svn_stringbuf_create_empty(result_pool);
return SVN_NO_ERROR;
}
@@ -757,6 +800,37 @@ svn_diff_hunk_readline_diff_text(svn_dif
hunk->diff_text_range.current = 0;
SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR,
&hunk->diff_text_range.current, scratch_pool));
+
+ if (*eof && !*eol && *line->data)
+ {
+ /* Ok, we miss a final EOL in the patch file, but didn't see a
+ no eol marker line.
+
+ We should report that we had an EOL or the patch code will
+ misbehave (and it knows nothing about no eol markers) */
+
+ if (eol != &eol_p)
+ {
+ /* Lets pick the first eol we find in our patch file */
+ apr_off_t start = 0;
+ svn_stringbuf_t *str;
+
+ SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &start,
+ scratch_pool));
+
+ SVN_ERR(svn_io_file_readline(hunk->apr_file, &str, eol, NULL,
+ APR_SIZE_MAX,
+ scratch_pool, scratch_pool));
+
+ /* Every patch file that has hunks has at least one EOL*/
+ SVN_ERR_ASSERT(*eol != NULL);
+ }
+
+ *eof = FALSE;
+
+ /* Fall through to seek back to the right location */
+ }
+
SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &pos, scratch_pool));
if (hunk->patch->reverse)
@@ -963,6 +1037,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
apr_off_t start, end;
apr_off_t original_end;
apr_off_t modified_end;
+ svn_boolean_t original_no_final_eol = FALSE;
+ svn_boolean_t modified_no_final_eol = FALSE;
svn_linenum_t original_lines;
svn_linenum_t modified_lines;
svn_linenum_t leading_context;
@@ -1060,6 +1136,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
}
+ /* Set for the type and context by using != the other type */
+ if (last_line_type != modified_line)
+ original_no_final_eol = TRUE;
+ if (last_line_type != original_line)
+ modified_no_final_eol = TRUE;
continue;
}
@@ -1187,14 +1268,16 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
result_pool));
if (*prop_name)
- *prop_operation = svn_diff_op_added;
+ *prop_operation = (patch->reverse ? svn_diff_op_deleted
+ : svn_diff_op_added);
}
else if (starts_with(line->data, "Deleted: "))
{
SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
result_pool));
if (*prop_name)
- *prop_operation = svn_diff_op_deleted;
+ *prop_operation = (patch->reverse ? svn_diff_op_added
+ : svn_diff_op_deleted);
}
else if (starts_with(line->data, "Modified: "))
{
@@ -1235,6 +1318,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
(*hunk)->modified_text_range.start = start;
(*hunk)->modified_text_range.current = start;
(*hunk)->modified_text_range.end = modified_end;
+ (*hunk)->original_no_final_eol = original_no_final_eol;
+ (*hunk)->modified_no_final_eol = modified_no_final_eol;
}
else
/* Something went wrong, just discard the result. */
@@ -1793,6 +1878,7 @@ parse_hunks(svn_patch_t *patch, apr_file
static svn_error_t *
parse_binary_patch(svn_patch_t *patch, apr_file_t *apr_file,
+ svn_boolean_t reverse,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -1826,7 +1912,7 @@ parse_binary_patch(svn_patch_t *patch, a
char c = line->data[0];
/* 66 = len byte + (52/4*5) chars */
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
+ if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
&& line->len <= 66
&& !strchr(line->data, ':')
&& !strchr(line->data, ' '))
@@ -1893,6 +1979,22 @@ parse_binary_patch(svn_patch_t *patch, a
patch->binary_patch = bpatch; /* SUCCESS */
}
+ /* Reverse patch if requested */
+ if (reverse && patch->binary_patch)
+ {
+ apr_off_t tmp_start = bpatch->src_start;
+ apr_off_t tmp_end = bpatch->src_end;
+ svn_filesize_t tmp_filesize = bpatch->src_filesize;
+
+ bpatch->src_start = bpatch->dst_start;
+ bpatch->src_end = bpatch->dst_end;
+ bpatch->src_filesize = bpatch->dst_filesize;
+
+ bpatch->dst_start = tmp_start;
+ bpatch->dst_end = tmp_end;
+ bpatch->dst_filesize = tmp_filesize;
+ }
+
return SVN_NO_ERROR;
}
@@ -1924,6 +2026,7 @@ static struct transition transitions[] =
{"deleted file ", state_git_diff_seen, git_deleted_file},
{"GIT binary patch", state_git_diff_seen, binary_patch_start},
+ {"GIT binary patch", state_git_tree_seen, binary_patch_start},
};
svn_error_t *
@@ -2038,6 +2141,22 @@ svn_diff_parse_next_patch(svn_patch_t **
temp = patch->old_filename;
patch->old_filename = patch->new_filename;
patch->new_filename = temp;
+
+ switch (patch->operation)
+ {
+ case svn_diff_op_added:
+ patch->operation = svn_diff_op_deleted;
+ break;
+ case svn_diff_op_deleted:
+ patch->operation = svn_diff_op_added;
+ break;
+
+ /* ### case svn_diff_op_copied:
+ ### case svn_diff_op_moved:*/
+
+ case svn_diff_op_modified:
+ break; /* Stays modify */
+ }
}
if (patch->old_filename == NULL || patch->new_filename == NULL)
@@ -2049,7 +2168,7 @@ svn_diff_parse_next_patch(svn_patch_t **
{
if (state == state_binary_patch_found)
{
- SVN_ERR(parse_binary_patch(patch, patch_file->apr_file,
+ SVN_ERR(parse_binary_patch(patch, patch_file->apr_file, reverse,
result_pool, iterpool));
/* And fall through in property parsing */
}
Modified: subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c Fri Sep 25
23:26:59 2015
@@ -108,7 +108,7 @@ txn_body_lock(void *baton, trail_t *trai
SVN_ERR(svn_fs_base__get_path_kind(&kind, args->path, trail, trail->pool));
/* Until we implement directory locks someday, we only allow locks
- on files or non-existent paths. */
+ on files. */
if (kind == svn_node_dir)
return SVN_FS__ERR_NOT_FILE(trail->fs, args->path);
Modified: subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c Fri Sep 25
23:26:59 2015
@@ -847,7 +847,7 @@ lock_body(void *baton, apr_pool_t *pool)
apr_pool_t *iterpool = svn_pool_create(pool);
/* Until we implement directory locks someday, we only allow locks
- on files or non-existent paths. */
+ on files. */
/* Use fs->vtable->foo instead of svn_fs_foo to avoid circular
library dependencies, which are not portable. */
SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool));
Propchange: subversion/branches/patch-exec/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Sep 25 23:26:59 2015
@@ -93,4 +93,4 @@
/subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
/subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1653608,
1658482
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1692717-1704588
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1692717-1705384
Modified: subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c Fri Sep 25
23:26:59 2015
@@ -868,7 +868,7 @@ lock_body(void *baton,
apr_pool_t *iterpool = svn_pool_create(pool);
/* Until we implement directory locks someday, we only allow locks
- on files or non-existent paths. */
+ on files. */
/* Use fs->vtable->foo instead of svn_fs_foo to avoid circular
library dependencies, which are not portable. */
SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool));
Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c
(original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c Fri Sep
25 23:26:59 2015
@@ -226,6 +226,12 @@ capabilities_headers_iterator_callback(v
{
session->supports_rev_rsrc_replay = TRUE;
}
+ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals))
+ {
+ /* Use compressed svndiff1 format for servers that properly
+ advertise this capability (Subversion 1.10 and greater). */
+ session->supports_svndiff1 = TRUE;
+ }
}
/* SVN-specific headers -- if present, server supports HTTP protocol v2 */
@@ -243,7 +249,8 @@ capabilities_headers_iterator_callback(v
apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
}
- /* Use compressed svndiff1 format for servers that speak HTTPv2.
+ /* Use compressed svndiff1 format for servers that speak HTTPv2,
+ in addition to servers that send SVN_DAV_NS_DAV_SVN_SVNDIFF1.
Apache HTTPd + mod_dav_svn servers support svndiff1, beginning
from Subversion 1.4, but they do not advertise this capability.
Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h
(original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h Fri Sep
25 23:26:59 2015
@@ -1548,6 +1548,17 @@ svn_ra_serf__create_bucket_with_eagain(c
apr_size_t len,
serf_bucket_alloc_t *allocator);
+/* Parse a given URL_STR, fill in all supplied fields of URI
+ * structure.
+ *
+ * This function is a compatibility wrapper around apr_uri_parse().
+ * Different apr-util versions set apr_uri_t.path to either NULL or ""
+ * for root paths, and serf expects to see "/". This function always
+ * sets URI.path to "/" for these paths. */
+svn_error_t *
+svn_ra_serf__uri_parse(apr_uri_t *uri,
+ const char *url_str,
+ apr_pool_t *result_pool);
#if defined(SVN_DEBUG)
Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c Fri Sep 25
23:26:59 2015
@@ -64,7 +64,7 @@ ra_serf_version(void)
#define RA_SERF_DESCRIPTION_VER \
N_("Module for accessing a repository via WebDAV protocol using serf.\n" \
- " - using serf %d.%d.%d")
+ " - using serf %d.%d.%d (compiled with %d.%d.%d)")
/* Implements svn_ra__vtable_t.get_description(). */
static const char *
@@ -73,7 +73,12 @@ ra_serf_get_description(apr_pool_t *pool
int major, minor, patch;
serf_lib_version(&major, &minor, &patch);
- return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER), major, minor, patch);
+ return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER),
+ major, minor, patch,
+ SERF_MAJOR_VERSION,
+ SERF_MINOR_VERSION,
+ SERF_PATCH_VERSION
+ );
}
/* Implements svn_ra__vtable_t.get_schemes(). */
@@ -508,19 +513,8 @@ svn_ra_serf__open(svn_ra_session_t *sess
serf_sess->pool));
- status = apr_uri_parse(serf_sess->pool, session_URL, &url);
- if (status)
- {
- return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
- _("Illegal URL '%s'"),
- session_URL);
- }
- /* Depending the version of apr-util in use, for root paths url.path
- will be NULL or "", where serf requires "/". */
- if (url.path == NULL || url.path[0] == '\0')
- {
- url.path = apr_pstrdup(serf_sess->pool, "/");
- }
+ SVN_ERR(svn_ra_serf__uri_parse(&url, session_URL, serf_sess->pool));
+
if (!url.port)
{
url.port = apr_uri_port_of_scheme(url.scheme);
@@ -740,18 +734,15 @@ ra_serf_dup_session(svn_ra_session_t *ne
new_sess->repos_root_str = apr_pstrdup(result_pool,
new_sess->repos_root_str);
- status = apr_uri_parse(result_pool, new_sess->repos_root_str,
- &new_sess->repos_root);
- if (status)
- return svn_ra_serf__wrap_err(status, NULL);
+ SVN_ERR(svn_ra_serf__uri_parse(&new_sess->repos_root,
+ new_sess->repos_root_str,
+ result_pool));
new_sess->session_url_str = apr_pstrdup(result_pool, new_session_url);
- status = apr_uri_parse(result_pool, new_sess->session_url_str,
- &new_sess->session_url);
-
- if (status)
- return svn_ra_serf__wrap_err(status, NULL);
+ SVN_ERR(svn_ra_serf__uri_parse(&new_sess->session_url,
+ new_sess->session_url_str,
+ result_pool));
/* svn_boolean_t supports_inline_props */
/* supports_rev_rsrc_replay */
@@ -800,7 +791,6 @@ svn_ra_serf__reparent(svn_ra_session_t *
{
svn_ra_serf__session_t *session = ra_session->priv;
apr_uri_t new_url;
- apr_status_t status;
/* If it's the URL we already have, wave our hands and do nothing. */
if (strcmp(session->session_url_str, url) == 0)
@@ -822,25 +812,11 @@ svn_ra_serf__reparent(svn_ra_session_t *
"URL '%s'"), url, session->repos_root_str);
}
- status = apr_uri_parse(pool, url, &new_url);
- if (status)
- {
- return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
- _("Illegal repository URL '%s'"), url);
- }
+ SVN_ERR(svn_ra_serf__uri_parse(&new_url, url, pool));
- /* Depending the version of apr-util in use, for root paths url.path
- will be NULL or "", where serf requires "/". */
/* ### Maybe we should use a string buffer for these strings so we
### don't allocate memory in the session on every reparent? */
- if (new_url.path == NULL || new_url.path[0] == '\0')
- {
- session->session_url.path = apr_pstrdup(session->pool, "/");
- }
- else
- {
- session->session_url.path = apr_pstrdup(session->pool, new_url.path);
- }
+ session->session_url.path = apr_pstrdup(session->pool, new_url.path);
session->session_url_str = apr_pstrdup(session->pool, url);
return SVN_NO_ERROR;
Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c Fri Sep 25
23:26:59 2015
@@ -1951,3 +1951,29 @@ svn_ra_serf__create_handler(svn_ra_serf_
return handler;
}
+svn_error_t *
+svn_ra_serf__uri_parse(apr_uri_t *uri,
+ const char *url_str,
+ apr_pool_t *result_pool)
+{
+ apr_status_t status;
+
+ status = apr_uri_parse(result_pool, url_str, uri);
+ if (status)
+ {
+ /* Do not use returned error status in error message because currently
+ apr_uri_parse() returns APR_EGENERAL for all parsing errors. */
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ _("Illegal URL '%s'"),
+ url_str);
+ }
+
+ /* Depending the version of apr-util in use, for root paths uri.path
+ will be NULL or "", where serf requires "/". */
+ if (uri->path == NULL || uri->path[0] == '\0')
+ {
+ uri->path = apr_pstrdup(result_pool, "/");
+ }
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/patch-exec/subversion/libsvn_subr/auth.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_subr/auth.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_subr/auth.c Fri Sep 25
23:26:59 2015
@@ -370,7 +370,9 @@ svn_auth_next_credentials(void **credent
if (creds != NULL)
{
/* Put the creds in the cache */
- svn_hash_sets(auth_baton->creds_cache, state->cache_key, creds);
+ svn_hash_sets(auth_baton->creds_cache,
+ apr_pstrdup(auth_baton->pool, state->cache_key),
+ creds);
break;
}
Modified: subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c
(original)
+++ subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c Fri
Sep 25 23:26:59 2015
@@ -53,9 +53,9 @@ HANDLE dbghelp_dll = INVALID_HANDLE_VALU
#define LOGFILE_PREFIX "svn-crash-log"
#if defined(_M_IX86)
-#define FORMAT_PTR "0x%08x"
+#define FORMAT_PTR "0x%08Ix"
#elif defined(_M_X64)
-#define FORMAT_PTR "0x%016I64x"
+#define FORMAT_PTR "0x%016Ix"
#endif
/*** Code. ***/
@@ -171,7 +171,7 @@ write_module_info_callback(void *data,
MINIDUMP_MODULE_CALLBACK module = callback_input->Module;
char *buf = convert_wbcs_to_ansi(module.FullPath);
- fprintf(log_file, FORMAT_PTR, module.BaseOfImage);
+ fprintf(log_file, FORMAT_PTR, (INT_PTR)module.BaseOfImage);
fprintf(log_file, " %s", buf);
free(buf);
@@ -302,7 +302,7 @@ format_basic_type(char *buf, DWORD basic
break;
default:
sprintf(buf, "[unhandled type 0x%08x of length " FORMAT_PTR "]",
- basic_type, length);
+ basic_type, (INT_PTR)length);
break;
}
}
@@ -341,7 +341,7 @@ format_value(char *value_str, DWORD64 mo
if (ptr == 0)
sprintf(value_str, "(%s) " FORMAT_PTR,
- type_name, (DWORD_PTR *)value_addr);
+ type_name, (INT_PTR)(DWORD_PTR *)value_addr);
else if (ptr == 1)
sprintf(value_str, "(%s *) " FORMAT_PTR,
type_name, *(DWORD_PTR *)value_addr);
Modified: subversion/branches/patch-exec/subversion/mod_dav_svn/version.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/mod_dav_svn/version.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/patch-exec/subversion/mod_dav_svn/version.c Fri Sep 25
23:26:59 2015
@@ -152,6 +152,7 @@ get_vsn_options(apr_pool_t *p, apr_text_
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INHERITED_PROPS);
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INLINE_PROPS);
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS);
+ apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_SVNDIFF1);
/* Mergeinfo is a special case: here we merely say that the server
* knows how to handle mergeinfo -- whether the repository does too
* is a separate matter.
Modified: subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
(original)
+++ subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py Fri
Sep 25 23:26:59 2015
@@ -3647,7 +3647,7 @@ def patch_lacking_trailing_eol(sbox):
# Expect a newline to be appended
expected_disk = svntest.main.greek_state.copy()
- expected_disk.tweak('iota', contents=iota_contents + "Some more bytes")
+ expected_disk.tweak('iota', contents=iota_contents + "Some more bytes\n")
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.tweak('iota', status='M ')
@@ -4559,7 +4559,6 @@ def patch_apply_no_fuz(sbox):
if not filecmp.cmp(sbox.ospath('test.txt'), sbox.ospath('test_v2.txt')):
raise svntest.Failure("Patch result not identical")
-@XFail()
def patch_lacking_trailing_eol_on_context(sbox):
"patch file lacking trailing eol on context"
@@ -5620,7 +5619,6 @@ def patch_obstructing_symlink_traversal(
expected_output, expected_disk,
expected_status, expected_skip)
-@XFail()
def patch_binary_file(sbox):
"patch a binary file"
@@ -5664,14 +5662,305 @@ def patch_binary_file(sbox):
expected_output = wc.State(wc_dir, {
'iota' : Item(status='UU'),
})
- expected_disk = None
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.tweak('iota',
+ props={'svn:mime-type':'application/binary'},
+ contents =
+ 'This is the file \'iota\'.\n'
+ '\0\202\203\204\205\206\207nsomething\nelse\xFF')
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.tweak('iota', status='MM')
expected_skip = wc.State('', { })
svntest.actions.run_and_verify_patch(wc_dir, tmp,
expected_output, expected_disk,
- expected_status, expected_skip)
+ expected_status, expected_skip,
+ [], True, True)
+
+ # Ok, now try applying it backwards
+ expected_output.tweak('iota', status='GU')
+ expected_disk = svntest.main.greek_state.copy()
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ svntest.actions.run_and_verify_patch(wc_dir, tmp,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+def patch_delete_nodes(sbox):
+ "apply deletes via patch"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_propset('A', 'B', 'A/B/E/alpha')
+ sbox.simple_append('A/mu', '\0')
+ sbox.simple_propset('svn:mime-type', 'application/nonsense', 'A/mu')
+
+ sbox.simple_commit() # r2
+ sbox.simple_update()
+
+ expected_skip = wc.State('', { })
+
+ original_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ original_disk = svntest.main.greek_state.copy()
+ original_disk.tweak('A/mu',
+ props={'svn:mime-type':'application/nonsense'},
+ contents = 'This is the file \'mu\'.\n\0')
+ original_disk.tweak('A/B/E/alpha', props={'A':'B'})
+ svntest.actions.run_and_verify_status(wc_dir, original_status)
+ svntest.actions.verify_disk(wc_dir, original_disk, True)
+
+ sbox.simple_rm('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+
+ _, diff, _ = svntest.actions.run_and_verify_svn(None, [],
+ 'diff', '--git', wc_dir)
+
+ patch = sbox.get_tempname('patch')
+ svntest.main.file_write(patch, ''.join(diff))
+
+ deleted_status = original_status.copy()
+ deleted_disk = original_disk.copy()
+ deleted_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+ deleted_status.tweak('A/B/E/alpha', 'A/B/E/beta', 'A/mu', status='D ')
+
+
+ svntest.actions.run_and_verify_status(wc_dir, deleted_status)
+ svntest.actions.verify_disk(wc_dir, deleted_disk, True)
+
+ # And now apply the patch from the clean state
+ sbox.simple_revert('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+
+ # Expect that the hint 'empty dir? -> delete dir' deletes 'E'
+ # ### A smarter diff format might change this in a future version
+ deleted_disk.remove('A/B/E')
+ deleted_status.tweak('A/B/E', status='D ')
+ expected_output = wc.State(wc_dir, {
+ 'A/mu' : Item(status='D '),
+ 'A/B/E' : Item(status='D '),
+ 'A/B/E/beta' : Item(status='D '),
+ 'A/B/E/alpha' : Item(status='D '),
+ })
+
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, deleted_disk,
+ deleted_status, expected_skip,
+ [], False, True)
+
+ # And let's see if we can apply the reverse version of the patch
+ expected_output = wc.State(wc_dir, {
+ 'A/mu' : Item(status='A '),
+ 'A/B/E' : Item(status='A '),
+ 'A/B/E/beta' : Item(status='A '),
+ 'A/B/E/alpha' : Item(status='A '),
+ })
+ original_status.tweak('A/mu', status='RM') # New file
+ original_status.tweak('A/B/E', status='R ') # New dir
+ original_status.tweak('A/B/E/alpha', 'A/B/E/beta',
+ status='A ', wc_rev='-',
+ entry_status='R ', entry_rev='2')
+
+
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, original_disk,
+ original_status, expected_skip,
+ [], True, True, '--reverse-diff')
+
+def patch_delete_missing_eol(sbox):
+ "apply a delete missing an eol"
+
+ sbox.build(read_only = True)
+ wc_dir = sbox.wc_dir
+
+ delete_patch = [
+ "Index: A/B/E/beta\n",
+ "===================================================================\n",
+ "--- A/B/E/beta (revision 1)\n",
+ "+++ /dev/null\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'beta'." # No final EOL
+ ]
+
+ patch = sbox.get_tempname('patch')
+ svntest.main.file_write(patch, ''.join(delete_patch))
+
+ expected_output = wc.State(wc_dir, {
+ 'A/B/E/beta' : Item(status='D '),
+ })
+ expected_skip = wc.State(wc_dir, {
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('A/B/E/beta', status='D ')
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.remove('A/B/E/beta')
+
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # Try again? -> Skip... Why not some already applied notification?
+ # -> There is nothing to compare to
+ expected_output = wc.State(wc_dir, {
+ })
+ expected_skip = wc.State(wc_dir, {
+ 'A/B/E/beta' : Item(verb='Skipped'),
+ })
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # Reverse
+ expected_output = wc.State(wc_dir, {
+ 'A/B/E/beta' : Item(status='A '),
+ })
+ expected_skip = wc.State(wc_dir, {
+ })
+ expected_disk = svntest.main.greek_state.copy()
+ expected_status.tweak('A/B/E/beta', status='R ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+ # Try again? -> Already applied
+ expected_output = wc.State(wc_dir, {
+ 'A/B/E/beta' : Item(status='G '),
+ })
+ expected_skip = wc.State(wc_dir, {
+ })
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+def patch_final_eol(sbox):
+ "patch the final eol"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ delete_patch = [
+ 'Index: A/mu\n',
+ '===================================================================\n',
+ '--- A/mu\t(revision 1)\n',
+ '+++ A/mu\t(working copy)\n',
+ '@@ -1 +1 @@\n',
+ '-This is the file \'mu\'.\n',
+ '+This is the file \'mu\'.\n',
+ '\ No newline at end of file\n',
+ 'Index: iota\n',
+ '===================================================================\n',
+ '--- iota\t(revision 1)\n',
+ '+++ iota\t(working copy)\n',
+ '@@ -1 +1 @@\n',
+ '-This is the file \'iota\'.\n',
+ '+This is the file \'iota\'.\n',
+ '\ No newline at end of file' # Missing EOL
+ ]
+
+ patch = sbox.get_tempname('patch')
+ # We explicitly use wb here as this is the eol type added later in the test
+ svntest.main.file_write(patch, ''.join(delete_patch), mode='wb')
+
+ expected_output = wc.State(wc_dir, {
+ 'A/mu' : Item(status='U '),
+ 'iota' : Item(status='U '),
+ })
+ expected_skip = wc.State(wc_dir, {})
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('iota', 'A/mu', status='M ')
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.tweak('iota', contents="This is the file 'iota'.")
+ expected_disk.tweak('A/mu', contents="This is the file 'mu'.")
+
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # And again
+ expected_output.tweak('iota', 'A/mu', status='G ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # Reverse
+ expected_disk.tweak('iota', contents="This is the file 'iota'.\n")
+ expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n")
+ expected_status.tweak('iota', 'A/mu', status=' ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+ # And once more
+ expected_output.tweak('iota', 'A/mu', status='U ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+ # Change the unmodified form
+ sbox.simple_append('iota', 'This is the file \'iota\'.', truncate=True)
+ sbox.simple_append('A/mu', 'This is the file \'mu\'.', truncate=True)
+ sbox.simple_commit()
+ expected_status.tweak('iota', 'A/mu', wc_rev='2')
+
+ add_patch = [
+ 'Index: A/mu\n',
+ '===================================================================\n',
+ '--- A/mu\t(revision 2)\n',
+ '+++ A/mu\t(working copy)\n',
+ '@@ -1 +1 @@\n',
+ '-This is the file \'mu\'.\n',
+ '\ No newline at end of file\n',
+ '+This is the file \'mu\'.\n',
+ 'Index: iota\n',
+ '===================================================================\n',
+ '--- iota\t(revision 2)\n',
+ '+++ iota\t(working copy)\n',
+ '@@ -1 +1 @@\n',
+ '-This is the file \'iota\'.\n',
+ '\ No newline at end of file\n',
+ '+This is the file \'iota\'.' # Missing eol
+ ]
+
+ svntest.main.file_write(patch, ''.join(add_patch), mode='wb')
+
+ # Apply the patch
+ expected_output.tweak('iota', 'A/mu', status='U ')
+ expected_disk.tweak('iota', contents="This is the file 'iota'.\n")
+ expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n")
+ expected_status.tweak('iota', 'A/mu', status='M ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # And again
+ expected_output.tweak('iota', 'A/mu', status='G ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True)
+
+ # And in reverse
+ expected_disk.tweak('iota', contents="This is the file 'iota'.")
+ expected_disk.tweak('A/mu', contents="This is the file 'mu'.")
+ expected_status.tweak('iota', 'A/mu', status=' ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
+
+ # And again
+ expected_output.tweak('iota', 'A/mu', status='U ')
+ svntest.actions.run_and_verify_patch(wc_dir, patch,
+ expected_output, expected_disk,
+ expected_status, expected_skip,
+ [], False, True, '--reverse-diff')
def patch_adds_executability_nocontents(sbox):
"""patch adds svn:executable, without contents"""
@@ -5855,7 +6144,7 @@ def patch_ambiguous_executability_consis
expected_status, expected_skip,
error_re_string=None,
check_props=True)
-
+
########################################################################
#Run the tests
@@ -5918,6 +6207,9 @@ test_list = [ None,
patch_symlink_traversal,
patch_obstructing_symlink_traversal,
patch_binary_file,
+ patch_delete_nodes,
+ patch_delete_missing_eol,
+ patch_final_eol,
patch_adds_executability_nocontents,
patch_adds_executability_yescontents,
patch_deletes_executability,
Modified:
subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
---
subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
(original)
+++
subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
Fri Sep 25 23:26:59 2015
@@ -305,6 +305,24 @@ create_patch_file(svn_patch_file_t **pat
return SVN_NO_ERROR;
}
+/* svn_stream_readline() with hunk reader semantics */
+static svn_error_t *
+stream_readline_diff(svn_stream_t *stream,
+ svn_stringbuf_t **buf,
+ const char *eol,
+ svn_boolean_t *eof,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR(svn_stream_readline(stream, buf, eol, eof, result_pool));
+
+ /* Hunks are only at EOF after they are completely read, even if
+ they don't have a final EOL in the text */
+ if (*eof && (*buf)->len)
+ *eof = FALSE;
+
+ return SVN_NO_ERROR;
+}
+
/* Check that reading a line from HUNK equals what's inside EXPECTED.
* If ORIGINAL is TRUE, read the original hunk text; else, read the
* modified hunk text. */
@@ -323,7 +341,7 @@ check_content(svn_diff_hunk_t *hunk, svn
while (TRUE)
{
- SVN_ERR(svn_stream_readline(exp, &exp_buf, NL, &exp_eof, pool));
+ SVN_ERR(stream_readline_diff(exp, &exp_buf, NL, &exp_eof, pool));
if (original)
SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_buf, NULL,
&hunk_eof, pool, pool));
Modified: subversion/branches/patch-exec/tools/dist/backport/merger.py
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/tools/dist/backport/merger.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/tools/dist/backport/merger.py (original)
+++ subversion/branches/patch-exec/tools/dist/backport/merger.py Fri Sep 25
23:26:59 2015
@@ -161,7 +161,7 @@ def merge(entry, expected_stderr=None, *
# Prepare mergeargs and logmsg.
logmsg = ""
if entry.branch:
- branch_url = "%s/%s" % (sf.BRANCHES, entry.branch)
+ branch_url = sf.branch_url(entry.branch)
if svn_version() >= (1, 8):
mergeargs = ['--', branch_url]
logmsg = "Merge {}:\n".format(entry.noun())
@@ -181,7 +181,7 @@ def merge(entry, expected_stderr=None, *
logmsg += "Merge {} from trunk:\n".format(entry.noun())
logmsg += "\n"
mergeargs.extend('-c' + str(revision) for revision in entry.revisions)
- mergeargs.extend(['--', sf.TRUNK])
+ mergeargs.extend(['--', sf.trunk_url()])
logmsg += entry.raw
# TODO(interactive mode): exclude STATUS from reverts
@@ -237,9 +237,9 @@ def validate_branch_contains_named_revis
return # skip check
sf = entry.status_file
- branch_url = "%s/%s" % (sf.BRANCHES, entry.branch)
+ branch_url = sf.branch_url(entry.branch)
present_str = (
- run_svn(['mergeinfo', '--show-revs=merged', '--', sf.TRUNK, branch_url])[1]
+ run_svn(['mergeinfo', '--show-revs=merged', '--', sf.trunk_url(),
branch_url])[1]
+
run_svn(['mergeinfo', '--show-revs=eligible', '--', branch_url])[1]
)
Modified: subversion/branches/patch-exec/tools/dist/backport/status.py
URL:
http://svn.apache.org/viewvc/subversion/branches/patch-exec/tools/dist/backport/status.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/tools/dist/backport/status.py (original)
+++ subversion/branches/patch-exec/tools/dist/backport/status.py Fri Sep 25
23:26:59 2015
@@ -157,13 +157,24 @@ class Paragraph:
class StatusFile:
"Encapsulates the STATUS file."
- TRUNK = '^/subversion/trunk'
- BRANCHES = '^/subversion/branches'
-
def __init__(self, status_fp):
"Constructor. STATUS_FP is an open file-like object to parse."
self._parse(status_fp)
self.validate_unique_entry_ids() # Use-case for making this optional?
+ self._project_root_url = '^/subversion'
+
+ def branch_url(self, branch_basename):
+ """Return the URL of a branch with a given basename, of 'Branch:' headers
+ that specify a basename only.
+
+ The returned URL may be an ^/foo short URL."""
+ return (self._project_root_url + "/branches/" + branch_basename)
+
+ def trunk_url(self):
+ """Return the URL to trunk. Trunk is used as the default merge source.
+
+ The returned URL may be an ^/foo short URL."""
+ return self._project_root_url + '/trunk'
def _parse(self, status_fp):
"Parse self.status_fp into self.paragraphs."