290 self.fileprinted = False |
290 self.fileprinted = False |
291 self.printfile(False) |
291 self.printfile(False) |
292 self.hunks = 0 |
292 self.hunks = 0 |
293 |
293 |
294 def readlines(self, fname): |
294 def readlines(self, fname): |
|
295 if os.path.islink(fname): |
|
296 return [os.readlink(fname)] |
295 fp = self.opener(fname, 'r') |
297 fp = self.opener(fname, 'r') |
296 try: |
298 try: |
297 return list(linereader(fp, self.eol is not None)) |
299 return list(linereader(fp, self.eol is not None)) |
298 finally: |
300 finally: |
299 fp.close() |
301 fp.close() |
300 |
302 |
301 def writelines(self, fname, lines): |
303 def writelines(self, fname, lines): |
302 fp = self.opener(fname, 'w') |
304 # Ensure supplied data ends in fname, being a regular file or |
|
305 # a symlink. updatedir() will -too magically- take care of |
|
306 # setting it to the proper type afterwards. |
|
307 islink = os.path.islink(fname) |
|
308 if islink: |
|
309 fp = cStringIO.StringIO() |
|
310 else: |
|
311 fp = self.opener(fname, 'w') |
303 try: |
312 try: |
304 if self.eol and self.eol != '\n': |
313 if self.eol and self.eol != '\n': |
305 for l in lines: |
314 for l in lines: |
306 if l and l[-1] == '\n': |
315 if l and l[-1] == '\n': |
307 l = l[:-1] + self.eol |
316 l = l[:-1] + self.eol |
308 fp.write(l) |
317 fp.write(l) |
309 else: |
318 else: |
310 fp.writelines(lines) |
319 fp.writelines(lines) |
|
320 if islink: |
|
321 self.opener.symlink(fp.getvalue(), fname) |
311 finally: |
322 finally: |
312 fp.close() |
323 fp.close() |
313 |
324 |
314 def unlink(self, fname): |
325 def unlink(self, fname): |
315 os.unlink(fname) |
326 os.unlink(fname) |
397 if self.exists and h.createfile(): |
408 if self.exists and h.createfile(): |
398 self.ui.warn(_("file %s already exists\n") % self.fname) |
409 self.ui.warn(_("file %s already exists\n") % self.fname) |
399 self.rej.append(h) |
410 self.rej.append(h) |
400 return -1 |
411 return -1 |
401 |
412 |
402 if isinstance(h, githunk): |
413 if isinstance(h, binhunk): |
403 if h.rmfile(): |
414 if h.rmfile(): |
404 self.unlink(self.fname) |
415 self.unlink(self.fname) |
405 else: |
416 else: |
406 self.lines[:] = h.new() |
417 self.lines[:] = h.new() |
407 self.offset += len(h.new()) |
418 self.offset += len(h.new()) |
663 return res |
674 return res |
664 |
675 |
665 def new(self, fuzz=0, toponly=False): |
676 def new(self, fuzz=0, toponly=False): |
666 return self.fuzzit(self.b, fuzz, toponly) |
677 return self.fuzzit(self.b, fuzz, toponly) |
667 |
678 |
668 class githunk(object): |
679 class binhunk: |
669 """A git hunk""" |
680 'A binary patch file. Only understands literals so far.' |
670 def __init__(self, gitpatch): |
681 def __init__(self, gitpatch): |
671 self.gitpatch = gitpatch |
682 self.gitpatch = gitpatch |
672 self.text = None |
683 self.text = None |
673 self.hunk = [] |
684 self.hunk = ['GIT binary patch\n'] |
674 |
685 |
675 def createfile(self): |
686 def createfile(self): |
676 return self.gitpatch.op in ('ADD', 'RENAME', 'COPY') |
687 return self.gitpatch.op in ('ADD', 'RENAME', 'COPY') |
677 |
688 |
678 def rmfile(self): |
689 def rmfile(self): |
681 def complete(self): |
692 def complete(self): |
682 return self.text is not None |
693 return self.text is not None |
683 |
694 |
684 def new(self): |
695 def new(self): |
685 return [self.text] |
696 return [self.text] |
686 |
|
687 class binhunk(githunk): |
|
688 'A binary patch file. Only understands literals so far.' |
|
689 def __init__(self, gitpatch): |
|
690 super(binhunk, self).__init__(gitpatch) |
|
691 self.hunk = ['GIT binary patch\n'] |
|
692 |
697 |
693 def extract(self, lr): |
698 def extract(self, lr): |
694 line = lr.readline() |
699 line = lr.readline() |
695 self.hunk.append(line) |
700 self.hunk.append(line) |
696 while line and not line.startswith('literal '): |
701 while line and not line.startswith('literal '): |
715 if len(text) != size: |
720 if len(text) != size: |
716 raise PatchError(_('binary patch is %d bytes, not %d') % |
721 raise PatchError(_('binary patch is %d bytes, not %d') % |
717 len(text), size) |
722 len(text), size) |
718 self.text = text |
723 self.text = text |
719 |
724 |
720 class symlinkhunk(githunk): |
|
721 """A git symlink hunk""" |
|
722 def __init__(self, gitpatch, hunk): |
|
723 super(symlinkhunk, self).__init__(gitpatch) |
|
724 self.hunk = hunk |
|
725 |
|
726 def complete(self): |
|
727 return True |
|
728 |
|
729 def fix_newline(self): |
|
730 return |
|
731 |
|
732 def parsefilename(str): |
725 def parsefilename(str): |
733 # --- filename \t|space stuff |
726 # --- filename \t|space stuff |
734 s = str[4:].rstrip('\r\n') |
727 s = str[4:].rstrip('\r\n') |
735 i = s.find('\t') |
728 i = s.find('\t') |
736 if i < 0: |
729 if i < 0: |
873 context = True |
866 context = True |
874 gpatch = changed.get(bfile) |
867 gpatch = changed.get(bfile) |
875 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD' |
868 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD' |
876 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE' |
869 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE' |
877 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove) |
870 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove) |
878 if remove: |
|
879 gpatch = changed.get(afile[2:]) |
|
880 if gpatch and gpatch.mode[0]: |
|
881 current_hunk = symlinkhunk(gpatch, current_hunk) |
|
882 except PatchError, err: |
871 except PatchError, err: |
883 ui.debug(err) |
872 ui.debug(err) |
884 current_hunk = None |
873 current_hunk = None |
885 continue |
874 continue |
886 hunknum += 1 |
875 hunknum += 1 |