Commits

Anonymous committed 40dad62

First Commit

Comments (0)

Files changed (4)

+- Group0:
+    prjname: 4CX01P
+    syncdirs: U:\ V:\ X:\ Y:\ Z:\
+- Group1:
+	project: SYNC
+	paths: B: E: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: X: Y: Z: \\192.168.200.224\VOL1\PDLINE
+- Group2:
+	project: 4BK01C
+	paths: K: M: O: R: B: J: Y: I: H: U: E: V:
+- Group3:
+	project: INTEL
+	paths: O:\4X701 R:\4X701 B:\4X701 M:\4X701 K:\4X701 J:\4X701 Z:\4X701 V:\4X701 Y:\4X701 S:\4X701 P:\4X701 U:\4X701 T:\4X701 N:\4X701 I:\4X701 H:\4X701 G:\4X701 E:\4X701 X:\4X701 L:\4X701 \\192.168.200.31\NETWARE\PDLINE\4X701
+- Group4:
+	project: DISCRETE
+	paths: O:\4X701 R:\4X701 B:\4X701 M:\4X701 K:\4X701 J:\4X701 Z:\4X701 V:\4X701 Y:\4X701 S:\4X701 P:\4X701 U:\4X701 T:\4X701 N:\4X701 I:\4X701 H:\4X701 G:\4X701 E:\4X701 X:\4X701 L:\4X701 \\192.168.200.31\NETWARE\PDLINE\4X701
+- Group5:
+	project: 4X701PAI
+	paths: R: B: Y: Z: U: Q: V: S: P: X:
+- Group6:
+	project: 4X701C
+	paths: K: M: O: R: B: J: Y: H: E: U:
+- Group7:
+	project: 4AQ01FG
+	paths: A: D: F: M: K: O: V: Y: J: Z: U: B: S: P: R: T: N: X: H: I: G: E: L:
+- Group8:
+	project: 4AQ01PAI
+	paths: X: Y: V: Q: S: P: Z: A: D: U: T: F: N: \\192.168.200.224\VOL1\PDLINE \\192.168.200.31\NETWARE\PDLINE
+- Group9:
+	project: 4AQ01
+	paths: R: B: U: V: O: M: Z: I: H: S: Y: P: X: G:
+- Group10:
+	project: 4AQ01C
+	paths: M: K: U: V: R: B: H: E: Y: Z:
+- Group11:
+	project: 4R601
+	paths: K: M: O: I: E: H:
+- Group12:
+	project: 4C301
+	paths: K: M: J: O: Y: Z: U: I: H: G: E:
+- Group13:
+	project: 4V101
+	paths: R: B: K: O: M: I: H: E:
+- Group14:
+	project: 4S701
+	paths: O: M: K: I: H: E:
+- Group15:
+	project: 4V601
+	paths: M: O: K: I: H: E:
+- Group16:
+	project: 4Q101F
+	paths: M: O: R: B: I: H:
+- Group17:
+	project: 4Q601
+	paths: K: M: O: J: I: H: G: E:
+- Group18:
+	project: 4Q601FG
+	paths: K: M: O: I: H: E:
+- Group19:
+	project: 4W101
+	paths: O: K: J: U: M: I: H: G: E:
+- Group21:
+	project: 4GN01PAI
+	paths: U: Y: V:  A: F:
+- Group22:
+	project: 4W001FG
+	paths: M: O: V: J: Y: Z: U: S: P: I: H:  G: T: X:
+- Group23:
+	project: 4W001
+	paths: V: Y: Z: Q: U: S: P: X:
+- Group24:
+	project: PAID
+	paths: V: R: B: Z: Y: U: S: P: X: A: D: Q:
+- Group25:
+	project: RUN4W101
+	paths: R: B: M: O: K: J: U: I: H: G: E:
+- Group26:
+	project: 4X201FG
+	paths: M: O: V: I: H:
+- Group27:
+	project: 4Q601V
+	paths: K: M: J: O: I: H: G: E:
+- Group28:
+	project: 4J601FG
+	paths: M: O: V: R: B: J: Z: Y: U: S: P: N: T: I: H: G: X: L:
+- Group29:
+	project: 4J601PAI
+	paths: R: B: Z: Y: U: Q: V: S: P: X:
+- Group30:
+	project: 4AR01
+	paths: R: B: O: K: J: M: U: I: H: G: E:
+- Group31:
+	project: 4AE01
+	paths: O:  U: Y: Z: I: X:
+- Group32:
+	project: 4S701
+	paths: V: R: B:
+- Group33:
+	project: POTOMAC
+	paths: R: Z: Y: Q: U: S: P: X: V:
+- Group34:
+	project: 4W001CA
+	paths: U: Y: Z:
+- Group35:
+	project: RUN4AR01
+	paths: R: B: O: K: J: M: U: I: H: G: E:
+- Group36:
+	project: 4BK01FG
+	paths: M: O: V: J: Z: Y: U: S: P: N: T: R: B: I: H: G: E: X: L: A: F: D: \\192.168.200.31\NETWARE\PDLINE
+- Group37:
+	project: 4BK01PAI
+	paths: R: B: Y: Q: V: S: P: X: Z: U: A: D:
+- Group38:
+	project: 4CX01FG
+	paths: R: B: N: T: U: O: M: I: H: Z: V: P: S: Y: X: L: G: A: D: F: \\192.168.200.224\VOL1\PDLINE
+- Group39:
+	project: 4CN01FG
+	paths: R: B: N: T: U: O: M: I: H: Z: V: P: S: Y: X: L: G: A: D: F: \\192.168.200.224\VOL1\PDLINE
+- Group40:
+	project: 4CN01PAI
+	paths: X: V: U: Z: Y: S: P: Q:  A:  D:  N: T: F: \\192.168.200.224\VOL1\PDLINE
+- Group41:
+	project: 4CN01
+	paths: B: N: Z: H: I: U: Y: X: S: G: T:
+- Group42:
+	project: 4CX01
+	paths: R: B: N: T: U: O: M: I: H: Z: V: P: S: Y: X: L: G:
+- Group43:
+	project: 4CX01PAI
+	paths: Z: Y: U: Q: A: V: S: P: N: T: F: X: D: \\192.168.200.224\VOL1\PDLINE
+- Group44:
+	project: 4CX01P
+	paths: Z: Y: U: Q: V: S: P: X:
+- Group45:
+	project: BTOA
+	paths: Y: Q: V: S: P: X: Z: U: A: D: \\192.168.200.224\VOL1\PDLINE
+- Group46:
+	project: 4EX01C
+	paths: K: M: O: R: B: J: Y: I: H: U: E: V:
+- Group47:
+	project: 4EX01FG
+	paths: M: O: V: J: Z: Y: U: S: P: N: T: R: B: I: H: G: E: X: L: A: F: D:
+- Group48:
+	project: 4EX01PAI
+	paths: R: B: Y: Q: V: S: P: X: Z: U: A: D:
+- Group49:
+	project: 4GN01
+	paths: B: H: I: U: A:  F:  T:
+- Group50:
+	project: 4HH01
+	paths: H: I: U: T: N: Z: F: D: A:
+- Group51:
+	project: 4DA01
+	paths: B: E: H: V:
+- Group52:
+	project: 4HH01PAI
+	paths: U: V: X: Y: Z: P:
+- Group53:
+	project: 4EK01
+	paths: B: T: I: U: H: V: F: D: A:
+- Group54:
+	project: 4EK01FG
+	paths: B: T: I: U: H: V: F: D: A:
+- Group55:
+	project: 4EK01PAI
+	paths: B: T: I: U: H: V: F: D: A:
+- Group56:
+	project: 4EM01
+	paths: B: T: I: U: H: V:
+- Group57:
+	project: 4EM01FG
+	paths: B: T: I: U: H: V:
+- Group58:
+	project: 4EM01PAI
+	paths: B: T: I: U: H: V:
+- Group59:
+	project: 4EN01
+	paths: B: T: I: U: H: V:
+- Group60:
+	project: 4EN01FG
+	paths: B: T: I: U: H: V:
+- Group61:
+	project: 4EN01PAI
+	paths: B: T: I: U: H: V:
+#!/usr/bin/env python
+
+"""HgMon.py -- Monitoring directory change and sync project directories upon
+request. """
+
+import os
+import time
+import yaml
+import logging
+from datetime import datetime
+import logging.handlers
+from subprocess import Popen, PIPE
+from functools import wraps
+
+def auto_branch_name():
+    "generates branch name based on datetime.now()"
+    now = datetime.now()
+    d, t = now.date(), now.time()
+    dstr = str(d.year)[2:] + str(d.month).zfill(2) + str(d.day).zfill(2)
+    tstr = str(t.hour).zfill(2) + str(t.minute).zfill(2) + str(t.second).zfill(2)
+    return dstr + '/' + tstr
+    
+def modify_config(project_dir):
+    "Writes config to do auto update after hg push."
+    config_file = os.path.join(project_dir, '.hg', 'hgrc')
+    with open(config_file, 'a') as cfg:
+        cfg.write('[hooks]\n')
+        cfg.write('changegroup = hg update >&2\n')
+
+def loadconfig(configfile):
+    "Project_dir_group_config_file -> dir group list"
+    with open(configfile) as f:
+        y = yaml.load(f)
+    grouplist = []
+    for entry in y:
+        for k, v in entry.iteritems():
+            sdirs = v['syncdirs'].split()
+            pname = v['prjname']
+            grouplist.append(set(map(lambda x: os.path.join(x, pname), sdirs)))
+    return grouplist
+
+def parse_flag(chflag):
+    "change flag file -> user, comment"
+    with open(chflag, 'r') as fh:
+        user, comment = tuple(
+            fh.readline().strip().split(' ', 1))
+    return user, comment
+    
+def log_hg(func):
+    "Simple logging decorator."
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        logging.basicConfig(filename=os.path.join(os.getcwd(), 'hgmon.log'),
+                            level=logging.DEBUG,
+                            format="[%(asctime)s] - %(message)s",)
+        returncode, stdout, stderr = func(*args, **kwargs)
+        if returncode == 0:
+            logging.info("%s executed with %s" % (func.__name__, args))
+            for line in stdout:
+                logging.debug(line)
+        else:
+            logging.error("%s failed with args %s" %(func.__name__, args))
+            for line in stdout:
+                logging.error(line)
+            for line in stderr:
+                logging.error(line)
+    return wrapper
+
+@log_hg
+def hg_init(d, out=PIPE):
+    "Initiating hg repo"
+    hgcmd = Popen('hg init',
+                     stdout=out, stderr=out, shell=True,
+                     cwd=d,
+                     env={'PATH': os.environ['PATH']}
+                    )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+ 
+@log_hg
+def hg_commit(d, user, comment, out=PIPE):
+    "hg commit -A -u 'user' -m 'comment'"
+    hgcmd = Popen('hg commit -A -m "%s"' % comment,
+                   stdout=out, stderr=out, shell=True,
+                   cwd=d,
+                   env={'HGUSER': user,
+                        'PATH': os.environ['PATH']}
+                   )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+
+@log_hg
+def hg_push(d, user, dest, out=PIPE):
+    "hg push -f"
+    hgcmd = Popen('hg push -f %s' % dest,
+                    stdout=out, stderr=out, shell=True,
+                    cwd=d,
+                    env={'HGUSER': user,
+                         'PATH': os.environ['PATH']}
+                   )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+
+@log_hg
+def hg_update_branch(d, user, br_name=None, out=PIPE):
+    '''hg update'''
+    hgcmd = Popen('hg update %s' % (br_name if br_name else ''),
+                    stdout=out, stderr=out, shell=True,
+                    cwd=d,
+                    env={'HGUSER': user,
+                         'PATH': os.environ['PATH']}
+                   )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+
+#@log_hg
+def hg_update_c(d, user, out=PIPE):
+    "hg update -c"
+    hgcmd = Popen('hg update -c',
+                 stdout=out, stderr=out, shell=True,
+                 cwd=d,
+                 env={'HGUSER': user,
+                      'PATH': os.environ['PATH']}
+                 )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+
+@log_hg
+def hg_branch(d, user, branch_name, out=PIPE):
+    "hg update branch_name"
+    hgcmd = Popen('hg branch %s' % auto_branch_name(),
+                 stdout=out, stderr=out, shell=True,
+                 cwd=d,
+                 env={'HGUSER': user,
+                      'PATH': os.environ['PATH']}
+                 )
+    return hgcmd.wait(), hgcmd.stdout, hgcmd.stderr
+
+@log_hg
+def hg_autobranch(d, user, out=PIPE):
+    "branch to auto_branch, commit, branch back to default"
+    returncode, stdout, stderr = hg_update_c(d, user)
+    if returncode == -1:
+        hg_branch(d, user, auto_branch_name())
+        hg_commit(d, user, 'auto commit')
+        return hg_update_branch(d, user, br_name='default')
+    return returncode, stdout, stderr
+
+if __name__ == '__main__':
+    configfile = 'config.yaml'
+    flagfile = 'CHANGED.FLG'
+    while True:
+        grouplist = loadconfig(configfile)
+        for group in grouplist:
+            for project_dir in group:
+                chflag = os.path.join(project_dir, flagfile)
+                hgflag = os.path.join(project_dir, '.hg')
+                if not os.path.isdir(project_dir): os.mkdir(project_dir)
+                if not os.path.exists(hgflag):
+                    hg_init(project_dir)
+                    #modify_config(project_dir)
+                if os.path.exists(chflag):
+                    time.sleep(0.2)
+                    user, comment = parse_flag(chflag)
+                    os.remove(chflag)
+                    hg_commit(project_dir, user, comment)
+                    syncgroup = group.copy()
+                    syncgroup.remove(project_dir)
+                    for syncdir in syncgroup:
+                        hg_push(project_dir, user, syncdir)
+                        hg_autobranch(syncdir, user)
+        time.sleep(10)
+
+Synchronizing hg repositories in different locations.
+
+In my working environment we still use DOS a lot to modify code hosted on 
+Novell (with some arcane Linux distros) servers. Same project is hosted on 
+different servers, and has to be synchronized to each other. All the projects 
+are shared with Samba service. There is a Windows server connecting to all the 
+Samba shares. The synchronizing script runs on the Windows Server. Currently we 
+use a simple copy-to-all method to keep the projects synchronized.
+
+This script is an attempt to integrate version control with directory 
+synchronizing . It provides a simple way to turn the project directories into 
+hg repos, synchronizing projects among different locations, and also tracks 
+project changes. 
+
+Currently only simple auto committing, synchronizing, and auto 
+branching are supported.
+