Skip to content

Commit 178f408

Browse files
authored
Support archive (tarball/zip) submissions for model competitions (#34)
- Read submission files as bytes (Vec<u8>) instead of String to handle binary archives without crashing on invalid UTF-8 - Change submit_solution signature from &str to &[u8] for file content - Add is_archive_file() helper to detect .tar.gz, .tgz, .zip files - Skip popcorn directive parsing for archive files (return empty directives)
1 parent 041d0e2 commit 178f408

3 files changed

Lines changed: 30 additions & 9 deletions

File tree

src/cmd/submit.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,10 @@ impl App {
295295
.clone()
296296
.ok_or_else(|| anyhow!("Submission mode not selected"))?;
297297

298-
// Read file content
298+
// Read file content as bytes (supports both text and archive files)
299299
let mut file = File::open(&filepath)?;
300-
let mut file_content = String::new();
301-
file.read_to_string(&mut file_content)?;
300+
let mut file_content = Vec::new();
301+
file.read_to_end(&mut file_content)?;
302302

303303
self.submission_task = Some(tokio::spawn(async move {
304304
service::submit_solution(
@@ -734,10 +734,10 @@ pub async fn run_submit_plain(
734734
anyhow!("Submission mode not specified. Use --mode flag (test, benchmark, leaderboard, profile)")
735735
})?;
736736

737-
// Read file content
737+
// Read file content as bytes (supports both text and archive files)
738738
let mut file = File::open(&file_to_submit)?;
739-
let mut file_content = String::new();
740-
file.read_to_string(&mut file_content)?;
739+
let mut file_content = Vec::new();
740+
file.read_to_end(&mut file_content)?;
741741

742742
eprintln!("Submitting to leaderboard: {}", final_leaderboard);
743743
eprintln!("GPU: {}", final_gpu);

src/service/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ pub async fn delete_user_submission(client: &Client, submission_id: i64) -> Resu
450450
pub async fn submit_solution<P: AsRef<Path>>(
451451
client: &Client,
452452
filepath: P,
453-
file_content: &str,
453+
file_content: &[u8],
454454
leaderboard: &str,
455455
gpu: &str,
456456
submission_mode: &str,
@@ -465,7 +465,7 @@ pub async fn submit_solution<P: AsRef<Path>>(
465465
.ok_or_else(|| anyhow!("Invalid filepath"))?
466466
.to_string_lossy();
467467

468-
let part = Part::bytes(file_content.as_bytes().to_vec()).file_name(filename.to_string());
468+
let part = Part::bytes(file_content.to_vec()).file_name(filename.to_string());
469469

470470
let form = Form::new().part("file", part);
471471

@@ -824,7 +824,7 @@ mod tests {
824824
let result = submit_solution(
825825
&client,
826826
"test.py",
827-
"print('hello')",
827+
b"print('hello')",
828828
"test-leaderboard",
829829
"H100",
830830
"test",

src/utils/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,28 @@ pub struct PopcornDirectives {
77
pub gpus: Vec<String>,
88
}
99

10+
pub fn is_archive_file<P: AsRef<Path>>(filepath: P) -> bool {
11+
let path = filepath.as_ref();
12+
let name = path
13+
.file_name()
14+
.unwrap_or_default()
15+
.to_string_lossy()
16+
.to_lowercase();
17+
name.ends_with(".tar.gz") || name.ends_with(".tgz") || name.ends_with(".zip")
18+
}
19+
1020
pub fn get_popcorn_directives<P: AsRef<Path>>(filepath: P) -> Result<(PopcornDirectives, bool)> {
21+
// Archive files (tarballs, zips) are binary and cannot contain directives
22+
if is_archive_file(&filepath) {
23+
return Ok((
24+
PopcornDirectives {
25+
leaderboard_name: String::new(),
26+
gpus: Vec::new(),
27+
},
28+
false,
29+
));
30+
}
31+
1132
let content = fs::read_to_string(filepath)?;
1233

1334
let mut gpus: Vec<String> = Vec::new();

0 commit comments

Comments
 (0)