Add --munge-links rsync option; convert to python.
authorWayne Davison <wayne@opencoder.net>
Mon, 20 Dec 2021 21:34:05 +0000 (13:34 -0800)
committerWayne Davison <wayne@opencoder.net>
Mon, 20 Dec 2021 21:51:50 +0000 (13:51 -0800)
packaging/cull_options

index 7588002be1f90d2c461f4ca8781f3ec686b6d530..85311c7c7f90ecd83b2e144e44c98246a0b4dea6 100755 (executable)
-#!/usr/bin/env perl
-# This script outputs some perl code that parses all possible options
-# that the code in options.c might send to the server.  This perl code
-# is included in the rrsync script.
-use strict;
-
-our %short_no_arg;
-our %short_with_num = ( '@' => 1 );
-our %long_opt = ( # 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,
-    'one-file-system' => 0,
-    'owner' => 0,
-    'perms' => 0,
-    'recursive' => 0,
-    'times' => 0,
-    'write-devices' => -1,
-);
-our $last_long_opt;
-
-open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
-
-while (<IN>) {
-    if (/\Qargstr[x++]\E = '([^.ie])'/) {
-       $short_no_arg{$1} = 1;
-       undef $last_long_opt;
-    } elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
-       $short_with_num{$1} = 1;
-       undef $last_long_opt;
-    } elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
-       $last_long_opt = $1;
-       $long_opt{$1} = 0 unless exists $long_opt{$1};
-    } elsif (defined($last_long_opt)
-       && /\Qargs[ac++]\E = ([^["\s]+);/) {
-       $long_opt{$last_long_opt} = 2;
-       undef $last_long_opt;
-    } elsif (/return "--([^"]+-dest)";/) {
-       $long_opt{$1} = 2;
-       undef $last_long_opt;
-    } elsif (/\Qasprintf(\E[^,]+, "--([^"=]+)=/ || /\Qargs[ac++]\E = "--([^"=]+)=/ || /fmt = .*: "--([^"=]+)=/) {
-       $long_opt{$1} = 1;
-       undef $last_long_opt;
-    }
-}
-close IN;
-
-my $short_no_arg = join('', sort keys %short_no_arg);
-my $short_with_num = join('', sort keys %short_with_num);
-
-print <<EOT;
+#!/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_opt = { # 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,
+        'times': 0,
+        '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_opt:
+                    long_opt[last_long_opt] = 0
+                else:
+                    last_long_opt = None
+                continue
+
+            if last_long_opt:
+                m = re.search(r'args\[ac\+\+\] = ([^["\s]+);', line)
+                if m:
+                    long_opt[last_long_opt] = 2
+                    last_long_opt = None
+                    continue
+
+            m = re.search(r'return "--([^"]+-dest)";', line)
+            if m:
+                long_opt[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'fmt = .*: "--([^"=]+)=', line)
+            if m:
+                long_opt[m.group(1)] = 1
+                last_long_opt = None
+
+    long_opt['files-from'] = 3
+
+    txt = """
 # These options are the only options that rsync might send to the server,
 # and only in the option format that the stock rsync produces.
 
 # To disable a short-named option, add its letter to this string:
-our \$short_disabled = 's';
-
-our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
-our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY
+"""
 
+    txt += str_assign('short_disabled', 's') + "\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.
-our \%long_opt = (
-EOT
-
-foreach my $opt (sort keys %long_opt) {
-    my $val = $long_opt{$opt};
-    $val = 1 if $opt =~ /^(max-|min-)/;
-    $val = 3 if $opt eq 'files-from';
-    $val = q"$only eq 'r' ? -1 : " . $val if $opt =~ /^(remove-|log-file)/;
-    $val = q"$only eq 'w' ? -1 : " . $val if $opt eq 'sender';
-    print "  '$opt' => $val,\n";
-}
-
-print ");\n\n";
+"""
+
+    print(txt, end='')
+
+    if args.python:
+        print("long_opt = {")
+        sep = ':'
+    else:
+        print("our %long_opt = (")
+        sep = ' =>'
+
+    for opt in sorted(long_opt):
+        if opt.startswith(('min-', 'max-')):
+            val = 1
+        else:
+            val = long_opt[opt]
+        print(' ', repr(opt) + sep, str(val) + ',')
+
+    if args.python:
+        print("}")
+    else:
+        print(");")
+    print('')
+
+
+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 (the default).")
+    out_group.add_argument('--python', action='store_true', help="Output python code.")
+    parser.add_argument('--help', '-h', action='help', help="Output this help message and exit.")
+    args = parser.parse_args()
+    main()
+
+# vim: sw=4 et