##// END OF EJS Templates
fix rename --after
Robin Farine -
r1565:4bcbc126 default
parent child Browse files
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 elif os.path.exists(reltarget):
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 not opts['after']:
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 not os.path.exists(pats[0])) and not destdirexists:
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 copy(abssrc, relsrc, targetpath(abssrc), exact)
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