Created
February 2, 2012 21:38
-
-
Save jlehtoma/1725931 to your computer and use it in GitHub Desktop.
soRvi-dev post-commit hook
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/env python | |
# This goes to GIT_ROOT/.git/hooks | |
import os | |
import shutil | |
import sys | |
from ConfigParser import NoSectionError | |
try: | |
from git import Repo, InvalidGitRepositoryError | |
except ImportError: | |
print("GitPython not available, can't do post-commit processing") | |
sys.exit(1) | |
GIT_ROOT = os.path.abspath(".") | |
if not os.path.exists(GIT_ROOT): | |
print("ERROR: Source dir %s does not exist." % GIT_ROOT) | |
sys.exit(1) | |
try: | |
# Finally source directory must also host a git repo | |
repo = Repo(GIT_ROOT) | |
except InvalidGitRepositoryError: | |
print("ERROR: %s dir is not a git repository" % GIT_ROOT) | |
sys.exit(1) | |
config = repo.config_reader() | |
try: | |
SVN_TARGET = config.get_value("svn-mirror", "target") | |
SAFE = config.get_value("svn-mirror", "safemode") | |
LIST = config.get_value("svn-mirror", "listmode") | |
except NoSectionError, e: | |
print("ERROR: %s" % e) | |
sys.exit(1) | |
ref_name = str(repo.head.reference) | |
if ref_name == 'master': | |
print("Commit on master, mirroring changes") | |
# Get the informarion from the last git commit as String and split | |
# by newlines | |
last_commit = repo.git.whatchanged(-1, oneline=True).split("\n") | |
# Further process each line by splitting with whitespace | |
last_commit = [item.split(" ") for item in last_commit] | |
# Split each line component with tab, only the last component should have | |
# tab as a separator (e.g. "M\tdir/file") | |
last_commit = [[subitem.split("\t") for subitem in item] for item in last_commit] | |
# Create an empty dictionary -> 'A'(dded), 'M'(odified) and 'D'(eleted) | |
# will be the keys, relative filepaths (relative to the git root) the | |
# values | |
changed_files = {} | |
for tag in ['A', 'M', 'D']: | |
# Initialize each key (commit category) with an empty list | |
changed_files[tag] = [] | |
# Assign each file into a corresponding commit category | |
for item in last_commit: | |
# The first item in the commit set is the commit message, which only | |
# has 1 item | |
if len(item[-1]) > 1: | |
# Relative file name | |
_file = item[-1][1] | |
# Commit tag ('A', 'M' or 'D') | |
tag = item[-1][0] | |
changed_files[tag].append(_file) | |
# List all the files and commit category tags if requested | |
if LIST: | |
print("Content of the last commit") | |
if changed_files['A']: | |
print('Added files:') | |
for _file in changed_files['A']: | |
print('\t%s' % _file) | |
if changed_files['M']: | |
print('Modified files:') | |
for _file in changed_files['M']: | |
print('\t%s' % _file) | |
if changed_files['D']: | |
print('Deleted files:') | |
for _file in changed_files['D']: | |
print('\t%s' % _file) | |
# Target directory must exist. NOTE: other than checking whether the target | |
# (root) directory exists, the script makes no further checks whether the | |
# folder structure really mirrors that of the source dir. The relative | |
# path *within* the target directory comes from the relative path in the | |
# source directory (as given by git's commit information). If the target | |
# directory does not have a similar folder structure an error will be | |
# raised when trying to copy/delete the file in the target directory. | |
if os.path.exists(SVN_TARGET): | |
print("Target directory: %s" % SVN_TARGET) | |
else: | |
print("ERROR: Target dir %s does not exist." % SVN_TARGET) | |
sys.exit(1) | |
for _file in changed_files['A']: | |
# Adding means there is no counterpart in the target directory so | |
# we will just copy the file over to the target directory | |
source_file = os.path.join(GIT_ROOT, _file) | |
target_file = os.path.join(SVN_TARGET, _file) | |
if SAFE: | |
go = raw_input("Copy file %s? [Y/n]" % source_file) | |
else: | |
go = 'Y' | |
if go not in ['n', 'N', 'no', 'NO']: | |
print("Copying %s -> %s" % (source_file, target_file)) | |
try: | |
shutil.copy2(source_file, target_file) | |
except IOError, e: | |
print("ERROR: Could not copy file %s" % e) | |
for _file in changed_files['M']: | |
# Modifiying means that there should be a counterpart in the target | |
# directory. We will try to overwrite the existing file. | |
source_file = os.path.join(GIT_ROOT, _file) | |
target_file = os.path.join(SVN_TARGET, _file) | |
# See if the target file truly exists, if it does not, copy the | |
# the source file regardless | |
if os.path.exists(target_file): | |
if SAFE: | |
go = raw_input("Overwrite file %s? [Y/n]" % target_file) | |
else: | |
go = 'Y' | |
if go not in ['n', 'N', 'no', 'NO']: | |
print("Overwriting %s -> %s" % (source_file, target_file)) | |
try: | |
shutil.copy2(source_file, target_file) | |
except IOError, e: | |
print("ERROR: Could not overwrite file %s" % e) | |
else: | |
print("Target file %s not found" % target_file) | |
if SAFE: | |
go = raw_input("Copy file %s? [Y/n]" % source_file) | |
else: | |
go = 'Y' | |
if go not in ['n', 'N', 'no', 'NO']: | |
print("Copying %s -> %s" % (source_file, target_file)) | |
try: | |
shutil.copy2(source_file, target_file) | |
except IOError, e: | |
print("ERROR: Could not copy file %s" % e) | |
for _file in changed_files['D']: | |
# Deleting means that there should be a counterpart in the target | |
# directory. We will try to delete the existing file. | |
target_file = os.path.join(SVN_TARGET, _file) | |
if os.path.exists(target_file): | |
if SAFE: | |
go = raw_input("Delete file %s? [Y/n]" % target_file) | |
else: | |
go = 'Y' | |
if go not in ['n', 'N', 'no', 'NO']: | |
print("Deleting %s" % target_file) | |
try: | |
os.remove(target_file) | |
except OSError, e: | |
print("ERROR: Could not delete file %s" % e) | |
else: | |
print("File %s not found" % target_file) | |
print "\nCopying finished." | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment