hgext/mq.py
changeset 2776 ae726521717c
parent 2775 ee48e5ef8753
parent 2774 663094f5595b
child 2786 f4d916351366
equal deleted inserted replaced
2775:ee48e5ef8753 2776:ae726521717c
    65         self.series_path = "series"
    65         self.series_path = "series"
    66         self.status_path = "status"
    66         self.status_path = "status"
    67 
    67 
    68         if os.path.exists(os.path.join(self.path, self.series_path)):
    68         if os.path.exists(os.path.join(self.path, self.series_path)):
    69             self.full_series = self.opener(self.series_path).read().splitlines()
    69             self.full_series = self.opener(self.series_path).read().splitlines()
    70         self.read_series(self.full_series)
    70         self.parse_series()
    71 
    71 
    72         if os.path.exists(os.path.join(self.path, self.status_path)):
    72         if os.path.exists(os.path.join(self.path, self.status_path)):
    73             self.applied = [StatusEntry(l)
    73             self.applied = [StatusEntry(l)
    74                             for l in self.opener(self.status_path).read().splitlines()]
    74                             for l in self.opener(self.status_path).read().splitlines()]
    75 
    75 
    84                 if s == patch:
    84                 if s == patch:
    85                     return index
    85                     return index
    86             index += 1
    86             index += 1
    87         return None
    87         return None
    88 
    88 
    89     def read_series(self, list):
    89     def parse_series(self):
    90         def matcher(list):
       
    91             pre = re.compile("(\s*)([^#]+)")
       
    92             for l in list:
       
    93                 m = pre.match(l)
       
    94                 if m:
       
    95                     s = m.group(2)
       
    96                     s = s.rstrip()
       
    97                     if len(s) > 0:
       
    98                         yield s
       
    99         self.series = []
    90         self.series = []
   100         self.series = [ x for x in matcher(list) ]
    91         for l in self.full_series:
       
    92             s = l.split('#', 1)[0].strip()
       
    93             if s:
       
    94                 self.series.append(s)
   101 
    95 
   102     def save_dirty(self):
    96     def save_dirty(self):
   103         if self.applied_dirty:
    97         def write_list(items, path):
   104             if len(self.applied) > 0:
    98             fp = self.opener(path, 'w')
   105                 nl = "\n"
    99             for i in items:
   106             else:
   100                 print >> fp, i
   107                 nl = ""
   101             fp.close()
   108             f = self.opener(self.status_path, "w")
   102         if self.applied_dirty: write_list(map(str, self.applied), self.status_path)
   109             f.write("\n".join([str(x) for x in self.applied]) + nl)
   103         if self.series_dirty: write_list(self.full_series, self.series_path)
   110         if self.series_dirty:
       
   111             if len(self.full_series) > 0:
       
   112                 nl = "\n"
       
   113             else:
       
   114                 nl = ""
       
   115             f = self.opener(self.series_path, "w")
       
   116             f.write("\n".join(self.full_series) + nl)
       
   117 
   104 
   118     def readheaders(self, patch):
   105     def readheaders(self, patch):
   119         def eatdiff(lines):
   106         def eatdiff(lines):
   120             while lines:
   107             while lines:
   121                 l = lines[-1]
   108                 l = lines[-1]
   404                 r.remove([patch], True)
   391                 r.remove([patch], True)
   405             else:
   392             else:
   406                 os.unlink(os.path.join(self.path, patch))
   393                 os.unlink(os.path.join(self.path, patch))
   407         i = self.find_series(patch)
   394         i = self.find_series(patch)
   408         del self.full_series[i]
   395         del self.full_series[i]
   409         self.read_series(self.full_series)
   396         self.parse_series()
   410         self.series_dirty = 1
   397         self.series_dirty = 1
   411 
   398 
   412     def check_toppatch(self, repo):
   399     def check_toppatch(self, repo):
   413         if len(self.applied) > 0:
   400         if len(self.applied) > 0:
   414             top = revlog.bin(self.applied[-1].rev)
   401             top = revlog.bin(self.applied[-1].rev)
   441                             "New patch: %s" % patch, force=True, wlock=wlock)
   428                             "New patch: %s" % patch, force=True, wlock=wlock)
   442         if n == None:
   429         if n == None:
   443             raise util.Abort(_("repo commit failed"))
   430             raise util.Abort(_("repo commit failed"))
   444         self.full_series[insert:insert] = [patch]
   431         self.full_series[insert:insert] = [patch]
   445         self.applied.append(StatusEntry(revlog.hex(n), patch))
   432         self.applied.append(StatusEntry(revlog.hex(n), patch))
   446         self.read_series(self.full_series)
   433         self.parse_series()
   447         self.series_dirty = 1
   434         self.series_dirty = 1
   448         self.applied_dirty = 1
   435         self.applied_dirty = 1
   449         p = self.opener(patch, "w")
   436         p = self.opener(patch, "w")
   450         if msg:
   437         if msg:
   451             msg = msg + "\n"
   438             msg = msg + "\n"
   939             raise util.Abort(_("patch %s is not in series file") % patch)
   926             raise util.Abort(_("patch %s is not in series file") % patch)
   940         if not patch:
   927         if not patch:
   941             start = self.series_end()
   928             start = self.series_end()
   942         else:
   929         else:
   943             start = self.series.index(patch) + 1
   930             start = self.series.index(patch) + 1
   944         for p in self.series[start:]:
   931         return [(i, self.series[i]) for i in xrange(start, len(self.series))]
   945             if self.ui.verbose:
       
   946                 self.ui.write("%d " % self.series.index(p))
       
   947             self.ui.write("%s\n" % p)
       
   948 
   932 
   949     def qseries(self, repo, missing=None, summary=False):
   933     def qseries(self, repo, missing=None, summary=False):
   950         start = self.series_end()
   934         start = self.series_end()
   951         if not missing:
   935         if not missing:
   952             for i in range(len(self.series)):
   936             for i in range(len(self.series)):
  1017             self.ui.warn("No saved patch data found\n")
  1001             self.ui.warn("No saved patch data found\n")
  1018             return 1
  1002             return 1
  1019         self.ui.warn("restoring status: %s\n" % lines[0])
  1003         self.ui.warn("restoring status: %s\n" % lines[0])
  1020         self.full_series = series
  1004         self.full_series = series
  1021         self.applied = applied
  1005         self.applied = applied
  1022         self.read_series(self.full_series)
  1006         self.parse_series()
  1023         self.series_dirty = 1
  1007         self.series_dirty = 1
  1024         self.applied_dirty = 1
  1008         self.applied_dirty = 1
  1025         heads = repo.changelog.heads()
  1009         heads = repo.changelog.heads()
  1026         if delete:
  1010         if delete:
  1027             if rev not in heads:
  1011             if rev not in heads:
  1163             if patch in self.series:
  1147             if patch in self.series:
  1164                 raise util.Abort(_('patch %s is already in the series file')
  1148                 raise util.Abort(_('patch %s is already in the series file')
  1165                                  % patch)
  1149                                  % patch)
  1166             index = self.full_series_end() + i
  1150             index = self.full_series_end() + i
  1167             self.full_series[index:index] = [patch]
  1151             self.full_series[index:index] = [patch]
  1168             self.read_series(self.full_series)
  1152             self.parse_series()
  1169             self.ui.warn("adding %s to series file\n" % patch)
  1153             self.ui.warn("adding %s to series file\n" % patch)
  1170             i += 1
  1154             i += 1
  1171             added.append(patch)
  1155             added.append(patch)
  1172             patch = None
  1156             patch = None
  1173         self.series_dirty = 1
  1157         self.series_dirty = 1
  1190     repo.mq.qapplied(repo, patch)
  1174     repo.mq.qapplied(repo, patch)
  1191     return 0
  1175     return 0
  1192 
  1176 
  1193 def unapplied(ui, repo, patch=None, **opts):
  1177 def unapplied(ui, repo, patch=None, **opts):
  1194     """print the patches not yet applied"""
  1178     """print the patches not yet applied"""
  1195     repo.mq.unapplied(repo, patch)
  1179     for i, p in repo.mq.unapplied(repo, patch):
  1196     return 0
  1180         if ui.verbose:
       
  1181             ui.write("%d " % i)
       
  1182         ui.write("%s\n" % p)
  1197 
  1183 
  1198 def qimport(ui, repo, *filename, **opts):
  1184 def qimport(ui, repo, *filename, **opts):
  1199     """import a patch"""
  1185     """import a patch"""
  1200     q = repo.mq
  1186     q = repo.mq
  1201     q.qimport(repo, filename, patch=opts['name'],
  1187     q.qimport(repo, filename, patch=opts['name'],
  1232     before that it has no patches applied.
  1218     before that it has no patches applied.
  1233 
  1219 
  1234     Source patch repository is looked for in <src>/.hg/patches by
  1220     Source patch repository is looked for in <src>/.hg/patches by
  1235     default.  Use -p <url> to change.
  1221     default.  Use -p <url> to change.
  1236     '''
  1222     '''
  1237     commands.setremoteconfig(**opts)
  1223     commands.setremoteconfig(ui, opts)
  1238     if dest is None:
  1224     if dest is None:
  1239         dest = hg.defaultdest(source)
  1225         dest = hg.defaultdest(source)
  1240     sr = hg.repository(ui, ui.expandpath(source))
  1226     sr = hg.repository(ui, ui.expandpath(source))
  1241     qbase, destrev = None, None
  1227     qbase, destrev = None, None
  1242     if sr.local():
  1228     if sr.local():
  1301     changes unless -f is specified, in which case the patch will
  1287     changes unless -f is specified, in which case the patch will
  1302     be initialised with them.
  1288     be initialised with them.
  1303 
  1289 
  1304     -m or -l set the patch header as well as the commit message.
  1290     -m or -l set the patch header as well as the commit message.
  1305     If neither is specified, the patch header is empty and the
  1291     If neither is specified, the patch header is empty and the
  1306     commit message is 'New patch: PATCH'
  1292     commit message is 'New patch: PATCH'"""
  1307 
       
  1308     If -f is specified, the patch will be initialized with any
       
  1309     uncommitted changes. Otherwise, if there outsta"""
       
  1310     q = repo.mq
  1293     q = repo.mq
  1311     message=commands.logmessage(**opts)
  1294     message=commands.logmessage(**opts)
  1312     q.new(repo, patch, msg=message, force=opts['force'])
  1295     q.new(repo, patch, msg=message, force=opts['force'])
  1313     q.save_dirty()
  1296     q.save_dirty()
  1314     return 0
  1297     return 0
  1334     return 0
  1317     return 0
  1335 
  1318 
  1336 def fold(ui, repo, *files, **opts):
  1319 def fold(ui, repo, *files, **opts):
  1337     """fold the named patches into the current patch
  1320     """fold the named patches into the current patch
  1338 
  1321 
  1339     Patches must not yet be applied.
  1322     Patches must not yet be applied. Each patch will be successively
       
  1323     applied to the current patch in the order given. If all the
       
  1324     patches apply successfully, the current patch will be refreshed
       
  1325     with the new cumulative patch, and the folded patches will
       
  1326     be deleted. With -f/--force, the folded patch files will
       
  1327     be removed afterwards.
       
  1328 
  1340     The header for each folded patch will be concatenated with
  1329     The header for each folded patch will be concatenated with
  1341     the current patch header, separated by a line of '* * *'."""
  1330     the current patch header, separated by a line of '* * *'."""
  1342 
  1331 
  1343     q = repo.mq
  1332     q = repo.mq
  1344 
  1333 
  1382         message = ui.edit(message, user or ui.username())
  1371         message = ui.edit(message, user or ui.username())
  1383 
  1372 
  1384     q.refresh(repo, msg=message)
  1373     q.refresh(repo, msg=message)
  1385 
  1374 
  1386     for patch in patches:
  1375     for patch in patches:
  1387         q.delete(repo, patch)
  1376         q.delete(repo, patch, force=opts['force'])
  1388 
  1377 
  1389     q.save_dirty()
  1378     q.save_dirty()
  1390 
  1379 
  1391 def header(ui, repo, patch=None):
  1380 def header(ui, repo, patch=None):
  1392     """Print the header of the topmost or specified patch"""
  1381     """Print the header of the topmost or specified patch"""
  1491 
  1480 
  1492     if ui.verbose:
  1481     if ui.verbose:
  1493         ui.write('Renaming %s to %s\n' % (patch, name))
  1482         ui.write('Renaming %s to %s\n' % (patch, name))
  1494     i = q.find_series(patch)
  1483     i = q.find_series(patch)
  1495     q.full_series[i] = name
  1484     q.full_series[i] = name
  1496     q.read_series(q.full_series)
  1485     q.parse_series()
  1497     q.series_dirty = 1
  1486     q.series_dirty = 1
  1498 
  1487 
  1499     info = q.isapplied(patch)
  1488     info = q.isapplied(patch)
  1500     if info:
  1489     if info:
  1501         q.applied[info[0]] = StatusEntry(info[1], name)
  1490         q.applied[info[0]] = StatusEntry(info[1], name)
  1615          [('f', 'force', None, _('delete patch file'))],
  1604          [('f', 'force', None, _('delete patch file'))],
  1616           'hg qdelete [-f] PATCH'),
  1605           'hg qdelete [-f] PATCH'),
  1617     'qfold':
  1606     'qfold':
  1618         (fold,
  1607         (fold,
  1619          [('e', 'edit', None, _('edit patch header')),
  1608          [('e', 'edit', None, _('edit patch header')),
       
  1609           ('f', 'force', None, _('delete folded patch files')),
  1620           ('m', 'message', '', _('set patch header to <text>')),
  1610           ('m', 'message', '', _('set patch header to <text>')),
  1621           ('l', 'logfile', '', _('set patch header to contents of <file>'))],
  1611           ('l', 'logfile', '', _('set patch header to contents of <file>'))],
  1622          'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
  1612          'hg qfold [-e] [-m <text>] [-l <file] PATCH...'),
  1623     'qheader': (header, [],
  1613     'qheader': (header, [],
  1624                 _('hg qheader [PATCH]')),
  1614                 _('hg qheader [PATCH]')),