1#! /usr/bin/env python3 2 3r""" 4SVN helper script. 5 6Try to set the svn:eol-style property to "native" on every .py, .txt, .c and 7.h file in the directory tree rooted at the current directory. 8 9Files with the svn:eol-style property already set (to anything) are skipped. 10 11svn will itself refuse to set this property on a file that's not under SVN 12control, or that has a binary mime-type property set. This script inherits 13that behavior, and passes on whatever warning message the failing "svn 14propset" command produces. 15 16In the Python project, it's safe to invoke this script from the root of 17a checkout. 18 19No output is produced for files that are ignored. For a file that gets 20svn:eol-style set, output looks like: 21 22 property 'svn:eol-style' set on 'Lib\ctypes\__init__.py' 23 24For a file not under version control: 25 26 svn: warning: 'patch-finalizer.txt' is not under version control 27 28and for a file with a binary mime-type property: 29 30 svn: File 'Lib\test\test_pep263.py' has binary mime type property 31""" 32 33import re 34import os 35import sys 36import subprocess 37 38 39def propfiles(root, fn): 40 default = os.path.join(root, ".svn", "props", fn + ".svn-work") 41 try: 42 format = int(open(os.path.join(root, ".svn", "format")).read().strip()) 43 except IOError: 44 return [] 45 if format in (8, 9): 46 # In version 8 and 9, committed props are stored in prop-base, local 47 # modifications in props 48 return [os.path.join(root, ".svn", "prop-base", fn + ".svn-base"), 49 os.path.join(root, ".svn", "props", fn + ".svn-work")] 50 raise ValueError("Unknown repository format") 51 52 53def proplist(root, fn): 54 """Return a list of property names for file fn in directory root.""" 55 result = [] 56 for path in propfiles(root, fn): 57 try: 58 f = open(path) 59 except IOError: 60 # no properties file: not under version control, 61 # or no properties set 62 continue 63 while True: 64 # key-value pairs, of the form 65 # K <length> 66 # <keyname>NL 67 # V length 68 # <value>NL 69 # END 70 line = f.readline() 71 if line.startswith("END"): 72 break 73 assert line.startswith("K ") 74 L = int(line.split()[1]) 75 key = f.read(L) 76 result.append(key) 77 f.readline() 78 line = f.readline() 79 assert line.startswith("V ") 80 L = int(line.split()[1]) 81 value = f.read(L) 82 f.readline() 83 f.close() 84 return result 85 86 87def set_eol_native(path): 88 cmd = 'svn propset svn:eol-style native "{}"'.format(path) 89 propset = subprocess.Popen(cmd, shell=True) 90 propset.wait() 91 92 93possible_text_file = re.compile(r"\.([hc]|py|txt|sln|vcproj)$").search 94 95 96def main(): 97 for arg in sys.argv[1:] or [os.curdir]: 98 if os.path.isfile(arg): 99 root, fn = os.path.split(arg) 100 if 'svn:eol-style' not in proplist(root, fn): 101 set_eol_native(arg) 102 elif os.path.isdir(arg): 103 for root, dirs, files in os.walk(arg): 104 if '.svn' in dirs: 105 dirs.remove('.svn') 106 for fn in files: 107 if possible_text_file(fn): 108 if 'svn:eol-style' not in proplist(root, fn): 109 path = os.path.join(root, fn) 110 set_eol_native(path) 111 112 113if __name__ == '__main__': 114 main() 115