[PATCH] Add script to rewrite manifest to workaround lack of parent deltas
benoit.boissinot at ens-lyon.org
Mon Aug 24 11:26:01 CDT 2009
On Fri, Aug 21, 2009 at 06:18:02PM -0400, Greg Ward wrote:
> # HG changeset patch
> # User Greg Ward <greg-hg at gerg.ca>
> # Date 1233047576 0
> # Node ID 4b03b395c5923319c1d9986ab47e6e3d99bfc6f8
> # Parent b47fa638bfc7d6e5185f49113a6c418fbe6cf0b3
> Add script to rewrite manifest to workaround lack of parent deltas.
Other comments (sorry I should have batched the review).
> +# Originally written by Benoit Boissinot <benoit.boissinot at ens-lyon.org>
> +# as a patch to rewrite-log. Cleaned up, refactored, documented, and
> +# renamed by Greg Ward <greg at gerg.ca>.
> +# XXX would be nice to have a way to verify the repository after shrinking,
> +# e.g. by comparing "before" and "after" states of random changesets
> +# (maybe: export before, shrink, export after, diff).
> +import sys, os, tempfile
> +from mercurial import ui as ui_, hg, revlog, transaction, node, util
> +def toposort(rl):
If you want to use .pop() (I'm not sure it's worth it):
> + # XXX this is a reimplementation of the 'branchsort' topo sort
> + # algorithm in hgext.convert.convcmd... would be nice not to duplicate
> + # the algorithm
> + write('sorting ...')
> + visit = root
> + ret = 
> + while visit:
> + i = visit.pop(0)
i = visit.pop()
> + ret.append(i)
> + if i not in children:
> + # This only happens if some node's p1 == p2, which can
> + # happen in the manifest in certain circumstances.
> + continue
> + next = 
> + for c in children.pop(i):
> + parents_unseen = [p for p in rl.parentrevs(c)
> + if p != node.nullrev and p in children]
> + if len(parents_unseen) == 0:
> + next.append(c)
> + visit = next + visit
visit += next
> +def main():
> + # Unbuffer stdout for nice progress output.
> + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
> + write = sys.stdout.write
> + # Open the local repository.
> + ui = ui_.ui()
> + repo = hg.repository(ui)
> + indexfn = repo.join('store/00manifest.i')
> + datafn = indexfn[:-2] + '.d'
> + if not os.path.exists(datafn):
> + sys.exit('error: %s does not exist: manifest not big enough '
> + 'to be worth shrinking' % datafn)
I've found the warning annoying so I changed it like this:
> + oldindexfn = indexfn + '.old'
> + olddatafn = datafn + '.old'
oldindexfn = tempfile.mktemp(dir=repo.sjoin(''),
olddatafn = oldindexfn[:-6] + '.d.old'
> + if os.path.exists(oldindexfn) or os.path.exists(olddatafn):
> + sys.exit('error: one or both of %s or %s exists from a previous run; '
> + 'please clean up before running again'
> + % (oldindexfn, olddatafn))
Final note: If someone wants to do that, the script could accept
arbitrary revlogs as arguments, except the changelog (because it would
need fixing the linkrevs).
More information about the Mercurial-devel