TrackGit
Status.cpp
Go to the documentation of this file.
1 
8 #include "Status.h"
9 #include "../UI/StatusWindow.h"
10 
11 #include <InterfaceKit.h>
12 
13 #include <stdlib.h>
14 #include <strings.h>
15 
16 
22 Status::Status(BString repo, BString dirPath)
23  :
24  GitCommand()
25 {
26  fRepo = repo;
27  fDirPath = dirPath;
28  fStatusWindow = NULL;
29 }
30 
31 
38 {
39  if (fStatusWindow == NULL)
41  return fStatusWindow;
42 }
43 
44 
49 void
51 {
52  BString* statusText = GetStatusText();
53 
54 }
55 
56 
62 BString*
63 Status::GetStatusTextUtil(git_status_list* status, StatusWindow* window)
64 {
65  size_t i, maxi = git_status_list_entrycount(status);
66  const git_status_entry *s;
67  int header = 0, changesInIndex = 0;
68  int changesInWorkDir = 0, rmInWorkDir = 0;
69  const char *old_path, *new_path;
70  BString* statusText = new BString();
71 
73  for (i = 0; i < maxi; ++i) {
74  char *istatus = NULL;
75 
76  s = git_status_byindex(status, i);
77 
78  if (s->status == GIT_STATUS_CURRENT)
79  continue;
80 
81  if (s->status & GIT_STATUS_WT_DELETED)
82  rmInWorkDir = 1;
83 
84  if (s->status & GIT_STATUS_INDEX_NEW)
85  istatus = "new file: ";
86  if (s->status & GIT_STATUS_INDEX_MODIFIED)
87  istatus = "modified: ";
88  if (s->status & GIT_STATUS_INDEX_DELETED)
89  istatus = "deleted: ";
90  if (s->status & GIT_STATUS_INDEX_RENAMED)
91  istatus = "renamed: ";
92  if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
93  istatus = "typechange:";
94 
95  if (istatus == NULL)
96  continue;
97 
98  if (!header) {
99  statusText->Append("\n");
100  statusText->Append("Changes to be committed:\n");
101  if (window) {
102  window->AddItem(BString(), BString());
103  window->AddItem(BString("Changes to be commited:"), BString());
104  }
105  header = 1;
106  }
107 
108  old_path = s->head_to_index->old_file.path;
109  new_path = s->head_to_index->new_file.path;
110 
111  BString text;
112  if (old_path && new_path && strcmp(old_path, new_path)) {
113  text.Append("\t%istatus %old -> %new\n");
114  text.ReplaceFirst("%istatus", istatus);
115  text.ReplaceFirst("%old", old_path);
116  text.ReplaceFirst("%new", new_path);
117  if (window)
118  window->AddItem(text, BString(new_path));
119  } else {
120  text.Append("\t%istatus %file\n");
121  text.ReplaceFirst("%istatus", istatus);
122  text.ReplaceFirst("%file", old_path ? old_path : new_path);
123  if (window)
124  window->AddItem(text, BString(old_path ? old_path : new_path));
125  }
126  statusText->Append(text);
127  }
128 
129  if (header) {
130  changesInIndex = 1;
131  }
132  header = 0;
133 
135  for (i = 0; i < maxi; ++i) {
136  char *wstatus = NULL;
137 
138  s = git_status_byindex(status, i);
139 
145  if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL)
146  continue;
147 
149  if (s->status & GIT_STATUS_WT_MODIFIED)
150  wstatus = "modified: ";
151  if (s->status & GIT_STATUS_WT_DELETED)
152  wstatus = "deleted: ";
153  if (s->status & GIT_STATUS_WT_RENAMED)
154  wstatus = "renamed: ";
155  if (s->status & GIT_STATUS_WT_TYPECHANGE)
156  wstatus = "typechange:";
157 
158  if (wstatus == NULL)
159  continue;
160 
161  if (!header) {
162  statusText->Append("\n");
163  statusText->Append("Changes not staged for commit:\n");
164  header = 1;
165  if (window) {
166  window->AddItem(BString(), BString());
167  window->AddItem(BString("Changes not staged for commit:"),
168  BString());
169  }
170  }
171 
172  old_path = s->index_to_workdir->old_file.path;
173  new_path = s->index_to_workdir->new_file.path;
174 
175  BString text;
176  if (old_path && new_path && strcmp(old_path, new_path)) {
177  text.Append("\t%wstatus %old -> %new\n");
178  text.ReplaceFirst("%wstatus", wstatus);
179  text.ReplaceFirst("%old", old_path);
180  text.ReplaceFirst("%new", new_path);
181  if (window)
182  window->AddItem(text, BString(new_path));
183  } else {
184  text.Append("\t%wstatus %file\n");
185  text.ReplaceFirst("%wstatus", wstatus);
186  text.ReplaceFirst("%file", old_path ? old_path : new_path);
187  if (window)
188  window->AddItem(text, BString(old_path ? old_path : new_path));
189  }
190  statusText->Append(text);
191  }
192 
193  if (header) {
194  changesInWorkDir = 1;
195  }
196 
198  header = 0;
199 
200  for (i = 0; i < maxi; ++i) {
201  s = git_status_byindex(status, i);
202 
203  if (s->status == GIT_STATUS_WT_NEW) {
204 
205  if (!header) {
206  statusText->Append("\n");
207  statusText->Append("Untracked files:\n");
208  header = 1;
209  if (window) {
210  window->AddItem(BString(), BString());
211  window->AddItem(BString("Untracked files:"), BString());
212  }
213  }
214 
215  BString text;
216  text.Append("\tuntracked: %file\n");
217  text.ReplaceFirst("%file" , s->index_to_workdir->old_file.path);
218  statusText->Append(text);
219  if (window)
220  window->AddItem(text, BString(
221  s->index_to_workdir->old_file.path));
222 
223  }
224  }
225 
226  header = 0;
227 
229  for (i = 0; i < maxi; ++i) {
230  s = git_status_byindex(status, i);
231 
232  if (s->status == GIT_STATUS_IGNORED) {
233 
234  if (!header) {
235  statusText->Append("\n");
236  statusText->Append("Ignored files:\n");
237  header = 1;
238  if (window) {
239  window->AddItem(BString(), BString());
240  window->AddItem(BString("Ignored files:"), BString());
241  }
242  }
243 
244  BString text;
245  text.Append("\t%file\n");
246  text.ReplaceFirst("%file" ,
247  s->index_to_workdir->old_file.path);
248  statusText->Append(text);
249  if (window)
250  window->AddItem(text, BString(
251  s->index_to_workdir->old_file.path));
252  }
253  }
254 
255  if (!changesInIndex && changesInWorkDir) {
256  statusText->Append("\nNo changes added to commit\n");
257  if (window) {
258  window->AddItem(BString(), BString());
259  window->AddItem(BString("No changes added to commit."), BString());
260  }
261  }
262 
263  if (statusText->Length() == 0) {
264  statusText->Append("No changes to current branch.\n");
265  if (window)
266  window->AddItem(BString("No changes to current branch."),
267  BString());
268  }
269 
270  return statusText;
271 }
272 
273 
279 BString*
280 Status::GetBranchText(git_repository *repo, StatusWindow* window)
281 {
282  int error = 0;
283  const char *branch = NULL;
284  git_reference *head = NULL;
285 
286  error = git_repository_head(&head, repo);
287 
288  if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND)
289  branch = NULL;
290  else if (!error) {
291  branch = git_reference_shorthand(head);
292  } else
293  printf("Failed to get branch.\n");
294 
295  BString* branchText = new BString("Branch: ");
296  branchText->Append((branch) ? branch : "No Branch info");
297  branchText->Append("\n");
298  if (window)
299  window->AddItem(*branchText, BString());
300 
301  git_reference_free(head);
302 
303  return branchText;
304 }
305 
306 
312 BString*
314 {
315  git_repository *repo = NULL;
316  git_status_list *status;
317  struct opts o = { GIT_STATUS_OPTIONS_INIT, fDirPath.String() };
318 
319  git_libgit2_init();
320 
321  o.statusopt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
322  o.statusopt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
323  GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
324  GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
325  o.statusopt.baseline = 0;
326 
327  if (git_repository_open_ext(&repo, o.repodir, 0, NULL) != 0) {
328  const git_error* err = giterr_last();
329  printf("Error %d : %s\n", err->klass, err->message);
330 
331  BString buffer("Error : %s");
332  buffer.ReplaceFirst("%s", err->message);
333  BAlert* alert = new BAlert("", buffer.String(), "Cancel",
334  0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
335  alert->Go();
336  return NULL;
337  }
338 
339  if (git_repository_is_bare(repo)) {
340  BString buffer("Error : Cannot report status on bare repository.");
341  BAlert* alert = new BAlert("", buffer.String(), "Cancel",
342  0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
343  alert->Go();
344  return NULL;
345  }
346 
347  if (git_status_list_new(&status, repo, &o.statusopt) != 0) {
348  const git_error* err = giterr_last();
349  printf("Error %d : %s\n", err->klass, err->message);
350 
351  BString buffer("Error : %s");
352  buffer.ReplaceFirst("%s", err->message);
353  BAlert* alert = new BAlert("", buffer.String(), "Cancel",
354  0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
355  alert->Go();
356  return NULL;
357  }
358 
359  BString* branchText = GetBranchText(repo, fStatusWindow);
360  BString* statusText = GetStatusTextUtil(status, fStatusWindow);
361  BString* text = new BString("Current directory: %dir\n");
362  text->ReplaceFirst("%dir", fDirPath.String());
363  text->Append(*branchText);
364  text->Append(*statusText);
365 
366  git_libgit2_shutdown();
367 
368  return text;
369 }
Status Options structure.
Definition: Status.h:23
static BString * GetBranchText(git_repository *, StatusWindow *)
Constructs Branch text for current repo.
Definition: Status.cpp:280
BString fDirPath
The current directory where Status option is selected.
Definition: Status.h:47
virtual TrackGitWindow * GetWindow()
This returns pointer to the status window.
Definition: Status.cpp:37
BString * GetStatusText()
Constructs the entire Status Text along with current branch for given repo.
Definition: Status.cpp:313
GitCommand Class.
Definition: GitCommand.h:20
The Status Window class.
Definition: StatusWindow.h:38
static BString * GetStatusTextUtil(git_status_list *, StatusWindow *)
Constructs Status text for current repo.
Definition: Status.cpp:63
BString fRepo
The repo/directory where command is called.
Definition: Status.h:43
StatusWindow * fStatusWindow
The Status Window.
Definition: Status.h:51
const char * repodir
Definition: Status.h:25
void AddItem(BString, BString)
Adds item to the Status list.
virtual void Execute()
Status command execution.
Definition: Status.cpp:50
Status(BString, BString)
Status class Constructor.
Definition: Status.cpp:22
The TrackGit Window class.
git_status_options statusopt
Definition: Status.h:24
Header file of Status command.