Skip to content

Commit 552c24d

Browse files
author
Kazuki Suzuki Przyborowski
committed
Update
1 parent f341113 commit 552c24d

File tree

2 files changed

+301
-610
lines changed

2 files changed

+301
-610
lines changed

neofile.py

Lines changed: 75 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,116 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33
from __future__ import absolute_import, division, print_function, unicode_literals
4-
import sys, os, io, argparse, json
54

6-
__program_name__ = "PyNeoFile"
5+
"""PyNeoFile CLI (core-only)
6+
- Uses only the `pyneofile` core module.
7+
- Supports --no-json fast path for scans.
8+
- Adds verbose (-d) printing during CREATE (-c), mirroring original output.
9+
"""
710

8-
try:
9-
import pyneofile as P
10-
except Exception as e:
11-
raise SystemExit("Failed to import core module 'pyneofile': %s" % (e,))
11+
import sys, os, io, argparse
12+
import pyneofile as P
1213

1314
def _read_input_bytes(path):
1415
if path in (None, '-', b'-'):
15-
data = sys.stdin.buffer.read()
16-
return data
17-
with io.open(path, 'rb') as fp:
18-
return fp.read()
16+
return getattr(sys.stdin, 'buffer', sys.stdin).read()
17+
with io.open(path, 'rb') as fp: return fp.read()
1918

2019
def _write_output_bytes(path, data):
20+
if isinstance(data, str): data = data.encode('utf-8')
2121
if path in (None, '-', b'-'):
22-
sys.stdout.buffer.write(data)
23-
return
24-
d = os.path.dirname(path)
25-
if d and not os.path.isdir(d):
26-
os.makedirs(d)
27-
with io.open(path, 'wb') as fp:
28-
fp.write(data)
22+
getattr(sys.stdout, 'buffer', sys.stdout).write(data); return
23+
d = os.path.dirname(path); (os.makedirs(d) if d and not os.path.isdir(d) else None)
24+
with io.open(path, 'wb') as fp: fp.write(data)
2925

3026
def main(argv=None):
31-
p = argparse.ArgumentParser(prog=__program_name__, description="PyNeoFile CLI (core-only)")
27+
p = argparse.ArgumentParser(prog="neofile", description="PyNeoFile CLI (core-only)")
3228
g = p.add_mutually_exclusive_group(required=True)
33-
g.add_argument('-l', '--list', action='store_true', help='List archive entries')
34-
g.add_argument('-e', '--extract', action='store_true', help='Extract files')
35-
g.add_argument('-c', '--create', action='store_true', help='Create archive from path or stdin')
36-
g.add_argument('-r', '--repack', action='store_true', help='Repack archive, optionally changing compression')
37-
g.add_argument('--validate', action='store_true', help='Validate checksums/structure')
38-
g.add_argument('-t', '--convert', action='store_true', help='Convert foreign (zip/tar) -> neo')
29+
g.add_argument('-l', '--list', action='store_true')
30+
g.add_argument('-e', '--extract', action='store_true')
31+
g.add_argument('-c', '--create', action='store_true')
32+
g.add_argument('-r', '--repack', action='store_true')
33+
g.add_argument('--validate', action='store_true')
34+
g.add_argument('-t', '--convert', action='store_true')
35+
p.add_argument('-i','--input'); p.add_argument('-o','--output')
36+
p.add_argument('-P','--compression', default='auto')
37+
p.add_argument('-L','--level', default=None, type=int)
38+
p.add_argument('--skipchecksum', action='store_true')
39+
p.add_argument('-d','--verbose', action='store_true')
40+
p.add_argument('--no-json', action='store_true')
41+
a = p.parse_args(argv)
3942

40-
p.add_argument('-i', '--input', required=False, help='Input path (use - for stdin)')
41-
p.add_argument('-o', '--output', required=False, help='Output path (use - for stdout)')
42-
p.add_argument('-P', '--compression', default='auto', help='Compression: auto|none|zlib|gzip|bz2|lzma')
43-
p.add_argument('-L', '--level', default=None, type=int, help='Compression level')
44-
p.add_argument('--skipchecksum', action='store_true', help='Skip content checksum verification')
45-
p.add_argument('-d', '--verbose', action='store_true', help='Verbose listing')
46-
p.add_argument('--no-json', action='store_true', help='Skip reading per-file JSON blocks (faster)')
47-
48-
args = p.parse_args(argv)
49-
50-
if args.list:
51-
src = args.input
43+
if a.list:
44+
src = a.input
5245
if src in (None, '-', b'-'):
5346
data = _read_input_bytes(src)
54-
entries = P.archivefilelistfiles_neo(data, advanced=args.verbose, include_dirs=True, skipjson=True if args.no_json else True)
47+
entries = P.archivefilelistfiles_neo(data, advanced=a.verbose, include_dirs=True, skipjson=True if a.no_json else True)
5548
else:
56-
entries = P.archivefilelistfiles_neo(src, advanced=args.verbose, include_dirs=True, skipjson=args.no_json)
57-
if args.verbose:
49+
entries = P.archivefilelistfiles_neo(src, advanced=a.verbose, include_dirs=True, skipjson=a.no_json)
50+
if a.verbose:
5851
for e in entries:
59-
if isinstance(e, dict):
60-
print("{type} {compression} {size} {name}".format(**e))
61-
else:
62-
print(e)
52+
if isinstance(e, dict): print("{type}\t{compression}\t{size}\t{name}".format(**e))
53+
else: print(e)
6354
else:
64-
for e in entries:
65-
print(e['name'] if isinstance(e, dict) else e)
55+
for e in entries: print(e['name'] if isinstance(e, dict) else e)
6656
return 0
6757

68-
if args.validate:
69-
src = args.input
58+
if a.validate:
59+
src = a.input
7060
if src in (None, '-', b'-'):
7161
data = _read_input_bytes(src)
72-
ok, details = P.archivefilevalidate_neo(data, verbose=args.verbose, return_details=True, skipjson=args.no_json)
62+
ok, details = P.archivefilevalidate_neo(data, verbose=a.verbose, return_details=True, skipjson=a.no_json)
7363
else:
74-
ok, details = P.archivefilevalidate_neo(src, verbose=args.verbose, return_details=True, skipjson=args.no_json)
64+
ok, details = P.archivefilevalidate_neo(src, verbose=a.verbose, return_details=True, skipjson=a.no_json)
7565
print("OK" if ok else "BAD")
76-
if args.verbose:
77-
for d in details:
78-
print("{index} {name} {header_ok} {json_ok} {content_ok}".format(**d))
66+
if a.verbose:
67+
for d in details: print("{index}\t{name}\t{header_ok}\t{json_ok}\t{content_ok}".format(**d))
7968
return 0 if ok else 2
8069

81-
if args.extract:
82-
src = args.input
83-
outdir = args.output or '.'
70+
if a.extract:
71+
src = a.input; outdir = a.output or '.'
8472
if src in (None, '-', b'-'):
85-
data = _read_input_bytes(src)
86-
ok = P.unpack_neo(data, outdir, skipchecksum=args.skipchecksum, uncompress=True)
73+
data = _read_input_bytes(src); ok = P.unpack_neo(data, outdir, skipchecksum=a.skipchecksum, uncompress=True)
8774
else:
88-
ok = P.unpack_neo(src, outdir, skipchecksum=args.skipchecksum, uncompress=True)
75+
ok = P.unpack_neo(src, outdir, skipchecksum=a.skipchecksum, uncompress=True)
8976
return 0 if ok else 1
9077

91-
if args.create:
92-
dst = args.output or '-'
93-
if args.input in (None, '-', b'-'):
94-
data = _read_input_bytes(args.input)
95-
payload = {"stdin.bin": data}
78+
if a.create:
79+
dst = a.output or '-'; src_path = a.input
80+
if src_path in (None, '-', b'-'):
81+
data = _read_input_bytes(src_path); payload = {"stdin.bin": data}
9682
blob = P.pack_neo(payload, outfile=None, checksumtypes=('crc32','crc32','crc32'),
97-
encoding='UTF-8', compression=args.compression, compression_level=args.level)
98-
_write_output_bytes(dst, blob)
99-
else:
100-
res = P.pack_neo(args.input, outfile=dst, checksumtypes=('crc32','crc32','crc32'),
101-
encoding='UTF-8', compression=args.compression, compression_level=args.level)
102-
if isinstance(res, (bytes, bytearray)):
103-
_write_output_bytes(dst, res)
83+
encoding='UTF-8', compression=a.compression, compression_level=a.level)
84+
_write_output_bytes(dst, blob); return 0
85+
if a.verbose:
86+
norm = os.path.normpath(src_path)
87+
if os.path.isfile(norm):
88+
base = os.path.basename(norm).replace('\\','/'); print('./' + base)
89+
else:
90+
base = os.path.basename(norm).replace('\\','/')
91+
for root, dirs, files in os.walk(norm, topdown=True):
92+
rel = base if root == norm else base + '/' + os.path.relpath(root, norm).replace('\\','/')
93+
print('./' + rel)
94+
for fname in sorted(files): print('./' + rel + '/' + fname)
95+
res = P.pack_neo(src_path, outfile=dst, checksumtypes=('crc32','crc32','crc32'),
96+
encoding='UTF-8', compression=a.compression, compression_level=a.level)
97+
if isinstance(res, (bytes, bytearray)): _write_output_bytes(dst, res)
10498
return 0
10599

106-
if args.repack:
107-
src = args.input
108-
dst = args.output or '-'
109-
res = P.repack_neo(src if src not in (None, '-', b'-') else _read_input_bytes(src),
110-
outfile=dst, checksumtypes=('crc32','crc32','crc32'),
111-
compression=args.compression, compression_level=args.level)
112-
if isinstance(res, (bytes, bytearray)):
113-
_write_output_bytes(dst, res)
100+
if a.repack:
101+
src = a.input; dst = a.output or '-'
102+
data_or_path = src if src not in (None, '-', b'-') else _read_input_bytes(src)
103+
res = P.repack_neo(data_or_path, outfile=dst, checksumtypes=('crc32','crc32','crc32'),
104+
compression=a.compression, compression_level=a.level)
105+
if isinstance(res, (bytes, bytearray)): _write_output_bytes(dst, res)
114106
return 0
115107

116-
if args.convert:
117-
src = args.input
118-
dst = args.output or '-'
119-
if src in (None, '-', b'-'):
120-
raise SystemExit("convert requires a path input (zip/tar). Use -i <file>")
108+
if a.convert:
109+
src = a.input; dst = a.output or '-'
110+
if src in (None, '-', b'-'): raise SystemExit("convert requires a path input (zip/tar)")
121111
res = P.convert_foreign_to_neo(src, outfile=dst, checksumtypes=('crc32','crc32','crc32'),
122-
compression=args.compression, compression_level=args.level)
123-
if isinstance(res, (bytes, bytearray)):
124-
_write_output_bytes(dst, res)
112+
compression=a.compression, compression_level=a.level)
113+
if isinstance(res, (bytes, bytearray)): _write_output_bytes(dst, res)
125114
return 0
126115

127116
if __name__ == "__main__":

0 commit comments

Comments
 (0)