mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Source tree synchronization tool (for Windowes, mostly)
This commit is contained in:
		
							parent
							
								
									30e53c0c39
								
							
						
					
					
						commit
						a554107802
					
				
					 1 changed files with 200 additions and 0 deletions
				
			
		
							
								
								
									
										200
									
								
								Tools/scripts/treesync.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										200
									
								
								Tools/scripts/treesync.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,200 @@ | |||
| #! /usr/bin/env python | ||||
| 
 | ||||
| """Script to synchronize two source trees. | ||||
| 
 | ||||
| Invoke with two arguments: | ||||
| 
 | ||||
| python treesync.py slave master | ||||
| 
 | ||||
| The assumption is that "master" contains CVS administration while | ||||
| slave doesn't.  All files in the slave tree that have a CVS/Entries | ||||
| entry in the master tree are synchronized.  This means: | ||||
| 
 | ||||
|     If the files differ: | ||||
|         if the slave file is newer: | ||||
| 	    normalize the slave file | ||||
| 	    if the files still differ: | ||||
| 	        copy the slave to the master | ||||
| 	else (the master is newer): | ||||
| 	    copy the master to the slave | ||||
|      | ||||
|     normalizing the slave means replacing CRLF with LF when the master | ||||
|     doesn't use CRLF | ||||
| 
 | ||||
| """ | ||||
| 
 | ||||
| import os, sys, stat, string, getopt | ||||
| 
 | ||||
| # Interactivity options | ||||
| default_answer = "ask" | ||||
| create_files = "yes" | ||||
| create_directories = "no" | ||||
| write_slave = "ask" | ||||
| write_master = "ask" | ||||
| 
 | ||||
| def main(): | ||||
|     global always_no, always_yes | ||||
|     global create_directories, write_master, write_slave | ||||
|     opts, args = getopt.getopt(sys.argv[1:], "nym:s:d:f:a:") | ||||
|     for o, a in opts: | ||||
| 	if o == '-y': | ||||
| 	    default_answer = "yes" | ||||
| 	if o == '-n': | ||||
| 	    default_answer = "no" | ||||
| 	if o == '-s': | ||||
| 	    write_slave = a | ||||
| 	if o == '-m': | ||||
| 	    write_master = a | ||||
| 	if o == '-d': | ||||
| 	    create_directories = a | ||||
| 	if o == '-f': | ||||
| 	    create_files = a | ||||
| 	if o == '-a': | ||||
| 	    create_files = create_directories = write_slave = write_master = a | ||||
|     try: | ||||
| 	[slave, master] = args | ||||
|     except ValueError: | ||||
| 	print "usage: python", sys.argv[0] or "treesync.py", | ||||
| 	print "[-n] [-y] [-m y|n|a] [-s y|n|a] [-d y|n|a] [-f n|y|a]", | ||||
| 	print "slavedir masterdir" | ||||
| 	return | ||||
|     process(slave, master) | ||||
|      | ||||
| def process(slave, master): | ||||
|     cvsdir = os.path.join(master, "CVS") | ||||
|     if not os.path.isdir(cvsdir): | ||||
| 	print "skipping master subdirectory", master | ||||
| 	print "-- not under CVS" | ||||
| 	return | ||||
|     print "-"*40 | ||||
|     print "slave ", slave | ||||
|     print "master", master | ||||
|     if not os.path.isdir(slave): | ||||
| 	if not okay("create slave directory %s?" % slave, | ||||
| 		    answer=create_directories): | ||||
| 	    print "skipping master subdirectory", master | ||||
| 	    print "-- no corresponding slave", slave | ||||
| 	    return | ||||
| 	print "creating slave directory", slave | ||||
| 	try: | ||||
| 	    os.mkdir(slave) | ||||
| 	except os.error, msg: | ||||
| 	    print "can't make slave directory", slave, ":", msg | ||||
| 	    return | ||||
| 	else: | ||||
| 	    print "made slave directory", slave | ||||
|     cvsdir = None | ||||
|     subdirs = [] | ||||
|     names = os.listdir(master) | ||||
|     for name in names: | ||||
| 	mastername = os.path.join(master, name) | ||||
| 	slavename = os.path.join(slave, name) | ||||
| 	if name == "CVS": | ||||
| 	    cvsdir = mastername | ||||
| 	else: | ||||
| 	    if os.path.isdir(mastername) and not os.path.islink(mastername): | ||||
| 		subdirs.append((slavename, mastername)) | ||||
|     if cvsdir: | ||||
| 	entries = os.path.join(cvsdir, "Entries") | ||||
| 	for e in open(entries).readlines(): | ||||
| 	    words = string.split(e, '/') | ||||
| 	    if words[0] == '' and words[1:]: | ||||
| 		name = words[1] | ||||
| 		s = os.path.join(slave, name) | ||||
| 		m = os.path.join(master, name) | ||||
| 		compare(s, m) | ||||
|     for (s, m) in subdirs: | ||||
| 	process(s, m) | ||||
| 
 | ||||
| def compare(slave, master): | ||||
|     try: | ||||
| 	sf = open(slave, 'rb') | ||||
|     except IOError: | ||||
| 	sf = None | ||||
|     try: | ||||
| 	mf = open(master, 'rb') | ||||
|     except IOError: | ||||
| 	mf = None | ||||
|     if not sf: | ||||
| 	if not mf: | ||||
| 	    print "Not updating missing master", master | ||||
| 	    return | ||||
| 	print "Creating missing slave", slave | ||||
| 	copy(master, slave, answer=create_files) | ||||
| 	return | ||||
|     if sf and mf: | ||||
| 	if identical(sf, mf): | ||||
| 	    return | ||||
|     sft = mtime(sf) | ||||
|     mft = mtime(mf) | ||||
|     if mft > sft: | ||||
| 	# Master is newer -- copy master to slave | ||||
| 	sf.close() | ||||
| 	mf.close() | ||||
| 	print "Master             ", master | ||||
| 	print "is newer than slave", slave | ||||
| 	copy(master, slave, answer=write_slave) | ||||
| 	return | ||||
|     # Slave is newer -- copy slave to master | ||||
|     # But first check what to do about CRLF | ||||
|     mf.seek(0) | ||||
|     fun = funnychars(mf) | ||||
|     mf.close() | ||||
|     sf.close() | ||||
|     if fun: | ||||
| 	print "***UPDATING MASTER (BINARY COPY)***" | ||||
| 	copy(slave, master, "rb", write_master) | ||||
|     else: | ||||
| 	print "***UPDATING MASTER***" | ||||
| 	copy(slave, master, "r", write_master) | ||||
| 
 | ||||
| BUFSIZE = 16*1024 | ||||
| 
 | ||||
| def identical(sf, mf): | ||||
|     while 1: | ||||
| 	sd = sf.read(BUFSIZE) | ||||
| 	md = mf.read(BUFSIZE) | ||||
| 	if sd != md: return 0 | ||||
| 	if not sd: break | ||||
|     return 1 | ||||
| 
 | ||||
| def mtime(f): | ||||
|     st = os.fstat(f.fileno()) | ||||
|     return st[stat.ST_MTIME] | ||||
| 
 | ||||
| def funnychars(f): | ||||
|     while 1: | ||||
| 	buf = f.read(BUFSIZE) | ||||
| 	if not buf: break | ||||
| 	if '\r' in buf or '\0' in buf: return 1 | ||||
|     return 0 | ||||
| 
 | ||||
| def copy(src, dst, rmode="rb", wmode="wb", answer='ask'): | ||||
|     print "copying", src | ||||
|     print "     to", dst | ||||
|     if not okay("okay to copy? ", answer): | ||||
| 	return | ||||
|     f = open(src, rmode) | ||||
|     g = open(dst, wmode) | ||||
|     while 1: | ||||
| 	buf = f.read(BUFSIZE) | ||||
| 	if not buf: break | ||||
| 	g.write(buf) | ||||
|     f.close() | ||||
|     g.close() | ||||
| 
 | ||||
| def okay(prompt, answer='ask'): | ||||
|     answer = string.lower(string.strip(answer)) | ||||
|     if not answer or answer[0] not in 'ny': | ||||
| 	answer = raw_input(prompt) | ||||
| 	answer = string.lower(string.strip(answer)) | ||||
| 	if not answer: | ||||
| 	    answer = default_answer | ||||
|     if answer[:1] == 'y': | ||||
| 	return 1 | ||||
|     if answer[:1] == 'n': | ||||
| 	return 0 | ||||
|     print "Yes or No please -- try again:" | ||||
|     return okay(prompt) | ||||
| 
 | ||||
| main() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum