summaryrefslogtreecommitdiffstats
path: root/packaging/cull-options
blob: e71818cdb18ee5bf20c6c92c14e481ff2debb901 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
# This script outputs either perl or python code that parses all possible options
# that the code in options.c might send to the server.  The resulting code is then
# included in the rrsync script.

import re, argparse

short_no_arg = { }
short_with_num = { '@': 1 }
long_opts = { # These include some extra long-args that BackupPC uses:
        'block-size': 1,
        'daemon': -1,
        'debug': 1,
        'fake-super': 0,
        'fuzzy': 0,
        'group': 0,
        'hard-links': 0,
        'ignore-times': 0,
        'info': 1,
        'links': 0,
        'log-file': 3,
        'munge-links': 0,
        'no-munge-links': -1,
        'one-file-system': 0,
        'owner': 0,
        'perms': 0,
        'recursive': 0,
        'stderr': 1,
        'times': 0,
        'copy-devices': -1,
        'write-devices': -1,
        }

def main():
    last_long_opt = None

    with open('../options.c') as fh:
        for line in fh:
            m = re.search(r"argstr\[x\+\+\] = '([^.ie])'", line)
            if m:
                short_no_arg[m.group(1)] = 1
                last_long_opt = None
                continue

            m = re.search(r'asprintf\([^,]+, "-([a-zA-Z0-9])\%l?[ud]"', line)
            if m:
                short_with_num[m.group(1)] = 1
                last_long_opt = None
                continue

            m = re.search(r'args\[ac\+\+\] = "--([^"=]+)"', line)
            if m:
                last_long_opt = m.group(1)
                if last_long_opt not in long_opts:
                    long_opts[last_long_opt] = 0
                else:
                    last_long_opt = None
                continue

            if last_long_opt:
                m = re.search(r'args\[ac\+\+\] = safe_arg\("", ([^[("\s]+)\);', line)
                if m:
                    long_opts[last_long_opt] = 2
                    last_long_opt = None
                    continue
                if 'args[ac++] = ' in line:
                    last_long_opt = None

            m = re.search(r'return "--([^"]+-dest)";', line)
            if m:
                long_opts[m.group(1)] = 2
                last_long_opt = None
                continue

            m = re.search(r'asprintf\([^,]+, "--([^"=]+)=', line)
            if not m:
                m = re.search(r'args\[ac\+\+\] = "--([^"=]+)=', line)
                if not m:
                    m = re.search(r'args\[ac\+\+\] = safe_arg\("--([^"=]+)"', line)
                    if not m:
                        m = re.search(r'fmt = .*: "--([^"=]+)=', line)
            if m:
                long_opts[m.group(1)] = 1
                last_long_opt = None

    long_opts['files-from'] = 3

    txt = """\
### START of options data produced by the cull-options script. ###

# To disable a short-named option, add its letter to this string:
"""

    txt += str_assign('short_disabled', 's') + "\n"
    txt += '# These are also disabled when the restricted dir is not "/":\n'
    txt += str_assign('short_disabled_subdir', 'KLk') + "\n"
    txt += '# These are all possible short options that we will accept (when not disabled above):\n'
    txt += str_assign('short_no_arg', ''.join(sorted(short_no_arg)), 'DO NOT REMOVE ANY')
    txt += str_assign('short_with_num', ''.join(sorted(short_with_num)), 'DO NOT REMOVE ANY')
   
    txt += """
# To disable a long-named option, change its value to a -1.  The values mean:
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
# check the arg when receiving; and 3 = always check the arg.
"""

    print(txt, end='')

    if args.python:
        print("long_opts = {")
        sep = ':'
    else:
        print("our %long_opt = (")
        sep = ' =>'

    for opt in sorted(long_opts):
        if opt.startswith(('min-', 'max-')):
            val = 1
        else:
            val = long_opts[opt]
        print(' ', repr(opt) + sep, str(val) + ',')

    if args.python:
        print("}")
    else:
        print(");")
    print("\n### END of options data produced by the cull-options script. ###")


def str_assign(name, val, comment=None):
    comment = ' # ' + comment if comment else ''
    if args.python:
        return name + ' = ' + repr(val) + comment + "\n"
    return 'our $' + name + ' = ' + repr(val) + ';' + comment + "\n"


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Output culled rsync options for rrsync.", add_help=False)
    out_group = parser.add_mutually_exclusive_group()
    out_group.add_argument('--perl', action='store_true', help="Output perl code.")
    out_group.add_argument('--python', action='store_true', help="Output python code (the default).")
    parser.add_argument('--help', '-h', action='help', help="Output this help message and exit.")
    args = parser.parse_args()
    if not args.perl:
        args.python = True
    main()

# vim: sw=4 et