Show More
@@ -11,7 +11,14 from typing import ( | |||
|
11 | 11 | |
|
12 | 12 | from ..i18n import _ |
|
13 | 13 | |
|
14 | from .. import cmdutil, error, logcmdutil, merge as mergemod, state as statemod | |
|
14 | from .. import ( | |
|
15 | cmdutil, | |
|
16 | context, | |
|
17 | error, | |
|
18 | logcmdutil, | |
|
19 | merge as mergemod, | |
|
20 | state as statemod, | |
|
21 | ) | |
|
15 | 22 | |
|
16 | 23 | |
|
17 | 24 | if typing.TYPE_CHECKING: |
@@ -33,8 +40,11 def cmd_graft(ui, repo, *revs, **opts) - | |||
|
33 | 40 | return _stopgraft(ui, repo, graftstate) |
|
34 | 41 | elif action == "GRAFT": |
|
35 | 42 | return _graft_revisions(ui, repo, graftstate, *args) |
|
43 | elif action == "GRAFT-TO": | |
|
44 | return _graft_revisions_in_memory(ui, repo, graftstate, *args) | |
|
36 | 45 | else: |
|
37 |
|
|
|
46 | msg = b'unknown action: %s' % action.encode('ascii') | |
|
47 | raise error.ProgrammingError(msg) | |
|
38 | 48 | |
|
39 | 49 | |
|
40 | 50 | def _process_args( |
@@ -61,11 +71,20 def _process_args( | |||
|
61 | 71 | statedata[b'newnodes'] = [] |
|
62 | 72 | |
|
63 | 73 | # argument incompatible with followup from an interrupted operation |
|
64 | commit_args = ['edit', 'log', 'user', 'date', 'currentdate', 'currentuser'] | |
|
74 | commit_args = [ | |
|
75 | 'edit', | |
|
76 | 'log', | |
|
77 | 'user', | |
|
78 | 'date', | |
|
79 | 'currentdate', | |
|
80 | 'currentuser', | |
|
81 | 'to', | |
|
82 | ] | |
|
65 | 83 | nofollow_args = commit_args + ['base', 'rev'] |
|
66 | 84 | |
|
67 | 85 | arg_compatibilities = [ |
|
68 | 86 | ('no_commit', commit_args), |
|
87 | ('continue', ['to']), | |
|
69 | 88 | ('stop', nofollow_args), |
|
70 | 89 | ('abort', nofollow_args), |
|
71 | 90 | ] |
@@ -79,6 +98,12 def _process_args( | |||
|
79 | 98 | |
|
80 | 99 | graftstate = statemod.cmdstate(repo, b'graftstate') |
|
81 | 100 | |
|
101 | if opts.get('to'): | |
|
102 | toctx = logcmdutil.revsingle(repo, opts['to'], None) | |
|
103 | statedata[b'to'] = toctx.hex() | |
|
104 | else: | |
|
105 | toctx = repo[None].p1() | |
|
106 | ||
|
82 | 107 | if opts.get('stop'): |
|
83 | 108 | return "STOP", graftstate, None |
|
84 | 109 | elif opts.get('abort'): |
@@ -102,7 +127,8 def _process_args( | |||
|
102 | 127 | raise error.InputError(_(b'no revisions specified')) |
|
103 | 128 | else: |
|
104 | 129 | cmdutil.checkunfinished(repo) |
|
105 | cmdutil.bailifchanged(repo) | |
|
130 | if not opts.get('to'): | |
|
131 | cmdutil.bailifchanged(repo) | |
|
106 | 132 | revs = logcmdutil.revrange(repo, revs) |
|
107 | 133 | |
|
108 | 134 | for o in ( |
@@ -142,7 +168,7 def _process_args( | |||
|
142 | 168 | # already, they'd have been in the graftstate. |
|
143 | 169 | if not (cont or opts.get('force')) and basectx is None: |
|
144 | 170 | # check for ancestors of dest branch |
|
145 |
ancestors = repo.revs(b'%ld & (:: |
|
|
171 | ancestors = repo.revs(b'%ld & (::%d)', revs, toctx.rev()) | |
|
146 | 172 | for rev in ancestors: |
|
147 | 173 | ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev])) |
|
148 | 174 | |
@@ -164,7 +190,7 def _process_args( | |||
|
164 | 190 | |
|
165 | 191 | # The only changesets we can be sure doesn't contain grafts of any |
|
166 | 192 | # revs, are the ones that are common ancestors of *all* revs: |
|
167 |
for rev in repo.revs(b'only(%d,ancestor(%ld))', |
|
|
193 | for rev in repo.revs(b'only(%d,ancestor(%ld))', toctx.rev(), revs): | |
|
168 | 194 | ctx = repo[rev] |
|
169 | 195 | n = ctx.extra().get(b'source') |
|
170 | 196 | if n in ids: |
@@ -216,6 +242,8 def _process_args( | |||
|
216 | 242 | editor = cmdutil.getcommiteditor(editform=b'graft', **opts) |
|
217 | 243 | dry_run = bool(opts.get("dry_run")) |
|
218 | 244 | tool = opts.get('tool', b'') |
|
245 | if opts.get("to"): | |
|
246 | return "GRAFT-TO", graftstate, (statedata, revs, editor, dry_run, tool) | |
|
219 | 247 | return "GRAFT", graftstate, (statedata, revs, editor, cont, dry_run, tool) |
|
220 | 248 | |
|
221 | 249 | |
@@ -247,6 +275,65 def _build_meta(ui, repo, ctx, statedata | |||
|
247 | 275 | return (user, date, message, extra) |
|
248 | 276 | |
|
249 | 277 | |
|
278 | def _graft_revisions_in_memory( | |
|
279 | ui, | |
|
280 | repo, | |
|
281 | graftstate, | |
|
282 | statedata, | |
|
283 | revs, | |
|
284 | editor, | |
|
285 | dry_run, | |
|
286 | tool=b'', | |
|
287 | ): | |
|
288 | """graft revisions in memory | |
|
289 | ||
|
290 | Abort on unresolved conflicts. | |
|
291 | """ | |
|
292 | with repo.lock(), repo.transaction(b"graft"): | |
|
293 | target = repo[statedata[b"to"]] | |
|
294 | for r in revs: | |
|
295 | ctx = repo[r] | |
|
296 | ui.status(_build_progress(ui, repo, ctx)) | |
|
297 | if dry_run: | |
|
298 | # we might want to actually perform the grafting to detect | |
|
299 | # potential conflict in the dry run. | |
|
300 | continue | |
|
301 | wctx = context.overlayworkingctx(repo) | |
|
302 | wctx.setbase(target) | |
|
303 | if b'base' in statedata: | |
|
304 | base = repo[statedata[b'base']] | |
|
305 | else: | |
|
306 | base = ctx.p1() | |
|
307 | ||
|
308 | (user, date, message, extra) = _build_meta(ui, repo, ctx, statedata) | |
|
309 | ||
|
310 | # perform the graft merge with p1(rev) as 'ancestor' | |
|
311 | try: | |
|
312 | overrides = {(b'ui', b'forcemerge'): tool} | |
|
313 | with ui.configoverride(overrides, b'graft'): | |
|
314 | mergemod.graft( | |
|
315 | repo, | |
|
316 | ctx, | |
|
317 | base, | |
|
318 | wctx=wctx, | |
|
319 | ) | |
|
320 | except error.InMemoryMergeConflictsError as e: | |
|
321 | raise error.Abort( | |
|
322 | b'cannot graft in memory: merge conflicts', | |
|
323 | hint=_(bytes(e)), | |
|
324 | ) | |
|
325 | mctx = wctx.tomemctx( | |
|
326 | message, | |
|
327 | user=user, | |
|
328 | date=date, | |
|
329 | extra=extra, | |
|
330 | editor=editor, | |
|
331 | ) | |
|
332 | node = repo.commitctx(mctx) | |
|
333 | target = repo[node] | |
|
334 | return 0 | |
|
335 | ||
|
336 | ||
|
250 | 337 | def _graft_revisions( |
|
251 | 338 | ui, |
|
252 | 339 | repo, |
@@ -2971,6 +2971,12 def forget(ui, repo, *pats, **opts): | |||
|
2971 | 2971 | _(b'base revision when doing the graft merge (ADVANCED)'), |
|
2972 | 2972 | _(b'REV'), |
|
2973 | 2973 | ), |
|
2974 | ( | |
|
2975 | b'', | |
|
2976 | b'to', | |
|
2977 | b'', | |
|
2978 | _(b'graft to this destination, in memory (EXPERIMENTAL)'), | |
|
2979 | ), | |
|
2974 | 2980 | (b'c', b'continue', False, _(b'resume interrupted graft')), |
|
2975 | 2981 | (b'', b'stop', False, _(b'stop interrupted graft')), |
|
2976 | 2982 | (b'', b'abort', False, _(b'abort interrupted graft')), |
@@ -3061,6 +3067,16 def graft(ui, repo, *revs, **opts): | |||
|
3061 | 3067 | |
|
3062 | 3068 | .. container:: verbose |
|
3063 | 3069 | |
|
3070 | The experimental --to option allow to graft a revision in memory, | |
|
3071 | independently from the working copy. Merge conflict are not currenly | |
|
3072 | supported and the operation will be aborted if the configured tool | |
|
3073 | cannot handle the conflict that might be encountered. | |
|
3074 | ||
|
3075 | As the operation is performence in memory, the on disk file will not be | |
|
3076 | modified and some hooks might not be run. | |
|
3077 | ||
|
3078 | .. container:: verbose | |
|
3079 | ||
|
3064 | 3080 | Examples: |
|
3065 | 3081 | |
|
3066 | 3082 | - copy a single change to the stable branch and edit its description:: |
@@ -360,7 +360,7 Show all commands + options | |||
|
360 | 360 | export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template |
|
361 | 361 | files: rev, print0, include, exclude, template, subrepos |
|
362 | 362 | forget: interactive, include, exclude, dry-run |
|
363 | graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run | |
|
363 | graft: rev, base, to, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run | |
|
364 | 364 | grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude |
|
365 | 365 | heads: rev, topo, active, closed, style, template |
|
366 | 366 | help: extension, command, keyword, system |
@@ -882,6 +882,8 Empty graft | |||
|
882 | 882 | grafting 23:72d9c7c75bcc "24" |
|
883 | 883 | note: graft of 23:72d9c7c75bcc created no changes to commit |
|
884 | 884 | |
|
885 | $ pwd | |
|
886 | $TESTTMP/a | |
|
885 | 887 | $ cd .. |
|
886 | 888 | |
|
887 | 889 | Graft to duplicate a commit |
@@ -921,3 +923,329 Graft to duplicate a commit twice | |||
|
921 | 923 | |/ |
|
922 | 924 | o 0 |
|
923 | 925 | |
|
926 | $ cd ../ | |
|
927 | ||
|
928 | In memory graft with --to | |
|
929 | ========================= | |
|
930 | ||
|
931 | ||
|
932 | setup a repository | |
|
933 | ||
|
934 | $ hg init base-to | |
|
935 | $ cd base-to | |
|
936 | $ hg debugbuilddag -m ".:base..:dst*base.:src*base..:wc" | |
|
937 | $ hg up "wc" | |
|
938 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
939 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
940 | @ 7:r7 tip wc | |
|
941 | | | |
|
942 | o 6:r6 | |
|
943 | | | |
|
944 | o 5:r5 | |
|
945 | | | |
|
946 | | o 4:r4 src | |
|
947 | | | | |
|
948 | | o 3:r3 | |
|
949 | |/ | |
|
950 | | o 2:r2 dst | |
|
951 | | | | |
|
952 | | o 1:r1 | |
|
953 | |/ | |
|
954 | o 0:r0 base | |
|
955 | ||
|
956 | ||
|
957 | $ cd .. | |
|
958 | ||
|
959 | Simple test | |
|
960 | ----------- | |
|
961 | ||
|
962 | As few special case as possible | |
|
963 | ||
|
964 | $ cp -R base-to test-to-simple | |
|
965 | $ cd test-to-simple | |
|
966 | $ hg graft --rev src --to dst | |
|
967 | grafting 4:4178b3134f52 "r4" (src) | |
|
968 | merging mf | |
|
969 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
970 | o 8:r4 tip | |
|
971 | | | |
|
972 | | @ 7:r7 wc | |
|
973 | | | | |
|
974 | | o 6:r6 | |
|
975 | | | | |
|
976 | | o 5:r5 | |
|
977 | | | | |
|
978 | | | o 4:r4 src | |
|
979 | | | | | |
|
980 | | | o 3:r3 | |
|
981 | | |/ | |
|
982 | o | 2:r2 dst | |
|
983 | | | | |
|
984 | o | 1:r1 | |
|
985 | |/ | |
|
986 | o 0:r0 base | |
|
987 | ||
|
988 | $ cd .. | |
|
989 | ||
|
990 | Single changeset, local changes | |
|
991 | ------------------------------- | |
|
992 | ||
|
993 | Run "graft --to" with local changes | |
|
994 | ||
|
995 | $ cp -R base-to test-to-local-change | |
|
996 | $ cd test-to-local-change | |
|
997 | $ hg st --all | |
|
998 | C mf | |
|
999 | $ echo foo >> mf | |
|
1000 | $ hg status | |
|
1001 | M mf | |
|
1002 | $ hg graft --rev src --to dst | |
|
1003 | grafting 4:4178b3134f52 "r4" (src) | |
|
1004 | merging mf | |
|
1005 | ||
|
1006 | local file should not have been touched. | |
|
1007 | ||
|
1008 | $ hg status | |
|
1009 | M mf | |
|
1010 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
1011 | o 8:r4 tip | |
|
1012 | | | |
|
1013 | | @ 7:r7 wc | |
|
1014 | | | | |
|
1015 | | o 6:r6 | |
|
1016 | | | | |
|
1017 | | o 5:r5 | |
|
1018 | | | | |
|
1019 | | | o 4:r4 src | |
|
1020 | | | | | |
|
1021 | | | o 3:r3 | |
|
1022 | | |/ | |
|
1023 | o | 2:r2 dst | |
|
1024 | | | | |
|
1025 | o | 1:r1 | |
|
1026 | |/ | |
|
1027 | o 0:r0 base | |
|
1028 | ||
|
1029 | $ cd .. | |
|
1030 | ||
|
1031 | Multiple linear changesets | |
|
1032 | -------------------------- | |
|
1033 | ||
|
1034 | grafting multiple linear changesets | |
|
1035 | ||
|
1036 | $ cp -R base-to test-to-multiple-linear | |
|
1037 | $ cd test-to-multiple-linear | |
|
1038 | $ hg graft --rev 'src~1::src' --to dst | |
|
1039 | grafting 3:181578a106da "r3" | |
|
1040 | merging mf | |
|
1041 | grafting 4:4178b3134f52 "r4" (src) | |
|
1042 | merging mf | |
|
1043 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
1044 | o 9:r4 tip | |
|
1045 | | | |
|
1046 | o 8:r3 | |
|
1047 | | | |
|
1048 | | @ 7:r7 wc | |
|
1049 | | | | |
|
1050 | | o 6:r6 | |
|
1051 | | | | |
|
1052 | | o 5:r5 | |
|
1053 | | | | |
|
1054 | | | o 4:r4 src | |
|
1055 | | | | | |
|
1056 | | | o 3:r3 | |
|
1057 | | |/ | |
|
1058 | o | 2:r2 dst | |
|
1059 | | | | |
|
1060 | o | 1:r1 | |
|
1061 | |/ | |
|
1062 | o 0:r0 base | |
|
1063 | ||
|
1064 | $ cd .. | |
|
1065 | ||
|
1066 | Multiple unrelated changesets | |
|
1067 | -------------------------- | |
|
1068 | ||
|
1069 | Grafting multiple changesets on different branch | |
|
1070 | ||
|
1071 | The order specified on the command line should be preserved. | |
|
1072 | The result should be linear. | |
|
1073 | ||
|
1074 | $ cp -R base-to test-to-multiple-unrelated | |
|
1075 | $ cd test-to-multiple-unrelated | |
|
1076 | $ hg graft 'src' 'wc~1' 'src~1' --to dst | |
|
1077 | grafting 4:4178b3134f52 "r4" (src) | |
|
1078 | merging mf | |
|
1079 | grafting 6:735f0f7a080b "r6" | |
|
1080 | merging mf | |
|
1081 | grafting 3:181578a106da "r3" | |
|
1082 | merging mf | |
|
1083 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
1084 | o 10:r3 tip | |
|
1085 | | | |
|
1086 | o 9:r6 | |
|
1087 | | | |
|
1088 | o 8:r4 | |
|
1089 | | | |
|
1090 | | @ 7:r7 wc | |
|
1091 | | | | |
|
1092 | | o 6:r6 | |
|
1093 | | | | |
|
1094 | | o 5:r5 | |
|
1095 | | | | |
|
1096 | | | o 4:r4 src | |
|
1097 | | | | | |
|
1098 | | | o 3:r3 | |
|
1099 | | |/ | |
|
1100 | o | 2:r2 dst | |
|
1101 | | | | |
|
1102 | o | 1:r1 | |
|
1103 | |/ | |
|
1104 | o 0:r0 base | |
|
1105 | ||
|
1106 | $ cd .. | |
|
1107 | ||
|
1108 | with base | |
|
1109 | --------- | |
|
1110 | ||
|
1111 | $ cp -R base-to test-to-base | |
|
1112 | $ cd test-to-base | |
|
1113 | $ hg graft --base base src --to dst | |
|
1114 | grafting 4:4178b3134f52 "r4" (src) | |
|
1115 | merging mf | |
|
1116 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
1117 | o 8:r4 tip | |
|
1118 | | | |
|
1119 | | @ 7:r7 wc | |
|
1120 | | | | |
|
1121 | | o 6:r6 | |
|
1122 | | | | |
|
1123 | | o 5:r5 | |
|
1124 | | | | |
|
1125 | | | o 4:r4 src | |
|
1126 | | | | | |
|
1127 | | | o 3:r3 | |
|
1128 | | |/ | |
|
1129 | o | 2:r2 dst | |
|
1130 | | | | |
|
1131 | o | 1:r1 | |
|
1132 | |/ | |
|
1133 | o 0:r0 base | |
|
1134 | ||
|
1135 | $ hg diff --from base --to src | |
|
1136 | diff -r 93cbaf5e6529 -r 4178b3134f52 mf | |
|
1137 | --- a/mf Thu Jan 01 00:00:00 1970 +0000 | |
|
1138 | +++ b/mf Thu Jan 01 00:00:04 1970 +0000 | |
|
1139 | @@ -4,9 +4,9 @@ | |
|
1140 | 3 | |
|
1141 | 4 | |
|
1142 | 5 | |
|
1143 | -6 | |
|
1144 | +6 r3 | |
|
1145 | 7 | |
|
1146 | -8 | |
|
1147 | +8 r4 | |
|
1148 | 9 | |
|
1149 | 10 | |
|
1150 | 11 | |
|
1151 | $ hg export src | |
|
1152 | # HG changeset patch | |
|
1153 | # User debugbuilddag | |
|
1154 | # Date 4 0 | |
|
1155 | # Thu Jan 01 00:00:04 1970 +0000 | |
|
1156 | # Node ID 4178b3134f5224d297d3b9e0e98b983f42e53d55 | |
|
1157 | # Parent 181578a106daabea66d4465f4883f7f8552bbc9d | |
|
1158 | r4 | |
|
1159 | ||
|
1160 | diff -r 181578a106da -r 4178b3134f52 mf | |
|
1161 | --- a/mf Thu Jan 01 00:00:03 1970 +0000 | |
|
1162 | +++ b/mf Thu Jan 01 00:00:04 1970 +0000 | |
|
1163 | @@ -6,7 +6,7 @@ | |
|
1164 | 5 | |
|
1165 | 6 r3 | |
|
1166 | 7 | |
|
1167 | -8 | |
|
1168 | +8 r4 | |
|
1169 | 9 | |
|
1170 | 10 | |
|
1171 | 11 | |
|
1172 | $ hg export tip | |
|
1173 | # HG changeset patch | |
|
1174 | # User debugbuilddag | |
|
1175 | # Date 4 0 | |
|
1176 | # Thu Jan 01 00:00:04 1970 +0000 | |
|
1177 | # Node ID 40112ab60ecb01882916c1a4439c798746e34165 | |
|
1178 | # Parent 37d4c1cec295ddfa401f4a365e15a82a1974b056 | |
|
1179 | r4 | |
|
1180 | ||
|
1181 | diff -r 37d4c1cec295 -r 40112ab60ecb mf | |
|
1182 | --- a/mf Thu Jan 01 00:00:02 1970 +0000 | |
|
1183 | +++ b/mf Thu Jan 01 00:00:04 1970 +0000 | |
|
1184 | @@ -4,9 +4,9 @@ | |
|
1185 | 3 | |
|
1186 | 4 r2 | |
|
1187 | 5 | |
|
1188 | -6 | |
|
1189 | +6 r3 | |
|
1190 | 7 | |
|
1191 | -8 | |
|
1192 | +8 r4 | |
|
1193 | 9 | |
|
1194 | 10 | |
|
1195 | 11 | |
|
1196 | $ cd .. | |
|
1197 | ||
|
1198 | with conflict | |
|
1199 | ------------- | |
|
1200 | ||
|
1201 | We should abort in case of conflict and rollback any grafted procress | |
|
1202 | ||
|
1203 | $ cp -R base-to test-to-conflict | |
|
1204 | $ cd test-to-conflict | |
|
1205 | $ hg up src | |
|
1206 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
1207 | $ echo this-will-conflict >> mf | |
|
1208 | $ hg ci -m 'this-will-conflict' | |
|
1209 | $ hg up dst | |
|
1210 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
1211 | $ echo conflict-this-will-conflict >> mf | |
|
1212 | $ hg ci -m 'conflict-this-will' | |
|
1213 | $ hg up wc | |
|
1214 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
1215 | $ hg graft --to 'max(dst::)' src:: --dry-run | |
|
1216 | grafting 4:4178b3134f52 "r4" (src) | |
|
1217 | grafting 8:9fa2d3fe2323 "this-will-conflict" | |
|
1218 | $ hg graft --to 'max(dst::)' src:: | |
|
1219 | grafting 4:4178b3134f52 "r4" (src) | |
|
1220 | merging mf | |
|
1221 | grafting 8:9fa2d3fe2323 "this-will-conflict" | |
|
1222 | merging mf | |
|
1223 | transaction abort! | |
|
1224 | rollback completed | |
|
1225 | abort: cannot graft in memory: merge conflicts | |
|
1226 | (in-memory merge does not support merge conflicts) | |
|
1227 | [255] | |
|
1228 | $ hg log -G -T '{rev}:{desc} {tags}\n' | |
|
1229 | o 9:conflict-this-will tip | |
|
1230 | | | |
|
1231 | | o 8:this-will-conflict | |
|
1232 | | | | |
|
1233 | | | @ 7:r7 wc | |
|
1234 | | | | | |
|
1235 | | | o 6:r6 | |
|
1236 | | | | | |
|
1237 | | | o 5:r5 | |
|
1238 | | | | | |
|
1239 | | o | 4:r4 src | |
|
1240 | | | | | |
|
1241 | | o | 3:r3 | |
|
1242 | | |/ | |
|
1243 | o | 2:r2 dst | |
|
1244 | | | | |
|
1245 | o | 1:r1 | |
|
1246 | |/ | |
|
1247 | o 0:r0 base | |
|
1248 | ||
|
1249 | $ cd .. | |
|
1250 | ||
|
1251 |
General Comments 0
You need to be logged in to leave comments.
Login now