You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Daniel Shahaf <d....@daniel.shahaf.name> on 2014/06/20 02:06:22 UTC

"BASE != HEAD" notifications

One of my colleagues ran bisect but forgot to update back to HEAD after
finishing it.  Another forgot to run 'svn up' in the morning before starting
to edit a file, and later got conflicts

Both of these user errors might have been prevented if their client had
advised them (during the bisect, for Alice; in the morning, for Bob) that
their working copy's BASE tree differs from HEAD.  (That is, that 'svn st
-u' and 'svn diff --summarize -r HEAD' were non-empty.)

Does this sound useful?  Would library changes be needed to allow such
functionality to be developed?

I think the library changes will be straightforward: we would just need
to have a "dirty" bit, clear it upon update-to-HEAD, and set it upon
backdate and upon "Has HEAD changed?" checks initiated by the libsvn_client consumer.

Clients (e.g., $EDITOR plugins) could then be configured to request that
check periodically --- say, once per N hours per working copy.  Perhaps
an editor-agnostic daemon that monitors *all* working copies in one's
homedir could be developed, too.

(The "dirty" bit would be, more or less, a cache of "Last Changed Revision"
of ${local_relpath}@HEAD; it'll have to account for deletions, renames, and
replacements, though.)

Thoughts?

Re: "BASE != HEAD" notifications

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Neels Hofmeyr wrote on Tue, Jun 24, 2014 at 00:59:33 +0200:
> On Fri, Jun 20, 2014 at 12:06:22AM +0000, Daniel Shahaf wrote:
> > One of my colleagues ran bisect but forgot to update back to HEAD after
> > finishing it.  Another forgot to run 'svn up' in the morning before starting
> > to edit a file, and later got conflicts
> 
> Just a "dumb" question from the off... to remind me about 'svn up',
> doesn't the client need to contact the repository?

Yes.

> Are your colleagues using the same working copy?

No.

To clarify, I was describing two independent incidents, to two different
colleagues, in two different working copies.  Does it make sense?

Re: "BASE != HEAD" notifications

Posted by Neels Hofmeyr <ne...@elego.de>.
On Fri, Jun 20, 2014 at 12:06:22AM +0000, Daniel Shahaf wrote:
> One of my colleagues ran bisect but forgot to update back to HEAD after
> finishing it.  Another forgot to run 'svn up' in the morning before starting
> to edit a file, and later got conflicts

Just a "dumb" question from the off... to remind me about 'svn up',
doesn't the client need to contact the repository? Are your colleagues
using the same working copy?

~Neels

Re: "BASE != HEAD" notifications

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Julian Foad wrote on Mon, Jun 23, 2014 at 09:54:46 +0100:
> Daniel Shahaf wrote:
> 
> > One of my colleagues ran bisect but forgot to update back to HEAD after
> > finishing it.  Another forgot to run 'svn up' in the morning before starting
> > to edit a file, and later got conflicts
> > 
> > Both of these user errors might have been prevented if their client had
> > advised them (during the bisect, for Alice; in the morning, for Bob) that
> > their working copy's BASE tree differs from HEAD.  (That is, that 'svn st
> > -u' and 'svn diff --summarize -r HEAD' were non-empty.)
> > 
> > Does this sound useful?  Would library changes be needed to allow such
> > functionality to be developed?
> > 
> > I think the library changes will be straightforward: we would just need
> > to have a "dirty" bit, clear it upon update-to-HEAD, and set it upon
> > backdate and upon "Has HEAD changed?" checks initiated by the 
> > libsvn_client consumer.
> 
> The proposed library functionality is, roughly, caching of
> "base-version != head-version", for each WC path or rather each repos
> path represented in the WC?

Roughly, yes.  Infomally, the bit desired is "is the file I have the
latest one".  I'm not sure how precisely to formulate this question in
API terms; perhaps "is foo@BASE and foo@HEAD part of the same location
segment", i.e., foo@BASE and foo@HEAD are the same node-revision and
neither foo nor any of its tree-wise ancestors have been
deleted/added/replaced(/moved) between rBASE and rHEAD.

(In the preceding, read "HEAD" as "HEAD, as of the time the cached bit
was last computed".)

As to the backing storage: we could just compute the "base-version !=
head-version" bit during an online operation and store it in the db.
Alternatively, we could (a) store the repository-wide last-seen youngest
revision number; (b) for each file, store the youngest-known top bound
of its location segment; and compute the "base-version != head-version"
bit on the fly by comparing (a) and (b).  I think this second
alternative is what you termed "Next Changed Revision" below.  The idea
is to store not just the low end of node@BASE's location segment (Last
Changed Revision) but also the top end (which is Next Changed Revision
minus one).

> (A name such as "out-of-date" or "not-youngest" may be better than "dirty".)

Sure, I didn't mean "dirty" to be the term used in the final implementation
(for one, it's too generic).  Perhaps we could use a name that is a positive
rather than a negative, such as "has-been-changed-in-HEAD" or "has-heirs".

(Not "has-successors" because we already use the term "successor" in the
DAG layer, with a different meaning.)

> That sounds potentially reasonable.
> 
> With just a simple query, it would be enough to solve "Alice"'s problem (forgot to update back to head after bisecting).
> 
> It would not by itself solve "Bob"'s problem (forgot to run 'svn up' in the morning). For that, you would need periodic monitoring for new changes in the repo, which is comparable to running "svn up" or "svn st -u".
> 

Yes.  I imagine such periodic monitoring would be implemented in
third-party tools, such as GUI clients, IDEs, or desktop environments.

> > (The "dirty" bit would be, more or less, a cache of "Last Changed Revision"
> > of ${local_relpath}@HEAD; it'll have to account for deletions, renames, and
> > replacements, though.)
> 
> I have thought before of something very similar that may also be useful.
> 
> In the simple and fairly common case where a user commits a change in a
> tree where no other commit has been made since the user's last update,
> this commit always creates a superficially mixed-rev WC that is not
> really mixed-version -- that is, no versioned paths have any changes in
> the repo between the oldest and newest recorded base revisions.
> 
> If we cache the "Next Changed Revision" -- that is, the next revision after Base in which the path was changed in the repo (or the fact that there are no changes between Base and a given younger revision) -- then we can determine when a superficially mixed-rev WC is in fact pointing at the same version of each object.
> 
> The check for "can't merge into a mixed-rev WC", for example, could be relaxed to "can't merge into a mixed-version WC, but you can merge into a superficially mixed-rev WC".
> 
> - Julian

Re: "BASE != HEAD" notifications

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Branko Čibej wrote on Mon, Jun 23, 2014 at 11:21:49 +0200:
> On 23.06.2014 10:54, Julian Foad wrote:
> > Daniel Shahaf wrote:
> >
> >> One of my colleagues ran bisect but forgot to update back to HEAD after
> >> finishing it.  Another forgot to run 'svn up' in the morning before starting
> >> to edit a file, and later got conflicts
> >>
> >> Both of these user errors might have been prevented if their client had
> >> advised them (during the bisect, for Alice; in the morning, for Bob) that
> >> their working copy's BASE tree differs from HEAD.  (That is, that 'svn st
> >> -u' and 'svn diff --summarize -r HEAD' were non-empty.)
> >>
> >> Does this sound useful?  Would library changes be needed to allow such
> >> functionality to be developed?
> >>
> >> I think the library changes will be straightforward: we would just need
> >> to have a "dirty" bit, clear it upon update-to-HEAD, and set it upon
> >> backdate and upon "Has HEAD changed?" checks initiated by the 
> >> libsvn_client consumer.
> > The proposed library functionality is, roughly, caching of "base-version != head-version", for each WC path or rather each repos path represented in the WC? (A name such as "out-of-date" or "not-youngest" may be better than "dirty".)
> >
> > That sounds potentially reasonable.
> >
> > With just a simple query, it would be enough to solve "Alice"'s problem (forgot to update back to head after bisecting).
> >
> > It would not by itself solve "Bob"'s problem (forgot to run 'svn up' in the morning). For that, you would need periodic monitoring for new changes in the repo, which is comparable to running "svn up" or "svn st -u".
> >
> >> Clients (e.g., $EDITOR plugins) could then be configured to request that
> >> check periodically --- say, once per N hours per working copy.  Perhaps
> >> an editor-agnostic daemon that monitors *all* working copies in one's
> >> homedir could be developed, too.
> > Yes, I suppose this would be useful.
> 
> And I have to point out that we already provide all the tools and APIs
> that such plugins and/or daemons need.
> 

Sure, if $EDITOR is online when you open a file, it could run 'status -u
$file' in the background.  A plugin could even run 'status -u' in the
background every so often to build its private cache of files that are
out of date.

Nevertheless, if operations such as 'update' could obtain and store
this information at very little cost, and if it would be generally
useful, it might make sense for libsvn to compute, store, and API
that information.  Part of my goal in this thread has been to try
and assess whether that information would indeed be generally useful.

> Not to put too fine a point to it, the fact that you can edit an
> 'out-of-date' file is an intentional part of Subversion's design. As is
> the promise that the client won't go cap-in-hand to the server for every
> little detail.
> 

(I've addressed this in my other reply.)

> >> (The "dirty" bit would be, more or less, a cache of "Last Changed Revision"
> >> of ${local_relpath}@HEAD; it'll have to account for deletions, renames, and
> >> replacements, though.)
> > I have thought before of something very similar that may also be useful.
> >
> > In the simple and fairly common case where a user commits a change in a 
> > tree where no other commit has been made since the user's last update, 
> > this commit always creates a superficially mixed-rev WC that is not 
> > really mixed-version -- that is, no versioned paths have any changes in 
> > the repo between the oldest and newest recorded base revisions.
> >
> > If we cache the "Next Changed Revision" -- that is, the next revision after Base in which the path was changed in the repo (or the fact that there are no changes between Base and a given younger revision) -- then we can determine when a superficially mixed-rev WC is in fact pointing at the same version of each object.
> >
> > The check for "can't merge into a mixed-rev WC", for example, could be relaxed to "can't merge into a mixed-version WC, but you can merge into a superficially mixed-rev WC".
> 
> It would IMO be a /lot/ better to extend the protocol so that the final
> response to a commit contains the list of directories for which an 'svn
> update' to the committed revision is a no-op. That would eliminate most

That sounds like a useful enhancement.

> Bottom line, I object to apparently useful hacks that are likely to be
> outdated soon, but that we'll still have to maintain indefinitely.

I don't see how caching the top end of the location segment is a "hack".
It seems like a datum that could be generally useful.  In any case, if
it's a concern, we could make it a private implementation detail, or
even an "optional API" (such as an svn_client_info_t member that is not
guaranteed to be filled in).

Re: "BASE != HEAD" notifications

Posted by Branko Čibej <br...@wandisco.com>.
On 23.06.2014 10:54, Julian Foad wrote:
> Daniel Shahaf wrote:
>
>> One of my colleagues ran bisect but forgot to update back to HEAD after
>> finishing it.  Another forgot to run 'svn up' in the morning before starting
>> to edit a file, and later got conflicts
>>
>> Both of these user errors might have been prevented if their client had
>> advised them (during the bisect, for Alice; in the morning, for Bob) that
>> their working copy's BASE tree differs from HEAD.  (That is, that 'svn st
>> -u' and 'svn diff --summarize -r HEAD' were non-empty.)
>>
>> Does this sound useful?  Would library changes be needed to allow such
>> functionality to be developed?
>>
>> I think the library changes will be straightforward: we would just need
>> to have a "dirty" bit, clear it upon update-to-HEAD, and set it upon
>> backdate and upon "Has HEAD changed?" checks initiated by the 
>> libsvn_client consumer.
> The proposed library functionality is, roughly, caching of "base-version != head-version", for each WC path or rather each repos path represented in the WC? (A name such as "out-of-date" or "not-youngest" may be better than "dirty".)
>
> That sounds potentially reasonable.
>
> With just a simple query, it would be enough to solve "Alice"'s problem (forgot to update back to head after bisecting).
>
> It would not by itself solve "Bob"'s problem (forgot to run 'svn up' in the morning). For that, you would need periodic monitoring for new changes in the repo, which is comparable to running "svn up" or "svn st -u".
>
>> Clients (e.g., $EDITOR plugins) could then be configured to request that
>> check periodically --- say, once per N hours per working copy.  Perhaps
>> an editor-agnostic daemon that monitors *all* working copies in one's
>> homedir could be developed, too.
> Yes, I suppose this would be useful.

And I have to point out that we already provide all the tools and APIs
that such plugins and/or daemons need.

Not to put too fine a point to it, the fact that you can edit an
'out-of-date' file is an intentional part of Subversion's design. As is
the promise that the client won't go cap-in-hand to the server for every
little detail.


>> (The "dirty" bit would be, more or less, a cache of "Last Changed Revision"
>> of ${local_relpath}@HEAD; it'll have to account for deletions, renames, and
>> replacements, though.)
> I have thought before of something very similar that may also be useful.
>
> In the simple and fairly common case where a user commits a change in a 
> tree where no other commit has been made since the user's last update, 
> this commit always creates a superficially mixed-rev WC that is not 
> really mixed-version -- that is, no versioned paths have any changes in 
> the repo between the oldest and newest recorded base revisions.
>
> If we cache the "Next Changed Revision" -- that is, the next revision after Base in which the path was changed in the repo (or the fact that there are no changes between Base and a given younger revision) -- then we can determine when a superficially mixed-rev WC is in fact pointing at the same version of each object.
>
> The check for "can't merge into a mixed-rev WC", for example, could be relaxed to "can't merge into a mixed-version WC, but you can merge into a superficially mixed-rev WC".

It would IMO be a /lot/ better to extend the protocol so that the final
response to a commit contains the list of directories for which an 'svn
update' to the committed revision is a no-op. That would eliminate most
of the workflows that create mixed-revision working copies, the notable
exception being not committing from the root of the WC.

And as for merging, I believe we've already agreed that the
single-revision constraint is more arbitrary; it reflects a shortcoming
of our merge algorithm, not a limitation of the data model.


Bottom line, I object to apparently useful hacks that are likely to be
outdated soon, but that we'll still have to maintain indefinitely.


-- Brane

-- 
Branko Čibej | Director of Subversion
WANdisco // Non-Stop Data
e. brane@wandisco.com

Re: "BASE != HEAD" notifications

Posted by Julian Foad <ju...@btopenworld.com>.
Daniel Shahaf wrote:

> One of my colleagues ran bisect but forgot to update back to HEAD after
> finishing it.  Another forgot to run 'svn up' in the morning before starting
> to edit a file, and later got conflicts
> 
> Both of these user errors might have been prevented if their client had
> advised them (during the bisect, for Alice; in the morning, for Bob) that
> their working copy's BASE tree differs from HEAD.  (That is, that 'svn st
> -u' and 'svn diff --summarize -r HEAD' were non-empty.)
> 
> Does this sound useful?  Would library changes be needed to allow such
> functionality to be developed?
> 
> I think the library changes will be straightforward: we would just need
> to have a "dirty" bit, clear it upon update-to-HEAD, and set it upon
> backdate and upon "Has HEAD changed?" checks initiated by the 
> libsvn_client consumer.

The proposed library functionality is, roughly, caching of "base-version != head-version", for each WC path or rather each repos path represented in the WC? (A name such as "out-of-date" or "not-youngest" may be better than "dirty".)

That sounds potentially reasonable.

With just a simple query, it would be enough to solve "Alice"'s problem (forgot to update back to head after bisecting).

It would not by itself solve "Bob"'s problem (forgot to run 'svn up' in the morning). For that, you would need periodic monitoring for new changes in the repo, which is comparable to running "svn up" or "svn st -u".

> Clients (e.g., $EDITOR plugins) could then be configured to request that
> check periodically --- say, once per N hours per working copy.  Perhaps
> an editor-agnostic daemon that monitors *all* working copies in one's
> homedir could be developed, too.

Yes, I suppose this would be useful.

> (The "dirty" bit would be, more or less, a cache of "Last Changed Revision"
> of ${local_relpath}@HEAD; it'll have to account for deletions, renames, and
> replacements, though.)

I have thought before of something very similar that may also be useful.

In the simple and fairly common case where a user commits a change in a 
tree where no other commit has been made since the user's last update, 
this commit always creates a superficially mixed-rev WC that is not 
really mixed-version -- that is, no versioned paths have any changes in 
the repo between the oldest and newest recorded base revisions.

If we cache the "Next Changed Revision" -- that is, the next revision after Base in which the path was changed in the repo (or the fact that there are no changes between Base and a given younger revision) -- then we can determine when a superficially mixed-rev WC is in fact pointing at the same version of each object.

The check for "can't merge into a mixed-rev WC", for example, could be relaxed to "can't merge into a mixed-version WC, but you can merge into a superficially mixed-rev WC".

- Julian