Tweak a comment.
[rsync.git] / packaging / cull-options
1 #!/usr/bin/env python3
2 # This script outputs either perl or python code that parses all possible options
3 # that the code in options.c might send to the server.  The resulting code is then
4 # included in the rrsync script.
5
6 import re, argparse
7
8 short_no_arg = { }
9 short_with_num = { '@': 1 }
10 long_opts = { # These include some extra long-args that BackupPC uses:
11         'block-size': 1,
12         'daemon': -1,
13         'debug': 1,
14         'fake-super': 0,
15         'fuzzy': 0,
16         'group': 0,
17         'hard-links': 0,
18         'ignore-times': 0,
19         'info': 1,
20         'links': 0,
21         'log-file': 3,
22         'munge-links': 0,
23         'no-munge-links': -1,
24         'one-file-system': 0,
25         'owner': 0,
26         'perms': 0,
27         'recursive': 0,
28         'stderr': 1,
29         'times': 0,
30         'write-devices': -1,
31         }
32
33 def main():
34     last_long_opt = None
35
36     with open('../options.c') as fh:
37         for line in fh:
38             m = re.search(r"argstr\[x\+\+\] = '([^.ie])'", line)
39             if m:
40                 short_no_arg[m.group(1)] = 1
41                 last_long_opt = None
42                 continue
43
44             m = re.search(r'asprintf\([^,]+, "-([a-zA-Z0-9])\%l?[ud]"', line)
45             if m:
46                 short_with_num[m.group(1)] = 1
47                 last_long_opt = None
48                 continue
49
50             m = re.search(r'args\[ac\+\+\] = "--([^"=]+)"', line)
51             if m:
52                 last_long_opt = m.group(1)
53                 if last_long_opt not in long_opts:
54                     long_opts[last_long_opt] = 0
55                 else:
56                     last_long_opt = None
57                 continue
58
59             if last_long_opt:
60                 m = re.search(r'args\[ac\+\+\] = safe_arg\("", ([^[("\s]+)\);', line)
61                 if m:
62                     long_opts[last_long_opt] = 2
63                     last_long_opt = None
64                     continue
65                 if 'args[ac++] = ' in line:
66                     last_long_opt = None
67
68             m = re.search(r'return "--([^"]+-dest)";', line)
69             if m:
70                 long_opts[m.group(1)] = 2
71                 last_long_opt = None
72                 continue
73
74             m = re.search(r'asprintf\([^,]+, "--([^"=]+)=', line)
75             if not m:
76                 m = re.search(r'args\[ac\+\+\] = "--([^"=]+)=', line)
77                 if not m:
78                     m = re.search(r'args\[ac\+\+\] = safe_arg\("--([^"=]+)"', line)
79                     if not m:
80                         m = re.search(r'fmt = .*: "--([^"=]+)=', line)
81             if m:
82                 long_opts[m.group(1)] = 1
83                 last_long_opt = None
84
85     long_opts['files-from'] = 3
86
87     txt = """\
88 ### START of options data produced by the cull-options script. ###
89
90 # To disable a short-named option, add its letter to this string:
91 """
92
93     txt += str_assign('short_disabled', 's') + "\n"
94     txt += '# These are also disabled when the restricted dir is not "/":\n'
95     txt += str_assign('short_disabled_subdir', 'KLk') + "\n"
96     txt += '# These are all possible short options that we will accept (when not disabled above):\n'
97     txt += str_assign('short_no_arg', ''.join(sorted(short_no_arg)), 'DO NOT REMOVE ANY')
98     txt += str_assign('short_with_num', ''.join(sorted(short_with_num)), 'DO NOT REMOVE ANY')
99    
100     txt += """
101 # To disable a long-named option, change its value to a -1.  The values mean:
102 # 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
103 # check the arg when receiving; and 3 = always check the arg.
104 """
105
106     print(txt, end='')
107
108     if args.python:
109         print("long_opts = {")
110         sep = ':'
111     else:
112         print("our %long_opt = (")
113         sep = ' =>'
114
115     for opt in sorted(long_opts):
116         if opt.startswith(('min-', 'max-')):
117             val = 1
118         else:
119             val = long_opts[opt]
120         print(' ', repr(opt) + sep, str(val) + ',')
121
122     if args.python:
123         print("}")
124     else:
125         print(");")
126     print("\n### END of options data produced by the cull-options script. ###")
127
128
129 def str_assign(name, val, comment=None):
130     comment = ' # ' + comment if comment else ''
131     if args.python:
132         return name + ' = ' + repr(val) + comment + "\n"
133     return 'our $' + name + ' = ' + repr(val) + ';' + comment + "\n"
134
135
136 if __name__ == '__main__':
137     parser = argparse.ArgumentParser(description="Output culled rsync options for rrsync.", add_help=False)
138     out_group = parser.add_mutually_exclusive_group()
139     out_group.add_argument('--perl', action='store_true', help="Output perl code.")
140     out_group.add_argument('--python', action='store_true', help="Output python code (the default).")
141     parser.add_argument('--help', '-h', action='help', help="Output this help message and exit.")
142     args = parser.parse_args()
143     if not args.perl:
144         args.python = True
145     main()
146
147 # vim: sw=4 et