Skip to content

Commit

Permalink
web: when saving changes from editing, do a proper git merge.
Browse files Browse the repository at this point in the history
Otherwise two people could start editing at once, and save one after the
other.  The second would clobber the first's changes.

Now both saves will have the same parent git commit, and we'll merge them
together using our standard resolve() mechanism.

While we're here, let's also clean up repo.py to throw exceptions instead of
using return values.  The latter are very un-pythonic (and nobody was
checking the return values half the time anyway, which is pretty bad).
  • Loading branch information
apenwarr committed Jul 9, 2010
1 parent a4851ae commit e404e72
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 39 deletions.
3 changes: 2 additions & 1 deletion cmd/commit-cmd.py
Expand Up @@ -14,4 +14,5 @@
if extra:
o.fatal('no arguments expected')

sys.exit(repo.commit(msg = opt.message or 'Commit'))
repo.commit(msg = opt.message or 'Commit')

7 changes: 3 additions & 4 deletions cmd/pull-cmd.py
Expand Up @@ -13,11 +13,10 @@
o.fatal('no arguments expected')

repo.check_dir()
rv = repo.commit('Commit (pull)')
rv += repo.resolve()
repo.commit('Commit (pull)')
repo.resolve()
if repo.remote_url():
rv += repo.pull()
repo.pull()
else:
log('No remote repository configured.\n')
sys.exit(rv)

7 changes: 3 additions & 4 deletions cmd/push-cmd.py
Expand Up @@ -13,7 +13,6 @@
o.fatal('no arguments expected')

repo.check_dir()
rv = repo.commit('Commit (push)')
rv += repo.resolve()
rv += repo.push()
sys.exit(rv)
repo.commit('Commit (push)')
repo.resolve()
repo.push()
3 changes: 1 addition & 2 deletions cmd/resolve-cmd.py
Expand Up @@ -14,5 +14,4 @@

repo.check_dir()
repo.commit('Commit (resolve)')
sys.exit(repo.resolve())

repo.resolve()
9 changes: 4 additions & 5 deletions cmd/sync-cmd.py
Expand Up @@ -13,8 +13,7 @@
o.fatal('no arguments expected')

repo.check_dir()
rv = repo.commit('Commit (sync)')
rv += repo.resolve()
rv += repo.pull()
rv += repo.push()
sys.exit(rv)
repo.commit('Commit (sync)')
repo.resolve()
repo.pull()
repo.push()
8 changes: 6 additions & 2 deletions cmd/web-cmd.py
Expand Up @@ -149,13 +149,17 @@ def get(self):
self.render('edit.html', subpage='/sched/edit',
title = 'Edit Schedule',
tasks = get_sched(),
text = open(mainpath).read())
text = open(mainpath).read(),
commitid = repo.head_commitid())

def post(self):
repo.commit()
t = str(self.request.body)
open(mainpath, 'wb').write(t)
self.write('ok')
repo.commit('Edited (web)')

cid = repo.vcommit('Edited (web)', self.get_argument('commitid'))
repo.resolve(cid)
print 'Updated schedule (%s).' % repr(t[:40])


Expand Down
93 changes: 73 additions & 20 deletions lib/bog/repo.py
@@ -1,9 +1,27 @@
import os, subprocess, glob
import os, subprocess, glob, tempfile
from bog.helpers import *


def _run(argv):
rv = subprocess.call(argv)
if rv:
raise Exception('%r returned %d' % (argv, rv))


def _grab(argv, stdin=[]):
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
for i in stdin:
p.stdin.write(i)
p.stdin.close()
data = p.stdout.read().strip()
rv = p.wait()
if rv:
raise Exception('%r returned %d' % (argv, rv))
return data


def get_dir():
bd = os.getenv('BOG_DIR')
bd = os.environ.get('BOG_DIR')
if bd:
return os.path.join(bd, '') # ensure terminating /

Expand All @@ -27,38 +45,73 @@ def check_dir():
def remote_url():
bogdir = check_dir()
os.environ['GIT_DIR'] = os.path.join(bogdir, '.git')
p = subprocess.Popen(['git', 'config', 'remote.origin.url'],
stdout=subprocess.PIPE)
oldurl = p.stdout.read().strip()
p.wait()
oldurl = _grab(['git', 'config', 'remote.origin.url'])
return oldurl or None


def commit(msg='Checkpoint'):
def head_commitid():
bogdir = check_dir()
os.environ['GIT_DIR'] = os.path.join(bogdir, '.git')
subprocess.call(['git', 'add', '-A', bogdir])
rv = subprocess.call(['git', 'commit', '-m', msg])
subprocess.call(['git', 'branch', 'merge-me'],
stderr=open('/dev/null', 'w'))
return rv
try:
line = _grab(['git', 'show-ref', '--head', 'HEAD'])
commit = line.split()[0]
except Exception:
commit = None
return commit or None


def tree_from_commit(cid):
return _grab(['git', 'rev-parse', '%s:' % cid])


def vcommit(msg, parent):
bogdir = check_dir()
os.environ['GIT_DIR'] = os.path.join(bogdir, '.git')
(tmpfd,tmpname) = tempfile.mkstemp()
try:
os.environ['GIT_INDEX_FILE'] = tmpname
if not parent:
oldtid = _grab(['git', 'mktree']) # empty tree
else:
oldtid = tree_from_commit(parent)
_run(['git', 'read-tree', oldtid])
_run(['git', 'add', '-A', bogdir])
tid = _grab(['git', 'write-tree'])
if oldtid != tid:
cid = _grab(['git', 'commit-tree', tid] +
(parent and ['-p', parent] or []),
stdin = [msg])
else:
cid = parent
del os.environ['GIT_INDEX_FILE']
headcommit = head_commitid()
if headcommit:
_run(['git', 'reset', '--hard', headcommit])
return cid
finally:
if os.environ.get('GIT_INDEX_FILE') != None:
del os.environ['GIT_INDEX_FILE']
os.close(tmpfd)


def commit(msg='Checkpoint'):
cid = vcommit(msg, head_commitid())
resolve(cid)


def resolve():
def resolve(merge_from='merge-me'):
gitdir = os.path.join(check_dir(), '.git')
os.environ['GIT_DIR'] = gitdir
rv = subprocess.call(['git', 'merge', 'merge-me'])
rv += subprocess.call(['git', 'push', gitdir, 'master:merge-me'])
return rv
_run(['git', 'merge', '--', merge_from])
_run(['git', 'push', gitdir, 'master:merge-me'])


def push():
os.environ['GIT_DIR'] = os.path.join(check_dir(), '.git')
return subprocess.call(['git', 'push', 'origin', 'master:merge-me'])
_run(['git', 'push', 'origin', 'master:merge-me'])


def pull():
os.environ['GIT_DIR'] = os.path.join(check_dir(), '.git')
rv = subprocess.call(['git', 'pull', 'origin', 'master'])
rv += subprocess.call(['git', 'pull', 'origin', 'merge-me'])
return rv
_run(['git', 'pull', 'origin', 'master'])
_run(['git', 'pull', 'origin', 'merge-me'])
2 changes: 1 addition & 1 deletion templates/edit.html
Expand Up @@ -69,7 +69,7 @@
sched_post = function() {
var v = $('#schedtext').val();
if (v != oldtext) {
$.post('/sched/edit', v);
$.post('/sched/edit?commitid={{commitid}}', v);
oldtext = v;
}
};
Expand Down

0 comments on commit e404e72

Please sign in to comment.