Skip to content

Commit c97e89d

Browse files
committed
feat: Add delay options for metadata and file updates in sync arguments
Closes: #30
1 parent 7db3ad8 commit c97e89d

File tree

3 files changed

+80
-9
lines changed

3 files changed

+80
-9
lines changed

tsumugu-cli/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ Options:
7676
Ignore 403 FORBIDDEN as error when downloading files. It's recommended to use this with --no-delete if the upstream returns 403 non-deterministically or randomly
7777
--ignore-status <IGNORE_STATUS>
7878
Ignore given 4xx or 5xx status code as error when downloading files. Supports multiple
79+
--delay-update-metadata
80+
Do not update known package metadata till all other downloads are done
81+
--delay-update
82+
Do not update all existing files till all downloads are done
7983
-h, --help
8084
Print help
8185
-V, --version

tsumugu-cli/src/cli/sync.rs

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,31 @@ fn extension_push_task(worker: &Worker<Task>, wake: &AtomicUsize, package: &Exte
7575
);
7676
}
7777

78+
const KNOWN_METADATA_FILES: [&str; 10] = [
79+
// deb
80+
"Release",
81+
"Release.gpg",
82+
"InRelease",
83+
"Packages",
84+
"Packages.gz",
85+
"Packages.xz",
86+
"Sources",
87+
"Sources.gz",
88+
"Sources.xz",
89+
// rpm
90+
"repomd.xml",
91+
];
92+
93+
fn should_delay_update(args: &SyncArgs, item: &ListItem) -> bool {
94+
if args.delay_update {
95+
true
96+
} else if args.delay_update_metadata {
97+
KNOWN_METADATA_FILES.contains(&item.name.as_str())
98+
} else {
99+
false
100+
}
101+
}
102+
78103
fn download_file(
79104
task_context: &TaskContext,
80105
item: &ListItem,
@@ -84,6 +109,7 @@ fn download_file(
84109
cwd: &Path,
85110
check_header: bool,
86111
compare_size_only: bool,
112+
do_rename: bool,
87113
) -> Result<()> {
88114
let http_client = task_context.client;
89115
let runtime = &http_client.runtime;
@@ -157,12 +183,14 @@ fn download_file(
157183
.unwrap();
158184
}
159185
// move tmp file to expected path
160-
std::fs::rename(&tmp_path, path).unwrap_or_else(|_| {
161-
panic!(
162-
"renaming from {:?} to {:?} shall never fail",
163-
tmp_path, path
164-
)
165-
});
186+
if do_rename {
187+
std::fs::rename(&tmp_path, path).unwrap_or_else(|_| {
188+
panic!(
189+
"renaming from {:?} to {:?} shall never fail",
190+
tmp_path, path
191+
)
192+
});
193+
}
166194
bar.finish();
167195
bar.set_visible(false);
168196
Ok(())
@@ -181,6 +209,7 @@ struct ThreadsContext<'a> {
181209
failure_listing: &'a AtomicBool,
182210
failure_downloading: &'a AtomicBool,
183211
pb_manager: &'a kyuri::Manager,
212+
delayed_updates: &'a Arc<Mutex<Vec<PathBuf>>>,
184213
}
185214

186215
impl ThreadsContext<'_> {
@@ -462,6 +491,7 @@ fn download_handler(
462491
}
463492

464493
if should_download && !args.dry_run {
494+
let should_delay = should_delay_update(args, item) && expected_path.exists();
465495
if let Err(e) = download_file(
466496
task_context,
467497
item,
@@ -473,9 +503,18 @@ fn download_handler(
473503
!args.head_before_get && !args.trust_mtime_from_parser,
474504
// compare_size_only to give to should_download_by_header() inside (when check_header is true)
475505
compare_size_only,
476-
) && should_set_error(args, &e)
477-
{
478-
thr_context.mark_failure_downloading();
506+
!should_delay,
507+
) {
508+
if should_set_error(args, &e) {
509+
thr_context.mark_failure_downloading();
510+
}
511+
} else if should_delay {
512+
info!("Delaying update of {:?} to the end", expected_path);
513+
thr_context
514+
.delayed_updates
515+
.lock()
516+
.unwrap()
517+
.push(expected_path.clone());
479518
}
480519
} else if should_download {
481520
info!("Dry run, not downloading {}", task.url);
@@ -653,6 +692,7 @@ pub(crate) fn sync(args: &SyncArgs, bind_address: Option<String>, pb_manager: ky
653692
let download_dir = args.local.as_path();
654693

655694
let remote_list = Arc::new(Mutex::new(HashSet::new()));
695+
let delayed_updates = Arc::new(Mutex::new(Vec::new()));
656696

657697
let stat_objects = AtomicUsize::new(0);
658698
let stat_size = AtomicU64::new(0);
@@ -672,9 +712,28 @@ pub(crate) fn sync(args: &SyncArgs, bind_address: Option<String>, pb_manager: ky
672712
failure_listing: &failure_listing,
673713
failure_downloading: &failure_downloading,
674714
pb_manager: &pb_manager,
715+
delayed_updates: &delayed_updates,
675716
},
676717
);
677718

719+
// Process delayed updates
720+
{
721+
let delayed_updates = delayed_updates.lock().unwrap();
722+
for path in delayed_updates.iter() {
723+
info!("Updating delayed file {:?}", path);
724+
let tmp_path = path.with_file_name(format!(
725+
".tmp.{}",
726+
path.file_name().unwrap().to_string_lossy()
727+
));
728+
std::fs::rename(&tmp_path, path).unwrap_or_else(|_| {
729+
panic!(
730+
"renaming from {:?} to {:?} shall never fail",
731+
tmp_path, path
732+
)
733+
});
734+
}
735+
}
736+
678737
let mut exit_code = 0;
679738

680739
// Removing files that are not in remote list

tsumugu-cli/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ pub struct SyncArgs {
205205
/// Ignore given 4xx or 5xx status code as error when downloading files. Supports multiple.
206206
#[clap(long, value_parser = http_error_code)]
207207
ignore_status: Vec<u16>,
208+
209+
/// Do not update known package metadata till all other downloads are done.
210+
#[clap(long)]
211+
delay_update_metadata: bool,
212+
213+
/// Do not update all existing files till all downloads are done.
214+
#[clap(long)]
215+
delay_update: bool,
208216
}
209217

210218
#[derive(Parser, Debug)]

0 commit comments

Comments
 (0)