17db96d56Sopenharmony_ci#! /usr/bin/env python3 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci# Module ndiff version 1.7.0 47db96d56Sopenharmony_ci# Released to the public domain 08-Dec-2000, 57db96d56Sopenharmony_ci# by Tim Peters (tim.one@home.com). 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci# Provided as-is; use at your own risk; no warranty; no promises; enjoy! 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci# ndiff.py is now simply a front-end to the difflib.ndiff() function. 107db96d56Sopenharmony_ci# Originally, it contained the difflib.SequenceMatcher class as well. 117db96d56Sopenharmony_ci# This completes the raiding of reusable code from this formerly 127db96d56Sopenharmony_ci# self-contained script. 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ci"""ndiff [-q] file1 file2 157db96d56Sopenharmony_ci or 167db96d56Sopenharmony_cindiff (-r1 | -r2) < ndiff_output > file1_or_file2 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciPrint a human-friendly file difference report to stdout. Both inter- 197db96d56Sopenharmony_ciand intra-line differences are noted. In the second form, recreate file1 207db96d56Sopenharmony_ci(-r1) or file2 (-r2) on stdout, from an ndiff report on stdin. 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciIn the first form, if -q ("quiet") is not specified, the first two lines 237db96d56Sopenharmony_ciof output are 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci-: file1 267db96d56Sopenharmony_ci+: file2 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ciEach remaining line begins with a two-letter code: 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci "- " line unique to file1 317db96d56Sopenharmony_ci "+ " line unique to file2 327db96d56Sopenharmony_ci " " line common to both files 337db96d56Sopenharmony_ci "? " line not present in either input file 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ciLines beginning with "? " attempt to guide the eye to intraline 367db96d56Sopenharmony_cidifferences, and were not present in either input file. These lines can be 377db96d56Sopenharmony_ciconfusing if the source files contain tab characters. 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ciThe first file can be recovered by retaining only lines that begin with 407db96d56Sopenharmony_ci" " or "- ", and deleting those 2-character prefixes; use ndiff with -r1. 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ciThe second file can be recovered similarly, but by retaining only " " and 437db96d56Sopenharmony_ci"+ " lines; use ndiff with -r2; or, on Unix, the second file can be 447db96d56Sopenharmony_cirecovered by piping the output through 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci sed -n '/^[+ ] /s/^..//p' 477db96d56Sopenharmony_ci""" 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci__version__ = 1, 7, 0 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ciimport difflib, sys 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_cidef fail(msg): 547db96d56Sopenharmony_ci out = sys.stderr.write 557db96d56Sopenharmony_ci out(msg + "\n\n") 567db96d56Sopenharmony_ci out(__doc__) 577db96d56Sopenharmony_ci return 0 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci# open a file & return the file object; gripe and return 0 if it 607db96d56Sopenharmony_ci# couldn't be opened 617db96d56Sopenharmony_cidef fopen(fname): 627db96d56Sopenharmony_ci try: 637db96d56Sopenharmony_ci return open(fname) 647db96d56Sopenharmony_ci except IOError as detail: 657db96d56Sopenharmony_ci return fail("couldn't open " + fname + ": " + str(detail)) 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci# open two files & spray the diff to stdout; return false iff a problem 687db96d56Sopenharmony_cidef fcompare(f1name, f2name): 697db96d56Sopenharmony_ci f1 = fopen(f1name) 707db96d56Sopenharmony_ci f2 = fopen(f2name) 717db96d56Sopenharmony_ci if not f1 or not f2: 727db96d56Sopenharmony_ci return 0 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci a = f1.readlines(); f1.close() 757db96d56Sopenharmony_ci b = f2.readlines(); f2.close() 767db96d56Sopenharmony_ci for line in difflib.ndiff(a, b): 777db96d56Sopenharmony_ci print(line, end=' ') 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci return 1 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci# crack args (sys.argv[1:] is normal) & compare; 827db96d56Sopenharmony_ci# return false iff a problem 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_cidef main(args): 857db96d56Sopenharmony_ci import getopt 867db96d56Sopenharmony_ci try: 877db96d56Sopenharmony_ci opts, args = getopt.getopt(args, "qr:") 887db96d56Sopenharmony_ci except getopt.error as detail: 897db96d56Sopenharmony_ci return fail(str(detail)) 907db96d56Sopenharmony_ci noisy = 1 917db96d56Sopenharmony_ci qseen = rseen = 0 927db96d56Sopenharmony_ci for opt, val in opts: 937db96d56Sopenharmony_ci if opt == "-q": 947db96d56Sopenharmony_ci qseen = 1 957db96d56Sopenharmony_ci noisy = 0 967db96d56Sopenharmony_ci elif opt == "-r": 977db96d56Sopenharmony_ci rseen = 1 987db96d56Sopenharmony_ci whichfile = val 997db96d56Sopenharmony_ci if qseen and rseen: 1007db96d56Sopenharmony_ci return fail("can't specify both -q and -r") 1017db96d56Sopenharmony_ci if rseen: 1027db96d56Sopenharmony_ci if args: 1037db96d56Sopenharmony_ci return fail("no args allowed with -r option") 1047db96d56Sopenharmony_ci if whichfile in ("1", "2"): 1057db96d56Sopenharmony_ci restore(whichfile) 1067db96d56Sopenharmony_ci return 1 1077db96d56Sopenharmony_ci return fail("-r value must be 1 or 2") 1087db96d56Sopenharmony_ci if len(args) != 2: 1097db96d56Sopenharmony_ci return fail("need 2 filename args") 1107db96d56Sopenharmony_ci f1name, f2name = args 1117db96d56Sopenharmony_ci if noisy: 1127db96d56Sopenharmony_ci print('-:', f1name) 1137db96d56Sopenharmony_ci print('+:', f2name) 1147db96d56Sopenharmony_ci return fcompare(f1name, f2name) 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci# read ndiff output from stdin, and print file1 (which=='1') or 1177db96d56Sopenharmony_ci# file2 (which=='2') to stdout 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_cidef restore(which): 1207db96d56Sopenharmony_ci restored = difflib.restore(sys.stdin.readlines(), which) 1217db96d56Sopenharmony_ci sys.stdout.writelines(restored) 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ciif __name__ == '__main__': 1247db96d56Sopenharmony_ci args = sys.argv[1:] 1257db96d56Sopenharmony_ci if "-profile" in args: 1267db96d56Sopenharmony_ci import profile, pstats 1277db96d56Sopenharmony_ci args.remove("-profile") 1287db96d56Sopenharmony_ci statf = "ndiff.pro" 1297db96d56Sopenharmony_ci profile.run("main(args)", statf) 1307db96d56Sopenharmony_ci stats = pstats.Stats(statf) 1317db96d56Sopenharmony_ci stats.strip_dirs().sort_stats('time').print_stats() 1327db96d56Sopenharmony_ci else: 1337db96d56Sopenharmony_ci main(args) 134