##// END OF EJS Templates
unlinkpath: make empty directory removal optional (issue5901) (issue5826)...
Kyle Lippincott -
r38512:da2a7d83 @60 default
parent child Browse files
Show More
@@ -0,0 +1,242 b''
1 Tests for experimental.removeemptydirs
2
3 $ NO_RM=--config=experimental.removeemptydirs=0
4 $ isdir() { if [ -d $1 ]; then echo yes; else echo no; fi }
5 $ isfile() { if [ -f $1 ]; then echo yes; else echo no; fi }
6
7 `hg rm` of the last file in a directory:
8 $ hg init hgrm
9 $ cd hgrm
10 $ mkdir somedir
11 $ echo hi > somedir/foo
12 $ hg ci -qAm foo
13 $ isdir somedir
14 yes
15 $ hg rm somedir/foo
16 $ isdir somedir
17 no
18 $ hg revert -qa
19 $ isdir somedir
20 yes
21 $ hg $NO_RM rm somedir/foo
22 $ isdir somedir
23 yes
24 $ ls somedir
25 $ cd $TESTTMP
26
27 `hg mv` of the last file in a directory:
28 $ hg init hgmv
29 $ cd hgmv
30 $ mkdir somedir
31 $ mkdir destdir
32 $ echo hi > somedir/foo
33 $ hg ci -qAm foo
34 $ isdir somedir
35 yes
36 $ hg mv somedir/foo destdir/foo
37 $ isdir somedir
38 no
39 $ hg revert -qa
40 (revert doesn't get rid of destdir/foo?)
41 $ rm destdir/foo
42 $ isdir somedir
43 yes
44 $ hg $NO_RM mv somedir/foo destdir/foo
45 $ isdir somedir
46 yes
47 $ ls somedir
48 $ cd $TESTTMP
49
50 Updating to a commit that doesn't have the directory:
51 $ hg init hgupdate
52 $ cd hgupdate
53 $ echo hi > r0
54 $ hg ci -qAm r0
55 $ mkdir somedir
56 $ echo hi > somedir/foo
57 $ hg ci -qAm r1
58 $ isdir somedir
59 yes
60 $ hg co -q -r ".^"
61 $ isdir somedir
62 no
63 $ hg co -q tip
64 $ isdir somedir
65 yes
66 $ hg $NO_RM co -q -r ".^"
67 $ isdir somedir
68 yes
69 $ ls somedir
70 $ cd $TESTTMP
71
72 Rebasing across a commit that doesn't have the directory, from inside the
73 directory:
74 $ hg init hgrebase
75 $ cd hgrebase
76 $ echo hi > r0
77 $ hg ci -qAm r0
78 $ mkdir somedir
79 $ echo hi > somedir/foo
80 $ hg ci -qAm first_rebase_source
81 $ hg $NO_RM co -q -r ".^"
82 $ echo hi > somedir/bar
83 $ hg ci -qAm first_rebase_dest
84 $ hg $NO_RM co -q -r ".^"
85 $ echo hi > somedir/baz
86 $ hg ci -qAm second_rebase_dest
87 $ hg co -qr 'desc(first_rebase_source)'
88 $ cd $TESTTMP/hgrebase/somedir
89 $ hg --config extensions.rebase= rebase -qr . -d 'desc(first_rebase_dest)'
90 current directory was removed
91 (consider changing to repo root: $TESTTMP/hgrebase)
92 $ cd $TESTTMP/hgrebase/somedir
93 (The current node is the rebased first_rebase_source on top of
94 first_rebase_dest)
95 This should not output anything about current directory being removed:
96 $ hg $NO_RM --config extensions.rebase= rebase -qr . -d 'desc(second_rebase_dest)'
97 $ cd $TESTTMP
98
99 Histediting across a commit that doesn't have the directory, from inside the
100 directory (reordering nodes):
101 $ hg init hghistedit
102 $ cd hghistedit
103 $ echo hi > r0
104 $ hg ci -qAm r0
105 $ echo hi > r1
106 $ hg ci -qAm r1
107 $ echo hi > r2
108 $ hg ci -qAm r2
109 $ mkdir somedir
110 $ echo hi > somedir/foo
111 $ hg ci -qAm migrating_revision
112 $ cat > histedit_commands <<EOF
113 > pick 89079fab8aee 0 r0
114 > pick e6d271df3142 1 r1
115 > pick 89e25aa83f0f 3 migrating_revision
116 > pick b550aa12d873 2 r2
117 > EOF
118 $ cd $TESTTMP/hghistedit/somedir
119 $ hg --config extensions.histedit= histedit -q --commands ../histedit_commands
120
121 histedit doesn't output anything when the current diretory is removed. We rely
122 on the tests being commonly run on machines where the current directory
123 disappearing from underneath us actually has an observable effect, such as an
124 error or no files listed
125 #if linuxormacos
126 $ isfile foo
127 no
128 #endif
129 $ cd $TESTTMP/hghistedit/somedir
130 $ isfile foo
131 yes
132
133 $ cd $TESTTMP/hghistedit
134 $ cat > histedit_commands <<EOF
135 > pick 89079fab8aee 0 r0
136 > pick 7c7a22c6009f 3 migrating_revision
137 > pick e6d271df3142 1 r1
138 > pick 40a53c2d4276 2 r2
139 > EOF
140 $ cd $TESTTMP/hghistedit/somedir
141 $ hg $NO_RM --config extensions.histedit= histedit -q --commands ../histedit_commands
142 Regardless of system, we should always get a 'yes' here.
143 $ isfile foo
144 yes
145 $ cd $TESTTMP
146
147 This is essentially the exact test from issue5826, just cleaned up a little:
148
149 $ hg init issue5826_withrm
150 $ cd issue5826_withrm
151
152 $ cat >> $HGRCPATH <<EOF
153 > [extensions]
154 > histedit =
155 > EOF
156 Commit three revisions that each create a directory:
157
158 $ mkdir foo
159 $ touch foo/bar
160 $ hg commit -qAm "add foo"
161
162 $ mkdir bar
163 $ touch bar/bar
164 $ hg commit -qAm "add bar"
165
166 $ mkdir baz
167 $ touch baz/bar
168 $ hg commit -qAm "add baz"
169
170 Enter the first directory:
171
172 $ cd foo
173
174 Histedit doing 'pick, pick, fold':
175
176 $ hg histedit --commands /dev/stdin <<EOF
177 > pick 6274c77c93c3 1 add bar
178 > pick ff70a87b588f 0 add foo
179 > fold 9992bb0ac0db 2 add baz
180 > EOF
181 abort: $ENOENT$
182 [255]
183
184 Go back to the repo root after losing it as part of that operation:
185 $ cd $TESTTMP/issue5826_withrm
186
187 Note the lack of a non-zero exit code from this function - it exits
188 successfully, but doesn't really do anything.
189 $ hg histedit --continue
190 9992bb0ac0db: cannot fold - working copy is not a descendant of previous commit 5c806432464a
191 saved backup bundle to $TESTTMP/issue5826_withrm/.hg/strip-backup/ff70a87b588f-e94f9789-histedit.hg
192
193 $ hg log -T '{rev}:{node|short} {desc}\n'
194 2:94e3f9fae1d6 fold-temp-revision 9992bb0ac0db
195 1:5c806432464a add foo
196 0:d17db4b0303a add bar
197
198 Now test that again with experimental.removeemptydirs=false:
199 $ hg init issue5826_norm
200 $ cd issue5826_norm
201
202 $ cat >> $HGRCPATH <<EOF
203 > [extensions]
204 > histedit =
205 > [experimental]
206 > removeemptydirs = false
207 > EOF
208 Commit three revisions that each create a directory:
209
210 $ mkdir foo
211 $ touch foo/bar
212 $ hg commit -qAm "add foo"
213
214 $ mkdir bar
215 $ touch bar/bar
216 $ hg commit -qAm "add bar"
217
218 $ mkdir baz
219 $ touch baz/bar
220 $ hg commit -qAm "add baz"
221
222 Enter the first directory:
223
224 $ cd foo
225
226 Histedit doing 'pick, pick, fold':
227
228 $ hg histedit --commands /dev/stdin <<EOF
229 > pick 6274c77c93c3 1 add bar
230 > pick ff70a87b588f 0 add foo
231 > fold 9992bb0ac0db 2 add baz
232 > EOF
233 saved backup bundle to $TESTTMP/issue5826_withrm/issue5826_norm/.hg/strip-backup/5c806432464a-cd4c8d86-histedit.hg
234
235 Note the lack of a 'cd' being necessary here, and we don't need to 'histedit
236 --continue'
237
238 $ hg log -T '{rev}:{node|short} {desc}\n'
239 1:b9eddaa97cbc add foo
240 ***
241 add baz
242 0:d17db4b0303a add bar
@@ -1242,7 +1242,8 b' def copy(ui, repo, pats, opts, rename=Fa'
1242 dryrun=dryrun, cwd=cwd)
1242 dryrun=dryrun, cwd=cwd)
1243 if rename and not dryrun:
1243 if rename and not dryrun:
1244 if not after and srcexists and not samefile:
1244 if not after and srcexists and not samefile:
1245 repo.wvfs.unlinkpath(abssrc)
1245 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
1246 repo.wvfs.unlinkpath(abssrc, rmdir=rmdir)
1246 wctx.forget([abssrc])
1247 wctx.forget([abssrc])
1247
1248
1248 # pat: ossep
1249 # pat: ossep
@@ -2269,7 +2270,9 b' def remove(ui, repo, m, prefix, after, f'
2269 for f in list:
2270 for f in list:
2270 if f in added:
2271 if f in added:
2271 continue # we never unlink added files on remove
2272 continue # we never unlink added files on remove
2272 repo.wvfs.unlinkpath(f, ignoremissing=True)
2273 rmdir = repo.ui.configbool('experimental',
2274 'removeemptydirs')
2275 repo.wvfs.unlinkpath(f, ignoremissing=True, rmdir=rmdir)
2273 repo[None].forget(list)
2276 repo[None].forget(list)
2274
2277
2275 if warn:
2278 if warn:
@@ -3029,7 +3032,8 b' def _performrevert(repo, parents, ctx, a'
3029
3032
3030 def doremove(f):
3033 def doremove(f):
3031 try:
3034 try:
3032 repo.wvfs.unlinkpath(f)
3035 rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
3036 repo.wvfs.unlinkpath(f, rmdir=rmdir)
3033 except OSError:
3037 except OSError:
3034 pass
3038 pass
3035 repo.dirstate.remove(f)
3039 repo.dirstate.remove(f)
@@ -566,6 +566,9 b" coreconfigitem('experimental', 'obsmarke"
566 coreconfigitem('experimental', 'remotenames',
566 coreconfigitem('experimental', 'remotenames',
567 default=False,
567 default=False,
568 )
568 )
569 coreconfigitem('experimental', 'removeemptydirs',
570 default=True,
571 )
569 coreconfigitem('experimental', 'revlogv2',
572 coreconfigitem('experimental', 'revlogv2',
570 default=None,
573 default=None,
571 )
574 )
@@ -1707,7 +1707,9 b' class workingfilectx(committablefilectx)'
1707
1707
1708 def remove(self, ignoremissing=False):
1708 def remove(self, ignoremissing=False):
1709 """wraps unlink for a repo's working directory"""
1709 """wraps unlink for a repo's working directory"""
1710 self._repo.wvfs.unlinkpath(self._path, ignoremissing=ignoremissing)
1710 rmdir = self._repo.ui.configbool('experimental', 'removeemptydirs')
1711 self._repo.wvfs.unlinkpath(self._path, ignoremissing=ignoremissing,
1712 rmdir=rmdir)
1711
1713
1712 def write(self, data, flags, backgroundclose=False, **kwargs):
1714 def write(self, data, flags, backgroundclose=False, **kwargs):
1713 """wraps repo.wwrite"""
1715 """wraps repo.wwrite"""
@@ -497,7 +497,8 b' class fsbackend(abstractbackend):'
497 self.opener.setflags(fname, False, True)
497 self.opener.setflags(fname, False, True)
498
498
499 def unlink(self, fname):
499 def unlink(self, fname):
500 self.opener.unlinkpath(fname, ignoremissing=True)
500 rmdir = self.ui.configbool('experimental', 'removeemptydirs')
501 self.opener.unlinkpath(fname, ignoremissing=True, rmdir=rmdir)
501
502
502 def writerej(self, fname, failed, total, lines):
503 def writerej(self, fname, failed, total, lines):
503 fname = fname + ".rej"
504 fname = fname + ".rej"
@@ -2139,17 +2139,18 b' class atomictempfile(object):'
2139 else:
2139 else:
2140 self.close()
2140 self.close()
2141
2141
2142 def unlinkpath(f, ignoremissing=False):
2142 def unlinkpath(f, ignoremissing=False, rmdir=True):
2143 """unlink and remove the directory if it is empty"""
2143 """unlink and remove the directory if it is empty"""
2144 if ignoremissing:
2144 if ignoremissing:
2145 tryunlink(f)
2145 tryunlink(f)
2146 else:
2146 else:
2147 unlink(f)
2147 unlink(f)
2148 # try removing directories that might now be empty
2148 if rmdir:
2149 try:
2149 # try removing directories that might now be empty
2150 removedirs(os.path.dirname(f))
2150 try:
2151 except OSError:
2151 removedirs(os.path.dirname(f))
2152 pass
2152 except OSError:
2153 pass
2153
2154
2154 def tryunlink(f):
2155 def tryunlink(f):
2155 """Attempt to remove a file, ignoring ENOENT errors."""
2156 """Attempt to remove a file, ignoring ENOENT errors."""
@@ -246,8 +246,9 b' class abstractvfs(object):'
246 """Attempt to remove a file, ignoring missing file errors."""
246 """Attempt to remove a file, ignoring missing file errors."""
247 util.tryunlink(self.join(path))
247 util.tryunlink(self.join(path))
248
248
249 def unlinkpath(self, path=None, ignoremissing=False):
249 def unlinkpath(self, path=None, ignoremissing=False, rmdir=True):
250 return util.unlinkpath(self.join(path), ignoremissing=ignoremissing)
250 return util.unlinkpath(self.join(path), ignoremissing=ignoremissing,
251 rmdir=rmdir)
251
252
252 def utime(self, path=None, t=None):
253 def utime(self, path=None, t=None):
253 return os.utime(self.join(path), t)
254 return os.utime(self.join(path), t)
General Comments 0
You need to be logged in to leave comments. Login now