# HG changeset patch # User Durham Goode # Date 1385511785 28800 # Node ID 578b888c820e9b556d9ff63c6a83be213232d625 # Parent 7ac03bfa136940370da4848993620c24352a5a27 unshelve: don't commit unknown files during unshelve (issue4113) Previously, unshelve would temporarily commit unknown files (via addremove) in an attempt to allow unshelving into unknown files. This produced unexpected results, like the file time stamp changing and a .i file being created. This change makes it no longer use addremove. It ignores unknown files completely. If an unshelve would overwrite an unknown file, the unknown file is moved to *.orig The shelve continue/abort format is changed, but it just removes stuff from the end of the file, so it can still read the old format. diff -r 7ac03bfa1369 -r 578b888c820e hgext/shelve.py --- a/hgext/shelve.py Tue Nov 26 15:38:33 2013 +0100 +++ b/hgext/shelve.py Tue Nov 26 16:23:05 2013 -0800 @@ -91,7 +91,6 @@ pendingctx = fp.readline().strip() parents = [bin(h) for h in fp.readline().split()] stripnodes = [bin(h) for h in fp.readline().split()] - unknownfiles = fp.readline()[:-1].split('\0') finally: fp.close() @@ -101,13 +100,11 @@ obj.pendingctx = repo[bin(pendingctx)] obj.parents = parents obj.stripnodes = stripnodes - obj.unknownfiles = unknownfiles return obj @classmethod - def save(cls, repo, name, originalwctx, pendingctx, stripnodes, - unknownfiles): + def save(cls, repo, name, originalwctx, pendingctx, stripnodes): fp = repo.opener(cls._filename, 'wb') fp.write('%i\n' % cls._version) fp.write('%s\n' % name) @@ -115,7 +112,6 @@ fp.write('%s\n' % hex(pendingctx.node())) fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()])) fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes])) - fp.write('%s\n' % '\0'.join(unknownfiles)) fp.close() @classmethod @@ -379,7 +375,7 @@ lock = repo.lock() - mergefiles(ui, repo, state.wctx, state.pendingctx, state.unknownfiles) + mergefiles(ui, repo, state.wctx, state.pendingctx) repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') shelvedstate.clear(repo) @@ -387,9 +383,9 @@ finally: lockmod.release(lock, wlock) -def mergefiles(ui, repo, wctx, shelvectx, unknownfiles): +def mergefiles(ui, repo, wctx, shelvectx): """updates to wctx and merges the changes from shelvectx into the - dirstate. drops any files in unknownfiles from the dirstate.""" + dirstate.""" oldquiet = ui.quiet try: ui.quiet = True @@ -397,17 +393,18 @@ files = [] files.extend(shelvectx.files()) files.extend(shelvectx.parents()[0].files()) + + # revert will overwrite unknown files, so move them out of the way + m, a, r, d, u = repo.status(unknown=True)[:5] + for file in u: + if file in files: + util.rename(file, file + ".orig") cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(), *pathtofiles(repo, files), **{'no_backup': True}) finally: ui.quiet = oldquiet - # Send untracked files back to being untracked - dirstate = repo.dirstate - for f in unknownfiles: - dirstate.drop(f) - def unshelvecleanup(ui, repo, name, opts): """remove related files after an unshelve""" if not opts['keep']: @@ -446,7 +443,7 @@ # rebase was a no-op, so it produced no child commit shelvectx = state.pendingctx - mergefiles(ui, repo, state.wctx, shelvectx, state.unknownfiles) + mergefiles(ui, repo, state.wctx, shelvectx) state.stripnodes.append(shelvectx.node()) repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve') @@ -538,8 +535,8 @@ # to the original wctx. # Store pending changes in a commit - m, a, r, d, u = repo.status(unknown=True)[:5] - if m or a or r or d or u: + m, a, r, d = repo.status()[:4] + if m or a or r or d: def commitfunc(ui, repo, message, match, opts): hasmq = util.safehasattr(repo, 'mq') if hasmq: @@ -554,7 +551,6 @@ tempopts = {} tempopts['message'] = "pending changes temporary commit" - tempopts['addremove'] = True oldquiet = ui.quiet try: ui.quiet = True @@ -588,7 +584,7 @@ stripnodes = [repo.changelog.node(rev) for rev in xrange(oldtiprev, len(repo))] - shelvedstate.save(repo, basename, wctx, tmpwctx, stripnodes, u) + shelvedstate.save(repo, basename, wctx, tmpwctx, stripnodes) util.rename(repo.join('rebasestate'), repo.join('unshelverebasestate')) @@ -603,7 +599,7 @@ # rebase was a no-op, so it produced no child commit shelvectx = tmpwctx - mergefiles(ui, repo, wctx, shelvectx, u) + mergefiles(ui, repo, wctx, shelvectx) shelvedstate.clear(repo) # The transaction aborting will strip all the commits for us,