Hi Paul. Thanks for the comprehensive reply and sorry for the wait. Responses in line.
On Tue, 2011-07-12, Paul Burba wrote: > On Fri, Jul 8, 2011 at 1:04 PM, Julian Foad <julian.f...@wandisco.com> wrote: > > Hi Paul. That looks good. I have some queries and suggestions about > > the details, not all related specifically to this change, which I'm > > attaching in the form of a patch (not to be committed as-is), which I'd > > like your feedback on. > > Hi Julian, > > Sorry for the long wait, your questions have prompted some extensive > thinking about this issue #3668 and issue #3669 code. > > I've included the feedback on the patch inline at the end of this message. > > > I wonder, do any callers really want to receive invalid mergeinfo? Is > > this optional just because the server-side processing is slow and some > > callers don't care? > > It doesn't matter to some callers (merge.c:calculate_left_hand_side(), > merge.c:find_unmerged_mergeinfo()), so they don't impose the overhead > on the server... > > ...but sometimes we really do want the invalid mergeinfo -- see my > comments on your patch for merge.c:get_full_mergeinfo(). > > > I noticed some functions take an 'ignore_invalid_mergeinfo' parameter; > > that confused me because I thought it was referring to the same thing > > but instead it refers to a syntatically invalid svn:mergeinfo property > > value. > > > By contrast, what we're dealing with in the 'invalid_inherited' > > case is mergeinfo that's syntactically valid but semantically invalid or > > at least redundant because it refers to non-existent path-revs. I > > wonder if it would be worth either using a different term (I know there > > are loads of terms already, which can be confusing in itself) > > It would be more accurate to compare the boolean > ignore_invalid_mergeinfo parameter to the boolean > validate_inherited_mergeinfo parameter. Those are both input > parameters where 'invalid_inherited' is an svn_mergeinfo_t output > parameter. I'm very open to any suggested name changes, but there's > no getting away from the reality that there are a lot of terms. > > I have been guilty of occasionally referring to non-existent path-rev > mergeinfo (which is otherwise syntactically valid) as "invalid" in > some comments. I'll clean that up to the extent possible, but I do > rely on context at times to point to which type of "invalid" I'm > talking about (it is such a useful word after all :-) Well, it's not just comments: there is this function called get_invalid_inherited_mergeinfo() that returns its result in a parameter called "invalid_inherited_mergeinfo". But maybe that's the only remaining place where 'invalid' is used in that sense, I haven't checked. > > or > > otherwise working towards simply eliminating this kind of mergeinfo from > > our attention altogether by never exposing it and never giving the > > caller the choice. > > Your question has prompted me to change the default behavior of > svn_client__get_wc_or_repos_mergeinfo and > svn_client__get_wc_or_repos_mergeinfo_catalog such that they always > request inherited mergeinfo validation *if* contacting the server. I > can't see that any callers actually rely on the previous behavior and > I'd rather default to correct mergeinfo and deal with the problems (if > any) that causes. Sounds good. > [[[ > > Index: subversion/libsvn_client/merge.c > > =================================================================== [re. get_invalid_inherited_mergeinfo()] > > Query the repository for the mergeinfo TARGET_ABSPATH inherits at its > > - base revision and set *VALIDATED to indicate to the caller if we can > > - determine what portions of that inherited mergeinfo are invalid. > > + base revision. > > > > If no mergeinfo is inherited set *INVALID_INHERITED_MERGEINFO to NULL. > > > > If only empty mergeinfo is inherited set *INVALID_INHERITED_MERGEINFO to > > an empty hash. > > > > - If non-empty inherited mergeinfo is inherited then, if the server > > + If non-empty mergeinfo is inherited then, if the server > > supports the SVN_RA_CAPABILITY_VALIDATE_INHERITED_MERGEINFO capability, > > remove all valid path-revisions from the raw inherited mergeinfo, and set > > *INVALID_INHERITED_MERGEINFO to the remainder. > > > > + If non-empty mergeinfo is inherited but the server does not > > + support the SVN_RA_CAPABILITY_VALIDATE_INHERITED_MERGEINFO capability, > > + then ... ###? > > If the server does not have this capability and non-empty mergeinfo is > inherited, then *INVALID_INHERITED_MERGEINFO would be set to an empty > hash...*BUT* this function is only intended to be called if the server > has that capability. I'll add that to the doc string. Thanks. > > Note that if validation occurs, but all inherited mergeinfo describes > > - non-existent paths, then *INVALID_INHERITED_MERGEINFO is set to an empty > > - hash. > > + existent paths, then *INVALID_INHERITED_MERGEINFO is set to an empty > > hash. > > Your change is the complete opposite of what the code is doing, but > perhaps it's because the original wording isn't clear enough. How's > this instead: > > Note that if validation occurs and all inherited mergeinfo is > discarded as non-existent, then *INVALID_INHERITED_MERGEINFO is set to > an empty hash. That (and your r1145653 edit) still looks the wrong way around. Because, unless I'm misreading the double-negatives, this function supposedly returns a set of mergeinfo that refers to *non-existent* path-revs. > I reworked this entire doc string in r1145653. Hopefully it makes bit > more sense now. It's good apart from the bit above, thanks. > > + /* ### JAF: Why is the variable called "inherited" when the output > > + * parameter from that function is called "indirect"? I'm unsure > > + * whether these words mean the same thing or else whether one > > + * implies the other. */ > > if (indirect) > > *indirect = inherited; > > They are synonymous, I purged use of the 'indirect' term in r1145202 Thanks. > > + /* ### JAF: What are we doing here? We're asking for the > > *invalid* > > + * inherited mergeinfo (of TARGET_ABSPATH), and removing that > > from > > + * the total mergeinfo (of TARGET_ABSPATH) that was obtained from > > + * svn_client__get_wc_or_repos_mergeinfo(), so that we end up > > with > > + * what's known as 'validated' mergeinfo. > > What's going on here is [...] > So we want to keep what README inherits from its working copy parent > less any inherited mergeinfo that the repository can confirm describes > non-existent paths. OK, now I understand. Thank you for taking the time to spell this out. > In r1145653 I conditioned this block so it only occurs when mergeinfo > is inherited from the working copy. We could further optimize this by > only entering the block if the target inherits mergeinfo from a > working copy parent with local mergeinfo changes, but I want to get > your feedback first. I'm tempted to think of radically different ways of achieving the desired result, and I suggest leaving it as it is now, not trying to optimize it further. I might see if I can put a comment in here that would have helped me. (I know that, as a new reader, the things I want to know are not necessarily the things that you as the writer would always think of writing.) > > But this is the only > > + * use of get_invalid_inherited_mergeinfo() - to remove the > > + * invalid mergeinfo from the result of another function. It > > + * seems this should be done (and could be done more efficiently) > > + * by asking svn_client__get_wc_or_repos_mergeinfo() to ignore > > + * invalid mergeinfo, and indeed its counterpart > > + * svn_client__get_wc_or_repos_mergeinfo_catalog(), which it > > + * calls, already has an option to do so. */ > > As I think you realized based on your other questions, the > ignore_invalid_mergeinfo parameter has nothing to do with validating > inherited mergeinfo parameter. Oh yes, I did realize after writing that that the param I referred to isn't the one we need. > > Index: subversion/libsvn_client/mergeinfo.c > > =================================================================== > > svn_boolean_t validate_inherited_mergeinfo = FALSE; > > + /* ### JAF: Shouldn't we use a passed-in parameter instead? > > */ > > I got rid of the needless local variable in r1145653 but I don't > follow what you want re a passed-in parameter. Thanks. I was probably a bit confused; ignore that. > > Index: subversion/libsvn_client/mergeinfo.h > > =================================================================== > > - If the *TARGET_MERGEINFO for REL_PATH path is inherited and > > - *VALIDATE_INHERITED_MERGEINFO is TRUE, then *TARGET_MERGEINFO > > - will only contain merge source path-revisions that actually > > - exist in repository. > > - > > - If the *TARGET_MERGEINFO for REL_PATH path is inherited, > > + If the mergeinfo for REL_PATH path is inherited, > > VALIDATE_INHERITED_MERGEINFO is TRUE, and the server supports > > the #SVN_RA_CAPABILITY_VALIDATE_INHERITED_MERGEINFO capability, > > - then request that the server validate the mergeinfo in > > - *TARGET_MERGEINFO, so it contains only merge source path-revisions > > - that actually exist in repository. */ > > + then *TARGET_MERGEINFO will only contain merge source path-revisions > > + that actually exist in the repository. */ > > Committed this bit in r1145269. Thanks. > > Index: subversion/libsvn_ra_neon/options.c > > =================================================================== > > - if (strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO) == 0) > > - apr_hash_set(ras->capabilities, > > - SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING, > > - cap_result); > > - else > > - apr_hash_set(ras->capabilities, > > - SVN_RA_CAPABILITY_VALIDATE_INHERITED_MERGEINFO, > > - APR_HASH_KEY_STRING, cap_result); > > + apr_hash_set(ras->capabilities, > > + capability, APR_HASH_KEY_STRING, cap_result); > > There are no guarantees that the hash key you use here, the CAPABILITY > argument to svn_ra_neon__has_capability(), has the necessary lifetime. > What if the caller of svn_ra_has_capability didn't pass a string > literal? Unlikely I know, but possible. OK. We could strdup it ... but never mind. Just looking, as always, for simplifications. - Julian