Bug 3335 - convert with filemap aborts
Summary: convert with filemap aborts
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: convert (show other bugs)
Version: unspecified
Hardware: All All
: normal bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-23 07:01 UTC by Stefan Ring
Modified: 2013-01-17 18:56 UTC (History)
6 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Ring 2012-03-23 07:00 UTC
The repository rollback during hg convert seems to confuse the convert
process, leading to repository corruption.

I guess this is a follow-up to issue 2185.

A small excerpt from the repo graph log looks like this:

  | o    changeset:   23560:d699d7e3890d
  | |\   parent:      23559:59559cbdd62e
  | | |  parent:      23557:720ee305fbbd
  | | |  user:        cr@****
  | | |  date:        Tue Jan 24 12:13:14 2012 +0100
  | | |  summary:     kill-merged 720ee305fbbd
  | | |
  | | o    changeset:   23559:59559cbdd62e
  | | |\   parent:      23558:14c4805b6197
  | | | |  parent:      23556:785e465b4885
  | | | |  user:        cr@****
  | | | |  date:        Tue Jan 24 12:12:52 2012 +0100
  | | | |  summary:     kill-merged 785e465b4885
  | | | |
  | | | o    changeset:   23558:14c4805b6197
  | | | |\   parent:      23554:6f859fcb9a96
  | | | | |  parent:      23555:6344d5fbe8f0
  | | | | |  user:        cr@****
  | | | | |  date:        Tue Jan 24 12:11:58 2012 +0100
  | | | | |  summary:     kill-merged 6344d5fbe8f0
  | | | | |
  | o | | |  changeset:   23557:720ee305fbbd
  | | | | |  parent:      12002:bba474e74bf8
  | | | | |  user:        cr@****
  | | | | |  date:        Tue Jan 24 11:52:02 2012 +0100
  | | | | |  summary:     closed old default branch
  | | | | |
  | | o | |  changeset:   23556:785e465b4885
  | | | | |  parent:      11743:219879963eb1
  | | | | |  user:        cr@****
  | | | | |  date:        Tue Jan 24 11:51:55 2012 +0100
  | | | | |  summary:     closed old default branch
  | | | | |
  | | | | o  changeset:   23555:6344d5fbe8f0
  | | | | |  parent:      9126:6b28fd96adcb
  | | | | |  user:        cr@****
  | | | | |  date:        Tue Jan 24 11:51:26 2012 +0100
  | | | | |  summary:     closed old default branch
  | | | | |
  +-----o |  changeset:   23554:6f859fcb9a96
  | | | | |  parent:      23548:df450238eb0a
  | | | | |  parent:      23553:3e581f66dc69
  | | | | |  user:        cr@****
  | | | | |  date:        Tue Jan 24 11:45:29 2012 +0100
  | | | | |  summary:     merged V1.12

During convert into a fresh repository, using a filemap of only a single
line ("include <subdir>"), it goes like this (2628949f3521 is the current head):

$ ~/temp/bitbucket-mercurial/hg convert --filemap process.filemap -r
2628949f3521 /huge/hgpull/<product>_headonly process

  1281 closed old default branch
  1280 closed old default branch
  1279 closed old default branch
  1278 kill-merged 6344d5fbe8f0
  1277 kill-merged 785e465b4885
  filtering out empty revision
  repository tip rolled back to revision 776 (undo commit)
  1276 kill-merged 720ee305fbbd
  filtering out empty revision
  repository tip rolled back to revision 776 (undo commit)
  1275 ...
  1274 ...
  1273 Merged V1.12
  1272 ...
  ...

After a few more changesets -- at the next one which touches the filtered
subdir --, with Mercurial 2.0.1, I get an error like this:
  transaction abort!
  rollback completed
  abort: integrity check failed on 00changelog.i:778!

while with current hg-stable it throws a nice exception:

  ** unknown exception encountered, please report by visiting
  **  http://mercurial.selenic.com/wiki/BugTracker
  ** Python 2.7 (r27:82500, Sep 16 2010, 18:02:00) [GCC 4.5.1 20100907 (Red
Hat 4.5.1-3)]
  ** Mercurial Distributed SCM (version 2.1.1+23-2338ab19b236)
  ** Extensions loaded: hgk, children, color, convert, extdiff, graphlog,
mq, patchbomb,   purge, rebase, record, relink, transplant
  Traceback (most recent call last):
    File "/home/sr/temp/bitbucket-mercurial/hg", line 38, in <module>
      mercurial.dispatch.run()
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 27, in run
      sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 64, in   dispatch 
      return _runcatch(req)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 87, in   _runcatch
      return _dispatch(req)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 683, in   _dispatch
      cmdpats, cmdoptions)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 465, in   runcommand
      ret = _runcommand(ui, options, cmd, d)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/extensions.py",
line 184, in   wrap
      return wrapper(origfn, *args, **kwargs)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/color.py", line 362,
in colorcmd
      return orig(ui_, opts, cmd, cmdfunc)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 737, in   _runcommand
      return checkargs()
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 691, in   checkargs
      return cmdfunc()
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/dispatch.py",
line 680, in   <lambda>
      d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/util.py", line
456, in check
      return func(*args, **kwargs)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/convert/__init__.py",
line 269,   in convert
      return convcmd.convert(ui, src, dest, revmapfile, **opts)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/convert/convcmd.py",
line 469, in   convert
      c.convert(sortmode)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/convert/convcmd.py",
line 385, in   convert
      self.copy(c)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/convert/convcmd.py",
line 353, in   copy
      source, self.map)
    File "/huge/home/sr/temp/bitbucket-mercurial/hgext/convert/hg.py", line
171, in   putcommit
      self.repo.commitctx(ctx)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/localrepo.py",
line 1233, in   commitctx
      m2 = p2.manifest()
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/context.py", line
94, in   manifest
      return self._manifest
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/util.py", line
237, in __get__
      result = self.func(obj)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/context.py", line
64, in   _manifest
      return self._repo.manifest.read(self._changeset[0])
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/util.py", line
237, in __get__
      result = self.func(obj)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/context.py", line
60, in   _changeset
      return self._repo.changelog.read(self.node())
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/changelog.py",
line 192, in   read
      text = self.revision(node)
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/revlog.py", line
900, in   revision
      bins = [self._chunk(r) for r in chain]
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/revlog.py", line
828, in   _chunk
      return decompress(self._chunkraw(rev, rev))
    File "/huge/home/sr/temp/bitbucket-mercurial/mercurial/revlog.py", line
115, in   decompress
      return _decompress(bin)
  zlib.error: Error -5 while decompressing data: incomplete or truncated stream

If I do the same thing, but incrementally, it manages to get over these
problematic changesets. By incrementally, I mean calling hg convert
repeatedly, only changing the rev hash from one invocation to the next, in
this order:

59559cbdd62e (shown in graph log above)
d699d7e3890d (shown in graph log above)
2628949f3521 (head)

The first two invocations each end with
  filtering out empty revision
  repository tip rolled back to revision xxx (undo commit)

The third one (the same head as before) proceeds without a problem.

Unfortunately, I have not been able to create a small test case for this
yet. In particular, I'm not able to trigger the "filtering out empty
revision" piece at all.
Comment 1 kiilerix 2012-03-23 07:20 UTC
The "filtering out" case is touch in tests/test-convert-cvs.t ... but only
at the end of a conversion and thus not very likely to reproduce your case. 

Can you verify if it worked in 1.9.x? I wonder if it could be caused by
7c26ce9edbd2.
Comment 2 Stefan Ring 2012-03-23 07:27 UTC
Yes, it works in 1.9.3:

1281 kill-merged 6344d5fbe8f0
1280 kill-merged 785e465b4885
filtering out empty revision
repository tip rolled back to revision 777 (undo commit)
working directory now based on revision -1
1279 kill-merged 720ee305fbbd
filtering out empty revision
repository tip rolled back to revision 777 (undo commit)
working directory now based on revision -1

... and proceeds normally after that.
Comment 3 kiilerix 2012-03-23 07:29 UTC
Ok, so that can be used as a workaround.

Please try to bisect and see if the problem was introduced with 7c26ce9edbd2.
Comment 4 Stefan Ring 2012-03-23 07:56 UTC
This changeset breaks it: http://selenic.com/repo/hg/rev/d3ac759a6d66
Comment 5 Matt Mackall 2012-03-23 09:31 UTC
Fixing title: the rollback happens -after- the problem is detected (but
before it's reported).
Comment 6 Bugzilla 2012-05-12 09:29 UTC
--- Bug imported by bugzilla@serpentine.com 2012-05-12 09:29 EDT  ---

This bug was previously known as _bug_ 3334 at http://mercurial.selenic.com/bts/issue3334
Comment 7 HG Bot 2013-01-17 12:30 UTC
Fixed by http://selenic.com/repo/hg/rev/3e4a944c0d04
Idan Kamara <idankk86@gmail.com>
destroyed: keep the filecache in sync with __dict__ (issue3335) (issue3693) (issue3743)

We need to make sure that if X is in the filecache then it's also in the
filecache owner's __dict__, otherwise it will go out of sync:

repo.X                  # first access to X, records stat info in
                        # filecache and updates __dict__
repo._filecache.clear() # removes X from _filecache but it's still in __dict__
repo.invalidate()       # iterates over _filecache and removes entries
                        # from __dict__, but X isn't in _filecache, so
                        # it's kept in __dict__
repo.X                  # X is fetched from __dict__, bypassing the filecache

(please test the fix)
Comment 8 Stefan Ring 2013-01-17 18:54 UTC
(In reply to comment #7)

> (please test the fix)

Works for me!