@@ -14,6 +14,7 @@ mod filter;
1414mod fs_helpers;
1515mod key;
1616mod repo;
17+ mod status;
1718
1819use anyhow:: { Context , Result } ;
1920use clap:: { Parser , Subcommand } ;
@@ -81,6 +82,9 @@ enum Commands {
8182 /// Files to check (if empty, shows repository status)
8283 #[ arg( value_name = "FILE" ) ]
8384 files : Vec < String > ,
85+ /// Output status in JSON format
86+ #[ arg( long) ]
87+ json : bool ,
8488 } ,
8589 /// Key management commands
8690 #[ command( about = "Manage encryption key" ) ]
@@ -143,7 +147,7 @@ fn main() -> Result<()> {
143147 Commands :: Init => cmd_init ( ) ,
144148 Commands :: Unlock { key_source } => cmd_unlock ( key_source) ,
145149 Commands :: Lock { force } => cmd_lock ( force) ,
146- Commands :: Status { files } => cmd_status ( files) ,
150+ Commands :: Status { files, json } => cmd_status ( files, json ) ,
147151 Commands :: Key { key_cmd } => cmd_key ( key_cmd) ,
148152 Commands :: Filter { filter_cmd } => cmd_filter ( filter_cmd) ,
149153 }
@@ -240,54 +244,58 @@ fn cmd_lock(force: bool) -> Result<()> {
240244 Ok ( ( ) )
241245}
242246
243- fn cmd_status ( files : Vec < String > ) -> Result < ( ) > {
247+ fn cmd_status ( files : Vec < String > , json : bool ) -> Result < ( ) > {
244248 let repo = repo:: Repo :: discover ( ) ?;
245249
246250 if files. is_empty ( ) {
247251 // Show repository status
248- println ! ( "Repository: {}" , repo. workdir( ) . display( ) ) ;
249- let is_unlocked = repo. is_unlocked ( ) ?;
250- println ! (
251- "Status: {}" ,
252- if is_unlocked { "unlocked" } else { "locked" }
253- ) ;
254-
252+ let repo_status = if repo. is_unlocked ( ) ? {
253+ status:: LockStatus :: Unlocked
254+ } else {
255+ status:: LockStatus :: Locked
256+ } ;
255257 let filters_configured = repo. filters_configured ( ) ?;
256- println ! (
257- "Filters configured: {}" ,
258- if filters_configured { "yes" } else { "no" }
259- ) ;
260-
261- println ! ( "\n Tracked files configured for encryption by Git filter:" ) ;
262- let mut has_files = false ;
263- for file_result in repo. find_filtered_files ( ) ? {
264- let file = file_result?;
265- println ! ( " 🔒 {}" , file. display( ) ) ;
266- has_files = true ;
267- }
268- if !has_files {
269- println ! ( " (none)" ) ;
270- }
271-
272- // Only show warning if there are actually untracked files
273- if repo. has_untracked_files ( ) ? {
274- println ! (
275- "\n Note: You have untracked files in your working copy. Even if some\n \
276- of those new files match the filter patterns in `.gitattributes`,\n \
277- they won't be listed here until you `git add` them to the staging area."
278- ) ;
258+ let has_untracked_files = repo. has_untracked_files ( ) ?;
259+ let encrypted_files: Vec < _ > = repo
260+ . find_filtered_files ( ) ?
261+ . collect :: < Result < Vec < _ > > > ( )
262+ . context ( "Failed to get file path" ) ?;
263+
264+ let status = status:: RepositoryStatus {
265+ repository : repo. workdir ( ) . to_string_lossy ( ) . into_owned ( ) ,
266+ status : repo_status,
267+ filters_configured,
268+ encrypted_files,
269+ has_untracked_files,
270+ } ;
271+
272+ if json {
273+ println ! ( "{}" , serde_json:: to_string_pretty( & status) ?) ;
274+ } else {
275+ print ! ( "{}" , status) ;
279276 }
280277 } else {
281278 // Check status for specific files
282- for file_str in & files {
283- let file_path = std:: path:: Path :: new ( file_str) ;
284- let is_filtered = repo. is_filtered_file ( file_path) ?;
285- let status = if is_filtered {
286- "🔒 Encrypted in the repository"
287- } else {
288- "👀 Not encrypted in the repository"
289- } ;
290- println ! ( "{:20}: {}" , file_str, status) ;
279+ let file_statuses: Vec < status:: FileStatus > = files
280+ . iter ( )
281+ . map ( |file_str| {
282+ let file_path = std:: path:: Path :: new ( file_str) ;
283+ let is_filtered = repo. is_filtered_file ( file_path) ?;
284+ Ok ( status:: FileStatus {
285+ file : file_path. to_path_buf ( ) ,
286+ encrypted : is_filtered,
287+ } )
288+ } )
289+ . collect :: < Result < Vec < _ > > > ( ) ?;
290+
291+ let status_list = status:: FileStatusList {
292+ files : file_statuses,
293+ } ;
294+
295+ if json {
296+ println ! ( "{}" , serde_json:: to_string_pretty( & status_list) ?) ;
297+ } else {
298+ print ! ( "{}" , status_list) ;
291299 }
292300 }
293301
0 commit comments