Show More
@@ -821,16 +821,18 b' def docopy(ui, repo, pats, opts):' | |||
|
821 | 821 | ui.warn(_('%s: not overwriting - %s collides with %s\n') % |
|
822 | 822 | (reltarget, abssrc, prevsrc)) |
|
823 | 823 | return |
|
824 |
|
|
|
825 | if opts['force']: | |
|
826 | os.unlink(reltarget) | |
|
827 | else: | |
|
824 | if (not opts['after'] and os.path.exists(reltarget) or | |
|
825 | opts['after'] and repo.dirstate.state(abstarget) not in '?r'): | |
|
826 | if not opts['force']: | |
|
828 | 827 | ui.warn(_('%s: not overwriting - file exists\n') % |
|
829 | 828 | reltarget) |
|
830 | 829 | return |
|
831 | if ui.verbose or not exact: | |
|
832 | ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) | |
|
833 |
if |
|
|
830 | if not opts['after']: | |
|
831 | os.unlink(reltarget) | |
|
832 | if opts['after']: | |
|
833 | if not os.path.exists(reltarget): | |
|
834 | return | |
|
835 | else: | |
|
834 | 836 | targetdir = os.path.dirname(reltarget) or '.' |
|
835 | 837 | if not os.path.isdir(targetdir): |
|
836 | 838 | os.makedirs(targetdir) |
@@ -847,10 +849,64 b' def docopy(ui, repo, pats, opts):' | |||
|
847 | 849 | (relsrc, inst.strerror)) |
|
848 | 850 | errors += 1 |
|
849 | 851 | return |
|
852 | if ui.verbose or not exact: | |
|
853 | ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) | |
|
850 | 854 | targets[abstarget] = abssrc |
|
851 | 855 | repo.copy(abssrc, abstarget) |
|
852 | 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 | 910 | pats = list(pats) |
|
855 | 911 | if not pats: |
|
856 | 912 | raise util.Abort(_('no source or destination specified')) |
@@ -858,31 +914,31 b' def docopy(ui, repo, pats, opts):' | |||
|
858 | 914 | raise util.Abort(_('no destination specified')) |
|
859 | 915 | dest = pats.pop() |
|
860 | 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 | 918 | raise util.Abort(_('with multiple sources, destination must be an ' |
|
863 | 919 | 'existing directory')) |
|
864 | ||
|
920 | if opts['after']: | |
|
921 | tfn = targetpathafterfn | |
|
922 | else: | |
|
923 | tfn = targetpathfn | |
|
924 | copylist = [] | |
|
865 | 925 | for pat in pats: |
|
866 | if os.path.isdir(pat): | |
|
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 | |
|
926 | srcs = [] | |
|
878 | 927 | for tag, abssrc, relsrc, exact in walk(repo, [pat], opts): |
|
879 | 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 | 940 | if errors: |
|
883 | 941 | ui.warn(_('(consider using --after)\n')) |
|
884 | if len(copied) == 0: | |
|
885 | raise util.Abort(_('no files to copy')) | |
|
886 | 942 | return errors, copied |
|
887 | 943 | |
|
888 | 944 | def copy(ui, repo, *pats, **opts): |
@@ -15,18 +15,56 b' hg rename d1/d11/a1 d2/c' | |||
|
15 | 15 | hg status |
|
16 | 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 | 24 | echo "# move a single file to an existing directory" |
|
19 | 25 | hg rename d1/d11/a1 d2 |
|
20 | 26 | hg status |
|
21 | 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 | 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 | 63 | hg status |
|
26 | 64 | hg update -C |
|
27 | 65 | |
|
28 | 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 | 68 | hg status |
|
31 | 69 | hg update -C |
|
32 | 70 | |
@@ -36,6 +74,13 b' hg rename d1 d2 d3' | |||
|
36 | 74 | hg status |
|
37 | 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 | 84 | echo "# move everything under directory d1 to existing directory d2, do not" |
|
40 | 85 | echo "# overwrite existing files (d2/b)" |
|
41 | 86 | hg rename d1/* d2 |
@@ -53,6 +98,13 b" hg rename 'glob:d1/**' d2/d21" | |||
|
53 | 98 | hg status |
|
54 | 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 | 108 | echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)" |
|
57 | 109 | mkdir d2/d21 |
|
58 | 110 | hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21 |
@@ -1,9 +1,21 b'' | |||
|
1 | 1 | # rename a single file |
|
2 | 2 | A d2/c |
|
3 | 3 | R d1/d11/a1 |
|
4 | # rename --after a single file | |
|
5 | A d2/c | |
|
6 | R d1/d11/a1 | |
|
4 | 7 | # move a single file to an existing directory |
|
5 | 8 | A d2/a1 |
|
6 | 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 | 19 | # rename directory d1 as d3 |
|
8 | 20 | copying d1/a to d3/a |
|
9 | 21 | copying d1/b to d3/b |
@@ -21,6 +33,33 b' R d1/a' | |||
|
21 | 33 | R d1/b |
|
22 | 34 | R d1/ba |
|
23 | 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 | 63 | # move directory d1/d11 to an existing directory d2 (removes empty d1) |
|
25 | 64 | copying d1/d11/a1 to d2/d11/a1 |
|
26 | 65 | removing d1/d11/a1 |
@@ -47,6 +86,27 b' R d1/b' | |||
|
47 | 86 | R d1/ba |
|
48 | 87 | R d1/d11/a1 |
|
49 | 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 | 110 | # move everything under directory d1 to existing directory d2, do not |
|
51 | 111 | # overwrite existing files (d2/b) |
|
52 | 112 | d2/b: not overwriting - file exists |
@@ -82,6 +142,15 b' R d1/a' | |||
|
82 | 142 | R d1/b |
|
83 | 143 | R d1/ba |
|
84 | 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 | 154 | # move every file under d1 starting with an 'a' to d2/d21 (regexp) |
|
86 | 155 | copying d1/a to d2/d21/a |
|
87 | 156 | copying d1/d11/a1 to d2/d21/a1 |
@@ -93,7 +162,6 b' R d1/a' | |||
|
93 | 162 | R d1/d11/a1 |
|
94 | 163 | # attempt to overwrite an existing file |
|
95 | 164 | d1/ca: not overwriting - file exists |
|
96 | abort: no files to copy | |
|
97 | 165 | ? d1/ca |
|
98 | 166 | # forced overwrite of an existing file |
|
99 | 167 | A d1/ca |
General Comments 0
You need to be logged in to leave comments.
Login now