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