Last active
August 29, 2015 14:21
-
-
Save prologic/aa6e46a096e8a0c835d5 to your computer and use it in GitHub Desktop.
A very simple naive VCS in ~130 lines of Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Simple VCS""" | |
from hashlib import sha256 | |
from json import dumps, loads | |
from argparse import ArgumentParser | |
def sha256sum(filename, bufsize=(1024 * 1024)): | |
checksum = sha256() | |
with open(filename, "r") as f: | |
checksum.update(f.read(bufsize)) | |
return checksum.hexdigest() | |
class DB(object): | |
def __init__(self): | |
try: | |
self.data = loads(open(".db", "r").read()) | |
except IOError: | |
self.data = {} | |
def __contains__(self, filename): | |
return filename in self.data | |
def add(self, filename): | |
self.data[filename] = [sha256sum(filename)] | |
def remove(self, filename): | |
del self.data[filename] | |
def update(self, filename): | |
self.data[filename].append(sha256sum(filename)) | |
def status(self): | |
for filename, hashes in self.data.iteritems(): | |
if sha256sum(filename) != hashes[-1]: | |
yield "M", filename | |
def commit(self): | |
for status, filename in self.status(): | |
self.update(filename) | |
def save(self): | |
with open(".db", "w") as f: | |
f.write(dumps(self.data)) | |
def add(db, args): | |
if args.file in db: | |
print("File {} already added!".format(args.file)) | |
return -1 | |
db.add(args.file) | |
def status(db, args): | |
for status, filename in db.status(): | |
print("{0:<4} {1:s}".format(status, filename)) | |
return 0 | |
def commit(db, args): | |
db.commit() | |
return 0 | |
def parse_args(): | |
parser = ArgumentParser(description=__doc__) | |
parser.add_argument( | |
"-q", "--quiet", dest="quiet", | |
action="store_true", default=False, | |
help="Enable quiet mode", | |
) | |
subparsers = parser.add_subparsers( | |
title="Commands", | |
description="Available Commands", | |
help="Description" | |
) | |
# add | |
add_parser = subparsers.add_parser( | |
"add", | |
help="Add a file" | |
) | |
add_parser.set_defaults(func=add) | |
add_parser.add_argument( | |
"file", metavar="FILE", type=str, | |
help="File to add" | |
) | |
# status | |
status_parser = subparsers.add_parser( | |
"status", | |
help="Display status" | |
) | |
status_parser.set_defaults(func=status) | |
# commit | |
commit_parser = subparsers.add_parser( | |
"commit", | |
help="Commit changes" | |
) | |
commit_parser.set_defaults(func=commit) | |
return parser.parse_args() | |
def main(): | |
args = parse_args() | |
db = DB() | |
try: | |
raise SystemExit(args.func(db, args)) | |
finally: | |
db.save() | |
if __name__ == "__main__": | |
main() |
This in response to SO question How to compare two versions of same file (old and new), and detect if there were some changes?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo:
cat .db
: