437 if util.binary(basetext) or util.binary(atext) or util.binary(btext): |
441 if util.binary(basetext) or util.binary(atext) or util.binary(btext): |
438 raise util.Abort(_("don't know how to merge binary files")) |
442 raise util.Abort(_("don't know how to merge binary files")) |
439 Merge3Text.__init__(self, basetext, atext, btext, base, a, b) |
443 Merge3Text.__init__(self, basetext, atext, btext, base, a, b) |
440 |
444 |
441 |
445 |
|
446 def simplemerge(local, base, other, **opts): |
|
447 def readfile(filename): |
|
448 f = open(filename, "rb") |
|
449 text = f.read() |
|
450 f.close() |
|
451 if util.binary(text): |
|
452 msg = _("%s looks like a binary file.") % filename |
|
453 if not opts.get('text'): |
|
454 raise util.Abort(msg) |
|
455 elif not opts.get('quiet'): |
|
456 sys.stderr.write(_('warning: %s\n') % msg) |
|
457 return text |
|
458 |
|
459 name_a = local |
|
460 name_b = other |
|
461 labels = opts.get('label', []) |
|
462 if labels: |
|
463 name_a = labels.pop(0) |
|
464 if labels: |
|
465 name_b = labels.pop(0) |
|
466 if labels: |
|
467 raise util.Abort(_("can only specify two labels.")) |
|
468 |
|
469 localtext = readfile(local) |
|
470 basetext = readfile(base) |
|
471 othertext = readfile(other) |
|
472 |
|
473 orig = local |
|
474 local = os.path.realpath(local) |
|
475 if not opts.get('print'): |
|
476 opener = util.opener(os.path.dirname(local)) |
|
477 out = opener(os.path.basename(local), "w", atomictemp=True) |
|
478 else: |
|
479 out = sys.stdout |
|
480 |
|
481 reprocess = not opts.get('no_minimal') |
|
482 |
|
483 m3 = Merge3Text(basetext, localtext, othertext) |
|
484 for line in m3.merge_lines(name_a=name_a, name_b=name_b, |
|
485 reprocess=reprocess): |
|
486 out.write(line) |
|
487 |
|
488 if not opts.get('print'): |
|
489 out.rename() |
|
490 |
|
491 if m3.conflicts: |
|
492 if not opts.get('quiet'): |
|
493 sys.stdout.flush() |
|
494 sys.stderr.write(_("warning: conflicts during merge.\n")) |
|
495 return 1 |
|
496 |
|
497 options = [('L', 'label', [], _('labels to use on conflict markers')), |
|
498 ('a', 'text', None, _('treat all files as text')), |
|
499 ('p', 'print', None, |
|
500 _('print results instead of overwriting LOCAL')), |
|
501 ('', 'no-minimal', None, |
|
502 _('do not try to minimize conflict regions')), |
|
503 ('h', 'help', None, _('display help and exit')), |
|
504 ('q', 'quiet', None, _('suppress output'))] |
|
505 |
|
506 usage = _('''simplemerge [OPTS] LOCAL BASE OTHER |
|
507 |
|
508 Simple three-way file merge utility with a minimal feature set. |
|
509 |
|
510 Apply to LOCAL the changes necessary to go from BASE to OTHER. |
|
511 |
|
512 By default, LOCAL is overwritten with the results of this operation. |
|
513 ''') |
|
514 |
|
515 def showhelp(): |
|
516 sys.stdout.write(usage) |
|
517 sys.stdout.write('\noptions:\n') |
|
518 |
|
519 out_opts = [] |
|
520 for shortopt, longopt, default, desc in options: |
|
521 out_opts.append(('%2s%s' % (shortopt and '-%s' % shortopt, |
|
522 longopt and ' --%s' % longopt), |
|
523 '%s' % desc)) |
|
524 opts_len = max([len(opt[0]) for opt in out_opts]) |
|
525 for first, second in out_opts: |
|
526 sys.stdout.write(' %-*s %s\n' % (opts_len, first, second)) |
|
527 |
|
528 class ParseError(Exception): |
|
529 """Exception raised on errors in parsing the command line.""" |
|
530 |
442 def main(argv): |
531 def main(argv): |
443 # as for diff3 and meld the syntax is "MINE BASE OTHER" |
532 try: |
444 a = file(argv[1], 'rt').readlines() |
533 opts = {} |
445 base = file(argv[2], 'rt').readlines() |
534 try: |
446 b = file(argv[3], 'rt').readlines() |
535 args = fancyopts.fancyopts(argv[1:], options, opts) |
447 |
536 except fancyopts.getopt.GetoptError, e: |
448 m3 = Merge3(base, a, b) |
537 raise ParseError(e) |
449 |
538 if opts['help']: |
450 #for sr in m3.find_sync_regions(): |
539 showhelp() |
451 # print sr |
540 return 0 |
452 |
541 if len(args) != 3: |
453 # sys.stdout.writelines(m3.merge_lines(name_a=argv[1], name_b=argv[3])) |
542 raise ParseError(_('wrong number of arguments')) |
454 sys.stdout.writelines(m3.merge_annotated()) |
543 return simplemerge(*args, **opts) |
455 |
544 except ParseError, e: |
|
545 sys.stdout.write("%s: %s\n" % (sys.argv[0], e)) |
|
546 showhelp() |
|
547 return 1 |
|
548 except util.Abort, e: |
|
549 sys.stderr.write("abort: %s\n" % e) |
|
550 return 255 |
|
551 except KeyboardInterrupt: |
|
552 return 255 |
456 |
553 |
457 if __name__ == '__main__': |
554 if __name__ == '__main__': |
458 import sys |
555 import sys |
|
556 import os |
459 sys.exit(main(sys.argv)) |
557 sys.exit(main(sys.argv)) |