mercurial/patch.py
changeset 3716 ab5600428b08
parent 3702 70c3ee224c08
child 3717 9e248cfd8b94
equal deleted inserted replaced
3715:6cb3aca69cdc 3716:ab5600428b08
   112     if not diffs_seen:
   112     if not diffs_seen:
   113         os.unlink(tmpname)
   113         os.unlink(tmpname)
   114         return None, message, user, date
   114         return None, message, user, date
   115     return tmpname, message, user, date
   115     return tmpname, message, user, date
   116 
   116 
       
   117 GP_PATCH  = 1 << 0  # we have to run patch
       
   118 GP_FILTER = 1 << 1  # there's some copy/rename operation
       
   119 GP_BINARY = 1 << 2  # there's a binary patch
       
   120 
   117 def readgitpatch(patchname):
   121 def readgitpatch(patchname):
   118     """extract git-style metadata about patches from <patchname>"""
   122     """extract git-style metadata about patches from <patchname>"""
   119     class gitpatch:
   123     class gitpatch:
   120         "op is one of ADD, DELETE, RENAME, MODIFY or COPY"
   124         "op is one of ADD, DELETE, RENAME, MODIFY or COPY"
   121         def __init__(self, path):
   125         def __init__(self, path):
   131     gitre = re.compile('diff --git a/(.*) b/(.*)')
   135     gitre = re.compile('diff --git a/(.*) b/(.*)')
   132     pf = file(patchname)
   136     pf = file(patchname)
   133     gp = None
   137     gp = None
   134     gitpatches = []
   138     gitpatches = []
   135     # Can have a git patch with only metadata, causing patch to complain
   139     # Can have a git patch with only metadata, causing patch to complain
   136     dopatch = False
   140     dopatch = 0
   137 
   141 
   138     lineno = 0
   142     lineno = 0
   139     for line in pf:
   143     for line in pf:
   140         lineno += 1
   144         lineno += 1
   141         if line.startswith('diff --git'):
   145         if line.startswith('diff --git'):
   148                 gp.lineno = lineno
   152                 gp.lineno = lineno
   149         elif gp:
   153         elif gp:
   150             if line.startswith('--- '):
   154             if line.startswith('--- '):
   151                 if gp.op in ('COPY', 'RENAME'):
   155                 if gp.op in ('COPY', 'RENAME'):
   152                     gp.copymod = True
   156                     gp.copymod = True
   153                     dopatch = 'filter'
   157                     dopatch |= GP_FILTER
   154                 gitpatches.append(gp)
   158                 gitpatches.append(gp)
   155                 gp = None
   159                 gp = None
   156                 if not dopatch:
   160                 dopatch |= GP_PATCH
   157                     dopatch = True
       
   158                 continue
   161                 continue
   159             if line.startswith('rename from '):
   162             if line.startswith('rename from '):
   160                 gp.op = 'RENAME'
   163                 gp.op = 'RENAME'
   161                 gp.oldpath = line[12:].rstrip()
   164                 gp.oldpath = line[12:].rstrip()
   162             elif line.startswith('rename to '):
   165             elif line.startswith('rename to '):
   172                 gp.op = 'ADD'
   175                 gp.op = 'ADD'
   173                 gp.mode = int(line.rstrip()[-3:], 8)
   176                 gp.mode = int(line.rstrip()[-3:], 8)
   174             elif line.startswith('new mode '):
   177             elif line.startswith('new mode '):
   175                 gp.mode = int(line.rstrip()[-3:], 8)
   178                 gp.mode = int(line.rstrip()[-3:], 8)
   176             elif line.startswith('GIT binary patch'):
   179             elif line.startswith('GIT binary patch'):
   177                 if not dopatch:
   180                 dopatch |= GP_BINARY
   178                     dopatch = 'binary'
       
   179                 gp.binary = True
   181                 gp.binary = True
   180     if gp:
   182     if gp:
   181         gitpatches.append(gp)
   183         gitpatches.append(gp)
   182 
   184 
   183     if not gitpatches:
   185     if not gitpatches:
   184         dopatch = True
   186         dopatch = GP_PATCH
   185 
   187 
   186     return (dopatch, gitpatches)
   188     return (dopatch, gitpatches)
   187 
   189 
   188 def dogitpatch(patchname, gitpatches, cwd=None):
   190 def dogitpatch(patchname, gitpatches, cwd=None):
   189     """Preprocess git patch so that vanilla patch can handle it"""
   191     """Preprocess git patch so that vanilla patch can handle it"""
   310     for gp in gitpatches:
   312     for gp in gitpatches:
   311         files[gp.path] = (gp.op, gp)
   313         files[gp.path] = (gp.op, gp)
   312 
   314 
   313     fuzz = False
   315     fuzz = False
   314     if dopatch:
   316     if dopatch:
   315         if dopatch in ('filter', 'binary'):
   317         filterpatch = dopatch & (GP_FILTER | GP_BINARY)
       
   318         if filterpatch:
   316             patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
   319             patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
   317         try:
   320         try:
   318             if dopatch != 'binary':
   321             if dopatch & GP_PATCH:
   319                 fuzz = __patch(patchname)
   322                 fuzz = __patch(patchname)
   320         finally:
   323         finally:
   321             if dopatch == 'filter':
   324             if filterpatch:
   322                 os.unlink(patchname)
   325                 os.unlink(patchname)
   323 
   326 
   324     return fuzz
   327     return fuzz
   325 
   328 
   326 def diffopts(ui, opts={}, untrusted=False):
   329 def diffopts(ui, opts={}, untrusted=False):