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