Created
May 1, 2013 22:32
-
-
Save niklasf/5498916 to your computer and use it in GitHub Desktop.
Sample Git update hook that deploys the changed files to the web root.
This file contains 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/python | |
import logging | |
import git | |
import sys | |
import os | |
def main(): | |
""" | |
Update all files according to a diff. | |
""" | |
# Configure logging. | |
logger = logging.getLogger() | |
logger.setLevel(logging.INFO) | |
formatter = logging.Formatter('%(levelname)s: %(message)s') | |
ch = logging.StreamHandler(sys.stdout) | |
ch.setFormatter(formatter) | |
logger.addHandler(ch) | |
# Start. | |
logging.info('Starting update hook.') | |
repo = git.Repo() | |
# Check arguments. | |
logging.debug('Arguments: %s', sys.argv) | |
assert len(sys.argv) == 4 | |
if sys.argv[2] == '0000000000000000000000000000000000000000': | |
sys.argv[2] = repo.git.hash_object('-w', '-t', 'tree', os.devnull) | |
if sys.argv[3] == '0000000000000000000000000000000000000000': | |
sys.argv[3] = repo.git.hash_object('-w', '-t', 'tree', os.devnull) | |
# Iterate over the diff. | |
assert repo.bare == True | |
diff = repo.git.diff('--name-status', sys.argv[2], sys.argv[3]) | |
tree = repo.commit(sys.argv[3]).tree | |
for line in diff.split("\n"): | |
if not line: continue | |
status, file = line.split("\t", 1) | |
assert status in ['A', 'D', 'M'] | |
target = get_target(file) | |
logging.debug('%s %s -> %s', status, file, target) | |
if target: | |
if status == 'D': | |
# Unlink file. | |
os.unlink(target) | |
logging.info('Deleted %s', target) | |
# Remove parent dirs. | |
try: | |
os.removedirs(os.path.dirname(target)) | |
logging.info('Cleaned away parent of %s', target) | |
except OSError: | |
logging.debug('Did not clean away parent of %s', target) | |
else: | |
# Create directories. | |
node = tree[file] | |
assert isinstance(node, git.Blob) | |
if status == 'A': | |
try: | |
os.makedirs(os.path.dirname(target)) | |
logging.info('Created directory for %s', target) | |
except OSError: | |
logging.debug('Did not create directory for %s', target) | |
# Write blob. | |
node.stream_data(open(target, 'w')) | |
logging.info('Wrote %s', target) | |
else: | |
logging.info('Ignored %s', target) | |
# Done. | |
logging.info('update hook finished.') | |
def get_target(file): | |
""" | |
Returns the target by a given filename. | |
""" | |
splitpath = file.split(os.sep) | |
if splitpath[0] in ['www', 'local', 'tools', 'data']: | |
return os.path.join('/var', file) | |
else: | |
return False | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment