rust/rhg/src/commands/status.rs
branchstable
changeset 49000 dd6b67d5c256
parent 48738 00efd2d5037d
child 49110 4d3f6767319f
equal deleted inserted replaced
48999:cfd270d83169 49000:dd6b67d5c256
    23 use hg::repo::Repo;
    23 use hg::repo::Repo;
    24 use hg::utils::files::get_bytes_from_os_string;
    24 use hg::utils::files::get_bytes_from_os_string;
    25 use hg::utils::files::get_bytes_from_path;
    25 use hg::utils::files::get_bytes_from_path;
    26 use hg::utils::files::get_path_from_bytes;
    26 use hg::utils::files::get_path_from_bytes;
    27 use hg::utils::hg_path::{hg_path_to_path_buf, HgPath};
    27 use hg::utils::hg_path::{hg_path_to_path_buf, HgPath};
       
    28 use hg::DirstateStatus;
       
    29 use hg::PatternFileWarning;
       
    30 use hg::StatusError;
    28 use hg::StatusOptions;
    31 use hg::StatusOptions;
    29 use log::info;
    32 use log::info;
    30 use std::io;
    33 use std::io;
    31 use std::path::PathBuf;
    34 use std::path::PathBuf;
    32 
    35 
   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