if `--dest` does not contains the current working direct rebase crash and leave the user in a complicated situation. going to repository root and using rebase --continue seems to work fine. I suspect other command to be affected. We have multiple options here: 1. automatically update to parent directory if cwd is deleted 2. don't delete the parent directory in that case 3. warn before doing the rebase 4. cleanly abort during the process.
What precisely causes the crash? Can you include a trace? The ideal solution would simply be "don't crash." Deleting the current working directory doesn't usually need to be fatal.
Ping.
I'm using this test script for testing: $ cat >> $HGRCPATH <<EOF > [extensions] > rebase= > > [alias] > tglog = log -G --template "{rev}: '{desc}' {branches}\n" > EOF $ hg init a $ cd a $ touch initial-file $ hg add initial-file $ hg commit -m 'initial commit' $ touch dest-file $ hg add dest-file $ hg commit -m 'dest commit' $ hg up 0 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ touch other-file $ hg add other-file $ hg commit -m 'first source commit' created new head $ mkdir subdir $ cd subdir $ touch subfile $ hg add subfile $ hg commit -m 'second source with subdir' $ hg rebase -b . -d 1 --traceback I'm getting the following traceback + Traceback (most recent call last): + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 134, in _runcatch + return _dispatch(req) + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 807, in _dispatch + cmdpats, cmdoptions) + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 586, in runcommand + ret = _runcommand(ui, options, cmd, d) + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 898, in _runcommand + return checkargs() + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 869, in checkargs + return cmdfunc() + File "/home/pyd/src/mercurial-dev/mercurial/dispatch.py", line 804, in <lambda> + d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) + File "/home/pyd/src/mercurial-dev/mercurial/util.py", line 512, in check + return func(*args, **kwargs) + File "/home/pyd/src/mercurial-dev/hgext/rebase.py", line 308, in rebase + stats = rebasenode(repo, rev, p1, state, collapsef) + File "/home/pyd/src/mercurial-dev/hgext/rebase.py", line 494, in rebasenode + return merge.update(repo, rev, True, True, False, base, collapse) + File "/home/pyd/src/mercurial-dev/mercurial/merge.py", line 756, in update + branchmerge, force, partial, mergeancestor) + File "/home/pyd/src/mercurial-dev/mercurial/merge.py", line 566, in calculateupdates + partial, acceptremote) + File "/home/pyd/src/mercurial-dev/mercurial/merge.py", line 228, in manifestmerge + ret = copies.mergecopies(repo, wctx, p2, pa) + File "/home/pyd/src/mercurial-dev/mercurial/copies.py", line 208, in mergecopies + m1 = c1.manifest() + File "/home/pyd/src/mercurial-dev/mercurial/context.py", line 77, in manifest + return self._manifest + File "/home/pyd/src/mercurial-dev/mercurial/util.py", line 281, in __get__ + result = self.func(obj) + File "/home/pyd/src/mercurial-dev/mercurial/context.py", line 935, in _manifest + modified, added, removed, deleted = self._status + File "/home/pyd/src/mercurial-dev/mercurial/util.py", line 281, in __get__ + result = self.func(obj) + File "/home/pyd/src/mercurial-dev/mercurial/context.py", line 953, in _status + return self._repo.status()[:4] + File "/home/pyd/src/mercurial-dev/mercurial/localrepo.py", line 1485, in status + match = match or matchmod.always(self.root, self.getcwd()) + File "/home/pyd/src/mercurial-dev/mercurial/localrepo.py", line 749, in getcwd + return self.dirstate.getcwd() + File "/home/pyd/src/mercurial-dev/mercurial/dirstate.py", line 166, in getcwd + cwd = os.getcwd() + OSError: [Errno 2] No such file or directory So the first to fail is the dirstate code.
Possible fix: diff -r 427d672c0e4e mercurial/dirstate.py --- a/mercurial/dirstate.py Sun Nov 24 02:17:17 2013 +0100 +++ b/mercurial/dirstate.py Fri Jan 24 16:51:20 2014 -0600 @@ -162,8 +162,12 @@ else: return fallback + @propertycache + def _cwd(self): + return os.getcwd() + def getcwd(self): - cwd = os.getcwd() + cwd = self._cwd if cwd == self._root: return '' # self._root ends with a path separator if self._root is '/' or 'C:\' This caches our notion of cwd at first use. Since we're primarily using this to understand relative paths given as args, this should be fine. But there seem to be a bunch of other getcwd calls around.
Requires this fix to record diff --git a/hgext/record.py b/hgext/record.py --- a/hgext/record.py +++ b/hgext/record.py @@ -599,16 +599,12 @@ def dorecord(ui, repo, commitfunc, cmdsu # commit/qrefresh or the like! # it is important to first chdir to repo root -- we'll call # a highlevel command with list of pathnames relative to # repo root - cwd = os.getcwd() - os.chdir(repo.root) - try: - commitfunc(ui, repo, *newfiles, **opts) - finally: - os.chdir(cwd) + newfiles = [repo.wjoin(nf) for nf in newfiles] + commitfunc(ui, repo, *newfiles, **opts) return 0 finally: # 5. finally restore backed-up files try:
Fixed by http://selenic.com/repo/hg/rev/e40520642e64 Pierre-Yves David <pierre-yves.david@logilab.fr> rebase: do not crash in panic when cwd disapear in the process (issue4121) Before this patch rebase crashed badly when it happend. (not abort, crash). Fix courtesy of Matt Mackall. (please test the fix)