diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/jsonpatch | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/bin/jsonpatch b/bin/jsonpatch index 613f703..0961d1e 100755 --- a/bin/jsonpatch +++ b/bin/jsonpatch @@ -18,6 +18,8 @@ parser.add_argument('PATCH', type=argparse.FileType('r'), 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') parser.add_argument('-i', '--in-place', action='store_true', help='Modify ORIGINAL in-place instead of to stdout') parser.add_argument('-v', '--version', action='version', @@ -37,18 +39,36 @@ def patch_files(): doc = json.load(args.ORIGINAL) patch = json.load(args.PATCH) result = jsonpatch.apply_patch(doc, patch) + if args.in_place: dirname = os.path.abspath(os.path.dirname(args.ORIGINAL.name)) - fd, pathname = tempfile.mkstemp(dir=dirname) - fp = os.fdopen(fd, 'w') + try: + fd, pathname = tempfile.mkstemp(dir=dirname) + fp = os.fdopen(fd, 'w') + atomic = True + except OSError: + if args.backup: + os.rename(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') + fp = open(args.ORIGINAL.name, 'w') + atomic = False + else: fp = sys.stdout + json.dump(result, fp, indent=args.indent) + fp.write('\n') + if args.in_place: fp.close() - 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) + if atomic: + try: + 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: + os.unlink(args.ORIGINAL.name) + os.rename(pathname, args.ORIGINAL.name) if __name__ == "__main__": |