@@ -604,6 +604,8 @@ def do_add_parser(self, parser_adder):
604604 exiting with an error if there are issues''' )
605605 group .add_argument ('--path' , action = 'store_true' ,
606606 help = "print the top level manifest file's path" )
607+ group .add_argument ('--status' , action = 'store_true' ,
608+ help = "print the local workspace status" )
607609
608610 group = parser .add_argument_group ('options for --resolve and --freeze' )
609611 group .add_argument ('-o' , '--out' ,
@@ -624,6 +626,8 @@ def do_run(self, args, user_args):
624626 elif args .freeze :
625627 self ._die_if_manifest_project_filter ('freeze' )
626628 self ._dump (args , manifest .as_frozen_yaml (** dump_kwargs ))
629+ elif args .status :
630+ self ._status ()
627631 elif args .path :
628632 self .inf (manifest .path )
629633 else :
@@ -640,6 +644,46 @@ def _die_if_manifest_project_filter(self, action):
640644 'the manifest while projects are made inactive by the '
641645 'project filter.' )
642646
647+ def _status (self ):
648+ ppaths = []
649+ untracked = []
650+ for project in self ._projects (None ):
651+ # Skip inactive projects unless the user said
652+ # --all or named some projects explicitly.
653+ if not self .manifest .is_active (project ):
654+ self .dbg (f'{ project .name } : skipping inactive project' )
655+ continue
656+ ppaths .append (Path (project .abspath ).resolve ())
657+
658+ def _folder_status (folder ):
659+ self .dbg (f'folder status in: { folder } ' )
660+ for e in [e .resolve () for e in folder .iterdir ()]:
661+ if e .is_dir ():
662+ self .dbg (f'processing folder: { e } ' )
663+ for ppath in ppaths :
664+ if e .samefile (ppath ):
665+ # We hit a project root folder, skip it
666+ break
667+ elif e in ppath .parents :
668+ self .dbg (f'recursing into: { e } ' )
669+ _folder_status (e )
670+ break
671+ else :
672+ # No match, untracked folder
673+ untracked .append (e )
674+ continue
675+ else :
676+ # Untracked file
677+ untracked .append (e )
678+
679+ # Avoid using Path.walk() since that returns all files and folders under
680+ # a particular folder, which is overkill in our case. Instead, recurse
681+ # only when required.
682+ _folder_status (Path .cwd ())
683+ self .inf ('Untracked files and folders:' )
684+ for u in untracked :
685+ self .inf (u )
686+
643687 def _dump (self , args , to_dump ):
644688 if args .out :
645689 with open (args .out , 'w' ) as f :
0 commit comments