hgsync /

import os
import logging, logging.config
from datetime import datetime
from functools import wraps
from mercurial import cmdutil, ui, commands, patch, hg

log = logging.getLogger('SyncLog')
def auto_branch_name(dest):
    "generates branch name based on"
    for piece in dest.split(os.path.sep):
        if piece != '': break
    now =
    d, t =, now.time()
    dstr = '/'.join([str(d.year)[2:],
    tstr = ':'.join([str(t.hour).zfill(2),
    return '-'.join([dstr, tstr, piece])

def init(dest):
    "hg init dest"
    return commands.init(ui.ui(), dest=dest)

def diff(dest, u=ui.ui()):
    "prints diff log"
    repo = hg.repository(ui, dest)
    m = cmdutil.match(repo)
    node1, node2 = cmdutil.revpair(repo, 0)
    it = patch.diff(repo, node1, node2, match=m)
    if len(list(it)) > 0:
        for line in it:
            log.debug(line) # TODO: output to mail log
        return 1
    else: return 0

def commit(dest, comment, u=ui.ui()):
    "hg commit""commiting for %s" % dest)"Message: %s" % comment)
    repo = hg.repository(u, dest)
    return commands.commit(u, repo, message=comment, addremove=True)

def push(src, dest, u=ui.ui()):
    "hg push -f"
    src_repo = hg.repository(u, src)
    dest_repo = hg.repository(u, dest)
    return src_repo.push(dest_repo, force=True)

def update_branch(dest, br_name=None, u=ui.ui()):
    "hg update br_name"
    repo = hg.repository(u, dest)
    return commands.update(u, repo, node=br_name)

def branch(dest, br_name, u=ui.ui()):
    "hg branch br_name"
    repo = hg.repository(u, dest)
    return commands.branch(u, repo, label=br_name)

def autobranch(dest, u=ui.ui()):
    "Create new branch if repo is changed"
    if repo_is_changed(dest, u):
        br_name = auto_branch_name(dest)
        print "branch to %s, name %s" % (dest, br_name)
        branch(dest, br_name, u=u)
        commit(dest, 'auto commit', u)
        update_branch(dest, br_name='default', u=u)
        return True
        update_branch(dest, br_name='default', u=u)
        return False

def repo_is_changed(dest, u=ui.ui()):
    "'hg status' stripped down. Return true if the repo is changed."
    repo = hg.repository(u, dest)
    node1, node2 = cmdutil.revpair(repo, 0)
    m = cmdutil.match(repo)
    stat = repo.status(node1, node2, m, False, False, True)
    return len(filter(lambda x: len(x)!=0, stat)) != 0

def autosync(project_dir, syncgroup, u=ui.ui()):
    for syncdir in syncgroup:
        lockflag = os.path.join(syncdir, 'LOCKED.FLG')
        if os.path.exists(lockflag):
  "Skipping locked %s" % syncdir)
            continue"Synchronizing %s" % syncdir)
        push(project_dir, syncdir, u)
        branched = autobranch(syncdir, u)
        if branched:
  "Auto branch created on %s" % syncdir)
  "Synchronizing back..")
            autosync(syncdir, syncgroup, u)