269
282
@util.propertycache
270
283
def applied(self):
271
284
if os.path.exists(self.join(self.status_path)):
273
n, name = l.split(':', 1)
274
return statusentry(bin(n), name)
285
def parselines(lines):
287
entry = l.split(':', 1)
290
yield statusentry(bin(n), name)
292
self.ui.warn(_('malformated mq status line: %s\n') % entry)
293
# else we ignore empty lines
275
294
lines = self.opener(self.status_path).read().splitlines()
276
return [parse(l) for l in lines]
295
return list(parselines(lines))
279
298
@util.propertycache
793
812
return top, patch
794
813
return None, None
815
def check_substate(self, repo):
816
'''return list of subrepos at a different revision than substate.
817
Abort if any subrepos have uncommitted changes.'''
820
for s in wctx.substate:
821
if wctx.sub(s).dirty(True):
823
_("uncommitted changes in subrepository %s") % s)
824
elif wctx.sub(s).dirty():
796
828
def check_localchanges(self, repo, force=False, refresh=True):
797
829
m, a, r, d = repo.status()[:4]
798
830
if (m or a or r or d) and not force:
828
860
raise util.Abort(_('patch "%s" already exists') % patchfn)
862
inclsubs = self.check_substate(repo)
864
inclsubs.append('.hgsubstate')
829
865
if opts.get('include') or opts.get('exclude') or pats:
867
pats = list(pats or []) + inclsubs
830
868
match = cmdutil.match(repo, pats, opts)
831
869
# detect missing files in pats
832
870
def badfn(f, msg):
833
raise util.Abort('%s: %s' % (f, msg))
871
if f != '.hgsubstate': # .hgsubstate is auto-created
872
raise util.Abort('%s: %s' % (f, msg))
834
873
match.bad = badfn
835
874
m, a, r, d = repo.status(match=match)[:4]
837
876
m, a, r, d = self.check_localchanges(repo, force=True)
838
match = cmdutil.matchfiles(repo, m + a + r)
877
match = cmdutil.matchfiles(repo, m + a + r + inclsubs)
839
878
if len(repo[None].parents()) > 1:
840
879
raise util.Abort(_('cannot manage merge changesets'))
841
880
commitfiles = m + a + r
1006
1045
raise util.Abort(_("patch %s not in series") % patch)
1008
1047
def push(self, repo, patch=None, force=False, list=False,
1009
mergeq=None, all=False, move=False):
1048
mergeq=None, all=False, move=False, exact=False):
1010
1049
diffopts = self.diffopts()
1011
1050
wlock = repo.wlock()
1029
1068
# go backwards with qpush)
1031
1070
info = self.isapplied(patch)
1033
if info[0] < len(self.applied) - 1:
1035
_("cannot push to a previous patch: %s") % patch)
1071
if info and info[0] >= len(self.applied) - 1:
1037
1073
_('qpush: %s is already at the top\n') % patch)
1039
1076
pushable, reason = self.pushable(patch)
1078
if self.series.index(patch) < self.series_end():
1080
_("cannot push to a previous patch: %s") % patch)
1042
1083
reason = _('guarded by %r') % reason
1063
1104
self.check_localchanges(repo)
1108
raise util.Abort(_("cannot use --exact and --move together"))
1110
raise util.Abort(_("cannot push --exact with applied patches"))
1111
root = self.series[start]
1112
target = patchheader(self.join(root), self.plainmode).parent
1114
raise util.Abort(_("%s does not have a parent recorded" % root))
1115
if not repo[target] == repo['.']:
1116
hg.update(repo, target)
1067
raise util.Abort(_("please specify the patch to move"))
1120
raise util.Abort(_("please specify the patch to move"))
1068
1121
for i, rpn in enumerate(self.full_series[start:]):
1069
1122
# strip markers for patch guards
1070
1123
if self.guard_re.split(rpn, 1)[0] == patch:
1247
1300
if repo.changelog.heads(top) != [top]:
1248
1301
raise util.Abort(_("cannot refresh a revision with children"))
1303
inclsubs = self.check_substate(repo)
1250
1305
cparents = repo.changelog.parents(top)
1251
1306
patchparent = self.qparents(repo, top)
1252
1307
ph = patchheader(self.join(patchfn), self.plainmode)
1270
1325
# and then commit.
1272
1327
# this should really read:
1273
# mm, dd, aa, aa2 = repo.status(tip, patchparent)[:4]
1328
# mm, dd, aa = repo.status(top, patchparent)[:3]
1274
1329
# but we do it backwards to take advantage of manifest/chlog
1275
1330
# caching against the next repo.status call
1276
mm, aa, dd, aa2 = repo.status(patchparent, top)[:4]
1331
mm, aa, dd = repo.status(patchparent, top)[:3]
1277
1332
changes = repo.changelog.read(top)
1278
1333
man = repo.manifest.read(changes[0])
1290
1345
match = cmdutil.matchall(repo)
1291
1346
m, a, r, d = repo.status(match=match)[:4]
1293
1351
# we might end up with files that were added between
1294
1352
# qtip and the dirstate parent, but then changed in the
1295
1353
# local dirstate. in this case, we want them to only
1296
1354
# show up in the added section
1298
if x == '.hgsub' or x == '.hgsubstate':
1299
self.ui.warn(_('warning: not refreshing %s\n') % x)
1301
1356
if x not in aa:
1303
1358
# we might end up with files added by the local dirstate that
1304
1359
# were deleted by the patch. In this case, they should only
1305
1360
# show up in the changed section.
1307
if x == '.hgsub' or x == '.hgsubstate':
1308
self.ui.warn(_('warning: not adding %s\n') % x)
1315
1367
# make sure any files deleted in the local dirstate
1316
1368
# are not in the add or change column of the patch
1318
1370
for x in d + r:
1319
if x == '.hgsub' or x == '.hgsubstate':
1320
self.ui.warn(_('warning: not removing %s\n') % x)
1324
1373
forget.append(x)
1333
1382
c = [filter(matchfn, l) for l in (m, a, r)]
1334
match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2]))
1383
match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2] + inclsubs))
1335
1384
chunks = patch.diff(repo, patchparent, match=match,
1336
1385
changes=c, opts=diffopts)
1337
1386
for chunk in chunks:
1739
1788
_('need --name to import a patch from -'))
1740
1789
text = sys.stdin.read()
1742
text = url.open(self.ui, filename).read()
1791
fp = url.open(self.ui, filename)
1743
1794
except (OSError, IOError):
1744
1795
raise util.Abort(_("unable to read file %s") % filename)
1745
1796
if not patchname:
2344
2398
mergeq = queue(ui, repo.join(""), newpath)
2345
2399
ui.warn(_("merging with queue at: %s\n") % mergeq.path)
2346
2400
ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
2347
mergeq=mergeq, all=opts.get('all'), move=opts.get('move'))
2401
mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
2402
exact=opts.get('exact'))
2350
2405
def pop(ui, repo, patch=None, **opts):
2878
2934
return super(mqrepo, self).commit(text, user, date, match, force,
2881
def push(self, remote, force=False, revs=None, newbranch=False):
2937
def checkpush(self, force, revs):
2882
2938
if self.mq.applied and not force:
2883
2939
haspatches = True
2889
2945
haspatches = bool([n for n in revs if n in applied])
2891
2947
raise util.Abort(_('source has mq patches applied'))
2892
return super(mqrepo, self).push(remote, force, revs, newbranch)
2948
super(mqrepo, self).checkpush(force, revs)
2894
2950
def _findtags(self):
2895
2951
'''augment tags from base class with patch tags'''
2902
2958
mqtags = [(patch.node, patch.name) for patch in q.applied]
2904
if mqtags[-1][0] not in self.changelog.nodemap:
2961
r = self.changelog.rev(mqtags[-1][0])
2962
except error.RepoLookupError:
2905
2963
self.ui.warn(_('mq status file refers to unknown node %s\n')
2906
2964
% short(mqtags[-1][0]))
2927
2985
cl = self.changelog
2928
2986
qbasenode = q.applied[0].node
2929
if qbasenode not in cl.nodemap:
2988
qbase = cl.rev(qbasenode)
2989
except error.LookupError:
2930
2990
self.ui.warn(_('mq status file refers to unknown node %s\n')
2931
2991
% short(qbasenode))
2932
2992
return super(mqrepo, self)._branchtags(partial, lrev)
2934
qbase = cl.rev(qbasenode)
2935
2994
start = lrev + 1
2936
2995
if start < qbase:
2937
2996
# update the cache (excluding the patches) and save it
3122
3181
[('f', 'force', None, _('apply on top of local changes')),
3182
('e', 'exact', None, _('apply the target patch to its recorded parent')),
3123
3183
('l', 'list', None, _('list patch name in commit text')),
3124
3184
('a', 'all', None, _('apply all patches')),
3125
3185
('m', 'merge', None, _('merge from another queue (DEPRECATED)')),