mercurial/patch.py
changeset 7521 ca044918fdf1
parent 7520 e4ab4802f261
parent 7517 49f34b43cf90
child 7547 4949729ee9ee
equal deleted inserted replaced
7520:e4ab4802f261 7521:ca044918fdf1
   208                 gp.oldpath = line[10:].rstrip()
   208                 gp.oldpath = line[10:].rstrip()
   209             elif line.startswith('copy to '):
   209             elif line.startswith('copy to '):
   210                 gp.path = line[8:].rstrip()
   210                 gp.path = line[8:].rstrip()
   211             elif line.startswith('deleted file'):
   211             elif line.startswith('deleted file'):
   212                 gp.op = 'DELETE'
   212                 gp.op = 'DELETE'
       
   213                 # is the deleted file a symlink?
       
   214                 gp.setmode(int(line.rstrip()[-6:], 8))
   213             elif line.startswith('new file mode '):
   215             elif line.startswith('new file mode '):
   214                 gp.op = 'ADD'
   216                 gp.op = 'ADD'
   215                 gp.setmode(int(line.rstrip()[-6:], 8))
   217                 gp.setmode(int(line.rstrip()[-6:], 8))
   216             elif line.startswith('new mode '):
   218             elif line.startswith('new mode '):
   217                 gp.setmode(int(line.rstrip()[-6:], 8))
   219                 gp.setmode(int(line.rstrip()[-6:], 8))
   362         if self.exists and h.createfile():
   364         if self.exists and h.createfile():
   363             self.ui.warn(_("file %s already exists\n") % self.fname)
   365             self.ui.warn(_("file %s already exists\n") % self.fname)
   364             self.rej.append(h)
   366             self.rej.append(h)
   365             return -1
   367             return -1
   366 
   368 
   367         if isinstance(h, binhunk):
   369         if isinstance(h, githunk):
   368             if h.rmfile():
   370             if h.rmfile():
   369                 self.unlink(self.fname)
   371                 self.unlink(self.fname)
   370             else:
   372             else:
   371                 self.lines[:] = h.new()
   373                 self.lines[:] = h.new()
   372                 self.offset += len(h.new())
   374                 self.offset += len(h.new())
   652         return res
   654         return res
   653 
   655 
   654     def new(self, fuzz=0, toponly=False):
   656     def new(self, fuzz=0, toponly=False):
   655         return self.fuzzit(self.b, fuzz, toponly)
   657         return self.fuzzit(self.b, fuzz, toponly)
   656 
   658 
   657 class binhunk:
   659 class githunk(object):
   658     'A binary patch file. Only understands literals so far.'
   660     """A git hunk"""
   659     def __init__(self, gitpatch):
   661     def __init__(self, gitpatch):
   660         self.gitpatch = gitpatch
   662         self.gitpatch = gitpatch
   661         self.text = None
   663         self.text = None
   662         self.hunk = ['GIT binary patch\n']
   664         self.hunk = []
   663 
   665 
   664     def createfile(self):
   666     def createfile(self):
   665         return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
   667         return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
   666 
   668 
   667     def rmfile(self):
   669     def rmfile(self):
   670     def complete(self):
   672     def complete(self):
   671         return self.text is not None
   673         return self.text is not None
   672 
   674 
   673     def new(self):
   675     def new(self):
   674         return [self.text]
   676         return [self.text]
       
   677 
       
   678 class binhunk(githunk):
       
   679     'A binary patch file. Only understands literals so far.'
       
   680     def __init__(self, gitpatch):
       
   681         super(binhunk, self).__init__(gitpatch)
       
   682         self.hunk = ['GIT binary patch\n']
   675 
   683 
   676     def extract(self, lr):
   684     def extract(self, lr):
   677         line = lr.readline()
   685         line = lr.readline()
   678         self.hunk.append(line)
   686         self.hunk.append(line)
   679         while line and not line.startswith('literal '):
   687         while line and not line.startswith('literal '):
   698         if len(text) != size:
   706         if len(text) != size:
   699             raise PatchError(_('binary patch is %d bytes, not %d') %
   707             raise PatchError(_('binary patch is %d bytes, not %d') %
   700                              len(text), size)
   708                              len(text), size)
   701         self.text = text
   709         self.text = text
   702 
   710 
       
   711 class symlinkhunk(githunk):
       
   712     """A git symlink hunk"""
       
   713     def __init__(self, gitpatch, hunk):
       
   714         super(symlinkhunk, self).__init__(gitpatch)
       
   715         self.hunk = hunk
       
   716 
       
   717     def complete(self):
       
   718         return True
       
   719 
       
   720     def fix_newline(self):
       
   721         return
       
   722 
   703 def parsefilename(str):
   723 def parsefilename(str):
   704     # --- filename \t|space stuff
   724     # --- filename \t|space stuff
   705     s = str[4:].rstrip('\r\n')
   725     s = str[4:].rstrip('\r\n')
   706     i = s.find('\t')
   726     i = s.find('\t')
   707     if i < 0:
   727     if i < 0:
   855                     context = True
   875                     context = True
   856                 gpatch = changed.get(bfile)
   876                 gpatch = changed.get(bfile)
   857                 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
   877                 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
   858                 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
   878                 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
   859                 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
   879                 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
       
   880                 if remove:
       
   881                     gpatch = changed.get(afile[2:])
       
   882                     if gpatch and gpatch.mode[0]:
       
   883                         current_hunk = symlinkhunk(gpatch, current_hunk)
   860             except PatchError, err:
   884             except PatchError, err:
   861                 ui.debug(err)
   885                 ui.debug(err)
   862                 current_hunk = None
   886                 current_hunk = None
   863                 continue
   887                 continue
   864             hunknum += 1
   888             hunknum += 1
  1036             dst = os.path.join(repo.root, gp.path)
  1060             dst = os.path.join(repo.root, gp.path)
  1037             # patch won't create empty files
  1061             # patch won't create empty files
  1038             if gp.op == 'ADD' and not os.path.exists(dst):
  1062             if gp.op == 'ADD' and not os.path.exists(dst):
  1039                 flags = (isexec and 'x' or '') + (islink and 'l' or '')
  1063                 flags = (isexec and 'x' or '') + (islink and 'l' or '')
  1040                 repo.wwrite(gp.path, '', flags)
  1064                 repo.wwrite(gp.path, '', flags)
  1041             else:
  1065             elif gp.op != 'DELETE':
  1042                 util.set_flags(dst, islink, isexec)
  1066                 util.set_flags(dst, islink, isexec)
  1043     cmdutil.addremove(repo, cfiles, similarity=similarity)
  1067     cmdutil.addremove(repo, cfiles, similarity=similarity)
  1044     files = patches.keys()
  1068     files = patches.keys()
  1045     files.extend([r for r in removes if r not in files])
  1069     files.extend([r for r in removes if r not in files])
  1046     return util.sort(files)
  1070     return util.sort(files)