rust/rhg/src/commands/status.rs
changeset 51188 976403c95ba3
parent 50890 c112cc9effdc
child 51190 ac3859a8b796
equal deleted inserted replaced
51187:ddf2b33ee388 51188:976403c95ba3
    34 use hg::StatusOptions;
    34 use hg::StatusOptions;
    35 use hg::{self, narrow, sparse};
    35 use hg::{self, narrow, sparse};
    36 use log::info;
    36 use log::info;
    37 use rayon::prelude::*;
    37 use rayon::prelude::*;
    38 use std::io;
    38 use std::io;
       
    39 use std::mem::take;
    39 use std::path::PathBuf;
    40 use std::path::PathBuf;
    40 
    41 
    41 pub const HELP_TEXT: &str = "
    42 pub const HELP_TEXT: &str = "
    42 Show changed files in the working directory
    43 Show changed files in the working directory
    43 
    44 
   283     };
   284     };
   284 
   285 
   285     type StatusResult<'a> =
   286     type StatusResult<'a> =
   286         Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>;
   287         Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>;
   287 
   288 
       
   289     let relative_status = config
       
   290         .get_option(b"commands", b"status.relative")?
       
   291         .expect("commands.status.relative should have a default value");
       
   292 
       
   293     let relativize_paths = relative_status || {
       
   294         // See in Python code with `getuipathfn` usage in `commands.py`.
       
   295         let legacy_relative_behavior = args.contains_id("file");
       
   296         match relative_paths(invocation.config)? {
       
   297             RelativePaths::Legacy => legacy_relative_behavior,
       
   298             RelativePaths::Bool(v) => v,
       
   299         }
       
   300     };
       
   301 
       
   302     let mut output = DisplayStatusPaths {
       
   303         ui,
       
   304         no_status,
       
   305         relativize: if relativize_paths {
       
   306             Some(RelativizePaths::new(repo)?)
       
   307         } else {
       
   308             None
       
   309         },
       
   310         print0,
       
   311     };
       
   312 
   288     let after_status = |res: StatusResult| -> Result<_, CommandError> {
   313     let after_status = |res: StatusResult| -> Result<_, CommandError> {
   289         let (mut ds_status, pattern_warnings) = res?;
   314         let (mut ds_status, pattern_warnings) = res?;
   290         for warning in pattern_warnings {
   315         for warning in pattern_warnings {
   291             ui.write_stderr(&format_pattern_file_warning(&warning, repo))?;
   316             ui.write_stderr(&format_pattern_file_warning(&warning, repo))?;
   292         }
   317         }
   293 
   318 
   294         for (path, error) in ds_status.bad {
   319         for (path, error) in take(&mut ds_status.bad) {
   295             let error = match error {
   320             let error = match error {
   296                 hg::BadMatch::OsError(code) => {
   321                 hg::BadMatch::OsError(code) => {
   297                     std::io::Error::from_raw_os_error(code).to_string()
   322                     std::io::Error::from_raw_os_error(code).to_string()
   298                 }
   323                 }
   299                 hg::BadMatch::BadType(ty) => {
   324                 hg::BadMatch::BadType(ty) => {
   320             let manifest = repo.manifest_for_node(p1).map_err(|e| {
   345             let manifest = repo.manifest_for_node(p1).map_err(|e| {
   321                 CommandError::from((e, &*format!("{:x}", p1.short())))
   346                 CommandError::from((e, &*format!("{:x}", p1.short())))
   322             })?;
   347             })?;
   323             let working_directory_vfs = repo.working_directory_vfs();
   348             let working_directory_vfs = repo.working_directory_vfs();
   324             let store_vfs = repo.store_vfs();
   349             let store_vfs = repo.store_vfs();
   325             let res: Vec<_> = ds_status
   350             let res: Vec<_> = take(&mut ds_status.unsure)
   326                 .unsure
       
   327                 .into_par_iter()
   351                 .into_par_iter()
   328                 .map(|to_check| {
   352                 .map(|to_check| {
   329                     // The compiler seems to get a bit confused with complex
   353                     // The compiler seems to get a bit confused with complex
   330                     // inference when using a parallel iterator + map
   354                     // inference when using a parallel iterator + map
   331                     // + map_err + collect, so let's just inline some of the
   355                     // + map_err + collect, so let's just inline some of the
   368                     }
   392                     }
   369                 }
   393                 }
   370             }
   394             }
   371         }
   395         }
   372 
   396 
   373         let relative_status = config
       
   374             .get_option(b"commands", b"status.relative")?
       
   375             .expect("commands.status.relative should have a default value");
       
   376 
       
   377         let relativize_paths = relative_status || {
       
   378             // See in Python code with `getuipathfn` usage in `commands.py`.
       
   379             let legacy_relative_behavior = args.contains_id("file");
       
   380             match relative_paths(invocation.config)? {
       
   381                 RelativePaths::Legacy => legacy_relative_behavior,
       
   382                 RelativePaths::Bool(v) => v,
       
   383             }
       
   384         };
       
   385 
       
   386         let output = DisplayStatusPaths {
       
   387             ui,
       
   388             no_status,
       
   389             relativize: if relativize_paths {
       
   390                 Some(RelativizePaths::new(repo)?)
       
   391             } else {
       
   392                 None
       
   393             },
       
   394             print0,
       
   395         };
       
   396         if display_states.modified {
       
   397             output.display(b"M ", "status.modified", ds_status.modified)?;
       
   398         }
       
   399         if display_states.added {
       
   400             output.display(b"A ", "status.added", ds_status.added)?;
       
   401         }
       
   402         if display_states.removed {
       
   403             output.display(b"R ", "status.removed", ds_status.removed)?;
       
   404         }
       
   405         if display_states.deleted {
       
   406             output.display(b"! ", "status.deleted", ds_status.deleted)?;
       
   407         }
       
   408         if display_states.unknown {
       
   409             output.display(b"? ", "status.unknown", ds_status.unknown)?;
       
   410         }
       
   411         if display_states.ignored {
       
   412             output.display(b"I ", "status.ignored", ds_status.ignored)?;
       
   413         }
       
   414         if display_states.clean {
       
   415             output.display(b"C ", "status.clean", ds_status.clean)?;
       
   416         }
       
   417 
       
   418         let dirstate_write_needed = ds_status.dirty;
   397         let dirstate_write_needed = ds_status.dirty;
   419         let filesystem_time_at_status_start =
   398         let filesystem_time_at_status_start =
   420             ds_status.filesystem_time_at_status_start;
   399             ds_status.filesystem_time_at_status_start;
       
   400 
       
   401         output.output(display_states, ds_status)?;
   421 
   402 
   422         Ok((
   403         Ok((
   423             fixup,
   404             fixup,
   424             dirstate_write_needed,
   405             dirstate_write_needed,
   425             filesystem_time_at_status_start,
   406             filesystem_time_at_status_start,
   626                 )?
   607                 )?
   627             }
   608             }
   628         }
   609         }
   629         Ok(())
   610         Ok(())
   630     }
   611     }
       
   612 
       
   613     fn output(
       
   614         &mut self,
       
   615         display_states: DisplayStates,
       
   616         ds_status: DirstateStatus,
       
   617     ) -> Result<(), CommandError> {
       
   618         if display_states.modified {
       
   619             self.display(b"M ", "status.modified", ds_status.modified)?;
       
   620         }
       
   621         if display_states.added {
       
   622             self.display(b"A ", "status.added", ds_status.added)?;
       
   623         }
       
   624         if display_states.removed {
       
   625             self.display(b"R ", "status.removed", ds_status.removed)?;
       
   626         }
       
   627         if display_states.deleted {
       
   628             self.display(b"! ", "status.deleted", ds_status.deleted)?;
       
   629         }
       
   630         if display_states.unknown {
       
   631             self.display(b"? ", "status.unknown", ds_status.unknown)?;
       
   632         }
       
   633         if display_states.ignored {
       
   634             self.display(b"I ", "status.ignored", ds_status.ignored)?;
       
   635         }
       
   636         if display_states.clean {
       
   637             self.display(b"C ", "status.clean", ds_status.clean)?;
       
   638         }
       
   639         Ok(())
       
   640     }
   631 }
   641 }
   632 
   642 
   633 /// Outcome of the additional check for an ambiguous tracked file
   643 /// Outcome of the additional check for an ambiguous tracked file
   634 enum UnsureOutcome {
   644 enum UnsureOutcome {
   635     /// The file is actually clean
   645     /// The file is actually clean