Skip to content

Commit 862902b

Browse files
committed
Improved output & new Release GitHub action
1 parent 6d570d6 commit 862902b

File tree

3 files changed

+104
-61
lines changed

3 files changed

+104
-61
lines changed

.github/workflows/rust.yml

+31-20
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
# .github/workflows/release.yml
22

33
on:
4-
push:
5-
branches: [ "main" ]
6-
pull_request:
7-
branches: [ "main" ]
4+
release:
5+
types:
6+
- created
87

98
jobs:
10-
release:
11-
name: release ${{ matrix.target }}
9+
linux_windows:
1210
runs-on: ubuntu-latest
13-
strategy:
14-
fail-fast: false
15-
matrix:
16-
include:
17-
- target: x86_64-pc-windows-gnu
18-
archive: zip
19-
- target: x86_64-unknown-linux-musl
20-
archive: tar.gz tar.xz tar.zst
2111
steps:
22-
- uses: actions/checkout@master
23-
- name: Compile and release
24-
uses: rust-build/rust-build.action@v1.4.5
12+
- name: Checkout the repository
13+
uses: actions/checkout@v2
14+
15+
- name: Install Linux and Windows Cross Compilers
16+
run: sudo apt-get install --yes --no-install-recommends musl-tools gcc-mingw-w64-x86-64-win32
17+
18+
- name: Install rustup targets
19+
run: rustup target add x86_64-unknown-linux-musl x86_64-pc-windows-gnu
20+
21+
- name: Build the executable
22+
run: cargo build --release --target x86_64-unknown-linux-musl --target x86_64-pc-windows-gnu
23+
24+
- name: Tar x86_64 binary
25+
run: tar -czvf fingerprinter-rs-gnu-linux-x86_64.tar.gz -C target/x86_64-unknown-linux-musl/release fingerprinter-rs
26+
27+
- name: Zip windows binary
28+
run: zip -j fingerprinter-rs-windows.zip target/x86_64-pc-windows-gnu/release/fingerprinter-rs.exe
29+
30+
- name: Generate SHA256 checksums
31+
run: |
32+
shasum -a 256 fingerprinter-rs-gnu-linux-x86_64.tar.gz > fingerprinter-rs-gnu-linux-x86_64.tar.gz.sha256
33+
shasum -a 256 fingerprinter-rs-windows.zip > fingerprinter-rs-windows.zip.sha256
34+
35+
- name: Upload release binaries
36+
uses: alexellis/upload-assets@0.4.0
2537
env:
26-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38+
GITHUB_TOKEN: ${{ github.token }}
2739
with:
28-
RUSTTARGET: ${{ matrix.target }}
29-
ARCHIVE_TYPES: ${{ matrix.archive }}
40+
asset_paths: '["fingerprinter-rs-gnu-linux-x86_64.tar.gz", "fingerprinter-rs-windows.zip", "fingerprinter-rs-gnu-linux-x86_64.tar.gz.sha256", "fingerprinter-rs-windows.zip.sha256"]'

Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
[package]
22
name = "fingerprinter-rs"
3-
version = "0.1.0"
3+
version = "0.1.3"
44
edition = "2021"
55

66
[dependencies]
7-
clap = { version = "4.5.9", features = ["derive"] }
7+
clap = { version = "4.5.20", features = ["derive"] }
88
hex-literal = "0.4.1"
99
jwalk = "0.8.1"
1010
rayon = "1.10.0"
1111
sha2 = "0.10.8"
1212
walkdir = "2.5.0"
1313
xxhash-rust = { version = "0.8.12", features = ["xxh3"] }
1414

15-
serde_json = "1.0"
15+
serde_json = "1.0.132"
1616
serde = { version = "1.0.209", features = ["derive"] }
1717
chrono = "0.4.38"
1818

1919
# https://stackoverflow.com/a/54842093
2020
[profile.release]
21-
opt-level = 'z' # Optimize for size.
21+
opt-level = 'z' # Optimize for size.
2222
lto = true
2323
codegen-units=1
2424
panic = 'abort'

src/main.rs

+69-37
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ use sha2::{Digest, Sha256, Sha256VarCore};
1919
#[allow(unused_imports)]
2020
use xxhash_rust::xxh3::xxh3_64;
2121

22-
use std::env;
2322
use std::fs::*;
2423
use std::io;
25-
use std::io::{Read,Write};
24+
use std::io::{Read, Write};
2625
#[allow(unused_imports)]
2726
use std::path::{Path, PathBuf};
2827
use std::sync::{Arc, Mutex};
29-
use std::time::{Duration, Instant};
30-
28+
use std::time::{Duration, Instant, UNIX_EPOCH};
29+
use std::{env, fs};
30+
use chrono::{DateTime, Local};
31+
use serde::Serialize;
3132
#[allow(unused_imports)]
3233
use serde_json::{json, Value};
33-
use serde::Serialize;
3434

3535
/// Simple path processor
3636
#[derive(Parser, Debug)]
@@ -50,16 +50,20 @@ struct Args {
5050
struct FileRecordSha256 {
5151
file: String,
5252
hash: Output<Sha256VarCore>,
53+
timestamp_mod: FileRecordsTimestamps,
54+
// timestamp_cre: FileRecordsTimestamps,
5355
}
5456

5557
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize)]
5658
#[allow(dead_code)]
5759
struct FileRecordXxhash {
5860
file: String,
59-
hash: u64
61+
hash: u64,
62+
timestamp_mod: FileRecordsTimestamps,
63+
// timestamp_cre: FileRecordsTimestamps,
6064
}
6165

62-
#[derive(Serialize)]
66+
#[derive(Serialize, Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
6367
struct FileRecordsTimestamps {
6468
epoch: u128,
6569
iso8601: String,
@@ -93,7 +97,7 @@ fn visit(path: &Path, cb: &mut dyn FnMut(PathBuf), exclude: Vec<&str>) -> io::Re
9397
// Only include files that don't have a component in the exclude vector
9498
// logic from: https://stackoverflow.com/a/29504547
9599
let match_count = components
96-
.iter()
100+
.par_iter()
97101
.filter(|&x| exclude.contains(&x.to_str().unwrap()))
98102
.count();
99103
if match_count == 0 {
@@ -142,7 +146,8 @@ fn main() {
142146

143147
// To switch from Sha256 <-> Xxhash: 4 steps - #2: Set res to the right output
144148
// let res: Result<(&str, Output<Sha256VarCore>), bool> = match f2 { // Sha256
145-
let res: Result<(&str, u64), bool> = match f2 { // xxhash
149+
let res: Result<(&str, u64), bool> = match f2 {
150+
// xxhash
146151
#[allow(unused_mut)]
147152
Ok(mut f2) => {
148153
// To switch from Sha256 <-> Xxhash: 4 steps - #3: Change the implementation block
@@ -165,20 +170,22 @@ fn main() {
165170

166171
// Save full path?
167172
// Working relative path
168-
let filename = <PathBuf as AsRef<Path>>::as_ref(f).to_str().unwrap_or_default();
173+
let filename = <PathBuf as AsRef<Path>>::as_ref(&f)
174+
.to_str()
175+
.unwrap_or_default();
169176
// Convert to absolute path
170177
// let filenameref = <PathBuf as AsRef<Path>>::as_ref(f);
171178
// let filename = filenameref.clone().canonicalize().unwrap().to_str().unwrap_or_default();
172-
// .clone().canonicalize().unwrap().to_str().unwrap_or_default();
179+
// .clone().canonicalize().unwrap().to_str().unwrap_or_default();
173180
// let fullpath = Path::new(filename.to_owned().as_str()).canonicalize().unwrap().to_str().unwrap_or_default();
174181
// TODO: Fix check for save_full_path argument
175182
// if args.safe_full;path {
176-
// Result::Ok((Path::new(fullpath.clone()).clone().canonicalize().unwrap().to_str().unwrap(),
177-
// xxhash_rust::xxh3::xxh3_64(&buffer)))
178-
// Result::Ok((filename, xxhash_rust::xxh3::xxh3_64(&buffer)))
183+
// Result::Ok((Path::new(fullpath.clone()).clone().canonicalize().unwrap().to_str().unwrap(),
184+
// xxhash_rust::xxh3::xxh3_64(&buffer)))
185+
// Result::Ok((filename, xxhash_rust::xxh3::xxh3_64(&buffer)))
179186
//
180187
// } else { // Only save relative path
181-
Result::Ok((filename, xxhash_rust::xxh3::xxh3_64(&buffer)))
188+
Result::Ok((filename, xxhash_rust::xxh3::xxh3_64(&buffer)))
182189
// }
183190
}
184191
Err(ref e) => {
@@ -187,45 +194,67 @@ fn main() {
187194
}
188195
};
189196
if res.is_ok() {
190-
// Create a new struct instance and populate with filename and filehash
191-
// To switch from Sha256 <-> Xxhash: 4 steps - #4: Change the record hash impl
192-
// Sha256
193-
// let frs = FileRecordSha256 {
194-
// filename: res.unwrap().0.to_owned(),
195-
// filehash: res.unwrap().1,
196-
// };
197-
// filelist.lock().unwrap().push(frs);
197+
let metadata =
198+
fs::metadata(res.unwrap().0).expect("Unable to get metadata for file: @203");
199+
if let Ok(modtime) = metadata.modified() {
200+
let modtimemillis = modtime.duration_since(UNIX_EPOCH).unwrap().as_millis();
201+
// let cretimemillis = metadata.created().unwrap().duration_since(UNIX_EPOCH).unwrap().as_millis();
202+
// Create a new struct instance and populate with filename and filehash
203+
// To switch from Sha256 <-> Xxhash: 4 steps - #4: Change the record hash impl
204+
// Sha256
205+
// let frs = FileRecordSha256 {
206+
// filename: res.unwrap().0.to_owned(),
207+
// filehash: res.unwrap().1,
208+
// timestamp_mod: FileRecordsTimestamps {
209+
// epoch: time.duration_since(UNIX_EPOCH).unwrap().as_millis(),
210+
// iso8601: DateTime::from_timestamp_millis(time.duration_since(UNIX_EPOCH).unwrap().as_millis() as i64).expect("Unable to parse timestamp").to_rfc3339(),
211+
// },
212+
// };
213+
// filelist.lock().unwrap().push(frs);
214+
215+
// Xxhash
198216

199-
// Xxhash
200-
let frs = FileRecordXxhash {
201-
file: res.unwrap().0.to_owned(),
202-
hash: res.unwrap().1,
203-
};
204-
filelist.lock().unwrap().push(frs);
217+
let frs = FileRecordXxhash {
218+
file: res.unwrap().0.to_owned(),
219+
hash: res.unwrap().1,
220+
timestamp_mod: FileRecordsTimestamps {
221+
epoch: modtimemillis,
222+
iso8601: DateTime::from_timestamp_millis(modtimemillis as i64).expect("Unable to parse timestamp").with_timezone(&Local::now().timezone()).to_rfc3339(),
223+
},
224+
// timestamp_cre: FileRecordsTimestamps {
225+
// epoch: cretimemillis,
226+
// iso8601: DateTime::from_timestamp_millis(cretimemillis as i64).expect("Unable to parse timestamp").with_timezone(&Local::now().timezone()).to_rfc3339(),
227+
// },
228+
};
229+
filelist.lock().unwrap().push(frs);
230+
}
205231
}
206232
});
207233

208234
// Now sort and print vector (filelist)
209235
// TODO: Avoid creating a new variable to hold the list
210236
let mut fls2 = filelist.lock().unwrap().to_vec();
211237
fls2.sort(); // It just works!
212-
let path_info = PathInfo{
238+
let path_info = PathInfo {
213239
base: path.canonicalize().unwrap().to_str().unwrap().to_owned(),
214240
cmdline: args.path.clone(),
215-
run_from: env::current_dir().unwrap().to_str().unwrap().to_owned()
241+
run_from: env::current_dir().unwrap().to_str().unwrap().to_owned(),
216242
};
217243
let file_record: FileRecordsXxhash = FileRecordsXxhash {
218244
path: path_info,
219245
updated_on: get_time().unwrap(),
220246
count: fls2.len(),
221-
files: fls2.clone()
247+
files: fls2.clone(),
222248
};
223249
let file_record_json = serde_json::to_string(&file_record).unwrap();
224250
// for i2 in fls2.iter() {
225251
// println!("{:?} == {:x}", i2.filename, i2.filehash);
226252
// }
227253

228-
File::create(args.output).unwrap().write_all(file_record_json.as_bytes()).unwrap();
254+
File::create(args.output)
255+
.unwrap()
256+
.write_all(file_record_json.as_bytes())
257+
.unwrap();
229258

230259
let dur: Duration = start.elapsed(); // End timer
231260
eprintln!("Time elapsed: {:?}", dur); // Show elapsed time to STDERR
@@ -235,8 +264,8 @@ fn get_time() -> Result<FileRecordsTimestamps, std::io::Error> {
235264
use std::time::{SystemTime, UNIX_EPOCH};
236265

237266
/* std::time attempt - can't format rfc3339 :(
238-
so switched to chrono
239-
*/
267+
so switched to chrono
268+
*/
240269
// let start = SystemTime::now();
241270
// let since_epoch = start
242271
// .duration_since(UNIX_EPOCH)
@@ -247,10 +276,13 @@ fn get_time() -> Result<FileRecordsTimestamps, std::io::Error> {
247276
// // (SystemTime::duration_from_millis(since_epoch).to_rfc3339()).to_string(),
248277
// })
249278

250-
use chrono::{Local};
279+
use chrono::Local;
251280

252281
Ok(FileRecordsTimestamps {
253-
epoch: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(),
282+
epoch: SystemTime::now()
283+
.duration_since(UNIX_EPOCH)
284+
.unwrap()
285+
.as_millis(),
254286
iso8601: Local::now().to_rfc3339(),
255287
})
256288
}

0 commit comments

Comments
 (0)