Commit Graph

226 Commits

Author SHA1 Message Date
Pierre-Yves David
c27b91f154 obsolete: clarify that 'successorssets' returns the latest successors
We do not return the first successors we found, we returns the latest (non
obsolete  (mostly)) one following the obsolete link transitively. We update the
documentation to make this clean.
2015-09-15 13:12:03 -07:00
Pierre-Yves David
f317af09f6 obsolete: drop an empty line at the end of a docstring
This empty line is useless, let's drop it.
2015-09-15 13:10:25 -07:00
timeless@mozdev.org
ea67eda4f0 obsolete: improve English of successorssets 2015-09-08 20:44:18 -04:00
Siddharth Agarwal
a5b449ed2e obsolete: replace references to 'sopener' with 'svfs' 2015-06-25 22:19:49 -07:00
Jordi Gutiérrez Hermoso
a6105df67a phases: add hg help phases hint to failures to edit public commits
There were a couple of locations that were missing this hint after an
edition of some kind failed due to the public phase.
2015-06-01 14:16:52 -04:00
Jordi Gutiérrez Hermoso
3ed01018a3 phases: rewrite "immutable changeset" to "public changeset"
The phrase "cannot edit immutable changeset" is kind of tautological.
Of course unchangeable things can't be changed. We instead mention
"public" and provide a hint so that we can point to the actual
problem. Even in cases where some operation other than edition cannot
be performed, "public" gives the root cause that results in the
"immutable" effect.

There is a precedent for saying "public" instead of "immutable", for
example, in `hg commit --amend`.
2015-06-01 18:05:38 +00:00
Pierre-Yves David
c34d269931 util: drop the 'unpacker' helper
It is not helping anything anymore.
2015-05-18 23:43:36 -05:00
Augie Fackler
a5b17bd9d1 cleanup: use __builtins__.any instead of util.any
any() is available in all Python versions we support now.
2015-05-16 14:30:07 -04:00
Pierre-Yves David
96cf5ab0aa obsolete: sort obsmarkers during exchange
Because bundle2 allows a more precise exchange of obsmarkers during pull, it
sends them in a different order (previously unstable because of sets.)  As
a result, they are added to the repository in a different order. To stabilize
the order and ensure tests are unchanged when moving from bundle1 to bundle2 we
sort markers when exchanging them.

In the long run, the obsstore will probably not use a linear storage.
2015-05-10 06:48:08 -07:00
Laurent Charignon
22af9eef3f obsolete: speed up unstable computation
Speed up the computation of the unstable revset by using the not public()
revset. In another series of patches, we optimize the not public() revset and
together it leads to a 50-100x speedup on the computation of unstable() for
our big repos.
2015-04-28 16:51:23 -07:00
Laurent Charignon
9044778c8c obsolete: speed up computation of bumped revset
Speed up the computation of the bumped revset by using the not public() revset.
In another patch series, we optimized the not public() revset. Together,
this cuts the cost of the computation of bumped() from 17% of the total time of
smartlog on our big repo to under 0.1% of the total time.
2015-04-24 14:46:30 -07:00
Pierre-Yves David
bbf64d6a4d obsolete: avoid infinite loop from obs-cycle in divergence (issue4126)
As for other currently in place cycle detection, arbitrarily cut the first
obsolescence link that create a cycle avoiding the infinite loop. This will have
to be made more deterministic in the future but we do not really care right now.
2015-03-19 13:00:44 -07:00
Matt Harbison
73a96f7b7b obsolete: replace 'ctx._repo' with 'ctx.repo()' 2015-03-12 23:05:25 -04:00
Matt Harbison
9e0bfd2ea2 obsolete: drop the explicit seek to EOF after append mode open()
posixfile now handles this.
2015-01-31 12:54:35 -05:00
Martin von Zweigbergk
5f8a09ad0c obsolete: populate successors, precursors, children lazily
The precursors and children dictionaries are not used by many
commands. By making them lazily populated,
'hg log -r @~10::@ >/dev/null' is sped up from 0.564s to 0.440s on my
hg.hg repo with 73k markers.

Also make successors lazily populated, mostly for consistency with the
others.
2015-02-04 22:25:35 -08:00
Martin von Zweigbergk
bf0b56486b obsolete: pass only new markers to _checkinvalidmarkers()
We will soon delay populating precursors until we have to. To prepare
for that, make _checkinvalidmarkers() scan for a nullid precursor in
the list of new markers instead of the (currently) cheaper 'if nullid
in precursors' check.
2015-02-04 22:40:48 -08:00
Martin von Zweigbergk
9680bb7217 obsolete: extract helpers from _load()
In preparation for making the successors, precursors, and children
dictionaries lazily populated, break up _load() into one function for
adding markers to each dictionary.
2015-01-20 22:01:37 -08:00
Martin von Zweigbergk
2601c25066 _fm1readmarkers: generate list in C
This moves perfloadmarkers from
! result: 63866
! wall 0.239217 comb 0.250000 user 0.240000 sys 0.010000 (best of 42)

to

! result: 63866
! wall 0.218795 comb 0.210000 user 0.210000 sys 0.000000 (best of 46)
2015-01-27 09:22:59 -05:00
Augie Fackler
7838bfda1b obsolete: use parsers.fm1readmarker if it exists for a ~38% perf win
This moves perfloadmarkers on my linux workstation (63494 markers from
mpm, crew, and myself) performance from
! wall 0.357657 comb 0.360000 user 0.350000 sys 0.010000 (best of 28)
to
! wall 0.222345 comb 0.220000 user 0.210000 sys 0.010000 (best of 41)
which is a pretty good improvement.

On my BSD machine, which is ancient and slow, before:
! wall 3.584964 comb 3.578125 user 3.539062 sys 0.039062 (best of 3)
after:
! wall 2.267974 comb 2.265625 user 2.195312 sys 0.070312 (best of 5)


I feel like we could do better by moving the whole generator function
into C, but I didn't want to tackle that right away.
2015-01-20 13:38:07 -05:00
Augie Fackler
a4620354b4 obsolete: make optional offset parameter to fm*readmarkers required
It was always passed by the only callsite, so just make it required.
2015-01-20 09:38:22 -05:00
Pierre-Yves David
35033dc470 obsstore: make the invalid markers check wrap-able
Some evolve user ignored the invalid markers for about two years and still have
some of them in some repository. This lead to plain abort whenever mercurial try
to open such repo. We need reinstall some way to clean this up in the evolve
extension. For this purpose, we need the checker code wrap-able independently.

This is scheduled for stable as this issue is blocking some evolve user.
2015-01-30 18:49:33 +00:00
Matt Mackall
efd707b6d7 readmarkers: add a SHA256 fixme note 2015-01-11 16:46:13 -06:00
Matt Mackall
1b1c572cac readmarkers: fast-path single successors and parents
This gives about a 5% performance bump.
2015-01-11 16:37:57 -06:00
Matt Mackall
aaefce821d readmarkers: promote global constants to locals for performance 2015-01-11 15:35:09 -06:00
Matt Mackall
5a2d46743d readmarkers: drop a temporary 2015-01-11 14:52:57 -06:00
Matt Mackall
f70b8899f1 readmarkers: read node reading into node length conditional
This removes some conditional assignments
2015-01-11 14:51:49 -06:00
Matt Mackall
fd24385ccc readmarkers: drop a temporary
Two other temporaries are renamed to fit line-length.
2015-01-11 14:46:55 -06:00
Matt Mackall
54920da7a8 readmarkers: hoist subtraction out of loop comparison 2015-01-11 14:44:57 -06:00
Matt Mackall
ccb9e25cca readmarkers: streamline offset tracking
This minimizes the number of assignments and operations needed to use offsets.
2015-01-11 14:43:31 -06:00
Matt Mackall
4cb9887cb8 readmarkers: use unpacker for fixed header 2015-01-11 14:37:50 -06:00
Matt Mackall
66bb59fd8e readmarkers: drop metadata temporary 2015-01-11 14:35:03 -06:00
Matt Mackall
eeecc7d717 readmarkers: drop date temporary 2015-01-11 14:33:49 -06:00
Matt Mackall
46c0e8872c readmarkers: drop another conditional 2015-01-11 14:32:56 -06:00
Matt Mackall
b42ed84f7a readmarkers: drop a conditional 2015-01-10 21:28:15 -06:00
Matt Mackall
aebd9ab379 readmarkers: add some whitespace 2015-01-10 21:27:29 -06:00
Matt Mackall
00030ac687 readmarkers: combine parent conditionals 2015-01-10 21:25:07 -06:00
Matt Mackall
57b821b575 readmarkers: drop temporary substring assignments
Assignments are expensive in inner loops
2015-01-10 21:24:45 -06:00
Pierre-Yves David
0701311291 obsstore: cache size computation for fm1 node
We have two different types of node type (sha1 and sha256, only sha1 is used
now) and therefor different sizes for them. We now compute the value once
instead of redoing the computation every loop. This has no visible performance
impact.
2014-11-26 23:23:33 -08:00
Pierre-Yves David
0fb7a735b0 obsstore: prefetch struct.calcsize
This function is widely used and worth but be at module level. No specific
performance boost is visible, but this is more consistent.
2014-11-26 23:21:20 -08:00
Pierre-Yves David
ff08bc7b93 obsstore: disable garbage collection during initialization (issue4456)
Python garbage collection is triggered by container creation. So code that
creates a lot of tuples tends to trigger GC a lot. We disable the gc during
obsolescence marker parsing and associated initialization. This provides an
interesting speedup (25%).

Load marker function on my 58758 markers repo:
before: 0.468247 seconds
after:  0.344362 seconds

The benefit is a bit less visible overall. With python2.6 on my system I see:
after:  0.60
before: 0.53

The difference is probably explained by the delaying of a costly GC. (but there
is still a win). Marking involved tuples, lists and dicts as ignorable by the
garbage collector should give us more benefit. But this is another adventure.

Thanks goes to Siddharth Agarwal for the lead.
2014-11-26 16:58:31 -08:00
Pierre-Yves David
629a6bc7d0 obsstore: record data as floating point in fm0 format
For python struct module, "d" is double. But for python string
formating, "d" is integer. We want to preserve the floating point
nature of the data, so we store it in the metadata as floating
point. We use "%r" to make sure we get as many significant digitis as
necessary to restore the float to the exact same value on the other
side.

The fm1 is transmitting the information as float. The lack of this made
fm1-stored markers not survive a round-trip to fm0 leading to duplicated
markers (or two markers very alike).
2014-10-16 14:46:37 -07:00
Durham Goode
73a4415474 obsolete: prevent options from being used without createmarkers
exchange and allowunstable should only be enabled if createmarkers is enabled,
so check for that and raise an exception if that's not the case.
2014-10-14 13:27:00 -07:00
Durham Goode
bbb89aae08 obsolete: add exchange option
This adds an option that enables obsolete marker exchange.
2014-10-14 13:26:01 -07:00
Durham Goode
faa1c33f8b obsolete: add allowunstable option
This option allows the creation of unstable commits. This allows things like
amending in the middle of a stack of commits, etc.
2014-10-14 13:25:13 -07:00
Durham Goode
18f3737f3a obsolete: add createmarkers option
The basic obsolete option is allowing the creation of obsolete markers. This
does not enable other features, such as allowing unstable commits or exchanging
obsolete markers.
2014-10-14 13:23:52 -07:00
Durham Goode
122b7f93b8 obsolete: add readonly flag to obstore constructor
Previously, obstore read the obsolete._enabled flag to determine whether to
allow writes to the obstore. Since obsolete._enabled will be moving into a repo
specific config, we can't read it globally, and therefore must pass the
information into the constructor.
2014-10-14 13:20:31 -07:00
Durham Goode
a10734d5ff obsolete: add isenabled function for option checking
Previously, obsolete used the module level _enabled flag to determine whether it
was on or off. We need a bit more granular control, so we'll be introducing
toggle options. The isenabled() function is how you check if a particular option
is enabled for the given repository.

Future patches will add options such as 'createmarkers', 'allowunstable', and
'exchange' to enable various features of obsolete markers.
2014-10-14 13:17:35 -07:00
Pierre-Yves David
52a52fdcdf obsolete: use format version 1 as the default for obsstore 2014-09-16 17:57:44 -07:00
Pierre-Yves David
febcb6830b obsolete: add a "format.obsstore-version" config option
This option controls what version of the binary format to use when creating a new
obsstore file.

Default is still the old format. No safeguards are currently placed around the
option value, but no clueless users are in danger of harm since it is
undocumented.
2014-09-16 17:52:40 -07:00
Pierre-Yves David
3adb84204d obsolete: introduce a new binary encoding for obsmarkers (version 1)
This new encoding explicitly stores the date and parents allowing a
significantly faster marker decoding. See inline documentation for details.

This format is not yet used to store format on disk. But it will be used in
bundle2 exchange if both side support it. Support for on-disk format is coming
in other changesets.
2014-10-09 00:10:10 -07:00
Pierre-Yves David
2454012c73 obsstore: add a flag for sha256 hashes
We add flag to inform that the marker is using sha256 hashes. As format 0 is not
able to handle sha256 hashes (32 bytes long), we plain crash if we even attempt to
encode a sha256 with it.
2014-10-10 16:43:04 -05:00
Pierre-Yves David
6c00b7eafa obsolete: use uint## in the format documention
This is shorter and kind of more readable for people who care about binary
format.
2014-10-09 00:15:04 -07:00
Pierre-Yves David
7947a20614 obsolete: gather _fm0 meta encoding with other _fm0 code 2014-10-08 22:34:48 -07:00
Pierre-Yves David
db2b475090 obsolete: _rename decodemeta to _fm0decodemeta
This will be format zero specific.
2014-10-08 22:12:06 -07:00
Pierre-Yves David
67a3810eec obsolete: _rename encodemeta to _fm0encodemeta
This will be format zero specific.
2014-10-08 22:11:36 -07:00
Pierre-Yves David
d862c4a145 obsolete: store metadata as a tuple of (key, value) pairs (API)
Different formats will encode metadata in different ways. So we cannot keep the
binary blob in the object anymore. We use a tuple to ensure it is immutable and
hashable.
2014-10-08 22:10:15 -07:00
Pierre-Yves David
a7d9bc3421 obsolete: replace "nb" notation with "num" (for "number")
As requested by Matt Mackall.
2014-10-02 16:57:51 -05:00
Pierre-Yves David
2c1c685c0b obsolete: use version constants in the format mapping 2014-09-16 15:57:51 -07:00
Pierre-Yves David
556c3d9a5e obsolete: use the version argument in encodemarkers
Recent scientific studies show that assigning a variable have no effect on
a unrelated constant. We therefore use the variable where we intended to in the
first place.
2014-09-16 15:56:38 -07:00
Pierre-Yves David
7fe702d01c obsolete: gather all contents related to format version 0 in a single place
All contents includes documentation, constants, and functions, so we
gather all of those things into a single location. The diff is confusing
because it cannot understand what code is semantically moved around in this
grand migration.
2014-09-12 14:41:43 +02:00
Pierre-Yves David
5c32e2e043 obsolete: ensure that getrevs always return a set
When a set of revisions was empty, we were using an empty tuple. We now return an
empty frozenset to ensure the object could be used in an operation that requires a
set.
2014-09-23 12:21:38 -07:00
Pierre-Yves David
1873ea14ec obsolete: properly drop 'date' from metadata
Mistakes were made while resolving rebase conflicts in 92753bcc8aa2. This led to
'date' being preserved in metadata when reading markers from a binary stream.

As a result, some known markers were seen as "new" when pulling. I noticed it
because a no-op pulls from main added about 600 duplicated markers to my
obsstore (for each pull).

I do not believe we need to perform any specific action to actively
de-duplicates existing obsstore. After this fix, duplicated markers will no be
propagated and the few affected repositories can probably deal with duplication (or
people can repull the obsstore from a clone).

As a side effect, we decode metadata only once, reducing the impact of the hack
in fm0 to store extra important data (parents and date).
2014-09-10 14:42:52 +01:00
Pierre-Yves David
9c8ad08d12 obsolete: add a commonversion function
This function returns the highest common version between the locally known
formats and a list of remotely known formats. This is going to be useful to
know what format should be used for exchange.
2014-08-26 11:36:23 +02:00
Pierre-Yves David
fc6088afa7 obsmarker: record the number of new markers in the transaction
This lets hooks be notified about new markers in the repository.
2014-08-25 18:26:56 +02:00
Pierre-Yves David
d8f05095f7 obsolete: make encodemarkers a public function
We'll need access to it for bundle2.
2014-08-25 16:24:40 +02:00
Pierre-Yves David
460e985627 obsolete: move _encodemarkers next to _readmarkers 2014-08-25 16:21:33 +02:00
Pierre-Yves David
73e94f0411 obsstore: store and preserve ondisk version 2014-08-25 16:18:44 +02:00
Pierre-Yves David
150d8e5d5f obsolete: have _readmarkers return the format version
readmarkers is not returning the version of the format it read from. This will
let callers know about the format and allow them to preserve it.
2014-08-25 16:51:51 +02:00
Pierre-Yves David
2be245bb0d obsolete: support for any known obsstore format when reading or writing
We can now read and write any known format. The list of known formats
currently has one element (0). The obsstore itself is not aware of
multiple formats yet and always uses format 0.
2014-08-25 16:16:01 +02:00
Pierre-Yves David
e891429fca obsolete: move _fm0encodeonemarker next to _fm0readmarkers 2014-08-25 16:09:18 +02:00
Pierre-Yves David
59d5970fe3 obsolete: rename _encodeonemarker to _fm0encodeonemarkers
This function encodes markers in version 0 of the format.
2014-08-25 16:43:23 +02:00
Pierre-Yves David
30503ced28 obsolete: extract the part of _readmarkers specific to format version 0
If we are to introduce new formats we need to be able call different
functions for different formats. Creating a function for format
version 0 is the first step.
2014-08-25 14:58:11 +02:00
Pierre-Yves David
104efe6c90 obsolete: rename all _fm to _fm0
This change is because these formats are used for version 0 of the
obsstore format. This is going to be useful in the future when we
introduce new versions of the format.
2014-08-25 14:56:15 +02:00
Pierre-Yves David
7cf82e8c6d obsolete: rename _fnodesize to _fmfnodesize
All variables involved in the obsstore format are prefixed with `_fm`.
`_fnodesize` was the exception. It is now back in line.

This is meaningful as we'll need to distinguish between multiple versions of the
obsstore format.
2014-08-25 14:52:51 +02:00
Pierre-Yves David
1ea986ffcd obsstore: have the mergemarkers method return the number of new markers
The mergemarkers function now returns the number of unknown markers in
the stream that have been added to the obsstore. This is similar to what
`obsstore.add` already does.

The method gains a docstring in the process.
2014-08-21 17:42:50 -07:00
Gregory Szorc
3cffe8cb84 obsolete: avoid slow, generic date parsing
Simple profiling of `hg log -r .` revealed ~18,000 calls to
mercurial.i18n.gettext() on the author's repository. The
culprit was 3 _() calls in util.parsedate() multiplied by
~6000 obsmarkers originating from the parsing of obsmarkers.

Changing the obsmarker code to parse the stored format of
dates instead of going through a generic path eliminates these
gettext() lookups and makes `hg log -r .` execute ~10% faster
on the author's repo. The performance gain is proportional to
the number of obsmarkers.

The author attempted to patch util.parsedate() to avoid the
gettext() lookups. However, that code is whacky and the author
is jet lagged, so the approach was not attempted.
2014-08-29 18:00:44 +02:00
Pierre-Yves David
dfccc53b1c debugobsolete: add a --rev argument
This argument can be used to list markers relevant to a set of revisions. We
add a test for this option and the relevant computation in the same move.
2014-08-19 23:22:44 -07:00
Pierre-Yves David
e3efc0de1b obsolete: rename allmarkers to getmarkers
This function is going to gain a "nodes" argument to filter the markers to the
ones relevant to <nodes> only.
2014-08-20 18:11:23 -07:00
Pierre-Yves David
9b224dd694 obsstore: add relevantmarkers method
We add a ``relevantmarkers`` method to fetch all markers that seem relevant to a
set of nodes. See function documentation about how this set is computed. This
will let us exchange only the markers that seem "relevant" to the set of
changesets related to a push or a pull.

The approach used to define "relevant" has been successfully tested in evolve
for 6 months.
2014-08-19 17:03:10 -07:00
Pierre-Yves David
4bdfd3c696 obsstore: keep track of children information
We use the new `parents` field to build a dictionary of markers that touch
children of a node. This will be used to link prune markers to a set of
exchanged nodes.
2014-08-19 16:53:53 -07:00
Pierre-Yves David
72d4cdd2bd obsstore: drop outdated comment
This comment was associated with a now-defunct line.
2014-08-19 16:46:17 -07:00
Augie Fackler
1705b23c44 obsolete: avoid 2-argument form of enumerate, which was new in Python 2.6 2014-08-20 14:33:59 -04:00
Pierre-Yves David
d03cabd953 obsmarkers: add a parentnodes method to retrieve parent information 2014-08-18 17:14:27 -07:00
Pierre-Yves David
fd1f0f7321 obsstore: also store the 'parents' field on disk
We now store the `parents` field on disk. We use the same strategy as for
`date`: We stick it into the metadata. This is slow and dirty, but this is also
the only way we currently have.

At some point we'll have a new obsstore format to store this properly.
2014-08-18 16:28:44 -07:00
Pierre-Yves David
41733331bc obsstore: drop 'date' from the metadata dictionary
We are extracting the `date` information from the metadata at read time.
However, we failed to remove it from the metadata returned in the markers. This
is now fixed.
2014-08-18 17:06:08 -07:00
Pierre-Yves David
c584b9c277 createmarkers: automatically record the parent of pruned changesets
We need this information to build the set of relevant markers during
exchanges. This can only be done at the `createmarkers` level since
the `obsstore.create` function does not have a repo and therefore has
no access to the parent information.
2014-08-18 16:17:16 -07:00
Pierre-Yves David
767b2c8f0d obsstore: add a parents argument to obsstore.create
We need a way to pass the information to the function. Some guru told me that
what's arguments are made for.
2014-08-18 16:12:29 -07:00
Pierre-Yves David
95fa5b1577 obsstore: add a parents field
This field is intended to store the parent of the precursor. This is useful to
attach pruned changesets to a set of exchanged changesets. We currently just
add the fields with a None value. None stands for "no data recorded".
2014-08-18 16:08:44 -07:00
Pierre-Yves David
21ceed5f91 obsstore: add some documentation about the marker fields
As the number of fields grow, it makes sense to start documenting their contents.
2014-08-19 14:42:08 -07:00
Pierre-Yves David
3b78721608 obsmarker: add date as an explicit field
The markers are now 5-item tuples (concluded by the date). The obsstore.fields
contents have been updated accordingly.

There is no change to the on-disk format yet, so the date has to be extracted
every time we read binary markers and re-injected each team we write them. This
introduces a slowdown that will be solved when a new version of the format is
added. Such a slowdown was already introduced by the evolve extension anyway.
2014-08-19 10:01:06 -07:00
Pierre-Yves David
971ae35ea3 obsstore: add fields attribute to track each field in a marker
We are going to increase the amount of data explicitly stored in obsolescence
markers. This mean we are going to have a longer tuple and some values will be
shuffled around. So we add a ``fields`` attribute to the obsstore class to
keep track of what entry is what. This will be useful for extensions and for
documentation purpose.
2014-08-12 01:49:38 -07:00
Pierre-Yves David
f43f2ce984 obsolete: add a date argument to the createmarkers function
The function is now just passing the value to create markers.
2014-08-14 12:59:48 -07:00
Pierre-Yves David
a9a2652690 obsstore: add an explicit date argument to obsstore.create
The date will become an official field in the markers (and ultimately
in the on-disk format). We start by making it an official argument for
the function.
2014-08-13 22:44:47 -07:00
Pierre-Yves David
3b69b7e067 obsolete: explicitly pass metadata argument using keyword argument
We are about to add more arguments to this function (date, parents, etc).
Passing metadata as a keyword argument gives us more flexibility when adding
them.
2014-08-14 01:53:07 -07:00
Pierre-Yves David
b1789db911 obsmarker: add a flags method
We introduce a proper method to access the flag information.
2014-08-15 09:41:30 -07:00
Matt Mackall
92e0debc2b merge with stable 2014-08-15 11:48:05 -05:00
Mads Kiilerich
5d377a8588 cleanup: avoid local vars shadowing imports
This will mute some pyflakes "import ... shadowed by loop variable" warnings.
2014-08-15 16:20:47 +02:00
Pierre-Yves David
8bf8eb1b78 obsstore.create: add a simple safeguard against cyclic markers
We detect when there is a cycle in the marker itself (precursors being listed
as successors).
2014-08-14 14:59:42 -07:00
Martin Geisler
df032a1bc2 obsolete: fix one-element tuple in module docstring 2014-04-19 20:12:53 +02:00
Martin Geisler
010f4026c6 obsolete: let N denote number of obsoleted changestes in a marker
The number of obsoleted changesets is referred to as N later in the
docstring.
2014-04-19 19:53:46 +02:00