##// END OF EJS Templates
unshelve: add interactive mode...
Navaneeth Suresh -
r43220:5162753c default
parent child Browse files
Show More
@@ -266,8 +266,8 b' def dorecord(ui, repo, commitfunc, cmdsu'
266 In the end we'll record interesting changes, and everything else
266 In the end we'll record interesting changes, and everything else
267 will be left in place, so the user can continue working.
267 will be left in place, so the user can continue working.
268 """
268 """
269
269 if not opts.get('interactive-unshelve'):
270 checkunfinished(repo, commit=True)
270 checkunfinished(repo, commit=True)
271 wctx = repo[None]
271 wctx = repo[None]
272 merge = len(wctx.parents()) > 1
272 merge = len(wctx.parents()) > 1
273 if merge:
273 if merge:
@@ -6168,6 +6168,8 b' def unbundle(ui, repo, fname1, *fnames, '
6168 _('abort an incomplete unshelve operation')),
6168 _('abort an incomplete unshelve operation')),
6169 ('c', 'continue', None,
6169 ('c', 'continue', None,
6170 _('continue an incomplete unshelve operation')),
6170 _('continue an incomplete unshelve operation')),
6171 ('i', 'interactive', None,
6172 _('use interactive mode')),
6171 ('k', 'keep', None,
6173 ('k', 'keep', None,
6172 _('keep shelve after unshelving')),
6174 _('keep shelve after unshelving')),
6173 ('n', 'name', '',
6175 ('n', 'name', '',
@@ -6175,7 +6177,7 b' def unbundle(ui, repo, fname1, *fnames, '
6175 ('t', 'tool', '', _('specify merge tool')),
6177 ('t', 'tool', '', _('specify merge tool')),
6176 ('', 'date', '',
6178 ('', 'date', '',
6177 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
6179 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
6178 _('hg unshelve [[-n] SHELVED]'),
6180 _('hg unshelve [OPTION]... [FILE]... [-n SHELVED]'),
6179 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
6181 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
6180 def unshelve(ui, repo, *shelved, **opts):
6182 def unshelve(ui, repo, *shelved, **opts):
6181 """restore a shelved change to the working directory
6183 """restore a shelved change to the working directory
@@ -694,10 +694,11 b' def unshelvecleanup(ui, repo, name, opts'
694 if shfile.exists():
694 if shfile.exists():
695 shfile.movetobackup()
695 shfile.movetobackup()
696 cleanupoldbackups(repo)
696 cleanupoldbackups(repo)
697 def unshelvecontinue(ui, repo, state, opts):
697 def unshelvecontinue(ui, repo, state, opts, basename=None):
698 """subcommand to continue an in-progress unshelve"""
698 """subcommand to continue an in-progress unshelve"""
699 # We're finishing off a merge. First parent is our original
699 # We're finishing off a merge. First parent is our original
700 # parent, second is the temporary "fake" commit we're unshelving.
700 # parent, second is the temporary "fake" commit we're unshelving.
701 interactive = opts.get('interactive')
701 with repo.lock():
702 with repo.lock():
702 checkparents(repo, state)
703 checkparents(repo, state)
703 ms = merge.mergestate.read(repo)
704 ms = merge.mergestate.read(repo)
@@ -720,10 +721,15 b' def unshelvecontinue(ui, repo, state, op'
720 with repo.ui.configoverride(overrides, 'unshelve'):
721 with repo.ui.configoverride(overrides, 'unshelve'):
721 with repo.dirstate.parentchange():
722 with repo.dirstate.parentchange():
722 repo.setparents(state.parents[0], nodemod.nullid)
723 repo.setparents(state.parents[0], nodemod.nullid)
723 newnode = repo.commit(text=shelvectx.description(),
724 if not interactive:
724 extra=shelvectx.extra(),
725 ispartialunshelve = False
725 user=shelvectx.user(),
726 newnode = repo.commit(text=shelvectx.description(),
726 date=shelvectx.date())
727 extra=shelvectx.extra(),
728 user=shelvectx.user(),
729 date=shelvectx.date())
730 else:
731 newnode, ispartialunshelve = _dounshelveinteractive(ui,
732 repo, shelvectx, basename, opts)
727
733
728 if newnode is None:
734 if newnode is None:
729 # If it ended up being a no-op commit, then the normal
735 # If it ended up being a no-op commit, then the normal
@@ -743,12 +749,13 b' def unshelvecontinue(ui, repo, state, op'
743 mergefiles(ui, repo, state.wctx, shelvectx)
749 mergefiles(ui, repo, state.wctx, shelvectx)
744 restorebranch(ui, repo, state.branchtorestore)
750 restorebranch(ui, repo, state.branchtorestore)
745
751
746 if not phases.supportinternal(repo):
752 if not ispartialunshelve:
747 repair.strip(ui, repo, state.nodestoremove, backup=False,
753 if not phases.supportinternal(repo):
748 topic='shelve')
754 repair.strip(ui, repo, state.nodestoremove, backup=False,
755 topic='shelve')
756 shelvedstate.clear(repo)
757 unshelvecleanup(ui, repo, state.name, opts)
749 _restoreactivebookmark(repo, state.activebookmark)
758 _restoreactivebookmark(repo, state.activebookmark)
750 shelvedstate.clear(repo)
751 unshelvecleanup(ui, repo, state.name, opts)
752 ui.status(_("unshelve of '%s' complete\n") % state.name)
759 ui.status(_("unshelve of '%s' complete\n") % state.name)
753
760
754 def hgcontinueunshelve(ui, repo):
761 def hgcontinueunshelve(ui, repo):
@@ -797,14 +804,40 b' def _unshelverestorecommit(ui, repo, tr,'
797
804
798 return repo, shelvectx
805 return repo, shelvectx
799
806
807 def _dounshelveinteractive(ui, repo, shelvectx, basename, opts):
808 """The user might want to unshelve certain changes only from the stored
809 shelve. So, we would create two commits. One with requested changes to
810 unshelve at that time and the latter is shelved for future.
811 """
812 opts['message'] = shelvectx.description()
813 opts['interactive-unshelve'] = True
814 pats = []
815 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True,
816 editor=True)
817 newnode = cmdutil.dorecord(ui, repo, commitfunc, None, False,
818 cmdutil.recordfilter, *pats,
819 **pycompat.strkwargs(opts))
820 snode = repo.commit(text=shelvectx.description(),
821 extra=shelvectx.extra(),
822 user=shelvectx.user(),
823 date=shelvectx.date())
824 m = scmutil.matchfiles(repo, repo[snode].files())
825 if snode:
826 _shelvecreatedcommit(repo, snode, basename, m)
827
828 return newnode, bool(snode)
829
800 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx,
830 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx,
801 tmpwctx, shelvectx, branchtorestore,
831 tmpwctx, shelvectx, branchtorestore,
802 activebookmark):
832 activebookmark):
803 """Rebase restored commit from its original location to a destination"""
833 """Rebase restored commit from its original location to a destination"""
804 # If the shelve is not immediately on top of the commit
834 # If the shelve is not immediately on top of the commit
805 # we'll be merging with, rebase it to be on top.
835 # we'll be merging with, rebase it to be on top.
806 if tmpwctx.node() == shelvectx.p1().node():
836 interactive = opts.get('interactive')
807 return shelvectx
837 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
838 # We won't skip on interactive mode because, the user might want to
839 # unshelve certain changes only.
840 return shelvectx, False
808
841
809 overrides = {
842 overrides = {
810 ('ui', 'forcemerge'): opts.get('tool', ''),
843 ('ui', 'forcemerge'): opts.get('tool', ''),
@@ -828,10 +861,15 b' def _rebaserestoredcommit(ui, repo, opts'
828
861
829 with repo.dirstate.parentchange():
862 with repo.dirstate.parentchange():
830 repo.setparents(tmpwctx.node(), nodemod.nullid)
863 repo.setparents(tmpwctx.node(), nodemod.nullid)
831 newnode = repo.commit(text=shelvectx.description(),
864 if not interactive:
832 extra=shelvectx.extra(),
865 ispartialunshelve = False
833 user=shelvectx.user(),
866 newnode = repo.commit(text=shelvectx.description(),
834 date=shelvectx.date())
867 extra=shelvectx.extra(),
868 user=shelvectx.user(),
869 date=shelvectx.date())
870 else:
871 newnode, ispartialunshelve = _dounshelveinteractive(ui, repo,
872 shelvectx, basename, opts)
835
873
836 if newnode is None:
874 if newnode is None:
837 # If it ended up being a no-op commit, then the normal
875 # If it ended up being a no-op commit, then the normal
@@ -846,7 +884,7 b' def _rebaserestoredcommit(ui, repo, opts'
846 shelvectx = repo[newnode]
884 shelvectx = repo[newnode]
847 hg.updaterepo(repo, tmpwctx.node(), False)
885 hg.updaterepo(repo, tmpwctx.node(), False)
848
886
849 return shelvectx
887 return shelvectx, ispartialunshelve
850
888
851 def _forgetunknownfiles(repo, shelvectx, addedbefore):
889 def _forgetunknownfiles(repo, shelvectx, addedbefore):
852 # Forget any files that were unknown before the shelve, unknown before
890 # Forget any files that were unknown before the shelve, unknown before
@@ -883,13 +921,14 b' def dounshelve(ui, repo, *shelved, **opt'
883 opts = pycompat.byteskwargs(opts)
921 opts = pycompat.byteskwargs(opts)
884 abortf = opts.get('abort')
922 abortf = opts.get('abort')
885 continuef = opts.get('continue')
923 continuef = opts.get('continue')
924 interactive = opts.get('interactive')
886 if not abortf and not continuef:
925 if not abortf and not continuef:
887 cmdutil.checkunfinished(repo)
926 cmdutil.checkunfinished(repo)
888 shelved = list(shelved)
927 shelved = list(shelved)
889 if opts.get("name"):
928 if opts.get("name"):
890 shelved.append(opts["name"])
929 shelved.append(opts["name"])
891
930
892 if abortf or continuef:
931 if abortf or continuef and not interactive:
893 if abortf and continuef:
932 if abortf and continuef:
894 raise error.Abort(_('cannot use both abort and continue'))
933 raise error.Abort(_('cannot use both abort and continue'))
895 if shelved:
934 if shelved:
@@ -911,8 +950,11 b' def dounshelve(ui, repo, *shelved, **opt'
911 raise error.Abort(_('no shelved changes to apply!'))
950 raise error.Abort(_('no shelved changes to apply!'))
912 basename = util.split(shelved[0][1])[1]
951 basename = util.split(shelved[0][1])[1]
913 ui.status(_("unshelving change '%s'\n") % basename)
952 ui.status(_("unshelving change '%s'\n") % basename)
914 else:
953 elif shelved:
915 basename = shelved[0]
954 basename = shelved[0]
955 if continuef and interactive:
956 state = _loadshelvedstate(ui, repo, opts)
957 return unshelvecontinue(ui, repo, state, opts, basename)
916
958
917 if not shelvedfile(repo, basename, patchextension).exists():
959 if not shelvedfile(repo, basename, patchextension).exists():
918 raise error.Abort(_("shelved change '%s' not found") % basename)
960 raise error.Abort(_("shelved change '%s' not found") % basename)
@@ -941,19 +983,19 b' def dounshelve(ui, repo, *shelved, **opt'
941 if shelvectx.branch() != shelvectx.p1().branch():
983 if shelvectx.branch() != shelvectx.p1().branch():
942 branchtorestore = shelvectx.branch()
984 branchtorestore = shelvectx.branch()
943
985
944 shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
986 shelvectx, ispartialunshelve = _rebaserestoredcommit(ui, repo, opts,
945 basename, pctx, tmpwctx,
987 tr, oldtiprev, basename, pctx, tmpwctx, shelvectx,
946 shelvectx, branchtorestore,
988 branchtorestore, activebookmark)
947 activebookmark)
948 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
989 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
949 with ui.configoverride(overrides, 'unshelve'):
990 with ui.configoverride(overrides, 'unshelve'):
950 mergefiles(ui, repo, pctx, shelvectx)
991 mergefiles(ui, repo, pctx, shelvectx)
951 restorebranch(ui, repo, branchtorestore)
992 restorebranch(ui, repo, branchtorestore)
952 _forgetunknownfiles(repo, shelvectx, addedbefore)
993 if not ispartialunshelve:
994 _forgetunknownfiles(repo, shelvectx, addedbefore)
953
995
954 shelvedstate.clear(repo)
996 shelvedstate.clear(repo)
955 _finishunshelve(repo, oldtiprev, tr, activebookmark)
997 _finishunshelve(repo, oldtiprev, tr, activebookmark)
956 unshelvecleanup(ui, repo, basename, opts)
998 unshelvecleanup(ui, repo, basename, opts)
957 finally:
999 finally:
958 if tr:
1000 if tr:
959 tr.release()
1001 tr.release()
@@ -354,7 +354,7 b' Show all commands + options'
354 tags: template
354 tags: template
355 tip: patch, git, style, template
355 tip: patch, git, style, template
356 unbundle: update
356 unbundle: update
357 unshelve: abort, continue, keep, name, tool, date
357 unshelve: abort, continue, interactive, keep, name, tool, date
358 update: clean, check, merge, date, rev, tool
358 update: clean, check, merge, date, rev, tool
359 verify: full
359 verify: full
360 version: template
360 version: template
@@ -1158,3 +1158,228 b' Abort unshelve while merging (issue5123)'
1158 [255]
1158 [255]
1159
1159
1160 $ cd ..
1160 $ cd ..
1161
1162 -- test for interactive mode on unshelve
1163
1164 $ hg init a
1165 $ cd a
1166 $ echo > b
1167 $ hg ci -Am b
1168 adding b
1169 $ echo > c
1170 $ echo > d
1171 $ hg add .
1172 adding c
1173 adding d
1174 $ hg shelve
1175 shelved as default
1176 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1177 $ echo > e
1178 $ hg add e
1179 $ hg ci -m e
1180 $ hg shelve --patch
1181 default (1s ago) changes to: b
1182
1183 diff --git a/c b/c
1184 new file mode 100644
1185 --- /dev/null
1186 +++ b/c
1187 @@ -0,0 +1,1 @@
1188 +
1189 diff --git a/d b/d
1190 new file mode 100644
1191 --- /dev/null
1192 +++ b/d
1193 @@ -0,0 +1,1 @@
1194 +
1195 $ hg unshelve -i <<EOF
1196 > y
1197 > y
1198 > y
1199 > n
1200 > EOF
1201 unshelving change 'default'
1202 rebasing shelved changes
1203 diff --git a/c b/c
1204 new file mode 100644
1205 examine changes to 'c'?
1206 (enter ? for help) [Ynesfdaq?] y
1207
1208 @@ -0,0 +1,1 @@
1209 +
1210 record change 1/2 to 'c'?
1211 (enter ? for help) [Ynesfdaq?] y
1212
1213 diff --git a/d b/d
1214 new file mode 100644
1215 examine changes to 'd'?
1216 (enter ? for help) [Ynesfdaq?] y
1217
1218 @@ -0,0 +1,1 @@
1219 +
1220 record change 2/2 to 'd'?
1221 (enter ? for help) [Ynesfdaq?] n
1222
1223 $ ls
1224 b
1225 c
1226 e
1227 -- shelve should not contain `c` now
1228 $ hg shelve --patch
1229 default (1s ago) changes to: b
1230
1231 diff --git a/d b/d
1232 new file mode 100644
1233 --- /dev/null
1234 +++ b/d
1235 @@ -0,0 +1,1 @@
1236 +
1237 $ hg unshelve -i <<EOF
1238 > y
1239 > y
1240 > EOF
1241 unshelving change 'default'
1242 rebasing shelved changes
1243 diff --git a/d b/d
1244 new file mode 100644
1245 examine changes to 'd'?
1246 (enter ? for help) [Ynesfdaq?] y
1247
1248 @@ -0,0 +1,1 @@
1249 +
1250 record this change to 'd'?
1251 (enter ? for help) [Ynesfdaq?] y
1252
1253 $ ls
1254 b
1255 c
1256 d
1257 e
1258 $ hg shelve --list
1259
1260 -- now, unshelve selected changes from a file
1261
1262 $ echo B > foo
1263 $ hg add foo
1264 $ hg ci -m 'add B to foo'
1265 $ cat > foo <<EOF
1266 > A
1267 > B
1268 > C
1269 > EOF
1270 $ hg shelve
1271 shelved as default
1272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1273 $ cat foo
1274 B
1275 $ hg unshelve -i <<EOF
1276 > y
1277 > y
1278 > n
1279 > EOF
1280 unshelving change 'default'
1281 rebasing shelved changes
1282 diff --git a/foo b/foo
1283 2 hunks, 2 lines changed
1284 examine changes to 'foo'?
1285 (enter ? for help) [Ynesfdaq?] y
1286
1287 @@ -1,1 +1,2 @@
1288 +A
1289 B
1290 record change 1/2 to 'foo'?
1291 (enter ? for help) [Ynesfdaq?] y
1292
1293 @@ -1,1 +2,2 @@
1294 B
1295 +C
1296 record change 2/2 to 'foo'?
1297 (enter ? for help) [Ynesfdaq?] n
1298
1299 $ cat foo
1300 A
1301 B
1302 $ hg shelve --patch
1303 default (1s ago) changes to: add B to foo
1304
1305 diff --git a/foo b/foo
1306 --- a/foo
1307 +++ b/foo
1308 @@ -1,2 +1,3 @@
1309 A
1310 B
1311 +C
1312
1313 -- unshelve interactive on conflicts
1314
1315 $ echo A >> bar1
1316 $ echo A >> bar2
1317 $ hg add bar1 bar2
1318 $ hg ci -m 'add A to bars'
1319 $ echo B >> bar1
1320 $ echo B >> bar2
1321 $ hg shelve
1322 shelved as default-01
1323 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1324 $ echo C >> bar1
1325 $ echo C >> bar2
1326 $ hg ci -m 'add C to bars'
1327 $ hg unshelve -i
1328 unshelving change 'default-01'
1329 rebasing shelved changes
1330 merging bar1
1331 merging bar2
1332 warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark')
1333 warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark')
1334 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1335 [1]
1336
1337 $ cat > bar1 <<EOF
1338 > A
1339 > B
1340 > C
1341 > EOF
1342 $ cat > bar2 <<EOF
1343 > A
1344 > B
1345 > C
1346 > EOF
1347 $ hg resolve -m bar1 bar2
1348 (no more unresolved files)
1349 continue: hg unshelve --continue
1350 $ cat bar1
1351 A
1352 B
1353 C
1354 $ hg unshelve --continue -i <<EOF
1355 > y
1356 > y
1357 > y
1358 > y
1359 > EOF
1360 unshelving change 'default-01'
1361 diff --git a/bar1 b/bar1
1362 1 hunks, 1 lines changed
1363 examine changes to 'bar1'?
1364 (enter ? for help) [Ynesfdaq?] y
1365
1366 @@ -1,2 +1,3 @@
1367 A
1368 +B
1369 C
1370 record change 1/2 to 'bar1'?
1371 (enter ? for help) [Ynesfdaq?] y
1372
1373 diff --git a/bar2 b/bar2
1374 1 hunks, 1 lines changed
1375 examine changes to 'bar2'?
1376 (enter ? for help) [Ynesfdaq?] y
1377
1378 @@ -1,2 +1,3 @@
1379 A
1380 +B
1381 C
1382 record change 2/2 to 'bar2'?
1383 (enter ? for help) [Ynesfdaq?] y
1384
1385 unshelve of 'default-01' complete
General Comments 0
You need to be logged in to leave comments. Login now