228 list_unknown: display_states.unknown, |
231 list_unknown: display_states.unknown, |
229 list_ignored: display_states.ignored, |
232 list_ignored: display_states.ignored, |
230 list_copies, |
233 list_copies, |
231 collect_traversed_dirs: false, |
234 collect_traversed_dirs: false, |
232 }; |
235 }; |
233 let (mut ds_status, pattern_warnings) = dmap.status( |
236 |
234 &AlwaysMatcher, |
237 type StatusResult<'a> = |
235 repo.working_directory_path().to_owned(), |
238 Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; |
236 ignore_files(repo, config), |
239 |
237 options, |
240 let after_status = |res: StatusResult| -> Result<_, CommandError> { |
238 )?; |
241 let (mut ds_status, pattern_warnings) = res?; |
239 for warning in pattern_warnings { |
242 for warning in pattern_warnings { |
240 match warning { |
243 match warning { |
241 hg::PatternFileWarning::InvalidSyntax(path, syntax) => ui |
244 hg::PatternFileWarning::InvalidSyntax(path, syntax) => ui |
242 .write_stderr(&format_bytes!( |
245 .write_stderr(&format_bytes!( |
243 b"{}: ignoring invalid syntax '{}'\n", |
246 b"{}: ignoring invalid syntax '{}'\n", |
244 get_bytes_from_path(path), |
247 get_bytes_from_path(path), |
245 &*syntax |
248 &*syntax |
246 ))?, |
249 ))?, |
247 hg::PatternFileWarning::NoSuchFile(path) => { |
250 hg::PatternFileWarning::NoSuchFile(path) => { |
248 let path = if let Ok(relative) = |
251 let path = if let Ok(relative) = |
249 path.strip_prefix(repo.working_directory_path()) |
252 path.strip_prefix(repo.working_directory_path()) |
250 { |
253 { |
251 relative |
254 relative |
|
255 } else { |
|
256 &*path |
|
257 }; |
|
258 ui.write_stderr(&format_bytes!( |
|
259 b"skipping unreadable pattern file '{}': \ |
|
260 No such file or directory\n", |
|
261 get_bytes_from_path(path), |
|
262 ))? |
|
263 } |
|
264 } |
|
265 } |
|
266 |
|
267 for (path, error) in ds_status.bad { |
|
268 let error = match error { |
|
269 hg::BadMatch::OsError(code) => { |
|
270 std::io::Error::from_raw_os_error(code).to_string() |
|
271 } |
|
272 hg::BadMatch::BadType(ty) => { |
|
273 format!("unsupported file type (type is {})", ty) |
|
274 } |
|
275 }; |
|
276 ui.write_stderr(&format_bytes!( |
|
277 b"{}: {}\n", |
|
278 path.as_bytes(), |
|
279 error.as_bytes() |
|
280 ))? |
|
281 } |
|
282 if !ds_status.unsure.is_empty() { |
|
283 info!( |
|
284 "Files to be rechecked by retrieval from filelog: {:?}", |
|
285 ds_status.unsure.iter().map(|s| &s.path).collect::<Vec<_>>() |
|
286 ); |
|
287 } |
|
288 let mut fixup = Vec::new(); |
|
289 if !ds_status.unsure.is_empty() |
|
290 && (display_states.modified || display_states.clean) |
|
291 { |
|
292 let p1 = repo.dirstate_parents()?.p1; |
|
293 let manifest = repo.manifest_for_node(p1).map_err(|e| { |
|
294 CommandError::from((e, &*format!("{:x}", p1.short()))) |
|
295 })?; |
|
296 for to_check in ds_status.unsure { |
|
297 if unsure_is_modified(repo, &manifest, &to_check.path)? { |
|
298 if display_states.modified { |
|
299 ds_status.modified.push(to_check); |
|
300 } |
252 } else { |
301 } else { |
253 &*path |
302 if display_states.clean { |
254 }; |
303 ds_status.clean.push(to_check.clone()); |
255 ui.write_stderr(&format_bytes!( |
304 } |
256 b"skipping unreadable pattern file '{}': \ |
305 fixup.push(to_check.path.into_owned()) |
257 No such file or directory\n", |
306 } |
258 get_bytes_from_path(path), |
|
259 ))? |
|
260 } |
307 } |
261 } |
308 } |
262 } |
309 let relative_paths = (!ui.plain(None)) |
263 |
310 && config |
264 for (path, error) in ds_status.bad { |
311 .get_option(b"commands", b"status.relative")? |
265 let error = match error { |
312 .unwrap_or(config.get_bool(b"ui", b"relative-paths")?); |
266 hg::BadMatch::OsError(code) => { |
313 let output = DisplayStatusPaths { |
267 std::io::Error::from_raw_os_error(code).to_string() |
314 ui, |
268 } |
315 no_status, |
269 hg::BadMatch::BadType(ty) => { |
316 relativize: if relative_paths { |
270 format!("unsupported file type (type is {})", ty) |
317 Some(RelativizePaths::new(repo)?) |
271 } |
318 } else { |
|
319 None |
|
320 }, |
272 }; |
321 }; |
273 ui.write_stderr(&format_bytes!( |
322 if display_states.modified { |
274 b"{}: {}\n", |
323 output.display(b"M ", "status.modified", ds_status.modified)?; |
275 path.as_bytes(), |
324 } |
276 error.as_bytes() |
325 if display_states.added { |
277 ))? |
326 output.display(b"A ", "status.added", ds_status.added)?; |
278 } |
327 } |
279 if !ds_status.unsure.is_empty() { |
328 if display_states.removed { |
280 info!( |
329 output.display(b"R ", "status.removed", ds_status.removed)?; |
281 "Files to be rechecked by retrieval from filelog: {:?}", |
330 } |
282 ds_status.unsure.iter().map(|s| &s.path).collect::<Vec<_>>() |
331 if display_states.deleted { |
283 ); |
332 output.display(b"! ", "status.deleted", ds_status.deleted)?; |
284 } |
333 } |
285 let mut fixup = Vec::new(); |
334 if display_states.unknown { |
286 if !ds_status.unsure.is_empty() |
335 output.display(b"? ", "status.unknown", ds_status.unknown)?; |
287 && (display_states.modified || display_states.clean) |
336 } |
288 { |
337 if display_states.ignored { |
289 let p1 = repo.dirstate_parents()?.p1; |
338 output.display(b"I ", "status.ignored", ds_status.ignored)?; |
290 let manifest = repo.manifest_for_node(p1).map_err(|e| { |
339 } |
291 CommandError::from((e, &*format!("{:x}", p1.short()))) |
340 if display_states.clean { |
292 })?; |
341 output.display(b"C ", "status.clean", ds_status.clean)?; |
293 for to_check in ds_status.unsure { |
342 } |
294 if unsure_is_modified(repo, &manifest, &to_check.path)? { |
343 |
295 if display_states.modified { |
344 let dirstate_write_needed = ds_status.dirty; |
296 ds_status.modified.push(to_check); |
345 let filesystem_time_at_status_start = |
297 } |
346 ds_status.filesystem_time_at_status_start; |
298 } else { |
347 |
299 if display_states.clean { |
348 Ok(( |
300 ds_status.clean.push(to_check.clone()); |
349 fixup, |
301 } |
350 dirstate_write_needed, |
302 fixup.push(to_check.path.into_owned()) |
351 filesystem_time_at_status_start, |
303 } |
352 )) |
304 } |
|
305 } |
|
306 let relative_paths = (!ui.plain(None)) |
|
307 && config |
|
308 .get_option(b"commands", b"status.relative")? |
|
309 .unwrap_or(config.get_bool(b"ui", b"relative-paths")?); |
|
310 let output = DisplayStatusPaths { |
|
311 ui, |
|
312 no_status, |
|
313 relativize: if relative_paths { |
|
314 Some(RelativizePaths::new(repo)?) |
|
315 } else { |
|
316 None |
|
317 }, |
|
318 }; |
353 }; |
319 if display_states.modified { |
354 let (fixup, mut dirstate_write_needed, filesystem_time_at_status_start) = |
320 output.display(b"M ", "status.modified", ds_status.modified)?; |
355 dmap.with_status( |
321 } |
356 &AlwaysMatcher, |
322 if display_states.added { |
357 repo.working_directory_path().to_owned(), |
323 output.display(b"A ", "status.added", ds_status.added)?; |
358 ignore_files(repo, config), |
324 } |
359 options, |
325 if display_states.removed { |
360 after_status, |
326 output.display(b"R ", "status.removed", ds_status.removed)?; |
361 )?; |
327 } |
|
328 if display_states.deleted { |
|
329 output.display(b"! ", "status.deleted", ds_status.deleted)?; |
|
330 } |
|
331 if display_states.unknown { |
|
332 output.display(b"? ", "status.unknown", ds_status.unknown)?; |
|
333 } |
|
334 if display_states.ignored { |
|
335 output.display(b"I ", "status.ignored", ds_status.ignored)?; |
|
336 } |
|
337 if display_states.clean { |
|
338 output.display(b"C ", "status.clean", ds_status.clean)?; |
|
339 } |
|
340 |
|
341 let mut dirstate_write_needed = ds_status.dirty; |
|
342 let filesystem_time_at_status_start = |
|
343 ds_status.filesystem_time_at_status_start; |
|
344 |
362 |
345 if (fixup.is_empty() || filesystem_time_at_status_start.is_none()) |
363 if (fixup.is_empty() || filesystem_time_at_status_start.is_none()) |
346 && !dirstate_write_needed |
364 && !dirstate_write_needed |
347 { |
365 { |
348 // Nothing to update |
366 // Nothing to update |