hgext/mq.py
changeset 2748 752b9475a700
parent 2747 0016fc748f61
child 2750 8c814c1ab31e
child 2753 84218111e80f
equal deleted inserted replaced
2747:0016fc748f61 2748:752b9475a700
       
     1 
     1 # queue.py - patch queues for mercurial
     2 # queue.py - patch queues for mercurial
     2 #
     3 #
     3 # Copyright 2005 Chris Mason <mason@suse.com>
     4 # Copyright 2005 Chris Mason <mason@suse.com>
     4 #
     5 #
     5 # This software may be used and distributed according to the terms
     6 # This software may be used and distributed according to the terms
   268                 self.applied_dirty = 1
   269                 self.applied_dirty = 1
   269             if err:
   270             if err:
   270                 return (err, head)
   271                 return (err, head)
   271         return (0, head)
   272         return (0, head)
   272 
   273 
       
   274     def patch(self, repo, patchfile):
       
   275         '''Apply patchfile  to the working directory.
       
   276         patchfile: file name of patch'''
       
   277         try:
       
   278             pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
       
   279             f = os.popen("%s -d '%s' -p1 --no-backup-if-mismatch < '%s'" %
       
   280                          (pp, repo.root, patchfile))
       
   281         except:
       
   282             self.ui.warn("patch failed, unable to continue (try -v)\n")
       
   283             return (None, [], False)
       
   284         files = []
       
   285         fuzz = False
       
   286         for l in f:
       
   287             l = l.rstrip('\r\n');
       
   288             if self.ui.verbose:
       
   289                 self.ui.warn(l + "\n")
       
   290             if l[:14] == 'patching file ':
       
   291                 pf = os.path.normpath(l[14:])
       
   292                 # when patch finds a space in the file name, it puts
       
   293                 # single quotes around the filename.  strip them off
       
   294                 if pf[0] == "'" and pf[-1] == "'":
       
   295                     pf = pf[1:-1]
       
   296                 if pf not in files:
       
   297                     files.append(pf)
       
   298                 printed_file = False
       
   299                 file_str = l
       
   300             elif l.find('with fuzz') >= 0:
       
   301                 if not printed_file:
       
   302                     self.ui.warn(file_str + '\n')
       
   303                     printed_file = True
       
   304                 self.ui.warn(l + '\n')
       
   305                 fuzz = True
       
   306             elif l.find('saving rejects to file') >= 0:
       
   307                 self.ui.warn(l + '\n')
       
   308             elif l.find('FAILED') >= 0:
       
   309                 if not printed_file:
       
   310                     self.ui.warn(file_str + '\n')
       
   311                     printed_file = True
       
   312                 self.ui.warn(l + '\n')
       
   313 
       
   314         return (not f.close(), files, fuzz)
       
   315         
   273     def apply(self, repo, series, list=False, update_status=True,
   316     def apply(self, repo, series, list=False, update_status=True,
   274               strict=False, patchdir=None, merge=None, wlock=None):
   317               strict=False, patchdir=None, merge=None, wlock=None):
   275         # TODO unify with commands.py
   318         # TODO unify with commands.py
   276         if not patchdir:
   319         if not patchdir:
   277             patchdir = self.path
   320             patchdir = self.path
   297             else:
   340             else:
   298                 if list:
   341                 if list:
   299                     message.append("\nimported patch %s" % patch)
   342                     message.append("\nimported patch %s" % patch)
   300                 message = '\n'.join(message)
   343                 message = '\n'.join(message)
   301 
   344 
   302             try:
   345             (patcherr, files, fuzz) = self.patch(repo, pf)
   303                 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
   346             patcherr = not patcherr
   304                 f = os.popen("%s -d '%s' -p1 --no-backup-if-mismatch < '%s'" %
       
   305                              (pp, repo.root, pf))
       
   306             except:
       
   307                 self.ui.warn("patch failed, unable to continue (try -v)\n")
       
   308                 err = 1
       
   309                 break
       
   310             files = []
       
   311             fuzz = False
       
   312             for l in f:
       
   313                 l = l.rstrip('\r\n');
       
   314                 if self.ui.verbose:
       
   315                     self.ui.warn(l + "\n")
       
   316                 if l[:14] == 'patching file ':
       
   317                     pf = os.path.normpath(l[14:])
       
   318                     # when patch finds a space in the file name, it puts
       
   319                     # single quotes around the filename.  strip them off
       
   320                     if pf[0] == "'" and pf[-1] == "'":
       
   321                         pf = pf[1:-1]
       
   322                     if pf not in files:
       
   323                         files.append(pf)
       
   324                     printed_file = False
       
   325                     file_str = l
       
   326                 elif l.find('with fuzz') >= 0:
       
   327                     if not printed_file:
       
   328                         self.ui.warn(file_str + '\n')
       
   329                         printed_file = True
       
   330                     self.ui.warn(l + '\n')
       
   331                     fuzz = True
       
   332                 elif l.find('saving rejects to file') >= 0:
       
   333                     self.ui.warn(l + '\n')
       
   334                 elif l.find('FAILED') >= 0:
       
   335                     if not printed_file:
       
   336                         self.ui.warn(file_str + '\n')
       
   337                         printed_file = True
       
   338                     self.ui.warn(l + '\n')
       
   339             patcherr = f.close()
       
   340 
   347 
   341             if merge and len(files) > 0:
   348             if merge and len(files) > 0:
   342                 # Mark as merged and update dirstate parent info
   349                 # Mark as merged and update dirstate parent info
   343                 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm')
   350                 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm')
   344                 p1, p2 = repo.dirstate.parents()
   351                 p1, p2 = repo.dirstate.parents()
  1287     """diff of the current patch"""
  1294     """diff of the current patch"""
  1288     # deep in the dirstate code, the walkhelper method wants a list, not a tuple
  1295     # deep in the dirstate code, the walkhelper method wants a list, not a tuple
  1289     repo.mq.diff(repo, list(files))
  1296     repo.mq.diff(repo, list(files))
  1290     return 0
  1297     return 0
  1291 
  1298 
       
  1299 def fold(ui, repo, *files):
       
  1300     """fold the named patches into the current patch
       
  1301     Patches must not yet be applied."""
       
  1302     q = repo.mq
       
  1303 
       
  1304     if not files:
       
  1305         raise util.Abort(_('qfold requires at least one patch name'))
       
  1306     if not q.check_toppatch(repo):
       
  1307         raise util.Abort(_('No patches applied\n'))
       
  1308 
       
  1309     parent = q.lookup('qtip')
       
  1310     patches = []
       
  1311     messages = []
       
  1312     for f in files:
       
  1313         patch = q.lookup(f)
       
  1314         if patch in patches or patch == parent:
       
  1315             self.ui.warn(_('Skipping already folded patch %s') % patch)
       
  1316         if q.isapplied(patch):
       
  1317             raise util.Abort(_('qfold cannot fold already applied patch %s') % patch)
       
  1318         patches.append(patch)
       
  1319 
       
  1320     for patch in patches:
       
  1321         messages.append(q.readheaders(patch)[0])
       
  1322         pf = os.path.join(q.path, patch)
       
  1323         (patchsuccess, files, fuzz) = q.patch(repo, pf)
       
  1324         if not patchsuccess:
       
  1325             raise util.Abort(_('Error folding patch %s') % patch)
       
  1326 
       
  1327     message = q.readheaders(parent)[0]
       
  1328     for msg in messages:
       
  1329         message.append('* * *')
       
  1330         message.extend(msg)
       
  1331     message = '\n'.join(message)
       
  1332 
       
  1333     q.refresh(repo, msg=message)
       
  1334 
       
  1335     for patch in patches:
       
  1336         q.delete(repo, patch)
       
  1337 
       
  1338     q.save_dirty()
       
  1339 
  1292 def header(ui, repo, patch=None):
  1340 def header(ui, repo, patch=None):
  1293     """Print the header of the topmost or specified patch"""
  1341     """Print the header of the topmost or specified patch"""
  1294     q = repo.mq
  1342     q = repo.mq
  1295 
  1343 
  1296     if patch:
  1344     if patch:
  1460         (commit,
  1508         (commit,
  1461          commands.table["^commit|ci"][1],
  1509          commands.table["^commit|ci"][1],
  1462          'hg qcommit [OPTION]... [FILE]...'),
  1510          'hg qcommit [OPTION]... [FILE]...'),
  1463     "^qdiff": (diff, [], 'hg qdiff [FILE]...'),
  1511     "^qdiff": (diff, [], 'hg qdiff [FILE]...'),
  1464     "qdelete": (delete, [], 'hg qdelete PATCH'),
  1512     "qdelete": (delete, [], 'hg qdelete PATCH'),
       
  1513     'qfold': (fold, [], 'hg qfold PATCH...'),
  1465     'qheader': (header, [],
  1514     'qheader': (header, [],
  1466                 _('hg qheader [PATCH]')),
  1515                 _('hg qheader [PATCH]')),
  1467     "^qimport":
  1516     "^qimport":
  1468         (qimport,
  1517         (qimport,
  1469          [('e', 'existing', None, 'import file in patch dir'),
  1518          [('e', 'existing', None, 'import file in patch dir'),