Show More
@@ -0,0 +1,61 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | cp "$TESTDIR"/../contrib/simplemerge . | |||
|
4 | ||||
|
5 | echo base > base | |||
|
6 | ||||
|
7 | echo local > local | |||
|
8 | cat base >> local | |||
|
9 | cp local orig | |||
|
10 | ||||
|
11 | cat base > other | |||
|
12 | echo other >> other | |||
|
13 | ||||
|
14 | echo '% changing local directly' | |||
|
15 | python simplemerge local base other && echo "merge succeeded" | |||
|
16 | cat local | |||
|
17 | cp orig local | |||
|
18 | ||||
|
19 | echo '% printing to stdout' | |||
|
20 | python simplemerge -p local base other | |||
|
21 | echo ' local:' | |||
|
22 | cat local | |||
|
23 | ||||
|
24 | echo '% conflicts' | |||
|
25 | cp base conflict-local | |||
|
26 | cp other conflict-other | |||
|
27 | echo not other >> conflict-local | |||
|
28 | echo end >> conflict-local | |||
|
29 | echo end >> conflict-other | |||
|
30 | python simplemerge -p conflict-local base conflict-other || echo "merge failed" | |||
|
31 | ||||
|
32 | echo '% --no-minimal' | |||
|
33 | python simplemerge -p --no-minimal conflict-local base conflict-other | |||
|
34 | ||||
|
35 | echo '% 1 label' | |||
|
36 | python simplemerge -p -L foo conflict-local base conflict-other | |||
|
37 | ||||
|
38 | echo '% 2 labels' | |||
|
39 | python simplemerge -p -L foo -L bar conflict-local base conflict-other | |||
|
40 | ||||
|
41 | echo '% too many labels' | |||
|
42 | python simplemerge -p -L foo -L bar -L baz conflict-local base conflict-other | |||
|
43 | ||||
|
44 | echo '% binary file' | |||
|
45 | printf '\x00' > binary-local | |||
|
46 | cat orig >> binary-local | |||
|
47 | python simplemerge -p binary-local base other | |||
|
48 | ||||
|
49 | echo '% binary file --text' | |||
|
50 | python simplemerge -a -p binary-local base other | |||
|
51 | ||||
|
52 | echo '% help' | |||
|
53 | python simplemerge --help | |||
|
54 | ||||
|
55 | echo '% wrong number of arguments' | |||
|
56 | python simplemerge | |||
|
57 | ||||
|
58 | echo '% bad option' | |||
|
59 | python simplemerge --foo -p local base other | |||
|
60 | ||||
|
61 | exit 0 |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
@@ -19,8 +19,10 b'' | |||||
19 | # mbp: "you know that thing where cvs gives you conflict markers?" |
|
19 | # mbp: "you know that thing where cvs gives you conflict markers?" | |
20 | # s: "i hate that." |
|
20 | # s: "i hate that." | |
21 |
|
21 | |||
|
22 | from mercurial import demandimport | |||
|
23 | demandimport.enable() | |||
22 |
|
24 | |||
23 | from mercurial import util, mdiff |
|
25 | from mercurial import util, mdiff, fancyopts | |
24 | from mercurial.i18n import _ |
|
26 | from mercurial.i18n import _ | |
25 |
|
27 | |||
26 |
|
28 | |||
@@ -97,6 +99,7 b' class Merge3Text(object):' | |||||
97 | reprocess=False): |
|
99 | reprocess=False): | |
98 | """Return merge in cvs-like form. |
|
100 | """Return merge in cvs-like form. | |
99 | """ |
|
101 | """ | |
|
102 | self.conflicts = False | |||
100 | newline = '\n' |
|
103 | newline = '\n' | |
101 | if len(self.a) > 0: |
|
104 | if len(self.a) > 0: | |
102 | if self.a[0].endswith('\r\n'): |
|
105 | if self.a[0].endswith('\r\n'): | |
@@ -126,6 +129,7 b' class Merge3Text(object):' | |||||
126 | for i in range(t[1], t[2]): |
|
129 | for i in range(t[1], t[2]): | |
127 | yield self.b[i] |
|
130 | yield self.b[i] | |
128 | elif what == 'conflict': |
|
131 | elif what == 'conflict': | |
|
132 | self.conflicts = True | |||
129 | yield start_marker + newline |
|
133 | yield start_marker + newline | |
130 | for i in range(t[3], t[4]): |
|
134 | for i in range(t[3], t[4]): | |
131 | yield self.a[i] |
|
135 | yield self.a[i] | |
@@ -439,21 +443,115 b' class Merge3(Merge3Text):' | |||||
439 | Merge3Text.__init__(self, basetext, atext, btext, base, a, b) |
|
443 | Merge3Text.__init__(self, basetext, atext, btext, base, a, b) | |
440 |
|
444 | |||
441 |
|
445 | |||
442 | def main(argv): |
|
446 | def simplemerge(local, base, other, **opts): | |
443 | # as for diff3 and meld the syntax is "MINE BASE OTHER" |
|
447 | def readfile(filename): | |
444 | a = file(argv[1], 'rt').readlines() |
|
448 | f = open(filename, "rb") | |
445 | base = file(argv[2], 'rt').readlines() |
|
449 | text = f.read() | |
446 | b = file(argv[3], 'rt').readlines() |
|
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 | |||
447 |
|
496 | |||
448 | m3 = Merge3(base, a, b) |
|
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') | |||
449 |
|
518 | |||
450 | #for sr in m3.find_sync_regions(): |
|
519 | out_opts = [] | |
451 | # print sr |
|
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.""" | |||
452 |
|
530 | |||
453 | # sys.stdout.writelines(m3.merge_lines(name_a=argv[1], name_b=argv[3])) |
|
531 | def main(argv): | |
454 | sys.stdout.writelines(m3.merge_annotated()) |
|
532 | try: | |
455 |
|
533 | opts = {} | ||
|
534 | try: | |||
|
535 | args = fancyopts.fancyopts(argv[1:], options, opts) | |||
|
536 | except fancyopts.getopt.GetoptError, e: | |||
|
537 | raise ParseError(e) | |||
|
538 | if opts['help']: | |||
|
539 | showhelp() | |||
|
540 | return 0 | |||
|
541 | if len(args) != 3: | |||
|
542 | raise ParseError(_('wrong number of arguments')) | |||
|
543 | return simplemerge(*args, **opts) | |||
|
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)) |
General Comments 0
You need to be logged in to leave comments.
Login now