mercurial/patch.py
changeset 7517 49f34b43cf90
parent 7507 8e76e9f67cb3
child 7521 ca044918fdf1
child 7561 fa23d169a895
equal deleted inserted replaced
7516:a8376f2aa3b1 7517:49f34b43cf90
   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:
   857                     context = True
   877                     context = True
   858                 gpatch = changed.get(bfile)
   878                 gpatch = changed.get(bfile)
   859                 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
   879                 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
   860                 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
   880                 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
   861                 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
   881                 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
       
   882                 if remove:
       
   883                     gpatch = changed.get(afile[2:])
       
   884                     if gpatch and gpatch.mode[0]:
       
   885                         current_hunk = symlinkhunk(gpatch, current_hunk)
   862             except PatchError, err:
   886             except PatchError, err:
   863                 ui.debug(err)
   887                 ui.debug(err)
   864                 current_hunk = None
   888                 current_hunk = None
   865                 continue
   889                 continue
   866             hunknum += 1
   890             hunknum += 1
  1038             dst = os.path.join(repo.root, gp.path)
  1062             dst = os.path.join(repo.root, gp.path)
  1039             # patch won't create empty files
  1063             # patch won't create empty files
  1040             if gp.op == 'ADD' and not os.path.exists(dst):
  1064             if gp.op == 'ADD' and not os.path.exists(dst):
  1041                 flags = (isexec and 'x' or '') + (islink and 'l' or '')
  1065                 flags = (isexec and 'x' or '') + (islink and 'l' or '')
  1042                 repo.wwrite(gp.path, '', flags)
  1066                 repo.wwrite(gp.path, '', flags)
  1043             else:
  1067             elif gp.op != 'DELETE':
  1044                 util.set_flags(dst, islink, isexec)
  1068                 util.set_flags(dst, islink, isexec)
  1045     cmdutil.addremove(repo, cfiles, similarity=similarity)
  1069     cmdutil.addremove(repo, cfiles, similarity=similarity)
  1046     files = patches.keys()
  1070     files = patches.keys()
  1047     files.extend([r for r in removes if r not in files])
  1071     files.extend([r for r in removes if r not in files])
  1048     return util.sort(files)
  1072     return util.sort(files)