Skip to content

Instantly share code, notes, and snippets.

@jlehtoma
Created February 2, 2012 21:38
Show Gist options
  • Save jlehtoma/1725931 to your computer and use it in GitHub Desktop.
Save jlehtoma/1725931 to your computer and use it in GitHub Desktop.
soRvi-dev post-commit hook
#!/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