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) |