3 import sys, argparse, subprocess, json
8 'hardlink_special': 'hardlink_specials',
9 'protect_args': 'secluded_args',
10 'protected_args': 'secluded_args',
14 MOVE_OPTIM = set('asm_roll SIMD_roll'.split())
17 if not args.rsync or args.rsync == '-':
18 ver_out = sys.stdin.read().strip()
20 ver_out = subprocess.check_output([args.rsync, '--version', '--version'], encoding='utf-8').strip()
21 if ver_out.startswith('{'):
25 misplaced_optims = { }
26 for line in ver_out.splitlines():
27 if line.startswith('rsync '):
28 prog, vstr, ver, pstr, vstr2, proto = line.split()
29 info['program'] = prog
30 if ver.startswith('v'):
36 proto = proto.replace('.PR', '.')
38 elif line.startswith('Copyright '):
39 info['copyright'] = line[10:]
40 elif line.startswith('Web site: '):
41 info['url'] = line[10:]
42 elif line.startswith(' '):
43 if not saw_comma and ',' in line:
47 for x in line.strip(' ,').split(', '):
49 val, var = x.split(' ', 1)
52 elif val.endswith('-bit'):
53 var = var[:-1] + '_bits'
54 val = int(val.split('-')[0])
58 var = var.replace(' ', '_').replace('-', '_')
61 if sect_name[0] != 'o' and var in MOVE_OPTIM:
62 misplaced_optims[var] = val
64 info[sect_name][var] = val
66 info[sect_name] += [ x for x in line.split() if not x.startswith('(') ]
70 sect_name = line.strip(' :').replace(' ', '_').lower()
73 for chk in 'capabilities optimizations'.split():
77 info['optimizations'].update(misplaced_optims)
78 for chk in 'checksum_list compress_list daemon_auth_list'.split():
81 info['license'] = 'GPLv3' if ver[0] == '3' else 'GPLv2'
82 info['caveat'] = 'rsync comes with ABSOLUTELY NO WARRANTY'
83 print(json.dumps(info))
86 if __name__ == '__main__':
87 parser = argparse.ArgumentParser(description="Output rsync's version data in JSON format, even if the rsync doesn't support a native json-output method.", add_help=False)
88 parser.add_argument('rsync', nargs='?', help="Specify an rsync command to run. Otherwise stdin is consumed.")
89 parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
90 args = parser.parse_args()