You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/03/30 22:58:01 UTC
svn commit: r929279 [11/20] - in
/subversion/branches/svn-patch-improvements: ./ build/ac-macros/
build/generator/ build/generator/templates/ contrib/client-side/emacs/
notes/feedback/ notes/meetings/ notes/wc-ng/ subversion/
subversion/bindings/javahl...
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c Tue Mar 30 20:57:53 2010
@@ -115,10 +115,20 @@ parse_pathname(const char **input,
return SVN_NO_ERROR;
}
-/* Ways in which two svn_merge_range_t can intersect, if at all. */
+/* Return TRUE iff (svn_merge_range_t *) RANGE describes a valid, forward
+ * revision range.
+ *
+ * Note: The smallest valid value of RANGE->start is 0 because it is an
+ * exclusive endpoint, being one less than the revision number of the first
+ * change described by the range, and the oldest possible change is "r1" as
+ * there cannot be a change "r0". */
+#define IS_VALID_FORWARD_RANGE(range) \
+ (SVN_IS_VALID_REVNUM((range)->start) && ((range)->start < (range)->end))
+
+/* Ways in which two svn_merge_range_t can intersect or adjoin, if at all. */
typedef enum
{
- /* Ranges don't intersect. */
+ /* Ranges don't intersect and don't adjoin. */
svn__no_intersection,
/* Ranges are equal. */
@@ -127,7 +137,7 @@ typedef enum
/* Ranges adjoin but don't overlap. */
svn__adjoining_intersection,
- /* Ranges overalp but neither is a subset of the other. */
+ /* Ranges overlap but neither is a subset of the other. */
svn__overlapping_intersection,
/* One range is a proper subset of the other. */
@@ -144,16 +154,8 @@ get_type_of_intersection(const svn_merge
{
SVN_ERR_ASSERT(r1);
SVN_ERR_ASSERT(r2);
-
- /* Why not use SVN_IS_VALID_REVNUM here? Because revision 0
- is described START = -1, END = 0. See svn_merge_range_t. */
- SVN_ERR_ASSERT(r1->start >= -1);
- SVN_ERR_ASSERT(r2->start >= -1);
-
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(r1->end));
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(r2->end));
- SVN_ERR_ASSERT(r1->start < r1->end);
- SVN_ERR_ASSERT(r2->start < r2->end);
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(r1));
+ SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(r2));
if (!(r1->start <= r2->end && r2->start <= r1->end))
*intersection_type = svn__no_intersection;
@@ -457,6 +459,10 @@ range_to_string(const svn_merge_range_t
}
/* Helper for svn_mergeinfo_parse()
+ Append revision ranges onto the array RANGELIST to represent the range
+ descriptions found in the string *INPUT. Read only as far as a newline
+ or the position END, whichever comes first. Set *INPUT to the position
+ after the last character of INPUT that was used.
revisionlist -> (revisionelement)(COMMA revisionelement)*
revisionrange -> REVISION "-" REVISION("*")
@@ -501,6 +507,11 @@ parse_rangelist(const char **input, cons
mrange->end = firstrev;
mrange->inheritable = TRUE;
+ if (firstrev == 0)
+ return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+ _("Invalid revision number '0' found in "
+ "range list"));
+
if (*curr == '-')
{
svn_revnum_t secondrev;
@@ -696,7 +707,7 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer
svn_error_t *
svn_rangelist_merge(apr_array_header_t **rangelist,
- apr_array_header_t *changes,
+ const apr_array_header_t *changes,
apr_pool_t *pool)
{
int i, j;
@@ -763,20 +774,31 @@ svn_rangelist_merge(apr_array_header_t *
return SVN_NO_ERROR;
}
+/* Return TRUE iff the forward revision ranges FIRST and SECOND overlap and
+ * (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */
static svn_boolean_t
range_intersect(const svn_merge_range_t *first, const svn_merge_range_t *second,
svn_boolean_t consider_inheritance)
{
+ SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
+ SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+
return (first->start + 1 <= second->end)
&& (second->start + 1 <= first->end)
&& (!consider_inheritance
|| (!(first->inheritable) == !(second->inheritable)));
}
+/* Return TRUE iff the forward revision range FIRST wholly contains the
+ * forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has
+ * the same inheritability. */
static svn_boolean_t
range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second,
svn_boolean_t consider_inheritance)
{
+ SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
+ SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+
return (first->start <= second->start) && (second->end <= first->end)
&& (!consider_inheritance
|| (!(first->inheritable) == !(second->inheritable)));
@@ -848,12 +870,7 @@ svn_mergeinfo__set_inheritance(svn_merge
hi;
hi = apr_hash_next(hi))
{
- apr_array_header_t *rangelist;
- const void *path;
- void *val;
- apr_hash_this(hi, &path, NULL, &val);
-
- rangelist = apr_hash_get(mergeinfo, path, APR_HASH_KEY_STRING);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
if (rangelist)
svn_rangelist__set_inheritance(rangelist, inheritable);
@@ -862,84 +879,126 @@ svn_mergeinfo__set_inheritance(svn_merge
return;
}
-/* Either remove any overlapping ranges described by ERASER from
- WHITEBOARD (when DO_REMOVE is TRUE), or capture the overlap, and
- place the remaining or overlapping ranges in OUTPUT. */
-/* ### FIXME: Some variables names and inline comments for this method
- ### are legacy from when it was solely the remove() impl. */
+/* If DO_REMOVE is true, then remove any overlapping ranges described by
+ RANGELIST1 from RANGELIST2 and place the results in *OUTPUT. When
+ DO_REMOVE is true, RANGELIST1 is effectively the "eraser" and RANGELIST2
+ the "whiteboard".
+
+ If DO_REMOVE is false, then capture the intersection between RANGELIST1
+ and RANGELIST2 and place the results in *OUTPUT. The ordering of
+ RANGELIST1 and RANGELIST2 doesn't matter when DO_REMOVE is false.
+
+ If CONSIDER_INHERITANCE is true, then take the inheritance of the
+ ranges in RANGELIST1 and RANGELIST2 into account when comparing them
+ for intersection, see the doc string for svn_rangelist_intersection().
+
+ If CONSIDER_INHERITANCE is false, then ranges with differing inheritance
+ may intersect, but the resulting intersection is non-inheritable only
+ if both ranges were non-inheritable, e.g.:
+
+ RANGELIST1 RANGELIST2 CONSIDER DO_REMOVE *OUTPUT
+ INHERITANCE
+ ---------- ------ ----------- --------- -------
+
+ 90-420* 1-100 TRUE FALSE Empty Rangelist
+ 90-420 1-100* TRUE FALSE Empty Rangelist
+ 90-420 1-100 TRUE FALSE 90-100
+ 90-420* 1-100* TRUE FALSE 90-100*
+
+ 90-420* 1-100 FALSE FALSE 90-100
+ 90-420 1-100* FALSE FALSE 90-100
+ 90-420 1-100 FALSE FALSE 90-100
+ 90-420* 1-100* FALSE FALSE 90-100*
+
+ Allocate the contents of *OUTPUT in POOL. */
static svn_error_t *
rangelist_intersect_or_remove(apr_array_header_t **output,
- apr_array_header_t *eraser,
- apr_array_header_t *whiteboard,
+ const apr_array_header_t *rangelist1,
+ const apr_array_header_t *rangelist2,
svn_boolean_t do_remove,
svn_boolean_t consider_inheritance,
apr_pool_t *pool)
{
- int i, j, lasti;
- svn_merge_range_t wboardelt;
+ int i1, i2, lasti2;
+ svn_merge_range_t working_elt2;
*output = apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
- i = 0;
- j = 0;
- lasti = -1; /* Initialized to a value that "i" will never be. */
+ i1 = 0;
+ i2 = 0;
+ lasti2 = -1; /* Initialized to a value that "i2" will never be. */
- while (i < whiteboard->nelts && j < eraser->nelts)
+ while (i1 < rangelist1->nelts && i2 < rangelist2->nelts)
{
svn_merge_range_t *elt1, *elt2;
- elt2 = APR_ARRAY_IDX(eraser, j, svn_merge_range_t *);
+ elt1 = APR_ARRAY_IDX(rangelist1, i1, svn_merge_range_t *);
- /* Instead of making a copy of the entire array of whiteboard
- elements, we just keep a copy of the current whiteboard element
+ /* Instead of making a copy of the entire array of rangelist2
+ elements, we just keep a copy of the current rangelist2 element
that needs to be used, and modify our copy if necessary. */
- if (i != lasti)
+ if (i2 != lasti2)
{
- wboardelt = *(APR_ARRAY_IDX(whiteboard, i, svn_merge_range_t *));
- lasti = i;
+ working_elt2 =
+ *(APR_ARRAY_IDX(rangelist2, i2, svn_merge_range_t *));
+ lasti2 = i2;
}
- elt1 = &wboardelt;
+ elt2 = &working_elt2;
- /* If the whiteboard range is contained completely in the
- eraser, we increment the whiteboard.
+ /* If the rangelist2 range is contained completely in the
+ rangelist1, we increment the rangelist2.
If the ranges intersect, and match exactly, we increment both
- eraser and whiteboard.
+ rangelist1 and rangelist2.
Otherwise, we have to generate a range for the left part of
- the removal of eraser from whiteboard, and possibly change
- the whiteboard to the remaining portion of the right part of
+ the removal of rangelist1 from rangelist2, and possibly change
+ the rangelist2 to the remaining portion of the right part of
the removal, to test against. */
- if (range_contains(elt2, elt1, consider_inheritance))
+ if (range_contains(elt1, elt2, consider_inheritance))
{
if (!do_remove)
- SVN_ERR(combine_with_lastrange(elt1, *output,
- consider_inheritance, pool,
- pool));
+ {
+ svn_merge_range_t tmp_range;
+ tmp_range.start = elt2->start;
+ tmp_range.end = elt2->end;
+ /* The intersection of two ranges is non-inheritable only
+ if both ranges are non-inheritable. */
+ tmp_range.inheritable =
+ (elt2->inheritable || elt1->inheritable);
+ SVN_ERR(combine_with_lastrange(&tmp_range, *output,
+ consider_inheritance, pool,
+ pool));
+ }
- i++;
+ i2++;
- if (elt1->start == elt2->start && elt1->end == elt2->end)
- j++;
+ if (elt2->start == elt1->start && elt2->end == elt1->end)
+ i1++;
}
- else if (range_intersect(elt2, elt1, consider_inheritance))
+ else if (range_intersect(elt1, elt2, consider_inheritance))
{
- if (elt1->start < elt2->start)
+ if (elt2->start < elt1->start)
{
- /* The whiteboard range starts before the eraser range. */
+ /* The rangelist2 range starts before the rangelist1 range. */
svn_merge_range_t tmp_range;
- tmp_range.inheritable = elt1->inheritable;
if (do_remove)
{
- /* Retain the range that falls before the eraser start. */
- tmp_range.start = elt1->start;
- tmp_range.end = elt2->start;
+ /* Retain the range that falls before the rangelist1
+ start. */
+ tmp_range.start = elt2->start;
+ tmp_range.end = elt1->start;
+ tmp_range.inheritable = elt2->inheritable;
}
else
{
- /* Retain the range that falls between the eraser
- start and whiteboard end. */
- tmp_range.start = elt2->start;
- tmp_range.end = MIN(elt1->end, elt2->end);
+ /* Retain the range that falls between the rangelist1
+ start and rangelist2 end. */
+ tmp_range.start = elt1->start;
+ tmp_range.end = MIN(elt2->end, elt1->end);
+ /* The intersection of two ranges is non-inheritable only
+ if both ranges are non-inheritable. */
+ tmp_range.inheritable =
+ (elt2->inheritable || elt1->inheritable);
}
SVN_ERR(combine_with_lastrange(&tmp_range,
@@ -947,40 +1006,43 @@ rangelist_intersect_or_remove(apr_array_
pool, pool));
}
- /* Set up the rest of the whiteboard range for further
+ /* Set up the rest of the rangelist2 range for further
processing. */
- if (elt1->end > elt2->end)
+ if (elt2->end > elt1->end)
{
- /* The whiteboard range ends after the eraser range. */
+ /* The rangelist2 range ends after the rangelist1 range. */
if (!do_remove)
{
/* Partial overlap. */
svn_merge_range_t tmp_range;
- tmp_range.start = MAX(elt1->start, elt2->start);
- tmp_range.end = elt2->end;
- tmp_range.inheritable = elt1->inheritable;
+ tmp_range.start = MAX(elt2->start, elt1->start);
+ tmp_range.end = elt1->end;
+ /* The intersection of two ranges is non-inheritable only
+ if both ranges are non-inheritable. */
+ tmp_range.inheritable =
+ (elt2->inheritable || elt1->inheritable);
SVN_ERR(combine_with_lastrange(&tmp_range,
*output,
consider_inheritance,
pool, pool));
}
- wboardelt.start = elt2->end;
- wboardelt.end = elt1->end;
+ working_elt2.start = elt1->end;
+ working_elt2.end = elt2->end;
}
else
- i++;
+ i2++;
}
else /* ranges don't intersect */
{
- /* See which side of the whiteboard the eraser is on. If it
- is on the left side, we need to move the eraser.
+ /* See which side of the rangelist2 the rangelist1 is on. If it
+ is on the left side, we need to move the rangelist1.
- If it is on past the whiteboard on the right side, we
- need to output the whiteboard and increment the
- whiteboard. */
- if (svn_sort_compare_ranges(&elt2, &elt1) < 0)
- j++;
+ If it is on past the rangelist2 on the right side, we
+ need to output the rangelist2 and increment the
+ rangelist2. */
+ if (svn_sort_compare_ranges(&elt1, &elt2) < 0)
+ i1++;
else
{
svn_merge_range_t *lastrange;
@@ -992,36 +1054,36 @@ rangelist_intersect_or_remove(apr_array_
lastrange = NULL;
if (do_remove && !(lastrange &&
- combine_ranges(lastrange, lastrange, elt1,
+ combine_ranges(lastrange, lastrange, elt2,
consider_inheritance)))
{
- lastrange = svn_merge_range_dup(elt1, pool);
+ lastrange = svn_merge_range_dup(elt2, pool);
APR_ARRAY_PUSH(*output, svn_merge_range_t *) = lastrange;
}
- i++;
+ i2++;
}
}
}
if (do_remove)
{
- /* Copy the current whiteboard element if we didn't hit the end
- of the whiteboard, and we still had it around. This element
- may have been touched, so we can't just walk the whiteboard
+ /* Copy the current rangelist2 element if we didn't hit the end
+ of the rangelist2, and we still had it around. This element
+ may have been touched, so we can't just walk the rangelist2
array, we have to use our copy. This case only happens when
- we ran out of eraser before whiteboard, *and* we had changed
- the whiteboard element. */
- if (i == lasti && i < whiteboard->nelts)
+ we ran out of rangelist1 before rangelist2, *and* we had changed
+ the rangelist2 element. */
+ if (i2 == lasti2 && i2 < rangelist2->nelts)
{
- SVN_ERR(combine_with_lastrange(&wboardelt, *output,
+ SVN_ERR(combine_with_lastrange(&working_elt2, *output,
consider_inheritance, pool, pool));
- i++;
+ i2++;
}
- /* Copy any other remaining untouched whiteboard elements. */
- for (; i < whiteboard->nelts; i++)
+ /* Copy any other remaining untouched rangelist2 elements. */
+ for (; i2 < rangelist2->nelts; i2++)
{
- svn_merge_range_t *elt = APR_ARRAY_IDX(whiteboard, i,
+ svn_merge_range_t *elt = APR_ARRAY_IDX(rangelist2, i2,
svn_merge_range_t *);
SVN_ERR(combine_with_lastrange(elt, *output,
@@ -1035,8 +1097,8 @@ rangelist_intersect_or_remove(apr_array_
svn_error_t *
svn_rangelist_intersect(apr_array_header_t **output,
- apr_array_header_t *rangelist1,
- apr_array_header_t *rangelist2,
+ const apr_array_header_t *rangelist1,
+ const apr_array_header_t *rangelist2,
svn_boolean_t consider_inheritance,
apr_pool_t *pool)
{
@@ -1046,8 +1108,8 @@ svn_rangelist_intersect(apr_array_header
svn_error_t *
svn_rangelist_remove(apr_array_header_t **output,
- apr_array_header_t *eraser,
- apr_array_header_t *whiteboard,
+ const apr_array_header_t *eraser,
+ const apr_array_header_t *whiteboard,
svn_boolean_t consider_inheritance,
apr_pool_t *pool)
{
@@ -1057,7 +1119,7 @@ svn_rangelist_remove(apr_array_header_t
svn_error_t *
svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added,
- apr_array_header_t *from, apr_array_header_t *to,
+ const apr_array_header_t *from, const apr_array_header_t *to,
svn_boolean_t consider_inheritance,
apr_pool_t *pool)
{
@@ -1295,7 +1357,7 @@ svn_error_t *
svn_mergeinfo_intersect2(svn_mergeinfo_t *mergeinfo,
svn_mergeinfo_t mergeinfo1,
svn_mergeinfo_t mergeinfo2,
- svn_boolean_t consider_ineheritance,
+ svn_boolean_t consider_inheritance,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1311,23 +1373,20 @@ svn_mergeinfo_intersect2(svn_mergeinfo_t
for (hi = apr_hash_first(apr_hash_pool_get(mergeinfo1), mergeinfo1);
hi; hi = apr_hash_next(hi))
{
- apr_array_header_t *rangelist;
- const void *path;
- void *val;
- apr_hash_this(hi, &path, NULL, &val);
-
- rangelist = apr_hash_get(mergeinfo2, path, APR_HASH_KEY_STRING);
- if (rangelist)
- {
- SVN_ERR(svn_rangelist_intersect(&rangelist,
- (apr_array_header_t *) val,
- rangelist, consider_ineheritance,
- scratch_pool));
- if (rangelist->nelts > 0)
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist1 = svn__apr_hash_index_val(hi);
+ apr_array_header_t *rangelist2;
+
+ rangelist2 = apr_hash_get(mergeinfo2, path, APR_HASH_KEY_STRING);
+ if (rangelist2)
+ {
+ SVN_ERR(svn_rangelist_intersect(&rangelist2, rangelist1, rangelist2,
+ consider_inheritance, scratch_pool));
+ if (rangelist2->nelts > 0)
apr_hash_set(*mergeinfo,
apr_pstrdup(result_pool, path),
APR_HASH_KEY_STRING,
- svn_rangelist_dup(rangelist, result_pool));
+ svn_rangelist_dup(rangelist2, result_pool));
}
}
return SVN_NO_ERROR;
@@ -1345,13 +1404,13 @@ svn_error_t *
svn_mergeinfo_remove2(svn_mergeinfo_t *mergeinfo,
svn_mergeinfo_t eraser,
svn_mergeinfo_t whiteboard,
- svn_boolean_t consider_ineritance,
+ svn_boolean_t consider_inheritance,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
*mergeinfo = apr_hash_make(result_pool);
return walk_mergeinfo_hash_for_diff(whiteboard, eraser, *mergeinfo, NULL,
- consider_ineritance, result_pool,
+ consider_inheritance, result_pool,
scratch_pool);
}
@@ -1447,14 +1506,11 @@ svn_error_t *
svn_mergeinfo_sort(svn_mergeinfo_t input, apr_pool_t *pool)
{
apr_hash_index_t *hi;
- void *val;
for (hi = apr_hash_first(pool, input); hi; hi = apr_hash_next(hi))
{
- apr_array_header_t *rl;
- apr_hash_this(hi, NULL, NULL, &val);
+ apr_array_header_t *rl = svn__apr_hash_index_val(hi);
- rl = val;
qsort(rl->elts, rl->nelts, rl->elt_size, svn_sort_compare_ranges);
}
return SVN_NO_ERROR;
@@ -1471,9 +1527,9 @@ svn_mergeinfo_catalog_dup(svn_mergeinfo_
hi;
hi = apr_hash_next(hi))
{
- const void *key;
- void *val;
- apr_hash_this(hi, &key, NULL, &val);
+ const char *key = svn__apr_hash_index_key(hi);
+ svn_mergeinfo_t val = svn__apr_hash_index_val(hi);
+
apr_hash_set(new_mergeinfo_catalog,
apr_pstrdup(pool, key),
APR_HASH_KEY_STRING,
@@ -1488,15 +1544,15 @@ svn_mergeinfo_dup(svn_mergeinfo_t mergei
{
svn_mergeinfo_t new_mergeinfo = apr_hash_make(pool);
apr_hash_index_t *hi;
- const void *path;
- apr_ssize_t pathlen;
- void *rangelist;
for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
{
- apr_hash_this(hi, &path, &pathlen, &rangelist);
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_ssize_t pathlen = svn__apr_hash_index_klen(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+
apr_hash_set(new_mergeinfo, apr_pstrmemdup(pool, path, pathlen), pathlen,
- svn_rangelist_dup((apr_array_header_t *) rangelist, pool));
+ svn_rangelist_dup(rangelist, pool));
}
return new_mergeinfo;
@@ -1513,25 +1569,23 @@ svn_mergeinfo_inheritable2(svn_mergeinfo
apr_pool_t *scratch_pool)
{
apr_hash_index_t *hi;
- const void *key;
- apr_ssize_t keylen;
- void *rangelist;
-
svn_mergeinfo_t inheritable_mergeinfo = apr_hash_make(result_pool);
+
for (hi = apr_hash_first(scratch_pool, mergeinfo);
hi;
hi = apr_hash_next(hi))
{
+ const char *key = svn__apr_hash_index_key(hi);
+ apr_ssize_t keylen = svn__apr_hash_index_klen(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
apr_array_header_t *inheritable_rangelist;
- apr_hash_this(hi, &key, &keylen, &rangelist);
- if (!path || svn_path_compare_paths(path, (const char *)key) == 0)
- SVN_ERR(svn_rangelist_inheritable2(&inheritable_rangelist,
- (apr_array_header_t *) rangelist,
+
+ if (!path || svn_path_compare_paths(path, key) == 0)
+ SVN_ERR(svn_rangelist_inheritable2(&inheritable_rangelist, rangelist,
start, end, inheritable,
result_pool, scratch_pool));
else
- inheritable_rangelist =
- svn_rangelist_dup((apr_array_header_t *)rangelist, result_pool);
+ inheritable_rangelist = svn_rangelist_dup(rangelist, result_pool);
/* Only add this rangelist if some ranges remain. A rangelist with
a path mapped to an empty rangelist is not syntactically valid */
@@ -1544,47 +1598,10 @@ svn_mergeinfo_inheritable2(svn_mergeinfo
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_mergeinfo_inheritable(svn_mergeinfo_t *output,
- svn_mergeinfo_t mergeinfo,
- const char *path,
- svn_revnum_t start,
- svn_revnum_t end,
- apr_pool_t *pool)
-{
- apr_hash_index_t *hi;
- const void *key;
- apr_ssize_t keylen;
- void *rangelist;
-
- svn_mergeinfo_t inheritable_mergeinfo = apr_hash_make(pool);
- for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
- {
- apr_array_header_t *inheritable_rangelist;
- apr_hash_this(hi, &key, &keylen, &rangelist);
- if (!path || svn_path_compare_paths(path, (const char *)key) == 0)
- SVN_ERR(svn_rangelist_inheritable(&inheritable_rangelist,
- (apr_array_header_t *) rangelist,
- start, end, pool));
- else
- inheritable_rangelist =
- svn_rangelist_dup((apr_array_header_t *)rangelist, pool);
-
- /* Only add this rangelist if some ranges remain. A rangelist with
- a path mapped to an empty rangelist is not syntactically valid */
- if (inheritable_rangelist->nelts)
- apr_hash_set(inheritable_mergeinfo,
- apr_pstrmemdup(pool, key, keylen), keylen,
- inheritable_rangelist);
- }
- *output = inheritable_mergeinfo;
- return SVN_NO_ERROR;
-}
-
svn_error_t *
svn_rangelist_inheritable2(apr_array_header_t **inheritable_rangelist,
- apr_array_header_t *rangelist,
+ const apr_array_header_t *rangelist,
svn_revnum_t start,
svn_revnum_t end,
svn_boolean_t inheritable,
@@ -1635,17 +1652,6 @@ svn_rangelist_inheritable2(apr_array_hea
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist,
- apr_array_header_t *rangelist,
- svn_revnum_t start,
- svn_revnum_t end,
- apr_pool_t *pool)
-{
- return svn_rangelist_inheritable2(inheritable_rangelist, rangelist,
- start, end, TRUE, pool, pool);
-}
-
svn_boolean_t
svn_mergeinfo__remove_empty_rangelists(svn_mergeinfo_t mergeinfo,
apr_pool_t *pool)
@@ -1657,14 +1663,8 @@ svn_mergeinfo__remove_empty_rangelists(s
{
for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
{
- const void *key;
- void *value;
- const char *path;
- apr_array_header_t *rangelist;
-
- apr_hash_this(hi, &key, NULL, &value);
- path = key;
- rangelist = value;
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
if (rangelist->nelts == 0)
{
@@ -1689,15 +1689,12 @@ svn_mergeinfo__remove_prefix_from_catalo
for (hi = apr_hash_first(pool, in_catalog); hi; hi = apr_hash_next(hi))
{
- const void *key;
- const char *original_path;
- void *value;
- apr_ssize_t klen;
+ const char *original_path = svn__apr_hash_index_key(hi);
+ apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+ svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
- apr_hash_this(hi, &key, &klen, &value);
- original_path = key;
SVN_ERR_ASSERT(klen >= prefix_len);
- SVN_ERR_ASSERT(strncmp(key, prefix, prefix_len) == 0);
+ SVN_ERR_ASSERT(strncmp(original_path, prefix, prefix_len) == 0);
apr_hash_set(*out_catalog, original_path + prefix_len,
klen-prefix_len, value);
@@ -1728,8 +1725,8 @@ svn_mergeinfo__add_suffix_to_mergeinfo(s
hi;
hi = apr_hash_next(hi))
{
- const char *path = svn_apr_hash_index_key(hi);
- apr_array_header_t *rangelist = svn_apr_hash_index_val(hi);
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
apr_hash_set(*out_mergeinfo,
svn_dirent_join(path, canonical_suffix, result_pool),
@@ -1742,7 +1739,7 @@ svn_mergeinfo__add_suffix_to_mergeinfo(s
}
apr_array_header_t *
-svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool)
+svn_rangelist_dup(const apr_array_header_t *rangelist, apr_pool_t *pool)
{
apr_array_header_t *new_rl = apr_array_make(pool, rangelist->nelts,
sizeof(svn_merge_range_t *));
@@ -1884,14 +1881,7 @@ svn_mergeinfo__get_range_endpoints(svn_r
for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
{
- const void *key;
- void *value;
- const char *path;
- apr_array_header_t *rangelist;
-
- apr_hash_this(hi, &key, NULL, &value);
- path = key;
- rangelist = value;
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
if (rangelist->nelts)
{
@@ -1928,14 +1918,10 @@ svn_mergeinfo__filter_catalog_by_ranges(
hi;
hi = apr_hash_next(hi))
{
- const void *key;
- void *val;
- const char *path;
-
- svn_mergeinfo_t mergeinfo, filtered_mergeinfo;
- apr_hash_this(hi, &key, NULL, &val);
- path = key;
- mergeinfo = val;
+ const char *path = svn__apr_hash_index_key(hi);
+ svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi);
+ svn_mergeinfo_t filtered_mergeinfo;
+
SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&filtered_mergeinfo,
mergeinfo,
youngest_rev,
@@ -1975,26 +1961,16 @@ svn_mergeinfo__filter_mergeinfo_by_range
hi;
hi = apr_hash_next(hi))
{
- const void *key;
- void *value;
- const char *path;
- apr_array_header_t *rangelist;
-
- apr_hash_this(hi, &key, NULL, &value);
- path = key;
- rangelist = value;
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
if (rangelist->nelts)
{
apr_array_header_t *new_rangelist;
- if (include_range)
- SVN_ERR(svn_rangelist_intersect(&new_rangelist, rangelist,
- filter_rangelist, FALSE,
- result_pool));
- else
- SVN_ERR(svn_rangelist_remove(&new_rangelist, filter_rangelist,
- rangelist, FALSE, result_pool));
+ SVN_ERR(rangelist_intersect_or_remove(
+ &new_rangelist, filter_rangelist, rangelist,
+ ! include_range, FALSE, result_pool));
if (new_rangelist->nelts)
apr_hash_set(*filtered_mergeinfo,
@@ -2019,7 +1995,7 @@ svn_mergeinfo__is_noninheritable(svn_mer
hi;
hi = apr_hash_next(hi))
{
- apr_array_header_t *rangelist = svn_apr_hash_index_val(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
int i;
for (i = 0; i < rangelist->nelts; i++)
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/opt.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/opt.c Tue Mar 30 20:57:53 2010
@@ -739,7 +739,7 @@ svn_opt_parse_path(svn_opt_revision_t *r
svn_error_t *
svn_opt__args_to_target_array(apr_array_header_t **targets_p,
apr_getopt_t *os,
- apr_array_header_t *known_targets,
+ const apr_array_header_t *known_targets,
apr_pool_t *pool)
{
int i;
@@ -1067,7 +1067,7 @@ svn_opt_print_help3(apr_getopt_t *os,
svn_error_t *
svn_opt_eat_peg_revisions(apr_array_header_t **true_targets_p,
- apr_array_header_t *targets,
+ const apr_array_header_t *targets,
apr_pool_t *pool)
{
int i;
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/prompt.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/prompt.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/prompt.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/prompt.c Tue Mar 30 20:57:53 2010
@@ -71,7 +71,7 @@ static apr_status_t wait_for_input(apr_f
* ourselves here.
*/
return APR_ENOTIMPL;
-#endif
+#endif
}
/* Set @a *result to the result of prompting the user with @a
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/quoprint.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/quoprint.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/quoprint.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/quoprint.c Tue Mar 30 20:57:53 2010
@@ -37,24 +37,24 @@
/* Caveats:
- (1) This code is for the encoding and decoding of binary data
- only. Thus, CRLF sequences are encoded as =0D=0A, and we
- don't have to worry about tabs and spaces coming before
- hard newlines, since there aren't any.
-
- (2) The decoder does no error reporting, and instead throws
- away invalid sequences. It also discards CRLF sequences,
- since those can only appear in the encoding of text data.
-
- (3) The decoder does not strip whitespace at the end of a
- line, so it is not actually compliant with RFC 2045.
- (Such whitespace should never occur, even in the encoding
- of text data, but RFC 2045 requires a decoder to detect
- that a transport agent has added trailing whitespace).
-
- (4) The encoder is tailored to make output embeddable in XML,
- which means it quotes <>'"& as well as the characters
- required by RFC 2045. */
+ (1) This code is for the encoding and decoding of binary data
+ only. Thus, CRLF sequences are encoded as =0D=0A, and we
+ don't have to worry about tabs and spaces coming before
+ hard newlines, since there aren't any.
+
+ (2) The decoder does no error reporting, and instead throws
+ away invalid sequences. It also discards CRLF sequences,
+ since those can only appear in the encoding of text data.
+
+ (3) The decoder does not strip whitespace at the end of a
+ line, so it is not actually compliant with RFC 2045.
+ (Such whitespace should never occur, even in the encoding
+ of text data, but RFC 2045 requires a decoder to detect
+ that a transport agent has added trailing whitespace).
+
+ (4) The encoder is tailored to make output embeddable in XML,
+ which means it quotes <>'"& as well as the characters
+ required by RFC 2045. */
#define QUOPRINT_LINELEN 76
#define VALID_LITERAL(c) ((c) == '\t' || ((c) >= ' ' && (c) <= '~' \
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/simple_providers.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/simple_providers.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/simple_providers.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/simple_providers.c Tue Mar 30 20:57:53 2010
@@ -202,7 +202,7 @@ svn_auth__simple_first_creds_helper(void
else
need_to_save = TRUE;
}
- }
+ }
/* See if we need to save this password if it is not present in
auth cache. */
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/skel.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/skel.c Tue Mar 30 20:57:53 2010
@@ -609,6 +609,24 @@ void svn_skel__prepend_str(const char *v
svn_skel__prepend(atom, skel);
}
+
+void svn_skel__append(svn_skel_t *list_skel, const svn_skel_t *skel)
+{
+ SVN_ERR_ASSERT_NO_RETURN(list_skel != NULL && !list_skel->is_atom);
+
+ if (list_skel->children == NULL)
+ {
+ list_skel->children = (svn_skel_t *)skel;
+ }
+ else
+ {
+ list_skel = list_skel->children;
+ while (list_skel->next != NULL)
+ list_skel = list_skel->next;
+ list_skel->next = (svn_skel_t *)skel;
+ }
+}
+
/* Examining skels. */
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/sorts.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/sorts.c Tue Mar 30 20:57:53 2010
@@ -196,7 +196,7 @@ bsearch_lower_bound(const void *key,
int
svn_sort__bsearch_lower_bound(const void *key,
- apr_array_header_t *array,
+ const apr_array_header_t *array,
int (*compare_func)(const void *, const void *))
{
return bsearch_lower_bound(key,
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/stream.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/stream.c Tue Mar 30 20:57:53 2010
@@ -456,7 +456,7 @@ svn_error_t *svn_stream_copy3(svn_stream
err = svn_stream_read(from, buf, &len);
if (err)
- break;
+ break;
if (len > 0)
err = svn_stream_write(to, buf, &len);
@@ -676,35 +676,6 @@ read_handler_apr(void *baton, char *buff
struct baton_apr *btn = baton;
svn_error_t *err;
- /* Check for range restriction. */
- if (btn->start >= 0 && btn->end > 0)
- {
- /* Get the current file position and make sure it is in range. */
- apr_off_t pos;
-
- pos = 0;
- SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &pos, btn->pool));
- if (pos < btn->start)
- {
- /* We're before the range, so forward the file cursor to
- * the start of the range. */
- pos = btn->start;
- SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &pos, btn->pool));
- }
- else if (pos >= btn->end)
- {
- /* We're past the range, indicate that no bytes can be read. */
- *len = 0;
- return SVN_NO_ERROR;
- }
- else
- {
- /* We're in range, but don't read over the end of the range. */
- if (pos + *len > btn->end)
- *len = btn->end - pos;
- }
- }
-
err = svn_io_file_read_full(btn->file, buffer, *len, len, btn->pool);
if (err && APR_STATUS_IS_EOF(err->apr_err))
{
@@ -846,12 +817,47 @@ svn_stream_from_aprfile2(apr_file_t *fil
return stream;
}
-svn_stream_t *
-svn_stream_from_aprfile(apr_file_t *file, apr_pool_t *pool)
+/* A read handler (#svn_read_fn_t) that forwards to read_handler_apr()
+ but only allows reading between BATON->start and BATON->end. */
+static svn_error_t *
+read_range_handler_apr(void *baton, char *buffer, apr_size_t *len)
{
- return svn_stream_from_aprfile2(file, TRUE, pool);
+ struct baton_apr *btn = baton;
+
+ /* ### BH: I think this can be simplified/optimized by just keeping
+ track of the current position. */
+
+ /* Check for range restriction. */
+ if (btn->start >= 0 && btn->end > 0)
+ {
+ /* Get the current file position and make sure it is in range. */
+ apr_off_t pos;
+
+ pos = 0;
+ SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &pos, btn->pool));
+ if (pos < btn->start)
+ {
+ /* We're before the range, so forward the file cursor to
+ * the start of the range. */
+ pos = btn->start;
+ SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &pos, btn->pool));
+ }
+ else if (pos >= btn->end)
+ {
+ /* We're past the range, indicate that no bytes can be read. */
+ *len = 0;
+ return SVN_NO_ERROR;
+ }
+
+ /* We're in range, but don't read over the end of the range. */
+ if (pos + *len > btn->end)
+ *len = (apr_size_t)(btn->end - pos);
+ }
+
+ return read_handler_apr(baton, buffer, len);
}
+
svn_stream_t *
svn_stream_from_aprfile_range_readonly(apr_file_t *file,
svn_boolean_t disown,
@@ -863,6 +869,7 @@ svn_stream_from_aprfile_range_readonly(a
svn_stream_t *stream;
apr_off_t pos;
+ /* ### HACK: These shortcuts don't handle disown FALSE properly */
if (file == NULL || start < 0 || end <= 0 || start >= end)
return svn_stream_empty(pool);
@@ -877,7 +884,7 @@ svn_stream_from_aprfile_range_readonly(a
baton->start = start;
baton->end = end;
stream = svn_stream_create(baton, pool);
- svn_stream_set_read(stream, read_handler_apr);
+ svn_stream_set_read(stream, read_range_handler_apr);
svn_stream_set_reset(stream, reset_handler_apr);
svn_stream_set_mark(stream, mark_handler_apr);
svn_stream_set_seek(stream, seek_handler_apr);
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/subst.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/subst.c Tue Mar 30 20:57:53 2010
@@ -769,9 +769,9 @@ struct translation_baton
apr_hash_t *keywords;
svn_boolean_t expand;
- /* Characters (excluding the terminating NUL character) which
+ /* 'short boolean' array that encodes what character values
may trigger a translation action, hence are 'interesting' */
- const char *interesting;
+ char interesting[256];
/* Length of the string EOL_STR points to. */
apr_size_t eol_str_len;
@@ -821,11 +821,21 @@ create_translation_baton(const char *eol
b->repair = repair;
b->keywords = keywords;
b->expand = expand;
- b->interesting = (eol_str && keywords) ? "$\r\n" : eol_str ? "\r\n" : "$";
b->newline_off = 0;
b->keyword_off = 0;
b->src_format_len = 0;
+ /* Most characters don't start translation actions.
+ * Mark those that do depending on the parameters we got. */
+ memset(b->interesting, FALSE, sizeof(b->interesting));
+ if (keywords)
+ b->interesting['$'] = TRUE;
+ if (eol_str)
+ {
+ b->interesting['\r'] = TRUE;
+ b->interesting['\n'] = TRUE;
+ }
+
return b;
}
@@ -938,14 +948,9 @@ translate_chunk(svn_stream_t *dst,
len = 0;
/* We wanted memcspn(), but lacking that, the loop below has
- the same effect.
-
- Also, skip NUL characters explicitly, since strchr()
- considers them part of the string argument,
- but we don't consider them interesting
+ the same effect. Also, skip NUL characters.
*/
- while ((p + len) < end
- && (! p[len] || ! strchr(interesting, p[len])))
+ while ((p + len) < end && !interesting[(unsigned char)p[len]])
len++;
if (len)
@@ -1033,6 +1038,7 @@ struct translated_stream_baton
};
+/* Implements svn_read_fn_t. */
static svn_error_t *
translated_stream_read(void *baton,
char *buffer,
@@ -1044,6 +1050,25 @@ translated_stream_read(void *baton,
apr_size_t off = 0;
apr_pool_t *iterpool;
+ /* Optimization for a frequent special case. The configuration parser (and
+ a few others) reads the stream one byte at a time. All the memcpy, pool
+ clearing etc. imposes a huge overhead in that case. In most cases, we
+ can just take that single byte directly from the read buffer.
+
+ Since *len > 1 requires lots of code to be run anyways, we can afford
+ the extra overhead of checking for *len == 1.
+
+ See <http://mail-archives.apache.org/mod_mbox/subversion-dev/201003.mbox/%3C4B94011E.1070207@alice-dsl.de%3E>.
+ */
+ if (unsatisfied == 1 && b->readbuf_off < b->readbuf->len)
+ {
+ /* Just take it from the read buffer */
+ *buffer = b->readbuf->data[b->readbuf_off++];
+
+ return SVN_NO_ERROR;
+ }
+
+ /* Standard code path. */
iterpool = b->iterpool;
while (readlen == SVN__STREAM_CHUNK_SIZE && unsatisfied > 0)
{
@@ -1086,6 +1111,7 @@ translated_stream_read(void *baton,
return SVN_NO_ERROR;
}
+/* Implements svn_write_fn_t. */
static svn_error_t *
translated_stream_write(void *baton,
const char *buffer,
@@ -1098,6 +1124,7 @@ translated_stream_write(void *baton,
return translate_chunk(b->stream, b->out_baton, buffer, *len, b->iterpool);
}
+/* Implements svn_close_fn_t. */
static svn_error_t *
translated_stream_close(void *baton)
{
@@ -1112,6 +1139,7 @@ translated_stream_close(void *baton)
return SVN_NO_ERROR;
}
+/* Implements svn_io_reset_fn_t. */
static svn_error_t *
translated_stream_reset(void *baton)
{
@@ -1136,6 +1164,7 @@ translated_stream_reset(void *baton)
return svn_error_return(err);
}
+/* Implements svn_io_mark_fn_t. */
static svn_error_t *
translated_stream_mark(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
{
@@ -1144,6 +1173,7 @@ translated_stream_mark(void *baton, svn_
return svn_error_return(svn_stream_mark(b->stream, mark, pool));
}
+/* Implements svn_io_seek_fn_t. */
static svn_error_t *
translated_stream_seek(void *baton, svn_stream_mark_t *mark)
{
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/svn_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/svn_string.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/svn_string.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/svn_string.c Tue Mar 30 20:57:53 2010
@@ -536,7 +536,7 @@ svn_cstring_split(const char *input,
svn_boolean_t svn_cstring_match_glob_list(const char *str,
- apr_array_header_t *list)
+ const apr_array_header_t *list)
{
int i;
Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_crawler.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_crawler.c Tue Mar 30 20:57:53 2010
@@ -74,6 +74,9 @@ restore_file(svn_wc__db_t *db,
SVN_ERR(svn_wc__get_pristine_contents(&src_stream, db, local_abspath, pool,
pool));
+ if (src_stream == NULL)
+ /* Nothing to restore. */
+ return SVN_NO_ERROR;
SVN_ERR(svn_wc__get_special(&special, db, local_abspath, pool));
if (special)
@@ -310,12 +313,12 @@ report_revisions_and_depths(svn_wc__db_t
svn_boolean_t depth_compatibility_trick,
svn_boolean_t report_everything,
svn_boolean_t use_commit_times,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
const char *dir_abspath;
const apr_array_header_t *children;
apr_hash_t *dirents;
- apr_pool_t *subpool = svn_pool_create(pool), *iterpool;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
const char *dir_repos_root, *dir_repos_relpath;
svn_depth_t dir_depth;
@@ -324,10 +327,10 @@ report_revisions_and_depths(svn_wc__db_t
/* Get both the SVN Entries and the actual on-disk entries. Also
notice that we're picking up hidden entries too (read_children never
hides children). */
- dir_abspath = svn_dirent_join(anchor_abspath, dir_path, subpool);
- SVN_ERR(svn_wc__db_read_children(&children, db, dir_abspath,
- subpool, subpool));
- SVN_ERR(svn_io_get_dir_filenames(&dirents, dir_abspath, subpool));
+ dir_abspath = svn_dirent_join(anchor_abspath, dir_path, scratch_pool);
+ SVN_ERR(svn_wc__db_base_get_children(&children, db, dir_abspath,
+ scratch_pool, iterpool));
+ SVN_ERR(svn_io_get_dir_filenames(&dirents, dir_abspath, scratch_pool));
/*** Do the real reporting and recursing. ***/
@@ -338,38 +341,35 @@ report_revisions_and_depths(svn_wc__db_t
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL,
db, dir_abspath,
- subpool, subpool));
+ scratch_pool, iterpool));
/* If the directory has no url, search its parents */
if (dir_repos_relpath == NULL)
SVN_ERR(svn_wc__db_scan_base_repos(&dir_repos_relpath, &dir_repos_root,
NULL, db, dir_abspath,
- subpool, subpool));
+ scratch_pool, iterpool));
/* If "this dir" has "svn:externals" property set on it, store its name
and depth in traversal_info. */
if (external_func)
{
SVN_ERR(read_traversal_info(db, dir_abspath, external_func,
- external_baton, dir_depth, subpool));
+ external_baton, dir_depth, iterpool));
}
/* Looping over current directory's SVN entries: */
- iterpool = svn_pool_create(subpool);
-
for (i = 0; i < children->nelts; ++i)
{
const char *child = APR_ARRAY_IDX(children, i, const char *);
const char *this_path, *this_abspath;
const char *this_repos_root_url, *this_repos_relpath;
- const char *this_original_repos_relpath;
svn_wc__db_status_t this_status;
svn_wc__db_kind_t this_kind;
- svn_revnum_t this_rev, this_base_rev;
+ svn_revnum_t this_rev;
svn_depth_t this_depth;
svn_wc__db_lock_t *this_lock;
- svn_boolean_t this_shadows_base, this_switched, replaced = FALSE;
-
+ svn_boolean_t this_switched;
+ svn_error_t *err;
/* Clear the iteration subpool here because the loop has a bunch
of 'continue' jump statements. */
@@ -379,15 +379,36 @@ report_revisions_and_depths(svn_wc__db_t
this_path = svn_dirent_join(dir_path, child, iterpool);
this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
- SVN_ERR(svn_wc__db_read_info(&this_status, &this_kind, &this_rev,
- &this_repos_relpath, &this_repos_root_url,
- NULL, NULL, NULL, NULL, NULL, &this_depth,
- NULL, NULL, NULL, NULL,
- &this_original_repos_relpath,
- NULL, NULL, NULL, NULL, NULL,
- &this_shadows_base, NULL,
- &this_lock,
- db, this_abspath, iterpool, iterpool));
+ err = svn_wc__db_base_get_info(&this_status, &this_kind, &this_rev,
+ &this_repos_relpath, &this_repos_root_url,
+ NULL, NULL, NULL, NULL, NULL, &this_depth,
+ NULL, NULL, NULL, &this_lock,
+ db, this_abspath, iterpool, iterpool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ svn_error_clear(err);
+ else
+ SVN_ERR(err);
+
+ /* ### While still using parent stubs: Fetch info from the stub.
+ Handles the error case above */
+ {
+ svn_boolean_t not_present;
+
+ SVN_ERR(svn_wc__db_temp_is_dir_deleted(¬_present, &this_rev, db,
+ this_abspath, iterpool));
+
+ if (not_present || err)
+ this_status = svn_wc__db_status_not_present;
+
+ if (!SVN_IS_VALID_REVNUM(this_rev))
+ this_rev = dir_rev; /* Obstructed node */
+ } /* /Stub handling */
+
+ if (this_depth == svn_depth_unknown)
+ this_depth = svn_depth_infinity;
+
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(this_rev));
/* First check for exclusion */
if (this_status == svn_wc__db_status_excluded)
@@ -422,75 +443,38 @@ report_revisions_and_depths(svn_wc__db_t
continue;
}
- if (this_kind == svn_wc__db_kind_dir)
- {
- svn_revnum_t del_rev;
- SVN_ERR(svn_wc__db_temp_is_dir_deleted(&replaced, &del_rev,
- db, this_abspath,
- iterpool));
- }
-
/*** The Big Tests: ***/
-
- if (this_shadows_base)
+ if (this_status == svn_wc__db_status_absent ||
+ this_status == svn_wc__db_status_excluded ||
+ this_status == svn_wc__db_status_not_present)
{
- svn_wc__db_status_t this_base_status;
- SVN_ERR(svn_wc__db_base_get_info(&this_base_status, NULL,
- &this_base_rev,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL,
- db, this_abspath,
- iterpool, iterpool));
-
- if (!replaced)
- replaced = (this_base_status == svn_wc__db_status_not_present);
- }
-
- {
- svn_boolean_t this_absent;
-
- if (replaced ||
- this_status == svn_wc__db_status_absent ||
- this_status == svn_wc__db_status_excluded ||
- this_status == svn_wc__db_status_not_present)
- {
- this_absent = TRUE;
- }
- else if (this_status == svn_wc__db_status_deleted && !this_shadows_base)
- this_absent = TRUE;
- else
- this_absent = FALSE;
-
- /* If the entry is 'deleted' or 'absent', make sure the server
- knows it's gone... */
- if (this_absent)
- {
- /* ...unless we're reporting everything, in which case we're
- going to report it missing later anyway. */
- if (! report_everything)
- SVN_ERR(reporter->delete_path(report_baton, this_path, iterpool));
- continue;
- }
- }
-
- /* From here on out, ignore any entry scheduled for addition */
- if ((this_status == svn_wc__db_status_added) ||
- (this_status == svn_wc__db_status_obstructed_add))
- {
- if (!replaced)
+ /* If the entry is 'deleted' or 'absent', make sure the server
+ knows it's gone...
+ ...unless we're reporting everything, in which case we're
+ going to report it missing later anyway. */
+ if (! report_everything)
+ SVN_ERR(reporter->delete_path(report_baton, this_path, iterpool));
continue;
-
- if (!this_shadows_base && this_original_repos_relpath)
- continue; /* Skip copy roots (and all children) */
- }
+ }
/* Is the entry on disk? */
if (apr_hash_get(dirents, child, APR_HASH_KEY_STRING) == NULL)
{
svn_boolean_t missing = FALSE;
- if (restore_files && this_status != svn_wc__db_status_deleted
- && !replaced)
+ svn_wc__db_status_t wrk_status;
+ svn_wc__db_kind_t wrk_kind;
+
+ SVN_ERR(svn_wc__db_read_info(&wrk_status, &wrk_kind, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL,
+ db, this_abspath, iterpool, iterpool));
+
+ if (restore_files && wrk_status != svn_wc__db_status_added
+ && wrk_status != svn_wc__db_status_deleted
+ && wrk_status != svn_wc__db_status_obstructed_add
+ && wrk_status != svn_wc__db_status_obstructed_delete)
{
svn_node_kind_t dirent_kind;
@@ -503,7 +487,7 @@ report_revisions_and_depths(svn_wc__db_t
if (dirent_kind == svn_node_none)
{
svn_boolean_t restored;
- SVN_ERR(restore_node(&restored, db, this_abspath, this_kind,
+ SVN_ERR(restore_node(&restored, db, this_abspath, wrk_kind,
use_commit_times, notify_func,
notify_baton, iterpool));
@@ -514,11 +498,11 @@ report_revisions_and_depths(svn_wc__db_t
else
missing = TRUE;
- /* If a directory is missing from disk, we have no way to
- recreate it locally, so report as missing and move
- along. Again, don't bother if we're reporting
- everything, because the dir is already missing on the server. */
- if (missing && this_kind == svn_wc__db_kind_dir
+ /* If a node is still missing from disk here, we have no way to recreate
+ it locally, so report as missing and move along. Again, don't bother
+ if we're reporting everything, because the dir is already missing on
+ the server. */
+ if (missing && wrk_kind == svn_wc__db_kind_dir
&& (depth > svn_depth_files || depth == svn_depth_unknown))
{
if (! report_everything)
@@ -546,32 +530,19 @@ report_revisions_and_depths(svn_wc__db_t
this_switched = FALSE;
}
- if (this_depth == svn_depth_unknown)
- this_depth = svn_depth_infinity;
-
- if (this_rev == SVN_INVALID_REVNUM)
- {
- /* For added and replaced nodes use their base revision
- in reports */
- this_rev = this_shadows_base ? this_base_rev : dir_rev;
- }
-
/*** Files ***/
if (this_kind == svn_wc__db_kind_file ||
this_kind == svn_wc__db_kind_symlink)
{
- const char *url = NULL;
-
- if (this_switched)
- url = svn_path_url_add_component2(dir_repos_root, this_repos_relpath, iterpool);
-
if (report_everything)
{
/* Report the file unconditionally, one way or another. */
if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_path,
- url,
+ svn_path_url_add_component2(
+ dir_repos_root,
+ this_repos_relpath, iterpool),
this_rev,
this_depth,
FALSE,
@@ -588,10 +559,12 @@ report_revisions_and_depths(svn_wc__db_t
}
/* Possibly report a disjoint URL ... */
- else if (this_switched && !this_shadows_base)
+ else if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_path,
- url,
+ svn_path_url_add_component2(
+ dir_repos_root,
+ this_repos_relpath, iterpool),
this_rev,
this_depth,
FALSE,
@@ -616,14 +589,8 @@ report_revisions_and_depths(svn_wc__db_t
&& (depth > svn_depth_files
|| depth == svn_depth_unknown))
{
- const char *url = NULL;
- svn_boolean_t start_empty;
svn_boolean_t is_incomplete = (this_status == svn_wc__db_status_incomplete);
-
- if (this_switched)
- url = svn_path_url_add_component2(dir_repos_root, this_repos_relpath, iterpool);
-
- start_empty = is_incomplete;
+ svn_boolean_t start_empty = is_incomplete;
if (depth_compatibility_trick
&& this_depth <= svn_depth_files
@@ -638,11 +605,14 @@ report_revisions_and_depths(svn_wc__db_t
if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_path,
- url,
+ svn_path_url_add_component2(
+ dir_repos_root,
+ this_repos_relpath, iterpool),
this_rev,
this_depth,
start_empty,
- this_lock ? this_lock->token : NULL,
+ this_lock ? this_lock->token
+ : NULL,
iterpool));
else
SVN_ERR(reporter->set_path(report_baton,
@@ -658,7 +628,9 @@ report_revisions_and_depths(svn_wc__db_t
else if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_path,
- url,
+ svn_path_url_add_component2(
+ dir_repos_root,
+ this_repos_relpath, iterpool),
this_rev,
this_depth,
start_empty,
@@ -704,7 +676,7 @@ report_revisions_and_depths(svn_wc__db_t
} /* end main entries loop */
/* We're done examining this dir's entries, so free everything. */
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -788,106 +760,133 @@ svn_wc_crawl_revisions5(svn_wc_context_t
void *external_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = wc_ctx->db;
svn_error_t *fserr, *err;
- svn_revnum_t base_rev = SVN_INVALID_REVNUM, target_rev;
+ svn_revnum_t target_rev = SVN_INVALID_REVNUM;
svn_boolean_t missing = FALSE;
svn_boolean_t start_empty;
svn_wc__db_status_t status;
- svn_wc__db_kind_t target_kind;
- const char *repos_relpath, *repos_root_url;
- svn_depth_t target_depth;
- svn_boolean_t replaced = FALSE;
- svn_wc__db_lock_t *target_lock;
- svn_boolean_t target_exists = TRUE;
+ svn_wc__db_kind_t target_kind = svn_wc__db_kind_unknown;
+ const char *repos_relpath=NULL, *repos_root=NULL;
+ svn_depth_t target_depth = svn_depth_unknown;
+ svn_wc__db_lock_t *target_lock = NULL;
+ svn_boolean_t explicit_rev;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
/* The first thing we do is get the base_rev from the working copy's
ROOT_DIRECTORY. This is the first revnum that entries will be
compared to. */
- err = svn_wc__db_read_info(&status, &target_kind, &target_rev,
- &repos_relpath, &repos_root_url,
- NULL, NULL, NULL, NULL, NULL,
- &target_depth, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &target_lock,
- db, local_abspath, pool, pool);
+ err = svn_wc__db_base_get_info(&status, &target_kind, &target_rev,
+ &repos_relpath, &repos_root,
+ NULL, NULL, NULL, NULL, NULL,
+ &target_depth, NULL, NULL, NULL,
+ &target_lock,
+ db, local_abspath, scratch_pool,
+ scratch_pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_return(err);
+ {
+ svn_boolean_t has_base = TRUE;
- svn_error_clear(err);
- target_exists = FALSE;
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_return(err);
- /* Set output values of svn_wc__db_read_info to their empty values */
- status = svn_wc__db_status_not_present;
- target_kind = svn_wc__db_kind_unknown;
- target_rev = -1;
- repos_relpath = NULL;
- repos_root_url = NULL;
- target_depth = svn_depth_unknown;
- target_lock = NULL;
- }
+ svn_error_clear(err);
+ has_base = FALSE;
+ SVN_ERR(svn_wc__db_read_kind(&target_kind, db, local_abspath, TRUE,
+ scratch_pool));
- if (status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__internal_is_replaced(&replaced, db, local_abspath, pool));
+ if (target_kind == svn_wc__db_kind_file
+ || target_kind == svn_wc__db_kind_symlink)
+ status = svn_wc__db_status_absent; /* Crawl via parent dir */
+ else
+ status = svn_wc__db_status_not_present; /* As checkout */
+ }
- if (!target_exists ||
- (status == svn_wc__db_status_not_present) ||
- (target_kind == svn_wc__db_kind_dir && !replaced &&
- (status == svn_wc__db_status_added ||
- status == svn_wc__db_status_absent ||
- status == svn_wc__db_status_excluded ||
- status == svn_wc__db_status_obstructed ||
- status == svn_wc__db_status_obstructed_add ||
- status == svn_wc__db_status_obstructed_delete)))
- {
- /* Don't check the exclude flag for the target.
-
- If we report the target itself as excluded, the server will
- send us nothing about the target -- but we want to permit
- targets to be explicitly pulled in. For example, 'svn up A'
- should always work, even if its parent is svn_depth_empty or
- svn_depth_files, or even if A was explicitly excluded from a
- parent at svn_depth_immediates or svn_depth_infinity.
- Whatever the case, we want A back now. */
+ /* ### Check the parentstub if we don't find a BASE. But don't
+ do this if we already have the info we want or we break
+ some copy scenarios. */
+ if (!has_base && target_kind == svn_wc__db_kind_dir)
+ {
+ svn_boolean_t not_present;
+ svn_revnum_t rev = SVN_INVALID_REVNUM;
+ err = svn_wc__db_temp_is_dir_deleted(¬_present, &rev,
+ db, local_abspath, scratch_pool);
- if (!SVN_IS_VALID_REVNUM(base_rev))
- {
- const char *dir_abspath = svn_dirent_dirname(local_abspath, pool);
+ if (err && (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
+ || err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY))
+ {
+ svn_error_clear(err);
+ not_present = FALSE;
+ }
+ else
+ SVN_ERR(err);
- SVN_ERR(find_base_rev(&base_rev, db, dir_abspath, dir_abspath,
- pool));
- }
+ if (not_present)
+ status = svn_wc__db_status_not_present;
+
+ if (!SVN_IS_VALID_REVNUM(target_rev))
+ target_rev = rev;
+ }
+ }
+
+ if ((status == svn_wc__db_status_not_present)
+ || (target_kind == svn_wc__db_kind_dir
+ && status != svn_wc__db_status_normal
+ && status != svn_wc__db_status_incomplete))
+ {
+ /* The target does not exist or is a local addition */
- /* There aren't any versioned paths to crawl which are known to
- the repository. */
+ if (!SVN_IS_VALID_REVNUM(target_rev))
+ target_rev = 0;
- /* If no versioned path exists, we use the requested depth, which
- is the depth at which the new path should be brought in. Default
- to infinity if no explicit depth was given. */
if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
- SVN_ERR(reporter->set_path(report_baton, "", base_rev, depth,
- status == svn_wc__db_status_incomplete,
- target_lock ? target_lock->token : NULL,
- pool));
- SVN_ERR(reporter->delete_path(report_baton, "", pool));
+ SVN_ERR(reporter->set_path(report_baton, "", target_rev, depth,
+ FALSE,
+ NULL,
+ scratch_pool));
+ SVN_ERR(reporter->delete_path(report_baton, "", scratch_pool));
/* Finish the report, which causes the update editor to be
driven. */
- return reporter->finish_report(report_baton, pool);
+ SVN_ERR(reporter->finish_report(report_baton, scratch_pool));
+
+ return SVN_NO_ERROR;
}
- base_rev = target_rev;
+ if (!repos_root || !repos_relpath)
+ {
+ err = svn_wc__db_scan_base_repos(&repos_relpath, &repos_root, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ svn_error_clear(err);
+ else
+ SVN_ERR(err);
- if (!SVN_IS_VALID_REVNUM(base_rev))
- SVN_ERR(find_base_rev(&base_rev, db, local_abspath, local_abspath, pool));
+ /* Ok, that leaves a local addition. Deleted and not existing nodes
+ are already handled. */
+ if (!repos_root || !repos_relpath)
+ SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
+ &repos_root, NULL, NULL, NULL, NULL,
+ NULL, db, local_abspath,
+ scratch_pool, scratch_pool));
+ }
+
+ if (!SVN_IS_VALID_REVNUM(target_rev))
+ {
+ SVN_ERR(find_base_rev(&target_rev, db, local_abspath, local_abspath,
+ scratch_pool));
+ explicit_rev = TRUE;
+ }
+ else
+ explicit_rev = FALSE;
start_empty = (status == svn_wc__db_status_incomplete);
if (depth_compatibility_trick
@@ -903,13 +902,13 @@ svn_wc_crawl_revisions5(svn_wc_context_t
/* The first call to the reporter merely informs it that the
top-level directory being updated is at BASE_REV. Its PATH
argument is ignored. */
- SVN_ERR(reporter->set_path(report_baton, "", base_rev, target_depth,
- start_empty, NULL, pool));
+ SVN_ERR(reporter->set_path(report_baton, "", target_rev, target_depth,
+ start_empty, NULL, scratch_pool));
if (status != svn_wc__db_status_deleted)
{
apr_finfo_t info;
- err = svn_io_stat(&info, local_abspath, APR_FINFO_MIN, pool);
+ err = svn_io_stat(&info, local_abspath, APR_FINFO_MIN, scratch_pool);
if (err)
{
if (APR_STATUS_IS_ENOENT(err->apr_err))
@@ -926,7 +925,7 @@ svn_wc_crawl_revisions5(svn_wc_context_t
err = restore_node(&restored, wc_ctx->db, local_abspath,
target_kind, use_commit_times,
notify_func, notify_baton,
- pool);
+ scratch_pool);
if (err)
goto abort_report;
@@ -941,7 +940,7 @@ svn_wc_crawl_revisions5(svn_wc_context_t
{
/* Report missing directories as deleted to retrieve them
from the repository. */
- err = reporter->delete_path(report_baton, "", pool);
+ err = reporter->delete_path(report_baton, "", scratch_pool);
if (err)
goto abort_report;
}
@@ -952,7 +951,7 @@ svn_wc_crawl_revisions5(svn_wc_context_t
err = report_revisions_and_depths(wc_ctx->db,
local_abspath,
"",
- base_rev,
+ target_rev,
reporter, report_baton,
external_func, external_baton,
notify_func, notify_baton,
@@ -961,7 +960,7 @@ svn_wc_crawl_revisions5(svn_wc_context_t
depth_compatibility_trick,
start_empty,
use_commit_times,
- pool);
+ scratch_pool);
if (err)
goto abort_report;
}
@@ -971,93 +970,82 @@ svn_wc_crawl_revisions5(svn_wc_context_t
target_kind == svn_wc__db_kind_symlink)
{
svn_boolean_t skip_set_path = FALSE;
-
- if (repos_relpath)
- {
- const char *parent_abspath, *base;
- svn_wc__db_status_t parent_status;
- const char *parent_repos_relpath;
-
- svn_dirent_split(local_abspath, &parent_abspath, &base, pool);
-
- /* We can assume a file is in the same repository as its parent
- directory, so we only look at the relpath. */
- err = svn_wc__db_read_info(&parent_status, NULL, NULL,
+ const char *parent_abspath, *base;
+ svn_wc__db_status_t parent_status;
+ const char *parent_repos_relpath;
+
+ svn_dirent_split(local_abspath, &parent_abspath, &base,
+ scratch_pool);
+
+ /* We can assume a file is in the same repository as its parent
+ directory, so we only look at the relpath. */
+ err = svn_wc__db_base_get_info(&parent_status, NULL, NULL,
&parent_repos_relpath, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, parent_abspath, pool, pool);
+ NULL, NULL,
+ db, parent_abspath,
+ scratch_pool, scratch_pool);
- if (err)
- goto abort_report;
+ if (err)
+ goto abort_report;
- if (!parent_repos_relpath &&
- parent_status == svn_wc__db_status_added)
- {
- err = svn_wc__db_scan_addition(NULL, NULL,
- &parent_repos_relpath, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, parent_abspath,
- pool, pool);
- }
- else if (!parent_repos_relpath)
- err = svn_wc__db_scan_base_repos(&parent_repos_relpath, NULL,
- NULL,
- db, parent_abspath,
- pool, pool);
+ if (!parent_repos_relpath)
+ err = svn_wc__db_scan_base_repos(&parent_repos_relpath, NULL,
+ NULL,
+ db, parent_abspath,
+ scratch_pool, scratch_pool);
+
+ if (err)
+ goto abort_report;
+ if (strcmp(repos_relpath,
+ svn_relpath_join(parent_repos_relpath, base,
+ scratch_pool)) != 0)
+ {
+ /* This file is disjoint with respect to its parent
+ directory. Since we are looking at the actual target of
+ the report (not some file in a subdirectory of a target
+ directory), and that target is a file, we need to pass an
+ empty string to link_path. */
+ err = reporter->link_path(report_baton,
+ "",
+ svn_path_url_add_component2(
+ repos_root,
+ repos_relpath,
+ scratch_pool),
+ target_rev,
+ target_depth,
+ FALSE,
+ target_lock ? target_lock->token : NULL,
+ scratch_pool);
if (err)
goto abort_report;
-
- if (strcmp(repos_relpath,
- svn_relpath_join(parent_repos_relpath, base, pool)) != 0)
- {
- /* This file is disjoint with respect to its parent
- directory. Since we are looking at the actual target of
- the report (not some file in a subdirectory of a target
- directory), and that target is a file, we need to pass an
- empty string to link_path. */
- err = reporter->link_path(report_baton,
- "",
- svn_path_url_add_component2(
- repos_root_url,
- repos_relpath,
- pool),
- base_rev,
- target_depth,
- FALSE,
- target_lock ? target_lock->token : NULL,
- pool);
- if (err)
- goto abort_report;
- skip_set_path = TRUE;
- }
+ skip_set_path = TRUE;
}
- if (!skip_set_path && (target_rev != base_rev || target_lock))
+ if (!skip_set_path && (explicit_rev || target_lock))
{
/* If this entry is a file node, we just want to report that
node's revision. Since we are looking at the actual target
of the report (not some file in a subdirectory of a target
directory), and that target is a file, we need to pass an
empty string to set_path. */
- err = reporter->set_path(report_baton, "", base_rev,
+ err = reporter->set_path(report_baton, "", target_rev,
target_depth,
FALSE,
target_lock ? target_lock->token : NULL,
- pool);
+ scratch_pool);
if (err)
goto abort_report;
}
}
/* Finish the report, which causes the update editor to be driven. */
- return reporter->finish_report(report_baton, pool);
+ return reporter->finish_report(report_baton, scratch_pool);
abort_report:
/* Clean up the fs transaction. */
- if ((fserr = reporter->abort_report(report_baton, pool)))
+ if ((fserr = reporter->abort_report(report_baton, scratch_pool)))
{
fserr = svn_error_quick_wrap(fserr, _("Error aborting report"));
svn_error_compose(err, fserr);
@@ -1082,6 +1070,7 @@ struct copying_stream_baton
};
+/* */
static svn_error_t *
read_handler_copy(void *baton, char *buffer, apr_size_t *len)
{
@@ -1092,6 +1081,7 @@ read_handler_copy(void *baton, char *buf
return svn_stream_write(btn->target, buffer, len);
}
+/* */
static svn_error_t *
close_handler_copy(void *baton)
{
@@ -1152,8 +1142,9 @@ svn_wc__internal_transmit_text_deltas(co
SVN_WC_TRANSLATE_TO_NF,
scratch_pool, scratch_pool));
- /* Alert the caller that we have created a temporary file that might
- need to be cleaned up, if he asked for one. */
+ /* If the caller wants a copy of the working file translated to
+ * repository-normal form, make the copy by tee-ing the stream and set
+ * *TEMPFILE to the path to it. */
if (tempfile)
{
const char *tmp_base;
@@ -1188,6 +1179,8 @@ svn_wc__internal_transmit_text_deltas(co
/* Compute delta against the pristine contents */
SVN_ERR(svn_wc__get_pristine_contents(&base_stream, db, local_abspath,
scratch_pool, scratch_pool));
+ if (base_stream == NULL)
+ base_stream = svn_stream_empty(scratch_pool);
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL,
NULL, NULL, NULL,
@@ -1218,7 +1211,10 @@ svn_wc__internal_transmit_text_deltas(co
/* ### we should ALREADY have the checksum for pristine. */
SVN_ERR(svn_wc__get_pristine_contents(&p_stream, db, local_abspath,
- scratch_pool, scratch_pool));
+ scratch_pool, scratch_pool));
+ if (p_stream == NULL)
+ p_stream = svn_stream_empty(scratch_pool);
+
p_stream = svn_stream_checksummed2(p_stream, &p_checksum,
NULL, svn_checksum_md5, TRUE,
scratch_pool);