@@ -3,6 +3,7 @@ import commandLineUsage from 'command-line-usage';
3
3
import { globSync } from 'glob' ;
4
4
import zlib from 'zlib' ;
5
5
import fs from 'fs' ;
6
+ import path from 'path' ;
6
7
7
8
function parseCommandLineArgs ( ) {
8
9
const optionDefinitions = [
@@ -46,12 +47,20 @@ function parseCommandLineArgs() {
46
47
return options ;
47
48
}
48
49
50
+ function calculateCompressionRatio ( originalSize , compressedSize ) {
51
+ return ( 1 - compressedSize / originalSize ) * 100 ;
52
+ }
53
+
54
+ function calculateExpansionRatio ( compressedSize , decompressedSize ) {
55
+ return ( decompressedSize / compressedSize - 1 ) * 100 ;
56
+ }
57
+
49
58
function compress ( inputData ) {
50
59
const compressedData = zlib . deflateSync ( inputData , { level : zlib . constants . Z_BEST_COMPRESSION } ) ;
51
60
52
61
const originalSize = inputData . length ;
53
62
const compressedSize = compressedData . length ;
54
- const compressionRatio = ( 1 - compressedSize / originalSize ) * 100 ;
63
+ const compressionRatio = calculateCompressionRatio ( originalSize , compressedSize ) ;
55
64
console . log ( ` Original size: ${ String ( originalSize ) . padStart ( 8 ) } bytes` ) ;
56
65
console . log ( ` Compressed size: ${ String ( compressedSize ) . padStart ( 8 ) } bytes` ) ;
57
66
console . log ( ` Compression ratio: ${ compressionRatio . toFixed ( 2 ) . padStart ( 8 ) } %` ) ;
@@ -64,52 +73,82 @@ function decompress(inputData) {
64
73
65
74
const compressedSize = inputData . length ;
66
75
const decompressedSize = decompressedData . length ;
67
- const expansionRatio = ( decompressedSize / compressedSize - 1 ) * 100 ;
76
+ const expansionRatio = calculateExpansionRatio ( compressedSize , decompressedSize ) ;
68
77
console . log ( ` Compressed size: ${ String ( compressedSize ) . padStart ( 8 ) } bytes` ) ;
69
78
console . log ( ` Decompressed size: ${ String ( decompressedSize ) . padStart ( 8 ) } bytes` ) ;
70
79
console . log ( ` Expansion ratio: ${ expansionRatio . toFixed ( 2 ) . padStart ( 8 ) } %` ) ;
71
80
72
81
return decompressedData ;
73
82
}
74
83
75
- function processFiles ( options ) {
84
+ function globsToFiles ( globs ) {
76
85
let files = [ ] ;
77
- console . assert ( options . globs . length > 0 ) ;
78
- for ( const glob of options . globs ) {
86
+ console . assert ( globs . length > 0 ) ;
87
+ for ( const glob of globs ) {
79
88
const matches = globSync ( glob , { nodir : true } ) ;
80
89
files = files . concat ( matches ) ;
81
90
}
82
91
files = Array . from ( new Set ( files ) ) . sort ( ) ;
92
+ return files ;
93
+ }
83
94
84
- const verb = options . decompress ? 'decompress' : 'compress' ;
95
+ function processFiles ( files , isDecompress , keep ) {
96
+ const verb = isDecompress ? 'decompress' : 'compress' ;
85
97
console . log ( `Found ${ files . length } files to ${ verb } ` + ( files . length ? ':' : '.' ) ) ;
86
98
87
- for ( const inputFile of files ) {
88
- try {
89
- console . log ( inputFile ) ;
99
+ // For printing overall statistics at the end.
100
+ let totalInputSize = 0 ;
101
+ let totalOutputSize = 0 ;
90
102
91
- // Copy the mode over to avoid git status entries after a roundtrip.
92
- const { mode } = fs . statSync ( inputFile ) ;
93
- const inputData = fs . readFileSync ( inputFile ) ;
94
- const outputData = options . decompress ? decompress ( inputData ) : compress ( inputData ) ;
95
- let outputFile ;
96
- if ( options . decompress ) {
97
- outputFile = inputFile . endsWith ( '.z' ) ? inputFile . slice ( 0 , - 2 ) : `${ inputFile } .decompressed` ;
103
+ for ( const inputFilename of files ) {
104
+ try {
105
+ console . log ( inputFilename ) ;
106
+ let outputFilename ;
107
+ if ( isDecompress ) {
108
+ if ( path . extname ( inputFilename ) !== '.z' ) {
109
+ console . warn ( ` Warning: Input file does not have a .z extension.` ) ;
110
+ outputFilename = `${ inputFilename } .decompressed` ;
111
+ } else {
112
+ outputFilename = inputFilename . slice ( 0 , - 2 ) ;
113
+ }
114
+ console . log ( ` Decompressing to: ${ outputFilename } ` ) ;
98
115
} else {
99
- outputFile = `${ inputFile } .z` ;
116
+ outputFilename = `${ inputFilename } .z` ;
100
117
}
101
- fs . writeFileSync ( outputFile , outputData , { mode } ) ;
102
118
103
- if ( ! options . keep ) {
104
- fs . unlinkSync ( inputFile ) ;
119
+ // Copy the mode over to avoid git status entries after a roundtrip.
120
+ const { mode } = fs . statSync ( inputFilename ) ;
121
+ const inputData = fs . readFileSync ( inputFilename ) ;
122
+ const outputData = isDecompress ? decompress ( inputData ) : compress ( inputData ) ;
123
+ fs . writeFileSync ( outputFilename , outputData , { mode } ) ;
124
+
125
+ totalInputSize += inputData . length ;
126
+ totalOutputSize += outputData . length ;
127
+
128
+ if ( ! keep ) {
129
+ fs . unlinkSync ( inputFilename ) ;
105
130
console . log ( ` Deleted input file.` ) ;
106
131
}
107
132
} catch ( err ) {
108
- console . error ( `Error ${ verb } ing ${ inputFile } :` , err ) ;
133
+ console . error ( `Error ${ verb } ing ${ inputFilename } :` , err ) ;
134
+ }
135
+ }
136
+
137
+ if ( files . length > 1 ) {
138
+ if ( isDecompress ) {
139
+ const totalExpansionRatio = calculateExpansionRatio ( totalInputSize , totalOutputSize ) ;
140
+ console . log ( `Total compressed sizes: ${ String ( totalInputSize ) . padStart ( 9 ) } bytes` ) ;
141
+ console . log ( `Total decompressed sizes: ${ String ( totalOutputSize ) . padStart ( 9 ) } bytes` ) ;
142
+ console . log ( `Average expansion ratio: ${ totalExpansionRatio . toFixed ( 2 ) . padStart ( 9 ) } %` ) ;
143
+ } else {
144
+ const totalCompressionRatio = calculateCompressionRatio ( totalInputSize , totalOutputSize ) ;
145
+ console . log ( `Total original sizes: ${ String ( totalInputSize ) . padStart ( 9 ) } bytes` ) ;
146
+ console . log ( `Total compressed sizes: ${ String ( totalOutputSize ) . padStart ( 9 ) } bytes` ) ;
147
+ console . log ( `Average compression ratio: ${ totalCompressionRatio . toFixed ( 2 ) . padStart ( 9 ) } %` ) ;
109
148
}
110
149
}
111
150
}
112
151
113
152
const options = parseCommandLineArgs ( ) ;
114
- processFiles ( options ) ;
115
-
153
+ const files = globsToFiles ( options . globs ) ;
154
+ processFiles ( files , options . decompress , options . keep ) ;
0 commit comments