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