Show More
@@ -1421,17 +1421,23 b' def copy(ui, repo, pats, opts, rename=Fa' | |||
|
1421 | 1421 | forget = opts.get(b"forget") |
|
1422 | 1422 | after = opts.get(b"after") |
|
1423 | 1423 | dryrun = opts.get(b"dry_run") |
|
1424 | ctx = repo[None] | |
|
1424 | rev = opts.get(b'at_rev') | |
|
1425 | if rev: | |
|
1426 | if not forget and not after: | |
|
1427 | # TODO: Remove this restriction and make it also create the copy | |
|
1428 | # targets (and remove the rename source if rename==True). | |
|
1429 | raise error.Abort(_(b'--at-rev requires --after')) | |
|
1430 | ctx = scmutil.revsingle(repo, rev) | |
|
1431 | if len(ctx.parents()) > 1: | |
|
1432 | raise error.Abort(_(b'cannot mark/unmark copy in merge commit')) | |
|
1433 | else: | |
|
1434 | ctx = repo[None] | |
|
1435 | ||
|
1425 | 1436 | pctx = ctx.p1() |
|
1426 | 1437 | |
|
1427 | 1438 | uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) |
|
1428 | 1439 | |
|
1429 | 1440 | if forget: |
|
1430 | rev = opts[b'at_rev'] | |
|
1431 | if rev: | |
|
1432 | ctx = scmutil.revsingle(repo, rev) | |
|
1433 | else: | |
|
1434 | ctx = repo[None] | |
|
1435 | 1441 | if ctx.rev() is None: |
|
1436 | 1442 | new_ctx = ctx |
|
1437 | 1443 | else: |
@@ -1484,9 +1490,6 b' def copy(ui, repo, pats, opts, rename=Fa' | |||
|
1484 | 1490 | raise error.Abort(_(b'no destination specified')) |
|
1485 | 1491 | dest = pats.pop() |
|
1486 | 1492 | |
|
1487 | if opts.get(b'at_rev'): | |
|
1488 | raise error.Abort(_("--at-rev is only supported with --forget")) | |
|
1489 | ||
|
1490 | 1493 | def walkpat(pat): |
|
1491 | 1494 | srcs = [] |
|
1492 | 1495 | m = scmutil.match(ctx, [pat], opts, globbed=True) |
@@ -1517,6 +1520,55 b' def copy(ui, repo, pats, opts, rename=Fa' | |||
|
1517 | 1520 | srcs.append((abs, rel, exact)) |
|
1518 | 1521 | return srcs |
|
1519 | 1522 | |
|
1523 | if ctx.rev() is not None: | |
|
1524 | rewriteutil.precheck(repo, [ctx.rev()], b'uncopy') | |
|
1525 | absdest = pathutil.canonpath(repo.root, cwd, dest) | |
|
1526 | if ctx.hasdir(absdest): | |
|
1527 | raise error.Abort( | |
|
1528 | _(b'%s: --at-rev does not support a directory as destination') | |
|
1529 | % uipathfn(absdest) | |
|
1530 | ) | |
|
1531 | if absdest not in ctx: | |
|
1532 | raise error.Abort( | |
|
1533 | _(b'%s: copy destination does not exist in %s') | |
|
1534 | % (uipathfn(absdest), ctx) | |
|
1535 | ) | |
|
1536 | ||
|
1537 | # avoid cycle context -> subrepo -> cmdutil | |
|
1538 | from . import context | |
|
1539 | ||
|
1540 | copylist = [] | |
|
1541 | for pat in pats: | |
|
1542 | srcs = walkpat(pat) | |
|
1543 | if not srcs: | |
|
1544 | continue | |
|
1545 | for abs, rel, exact in srcs: | |
|
1546 | copylist.append(abs) | |
|
1547 | ||
|
1548 | # TODO: Add support for `hg cp --at-rev . foo bar dir` and | |
|
1549 | # `hg cp --at-rev . dir1 dir2`, preferably unifying the code with the | |
|
1550 | # existing functions below. | |
|
1551 | if len(copylist) != 1: | |
|
1552 | raise error.Abort(_(b'--at-rev requires a single source')) | |
|
1553 | ||
|
1554 | new_ctx = context.overlayworkingctx(repo) | |
|
1555 | new_ctx.setbase(ctx.p1()) | |
|
1556 | mergemod.graft(repo, ctx, wctx=new_ctx) | |
|
1557 | ||
|
1558 | new_ctx.markcopied(absdest, copylist[0]) | |
|
1559 | ||
|
1560 | with repo.lock(): | |
|
1561 | mem_ctx = new_ctx.tomemctx_for_amend(ctx) | |
|
1562 | new_node = mem_ctx.commit() | |
|
1563 | ||
|
1564 | if repo.dirstate.p1() == ctx.node(): | |
|
1565 | with repo.dirstate.parentchange(): | |
|
1566 | scmutil.movedirstate(repo, repo[new_node]) | |
|
1567 | replacements = {ctx.node(): [new_node]} | |
|
1568 | scmutil.cleanupnodes(repo, replacements, b'copy', fixphase=True) | |
|
1569 | ||
|
1570 | return | |
|
1571 | ||
|
1520 | 1572 | # abssrc: hgsep |
|
1521 | 1573 | # relsrc: ossep |
|
1522 | 1574 | # otarget: ossep |
@@ -2315,7 +2315,7 b' def continuecmd(ui, repo, **opts):' | |||
|
2315 | 2315 | b'', |
|
2316 | 2316 | b'at-rev', |
|
2317 | 2317 | b'', |
|
2318 | _(b'unmark copies in the given revision (EXPERIMENTAL)'), | |
|
2318 | _(b'(un)mark copies in the given revision (EXPERIMENTAL)'), | |
|
2319 | 2319 | _(b'REV'), |
|
2320 | 2320 | ), |
|
2321 | 2321 | ( |
@@ -2345,7 +2345,7 b' def copy(ui, repo, *pats, **opts):' | |||
|
2345 | 2345 | all given (positional) arguments are unmarked as copies. The destination |
|
2346 | 2346 | file(s) will be left in place (still tracked). |
|
2347 | 2347 | |
|
2348 | This command takes effect with the next commit. | |
|
2348 | This command takes effect with the next commit by default. | |
|
2349 | 2349 | |
|
2350 | 2350 | Returns 0 on success, 1 if errors are encountered. |
|
2351 | 2351 | """ |
@@ -14,8 +14,12 b'' | |||
|
14 | 14 | |
|
15 | 15 | * `hg copy --forget` can be used to unmark a file as copied. |
|
16 | 16 | |
|
17 | == New Experimental Features == | |
|
17 | 18 | |
|
18 | == New Experimental Features == | |
|
19 | * `hg copy` now supports a `--at-rev` argument to mark files as | |
|
20 | copied in the specified commit. It only works with `--after` for | |
|
21 | now (i.e., it's only useful for marking files copied using non-hg | |
|
22 | `cp` as copied). | |
|
19 | 23 | |
|
20 | 24 | * Use `hg copy --forget --at-rev REV` to unmark already committed |
|
21 | 25 | copies. |
@@ -120,10 +120,14 b' Commit issue 1476 with a rename on the o' | |||
|
120 | 120 | $ hg log -r tip -C -v | grep copies |
|
121 | 121 | copies: b2 (b1) |
|
122 | 122 | |
|
123 | Test unmarking copies in merge commit | |
|
123 | Test marking/unmarking copies in merge commit | |
|
124 | 124 | |
|
125 | 125 | $ hg copy --forget --at-rev . b2 |
|
126 | abort: cannot unmark copy in merge commit | |
|
126 | abort: cannot mark/unmark copy in merge commit | |
|
127 | [255] | |
|
128 | ||
|
129 | $ hg copy --after --at-rev . b1 b2 | |
|
130 | abort: cannot mark/unmark copy in merge commit | |
|
127 | 131 | [255] |
|
128 | 132 | |
|
129 | 133 | $ cd .. |
This diff has been collapsed as it changes many lines, (718 lines changed) Show them Hide them | |||
@@ -6,693 +6,51 b'' | |||
|
6 | 6 | $ echo d1/b > d1/b |
|
7 | 7 | $ echo d2/b > d2/b |
|
8 | 8 | $ hg add d1/a d1/b d1/ba d1/d11/a1 d2/b |
|
9 |
$ hg commit -m " |
|
|
10 | ||
|
11 | rename a single file | |
|
12 | ||
|
13 | $ hg rename d1/d11/a1 d2/c | |
|
14 | $ hg --config ui.portablefilenames=abort rename d1/a d1/con.xml | |
|
15 | abort: filename contains 'con', which is reserved on Windows: d1/con.xml | |
|
16 | [255] | |
|
17 | $ hg sum | |
|
18 | parent: 0:9b4b6e7b2c26 tip | |
|
19 | 1 | |
|
20 | branch: default | |
|
21 | commit: 1 renamed | |
|
22 | update: (current) | |
|
23 | phases: 1 draft | |
|
24 | $ hg status -C | |
|
25 | A d2/c | |
|
26 | d1/d11/a1 | |
|
27 | R d1/d11/a1 | |
|
28 | $ hg update -C | |
|
29 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
30 | $ rm d2/c | |
|
31 | ||
|
32 | rename a single file using absolute paths | |
|
33 | ||
|
34 | $ hg rename `pwd`/d1/d11/a1 `pwd`/d2/c | |
|
35 | $ hg status -C | |
|
36 | A d2/c | |
|
37 | d1/d11/a1 | |
|
38 | R d1/d11/a1 | |
|
39 | $ hg update -C | |
|
40 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
41 | $ rm d2/c | |
|
9 | $ hg commit -m "intial" | |
|
42 | 10 | |
|
43 | rename --after a single file | |
|
44 | 11 | |
|
45 | $ mv d1/d11/a1 d2/c | |
|
46 | $ hg rename --after d1/d11/a1 d2/c | |
|
47 | $ hg status -C | |
|
48 | A d2/c | |
|
49 | d1/d11/a1 | |
|
50 | R d1/d11/a1 | |
|
51 | $ hg update -C | |
|
52 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
53 | $ rm d2/c | |
|
54 | ||
|
55 | rename --after a single file when src and tgt already tracked | |
|
56 | ||
|
57 | $ mv d1/d11/a1 d2/c | |
|
58 | $ hg addrem -s 0 | |
|
59 | removing d1/d11/a1 | |
|
60 | adding d2/c | |
|
61 | $ hg rename --after d1/d11/a1 d2/c | |
|
62 | $ hg status -C | |
|
63 | A d2/c | |
|
64 | d1/d11/a1 | |
|
65 | R d1/d11/a1 | |
|
66 | $ hg update -C | |
|
67 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
68 | $ rm d2/c | |
|
69 | ||
|
70 | rename --after a single file to a nonexistent target filename | |
|
71 | ||
|
72 | $ hg rename --after d1/a dummy | |
|
73 | d1/a: not recording move - dummy does not exist | |
|
74 | [1] | |
|
75 | ||
|
76 | move a single file to an existing directory | |
|
12 | Test single file | |
|
77 | 13 | |
|
78 | $ hg rename d1/d11/a1 d2 | |
|
79 | $ hg status -C | |
|
80 | A d2/a1 | |
|
81 | d1/d11/a1 | |
|
82 | R d1/d11/a1 | |
|
83 | $ hg update -C | |
|
84 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
85 | $ rm d2/a1 | |
|
86 | ||
|
87 | move --after a single file to an existing directory | |
|
88 | ||
|
89 | $ mv d1/d11/a1 d2 | |
|
90 | $ hg rename --after d1/d11/a1 d2 | |
|
91 | $ hg status -C | |
|
92 | A d2/a1 | |
|
93 | d1/d11/a1 | |
|
94 | R d1/d11/a1 | |
|
95 | $ hg update -C | |
|
96 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
97 | $ rm d2/a1 | |
|
98 | ||
|
99 | rename a file using a relative path | |
|
100 | ||
|
101 | $ (cd d1/d11; hg rename ../../d2/b e) | |
|
102 | $ hg status -C | |
|
103 | A d1/d11/e | |
|
104 | d2/b | |
|
105 | R d2/b | |
|
106 | $ hg update -C | |
|
107 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
108 | $ rm d1/d11/e | |
|
109 | ||
|
110 | rename --after a file using a relative path | |
|
111 | ||
|
112 | $ (cd d1/d11; mv ../../d2/b e; hg rename --after ../../d2/b e) | |
|
113 | $ hg status -C | |
|
114 | A d1/d11/e | |
|
115 | d2/b | |
|
116 | R d2/b | |
|
117 | $ hg update -C | |
|
118 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
119 | $ rm d1/d11/e | |
|
120 | ||
|
121 | rename directory d1 as d3 | |
|
122 | ||
|
123 | $ hg rename d1/ d3 | |
|
124 | moving d1/a to d3/a | |
|
125 | moving d1/b to d3/b | |
|
126 | moving d1/ba to d3/ba | |
|
127 | moving d1/d11/a1 to d3/d11/a1 | |
|
128 | $ hg status -C | |
|
129 | A d3/a | |
|
130 | d1/a | |
|
131 | A d3/b | |
|
132 | d1/b | |
|
133 | A d3/ba | |
|
134 | d1/ba | |
|
135 | A d3/d11/a1 | |
|
136 | d1/d11/a1 | |
|
137 | R d1/a | |
|
138 | R d1/b | |
|
139 | R d1/ba | |
|
140 | R d1/d11/a1 | |
|
141 | $ hg update -C | |
|
142 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
143 | $ rm -rf d3 | |
|
144 | ||
|
145 | rename --after directory d1 as d3 | |
|
146 | ||
|
147 | $ mv d1 d3 | |
|
148 | $ hg rename --after d1 d3 | |
|
149 | moving d1/a to d3/a | |
|
150 | moving d1/b to d3/b | |
|
151 | moving d1/ba to d3/ba | |
|
152 | moving d1/d11/a1 to d3/d11/a1 | |
|
153 | $ hg status -C | |
|
154 | A d3/a | |
|
155 | d1/a | |
|
156 | A d3/b | |
|
14 | # One recoded copy, one copy to record after commit | |
|
15 | $ hg cp d1/b d1/c | |
|
16 | $ cp d1/b d1/d | |
|
17 | $ hg add d1/d | |
|
18 | $ hg ci -m 'copy d1/b to d1/c and d1/d' | |
|
19 | $ hg st -C --change . | |
|
20 | A d1/c | |
|
157 | 21 | d1/b |
|
158 |
A d |
|
|
159 | d1/ba | |
|
160 | A d3/d11/a1 | |
|
161 | d1/d11/a1 | |
|
162 | R d1/a | |
|
163 | R d1/b | |
|
164 | R d1/ba | |
|
165 | R d1/d11/a1 | |
|
166 | $ hg update -C | |
|
167 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
168 | $ rm -rf d3 | |
|
169 | ||
|
170 | move a directory using a relative path | |
|
171 | ||
|
172 | $ (cd d2; mkdir d3; hg rename ../d1/d11 d3) | |
|
173 | moving ../d1/d11/a1 to d3/d11/a1 | |
|
174 | $ hg status -C | |
|
175 | A d2/d3/d11/a1 | |
|
176 | d1/d11/a1 | |
|
177 | R d1/d11/a1 | |
|
178 | $ hg update -C | |
|
179 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
180 | $ rm -rf d2/d3 | |
|
181 | ||
|
182 | move --after a directory using a relative path | |
|
183 | ||
|
184 | $ (cd d2; mkdir d3; mv ../d1/d11 d3; hg rename --after ../d1/d11 d3) | |
|
185 | moving ../d1/d11/a1 to d3/d11/a1 | |
|
186 | $ hg status -C | |
|
187 | A d2/d3/d11/a1 | |
|
188 | d1/d11/a1 | |
|
189 | R d1/d11/a1 | |
|
190 | $ hg update -C | |
|
191 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
192 | $ rm -rf d2/d3 | |
|
193 | ||
|
194 | move directory d1/d11 to an existing directory d2 (removes empty d1) | |
|
195 | ||
|
196 | $ hg rename d1/d11/ d2 | |
|
197 | moving d1/d11/a1 to d2/d11/a1 | |
|
198 | $ hg status -C | |
|
199 | A d2/d11/a1 | |
|
200 | d1/d11/a1 | |
|
201 | R d1/d11/a1 | |
|
202 | $ hg update -C | |
|
203 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
204 | $ rm -rf d2/d11 | |
|
205 | ||
|
206 | move directories d1 and d2 to a new directory d3 | |
|
207 | ||
|
208 | $ mkdir d3 | |
|
209 | $ hg rename d1 d2 d3 | |
|
210 | moving d1/a to d3/d1/a | |
|
211 | moving d1/b to d3/d1/b | |
|
212 | moving d1/ba to d3/d1/ba | |
|
213 | moving d1/d11/a1 to d3/d1/d11/a1 | |
|
214 | moving d2/b to d3/d2/b | |
|
215 | $ hg status -C | |
|
216 | A d3/d1/a | |
|
217 | d1/a | |
|
218 | A d3/d1/b | |
|
22 | A d1/d | |
|
23 | # Errors out without --after for now | |
|
24 | $ hg cp --at-rev . d1/b d1/d | |
|
25 | abort: --at-rev requires --after | |
|
26 | [255] | |
|
27 | # Errors out with non-existent destination | |
|
28 | $ hg cp -A --at-rev . d1/b d1/non-existent | |
|
29 | abort: d1/non-existent: copy destination does not exist in 8a9d70fa20c9 | |
|
30 | [255] | |
|
31 | # Successful invocation | |
|
32 | $ hg cp -A --at-rev . d1/b d1/d | |
|
33 | saved backup bundle to $TESTTMP/.hg/strip-backup/8a9d70fa20c9-973ae357-copy.hg | |
|
34 | # New copy is recorded, and previously recorded copy is also still there | |
|
35 | $ hg st -C --change . | |
|
36 | A d1/c | |
|
219 | 37 | d1/b |
|
220 |
A |
|
|
221 | d1/ba | |
|
222 | A d3/d1/d11/a1 | |
|
223 | d1/d11/a1 | |
|
224 | A d3/d2/b | |
|
225 | d2/b | |
|
226 | R d1/a | |
|
227 | R d1/b | |
|
228 | R d1/ba | |
|
229 | R d1/d11/a1 | |
|
230 | R d2/b | |
|
231 | $ hg update -C | |
|
232 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
233 | $ rm -rf d3 | |
|
234 | ||
|
235 | move --after directories d1 and d2 to a new directory d3 | |
|
236 | ||
|
237 | $ mkdir d3 | |
|
238 | $ mv d1 d2 d3 | |
|
239 | $ hg rename --after d1 d2 d3 | |
|
240 | moving d1/a to d3/d1/a | |
|
241 | moving d1/b to d3/d1/b | |
|
242 | moving d1/ba to d3/d1/ba | |
|
243 | moving d1/d11/a1 to d3/d1/d11/a1 | |
|
244 | moving d2/b to d3/d2/b | |
|
245 | $ hg status -C | |
|
246 | A d3/d1/a | |
|
247 | d1/a | |
|
248 | A d3/d1/b | |
|
38 | A d1/d | |
|
249 | 39 | d1/b |
|
250 | A d3/d1/ba | |
|
251 | d1/ba | |
|
252 | A d3/d1/d11/a1 | |
|
253 | d1/d11/a1 | |
|
254 | A d3/d2/b | |
|
255 | d2/b | |
|
256 | R d1/a | |
|
257 | R d1/b | |
|
258 | R d1/ba | |
|
259 | R d1/d11/a1 | |
|
260 | R d2/b | |
|
261 | $ hg update -C | |
|
262 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
263 | $ rm -rf d3 | |
|
264 | 40 | |
|
265 | move everything under directory d1 to existing directory d2, do not | |
|
266 | overwrite existing files (d2/b) | |
|
41 | Test using directory as destination | |
|
267 | 42 | |
|
268 | $ hg rename d1/* d2 | |
|
269 | d2/b: not overwriting - file already committed | |
|
270 | ('hg rename --force' to replace the file by recording a rename) | |
|
271 | moving d1/d11/a1 to d2/d11/a1 | |
|
272 | [1] | |
|
273 | $ hg status -C | |
|
274 | A d2/a | |
|
275 | d1/a | |
|
276 | A d2/ba | |
|
277 | d1/ba | |
|
278 | A d2/d11/a1 | |
|
279 | d1/d11/a1 | |
|
280 | R d1/a | |
|
281 | R d1/ba | |
|
282 | R d1/d11/a1 | |
|
283 | $ diff -u d1/b d2/b | |
|
284 | --- d1/b * (glob) | |
|
285 | +++ d2/b * (glob) | |
|
286 | @@ * (glob) | |
|
287 | -d1/b | |
|
288 | +d2/b | |
|
289 | [1] | |
|
290 | $ hg update -C | |
|
291 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
292 | $ rm d2/a d2/ba d2/d11/a1 | |
|
293 | ||
|
294 | attempt to move one file into a non-existent directory | |
|
295 | ||
|
296 | $ hg rename d1/a dx/ | |
|
297 | abort: destination dx/ is not a directory | |
|
298 | [255] | |
|
299 | $ hg status -C | |
|
300 | $ hg update -C | |
|
301 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
302 | ||
|
303 | attempt to move potentially more than one file into a non-existent directory | |
|
304 | ||
|
305 | $ hg rename 'glob:d1/**' dx | |
|
306 | abort: with multiple sources, destination must be an existing directory | |
|
43 | $ hg co 0 | |
|
44 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
|
45 | $ cp -R d1 d3 | |
|
46 | $ hg add d3 | |
|
47 | adding d3/a | |
|
48 | adding d3/b | |
|
49 | adding d3/ba | |
|
50 | adding d3/d11/a1 | |
|
51 | $ hg ci -m 'copy d1/ to d3/' | |
|
52 | created new head | |
|
53 | $ hg cp -A --at-rev . d1 d3 | |
|
54 | abort: d3: --at-rev does not support a directory as destination | |
|
307 | 55 | [255] |
|
308 | 56 | |
|
309 | move every file under d1 to d2/d21 | |
|
310 | ||
|
311 | $ mkdir d2/d21 | |
|
312 | $ hg rename 'glob:d1/**' d2/d21 | |
|
313 | moving d1/a to d2/d21/a | |
|
314 | moving d1/b to d2/d21/b | |
|
315 | moving d1/ba to d2/d21/ba | |
|
316 | moving d1/d11/a1 to d2/d21/a1 | |
|
317 | $ hg status -C | |
|
318 | A d2/d21/a | |
|
319 | d1/a | |
|
320 | A d2/d21/a1 | |
|
321 | d1/d11/a1 | |
|
322 | A d2/d21/b | |
|
323 | d1/b | |
|
324 | A d2/d21/ba | |
|
325 | d1/ba | |
|
326 | R d1/a | |
|
327 | R d1/b | |
|
328 | R d1/ba | |
|
329 | R d1/d11/a1 | |
|
330 | $ hg update -C | |
|
331 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
332 | $ rm -rf d2/d21 | |
|
333 | ||
|
334 | move --after some files under d1 to d2/d21 | |
|
335 | ||
|
336 | $ mkdir d2/d21 | |
|
337 | $ mv d1/a d1/d11/a1 d2/d21 | |
|
338 | $ hg rename --after 'glob:d1/**' d2/d21 | |
|
339 | moving d1/a to d2/d21/a | |
|
340 | d1/b: not recording move - d2/d21/b does not exist | |
|
341 | d1/ba: not recording move - d2/d21/ba does not exist | |
|
342 | moving d1/d11/a1 to d2/d21/a1 | |
|
343 | [1] | |
|
344 | $ hg status -C | |
|
345 | A d2/d21/a | |
|
346 | d1/a | |
|
347 | A d2/d21/a1 | |
|
348 | d1/d11/a1 | |
|
349 | R d1/a | |
|
350 | R d1/d11/a1 | |
|
351 | $ hg update -C | |
|
352 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
353 | $ rm -rf d2/d21 | |
|
354 | ||
|
355 | move every file under d1 starting with an 'a' to d2/d21 (regexp) | |
|
356 | ||
|
357 | $ mkdir d2/d21 | |
|
358 | $ hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21 | |
|
359 | moving d1/a to d2/d21/a | |
|
360 | moving d1/d11/a1 to d2/d21/a1 | |
|
361 | $ hg status -C | |
|
362 | A d2/d21/a | |
|
363 | d1/a | |
|
364 | A d2/d21/a1 | |
|
365 | d1/d11/a1 | |
|
366 | R d1/a | |
|
367 | R d1/d11/a1 | |
|
368 | $ hg update -C | |
|
369 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
370 | $ rm -rf d2/d21 | |
|
371 | ||
|
372 | attempt to overwrite an existing file | |
|
373 | ||
|
374 | $ echo "ca" > d1/ca | |
|
375 | $ hg rename d1/ba d1/ca | |
|
376 | d1/ca: not overwriting - file exists | |
|
377 | ('hg rename --after' to record the rename) | |
|
378 | [1] | |
|
379 | $ hg status -C | |
|
380 | ? d1/ca | |
|
381 | $ hg update -C | |
|
382 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
383 | ||
|
384 | forced overwrite of an existing file | |
|
385 | ||
|
386 | $ echo "ca" > d1/ca | |
|
387 | $ hg rename --force d1/ba d1/ca | |
|
388 | $ hg status -C | |
|
389 | A d1/ca | |
|
390 | d1/ba | |
|
391 | R d1/ba | |
|
392 | $ hg update -C | |
|
393 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
394 | $ rm d1/ca | |
|
395 | ||
|
396 | attempt to overwrite an existing broken symlink | |
|
397 | ||
|
398 | #if symlink | |
|
399 | $ ln -s ba d1/ca | |
|
400 | $ hg rename --traceback d1/ba d1/ca | |
|
401 | d1/ca: not overwriting - file exists | |
|
402 | ('hg rename --after' to record the rename) | |
|
403 | [1] | |
|
404 | $ hg status -C | |
|
405 | ? d1/ca | |
|
406 | $ hg update -C | |
|
407 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
408 | $ rm d1/ca | |
|
409 | ||
|
410 | replace a symlink with a file | |
|
411 | ||
|
412 | $ ln -s ba d1/ca | |
|
413 | $ hg rename --force d1/ba d1/ca | |
|
414 | $ hg status -C | |
|
415 | A d1/ca | |
|
416 | d1/ba | |
|
417 | R d1/ba | |
|
418 | $ hg update -C | |
|
419 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
420 | $ rm d1/ca | |
|
421 | #endif | |
|
422 | ||
|
423 | do not copy more than one source file to the same destination file | |
|
424 | ||
|
425 | $ mkdir d3 | |
|
426 | $ hg rename d1/* d2/* d3 | |
|
427 | moving d1/d11/a1 to d3/d11/a1 | |
|
428 | d3/b: not overwriting - d2/b collides with d1/b | |
|
429 | [1] | |
|
430 | $ hg status -C | |
|
431 | A d3/a | |
|
432 | d1/a | |
|
433 | A d3/b | |
|
434 | d1/b | |
|
435 | A d3/ba | |
|
436 | d1/ba | |
|
437 | A d3/d11/a1 | |
|
438 | d1/d11/a1 | |
|
439 | R d1/a | |
|
440 | R d1/b | |
|
441 | R d1/ba | |
|
442 | R d1/d11/a1 | |
|
443 | $ hg update -C | |
|
444 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
445 | $ rm -rf d3 | |
|
446 | ||
|
447 | move a whole subtree with "hg rename ." | |
|
448 | ||
|
449 | $ mkdir d3 | |
|
450 | $ (cd d1; hg rename . ../d3) | |
|
451 | moving a to ../d3/d1/a | |
|
452 | moving b to ../d3/d1/b | |
|
453 | moving ba to ../d3/d1/ba | |
|
454 | moving d11/a1 to ../d3/d1/d11/a1 | |
|
455 | $ hg status -C | |
|
456 | A d3/d1/a | |
|
457 | d1/a | |
|
458 | A d3/d1/b | |
|
459 | d1/b | |
|
460 | A d3/d1/ba | |
|
461 | d1/ba | |
|
462 | A d3/d1/d11/a1 | |
|
463 | d1/d11/a1 | |
|
464 | R d1/a | |
|
465 | R d1/b | |
|
466 | R d1/ba | |
|
467 | R d1/d11/a1 | |
|
468 | $ hg update -C | |
|
469 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
470 | $ rm -rf d3 | |
|
471 | ||
|
472 | move a whole subtree with "hg rename --after ." | |
|
473 | ||
|
474 | $ mkdir d3 | |
|
475 | $ mv d1/* d3 | |
|
476 | $ (cd d1; hg rename --after . ../d3) | |
|
477 | moving a to ../d3/a | |
|
478 | moving b to ../d3/b | |
|
479 | moving ba to ../d3/ba | |
|
480 | moving d11/a1 to ../d3/d11/a1 | |
|
481 | $ hg status -C | |
|
482 | A d3/a | |
|
483 | d1/a | |
|
484 | A d3/b | |
|
485 | d1/b | |
|
486 | A d3/ba | |
|
487 | d1/ba | |
|
488 | A d3/d11/a1 | |
|
489 | d1/d11/a1 | |
|
490 | R d1/a | |
|
491 | R d1/b | |
|
492 | R d1/ba | |
|
493 | R d1/d11/a1 | |
|
494 | $ hg update -C | |
|
495 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
496 | $ rm -rf d3 | |
|
497 | ||
|
498 | move the parent tree with "hg rename .." | |
|
499 | ||
|
500 | $ (cd d1/d11; hg rename .. ../../d3) | |
|
501 | moving ../a to ../../d3/a | |
|
502 | moving ../b to ../../d3/b | |
|
503 | moving ../ba to ../../d3/ba | |
|
504 | moving a1 to ../../d3/d11/a1 | |
|
505 | $ hg status -C | |
|
506 | A d3/a | |
|
507 | d1/a | |
|
508 | A d3/b | |
|
509 | d1/b | |
|
510 | A d3/ba | |
|
511 | d1/ba | |
|
512 | A d3/d11/a1 | |
|
513 | d1/d11/a1 | |
|
514 | R d1/a | |
|
515 | R d1/b | |
|
516 | R d1/ba | |
|
517 | R d1/d11/a1 | |
|
518 | $ hg update -C | |
|
519 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
520 | $ rm -rf d3 | |
|
521 | ||
|
522 | skip removed files | |
|
523 | ||
|
524 | $ hg remove d1/b | |
|
525 | $ hg rename d1 d3 | |
|
526 | moving d1/a to d3/a | |
|
527 | moving d1/ba to d3/ba | |
|
528 | moving d1/d11/a1 to d3/d11/a1 | |
|
529 | $ hg status -C | |
|
530 | A d3/a | |
|
531 | d1/a | |
|
532 | A d3/ba | |
|
533 | d1/ba | |
|
534 | A d3/d11/a1 | |
|
535 | d1/d11/a1 | |
|
536 | R d1/a | |
|
537 | R d1/b | |
|
538 | R d1/ba | |
|
539 | R d1/d11/a1 | |
|
540 | $ hg update -C | |
|
541 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
542 | $ rm -rf d3 | |
|
543 | ||
|
544 | transitive rename | |
|
545 | ||
|
546 | $ hg rename d1/b d1/bb | |
|
547 | $ hg rename d1/bb d1/bc | |
|
548 | $ hg status -C | |
|
549 | A d1/bc | |
|
550 | d1/b | |
|
551 | R d1/b | |
|
552 | $ hg update -C | |
|
553 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
554 | $ rm d1/bc | |
|
555 | ||
|
556 | transitive rename --after | |
|
557 | ||
|
558 | $ hg rename d1/b d1/bb | |
|
559 | $ mv d1/bb d1/bc | |
|
560 | $ hg rename --after d1/bb d1/bc | |
|
561 | $ hg status -C | |
|
562 | A d1/bc | |
|
563 | d1/b | |
|
564 | R d1/b | |
|
565 | $ hg update -C | |
|
566 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
567 | $ rm d1/bc | |
|
568 | ||
|
569 | $ echo "# idempotent renames (d1/b -> d1/bb followed by d1/bb -> d1/b)" | |
|
570 | # idempotent renames (d1/b -> d1/bb followed by d1/bb -> d1/b) | |
|
571 | $ hg rename d1/b d1/bb | |
|
572 | $ echo "some stuff added to d1/bb" >> d1/bb | |
|
573 | $ hg rename d1/bb d1/b | |
|
574 | $ hg status -C | |
|
575 | M d1/b | |
|
576 | $ hg update -C | |
|
577 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
578 | ||
|
579 | overwriting with renames (issue1959) | |
|
580 | ||
|
581 | $ hg rename d1/a d1/c | |
|
582 | $ hg rename d1/b d1/a | |
|
583 | $ hg status -C | |
|
584 | M d1/a | |
|
585 | d1/b | |
|
586 | A d1/c | |
|
587 | d1/a | |
|
588 | R d1/b | |
|
589 | $ hg diff --git | |
|
590 | diff --git a/d1/a b/d1/a | |
|
591 | --- a/d1/a | |
|
592 | +++ b/d1/a | |
|
593 | @@ -1,1 +1,1 @@ | |
|
594 | -d1/a | |
|
595 | +d1/b | |
|
596 | diff --git a/d1/b b/d1/b | |
|
597 | deleted file mode 100644 | |
|
598 | --- a/d1/b | |
|
599 | +++ /dev/null | |
|
600 | @@ -1,1 +0,0 @@ | |
|
601 | -d1/b | |
|
602 | diff --git a/d1/a b/d1/c | |
|
603 | copy from d1/a | |
|
604 | copy to d1/c | |
|
605 | $ hg update -C | |
|
606 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
607 | $ rm d1/c # The file was marked as added, so 'hg update' action was 'forget' | |
|
608 | ||
|
609 | check illegal path components | |
|
610 | ||
|
611 | $ hg rename d1/d11/a1 .hg/foo | |
|
612 | abort: path contains illegal component: .hg/foo | |
|
613 | [255] | |
|
614 | $ hg status -C | |
|
615 | $ hg rename d1/d11/a1 ../foo | |
|
616 | abort: ../foo not under root '$TESTTMP' | |
|
617 | [255] | |
|
618 | $ hg status -C | |
|
619 | ||
|
620 | $ mv d1/d11/a1 .hg/foo | |
|
621 | $ hg rename --after d1/d11/a1 .hg/foo | |
|
622 | abort: path contains illegal component: .hg/foo | |
|
623 | [255] | |
|
624 | $ hg status -C | |
|
625 | ! d1/d11/a1 | |
|
626 | $ hg update -C | |
|
627 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
628 | $ rm .hg/foo | |
|
629 | ||
|
630 | $ hg rename d1/d11/a1 .hg | |
|
631 | abort: path contains illegal component: .hg/a1 | |
|
632 | [255] | |
|
633 | $ hg --config extensions.largefiles= rename d1/d11/a1 .hg | |
|
634 | The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) | |
|
635 | abort: path contains illegal component: .hg/a1 | |
|
636 | [255] | |
|
637 | $ hg status -C | |
|
638 | $ hg rename d1/d11/a1 .. | |
|
639 | abort: ../a1 not under root '$TESTTMP' | |
|
640 | [255] | |
|
641 | $ hg --config extensions.largefiles= rename d1/d11/a1 .. | |
|
642 | The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) | |
|
643 | abort: ../a1 not under root '$TESTTMP' | |
|
644 | [255] | |
|
645 | $ hg status -C | |
|
646 | ||
|
647 | $ mv d1/d11/a1 .hg | |
|
648 | $ hg rename --after d1/d11/a1 .hg | |
|
649 | abort: path contains illegal component: .hg/a1 | |
|
650 | [255] | |
|
651 | $ hg status -C | |
|
652 | ! d1/d11/a1 | |
|
653 | $ hg update -C | |
|
654 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
655 | $ rm .hg/a1 | |
|
656 | ||
|
657 | $ (cd d1/d11; hg rename ../../d2/b ../../.hg/foo) | |
|
658 | abort: path contains illegal component: .hg/foo | |
|
659 | [255] | |
|
660 | $ hg status -C | |
|
661 | $ (cd d1/d11; hg rename ../../d2/b ../../../foo) | |
|
662 | abort: ../../../foo not under root '$TESTTMP' | |
|
663 | [255] | |
|
664 | $ hg status -C | |
|
665 | ||
|
666 | check that stat information such as mtime is preserved on rename - it's unclear | |
|
667 | whether the `touch` and `stat` commands are portable, so we mimic them using | |
|
668 | python. Not all platforms support precision of even one-second granularity, so | |
|
669 | we allow a rather generous fudge factor here; 1234567890 is 2009, and the | |
|
670 | primary thing we care about is that it's not the machine's current time; | |
|
671 | hopefully it's really unlikely for a machine to have such a broken clock that | |
|
672 | this test fails. :) | |
|
673 | ||
|
674 | $ mkdir mtime | |
|
675 | Create the file (as empty), then update its mtime and atime to be 1234567890. | |
|
676 | >>> import os | |
|
677 | >>> filename = "mtime/f" | |
|
678 | >>> mtime = 1234567890 | |
|
679 | >>> open(filename, "w").close() | |
|
680 | >>> os.utime(filename, (mtime, mtime)) | |
|
681 | $ hg ci -qAm 'add mtime dir' | |
|
682 | "hg cp" does not preserve the mtime, so it should be newer than the 2009 | |
|
683 | timestamp. | |
|
684 | $ hg cp -q mtime mtime_cp | |
|
685 | >>> from __future__ import print_function | |
|
686 | >>> import os | |
|
687 | >>> filename = "mtime_cp/f" | |
|
688 | >>> print(os.stat(filename).st_mtime < 1234567999) | |
|
689 | False | |
|
690 | "hg mv" preserves the mtime, so it should be ~equal to the 2009 timestamp | |
|
691 | (modulo some fudge factor due to not every system supporting 1s-level | |
|
692 | precision). | |
|
693 | $ hg mv -q mtime mtime_mv | |
|
694 | >>> from __future__ import print_function | |
|
695 | >>> import os | |
|
696 | >>> filename = "mtime_mv/f" | |
|
697 | >>> print(os.stat(filename).st_mtime < 1234567999) | |
|
698 | True |
General Comments 0
You need to be logged in to leave comments.
Login now