On 4/12/17 10:44 PM, Gregory Szorc wrote:
I just read this entire thread and am trying to wrap my head around different sides of the argument. I clearly see where Durham, Ryan, and others are coming from with "strip-based operations are bad." I think we can all agree on that. I can also see how the new hiding mechanism is effectively the same as strip-based operations in terms of behavior, but without the poor performance and hacks. So it seems like a generally good idea. But I'm having difficulty comprehending Pierre-Yves's opposition to this seemingly good proposal. Pierre-Yves has thought about evolution concepts more than anyone, so when he raises an alarm, it is worth taking the time to listen and understand his concerns so we don't jeopardize the future of evolve. However, despite the vast amount of words written, it still isn't clear to me exactly what the main objection is. But from seeing "global state" and "monotonic" enough times and reading through https://www.mercurial-scm.org/wiki/CEDConcept <https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_wiki_CEDConcept&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=nuarHzhP1wi1T9iURRCj1A&m=P4L1wyyuErdKv1jvHswuE4jmAIfQ_TO0FXg9EjEkN_o&s=7Ttw0QZoZoUkJujhNsmSQlKkC2kJ29T1Mtj2_r4jEQg&e=>, I think I have an idea. (Pierre-Yves: please confirm or correct what I'm about to say.) I think most of Pierre-Yves's concerns are rooted at a *potential* intrinsic incompatibility between a) a generic, non-versioned, non-monotonic hiding mechanism (the proposal) and b) what is essentially obsolescence markers of today. For example, if the new hiding mechanism isn't designed with consideration for evolve, evolve/Mercurial would see an instruction to hide a changeset but evolve would be powerless to make any kind of reasonable judgement based on the "why" and "how" that changeset became hidden because that data just isn't recorded. In other words, generic hiding lacks the "global state" and "monotonic" properties of the obsolescence store and its exchange, making evolve less effective. This *would* undermine the ability to ship a high quality product: so Pierre-Yves isn't using hyperbole when he says he fears that he could deliver evolve depending on how this hiding feature is implemented.
I think your analysis is correct. There are trade offs: A completely mutable hidden store would hinder certain types of analysis in the future. A append-only-obsmarker based hidden would prevent certain types of user interactions in the future (ex: unhiding).
I believe optimizing for the 'certain types of analysis' case is optimizing for an edge case of an edge case workflow (mutable history conflicts within mutable history collaboration) at the expense of the common case workflows (local history mutation, commit revival, commit hiding mental model, and simple client/server workflows).
In my understanding, the actual user experience impact on evolve of this proposal (vs the theory oriented impact) is that *if* the user is doing mutable history collaboration, and *if* they have a mutable history conflict of some type, and *if* they've messed with visibility themselves, *then* evolve would be unable to determine the correct result and would have to prompt the user. I might be over simplifying, so I agree that concrete examples would help understand the impact of this change.
So, in my head having 'hg hide/unhide' be a dead simple, understandable (for both users and extensions) primitive in all cases is highly desirable, and is worth the trade off.
Regardless of whether this is actually Pierre-Yves's fundamental concern, there is a conflict here that needs addressed. And I /think/ that conflict can be summarized as "how do we ensure that evolve is the sole source of truth for hidden/obsolescence data?" Because if evolve isn't the sole source of truth for hidden/obsolescence data, then evolve has to essentially guess at what to do with changesets hidden for "unknown" reasons and that severely undermines the ability of evolve to work well.
As mentioned above, it only undermines evolve's ability if the user actually did manual visibility manipulations. If they didn't, then things work exactly as they do today. And the remediation in the failure case is to just tell the user "hey, you have to choose between action A or action B". This doesn't sound so bad, especially if this prompt is going to be part of certain evolve workflows anyway (since there will almost certainly exist ambiguous situations in even the most well designed evolve world).
What I think this means is that we need writes to a generic hiding mechanism and evolve/obsolescence markers to be mutually exclusive. I.e. if obsolescence markers are active, we can't be hiding things via not-obsolescence-markers because doing so would deprive evolve of critical knowledge.
We'll want obsmarker data even in a non-evolve world. See my restack proposal for how obs information can be useful as simply metadata about history, regardless of how hidden is computed. But, the two algorithms for hiding could be mutually exclusive (with obsmarkers enabled for both).
So, we can have a generic hiding mechanism in core Mercurial. We can lean on that mechanism in the vanilla Mercurial configuration to hide changesets so we don't have to strip. And, depending on how it is implemented, obsolescence markers could potentially use that mechanism for efficient hidden calculation (e.g. if it is a bitmap on disk computed from obsolescence markers data). But what is extremely undesirable from the perspective of evolve are writes to that hidden "store" coming from not-evolve when evolve is active. If my assessment is correct, I think I have a relatively simple solution to this mess: 1) a unified API in core for "hiding" changesets. It writes directly to a generic store or to obsolescence (if enabled). This is the only way to "hide" a changeset. 2) clients refusing to write generic hidden data when obsolescence is used. This will prevent evolve from encountering hidden changesets lacking "global state" and "monotonic" properties. 3) any user-facing commands or behavior related to generic hiding (such as `hg update <hidden>` unhiding a changeset) need to be disabled or changed when obsolescence is enabled because they break the needs of evolve to have "global state" and "monotonic" properties. (If #2 is implemented, anything attempting to hide/unhide without obsolescence markers would break. So this point follows as a consequence of #2.) 4) a mechanism to "upgrade" a repo using generic hiding data to use obsolescence. This may involve some kind of special, local-only obsolescence marker that basically says "obsoleted in local storage" so when that changeset is pulled from a remote, it can be unhidden without the the nasty implications of breaking "global state" and "monotonic" properties (because these properties didn't exist in the first place). Alternatively, we could just say "sorry, you can't use both at the same time: run `hg debugupgraderepo --gc` to prune the store of pre-evolve data" and then evolve can "own" all hidden data from what is effectively a fresh clone. #3 poses some interesting UX problems. You ideally want end-user facing concepts and commands to remain similar for evolve and non-evolve users. But if you want evolve to have its "global state" and "monotonic" properties, that necessitates significant behavioral divergence from a generic hiding mechanism (e.g. you have to use a new changeset to unhide something to satisfy monotonic). We can mitigate the problem by limiting the surface area of user-facing commands for hiding/unhiding things. And/or we can just say "evolve changes everything" and not worry too much about the user impact.
Sure, we could have a flag that toggles you between these two worlds. But I think that just punts the deprecation of one down the line and leaves extensions in a weird state where they have to be aware of the two possible environments (much as they do today with strip-vs-evolve environments).
_______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel