svneol.py revision 4710c53dcad1ebf3755f3efb9e80ac24bd72a9b2
14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#! /usr/bin/env python 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSVN helper script. 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTry to set the svn:eol-style property to "native" on every .py, .txt, .c and 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm.h file in the directory tree rooted at the current directory. 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFiles with the svn:eol-style property already set (to anything) are skipped. 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsvn will itself refuse to set this property on a file that's not under SVN 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcontrol, or that has a binary mime-type property set. This script inherits 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthat behavior, and passes on whatever warning message the failing "svn 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpropset" command produces. 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIn the Python project, it's safe to invoke this script from the root of 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma checkout. 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmNo output is produced for files that are ignored. For a file that gets 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsvn:eol-style set, output looks like: 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm property 'svn:eol-style' set on 'Lib\ctypes\__init__.py' 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFor a file not under version control: 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm svn: warning: 'patch-finalizer.txt' is not under version control 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmand for a file with a binary mime-type property: 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm svn: File 'Lib\test\test_pep263.py' has binary mime type property 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport re 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef propfiles(root, fn): 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm default = os.path.join(root, ".svn", "props", fn+".svn-work") 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm format = int(open(os.path.join(root, ".svn", "format")).read().strip()) 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except IOError: 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return [] 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if format in (8, 9): 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # In version 8 and 9, committed props are stored in prop-base, local 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # modifications in props 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return [os.path.join(root, ".svn", "prop-base", fn+".svn-base"), 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm os.path.join(root, ".svn", "props", fn+".svn-work")] 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ValueError, "Unknown repository format" 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef proplist(root, fn): 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Return a list of property names for file fn in directory root" 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = [] 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for path in propfiles(root, fn): 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f = open(path) 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except IOError: 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # no properties file: not under version control, 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # or no properties set 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continue 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while 1: 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # key-value pairs, of the form 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # K <length> 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # <keyname>NL 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # V length 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # <value>NL 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # END 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = f.readline() 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if line.startswith("END"): 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert line.startswith("K ") 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm L = int(line.split()[1]) 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm key = f.read(L) 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result.append(key) 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.readline() 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = f.readline() 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert line.startswith("V ") 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm L = int(line.split()[1]) 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm value = f.read(L) 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.readline() 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.close() 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpossible_text_file = re.compile(r"\.([hc]|py|txt|sln|vcproj)$").search 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfor root, dirs, files in os.walk('.'): 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if '.svn' in dirs: 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dirs.remove('.svn') 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for fn in files: 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if possible_text_file(fn): 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if 'svn:eol-style' not in proplist(root, fn): 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = os.path.join(root, fn) 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm os.system('svn propset svn:eol-style native "%s"' % path) 92