94 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
| #!/usr/bin/env python 
 | |
| 
 | |
| import py
 | |
| import sys, os
 | |
| 
 | |
| def usage():
 | |
|     arg0 = sys.argv[0]
 | |
|     print """%s [user@]remote-host:/repo/location localrepo [identity keyfile]""" % (arg0,)
 | |
| 
 | |
| 
 | |
| def main(args):
 | |
|     remote = args[0]
 | |
|     localrepo = py.path.local(args[1])
 | |
|     if not localrepo.check(dir=1):
 | |
|         raise SystemExit("localrepo %s does not exist" %(localrepo,))
 | |
|     if len(args) == 3:
 | |
|         keyfile = py.path.local(args[2])
 | |
|     else:
 | |
|         keyfile = None
 | |
|     remote_host, path = remote.split(':', 1)
 | |
|     print "ssh-connecting to", remote_host 
 | |
|     gw = getgateway(remote_host, keyfile)
 | |
| 
 | |
|     local_rev = get_svn_youngest(localrepo)
 | |
| 
 | |
|     # local protocol 
 | |
|     # 1. client sends rev/repo -> server 
 | |
|     # 2. server checks for newer revisions and sends dumps 
 | |
|     # 3. client receives dumps, updates local repo 
 | |
|     # 4. client goes back to step 1
 | |
|     c = gw.remote_exec("""
 | |
|         import py
 | |
|         import os
 | |
|         remote_rev, repopath = channel.receive()
 | |
|         while 1: 
 | |
|             rev = py.process.cmdexec('svnlook youngest "%s"' % repopath) 
 | |
|             rev = int(rev)
 | |
|             if rev > remote_rev:
 | |
|                 revrange = (remote_rev+1, rev)
 | |
|                 dumpchannel = channel.gateway.newchannel()
 | |
|                 channel.send(revrange)
 | |
|                 channel.send(dumpchannel)
 | |
| 
 | |
|                 f = os.popen(
 | |
|                         "svnadmin dump -q --incremental -r %s:%s %s" 
 | |
|                          % (revrange[0], revrange[1], repopath), 'r')
 | |
|                 try:
 | |
|                     while 1:
 | |
|                         s = f.read(8192)
 | |
|                         if not s:
 | |
|                             raise EOFError
 | |
|                         dumpchannel.send(s)
 | |
|                 except EOFError:
 | |
|                     dumpchannel.close()
 | |
|                 remote_rev = rev 
 | |
|             else:
 | |
|                 # using svn-hook instead would be nice here
 | |
|                 py.std.time.sleep(30)
 | |
|     """)
 | |
| 
 | |
|     c.send((local_rev, path))
 | |
|     print "checking revisions from %d in %s" %(local_rev, remote)
 | |
|     while 1: 
 | |
|         revstart, revend = c.receive()
 | |
|         dumpchannel = c.receive() 
 | |
| 
 | |
|         print "receiving revisions", revstart, "-", revend, "replaying..."
 | |
|         svn_load(localrepo, dumpchannel)
 | |
|         print "current revision", revend 
 | |
| 
 | |
| def svn_load(repo, dumpchannel):
 | |
|     f = os.popen("svnadmin load -q %s" %(repo, ), "w")
 | |
|     for x in dumpchannel:
 | |
|         sys.stdout.write(".")
 | |
|         sys.stdout.flush()
 | |
|         f.write(x)
 | |
|     print >>sys.stdout
 | |
|     f.close() 
 | |
| 
 | |
| def get_svn_youngest(repo):
 | |
|     rev = py.process.cmdexec('svnlook youngest "%s"' % repo) 
 | |
|     return int(rev)
 | |
| 
 | |
| def getgateway(host, keyfile=None):
 | |
|     return execnet.SshGateway(host, identity=keyfile)
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     if len(sys.argv) < 3:
 | |
|         usage()
 | |
|         raise SystemExit(1)
 | |
| 
 | |
|     main(sys.argv[1:])
 | |
| 
 |