#!/usr/bin/env python3 import locale import os import os.path import platform import subprocess import sys import unicodedata from pathlib import Path # For a complete list of MIME Types see [https://www.sitepoint.com/mime-types-complete-list/]. svnPropsMap = { # Extensions ".bat" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "CRLF" }, ".bin" : { "svn:mime-type" : "application/octet-stream" }, ".bmp" : { "svn:mime-type" : "image/bmp" }, ".c" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native" , "svn:keywords" : "Date Author Id Revision HeadURL" }, ".c++" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".cc" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native" , "svn:keywords" : "Date Author Id Revision HeadURL" }, ".class" : { "svn:mime-type" : "application/java" }, ".cmake" : { "svn:mime-type" : "text/x-cmake", "svn:eol-style" : "native" }, ".cmd" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "CRLF" }, ".cpp" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".cs" : { "svn:mime-type" : "text/x-csharp", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".csproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".css" : { "svn:mime-type" : "text/css", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".cxx" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".doc" : { "svn:mime-type" : "application/msword" }, ".docx" : { "svn:mime-type" : "application/msword" }, ".dsp" : { "svn:eol-style" : "CRLF" }, ".dsw" : { "svn:eol-style" : "CRLF" }, ".dtd" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".el" : { "svn:mime-type" : "text/x-script.elisp", "svn:eol-style" : "native" }, ".elc" : { "svn:mime-type" : "application/x-bytecode.elisp" }, ".ent" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".exe" : { "svn:mime-type" : "application/octet-stream" }, ".fsproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".gif" : { "svn:mime-type" : "image/gif" }, ".gz" : { "svn:mime-type" : "application/x-gzip" }, ".h" : { "svn:mime-type" : "text/x-h", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".h.in" : { "svn:mime-type" : "text/x-h", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".h.vc" : { "svn:mime-type" : "text/x-h", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".hh" : { "svn:mime-type" : "text/x-h", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".hpp" : { "svn:mime-type" : "text/x-h", "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, ".hta" : { "svn:mime-type" : "application/hta" }, ".htm" : { "svn:mime-type" : "text/html", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".html" : { "svn:mime-type" : "text/html", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".htmls" : { "svn:mime-type" : "text/html", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".idl" : { "svn:mime-type" : "text/x-c", "svn:eol-style" : "native" , "svn:keywords" : "Date Author Id Revision HeadURL" }, ".jar" : { "svn:mime-type" : "application/java-archive" }, ".jav" : { "svn:mime-type" : "text/x-java-source", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".java" : { "svn:mime-type" : "text/x-java-source", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".jelly" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".jpeg" : { "svn:mime-type" : "image/jpeg" }, ".jpg" : { "svn:mime-type" : "image/jpeg" }, ".js" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".jsp" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".lisp" : { "svn:mime-type" : "application/x-lisp", "svn:eol-style" : "native" }, ".lsp" : { "svn:mime-type" : "application/x-lisp", "svn:eol-style" : "native" }, ".markdown" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".md" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".mdown" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".mdtext" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".mdtxt" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".mdwn" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".mkdn" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".obj" : { "svn:mime-type" : "application/octet-stream" }, ".pdf" : { "svn:mime-type" : "application/pdf" }, ".png" : { "svn:mime-type" : "image/png" }, ".properties" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".props" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".ps" : { "svn:mime-type" : "application/postscript" }, ".pssproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".py" : { "svn:mime-type" : "text/x-script.phyton", "svn:executable" : "on", "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".pyc" : { "svn:mime-type" : "application/x-bytecode.python" }, ".pyproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".pyw" : { "svn:mime-type" : "text/x-script.phyton", "svn:executable" : "on", "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".sh" : { "svn:mime-type" : "text/x-script.sh", "svn:executable" : "on", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".shtml" : { "svn:mime-type" : "text/html", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".sln" : { "svn:eol-style" : "CRLF" }, ".sql" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".targets" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".text" : { "svn:mime-type" : "text/markdown", "svn:eol-style" : "native" }, ".tgz" : { "svn:mime-type" : "application/octet-stream" }, ".tif" : { "svn:mime-type" : "image/tiff" }, ".tiff" : { "svn:mime-type" : "image/tiff" }, ".txt" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".vbproj" : { "svn:eol-style" : "CRLF" }, ".vcproj" : { "svn:eol-style" : "CRLF" }, ".vcxproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".vcxproj.filters" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".vsl" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".wixproj" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "CRLF" }, ".wsdl" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".xml" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".xproj" : { "svn:eol-style" : "CRLF" }, ".xsd" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".xsl" : { "svn:mime-type" : "text/xml", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, ".zip" : { "svn:mime-type" : "application/zip" }, # Files ".clang-format" : { "svn:eol-style" : "native" }, ".clang-tidy" : { "svn:eol-style" : "native" }, ".emacs" : { "svn:mime-type" : "text/x-script.elisp", "svn:eol-style" : "native" }, ".gnus" : { "svn:mime-type" : "text/x-script.elisp", "svn:eol-style" : "native" }, "cmakelists.txt" : { "svn:mime-type" : "text/x-cmake", "svn:eol-style" : "native" }, "copying" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, "gnumakefile" : { "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, "html5.template" : { "svn:mime-type" : "text/html", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, "makefile" : { "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, "makefile.common" : { "svn:eol-style" : "native", "svn:keywords" : "Date Author Id Revision HeadURL" }, "readme" : { "svn:mime-type" : "text/plain", "svn:eol-style" : "native", "svn:keywords" : "Date Revision" }, } def InitLocale(): loc = locale.setlocale(locale.LC_ALL, '') if loc is None: return None if len(loc) == 0: return None if not os.name.lower() == "nt": return loc pos = loc.rfind('.') if pos == -1: return loc cp = int(loc[pos + 1:]) try: import ctypes import ctypes.wintypes _SetConsoleOutputCP = ctypes.windll.kernel32.SetConsoleOutputCP _SetConsoleOutputCP.argtypes = [ctypes.wintypes.UINT ] _SetConsoleOutputCP.restype = ctypes.wintypes.BOOL _SetConsoleOutputCP(cp) except ImportError: pass return loc def _find(name, matchFunc=os.path.isfile): path = os.environ['PATH'].split(os.pathsep) path.extend(sys.path) for dirname in path: candidate = os.path.join(dirname, name) if matchFunc(candidate): return candidate return None def find(name): return _find(name) def findDir(name): return _find(name, matchFunc=os.path.isdir) def findSVN(): if hasattr(findSVN, "SVN"): return findSVN.SVN svnName = "svn" if os.name.lower() == "nt": svnName = "svn.exe" findSVN.SVN = find(svnName) if findSVN.SVN != None: return findSVN.SVN candidate = os.path.expandvars(os.path.join("${ProgramFiles}", "TortoiseSVN", "bin", "svn.exe")) if os.path.isfile(candidate): findSVN.SVN = candidate return findSVN.SVN return None def normalize_caseless(text): return unicodedata.normalize("NFKD", text.casefold()) def caseless_equal(left, right): return normalize_caseless(left) == normalize_caseless(right) def SetPropertiesForFileWorker(fileName, prop, value): if not os.path.isfile(fileName): return False svn = findSVN() if svn is None: return False args = [] args.append(svn) args.append("propset") args.append(prop) args.append(value) args.append(fileName) ret = True try: subprocess.check_call(args) except subprocess.CalledProcessError: ret = False except OSError: ret = False return ret def SetPropertiesForFile(fileName): if not os.path.isfile(fileName): return False print("Setting properties for '%s.'" % (fileName)) head, tail = os.path.split(fileName) root, ext = os.path.splitext(fileName) props = svnPropsMap.get(normalize_caseless(tail), None) if props is None: props = svnPropsMap.get(normalize_caseless(ext), None) if props is None: sep = '' ext = sep.join(Path(fileName).suffixes) props = svnPropsMap.get(normalize_caseless(ext), None) if props is None: return False ret = 0 for prop, value in props.items(): if SetPropertiesForFileWorker(fileName, prop, value): ret += 1 return ret def main(argv): InitLocale() if len(argv) == 1: for root, dirs, files in os.walk(os.getcwd(), topdown=False): for name in files: SetPropertiesForFile(os.path.join(root, name)) else: for arg in argv[1:]: if os.path.isfile(arg): SetPropertiesForFile(arg) elif os.path.isdir(arg): for root, dirs, files in os.walk(arg, topdown=False): for name in files: SetPropertiesForFile(os.path.join(root, name)) return 0 sys.exit(main(sys.argv))