1
1
use std:: collections:: HashMap ;
2
2
use std:: path:: PathBuf ;
3
- use std:: { fs, io, result} ;
3
+ use std:: fs;
4
+ use std:: io:: Read ;
4
5
5
6
use crate :: global_fns:: helpers:: search_for_file;
6
7
use config:: Config ;
@@ -10,20 +11,20 @@ use libs::tera::{from_value, to_value, Function as TeraFn, Result, Value};
10
11
use libs:: url;
11
12
use utils:: site:: resolve_internal_link;
12
13
13
- fn compute_file_hash < D : digest:: Digest > (
14
- mut file : fs :: File ,
14
+ fn compute_hash < D : digest:: Digest > (
15
+ literal : String ,
15
16
as_base64 : bool ,
16
- ) -> result :: Result < String , io :: Error >
17
+ ) -> String
17
18
where
18
19
digest:: Output < D > : core:: fmt:: LowerHex ,
19
20
D : std:: io:: Write ,
20
21
{
21
22
let mut hasher = D :: new ( ) ;
22
- io :: copy ( & mut file , & mut hasher) ? ;
23
+ hasher. update ( literal ) ;
23
24
if as_base64 {
24
- Ok ( encode_b64 ( hasher. finalize ( ) ) )
25
+ encode_b64 ( hasher. finalize ( ) )
25
26
} else {
26
- Ok ( format ! ( "{:x}" , hasher. finalize( ) ) )
27
+ format ! ( "{:x}" , hasher. finalize( ) )
27
28
}
28
29
}
29
30
@@ -128,7 +129,13 @@ impl TeraFn for GetUrl {
128
129
)
129
130
. map_err ( |e| format ! ( "`get_url`: {}" , e) ) ?
130
131
. and_then ( |( p, _) | fs:: File :: open ( & p) . ok ( ) )
131
- . and_then ( |f| compute_file_hash :: < Sha256 > ( f, false ) . ok ( ) )
132
+ . and_then ( |mut f| {
133
+ let mut contents = String :: new ( ) ;
134
+
135
+ f. read_to_string ( & mut contents) . ok ( ) ?;
136
+
137
+ Some ( compute_hash :: < Sha256 > ( contents, false ) )
138
+ } )
132
139
{
133
140
Some ( hash) => {
134
141
permalink = format ! ( "{}?h={}" , permalink, hash) ;
@@ -166,71 +173,99 @@ impl TeraFn for GetUrl {
166
173
}
167
174
168
175
#[ derive( Debug ) ]
169
- pub struct GetFileHash {
176
+ pub struct GetHash {
170
177
base_path : PathBuf ,
171
178
theme : Option < String > ,
172
179
output_path : PathBuf ,
173
180
}
174
- impl GetFileHash {
181
+ impl GetHash {
175
182
pub fn new ( base_path : PathBuf , theme : Option < String > , output_path : PathBuf ) -> Self {
176
183
Self { base_path, theme, output_path }
177
184
}
178
185
}
179
186
180
- impl TeraFn for GetFileHash {
187
+ impl TeraFn for GetHash {
181
188
fn call ( & self , args : & HashMap < String , Value > ) -> Result < Value > {
182
- let path = required_arg ! (
189
+ let path = optional_arg ! (
183
190
String ,
184
191
args. get( "path" ) ,
185
- "`get_file_hash` requires a `path` argument with a string value"
192
+ "`get_hash` requires either a `path` or a `literal` argument with a string value"
193
+ ) ;
194
+
195
+ let literal = optional_arg ! (
196
+ String ,
197
+ args. get( "literal" ) ,
198
+ "`get_hash` requires either a `path` or a `literal` argument with a string value"
186
199
) ;
200
+
201
+ let contents = match ( path, literal) {
202
+ ( Some ( _) , Some ( _) ) => {
203
+ return Err ( "`get_hash`: must have only one of `path` or `literal` argument" . into ( ) ) ;
204
+ } ,
205
+ ( None , None ) => {
206
+ return Err ( "`get_hash`: must have at least one of `path` or `literal` argument" . into ( ) ) ;
207
+ } ,
208
+ ( Some ( path_v) , None ) => {
209
+ let file_path =
210
+ match search_for_file ( & self . base_path , & path_v, & self . theme , & self . output_path )
211
+ . map_err ( |e| format ! ( "`get_hash`: {}" , e) ) ?
212
+ {
213
+ Some ( ( f, _) ) => f,
214
+ None => {
215
+ return Err ( format ! ( "`get_hash`: Cannot find file: {}" , path_v) . into ( ) ) ;
216
+ }
217
+ } ;
218
+
219
+ let mut f = match std:: fs:: File :: open ( file_path) {
220
+ Ok ( f) => f,
221
+ Err ( e) => {
222
+ return Err ( format ! ( "File {} could not be open: {}" , path_v, e) . into ( ) ) ;
223
+ }
224
+ } ;
225
+
226
+ let mut contents = String :: new ( ) ;
227
+
228
+ match f. read_to_string ( & mut contents) {
229
+ Ok ( f) => f,
230
+ Err ( e) => {
231
+ return Err ( format ! ( "File {} could not be read: {}" , path_v, e) . into ( ) ) ;
232
+ }
233
+ } ;
234
+
235
+ contents
236
+ }
237
+ ( None , Some ( literal_v) ) => { literal_v }
238
+ } ;
239
+
240
+
187
241
let sha_type = optional_arg ! (
188
242
u16 ,
189
243
args. get( "sha_type" ) ,
190
- "`get_file_hash `: `sha_type` must be 256, 384 or 512"
244
+ "`get_hash `: `sha_type` must be 256, 384 or 512"
191
245
)
192
246
. unwrap_or ( 384 ) ;
247
+
193
248
let base64 = optional_arg ! (
194
249
bool ,
195
250
args. get( "base64" ) ,
196
- "`get_file_hash `: `base64` must be true or false"
251
+ "`get_hash `: `base64` must be true or false"
197
252
)
198
253
. unwrap_or ( true ) ;
199
254
200
- let file_path =
201
- match search_for_file ( & self . base_path , & path, & self . theme , & self . output_path )
202
- . map_err ( |e| format ! ( "`get_file_hash`: {}" , e) ) ?
203
- {
204
- Some ( ( f, _) ) => f,
205
- None => {
206
- return Err ( format ! ( "`get_file_hash`: Cannot find file: {}" , path) . into ( ) ) ;
207
- }
208
- } ;
209
-
210
- let f = match std:: fs:: File :: open ( file_path) {
211
- Ok ( f) => f,
212
- Err ( e) => {
213
- return Err ( format ! ( "File {} could not be open: {}" , path, e) . into ( ) ) ;
214
- }
215
- } ;
216
-
217
255
let hash = match sha_type {
218
- 256 => compute_file_hash :: < Sha256 > ( f , base64) ,
219
- 384 => compute_file_hash :: < Sha384 > ( f , base64) ,
220
- 512 => compute_file_hash :: < Sha512 > ( f , base64) ,
221
- _ => return Err ( "`get_file_hash `: Invalid sha value" . into ( ) ) ,
256
+ 256 => compute_hash :: < Sha256 > ( contents , base64) ,
257
+ 384 => compute_hash :: < Sha384 > ( contents , base64) ,
258
+ 512 => compute_hash :: < Sha512 > ( contents , base64) ,
259
+ _ => return Err ( "`get_hash `: Invalid sha value" . into ( ) ) ,
222
260
} ;
223
261
224
- match hash {
225
- Ok ( digest) => Ok ( to_value ( digest) . unwrap ( ) ) ,
226
- Err ( _) => Err ( "`get_file_hash`: could no compute hash" . into ( ) ) ,
227
- }
262
+ Ok ( to_value ( hash) . unwrap ( ) )
228
263
}
229
264
}
230
265
231
266
#[ cfg( test) ]
232
267
mod tests {
233
- use super :: { GetFileHash , GetUrl } ;
268
+ use super :: { GetHash , GetUrl } ;
234
269
235
270
use std:: collections:: HashMap ;
236
271
use std:: fs:: create_dir;
@@ -456,7 +491,7 @@ title = "A title"
456
491
#[ test]
457
492
fn can_get_file_hash_sha256_no_base64 ( ) {
458
493
let dir = create_temp_dir ( ) ;
459
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
494
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
460
495
let mut args = HashMap :: new ( ) ;
461
496
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
462
497
args. insert ( "sha_type" . to_string ( ) , to_value ( 256 ) . unwrap ( ) ) ;
@@ -470,7 +505,7 @@ title = "A title"
470
505
#[ test]
471
506
fn can_get_file_hash_sha256_base64 ( ) {
472
507
let dir = create_temp_dir ( ) ;
473
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
508
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
474
509
let mut args = HashMap :: new ( ) ;
475
510
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
476
511
args. insert ( "sha_type" . to_string ( ) , to_value ( 256 ) . unwrap ( ) ) ;
@@ -481,7 +516,7 @@ title = "A title"
481
516
#[ test]
482
517
fn can_get_file_hash_sha384_no_base64 ( ) {
483
518
let dir = create_temp_dir ( ) ;
484
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
519
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
485
520
let mut args = HashMap :: new ( ) ;
486
521
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
487
522
args. insert ( "base64" . to_string ( ) , to_value ( false ) . unwrap ( ) ) ;
@@ -494,7 +529,7 @@ title = "A title"
494
529
#[ test]
495
530
fn can_get_file_hash_sha384 ( ) {
496
531
let dir = create_temp_dir ( ) ;
497
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
532
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
498
533
let mut args = HashMap :: new ( ) ;
499
534
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
500
535
assert_eq ! (
@@ -506,7 +541,7 @@ title = "A title"
506
541
#[ test]
507
542
fn can_get_file_hash_sha512_no_base64 ( ) {
508
543
let dir = create_temp_dir ( ) ;
509
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
544
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
510
545
let mut args = HashMap :: new ( ) ;
511
546
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
512
547
args. insert ( "sha_type" . to_string ( ) , to_value ( 512 ) . unwrap ( ) ) ;
@@ -520,7 +555,7 @@ title = "A title"
520
555
#[ test]
521
556
fn can_get_file_hash_sha512 ( ) {
522
557
let dir = create_temp_dir ( ) ;
523
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
558
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
524
559
let mut args = HashMap :: new ( ) ;
525
560
args. insert ( "path" . to_string ( ) , to_value ( "app.css" ) . unwrap ( ) ) ;
526
561
args. insert ( "sha_type" . to_string ( ) , to_value ( 512 ) . unwrap ( ) ) ;
@@ -530,6 +565,85 @@ title = "A title"
530
565
) ;
531
566
}
532
567
568
+ #[ test]
569
+ fn can_get_hash_sha256_no_base64 ( ) {
570
+ let dir = create_temp_dir ( ) ;
571
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
572
+ let mut args = HashMap :: new ( ) ;
573
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
574
+ args. insert ( "sha_type" . to_string ( ) , to_value ( 256 ) . unwrap ( ) ) ;
575
+ args. insert ( "base64" . to_string ( ) , to_value ( false ) . unwrap ( ) ) ;
576
+ assert_eq ! (
577
+ static_fn. call( & args) . unwrap( ) ,
578
+ "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
579
+ ) ;
580
+ }
581
+
582
+ #[ test]
583
+ fn can_get_hash_sha256_base64 ( ) {
584
+ let dir = create_temp_dir ( ) ;
585
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
586
+ let mut args = HashMap :: new ( ) ;
587
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
588
+ args. insert ( "sha_type" . to_string ( ) , to_value ( 256 ) . unwrap ( ) ) ;
589
+ args. insert ( "base64" . to_string ( ) , to_value ( true ) . unwrap ( ) ) ;
590
+ assert_eq ! (
591
+ static_fn. call( & args) . unwrap( ) ,
592
+ "pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=" ) ;
593
+ }
594
+
595
+ #[ test]
596
+ fn can_get_hash_sha384_no_base64 ( ) {
597
+ let dir = create_temp_dir ( ) ;
598
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
599
+ let mut args = HashMap :: new ( ) ;
600
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
601
+ args. insert ( "base64" . to_string ( ) , to_value ( false ) . unwrap ( ) ) ;
602
+ assert_eq ! (
603
+ static_fn. call( & args) . unwrap( ) ,
604
+ "99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f"
605
+ ) ;
606
+ }
607
+
608
+ #[ test]
609
+ fn can_get_hash_sha384 ( ) {
610
+ let dir = create_temp_dir ( ) ;
611
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
612
+ let mut args = HashMap :: new ( ) ;
613
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
614
+ assert_eq ! (
615
+ static_fn. call( & args) . unwrap( ) ,
616
+ "mVFDKRhrL2rkoTKefubGEKcpY2M1F0rGt0D5AoOW/MgD0Ok4Y6fD2Q+Gvu54L08/"
617
+ ) ;
618
+ }
619
+
620
+ #[ test]
621
+ fn can_get_hash_sha512_no_base64 ( ) {
622
+ let dir = create_temp_dir ( ) ;
623
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
624
+ let mut args = HashMap :: new ( ) ;
625
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
626
+ args. insert ( "sha_type" . to_string ( ) , to_value ( 512 ) . unwrap ( ) ) ;
627
+ args. insert ( "base64" . to_string ( ) , to_value ( false ) . unwrap ( ) ) ;
628
+ assert_eq ! (
629
+ static_fn. call( & args) . unwrap( ) ,
630
+ "2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b"
631
+ ) ;
632
+ }
633
+
634
+ #[ test]
635
+ fn can_get_hash_sha512 ( ) {
636
+ let dir = create_temp_dir ( ) ;
637
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
638
+ let mut args = HashMap :: new ( ) ;
639
+ args. insert ( "literal" . to_string ( ) , to_value ( "Hello World" ) . unwrap ( ) ) ;
640
+ args. insert ( "sha_type" . to_string ( ) , to_value ( 512 ) . unwrap ( ) ) ;
641
+ assert_eq ! (
642
+ static_fn. call( & args) . unwrap( ) ,
643
+ "LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw=="
644
+ ) ;
645
+ }
646
+
533
647
#[ test]
534
648
fn can_resolve_asset_path_to_valid_url ( ) {
535
649
let config = Config :: parse ( CONFIG_DATA ) . unwrap ( ) ;
@@ -540,7 +654,7 @@ title = "A title"
540
654
args. insert (
541
655
"path" . to_string ( ) ,
542
656
to_value ( dir. path ( ) . join ( "app.css" ) . strip_prefix ( std:: env:: temp_dir ( ) ) . unwrap ( ) )
543
- . unwrap ( ) ,
657
+ . unwrap ( ) ,
544
658
) ;
545
659
assert_eq ! (
546
660
static_fn. call( & args) . unwrap( ) ,
@@ -554,7 +668,7 @@ title = "A title"
554
668
#[ test]
555
669
fn error_when_file_not_found_for_hash ( ) {
556
670
let dir = create_temp_dir ( ) ;
557
- let static_fn = GetFileHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
671
+ let static_fn = GetHash :: new ( dir. into_path ( ) , None , PathBuf :: new ( ) ) ;
558
672
let mut args = HashMap :: new ( ) ;
559
673
args. insert ( "path" . to_string ( ) , to_value ( "doesnt-exist" ) . unwrap ( ) ) ;
560
674
let err = format ! ( "{}" , static_fn. call( & args) . unwrap_err( ) ) ;
0 commit comments