##// END OF EJS Templates
mq: update .hgsubstate if subrepos are clean (issue2499)...
Kevin Bullock -
r13174:be7e8e9b default
parent child Browse files
Show More
@@ -0,0 +1,342 b''
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "mq=" >> $HGRCPATH
3 $ echo "record=" >> $HGRCPATH
4 $ echo "[diff]" >> $HGRCPATH
5 $ echo "nodates=1" >> $HGRCPATH
6
7 fn to create new repository w/dirty subrepo, and cd into it
8 $ mkrepo() {
9 > hg init $1
10 > cd $1
11 > hg qinit
12 > }
13
14 fn to create dirty subrepo
15 $ mksubrepo() {
16 > hg init $1
17 > cd $1
18 > echo a > a
19 > hg add
20 > cd ..
21 > }
22
23 $ testadd() {
24 > local stdin=`cat`
25 > mksubrepo sub
26 > echo sub = sub >> .hgsub
27 > hg add .hgsub
28 > echo % abort when adding .hgsub w/dirty subrepo
29 > hg status -S
30 > echo '%' $*
31 > echo "$stdin" | hg $*
32 > echo [$?]
33 > hg -R sub ci -m0sub
34 > echo % update substate when adding .hgsub w/clean updated subrepo
35 > hg status -S
36 > echo '%' $*
37 > echo "$stdin" | hg $*
38 > hg debugsub
39 > }
40
41 $ testmod() {
42 > local stdin=`cat`
43 > mksubrepo sub2
44 > echo sub2 = sub2 >> .hgsub
45 > echo % abort when modifying .hgsub w/dirty subrepo
46 > hg status -S
47 > echo '%' $*
48 > echo "$stdin" | hg $*
49 > echo [$?]
50 > hg -R sub2 ci -m0sub2
51 > echo % update substate when modifying .hgsub w/clean updated subrepo
52 > hg status -S
53 > echo '%' $*
54 > echo "$stdin" | hg $*
55 > hg debugsub
56 > }
57
58 $ testrm1() {
59 > mksubrepo sub3
60 > echo sub3 = sub3 >> .hgsub
61 > hg ci -Aqmsub3
62 > $EXTRA
63 > echo b >> sub3/a
64 > hg rm .hgsub
65 > echo % update substate when removing .hgsub w/dirty subrepo
66 > hg status -S
67 > echo '%' $*
68 > echo "$stdin" | hg $*
69 > echo % debugsub should be empty
70 > hg debugsub
71 > }
72 $ testrm2() {
73 > mksubrepo sub4
74 > echo sub4 = sub4 >> .hgsub
75 > hg ci -Aqmsub4
76 > $EXTRA
77 > hg rm .hgsub
78 > echo % update substate when removing .hgsub w/clean updated subrepo
79 > hg status -S
80 > echo '%' $*
81 > echo "$stdin" | hg $*
82 > echo % debugsub should be empty
83 > hg debugsub
84 > }
85
86
87 handle subrepos safely on qnew
88
89 $ mkrepo repo-2499-qnew
90 $ testadd qnew -m0 0.diff
91 adding a
92 % abort when adding .hgsub w/dirty subrepo
93 A .hgsub
94 A sub/a
95 % qnew -m0 0.diff
96 abort: uncommitted changes in subrepository sub
97 [255]
98 % update substate when adding .hgsub w/clean updated subrepo
99 A .hgsub
100 % qnew -m0 0.diff
101 committing subrepository sub
102 path sub
103 source sub
104 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
105
106 $ testmod qnew -m1 1.diff
107 adding a
108 % abort when modifying .hgsub w/dirty subrepo
109 M .hgsub
110 A sub2/a
111 % qnew -m1 1.diff
112 abort: uncommitted changes in subrepository sub2
113 [255]
114 % update substate when modifying .hgsub w/clean updated subrepo
115 M .hgsub
116 % qnew -m1 1.diff
117 committing subrepository sub2
118 path sub
119 source sub
120 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
121 path sub2
122 source sub2
123 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
124
125 $ hg qpop -qa
126 patch queue now empty
127 $ testrm1 qnew -m2 2.diff
128 adding a
129 % update substate when removing .hgsub w/dirty subrepo
130 M sub3/a
131 R .hgsub
132 % qnew -m2 2.diff
133 % debugsub should be empty
134
135 $ hg qpop -qa
136 patch queue now empty
137 $ testrm2 qnew -m3 3.diff
138 adding a
139 % update substate when removing .hgsub w/clean updated subrepo
140 R .hgsub
141 % qnew -m3 3.diff
142 % debugsub should be empty
143
144 $ cd ..
145
146
147 handle subrepos safely on qrefresh
148
149 $ mkrepo repo-2499-qrefresh
150 $ hg qnew -m0 0.diff
151 $ testadd qrefresh
152 adding a
153 % abort when adding .hgsub w/dirty subrepo
154 A .hgsub
155 A sub/a
156 % qrefresh
157 abort: uncommitted changes in subrepository sub
158 [255]
159 % update substate when adding .hgsub w/clean updated subrepo
160 A .hgsub
161 % qrefresh
162 committing subrepository sub
163 path sub
164 source sub
165 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
166
167 $ hg qnew -m1 1.diff
168 $ testmod qrefresh
169 adding a
170 % abort when modifying .hgsub w/dirty subrepo
171 M .hgsub
172 A sub2/a
173 % qrefresh
174 abort: uncommitted changes in subrepository sub2
175 [255]
176 % update substate when modifying .hgsub w/clean updated subrepo
177 M .hgsub
178 % qrefresh
179 committing subrepository sub2
180 path sub
181 source sub
182 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
183 path sub2
184 source sub2
185 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
186
187 $ hg qpop -qa
188 patch queue now empty
189 $ EXTRA='hg qnew -m2 2.diff' testrm1 qrefresh
190 adding a
191 % update substate when removing .hgsub w/dirty subrepo
192 M sub3/a
193 R .hgsub
194 % qrefresh
195 % debugsub should be empty
196
197 $ hg qpop -qa
198 patch queue now empty
199 $ EXTRA='hg qnew -m3 3.diff' testrm2 qrefresh
200 adding a
201 % update substate when removing .hgsub w/clean updated subrepo
202 R .hgsub
203 % qrefresh
204 % debugsub should be empty
205
206 $ cd ..
207
208
209 handle subrepos safely on qpush/qpop
210
211 $ mkrepo repo-2499-qpush
212 $ mksubrepo sub
213 adding a
214 $ hg -R sub ci -m0sub
215 $ echo sub = sub > .hgsub
216 $ hg add .hgsub
217 $ hg qnew -m0 0.diff
218 committing subrepository sub
219 $ hg debugsub
220 path sub
221 source sub
222 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
223
224 qpop
225 $ hg qpop
226 popping 0.diff
227 patch queue now empty
228 $ hg status -AS
229 $ hg debugsub
230
231 qpush
232 $ hg qpush
233 applying 0.diff
234 now at: 0.diff
235 $ hg status -AS
236 C .hgsub
237 C .hgsubstate
238 C sub/a
239 $ hg debugsub
240 path sub
241 source sub
242 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
243
244 $ cd ..
245
246
247 handle subrepos safely on qrecord
248
249 $ mkrepo repo-2499-qrecord
250 $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
251 > y
252 > y
253 > EOF
254 adding a
255 % abort when adding .hgsub w/dirty subrepo
256 A .hgsub
257 A sub/a
258 % qrecord --config ui.interactive=1 -m0 0.diff
259 diff --git a/.hgsub b/.hgsub
260 new file mode 100644
261 examine changes to '.hgsub'? [Ynsfdaq?]
262 abort: uncommitted changes in subrepository sub
263 [255]
264 % update substate when adding .hgsub w/clean updated subrepo
265 A .hgsub
266 % qrecord --config ui.interactive=1 -m0 0.diff
267 diff --git a/.hgsub b/.hgsub
268 new file mode 100644
269 examine changes to '.hgsub'? [Ynsfdaq?]
270 committing subrepository sub
271 path sub
272 source sub
273 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
274
275 $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
276 > y
277 > y
278 > EOF
279 adding a
280 % abort when modifying .hgsub w/dirty subrepo
281 M .hgsub
282 A sub2/a
283 % qrecord --config ui.interactive=1 -m1 1.diff
284 diff --git a/.hgsub b/.hgsub
285 1 hunks, 1 lines changed
286 examine changes to '.hgsub'? [Ynsfdaq?]
287 @@ -1,1 +1,2 @@
288 sub = sub
289 +sub2 = sub2
290 record this change to '.hgsub'? [Ynsfdaq?]
291 abort: uncommitted changes in subrepository sub2
292 [255]
293 % update substate when modifying .hgsub w/clean updated subrepo
294 M .hgsub
295 % qrecord --config ui.interactive=1 -m1 1.diff
296 diff --git a/.hgsub b/.hgsub
297 1 hunks, 1 lines changed
298 examine changes to '.hgsub'? [Ynsfdaq?]
299 @@ -1,1 +1,2 @@
300 sub = sub
301 +sub2 = sub2
302 record this change to '.hgsub'? [Ynsfdaq?]
303 committing subrepository sub2
304 path sub
305 source sub
306 revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
307 path sub2
308 source sub2
309 revision 1f94c7611cc6b74f5a17b16121a1170d44776845
310
311 $ hg qpop -qa
312 patch queue now empty
313 $ EXTRA= testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
314 > y
315 > y
316 > EOF
317 adding a
318 % update substate when removing .hgsub w/dirty subrepo
319 M sub3/a
320 R .hgsub
321 % qrecord --config ui.interactive=1 -m2 2.diff
322 diff --git a/.hgsub b/.hgsub
323 deleted file mode 100644
324 examine changes to '.hgsub'? [Ynsfdaq?]
325 % debugsub should be empty
326
327 $ hg qpop -qa
328 patch queue now empty
329 $ EXTRA= testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
330 > y
331 > y
332 > EOF
333 adding a
334 % update substate when removing .hgsub w/clean updated subrepo
335 R .hgsub
336 % qrecord --config ui.interactive=1 -m3 3.diff
337 diff --git a/.hgsub b/.hgsub
338 deleted file mode 100644
339 examine changes to '.hgsub'? [Ynsfdaq?]
340 % debugsub should be empty
341
342 $ cd ..
@@ -793,6 +793,19 b' class queue(object):'
793 return top, patch
793 return top, patch
794 return None, None
794 return None, None
795
795
796 def check_substate(self, repo):
797 '''return list of subrepos at a different revision than substate.
798 Abort if any subrepos have uncommitted changes.'''
799 inclsubs = []
800 wctx = repo[None]
801 for s in wctx.substate:
802 if wctx.sub(s).dirty(True):
803 raise util.Abort(
804 _("uncommitted changes in subrepository %s") % s)
805 elif wctx.sub(s).dirty():
806 inclsubs.append(s)
807 return inclsubs
808
796 def check_localchanges(self, repo, force=False, refresh=True):
809 def check_localchanges(self, repo, force=False, refresh=True):
797 m, a, r, d = repo.status()[:4]
810 m, a, r, d = repo.status()[:4]
798 if (m or a or r or d) and not force:
811 if (m or a or r or d) and not force:
@@ -826,16 +839,23 b' class queue(object):'
826 % patchfn)
839 % patchfn)
827 else:
840 else:
828 raise util.Abort(_('patch "%s" already exists') % patchfn)
841 raise util.Abort(_('patch "%s" already exists') % patchfn)
842
843 inclsubs = self.check_substate(repo)
844 if inclsubs:
845 inclsubs.append('.hgsubstate')
829 if opts.get('include') or opts.get('exclude') or pats:
846 if opts.get('include') or opts.get('exclude') or pats:
847 if inclsubs:
848 pats = list(pats or []) + inclsubs
830 match = cmdutil.match(repo, pats, opts)
849 match = cmdutil.match(repo, pats, opts)
831 # detect missing files in pats
850 # detect missing files in pats
832 def badfn(f, msg):
851 def badfn(f, msg):
833 raise util.Abort('%s: %s' % (f, msg))
852 if f != '.hgsubstate': # .hgsubstate is auto-created
853 raise util.Abort('%s: %s' % (f, msg))
834 match.bad = badfn
854 match.bad = badfn
835 m, a, r, d = repo.status(match=match)[:4]
855 m, a, r, d = repo.status(match=match)[:4]
836 else:
856 else:
837 m, a, r, d = self.check_localchanges(repo, force=True)
857 m, a, r, d = self.check_localchanges(repo, force=True)
838 match = cmdutil.matchfiles(repo, m + a + r)
858 match = cmdutil.matchfiles(repo, m + a + r + inclsubs)
839 if len(repo[None].parents()) > 1:
859 if len(repo[None].parents()) > 1:
840 raise util.Abort(_('cannot manage merge changesets'))
860 raise util.Abort(_('cannot manage merge changesets'))
841 commitfiles = m + a + r
861 commitfiles = m + a + r
@@ -1259,6 +1279,8 b' class queue(object):'
1259 if repo.changelog.heads(top) != [top]:
1279 if repo.changelog.heads(top) != [top]:
1260 raise util.Abort(_("cannot refresh a revision with children"))
1280 raise util.Abort(_("cannot refresh a revision with children"))
1261
1281
1282 inclsubs = self.check_substate(repo)
1283
1262 cparents = repo.changelog.parents(top)
1284 cparents = repo.changelog.parents(top)
1263 patchparent = self.qparents(repo, top)
1285 patchparent = self.qparents(repo, top)
1264 ph = patchheader(self.join(patchfn), self.plainmode)
1286 ph = patchheader(self.join(patchfn), self.plainmode)
@@ -1337,7 +1359,7 b' class queue(object):'
1337 r = list(dd)
1359 r = list(dd)
1338 a = list(aa)
1360 a = list(aa)
1339 c = [filter(matchfn, l) for l in (m, a, r)]
1361 c = [filter(matchfn, l) for l in (m, a, r)]
1340 match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2]))
1362 match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2] + inclsubs))
1341 chunks = patch.diff(repo, patchparent, match=match,
1363 chunks = patch.diff(repo, patchparent, match=match,
1342 changes=c, opts=diffopts)
1364 changes=c, opts=diffopts)
1343 for chunk in chunks:
1365 for chunk in chunks:
@@ -236,9 +236,10 b' def subrepo(ctx, path):'
236
236
237 class abstractsubrepo(object):
237 class abstractsubrepo(object):
238
238
239 def dirty(self):
239 def dirty(self, ignoreupdate=False):
240 """returns true if the dirstate of the subrepo does not match
240 """returns true if the dirstate of the subrepo is dirty or does not
241 current stored state
241 match current stored state. If ignoreupdate is true, only check
242 whether the subrepo has uncommitted changes in its dirstate.
242 """
243 """
243 raise NotImplementedError
244 raise NotImplementedError
244
245
@@ -390,12 +391,13 b' class hgsubrepo(abstractsubrepo):'
390 s = subrepo(ctx, subpath)
391 s = subrepo(ctx, subpath)
391 s.archive(ui, archiver, os.path.join(prefix, self._path))
392 s.archive(ui, archiver, os.path.join(prefix, self._path))
392
393
393 def dirty(self):
394 def dirty(self, ignoreupdate=False):
394 r = self._state[1]
395 r = self._state[1]
395 if r == '':
396 if r == '' and not ignoreupdate: # no state recorded
396 return True
397 return True
397 w = self._repo[None]
398 w = self._repo[None]
398 if w.p1() != self._repo[r]: # version checked out change
399 # version checked out changed?
400 if w.p1() != self._repo[r] and not ignoreupdate:
399 return True
401 return True
400 return w.dirty() # working directory changed
402 return w.dirty() # working directory changed
401
403
@@ -538,9 +540,10 b' class svnsubrepo(abstractsubrepo):'
538 return True, True
540 return True, True
539 return bool(changes), False
541 return bool(changes), False
540
542
541 def dirty(self):
543 def dirty(self, ignoreupdate=False):
542 if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
544 if not self._wcchanged()[0]:
543 return False
545 if self._wcrev() == self._state[1] and not ignoreupdate:
546 return False
544 return True
547 return True
545
548
546 def commit(self, text, user, date):
549 def commit(self, text, user, date):
General Comments 0
You need to be logged in to leave comments. Login now