Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

web: when saving changes from editing, do a proper git merge.

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...
commit e404e72fb5b542ec280af0f78305ad0a9b89045e 1 parent a4851ae
@apenwarr authored
View
3  cmd/commit-cmd.py
@@ -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')
+
View
7 cmd/pull-cmd.py
@@ -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)
View
7 cmd/push-cmd.py
@@ -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()
View
3  cmd/resolve-cmd.py
@@ -14,5 +14,4 @@
repo.check_dir()
repo.commit('Commit (resolve)')
-sys.exit(repo.resolve())
-
+repo.resolve()
View
9 cmd/sync-cmd.py
@@ -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()
View
8 cmd/web-cmd.py
@@ -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])
View
93 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 /
@@ -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'])
View
2  templates/edit.html
@@ -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;
}
};

0 comments on commit e404e72

Please sign in to comment.
Something went wrong with that request. Please try again.