Show More
@@ -821,16 +821,18 b' def docopy(ui, repo, pats, opts):' | |||||
821 | ui.warn(_('%s: not overwriting - %s collides with %s\n') % |
|
821 | ui.warn(_('%s: not overwriting - %s collides with %s\n') % | |
822 | (reltarget, abssrc, prevsrc)) |
|
822 | (reltarget, abssrc, prevsrc)) | |
823 | return |
|
823 | return | |
824 |
|
|
824 | if (not opts['after'] and os.path.exists(reltarget) or | |
825 | if opts['force']: |
|
825 | opts['after'] and repo.dirstate.state(abstarget) not in '?r'): | |
826 | os.unlink(reltarget) |
|
826 | if not opts['force']: | |
827 | else: |
|
|||
828 | ui.warn(_('%s: not overwriting - file exists\n') % |
|
827 | ui.warn(_('%s: not overwriting - file exists\n') % | |
829 | reltarget) |
|
828 | reltarget) | |
830 | return |
|
829 | return | |
831 | if ui.verbose or not exact: |
|
830 | if not opts['after']: | |
832 | ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) |
|
831 | os.unlink(reltarget) | |
833 |
if |
|
832 | if opts['after']: | |
|
833 | if not os.path.exists(reltarget): | |||
|
834 | return | |||
|
835 | else: | |||
834 | targetdir = os.path.dirname(reltarget) or '.' |
|
836 | targetdir = os.path.dirname(reltarget) or '.' | |
835 | if not os.path.isdir(targetdir): |
|
837 | if not os.path.isdir(targetdir): | |
836 | os.makedirs(targetdir) |
|
838 | os.makedirs(targetdir) | |
@@ -847,10 +849,64 b' def docopy(ui, repo, pats, opts):' | |||||
847 | (relsrc, inst.strerror)) |
|
849 | (relsrc, inst.strerror)) | |
848 | errors += 1 |
|
850 | errors += 1 | |
849 | return |
|
851 | return | |
|
852 | if ui.verbose or not exact: | |||
|
853 | ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) | |||
850 | targets[abstarget] = abssrc |
|
854 | targets[abstarget] = abssrc | |
851 | repo.copy(abssrc, abstarget) |
|
855 | repo.copy(abssrc, abstarget) | |
852 | copied.append((abssrc, relsrc, exact)) |
|
856 | copied.append((abssrc, relsrc, exact)) | |
853 |
|
857 | |||
|
858 | def targetpathfn(pat, dest, srcs): | |||
|
859 | if os.path.isdir(pat): | |||
|
860 | if pat.endswith(os.sep): | |||
|
861 | pat = pat[:-len(os.sep)] | |||
|
862 | if destdirexists: | |||
|
863 | striplen = len(os.path.split(pat)[0]) | |||
|
864 | else: | |||
|
865 | striplen = len(pat) | |||
|
866 | if striplen: | |||
|
867 | striplen += len(os.sep) | |||
|
868 | res = lambda p: os.path.join(dest, p[striplen:]) | |||
|
869 | elif destdirexists: | |||
|
870 | res = lambda p: os.path.join(dest, os.path.basename(p)) | |||
|
871 | else: | |||
|
872 | res = lambda p: dest | |||
|
873 | return res | |||
|
874 | ||||
|
875 | def targetpathafterfn(pat, dest, srcs): | |||
|
876 | if util.patkind(pat, None)[0]: | |||
|
877 | # a mercurial pattern | |||
|
878 | res = lambda p: os.path.join(dest, os.path.basename(p)) | |||
|
879 | elif len(util.canonpath(repo.root, cwd, pat)) < len(srcs[0][0]): | |||
|
880 | # A directory. Either the target path contains the last | |||
|
881 | # component of the source path or it does not. | |||
|
882 | def evalpath(striplen): | |||
|
883 | score = 0 | |||
|
884 | for s in srcs: | |||
|
885 | t = os.path.join(dest, s[1][striplen:]) | |||
|
886 | if os.path.exists(t): | |||
|
887 | score += 1 | |||
|
888 | return score | |||
|
889 | ||||
|
890 | if pat.endswith(os.sep): | |||
|
891 | pat = pat[:-len(os.sep)] | |||
|
892 | striplen = len(pat) + len(os.sep) | |||
|
893 | if os.path.isdir(os.path.join(dest, os.path.split(pat)[1])): | |||
|
894 | score = evalpath(striplen) | |||
|
895 | striplen1 = len(os.path.split(pat)[0]) | |||
|
896 | if striplen1: | |||
|
897 | striplen1 += len(os.sep) | |||
|
898 | if evalpath(striplen1) > score: | |||
|
899 | striplen = striplen1 | |||
|
900 | res = lambda p: os.path.join(dest, p[striplen:]) | |||
|
901 | else: | |||
|
902 | # a file | |||
|
903 | if destdirexists: | |||
|
904 | res = lambda p: os.path.join(dest, os.path.basename(p)) | |||
|
905 | else: | |||
|
906 | res = lambda p: dest | |||
|
907 | return res | |||
|
908 | ||||
|
909 | ||||
854 | pats = list(pats) |
|
910 | pats = list(pats) | |
855 | if not pats: |
|
911 | if not pats: | |
856 | raise util.Abort(_('no source or destination specified')) |
|
912 | raise util.Abort(_('no source or destination specified')) | |
@@ -858,31 +914,31 b' def docopy(ui, repo, pats, opts):' | |||||
858 | raise util.Abort(_('no destination specified')) |
|
914 | raise util.Abort(_('no destination specified')) | |
859 | dest = pats.pop() |
|
915 | dest = pats.pop() | |
860 | destdirexists = os.path.isdir(dest) |
|
916 | destdirexists = os.path.isdir(dest) | |
861 |
if (len(pats) > 1 or |
|
917 | if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists: | |
862 | raise util.Abort(_('with multiple sources, destination must be an ' |
|
918 | raise util.Abort(_('with multiple sources, destination must be an ' | |
863 | 'existing directory')) |
|
919 | 'existing directory')) | |
864 |
|
920 | if opts['after']: | ||
|
921 | tfn = targetpathafterfn | |||
|
922 | else: | |||
|
923 | tfn = targetpathfn | |||
|
924 | copylist = [] | |||
865 | for pat in pats: |
|
925 | for pat in pats: | |
866 | if os.path.isdir(pat): |
|
926 | srcs = [] | |
867 | if destdirexists: |
|
|||
868 | striplen = len(os.path.split(pat)[0]) |
|
|||
869 | else: |
|
|||
870 | striplen = len(pat) |
|
|||
871 | if striplen: |
|
|||
872 | striplen += len(os.sep) |
|
|||
873 | targetpath = lambda p: os.path.join(dest, p[striplen:]) |
|
|||
874 | elif destdirexists: |
|
|||
875 | targetpath = lambda p: os.path.join(dest, os.path.basename(p)) |
|
|||
876 | else: |
|
|||
877 | targetpath = lambda p: dest |
|
|||
878 | for tag, abssrc, relsrc, exact in walk(repo, [pat], opts): |
|
927 | for tag, abssrc, relsrc, exact in walk(repo, [pat], opts): | |
879 | if okaytocopy(abssrc, relsrc, exact): |
|
928 | if okaytocopy(abssrc, relsrc, exact): | |
880 |
|
|
929 | srcs.append((abssrc, relsrc, exact)) | |
|
930 | if not srcs: | |||
|
931 | continue | |||
|
932 | copylist.append((tfn(pat, dest, srcs), srcs)) | |||
|
933 | if not copylist: | |||
|
934 | raise util.Abort(_('no files to copy')) | |||
|
935 | ||||
|
936 | for targetpath, srcs in copylist: | |||
|
937 | for abssrc, relsrc, exact in srcs: | |||
|
938 | copy(abssrc, relsrc, targetpath(relsrc), exact) | |||
881 |
|
939 | |||
882 | if errors: |
|
940 | if errors: | |
883 | ui.warn(_('(consider using --after)\n')) |
|
941 | ui.warn(_('(consider using --after)\n')) | |
884 | if len(copied) == 0: |
|
|||
885 | raise util.Abort(_('no files to copy')) |
|
|||
886 | return errors, copied |
|
942 | return errors, copied | |
887 |
|
943 | |||
888 | def copy(ui, repo, *pats, **opts): |
|
944 | def copy(ui, repo, *pats, **opts): |
@@ -15,18 +15,56 b' hg rename d1/d11/a1 d2/c' | |||||
15 | hg status |
|
15 | hg status | |
16 | hg update -C |
|
16 | hg update -C | |
17 |
|
17 | |||
|
18 | echo "# rename --after a single file" | |||
|
19 | mv d1/d11/a1 d2/c | |||
|
20 | hg rename --after d1/d11/a1 d2/c | |||
|
21 | hg status | |||
|
22 | hg update -C | |||
|
23 | ||||
18 | echo "# move a single file to an existing directory" |
|
24 | echo "# move a single file to an existing directory" | |
19 | hg rename d1/d11/a1 d2 |
|
25 | hg rename d1/d11/a1 d2 | |
20 | hg status |
|
26 | hg status | |
21 | hg update -C |
|
27 | hg update -C | |
22 |
|
28 | |||
|
29 | echo "# move --after a single file to an existing directory" | |||
|
30 | mv d1/d11/a1 d2 | |||
|
31 | hg rename --after d1/d11/a1 d2 | |||
|
32 | hg status | |||
|
33 | hg update -C | |||
|
34 | ||||
|
35 | echo "# rename a file using a relative path" | |||
|
36 | (cd d1/d11; hg rename ../../d2/b e) | |||
|
37 | hg status | |||
|
38 | hg update -C | |||
|
39 | ||||
|
40 | echo "# rename --after a file using a relative path" | |||
|
41 | (cd d1/d11; mv ../../d2/b e; hg rename --after ../../d2/b e) | |||
|
42 | hg status | |||
|
43 | hg update -C | |||
|
44 | ||||
23 | echo "# rename directory d1 as d3" |
|
45 | echo "# rename directory d1 as d3" | |
24 | hg rename d1 d3 |
|
46 | hg rename d1/ d3 | |
|
47 | hg status | |||
|
48 | hg update -C | |||
|
49 | ||||
|
50 | echo "# rename --after directory d1 as d3" | |||
|
51 | mv d1 d3 | |||
|
52 | hg rename --after d1 d3 | |||
|
53 | hg status | |||
|
54 | hg update -C | |||
|
55 | ||||
|
56 | echo "# move a directory using a relative path" | |||
|
57 | (cd d2; mkdir d3; hg rename ../d1/d11 d3) | |||
|
58 | hg status | |||
|
59 | hg update -C | |||
|
60 | ||||
|
61 | echo "# move --after a directory using a relative path" | |||
|
62 | (cd d2; mkdir d3; mv ../d1/d11 d3; hg rename --after ../d1/d11 d3) | |||
25 | hg status |
|
63 | hg status | |
26 | hg update -C |
|
64 | hg update -C | |
27 |
|
65 | |||
28 | echo "# move directory d1/d11 to an existing directory d2 (removes empty d1)" |
|
66 | echo "# move directory d1/d11 to an existing directory d2 (removes empty d1)" | |
29 | hg rename d1/d11 d2 |
|
67 | hg rename d1/d11/ d2 | |
30 | hg status |
|
68 | hg status | |
31 | hg update -C |
|
69 | hg update -C | |
32 |
|
70 | |||
@@ -36,6 +74,13 b' hg rename d1 d2 d3' | |||||
36 | hg status |
|
74 | hg status | |
37 | hg update -C |
|
75 | hg update -C | |
38 |
|
76 | |||
|
77 | echo "# move --after directories d1 and d2 to a new directory d3" | |||
|
78 | mkdir d3 | |||
|
79 | mv d1 d2 d3 | |||
|
80 | hg rename --after d1 d2 d3 | |||
|
81 | hg status | |||
|
82 | hg update -C | |||
|
83 | ||||
39 | echo "# move everything under directory d1 to existing directory d2, do not" |
|
84 | echo "# move everything under directory d1 to existing directory d2, do not" | |
40 | echo "# overwrite existing files (d2/b)" |
|
85 | echo "# overwrite existing files (d2/b)" | |
41 | hg rename d1/* d2 |
|
86 | hg rename d1/* d2 | |
@@ -53,6 +98,13 b" hg rename 'glob:d1/**' d2/d21" | |||||
53 | hg status |
|
98 | hg status | |
54 | hg update -C |
|
99 | hg update -C | |
55 |
|
100 | |||
|
101 | echo "# move --after some files under d1 to d2/d21 (glob)" | |||
|
102 | mkdir d2/d21 | |||
|
103 | mv d1/a d1/d11/a1 d2/d21 | |||
|
104 | hg rename --after 'glob:d1/**' d2/d21 | |||
|
105 | hg status | |||
|
106 | hg update -C | |||
|
107 | ||||
56 | echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)" |
|
108 | echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)" | |
57 | mkdir d2/d21 |
|
109 | mkdir d2/d21 | |
58 | hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21 |
|
110 | hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21 |
@@ -1,9 +1,21 b'' | |||||
1 | # rename a single file |
|
1 | # rename a single file | |
2 | A d2/c |
|
2 | A d2/c | |
3 | R d1/d11/a1 |
|
3 | R d1/d11/a1 | |
|
4 | # rename --after a single file | |||
|
5 | A d2/c | |||
|
6 | R d1/d11/a1 | |||
4 | # move a single file to an existing directory |
|
7 | # move a single file to an existing directory | |
5 | A d2/a1 |
|
8 | A d2/a1 | |
6 | R d1/d11/a1 |
|
9 | R d1/d11/a1 | |
|
10 | # move --after a single file to an existing directory | |||
|
11 | A d2/a1 | |||
|
12 | R d1/d11/a1 | |||
|
13 | # rename a file using a relative path | |||
|
14 | A d1/d11/e | |||
|
15 | R d2/b | |||
|
16 | # rename --after a file using a relative path | |||
|
17 | A d1/d11/e | |||
|
18 | R d2/b | |||
7 | # rename directory d1 as d3 |
|
19 | # rename directory d1 as d3 | |
8 | copying d1/a to d3/a |
|
20 | copying d1/a to d3/a | |
9 | copying d1/b to d3/b |
|
21 | copying d1/b to d3/b | |
@@ -21,6 +33,33 b' R d1/a' | |||||
21 | R d1/b |
|
33 | R d1/b | |
22 | R d1/ba |
|
34 | R d1/ba | |
23 | R d1/d11/a1 |
|
35 | R d1/d11/a1 | |
|
36 | # rename --after directory d1 as d3 | |||
|
37 | copying d1/a to d3/a | |||
|
38 | copying d1/b to d3/b | |||
|
39 | copying d1/ba to d3/ba | |||
|
40 | copying d1/d11/a1 to d3/d11/a1 | |||
|
41 | removing d1/a | |||
|
42 | removing d1/b | |||
|
43 | removing d1/ba | |||
|
44 | removing d1/d11/a1 | |||
|
45 | A d3/a | |||
|
46 | A d3/b | |||
|
47 | A d3/ba | |||
|
48 | A d3/d11/a1 | |||
|
49 | R d1/a | |||
|
50 | R d1/b | |||
|
51 | R d1/ba | |||
|
52 | R d1/d11/a1 | |||
|
53 | # move a directory using a relative path | |||
|
54 | copying ../d1/d11/a1 to d3/d11/a1 | |||
|
55 | removing ../d1/d11/a1 | |||
|
56 | A d2/d3/d11/a1 | |||
|
57 | R d1/d11/a1 | |||
|
58 | # move --after a directory using a relative path | |||
|
59 | copying ../d1/d11/a1 to d3/d11/a1 | |||
|
60 | removing ../d1/d11/a1 | |||
|
61 | A d2/d3/d11/a1 | |||
|
62 | R d1/d11/a1 | |||
24 | # move directory d1/d11 to an existing directory d2 (removes empty d1) |
|
63 | # move directory d1/d11 to an existing directory d2 (removes empty d1) | |
25 | copying d1/d11/a1 to d2/d11/a1 |
|
64 | copying d1/d11/a1 to d2/d11/a1 | |
26 | removing d1/d11/a1 |
|
65 | removing d1/d11/a1 | |
@@ -47,6 +86,27 b' R d1/b' | |||||
47 | R d1/ba |
|
86 | R d1/ba | |
48 | R d1/d11/a1 |
|
87 | R d1/d11/a1 | |
49 | R d2/b |
|
88 | R d2/b | |
|
89 | # move --after directories d1 and d2 to a new directory d3 | |||
|
90 | copying d1/a to d3/d1/a | |||
|
91 | copying d1/b to d3/d1/b | |||
|
92 | copying d1/ba to d3/d1/ba | |||
|
93 | copying d1/d11/a1 to d3/d1/d11/a1 | |||
|
94 | copying d2/b to d3/d2/b | |||
|
95 | removing d1/a | |||
|
96 | removing d1/b | |||
|
97 | removing d1/ba | |||
|
98 | removing d1/d11/a1 | |||
|
99 | removing d2/b | |||
|
100 | A d3/d1/a | |||
|
101 | A d3/d1/b | |||
|
102 | A d3/d1/ba | |||
|
103 | A d3/d1/d11/a1 | |||
|
104 | A d3/d2/b | |||
|
105 | R d1/a | |||
|
106 | R d1/b | |||
|
107 | R d1/ba | |||
|
108 | R d1/d11/a1 | |||
|
109 | R d2/b | |||
50 | # move everything under directory d1 to existing directory d2, do not |
|
110 | # move everything under directory d1 to existing directory d2, do not | |
51 | # overwrite existing files (d2/b) |
|
111 | # overwrite existing files (d2/b) | |
52 | d2/b: not overwriting - file exists |
|
112 | d2/b: not overwriting - file exists | |
@@ -82,6 +142,15 b' R d1/a' | |||||
82 | R d1/b |
|
142 | R d1/b | |
83 | R d1/ba |
|
143 | R d1/ba | |
84 | R d1/d11/a1 |
|
144 | R d1/d11/a1 | |
|
145 | # move --after some files under d1 to d2/d21 (glob) | |||
|
146 | copying d1/a to d2/d21/a | |||
|
147 | copying d1/d11/a1 to d2/d21/a1 | |||
|
148 | removing d1/a | |||
|
149 | removing d1/d11/a1 | |||
|
150 | A d2/d21/a | |||
|
151 | A d2/d21/a1 | |||
|
152 | R d1/a | |||
|
153 | R d1/d11/a1 | |||
85 | # move every file under d1 starting with an 'a' to d2/d21 (regexp) |
|
154 | # move every file under d1 starting with an 'a' to d2/d21 (regexp) | |
86 | copying d1/a to d2/d21/a |
|
155 | copying d1/a to d2/d21/a | |
87 | copying d1/d11/a1 to d2/d21/a1 |
|
156 | copying d1/d11/a1 to d2/d21/a1 | |
@@ -93,7 +162,6 b' R d1/a' | |||||
93 | R d1/d11/a1 |
|
162 | R d1/d11/a1 | |
94 | # attempt to overwrite an existing file |
|
163 | # attempt to overwrite an existing file | |
95 | d1/ca: not overwriting - file exists |
|
164 | d1/ca: not overwriting - file exists | |
96 | abort: no files to copy |
|
|||
97 | ? d1/ca |
|
165 | ? d1/ca | |
98 | # forced overwrite of an existing file |
|
166 | # forced overwrite of an existing file | |
99 | A d1/ca |
|
167 | A d1/ca |
General Comments 0
You need to be logged in to leave comments.
Login now