Created
April 16, 2009 06:52
-
-
Save mintchaos/96275 to your computer and use it in GitHub Desktop.
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 | |
# | |
# some bits stolen from Travis Cline's http://github.com/traviscline/git-branchdescriptions | |
# | |
import os | |
import re | |
import sys | |
from subprocess import Popen, PIPE | |
HELP_TEXT = """ | |
git-sync is quick hack rsync wrapper that's aware of git branches. | |
You must set sync.location to be an rsync path where your branches will | |
sync to such as: `git config sync.location user@servername:path/to/project/` | |
git sync will look in that path for folders with names that match your current | |
branch. If there are it'll rsync your working directory into that folder. If it | |
can't find a branch-named folder it'll sync your working directory to | |
sync.location/master. | |
It has two optional options. | |
`git sync check` | |
Will tell you where the current working directory will sync to. | |
`git sync create` | |
Will create a remote folder for your current branch in the remote directory. | |
`git sync` | |
Will run the sync. | |
WARNING: git-sync is potentially dangerous. it will delete your data if pointed | |
at the wrong directory. Please run `git sync check` first and be careful while | |
setting your paths. | |
It's also not backed by a test suite and I'm parsing arguments dumb. Whee! | |
---- | |
Requires GitPython | |
`easy_install/pip GitPython` | |
""" | |
try: # conditional import to allow setup.py to grab __version__ | |
import git | |
from git.errors import GitCommandError | |
except ImportError: | |
pass | |
def _santitize_branch_name(name): | |
""" | |
Strips down a git branch name to plain text. | |
""" | |
s = name.strip('*').strip().split()[0] # get first part of string sans '*' | |
s = _strip_ansi_escaped_chars(s) # remove color formatting if it exists | |
return s | |
def _strip_ansi_escaped_chars(s): | |
""" | |
Strips ANSI escaped characters from a string. | |
""" | |
esc = '\x1b.+?m' | |
return re.sub(esc+'$', '', re.sub('^'+esc, '', s)) | |
class GitSyncError(Exception): | |
pass | |
class GitSyncMisconfiguredError(GitSyncError): | |
pass | |
class GitSyncInvalidArgumentError(GitSyncError): | |
pass | |
class GitSync(object): | |
def __init__(self, command=None, args=None): | |
repo_path = os.getcwd() | |
self.repo = git.Repo(repo_path) | |
if command in ['check', 'create', None]: | |
self.command = command | |
else: | |
raise GitSyncInvalidArgumentError() | |
self.branch = _santitize_branch_name(self.repo.active_branch) | |
self.remote = self.repo.git.execute(('git', 'config', '--get', 'sync.location'), with_exceptions=False).strip('/') | |
try: | |
self.host, self.path = self.remote.split(':') | |
except ValueError: | |
raise GitSyncMisconfiguredError('\nYou must set sync.location to be an rsync path where your branches will sync to\nExample:\n`git config sync.location user@servername:path/to/project/`') | |
self.master_dir = self.repo.git.execute(('git', 'config', '--get', 'sync.master'), with_exceptions=False) or "master" | |
self.master_path = "%s/%s" % (self.path, self.master_dir) | |
def remote_popen(self, command): | |
return Popen(["ssh", self.host, command], stdout=PIPE) | |
def get_remote_dirs(self): | |
return self.remote_popen('ls %s' % self.path).stdout.read().split() | |
def get_remote_path(self): | |
if self.branch in self.get_remote_dirs(): | |
return "%s/%s" % (self.path, self.branch) | |
else: | |
return self.master_path | |
def sync(self): | |
os.system('rsync -avC --delete --exclude=".git" --include="core" %s/ %s:%s/' % (self.repo.wd, self.host, self.get_remote_path())) | |
def check(self): | |
print "Branch: %s will sync to %s:%s/" % (self.branch, self.host, self.get_remote_path()) | |
def create(self): | |
if self.branch in self.get_remote_dirs(): | |
print "Remote path for %s already exists" % self.branch | |
elif self.master_dir in self.get_remote_dirs(): | |
cmd = 'cp -r %(path)s/%(master)s %(path)s/%(branch)s' % dict(path=self.path, branch=self.branch, master=self.master_dir) | |
print cmd | |
self.remote_popen(cmd) | |
else: | |
self.remote_popen('mkdir -p %s/%s' % (self.path, self.branch)) | |
self.sync() | |
def run(self): | |
if self.command: | |
return getattr(self, self.command)() | |
return self.sync() | |
def run(args): | |
try: | |
command = args[1] | |
except IndexError: | |
command = None | |
try: | |
GitSync(command).run() | |
sys.exit(False) | |
except GitSyncError: | |
print HELP_TEXT | |
sys.exit(True) | |
if __name__ == '__main__': | |
run(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment