TrackGit
Utils.cpp
Go to the documentation of this file.
1 
9 #include "Utils.h"
10 #include "UI/ConflictsWindow.h"
11 #include "UI/CredentialsWindow.h"
12 
13 #include <StorageKit.h>
14 
15 #include <git2.h>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 
27 BString
28 extract_current_directory(const BMessage* msg)
29 {
30  // Get current directory path.
31  entry_ref dirRef;
32  if (msg->FindRef("dir_ref", &dirRef) != B_OK) {
33  printf("No dir_ref found!\n");
34  return NULL;
35  }
36  BEntry entry;
37  entry.SetTo(&dirRef);
38  BPath path;
39  entry.GetPath(&path);
40  return BString(path.Path());
41 }
42 
43 
49 void
50 extract_selected_paths(const BMessage* msg, vector<char*>& selected)
51 {
52  // Get current directory
53  BString dir = extract_current_directory(msg);
54  // Get all the selected refs
55  entry_ref fileRef;
56  for (int refs=0;
57  msg->FindRef("refs", refs, &fileRef) == B_NO_ERROR;
58  refs++) {
59  BEntry entry;
60  entry.SetTo(&fileRef);
61  BPath path;
62  entry.GetPath(&path);
63  BString relativePath(path.Path());
64  // Generate relative path from absolute path
65  relativePath.ReplaceFirst(dir, "");
66  relativePath.ReplaceFirst("/", "");
67  // To convert const char* to char*
68  char* p = (char*) malloc(relativePath.Length());
69  strcpy(p, relativePath.String());
70  selected.push_back(p);
71  }
72 }
73 
74 
80 BString
81 get_root_of_repo(BString dirPath)
82 {
83  git_libgit2_init();
84  git_buf buf = GIT_BUF_INIT_CONST(NULL, 0);
85 
86  // Check if current directory is in git repo.
87  int ret = git_repository_discover(&buf, dirPath.String(), 0, NULL);
88  git_libgit2_shutdown();
89 
90  // Return root of repo if current directory is in git repo
91  // else return current directory.
92  return (ret == 0) ? BString(buf.ptr) : dirPath;
93 }
94 
95 
103 int perform_fastforward(git_repository *repo, const git_oid *target_oid,
104  int is_unborn)
105 {
106  git_checkout_options ff_checkout_options = GIT_CHECKOUT_OPTIONS_INIT;
107  git_reference *target_ref;
108  git_reference *new_target_ref;
109  git_object *target = NULL;
110  int err = 0;
111 
112  if (is_unborn) {
113  const char *symbolic_ref;
114  git_reference *head_ref;
115 
116  /* HEAD reference is unborn,
117  * lookup manually so we don't try to resolve it
118  */
119  err = git_reference_lookup(&head_ref, repo, "HEAD");
120  if (err != 0) {
121  fprintf(stderr, "failed to lookup HEAD ref\n");
122  return -1;
123  }
124 
125  /* Grab the reference HEAD should be pointing to */
126  symbolic_ref = git_reference_symbolic_target(head_ref);
127 
128  /* Create our master reference on the target OID */
129  err = git_reference_create(&target_ref, repo, symbolic_ref,
130  target_oid, 0, NULL);
131  if (err != 0) {
132  fprintf(stderr, "failed to create master reference\n");
133  return -1;
134  }
135 
136  git_reference_free(head_ref);
137  } else {
138  /* HEAD exists, just lookup and resolve */
139  err = git_repository_head(&target_ref, repo);
140  if (err != 0) {
141  fprintf(stderr, "failed to get HEAD reference\n");
142  return -1;
143  }
144  }
145 
146  /* Lookup the target object */
147  err = git_object_lookup(&target, repo, target_oid, GIT_OBJ_COMMIT);
148  if (err != 0) {
149  fprintf(stderr, "failed to lookup OID %s\n",
150  git_oid_tostr_s(target_oid));
151  return -1;
152  }
153 
154  /* Checkout the result so the workdir is in the expected state */
155  ff_checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
156  err = git_checkout_tree(repo, target, &ff_checkout_options);
157  if (err != 0) {
158  fprintf(stderr, "failed to checkout HEAD reference\n");
159  return -1;
160  }
161 
162  /* Move the target reference to the target OID */
163  err = git_reference_set_target(&new_target_ref, target_ref, target_oid,
164  NULL);
165  if (err != 0) {
166  fprintf(stderr, "failed to move HEAD reference\n");
167  return -1;
168  }
169 
170  git_reference_free(target_ref);
171  git_reference_free(new_target_ref);
172  git_object_free(target);
173 
174  return 0;
175 }
176 
177 
185 int
186 create_commit(git_repository* repo, git_index* index, const char* message)
187 {
188  git_tree* tree;
189  git_commit* parent;
190  git_oid tree_id, commit_id, parent_id;
191  git_signature* sign;
192  git_config* cfg;
193  git_config* cfg_snapshot;
194  int ret;
195 
196  git_config_open_ondisk(&cfg, "/boot/home/config/settings/git/config");
197  git_config_snapshot(&cfg_snapshot, cfg);
198 
199  const char *user_name, *user_email;
200  ret = git_config_get_string(&user_name, cfg_snapshot, "user.name");
201  if (ret < 0)
202  return ret;
203 
204  ret = git_config_get_string(&user_email, cfg_snapshot, "user.email");
205  if (ret < 0)
206  return ret;
207 
208  // Get default commiter
209  ret = git_signature_now(&sign, user_name, user_email);
210  if (ret < 0)
211  return ret;
212 
213  // Init tree_id
214  ret = git_index_write_tree(&tree_id, index);
215  if (ret < 0)
216  return ret;
217 
218  git_index_free(index);
219 
220  // Init tree
221  ret = git_tree_lookup(&tree, repo, &tree_id);
222  if (ret < 0)
223  return ret;
224 
225  ret = git_reference_name_to_id(&parent_id, repo, "HEAD");
226  if (ret < 0) {
227  // No parent commit found. This might be initial commit.
228  ret = git_commit_create_v(&commit_id, repo, "HEAD", sign, sign, NULL,
229  message, tree, 0);
230  return ret;
231  }
232 
233  ret = git_commit_lookup(&parent, repo, &parent_id);
234  if (ret < 0)
235  return ret;
236 
237  // Create commit
238  ret = git_commit_create_v(&commit_id, repo, "HEAD", sign, sign, NULL,
239  message, tree, 1, parent);
240  return ret;
241 }
242 
243 
248 void output_conflicts(git_index *index)
249 {
250  ConflictsWindow* conflictsWindow = new ConflictsWindow();
251  git_index_conflict_iterator *conflicts;
252  const git_index_entry *ancestor;
253  const git_index_entry *our;
254  const git_index_entry *their;
255  int err = 0;
256  BString conflictsString;
257 
258  err = git_index_conflict_iterator_new(&conflicts, index);
259  if (err < 0) {
260  conflictsString << "Failed to create conflict iterator!\n";
261  goto ret;
262  }
263 
264  while ((err = git_index_conflict_next(&ancestor, &our, &their, conflicts))
265  == 0) {
266  conflictsString << "Conflict in file: "
267  << " a: " << (ancestor ? ancestor->path : "NULL")
268  << " o: " << (our->path ? our->path : "NULL")
269  << " t: " << (their->path ? their->path : "NULL")
270  << "\n";
271  }
272 
273  if (err != GIT_ITEROVER)
274  conflictsString << "Error iterating conflicts\n";
275 
276  git_index_conflict_iterator_free(conflicts);
277 
278  conflictsString << "\n"
279  << " a : Ancestor path\n"
280  << " o : Our path\n"
281  << " t : Their path\n";
282  conflictsString << "Resolve the conflicts and add files to mark them as "
283  << "resolved.\nCommit changes after resolving all files.\n";
284 ret:
285  printf("%s\n", conflictsString.String());
286  conflictsWindow->SetText(conflictsString);
287 
288  thread_id thread = conflictsWindow->Thread();
289  // wait for widow thread to return
290  status_t win_status = B_OK;
291  wait_for_thread(thread, &win_status);
292 }
293 
294 
299 int cred_acquire_cb(git_cred** out, const char* url,
300  const char* username_from_url, unsigned int allowed_types,
301  void* payload)
302 {
303  char username[100] = "",
304  password[100] = "";
305  CredentialsWindow* window = new CredentialsWindow(username, password);
306 
307  thread_id thread = window->Thread();
308  // wait for widow thread to return
309  status_t win_status = B_OK;
310  wait_for_thread(thread, &win_status);
311 
312  return git_cred_userpass_plaintext_new(out, username, password);
313 }
void output_conflicts(git_index *index)
Shows conflicts in current repo index in a window.
Definition: Utils.cpp:248
int create_commit(git_repository *repo, git_index *index, const char *message)
Creates a commit on given repo, index and message.
Definition: Utils.cpp:186
void extract_selected_paths(const BMessage *msg, vector< char *> &selected)
Get selected files.
Definition: Utils.cpp:50
Header file of Utils.
BString extract_current_directory(const BMessage *msg)
Get current directory.
Definition: Utils.cpp:28
int cred_acquire_cb(git_cred **out, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload)
This functions gets username and password from the user in case credentials are required.
Definition: Utils.cpp:299
The Conflicts Window class.
BString get_root_of_repo(BString dirPath)
Get the root of repo of current directory.
Definition: Utils.cpp:81
void SetText(BString)
Sets Text of the View in Window.
int perform_fastforward(git_repository *repo, const git_oid *target_oid, int is_unborn)
This performs fastforward on given repo, branch id.
Definition: Utils.cpp:103
The Credentials Window class.
Header file of Conflicts window.