summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Behrens <matt@zigg.com>2014-02-04 20:29:47 -0500
committerMatt Behrens <matt@zigg.com>2014-02-04 20:29:47 -0500
commit506730a1be916711b8f5a34a2a9cc11f6cc09e45 (patch)
tree7a77d263bdea859eb10a7cca265aa26d96e24b8f
parent1d285a80286e92bf1f90202032b6b24ecbdd015f (diff)
downloadpython-json-patch-506730a1be916711b8f5a34a2a9cc11f6cc09e45.tar.gz
add commentary and replace tabs with spaces
-rwxr-xr-xbin/jsonpatch36
1 files changed, 33 insertions, 3 deletions
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)