From 506730a1be916711b8f5a34a2a9cc11f6cc09e45 Mon Sep 17 00:00:00 2001 From: Matt Behrens Date: Tue, 4 Feb 2014 20:29:47 -0500 Subject: add commentary and replace tabs with spaces --- bin/jsonpatch | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'bin') diff --git a/bin/jsonpatch b/bin/jsonpatch index 0961d1e..eb8bdb3 100755 --- a/bin/jsonpatch +++ b/bin/jsonpatch @@ -14,14 +14,14 @@ parser = argparse.ArgumentParser( parser.add_argument('ORIGINAL', type=argparse.FileType('r'), help='Original file') parser.add_argument('PATCH', type=argparse.FileType('r'), - nargs='?', default=sys.stdin, + nargs='?', default=sys.stdin, help='Patch file (read from stdin if omitted)') parser.add_argument('--indent', type=int, default=None, help='Indent output by n spaces') parser.add_argument('-b', '--backup', action='store_true', - help='Back up ORIGINAL if modifying in-place') + help='Back up ORIGINAL if modifying in-place') parser.add_argument('-i', '--in-place', action='store_true', - help='Modify ORIGINAL in-place instead of to stdout') + help='Modify ORIGINAL in-place instead of to stdout') parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + jsonpatch.__version__) @@ -42,31 +42,61 @@ def patch_files(): if args.in_place: dirname = os.path.abspath(os.path.dirname(args.ORIGINAL.name)) + try: + # Attempt to replace the file atomically. We do this by + # creating a temporary file in the same directory as the + # original file so we can atomically move the new file over + # the original later. + fd, pathname = tempfile.mkstemp(dir=dirname) fp = os.fdopen(fd, 'w') atomic = True + except OSError: + # We failed to create the temporary file for an atomic + # replace, so fall back to non-atomic mode by backing up + # the original (if desired) and writing a new file. + if args.backup: os.rename(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') fp = open(args.ORIGINAL.name, 'w') atomic = False else: + # Since we're not replacing the original file in-place, write + # the modified JSON to stdout instead. + fp = sys.stdout + # By this point we have some sort of file object we can write the + # modified JSON to. + json.dump(result, fp, indent=args.indent) fp.write('\n') if args.in_place: + # Close the new file. If we aren't replacing atomically, this + # is our last step, since everything else is already in place. + fp.close() + if atomic: try: + # Complete the atomic replace by linking the original + # to a backup (if desired), fixing up the permissions + # on the temporary file, and moving it into place. + if args.backup: os.link(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') os.chmod(pathname, os.stat(args.ORIGINAL.name).st_mode) os.rename(pathname, args.ORIGINAL.name) + except OSError: + # In the event we could not actually do the atomic + # replace, unlink the original to move it out of the + # way and finally move the temporary file into place. + os.unlink(args.ORIGINAL.name) os.rename(pathname, args.ORIGINAL.name) -- cgit v1.2.1