Re: [Monotone-devel] Server fails to start up because it messes with MT directory

2005-05-07 Thread Nathaniel Smith
On Sat, May 07, 2005 at 12:25:16AM -0500, Timothy Brownawell wrote:
 It's trying to read MT/options. Since anything in this file can be put
 on the command line (so it's not critical to be able to read this),
 here's a patch to turn this into a warning. If there are no
 objections, I'll merge it in a couple days.

Looks good to me.  Add a test?

-- Nathaniel

-- 
  /* Tell the world that we're going to be the grim
   * reaper of innocent orphaned children.
   */
-- Linux kernel 2.4.5, main.c


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Re: CLI / path restrictions.

2005-05-07 Thread Nathaniel Smith
On Fri, May 06, 2005 at 10:27:49PM +0200, Bruno Hertz wrote:
 Hmm. Looking at common tools (like ls, chmod or whatever), restriction
 to pwd is the default, and recursiveness must explicitly be requested,
 like per '-R' option (OK, not possible with ls, of course). 'find' is
 one of the notable exceptions, where recursiveness is the default, and
 limitation to pwd or level of recursiveness is requested per
 'maxdepth'.

 I've seen the term 'depth' already being used somewhere, I think it
 was the revision history depth of the log command, so there might be
 some risk of confusing people.

(chmod acts on a whole directory as a unit too, though in a
different sense...)

Yeah, --depth is taken.  Could use --prune or something, like find, I
guess?

 But to meet user intuition somehow, I guess either of the above
 approaches might serve as a model.

It actually had never occurred to me that one might expect giving a
directory to mean only the first level of stuff in that directory;
maybe we need a straw poll on what people's intuitions here are?

Part of the problem is that commit dir/ just can't mean commit
changes in the top level of dir/, but nothing below that.  I mean...
I dunno, I can't imagine that being reasonable.  So, there's a theory
which says that everything else should be consistent with commit --
for diff and status, I think, this argument is very powerful;
diff foo should show exactly the same changes as commit foo will
commit.  Works for revert too, really; diff should show exactly
what revert will throw away.  For the ls family of commands, I guess
one could make an argument either way; consistency with ls(1) vs.
consistency with the rest of monotone.

[snip]
  Generally, I'm wondering whether it's possible to get rid off the
  requirement the user entering MT relative paths at all, e.g. by taking
  pwd into account.
 
  Yeah, that we haven't already is just a bug.  Do you know of any
  commands besides log that do this?
 
 Not right now, but if you are interested in reports I might give them
 as I go through the features resp. give summaries at specific
 points.

I don't think there are any others, but if you do find some, please
let us know!

 First though I hope to maybe ask some other questions in the
 near future which have been kind of puzzling me these recent days ...

Please feel free...

-- Nathaniel

-- 
...these, like all words, have single, decontextualized meanings: everyone
knows what each of these words means, everyone knows what constitutes an
instance of each of their referents.  Language is fixed.  Meaning is
certain.  Santa Claus comes down the chimney at midnight on December 24.
  -- The Language War, Robin Lakoff


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Server fails to start up because it messes with MT directory

2005-05-07 Thread Timothy Brownawell
On 5/7/05, Nathaniel Smith [EMAIL PROTECTED] wrote:
 On Sat, May 07, 2005 at 12:25:16AM -0500, Timothy Brownawell wrote:
  It's trying to read MT/options. Since anything in this file can be put
  on the command line (so it's not critical to be able to read this),
  here's a patch to turn this into a warning. If there are no
  objections, I'll merge it in a couple days.
 
 Looks good to me.  Add a test?

OK, there's a test now, and also a matching check in write_options.
Will be merged tomorrow.

Might also get some of the places that could do with more informative
error messages for this (unreadable files).

Tim


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] Re: CLI / path restrictions.

2005-05-07 Thread Bruno Hertz
Nathaniel Smith [EMAIL PROTECTED] writes:

 It actually had never occurred to me that one might expect giving a
 directory to mean only the first level of stuff in that directory;
 maybe we need a straw poll on what people's intuitions here are?

Who ever called 'ls' with a directory name as param might think
different. Shell expansion is non recursive either. Actually, most
commands work non recursive without explicit request. Take rm -rf as
another example.

 Part of the problem is that commit dir/ just can't mean commit
 changes in the top level of dir/, but nothing below that.  I mean...
 I dunno, I can't imagine that being reasonable.  So, there's a theory
 which says that everything else should be consistent with commit --
 for diff and status, I think, this argument is very powerful;
 diff foo should show exactly the same changes as commit foo will
 commit.  Works for revert too, really; diff should show exactly
 what revert will throw away.  For the ls family of commands, I guess
 one could make an argument either way; consistency with ls(1) vs.
 consistency with the rest of monotone.

If you want directory restrictions to act recursively per default,
please do so, I for one don't really care. But providing the means to
limit the level of recursiveness would still make an awful lot of
sense.

Apart from that, if 'commit .' committed the files in pwd only I
really can't say I'd be that surprised.

Regards, Bruno.




___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Re: CLI / path restrictions.

2005-05-07 Thread Derek Scherger
Bruno Hertz wrote:
 Who ever called 'ls' with a directory name as param might think
 different. Shell expansion is non recursive either. Actually, most
 commands work non recursive without explicit request. Take rm -rf as
 another example.

conversely, cvs diff dir etc. do act recursively, iirc, and can be told
to not recurse with -l, which is where I pulled the idea for --local from.

 If you want directory restrictions to act recursively per default,
 please do so, I for one don't really care. But providing the means to
 limit the level of recursiveness would still make an awful lot of
 sense.
 
 Apart from that, if 'commit .' committed the files in pwd only I
 really can't say I'd be that surprised.

certainly, given the same args and possibly --local option, commit,
status, diff, revert should all act on the same things!

Cheers,
Derek


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] CLI / path restrictions.

2005-05-07 Thread Derek Scherger
Nathaniel Smith wrote:
 Hardest part is coming up with a sensible way for the user to express
 this desire -- any suggestions?

off the top of my head --local (a la cvs) comes to mind...

 Though I guess the semantics of listing a directory are not totally
 clear; if I say 'log foo/', and there's a file foo/bar that used to be
 in some other dir, should the log include edits to foo/bar before it
 was in this dir?  if there used to be a file called foo/bar but is no
 longer, should the log include edits to foo/bar when it was in this
 dir?

part of me thinks we should list the rename but not bother tracing back
beyond that point. if that is the file you're interested in, you can ask
for a log from the rename revision using the old name to keep going.

Cheers,
Derek


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] Re: merge weirdness...

2005-05-07 Thread Wim Oudshoorn
I am at the moment just playing with monotone, but
after reading the e-mail below I started to think a little
bit about how to pick an ancestor for merging.
It is quite an interesting problem, and quite tricky because
for me it seems very hard to make precise what properties you
want for a merge ancestor  for revisions l and r.

But I think the current algorithme as I understand it can 
be improved.  
So first lets introduce some concepts:

* The revisions form a DAG (directed acyclic graph) G,
  for which the vertices V are the revisions.

* The DAG structure induce a partial ordering on the revision,
  defined by:

  r = s iff r = s or there is a path from r to s in the
 the revision graph.

* given a set of revisions S (subset of V)  

  Heads (S) = maximal elements of S for the partial order.
= { s in S | there is no t in S such that t != s and  s = t}

* given a revision r the ancestors are given by

  An (r) = { s in V | s = r }

* given a set of revisions S (subset of V) lets define D vertices
  (related to the dominators) by:

  D (S) = { s in S | for all x in S :  x = s or s = x}

  In other words, D(S) consists of the vertices that are comparable
  to all the other vertices in S.


From this it seems that:

LCA (l, r) = Heads ( An (l) intersect An (r))

the dominators of r are all the D points of the ancestors of r, or
in other words:

DOM (r) = D (An (r))

So the current algorithme is:
  
Nathaniel Smith [EMAIL PROTECTED] writes:

 To avoid this kind of problem, monotone currently uses the LCA+DOM,
 or lcad ancestor selection algorithm -- it chooses the most recent
 revision that is a common ancestor of both nodes, and a dominator of
 one of them.

LCA+DOM (l, r) = Heads (An (l) intersect Dom (r)) 
 or 
 Heads (Dom (l) intersect An (r))

 So, let's fix this.

 There are some different approaches to doing so:

   -- use a better ancestor selection algorithm:
  -- I'm pretty sure that if there's a unique LCA, use it;
 otherwise, fall back to LCA+DOM is a correct algorithm, and
 it should help a lot in the long-lived branches case, where
 propagates are reasonably rare.
  
This seems more complicated than needed.
I  propose 

Merge ancestor (l, r) = Heads (D (An (l) intersect An (r)))

Mathematical speaking this has a few advantages:

* Merge ancestor is either empty, or contains exactly one revision,
  so it does not need a random choice anymore.
* It coincides with LCA if there is a unique LCA
* in all other cases this ancestor is = LCA+DOM ancestor
  (so it is further from the root of the tree, so closer
  to the revisions to be merged).

* Also, the few cases I looked at, it seems that this
  merge ancestor algorithm has the advantage that 
  if you have long lived parallel branches with 
  a topology that is bad for mergin you can
  quite easily fix this by making a strategic merge.

  -- it is probably possible to do much better;  I have some
 sketches on how one can calculate some kind of optimal safe
 merge ancestor.  They are currently sketches.

I am very interested to hear about them.

   -- implement codeville-merge

I am interested to know how the codeville-merge works, but the codeville
site does not seem to have a lot of documentation of the algorithme ;-(

If the above is too cryptic, please let me know, I am happy to answer
questions, and as mentioned above, I just started thinking about this.

Oh, and if I am talking nonsense, please let me know :-)

Wim Oudshoorn.



___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] mtbrowser - Text based browser for source control

2005-05-07 Thread Henry Nestler
For some simple browsing in revisions database, I wrote this tool from
shell script. It use only dialog and some simple shell tools (cut, cat
echo, head, tail, sort, ...).
Is not full futured. I wrote this only in some hours today. Is very
simple to handle and fast. The longest time it need to get the
certs of revision.
--
Henry Nestler



mtbrowse.sh.gz
Description: GNU Zip compressed data
___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] Re: CLI / path restrictions.

2005-05-07 Thread Bruno Hertz
Derek Scherger [EMAIL PROTECTED] writes:

 certainly, given the same args and possibly --local option, commit,
 status, diff, revert should all act on the same things!

Sure. Without path spec on the entire working copy, else on the
path(s) specified.

And, as said, after taking the pain of abstracting the internal model
of monotone from the filesystem paradigm at all, thus making them
pretty much orthogonal, I think it's an appealing idea to let the UI
just behave like any other *nix tool.

Among the automatic benefits, a smoother learning curve, predictable
behavior and letting users take advantage of shell globbing are just
some examples. I think others could easily be found, especially in
scripted environments, where committing or diffing might be just one
of the tasks to be performed on a given file or path list.

Regards, Bruno.




___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Re: 3-way merge considered harmful

2005-05-07 Thread Oren Ben-Kiki
 May 2005 00:29:48 -0700, Nathaniel Smith [EMAIL PROTECTED] said:

 njs Here's another pathological case for 3-way merge:
 njsA
 njs|
 njsB
 njs   / \
 njs  C   D

I'd like to throw in $0.02 worth here.

First, this problem has nothing to do with project file operations. The 
same thing would happen if you were talking about adding, removing and 
changing lines in a text file.

It seems to me you have two ways to go about solving this. The first is 
that a merge doesn't consider the state of the file (or project tree or 
whatever), but also the history leading to it. Taking this road to its 
logical end you end up with something like Darcs. In such a system, a 
version is defined as the sum of a set of deltas, rather than as a 
particular state.

On Wednesday 04 May 2005 18:41, [EMAIL PROTECTED] wrote:
 As I see it, this case and the criss-cross problem just show that
 picking any common ancestor is not enough to provide a correct
 merge ancestor (one that doesnt lose work), and much less a nice
 merge ancestor (a correct merge ancestor that also never requires the
 users to solve the same conflict twice).

Exactly. The second way is to stick with only using the three states of 
the file (or project tree or whatever). It is then inevitable that the 
choice of ancestor will affect the end result of a 3-way merge.

You can view this as a feature more than a bug. For example, using 3-way 
merge, with appropriate common ancestor selection, yields a 
cherry-picking operation:

/- B -- C
   A
\- D -- E

A 3-way merge of C and E using B as a base would cherry-pick the 
B--C change and apply it to E. True, B isn't even an ancestor of E, 
unless one considers reverse deltas; but that just drives the point 
that the base for a 3-way merge is a different thing from least 
common ancestor, depending on what you are trying to achieve.

 I fail to imagine an example 
 where the LCAD algorithm could be not correct by choosing an ancestor
 such as A in your example.

In a state-based (rather than delta-state) system, selecting the 
ancestor for a 3-way merge becomes a semantical operation; it reflects 
the _intent_ of the operation. This means there's no way to discover 
the one and only true common ancestor for merging versions B and E 
above; there is simply no such thing. The best the system can do is 
provide an automated way to locate the ancestor which causes the merge 
to reflect _a particular developer intent_.

 Im also not very convinced yet that there exists no algorithm to find
 a nice merge ancestor. Even then, I personally would be willing to
 solve the same conflict twice once in a while, if it was necessary to
 be able to use a standard 3-way merger to solve conflicts.

Certainly the system can compute the correct ancestor for a particular 
intent, such as merging a branch back to the main trunk etc. However, I 
suspect that any such algorithm must, to some extent, rely on 
meta-information that is not available in the topology itself (call 
this the expected development workflow).

BTW, in a Darcs-like system, the situation isn't much different. For the 
system to automatically select the set of deltas to include in a 
system, it again must rely on such meta-information.

Put another way - if Monotone, or Darcs for that matter subscribed to a 
particular workflow methodology (trunk/branch, development/release, 
etc.) then there would be no problem in the first place. However both 
systems attempt at providing basic building blocks which can be used to 
implement many types of workflows. Well, surprise - this means that 
when you use these building blocks, _you_ have to decide on how to 
apply them according to _your_ particular workflow, and there are some 
ways to apply them that make little or no sense.

Nathaniel's pathological case is an example of a nonsensical usage of 
3-way merge, just like char *p = 0; *p = 'a'; is a nonsensical use of 
C pointers; this doesn't mean 3-way merge, or pointers, are inherently 
useless, or need to be fixed somehow.

Have fun,

Oren Ben-Kiki


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Re: 3-way merge considered harmful

2005-05-07 Thread Oren Ben-Kiki
 May 2005 00:29:48 -0700, Nathaniel Smith [EMAIL PROTECTED] said:

 njs Here's another pathological case for 3-way merge:
 njsA
 njs|
 njsB
 njs   / \
 njs  C   D

I'd like to throw in $0.02 worth here.

First, this problem has nothing to do with project file operations. The 
same thing would happen if you were talking about adding, removing and 
changing lines in a text file.

It seems to me you have two ways to go about solving this. The first is 
that a merge doesn't consider the state of the file (or project tree or 
whatever), but also the history leading to it. Taking this road to its 
logical end you end up with something like Darcs. In such a system, a 
version is defined as the sum of a set of deltas, rather than as a 
particular state.

On Wednesday 04 May 2005 18:41, [EMAIL PROTECTED] wrote:
 As I see it, this case and the criss-cross problem just show that
 picking any common ancestor is not enough to provide a correct
 merge ancestor (one that doesnt lose work), and much less a nice
 merge ancestor (a correct merge ancestor that also never requires the
 users to solve the same conflict twice).

Exactly. The second way is to stick with only using the three states of 
the file (or project tree or whatever). It is then inevitable that the 
choice of ancestor will affect the end result of a 3-way merge.

You can view this as a feature more than a bug. For example, using 3-way 
merge, with appropriate common ancestor selection, yields a 
cherry-picking operation:

/- B -- C
   A
\- D -- E

A 3-way merge of C and E using B as a base would cherry-pick the 
B--C change and apply it to E. True, B isn't even an ancestor of E, 
unless one considers reverse deltas; but that just drives the point 
that the base for a 3-way merge is a different thing from least 
common ancestor, depending on what you are trying to achieve.

 I fail to imagine an example 
 where the LCAD algorithm could be not correct by choosing an ancestor
 such as A in your example.

In a state-based (rather than delta-state) system, selecting the 
ancestor for a 3-way merge becomes a semantical operation; it reflects 
the _intent_ of the operation. This means there's no way to discover 
the one and only true common ancestor for merging versions B and E 
above; there is simply no such thing. The best the system can do is 
provide an automated way to locate the ancestor which causes the merge 
to reflect _a particular developer intent_.

 Im also not very convinced yet that there exists no algorithm to find
 a nice merge ancestor. Even then, I personally would be willing to
 solve the same conflict twice once in a while, if it was necessary to
 be able to use a standard 3-way merger to solve conflicts.

Certainly the system can compute the correct ancestor for a particular 
intent, such as merging a branch back to the main trunk etc. However, I 
suspect that any such algorithm must, to some extent, rely on 
meta-information that is not available in the topology itself (call 
this the expected development workflow).

BTW, in a Darcs-like system, the situation isn't much different. For the 
system to automatically select the set of deltas to include in a 
system, it again must rely on such meta-information.

Put another way - if Monotone, or Darcs for that matter subscribed to a 
particular workflow methodology (trunk/branch, development/release, 
etc.) then there would be no problem in the first place. However both 
systems attempt at providing basic building blocks which can be used to 
implement many types of workflows. Well, surprise - this means that 
when you use these building blocks, _you_ have to decide on how to 
apply them according to _your_ particular workflow, and there are some 
ways to apply them that make little or no sense.

Nathaniel's pathological case is an example of a nonsensical usage of 
3-way merge, just like char *p = 0; *p = 'a'; is a nonsensical use of 
C pointers; this doesn't mean 3-way merge, or pointers, are inherently 
useless, or need to be fixed somehow.

Have fun,

Oren Ben-Kiki


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] Re: How new-style codeville merge works

2005-05-07 Thread Bruce Stephens
Nathaniel Smith [EMAIL PROTECTED] writes:

 FYI:
   http://thread.gmane.org/gmane.comp.version-control.revctrl/2

Oh.  If I understand correctly, then it sounds like the basic storage
that everone's using is suboptimal, and really SCMs should store a big
database of lines, and files get stored as lists of pointers into that
database?  (As Stellation did, although Stellation appears to have
died.  I think they took that idea from a proprietary system, but I
don't remember which one.)

Or, if not that, then you'd want to store changes to text files in
some line-based form, I guess?  Otherwise surely you're recomputing
diff-like information lots of the time (something cheaper than actual
diffs, but I feel sure one could store something more useful than
xdelta; indeed, didn't SCCS use something which would have been useful
for this)?


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] monotone 0.19 - how long should a fresh pull take?

2005-05-07 Thread Matthew Gregan
At 2005-05-07T08:37:14-0700, Joe Wilson wrote:
  $ time monotone --db=mt.db --key= pull off.net net.venge.monotone
  ...
  real223m5.784s
  user219m30.140s
  sys 0m9.827s

I'm assuming you have an adequate network connection, because obviously
pull will take a long time if your network connection is very slow.

 Is this speed typical?

Absolutely not.  As a counter example, I just did a pull of the monotone
database in twenty minutes on my Windows/MingW box (a 2.0GHz Opteron).

Note that this was using a binary built from monotone head using MingW
rather than Cygwin, and the pull was from a copy of of the monotone
database located on a local LAN, so it's not precisely apples to apple.
However, the output of 'time' indicates most of your time was spent
processing rather than waiting on network I/O, so it's not a totally
unfair comparison.

Cygwin is generally quite slow compared to native applications.  I
wouldn't have thought it would be this bad, but then again I wouldn't be
totally surprised if your performance problems disappeared if you
rebuilt using MingW (you might be able to get away with building under
Cygwin and specifying the -mno-cygwin compiler option in the right
places).

 platform:  WinNT 4.0, Cygwin (fairly recent install)
 CPU:   2 GHz Pentium4, unknown CPU cache size
 compiler:  gcc version 3.3.3 (cygwin special)
 configure: default options only
 boost: boost_1_31_0

My build was with Boost 1.32.0, GCC 3.3, MingW 3.2.1-rc1, and default
compiler options.

 Is there a flag to have monotone show a percentage complete progress 
 indicator for the pull operation?  I was just about to kill the 3.6 hour
 process thinking it had died. It does not have to be 100% accurate - just
 a rough indication of how much work is left to be done.

Unfortunately, no.  It's not really possible to do this with the current
model because the client doesn't have a way of knowing how much work is
left to do.  There has been considerable done on improving performance
in the last couple of releases, so hopefully the lack of a progress
indicator will become less of an issue.

Cheers,
-mjg
-- 
Matthew Gregan |/
  /|[EMAIL PROTECTED]


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Re: How new-style codeville merge works

2005-05-07 Thread Nathaniel Smith
On Sat, May 07, 2005 at 11:56:03PM +0100, Bruce Stephens wrote:
 Nathaniel Smith [EMAIL PROTECTED] writes:
 
  FYI:
http://thread.gmane.org/gmane.comp.version-control.revctrl/2
 
 Oh.  If I understand correctly, then it sounds like the basic storage
 that everone's using is suboptimal, and really SCMs should store a big
 database of lines, and files get stored as lists of pointers into that
 database?  (As Stellation did, although Stellation appears to have
 died.  I think they took that idea from a proprietary system, but I
 don't remember which one.)
 
 Or, if not that, then you'd want to store changes to text files in
 some line-based form, I guess?  Otherwise surely you're recomputing
 diff-like information lots of the time (something cheaper than actual
 diffs, but I feel sure one could store something more useful than
 xdelta; indeed, didn't SCCS use something which would have been useful
 for this)?

Yes, a weave (SCCS's storage format) turns out to be remarkably
well-suited to this.  When Bram says he accidentally invented the
weave from first principles, by asking now what data structure would
be good for this, he's absolutely not kidding:
   
http://www.loglibrary.com/show_page/view/139?Multiplier=3600Interval=6StartTime=1115091103

Everything else here looks like interesting implementation questions,
but somewhat irrelevant to the algorithm itself :-).  There are a lot
of different ways to implement these sorts of ideas, with complicated
trade-offs... some sort of caching may well be a good idea, for sure.
But we don't even know that yet for sure.

-- Nathaniel

-- 
Eternity is very long, especially towards the end.
  -- Woody Allen


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] [patch] add ticker for revisions written to netsync; change tick_write_count format

2005-05-07 Thread Timothy Brownawell
Pull can take a long time to sanity-check revisions (especially on
initial pull to a fresh db), and doesn't provide any feedback during
this. This patch lets packet_consumer and children run a callback when
a revision is written out. Netsync then uses this to add a ticker for
revisions written. Is there a better way to do this?

Since this makes the count ticker too long for an 80-char terminal,
it also changes the way tick_write_count displays to be like
monotone:   certs |keys
monotone:8456 |  21

monotone: bytes in | bytes out | certs in | revs checked | revs in
monotone:25.6M |731.5k | 8456 | 2073 |2784

.
Comments, suggestions? Is this (ticker) something we want to change?

Tim
# 
# patch netsync.cc
#  from [60652355c67df5803337e5deb857a8dbb279ffa1]
#to [e1f885ae4739699f950e7d311e5d4bd8815ade54]
# 
# patch packet.cc
#  from [478a95c883062f409c2d9558dd3177e9d5e6ac2c]
#to [90a102794d4dc3b6943b502026bfb74c4ab69fab]
# 
# patch packet.hh
#  from [f5f36ee1eb04d53b1d407fe6f5ea1b24d9c4a847]
#to [3ecd9f0de0e37c56a105cfc6bfd8a5fdb84032c7]
# 
# patch ui.cc
#  from [b06e19535d68d00f01c8ab33848e79f1942c9532]
#to [c2e8c87e5b0de5106ab35fbcc356b069474c6994]
# 
--- netsync.cc
+++ netsync.cc
@@ -12,6 +12,7 @@
 #include boost/lexical_cast.hpp
 #include boost/scoped_ptr.hpp
 #include boost/shared_ptr.hpp
+#include boost/bind.hpp
 
 #include app_state.hh
 #include cert.hh
@@ -233,6 +234,7 @@
   auto_ptrticker cert_out_ticker;
   auto_ptrticker revision_in_ticker;
   auto_ptrticker revision_out_ticker;
+  auto_ptrticker revision_checked_ticker;
 
   map std::pairutf8, netcmd_item_type, 
boost::shared_ptrmerkle_table  merkle_tables;
@@ -260,6 +262,8 @@
   Netxx::Timeout const  to);
 
   virtual ~session() {}
+  
+  void rev_written_callback();
 
   id mk_nonce();
   void mark_recent_io();
@@ -433,6 +437,7 @@
   cert_out_ticker(NULL),
   revision_in_ticker(NULL),
   revision_out_ticker(NULL),
+  revision_checked_ticker(NULL),
   analyzed_ancestry(false),
   saved_nonce(),
   received_goodbye(false),
@@ -447,6 +452,9 @@
   this-collection = idx(collections, 0);
 }
 
+  dbw.set_on_revision_written(boost::bind(session::rev_written_callback,
+  this));
+  
   // we will panic here if the user doesn't like urandom and we can't give
   // them a real entropy-driven random.  
   bool request_blocking_rng = false;
@@ -478,6 +486,11 @@
 }
 }
 
+void session::rev_written_callback()
+{
+  if(revision_checked_ticker.get()) ++(*revision_checked_ticker);
+}
+
 id 
 session::mk_nonce()
 {
@@ -2887,6 +2900,7 @@
   sess.byte_out_ticker.reset(new ticker(bytes out, , 1024, true));
   if (role == sink_role)
 {
+  sess.revision_checked_ticker.reset(new ticker(revs written, w, 1));
   sess.cert_in_ticker.reset(new ticker(certs in, c, 3));
   sess.revision_in_ticker.reset(new ticker(revs in, r, 1));
 }
@@ -2898,6 +2912,7 @@
   else
 {
   I(role == source_and_sink_role);
+  sess.revision_checked_ticker.reset(new ticker(revs written, w, 1));
   sess.revision_in_ticker.reset(new ticker(revs in, r, 1));
   sess.revision_out_ticker.reset(new ticker(revs out, R, 1));
 }
--- packet.cc
+++ packet.cc
@@ -428,6 +428,13 @@
   I(all_prerequisites_satisfied());
 }
 
+
+void packet_consumer::set_on_revision_written(boost::function0void const  x)
+{
+  on_revision_written=x;
+}
+
+
 struct packet_db_writer::impl
 {
   app_state  app;
@@ -859,6 +866,7 @@
   if (dp-all_prerequisites_satisfied())
 {
   pimpl-app.db.put_revision(ident, dat);
+  if(on_revision_written) on_revision_written();
   pimpl-accepted_revision(ident, *this);
 }
 }
@@ -990,6 +998,11 @@
 
 #define DOIT(x) pimpl-do_packet(boost::shared_ptrdelayed_packet(new x));
 
+void packet_db_valve::set_on_revision_written(boost::function0void const  x)
+{
+  on_revision_written=x;
+  pimpl-writer.set_on_revision_written(x);
+}
 void
 packet_db_valve::consume_file_data(file_id const  ident, 
file_data const  dat)
--- packet.hh
+++ packet.hh
@@ -9,6 +9,8 @@
 #include iosfwd
 #include memory
 
+#include boost/function.hpp
+
 #include app_state.hh
 #include ui.hh
 #include vocab.hh
@@ -34,6 +36,12 @@
 
 struct packet_consumer
 {
+protected:
+  boost::function0void on_revision_written;
+public:
+  
+  virtual void set_on_revision_written(boost::function0void const  x);
+  
   virtual ~packet_consumer() {}
   virtual void consume_file_data(file_id const  ident, 
  file_data const  dat) = 0;
@@ -154,6 +162,7 @@
   packet_db_valve(app_state  app,
   bool take_keys = false);
   virtual ~packet_db_valve();
+  virtual void set_on_revision_written(boost::function0void const  x);
   virtual void consume_file_data(file_id const  ident, 
  file_data const  dat);
   virtual void