…lines 1–103 unchanged (103 lines)
104 /// `sample.csv` never clobbers a promotion that already happened.
105 promoted_to: String,
106 /// Which research dataset (tiny/small/full) this row was sampled from - see `Args::dataset`.
107 /// Carried through unchanged on every re-run, same as `promoted_to`: a row's provenance
108 /// doesn't change just because a later run happens to target a different `--repos-dir`.
109 dataset: String,
110 /// One of `SAMPLED`/`PROMOTED`/`REJECTED` - `human_solver` moves a row from `SAMPLED` to
111 /// whichever of the other two applies when the sample is triaged (`s` to promote, `R` to
112 /// reject); this tool never sets anything but `SAMPLED` on a freshly-sampled row.
113 status: String,
114 /// Why this row was rejected instead of promoted, verbatim from `human_solver`'s reject
115 /// prompt. Empty unless `status` is `REJECTED`.
116 rejection_reason: String,
117}
118
119type SampleKey = (String, String, String);
120
121/// Historical default for any row read from a sample.csv written before provenance tracking
122/// existed - every one of those was in fact sampled from the small research checkout (the only
123/// one available when they were added), so this is a real fallback value, not a placeholder.
124const LEGACY_DATASET: &str = "small";
125
126/// Backfills `status` for a row read from a sample.csv written before that column existed: a
127/// non-empty `promoted_to` means it was already promoted, otherwise it's just sitting there
128/// unsampled -- there's no way a pre-existing row could be `REJECTED`, since rejection didn't
129/// exist yet either.
130fn default_status(promoted_to: &str) -> &'static str {
131 if promoted_to.is_empty() {
132 "SAMPLED"
133 } else {
134 "PROMOTED"
135 }
136}
137
138fn default_output_path() -> PathBuf {
139 PathBuf::from(env!("CARGO_MANIFEST_DIR"))
140 .join("src")
141 .join("test")
142 .join("data")
…lines 143–161 unchanged (19 lines)
162 }
163
164 let mut reader = csv::Reader::from_path(path)?;
165 let mut rows = Vec::new();
166 for record in reader.records() {
167 let record = record?;
168 let promoted_to = record.get(4).unwrap_or("").to_string();
169 let status = match record.get(6) {
170 Some(status) if !status.is_empty() => status.to_string(),
171 _ => default_status(&promoted_to).to_string(),
172 };
173 rows.push(Row {
174 language: record[0].to_string(),
175 repository: record[1].to_string(),
176 commit: record[2].to_string(),
177 path: record[3].to_string(),
178 promoted_to,
179 dataset: record.get(5).unwrap_or(LEGACY_DATASET).to_string(),
180 status,
181 rejection_reason: record.get(7).unwrap_or("").to_string(),
182 });
183 }
184 Ok(rows)
185}
186
187fn main() -> Result<()> {
…lines 188–312 unchanged (125 lines)
313 language: language.clone(),
314 repository: repository_name.to_string(),
315 commit: id.to_string(),
316 path,
317 promoted_to: String::new(),
318 dataset: dataset.to_string(),
319 status: "SAMPLED".to_string(),
320 rejection_reason: String::new(),
321 };
322 reservoirs
323 .entry(language)
324 .or_default()
325 .offer(row, capacity, rng);
326
…lines 327–353 unchanged (27 lines)
354 "language",
355 "repository",
356 "commit",
357 "path",
358 "promoted_to",
359 "dataset",
360 "status",
361 "rejection_reason",
362 ])?;
363 for row in &rows {
364 writer.write_record([
365 &row.language,
366 &row.repository,
367 &row.commit,
368 &row.path,
369 &row.promoted_to,
370 &row.dataset,
371 &row.status,
372 &row.rejection_reason,
373 ])?;
374 }
375 writer.flush()?;
376 Ok(())
377}
378
…lines 379–469 unchanged (91 lines)