1
1
#include < iostream>
2
2
#include < ostream>
3
+ #include < set>
3
4
#include < string>
4
5
5
6
#include < git2.h>
@@ -71,52 +72,117 @@ enum class output_format
71
72
SHORT = 2
72
73
};
73
74
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
75
76
{
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))
78
85
{
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)
80
101
{
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
+ }
89
107
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))
102
166
{
103
- std::cout << old_path << " -> " << new_path << std::endl ;
167
+ not_tracked_entries_to_print. push_back (e) ;
104
168
}
105
169
else
106
170
{
107
- if (old_path)
108
- {
109
- std::cout << old_path << std::endl;
110
- }
171
+ if (untracked_dir_set.contains (directory))
172
+ {}
111
173
else
112
174
{
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));
114
177
}
115
178
}
116
179
}
180
+ else
181
+ {
182
+ not_tracked_entries_to_print.push_back (e);
183
+ }
117
184
}
118
- else
119
- {}
185
+ print_entries (not_tracked_entries_to_print);
120
186
}
121
187
122
188
void status_subcommand::run ()
@@ -127,7 +193,10 @@ void status_subcommand::run()
127
193
auto sl = status_list_wrapper::status_list (repo);
128
194
auto branch_name = reference_wrapper::get_ref_name (repo);
129
195
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{};
131
200
132
201
output_format of = output_format::DEFAULT;
133
202
if (short_flag)
@@ -162,11 +231,11 @@ void status_subcommand::run()
162
231
{
163
232
std::cout << tobecommited_header << std::endl;
164
233
}
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) );
170
239
if (is_long)
171
240
{
172
241
std::cout << std::endl;
@@ -179,23 +248,24 @@ void status_subcommand::run()
179
248
{
180
249
std::cout << notstagged_header << std::endl;
181
250
}
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) );
186
255
if (is_long)
187
256
{
188
257
std::cout << std::endl;
189
258
}
190
259
}
191
260
261
+
192
262
if (sl.has_untracked_header ())
193
263
{
194
264
if (is_long)
195
265
{
196
266
std::cout << untracked_header << std::endl;
197
267
}
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 );
199
269
if (is_long)
200
270
{
201
271
std::cout << std::endl;
@@ -208,7 +278,7 @@ void status_subcommand::run()
208
278
{
209
279
std::cout << ignored_header << std::endl;
210
280
}
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 );
212
282
if (is_long)
213
283
{
214
284
std::cout << std::endl;
0 commit comments