Browse Source

avoid rebuilding unchanged image files

Ondřej Hruška 4 months ago
parent
commit
7cb1bb11b2
Signed by: Ondřej Hruška <ondra@ondrovo.com> GPG key ID: 2C5FD5035250423D
5 changed files with 182 additions and 10 deletions
  1. 1 0
      .gitignore
  2. 75 0
      Cargo.lock
  3. 2 0
      Cargo.toml
  4. 64 0
      src/hash_dict.rs
  5. 40 10
      src/main.rs

+ 1 - 0
.gitignore View File

@@ -1,3 +1,4 @@
1 1
 /target
2 2
 **/*.rs.bk
3 3
 .idea/
4
+.hashes.txt

+ 75 - 0
Cargo.lock View File

@@ -47,6 +47,14 @@ dependencies = [
47 47
 ]
48 48
 
49 49
 [[package]]
50
+name = "base64"
51
+version = "0.10.1"
52
+source = "registry+https://github.com/rust-lang/crates.io-index"
53
+dependencies = [
54
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
55
+]
56
+
57
+[[package]]
50 58
 name = "bitflags"
51 59
 version = "0.7.0"
52 60
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -57,9 +65,22 @@ version = "1.0.4"
57 65
 source = "registry+https://github.com/rust-lang/crates.io-index"
58 66
 
59 67
 [[package]]
68
+name = "blake2"
69
+version = "0.8.0"
70
+source = "registry+https://github.com/rust-lang/crates.io-index"
71
+dependencies = [
72
+ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
73
+ "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
74
+ "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
75
+ "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
76
+]
77
+
78
+[[package]]
60 79
 name = "bread"
61 80
 version = "0.1.0"
62 81
 dependencies = [
82
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
83
+ "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
63 84
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
64 85
  "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
65 86
  "image-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -69,6 +90,11 @@ dependencies = [
69 90
 ]
70 91
 
71 92
 [[package]]
93
+name = "byte-tools"
94
+version = "0.3.0"
95
+source = "registry+https://github.com/rust-lang/crates.io-index"
96
+
97
+[[package]]
72 98
 name = "byteorder"
73 99
 version = "1.2.7"
74 100
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -130,6 +156,15 @@ dependencies = [
130 156
 ]
131 157
 
132 158
 [[package]]
159
+name = "crypto-mac"
160
+version = "0.7.0"
161
+source = "registry+https://github.com/rust-lang/crates.io-index"
162
+dependencies = [
163
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
164
+ "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
165
+]
166
+
167
+[[package]]
133 168
 name = "darling"
134 169
 version = "0.8.3"
135 170
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -193,6 +228,14 @@ dependencies = [
193 228
 ]
194 229
 
195 230
 [[package]]
231
+name = "digest"
232
+version = "0.8.0"
233
+source = "registry+https://github.com/rust-lang/crates.io-index"
234
+dependencies = [
235
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
236
+]
237
+
238
+[[package]]
196 239
 name = "either"
197 240
 version = "1.5.0"
198 241
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -239,6 +282,14 @@ version = "1.0.6"
239 282
 source = "registry+https://github.com/rust-lang/crates.io-index"
240 283
 
241 284
 [[package]]
285
+name = "generic-array"
286
+version = "0.12.0"
287
+source = "registry+https://github.com/rust-lang/crates.io-index"
288
+dependencies = [
289
+ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
290
+]
291
+
292
+[[package]]
242 293
 name = "gif"
243 294
 version = "0.9.2"
244 295
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -461,6 +512,11 @@ dependencies = [
461 512
 ]
462 513
 
463 514
 [[package]]
515
+name = "opaque-debug"
516
+version = "0.2.1"
517
+source = "registry+https://github.com/rust-lang/crates.io-index"
518
+
519
+[[package]]
464 520
 name = "percent-encoding"
465 521
 version = "1.0.1"
466 522
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -601,6 +657,11 @@ version = "0.3.3"
601 657
 source = "registry+https://github.com/rust-lang/crates.io-index"
602 658
 
603 659
 [[package]]
660
+name = "subtle"
661
+version = "1.0.0"
662
+source = "registry+https://github.com/rust-lang/crates.io-index"
663
+
664
+[[package]]
604 665
 name = "syn"
605 666
 version = "0.15.26"
606 667
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -651,6 +712,11 @@ dependencies = [
651 712
 ]
652 713
 
653 714
 [[package]]
715
+name = "typenum"
716
+version = "1.10.0"
717
+source = "registry+https://github.com/rust-lang/crates.io-index"
718
+
719
+[[package]]
654 720
 name = "ucd-util"
655 721
 version = "0.1.3"
656 722
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -691,8 +757,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
691 757
 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
692 758
 "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
693 759
 "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
760
+"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
694 761
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
695 762
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
763
+"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e"
764
+"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
696 765
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
697 766
 "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
698 767
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
@@ -701,18 +770,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
701 770
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
702 771
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
703 772
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
773
+"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
704 774
 "checksum darling 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "540f3246eaeecb3fc7ff9ac258f8958a57d3d87a637466fd5ad077663eabae80"
705 775
 "checksum darling_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69e5f4498f3c21a65d0477542d691dac79b0f44048f5174901fdbf1b676b94b7"
706 776
 "checksum darling_macro 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c04b3c08354a7d8a70d633931852de9e11b664881d8dd4d686e6bc7761e7fd"
707 777
 "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
708 778
 "checksum derive_builder 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15d9e4f0be540b522e95c1de6200be0b12946fdd8408c093a1948de638e16f55"
709 779
 "checksum derive_builder_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cffc940f53a89045824e676302b840a5a60d447560704d352316e2039125a2"
780
+"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
710 781
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
711 782
 "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7"
712 783
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
713 784
 "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
714 785
 "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
715 786
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
787
+"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
716 788
 "checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f"
717 789
 "checksum gif 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e41945ba23db3bf51b24756d73d81acb4f28d85c3dccc32c6fae904438c25f"
718 790
 "checksum gif-dispose 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c14b308f5d2295408f2bddc6628aec17382486357e7d9aed7fcd76e30a11c41"
@@ -740,6 +812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
740 812
 "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
741 813
 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
742 814
 "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238"
815
+"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682"
743 816
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
744 817
 "checksum pipeline 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0"
745 818
 "checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
@@ -758,11 +831,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
758 831
 "checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e"
759 832
 "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
760 833
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
834
+"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
761 835
 "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
762 836
 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
763 837
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
764 838
 "checksum tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2cc6c4fd13cb1cfd20abdb196e794ceccb29371855b7e7f575945f920a5b3c2"
765 839
 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
840
+"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
766 841
 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
767 842
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
768 843
 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"

+ 2 - 0
Cargo.toml View File

@@ -11,3 +11,5 @@ rss = "1.6.1"
11 11
 percent-encoding = "1.0.1"
12 12
 image-utils = "0.2.0"
13 13
 image = "0.21.0"
14
+blake2 = "0.8.0"
15
+base64 = "0.10.1"

+ 64 - 0
src/hash_dict.rs View File

@@ -0,0 +1,64 @@
1
+use std::collections::HashMap;
2
+use std::fs::File;
3
+use std::io::Read;
4
+use std::io::Write;
5
+use std::io;
6
+use std::path::PathBuf;
7
+
8
+// file-stored hash map used to prevent needless image regenerating
9
+#[derive(Debug)]
10
+pub struct HashDict {
11
+    hashes: HashMap<String, String>,
12
+    path: PathBuf,
13
+    any_change: bool,
14
+}
15
+
16
+impl HashDict {
17
+    pub fn load(path: PathBuf) -> Result<HashDict, io::Error>  {
18
+        let mut hd = HashDict {
19
+            hashes: HashMap::new(),
20
+            path,
21
+            any_change: false,
22
+        };
23
+
24
+        if !hd.path.exists() {
25
+            return Ok(hd);
26
+        }
27
+
28
+        let mut f = File::open(&hd.path)?;
29
+        let mut s = String::new();
30
+        f.read_to_string(&mut s)?;
31
+
32
+        let lines: Vec<&str> = s.split("\n").collect();
33
+        for l in lines {
34
+            let halves: Vec<&str> = l.split("\t").collect();
35
+            if halves.len() == 2 {
36
+                hd.hashes.insert(halves[0].to_string(), halves[1].to_string());
37
+            }
38
+        }
39
+
40
+        Ok(hd)
41
+    }
42
+
43
+    pub fn get(&self, key : &str) -> Option<&String> {
44
+        self.hashes.get(key)
45
+    }
46
+
47
+    pub fn put(&mut self, key : String, value: String) {
48
+        self.hashes.insert(key, value);
49
+        self.any_change = true;
50
+    }
51
+
52
+    pub fn save(&mut self) {
53
+        if self.any_change || !self.path.exists() {
54
+            let mut f = File::create(&self.path).unwrap();
55
+            let mut buf = String::new();
56
+            for (k, v) in &self.hashes {
57
+                buf.push_str(&format!("{}\t{}\n", k, v));
58
+            }
59
+            f.write(buf.as_ref()).unwrap();
60
+
61
+            self.any_change = false;
62
+        }
63
+    }
64
+}

+ 40 - 10
src/main.rs View File

@@ -1,4 +1,5 @@
1 1
 use std::env;
2
+use std::io;
2 3
 use std::fs;
3 4
 use std::fs::DirEntry;
4 5
 use std::fs::File;
@@ -14,6 +15,11 @@ use image_utils;
14 15
 use chrono::offset::TimeZone;
15 16
 use chrono::Date;
16 17
 use chrono::Utc;
18
+use blake2::{Digest,Blake2b};
19
+
20
+use base64;
21
+
22
+mod hash_dict;
17 23
 
18 24
 #[derive(Debug)]
19 25
 struct Bread {
@@ -119,11 +125,15 @@ fn main() {
119 125
 
120 126
     let mut channel_items = Vec::<Item>::new();
121 127
 
128
+    let mut hashes = hash_dict::HashDict::load(cwd.join(".hashes.txt")).unwrap();
129
+
122 130
     for bread in &breads {
123 131
         let date = bread.date.format("%Y/%m/%d").to_string();
124 132
         let date_slug = bread.date.format("%Y-%m-%d").to_string();
125 133
         let detail_file = date_slug.clone() + ".html";
126 134
 
135
+        println!("+ {}", date_slug);
136
+
127 137
         let (img_path, img_alt) = bread.thumb_photo();
128 138
         let note = if bread.note.is_empty() { "<i>There's no note about this bread.</i>" } else { &bread.note };
129 139
 
@@ -133,14 +143,30 @@ fn main() {
133 143
 
134 144
         let image_path_encoded = utf8_percent_encode(thumb_relpath.to_str().unwrap(), DEFAULT_ENCODE_SET).to_string();
135 145
 
136
-        let im = image::open(&web_path.join(img_path)).unwrap();
137
-        let im = im.thumbnail(500, 500);
138
-        //let mut output = File::create(&thumb_path);
139
-        im.save(&thumb_path).unwrap();
146
+        // TODO keep the original path in bread so we dont have to reconstruct it here
147
+        let image_real_path = web_path.join(img_path);
148
+
149
+        // Create the thumb
150
+        {
151
+            let mut img_file = fs::File::open(&image_real_path).unwrap();
152
+            let mut hasher = Blake2b::new();
153
+            io::copy(&mut img_file, &mut hasher).unwrap();
154
+            let hash = base64::encode(&hasher.result());
140 155
 
141
-        //image_utils::resize(&web_path.join(img_path), 500, 500, &thumb_path).unwrap();
156
+            let hash_key = thumb_path.to_str().unwrap();
157
+            let old_hash = hashes.get(hash_key);
158
+            if old_hash.is_none() || !old_hash.unwrap().eq(&hash) {
159
+                println!("building thumb...");
142 160
 
143
-        // bread pic for the thumbnails page
161
+                let im = image::open(&image_real_path).unwrap();
162
+                let im = im.thumbnail(500, 500);
163
+                im.save(&thumb_path).unwrap();
164
+
165
+                hashes.put(hash_key.to_string(), hash);
166
+            }
167
+        }
168
+
169
+        // Prepare the thumb card for the gallery page
144 170
         {
145 171
             let thumb = thumb_tpl
146 172
                 .replace("{detail_url}", &detail_file)
@@ -151,7 +177,7 @@ fn main() {
151 177
             thumbs.push_str(&thumb);
152 178
         }
153 179
 
154
-        // add to rss
180
+        // Add to RSS
155 181
         {
156 182
             let image_url : String = channel.link().to_string() + "/" + &image_path_encoded;
157 183
 
@@ -172,7 +198,7 @@ fn main() {
172 198
                 .build().unwrap());
173 199
         }
174 200
 
175
-        // generate the detail page
201
+        // Generate the detail page
176 202
         {
177 203
             let detail = detail_tpl
178 204
                 .replace("{head}", &head_tpl.replace("{title}", &format!("Bread from {}", date)).trim())
@@ -191,15 +217,19 @@ fn main() {
191 217
         }
192 218
     }
193 219
 
194
-    let main = main_tpl.replace("{breads}", &thumbs.trim())
195
-                       .replace("{head}", &head_tpl.replace("{title}", "Piggo's breads").trim());
220
+    hashes.save();
196 221
 
197 222
     {
223
+        println!("Building the gallery page");
224
+        let main = main_tpl.replace("{breads}", &thumbs.trim())
225
+            .replace("{head}", &head_tpl.replace("{title}", "Piggo's breads").trim());
226
+
198 227
         let mut f = OpenOptions::new().write(true).truncate(true).create(true).open(web_path.join("index.html")).unwrap();
199 228
         f.write(main.as_bytes()).unwrap();
200 229
     }
201 230
 
202 231
     {
232
+        println!("Generating feed...");
203 233
         let f = OpenOptions::new().write(true).truncate(true).create(true).open(web_path.join("feed.xml")).unwrap();
204 234
         channel.set_items(channel_items);
205 235
         channel.pretty_write_to(f, b' ', 2).unwrap();