mercurial/patch.py
branchstable
changeset 10748 fb06e357e698
parent 10747 b010d899665e
child 10749 03225f14c495
child 10883 196908117c27
equal deleted inserted replaced
10747:b010d899665e 10748:fb06e357e698
  1010 
  1010 
  1011     # our states
  1011     # our states
  1012     BFILE = 1
  1012     BFILE = 1
  1013     context = None
  1013     context = None
  1014     lr = linereader(fp)
  1014     lr = linereader(fp)
  1015     dopatch = True
       
  1016     # gitworkdone is True if a git operation (copy, rename, ...) was
  1015     # gitworkdone is True if a git operation (copy, rename, ...) was
  1017     # performed already for the current file. Useful when the file
  1016     # performed already for the current file. Useful when the file
  1018     # section may have no hunk.
  1017     # section may have no hunk.
  1019     gitworkdone = False
  1018     gitworkdone = False
       
  1019     empty = None
  1020 
  1020 
  1021     while True:
  1021     while True:
  1022         newfile = newgitfile = False
  1022         newfile = newgitfile = False
  1023         x = lr.readline()
  1023         x = lr.readline()
  1024         if not x:
  1024         if not x:
  1026         if current_hunk:
  1026         if current_hunk:
  1027             if x.startswith('\ '):
  1027             if x.startswith('\ '):
  1028                 current_hunk.fix_newline()
  1028                 current_hunk.fix_newline()
  1029             yield 'hunk', current_hunk
  1029             yield 'hunk', current_hunk
  1030             current_hunk = None
  1030             current_hunk = None
  1031             gitworkdone = False
  1031             empty = False
  1032         if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
  1032         if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
  1033             ((context is not False) and x.startswith('***************')))):
  1033             ((context is not False) and x.startswith('***************')))):
  1034             try:
  1034             try:
  1035                 if context is None and x.startswith('***************'):
  1035                 if context is None and x.startswith('***************'):
  1036                     context = True
  1036                     context = True
  1044                 continue
  1044                 continue
  1045             hunknum += 1
  1045             hunknum += 1
  1046             if emitfile:
  1046             if emitfile:
  1047                 emitfile = False
  1047                 emitfile = False
  1048                 yield 'file', (afile, bfile, current_hunk)
  1048                 yield 'file', (afile, bfile, current_hunk)
       
  1049                 empty = False
  1049         elif state == BFILE and x.startswith('GIT binary patch'):
  1050         elif state == BFILE and x.startswith('GIT binary patch'):
  1050             current_hunk = binhunk(changed[bfile])
  1051             current_hunk = binhunk(changed[bfile])
  1051             hunknum += 1
  1052             hunknum += 1
  1052             if emitfile:
  1053             if emitfile:
  1053                 emitfile = False
  1054                 emitfile = False
  1054                 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
  1055                 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
       
  1056                 empty = False
  1055             current_hunk.extract(lr)
  1057             current_hunk.extract(lr)
  1056         elif x.startswith('diff --git'):
  1058         elif x.startswith('diff --git'):
  1057             # check for git diff, scanning the whole patch file if needed
  1059             # check for git diff, scanning the whole patch file if needed
  1058             m = gitre.match(x)
  1060             m = gitre.match(x)
       
  1061             gitworkdone = False
  1059             if m:
  1062             if m:
  1060                 afile, bfile = m.group(1, 2)
  1063                 afile, bfile = m.group(1, 2)
  1061                 if not git:
  1064                 if not git:
  1062                     git = True
  1065                     git = True
  1063                     dopatch, gitpatches = scangitpatch(lr, x)
  1066                     gitpatches = scangitpatch(lr, x)[1]
  1064                     yield 'git', gitpatches
  1067                     yield 'git', gitpatches
  1065                     for gp in gitpatches:
  1068                     for gp in gitpatches:
  1066                         changed[gp.path] = gp
  1069                         changed[gp.path] = gp
  1067                 # else error?
  1070                 # else error?
  1068                 # copy/rename + modify should modify target, not source
  1071                 # copy/rename + modify should modify target, not source
  1069                 gp = changed.get(bfile)
  1072                 gp = changed.get(bfile)
  1070                 if gp and gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD'):
  1073                 if gp and (gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD')
       
  1074                            or gp.mode):
  1071                     afile = bfile
  1075                     afile = bfile
  1072                     gitworkdone = True
  1076                     gitworkdone = True
  1073                 newgitfile = True
  1077                 newgitfile = True
  1074         elif x.startswith('---'):
  1078         elif x.startswith('---'):
  1075             # check for a unified diff
  1079             # check for a unified diff
  1095             newfile = True
  1099             newfile = True
  1096             context = True
  1100             context = True
  1097             afile = parsefilename(x)
  1101             afile = parsefilename(x)
  1098             bfile = parsefilename(l2)
  1102             bfile = parsefilename(l2)
  1099 
  1103 
       
  1104         if newfile:
       
  1105             if empty:
       
  1106                 raise NoHunks
       
  1107             empty = not gitworkdone
       
  1108             gitworkdone = False
       
  1109 
  1100         if newgitfile or newfile:
  1110         if newgitfile or newfile:
  1101             emitfile = True
  1111             emitfile = True
  1102             state = BFILE
  1112             state = BFILE
  1103             hunknum = 0
  1113             hunknum = 0
  1104     if current_hunk:
  1114     if current_hunk:
  1105         if current_hunk.complete():
  1115         if current_hunk.complete():
  1106             yield 'hunk', current_hunk
  1116             yield 'hunk', current_hunk
       
  1117             empty = False
  1107         else:
  1118         else:
  1108             raise PatchError(_("malformed patch %s %s") % (afile,
  1119             raise PatchError(_("malformed patch %s %s") % (afile,
  1109                              current_hunk.desc))
  1120                              current_hunk.desc))
  1110 
  1121 
  1111     if hunknum == 0 and dopatch and not gitworkdone:
  1122     if (empty is None and not gitworkdone) or empty:
  1112         raise NoHunks
  1123         raise NoHunks
  1113 
  1124 
  1114 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
  1125 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
  1115     """
  1126     """
  1116     Reads a patch from fp and tries to apply it.
  1127     Reads a patch from fp and tries to apply it.