11use clap:: Parser ;
22use rand:: seq:: SliceRandom ;
33use serde:: Serialize ;
4+ use std:: collections:: HashSet ;
45use std:: error:: Error ;
6+ use std:: fs:: File ;
7+ use std:: io:: { BufRead , BufReader } ;
58
69// AWS SDK for Rust (1.x)
710use aws_config:: { load_defaults, BehaviorVersion } ;
@@ -28,6 +31,10 @@ struct Args {
2831 /// URL prefix to form the final URL (e.g. "https://api.example.com/s3/api/v1/resource?url=s3://")
2932 #[ arg( long, required = true ) ]
3033 url_prefix : String ,
34+
35+ /// File containing keys to exclude
36+ #[ arg( long, required = false ) ]
37+ exclude_file : Option < String > ,
3138}
3239
3340#[ derive( Serialize ) ]
@@ -50,6 +57,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
5057 let directory_prefix = & args. directory ;
5158 let url_prefix = & args. url_prefix ;
5259
60+ // Read excluded keys from file if provided
61+ let excluded_keys: HashSet < String > = if let Some ( exclude_file_path) = args. exclude_file {
62+ let file = File :: open ( & exclude_file_path) ?;
63+ BufReader :: new ( file) . lines ( ) . map_while ( Result :: ok) . collect ( )
64+ } else {
65+ HashSet :: new ( )
66+ } ;
67+
5368 let shared_config = load_defaults ( BehaviorVersion :: latest ( ) ) . await ;
5469 let s3_client = Client :: new ( & shared_config) ;
5570
@@ -77,6 +92,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
7792 let all_keys: Vec < String > = objects
7893 . iter ( )
7994 . filter_map ( |obj| obj. key ( ) . map ( str:: to_string) )
95+ . filter ( |key| !excluded_keys. contains ( key) )
8096 . collect ( ) ;
8197
8298 if all_keys. len ( ) < 2 {
@@ -91,12 +107,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
91107 let mut all_pairs = Vec :: new ( ) ;
92108 for ( i, source) in all_keys. iter ( ) . enumerate ( ) {
93109 // check if source is empty
94- if source. is_empty ( ) {
110+ if source. is_empty ( ) || source . ends_with ( '/' ) {
95111 continue ;
96112 }
97113 for ( j, candidate) in all_keys. iter ( ) . enumerate ( ) {
98114 // check if candidate is is_empty
99- if candidate. is_empty ( ) {
115+ if candidate. is_empty ( ) || candidate . ends_with ( '/' ) {
100116 continue ;
101117 }
102118 if i != j {
0 commit comments