224 return '\r' |
223 return '\r' |
225 if '\n' in data: # UNIX |
224 if '\n' in data: # UNIX |
226 return '\n' |
225 return '\n' |
227 return None # unknown |
226 return None # unknown |
228 |
227 |
229 def _matcheol(file, origfile): |
228 def _matcheol(file, back): |
230 "Convert EOL markers in a file to match origfile" |
229 "Convert EOL markers in a file to match origfile" |
231 tostyle = _eoltype(util.readfile(origfile)) |
230 tostyle = _eoltype(back.data()) # No repo.wread filters? |
232 if tostyle: |
231 if tostyle: |
233 data = util.readfile(file) |
232 data = util.readfile(file) |
234 style = _eoltype(data) |
233 style = _eoltype(data) |
235 if style: |
234 if style: |
236 newdata = data.replace(style, tostyle) |
235 newdata = data.replace(style, tostyle) |
503 } |
502 } |
504 ui = repo.ui |
503 ui = repo.ui |
505 |
504 |
506 args = _toolstr(ui, tool, "args", '$local $base $other') |
505 args = _toolstr(ui, tool, "args", '$local $base $other') |
507 if "$output" in args: |
506 if "$output" in args: |
508 out, a = a, back # read input from backup, write to original |
507 # read input from backup, write to original |
|
508 out = a |
|
509 a = repo.wvfs.join(back.path()) |
509 replace = {'local': a, 'base': b, 'other': c, 'output': out} |
510 replace = {'local': a, 'base': b, 'other': c, 'output': out} |
510 args = util.interpolate(r'\$', replace, args, |
511 args = util.interpolate(r'\$', replace, args, |
511 lambda s: util.shellquote(util.localpath(s))) |
512 lambda s: util.shellquote(util.localpath(s))) |
512 cmd = toolpath + ' ' + args |
513 cmd = toolpath + ' ' + args |
513 if _toolbool(ui, tool, "gui"): |
514 if _toolbool(ui, tool, "gui"): |
586 } |
587 } |
587 |
588 |
588 def _restorebackup(fcd, back): |
589 def _restorebackup(fcd, back): |
589 # TODO: Add a workingfilectx.write(otherfilectx) path so we can use |
590 # TODO: Add a workingfilectx.write(otherfilectx) path so we can use |
590 # util.copy here instead. |
591 # util.copy here instead. |
591 fcd.write(util.readfile(back), fcd.flags()) |
592 fcd.write(back.data(), fcd.flags()) |
592 |
593 |
593 def _makebackup(repo, ui, fcd, premerge): |
594 def _makebackup(repo, ui, wctx, fcd, premerge): |
594 """Makes a backup of the local `fcd` file prior to merging. |
595 """Makes and returns a filectx-like object for ``fcd``'s backup file. |
595 |
596 |
596 In addition to preserving the user's pre-existing modifications to `fcd` |
597 In addition to preserving the user's pre-existing modifications to `fcd` |
597 (if any), the backup is used to undo certain premerges, confirm whether a |
598 (if any), the backup is used to undo certain premerges, confirm whether a |
598 merge changed anything, and determine what line endings the new file should |
599 merge changed anything, and determine what line endings the new file should |
599 have. |
600 have. |
600 """ |
601 """ |
601 if fcd.isabsent(): |
602 if fcd.isabsent(): |
602 return None |
603 return None |
603 |
604 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset -> |
|
605 # merge -> filemerge). (I suspect the fileset import is the weakest link) |
|
606 from . import context |
604 a = _workingpath(repo, fcd) |
607 a = _workingpath(repo, fcd) |
605 back = scmutil.origpath(ui, repo, a) |
608 back = scmutil.origpath(ui, repo, a) |
606 if premerge: |
609 if premerge: |
607 util.copyfile(a, back) |
610 util.copyfile(a, back) |
608 return back |
611 return context.arbitraryfilectx(back, repo=repo) |
609 |
612 |
610 def _maketempfiles(repo, fco, fca): |
613 def _maketempfiles(repo, fco, fca): |
611 """Writes out `fco` and `fca` as temporary files, so an external merge |
614 """Writes out `fco` and `fca` as temporary files, so an external merge |
612 tool may use them. |
615 tool may use them. |
613 """ |
616 """ |
689 toolconf): |
692 toolconf): |
690 if onfailure: |
693 if onfailure: |
691 ui.warn(onfailure % fd) |
694 ui.warn(onfailure % fd) |
692 return True, 1, False |
695 return True, 1, False |
693 |
696 |
694 back = _makebackup(repo, ui, fcd, premerge) |
697 back = _makebackup(repo, ui, wctx, fcd, premerge) |
695 files = (None, None, None, back) |
698 files = (None, None, None, back) |
696 r = 1 |
699 r = 1 |
697 try: |
700 try: |
698 markerstyle = ui.config('ui', 'mergemarkers') |
701 markerstyle = ui.config('ui', 'mergemarkers') |
699 if not labels: |
702 if not labels: |
717 ui.warn(onfailure % fd) |
720 ui.warn(onfailure % fd) |
718 |
721 |
719 return True, r, deleted |
722 return True, r, deleted |
720 finally: |
723 finally: |
721 if not r and back is not None: |
724 if not r and back is not None: |
722 util.unlink(back) |
725 back.remove() |
723 |
726 |
724 def _check(repo, r, ui, tool, fcd, files): |
727 def _check(repo, r, ui, tool, fcd, files): |
725 fd = fcd.path() |
728 fd = fcd.path() |
726 unused, unused, unused, back = files |
729 unused, unused, unused, back = files |
727 |
730 |
739 r = 1 |
742 r = 1 |
740 |
743 |
741 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or |
744 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or |
742 'changed' in |
745 'changed' in |
743 _toollist(ui, tool, "check")): |
746 _toollist(ui, tool, "check")): |
744 if back is not None and filecmp.cmp(_workingpath(repo, fcd), back): |
747 if back is not None and not fcd.cmp(back): |
745 if ui.promptchoice(_(" output file %s appears unchanged\n" |
748 if ui.promptchoice(_(" output file %s appears unchanged\n" |
746 "was merge successful (yn)?" |
749 "was merge successful (yn)?" |
747 "$$ &Yes $$ &No") % fd, 1): |
750 "$$ &Yes $$ &No") % fd, 1): |
748 r = 1 |
751 r = 1 |
749 |
752 |