11#include  < iostream> 
22#include  < ostream> 
3+ #include  < set> 
34#include  < string> 
45
56#include  < git2.h> 
@@ -71,52 +72,117 @@ enum class output_format
7172    SHORT = 2 
7273};
7374
74- void   print_entries ( git_status_t  status, status_list_wrapper& sl,  bool  head_selector, output_format of)    //  TODO: add different mods 
75+ struct   print_entry 
7576{
76-     const  auto & entry_list = sl.get_entry_list (status);
77-     if  (!entry_list.empty ())
77+     std::string status;
78+     std::string item;
79+ };
80+ 
81+ std::string get_print_status (git_status_t  status, output_format of)
82+ {
83+     std::string entry_status;
84+     if  ((of == output_format::DEFAULT) || (of == output_format::LONG))
7885    {
79-         for  (auto * entry : entry_list)
86+         entry_status = status_msg_map.at (status).long_mod  + " \t "  ;
87+     }
88+     else  if  (of == output_format::SHORT)
89+     {
90+         entry_status = status_msg_map.at (status).short_mod ;
91+     }
92+     return  entry_status;
93+ }
94+ 
95+ void  update_tracked_dir_set (const  char * old_path, const  char * new_path, std::set<std::string>* tracked_dir_set = nullptr )
96+ {
97+     if  (tracked_dir_set)
98+     {
99+         const  size_t  first_slash_idx = std::string_view (old_path).find (' /'  );
100+         if  (std::string::npos != first_slash_idx)
80101        {
81-             if  ((of == output_format::DEFAULT) || (of == output_format::LONG))
82-             {
83-                 std::cout << status_msg_map.at (status).long_mod  << " \t "  ;
84-             }
85-             else  if  (of == output_format::SHORT)
86-             {
87-                 std::cout << status_msg_map.at (status).short_mod ;
88-             }
102+             auto  directory = std::string_view (old_path).substr (0 , first_slash_idx);
103+             tracked_dir_set->insert (std::string (directory));
104+         }
105+     }
106+ }
89107
90-             git_diff_delta* diff_delta;
91-             if  (head_selector)
92-             {
93-                 diff_delta = entry->head_to_index ;
94-             }
95-             else 
96-             {
97-                 diff_delta = entry->index_to_workdir ;
98-             }
99-             const  char * old_path = diff_delta->old_file .path ;
100-             const  char * new_path = diff_delta->new_file .path ;
101-             if  (old_path && new_path && std::strcmp (old_path, new_path))
108+ std::string get_print_item (const  char * old_path, const  char * new_path)
109+ {
110+     std::string entry_item;
111+     if  (old_path && new_path && std::strcmp (old_path, new_path))
112+     {
113+         entry_item = std::string (old_path) + "  -> "   + std::string (new_path);
114+     }
115+     else 
116+     {
117+         entry_item = old_path ? old_path : new_path;
118+     }
119+     return  entry_item;
120+ }
121+ 
122+ std::vector<print_entry> get_entries_to_print (git_status_t  status, status_list_wrapper& sl,
123+     bool  head_selector, output_format of, std::set<std::string>* tracked_dir_set = nullptr )
124+ {
125+     std::vector<print_entry> entries_to_print{};
126+     const  auto & entry_list = sl.get_entry_list (status);
127+     if  (entry_list.empty ())
128+     {
129+         return  entries_to_print;
130+     }
131+ 
132+     for  (auto * entry : entry_list)
133+     {
134+         git_diff_delta* diff_delta = head_selector ? entry->head_to_index  : entry->index_to_workdir ;
135+         const  char * old_path = diff_delta->old_file .path ;
136+         const  char * new_path = diff_delta->new_file .path ;
137+ 
138+         update_tracked_dir_set (old_path, new_path, tracked_dir_set);
139+ 
140+         print_entry e = { get_print_status (status, of), get_print_item (old_path, new_path)};
141+ 
142+         entries_to_print.push_back (std::move (e));
143+     }
144+     return  entries_to_print;
145+ }
146+ 
147+ void  print_entries (std::vector<print_entry> entries_to_print)
148+ {
149+     for  (auto  e: entries_to_print)
150+     {
151+         std::cout << e.status  << e.item  << std::endl;
152+     }
153+ }
154+ 
155+ void  print_not_tracked (std::vector<print_entry> entries_to_print, const  std::set<std::string>& tracked_dir_set,
156+         std::set<std::string>& untracked_dir_set)
157+ {
158+     std::vector<print_entry> not_tracked_entries_to_print{};
159+     for  (auto  e: entries_to_print)
160+     {
161+         const  size_t  first_slash_idx = e.item .find (' /'  );
162+         if  (std::string::npos != first_slash_idx)
163+         {
164+             auto  directory = e.item .substr (0 , first_slash_idx);
165+             if  (tracked_dir_set.contains (directory))
102166            {
103-                 std::cout << old_path <<  "  ->  "  << new_path << std::endl ;
167+                 not_tracked_entries_to_print. push_back (e) ;
104168            }
105169            else 
106170            {
107-                 if  (old_path)
108-                 {
109-                     std::cout << old_path  << std::endl;
110-                 }
171+                 if  (untracked_dir_set.contains (directory))
172+                 {}
111173                else 
112174                {
113-                     std::cout << new_path  << std::endl;
175+                     not_tracked_entries_to_print.push_back ({e.status , directory});
176+                     untracked_dir_set.insert (std::string (directory));
114177                }
115178            }
116179        }
180+         else 
181+         {
182+             not_tracked_entries_to_print.push_back (e);
183+         }
117184    }
118-     else 
119-     {}
185+     print_entries (not_tracked_entries_to_print);
120186}
121187
122188void  status_subcommand::run ()
@@ -127,7 +193,10 @@ void status_subcommand::run()
127193    auto  sl = status_list_wrapper::status_list (repo);
128194    auto  branch_name = reference_wrapper::get_ref_name (repo);
129195
130-     //  TODO: add branch info
196+     std::set<std::string> tracked_dir_set{};
197+     std::set<std::string> untracked_dir_set{};
198+     std::vector<std::string> untracked_to_print{};
199+     std::vector<std::string> ignored_to_print{};
131200
132201    output_format of = output_format::DEFAULT;
133202    if  (short_flag)
@@ -162,11 +231,11 @@ void status_subcommand::run()
162231        {
163232            std::cout << tobecommited_header << std::endl;
164233        }
165-         print_entries (GIT_STATUS_INDEX_NEW, sl, true , of);
166-         print_entries (GIT_STATUS_INDEX_MODIFIED, sl, true , of);
167-         print_entries (GIT_STATUS_INDEX_DELETED, sl, true , of);
168-         print_entries (GIT_STATUS_INDEX_RENAMED, sl, true , of);
169-         print_entries (GIT_STATUS_INDEX_TYPECHANGE, sl, true , of);
234+         print_entries (get_entries_to_print ( GIT_STATUS_INDEX_NEW, sl, true , of, &tracked_dir_set) );
235+         print_entries (get_entries_to_print ( GIT_STATUS_INDEX_MODIFIED, sl, true , of, &tracked_dir_set) );
236+         print_entries (get_entries_to_print ( GIT_STATUS_INDEX_DELETED, sl, true , of, &tracked_dir_set) );
237+         print_entries (get_entries_to_print ( GIT_STATUS_INDEX_RENAMED, sl, true , of, &tracked_dir_set) );
238+         print_entries (get_entries_to_print ( GIT_STATUS_INDEX_TYPECHANGE, sl, true , of, &tracked_dir_set) );
170239        if  (is_long)
171240        {
172241            std::cout << std::endl;
@@ -179,23 +248,24 @@ void status_subcommand::run()
179248        {
180249            std::cout << notstagged_header << std::endl;
181250        }
182-         print_entries (GIT_STATUS_WT_MODIFIED, sl, false , of);
183-         print_entries (GIT_STATUS_WT_DELETED, sl, false , of);
184-         print_entries (GIT_STATUS_WT_TYPECHANGE, sl, false , of);
185-         print_entries (GIT_STATUS_WT_RENAMED, sl, false , of);
251+         print_entries (get_entries_to_print ( GIT_STATUS_WT_MODIFIED, sl, false , of, &tracked_dir_set) );
252+         print_entries (get_entries_to_print ( GIT_STATUS_WT_DELETED, sl, false , of, &tracked_dir_set) );
253+         print_entries (get_entries_to_print ( GIT_STATUS_WT_TYPECHANGE, sl, false , of, &tracked_dir_set) );
254+         print_entries (get_entries_to_print ( GIT_STATUS_WT_RENAMED, sl, false , of, &tracked_dir_set) );
186255        if  (is_long)
187256        {
188257            std::cout << std::endl;
189258        }
190259    }
191260
261+ 
192262    if  (sl.has_untracked_header ())
193263    {
194264        if  (is_long)
195265        {
196266            std::cout << untracked_header << std::endl;
197267        }
198-         print_entries ( GIT_STATUS_WT_NEW, sl, false , of);
268+         print_not_tracked ( get_entries_to_print ( GIT_STATUS_WT_NEW, sl, false , of), tracked_dir_set, untracked_dir_set );
199269        if  (is_long)
200270        {
201271            std::cout << std::endl;
@@ -208,7 +278,7 @@ void status_subcommand::run()
208278        {
209279            std::cout << ignored_header << std::endl;
210280        }
211-         print_entries ( GIT_STATUS_IGNORED, sl, false , of);
281+         print_not_tracked ( get_entries_to_print ( GIT_STATUS_IGNORED, sl, false , of), tracked_dir_set, untracked_dir_set );
212282        if  (is_long)
213283        {
214284            std::cout << std::endl;
0 commit comments