diff --git a/src/bin/screens/edi_scm_screens.c b/src/bin/screens/edi_scm_screens.c index 66b27da..a4c3298 100644 --- a/src/bin/screens/edi_scm_screens.c +++ b/src/bin/screens/edi_scm_screens.c @@ -75,8 +75,12 @@ void edi_scm_screens_commit(Evas_Object *parent) { Evas_Object *popup, *box, *hbox, *label, *avatar, *input, *button; - Eina_Strbuf *user; + Evas_Object *list, *icon; + Eina_Strbuf *state_text, *user; + Eina_List *l; Edi_Scm_Engine *engine; + Edi_Scm_Status *status; + Eina_Bool staged_changes; engine= edi_scm_engine_get(); if (!engine) @@ -121,11 +125,89 @@ edi_scm_screens_commit(Evas_Object *parent) evas_object_show(avatar); elm_box_pack_end(hbox, avatar); + label = elm_label_add(box); + evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(label, "Summary"); + elm_box_pack_end(box, label); + evas_object_show(label); + + list = elm_list_add(box); + elm_list_mode_set(list, ELM_LIST_EXPAND); + elm_list_select_mode_set(list, ELM_OBJECT_SELECT_MODE_NONE); + evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, list); + + staged_changes = EINA_FALSE; + + if (edi_scm_status_get()) + { + state_text = eina_strbuf_new(); + EINA_LIST_FOREACH(engine->statuses, l, status) + { + icon = elm_icon_add(box); + if (status->staged) + staged_changes = EINA_TRUE; + + eina_strbuf_append_printf(state_text, "%s ", status->path); + + switch (status->change) + { + case EDI_SCM_STATUS_ADDED: + elm_icon_standard_set(icon, "document-new"); + eina_strbuf_append(state_text, "(add) "); + break; + case EDI_SCM_STATUS_MODIFIED: + elm_icon_standard_set(icon, "document-save-as"); + eina_strbuf_append(state_text, "(mod) "); + break; + case EDI_SCM_STATUS_DELETED: + elm_icon_standard_set(icon, "edit-delete"); + eina_strbuf_append(state_text, "(del) "); + break; + case EDI_SCM_STATUS_RENAMED: + elm_icon_standard_set(icon, "document-save-as"); + eina_strbuf_append(state_text, "(ren) "); + break; + case EDI_SCM_STATUS_UNTRACKED: + elm_icon_standard_set(icon, "dialog-question"); + eina_strbuf_append(state_text, "(untracked)"); + break; + default: + elm_icon_standard_set(icon, "text-x-generic"); + } + + if (!status->staged && status->change != EDI_SCM_STATUS_UNTRACKED) + eina_strbuf_append(state_text, "- unstaged"); + + elm_list_item_append(list, eina_strbuf_string_get(state_text), icon, NULL, NULL, NULL); + + eina_strbuf_reset(state_text); + + eina_stringshare_del(status->path); + free(status); + } + eina_strbuf_free(state_text); + eina_list_free(engine->statuses); + engine->statuses = NULL; + } + else + { + icon = elm_icon_add(box); + elm_icon_standard_set(icon, "dialog-information"); + elm_list_item_append(list, "Nothing to commit.", icon, NULL, NULL, NULL); + } + + elm_list_go(list); + evas_object_show(list); + input = elm_entry_add(box); - elm_entry_editable_set(input, EINA_TRUE); - elm_object_text_set(input, "Enter commit summary

And change details"); + elm_object_text_set(input, "Enter commit summary

And change details
"); evas_object_size_hint_weight_set(input, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(input, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_entry_editable_set(input, staged_changes); + elm_object_style_set(input, "entry"); evas_object_show(input); elm_box_pack_end(box, input); @@ -138,10 +220,10 @@ edi_scm_screens_commit(Evas_Object *parent) button = elm_button_add(popup); evas_object_data_set(button, "input", input); elm_object_text_set(button, "commit"); + elm_object_disabled_set(button, !staged_changes); elm_object_part_content_set(popup, "button2", button); evas_object_smart_callback_add(button, "clicked", _edi_scm_screens_commit_cb, input); - evas_object_show(popup); elm_object_focus_set(input, EINA_TRUE); } diff --git a/src/lib/edi_exe.c b/src/lib/edi_exe.c index 2e5baf5..ed22845 100644 --- a/src/lib/edi_exe.c +++ b/src/lib/edi_exe.c @@ -33,17 +33,29 @@ edi_exe_response(const char *command) { FILE *p; char buf[8192]; + Eina_Strbuf *lines; + char *out; + ssize_t len; p = popen(command, "r"); if (!p) return NULL; - buf[0] = '\0'; - fgets(buf, sizeof(buf), p); + lines = eina_strbuf_new(); + + while ((fgets(buf, sizeof(buf), p)) != NULL) + { + eina_strbuf_append_printf(lines, "%s", buf); + } pclose(p); - if (strlen(buf) <= 1) return NULL; + len = eina_strbuf_length_get(lines); + eina_strbuf_remove(lines, len - 1, len); - return strndup(buf, strlen(buf) - 1); + out = strdup(eina_strbuf_string_get(lines)); + + eina_strbuf_free(lines); + + return out; } diff --git a/src/lib/edi_scm.c b/src/lib/edi_scm.c index 99418b0..6d75b5d 100644 --- a/src/lib/edi_scm.c +++ b/src/lib/edi_scm.c @@ -149,6 +149,118 @@ _edi_scm_git_status(void) return code; } +static Edi_Scm_Status * +_parse_line(char *line) +{ + char *path, *change; + Edi_Scm_Status *status; + + change = line; + line[2] = '\0'; + path = line + 3; + + status = malloc(sizeof(Edi_Scm_Status)); + if (!status) + return NULL; + + status->staged = EINA_FALSE; + + if (change[0] == 'A' || change[1] == 'A') + { + status->change = EDI_SCM_STATUS_ADDED; + if (change[0] == 'A') status->staged = EINA_TRUE; + } + else if (change[0] == 'R' || change[1] == 'R') + { + status->change = EDI_SCM_STATUS_RENAMED; + if (change[0] == 'R') status->staged = EINA_TRUE; + } + else if (change[0] == 'M' || change[1] == 'M') + { + status->change = EDI_SCM_STATUS_MODIFIED; + if (change[0] == 'M') status->staged = EINA_TRUE; + } + else if (change[0] == 'D' || change[1] == 'D') + { + status->change = EDI_SCM_STATUS_DELETED; + if (change[0] == 'D') status->staged = EINA_TRUE; + } + else if (change[0] == '?' && change[1] == '?') + { + status->change = EDI_SCM_STATUS_UNTRACKED; + } + else + status->change = EDI_SCM_STATUS_UNKNOWN; + + status->path = eina_stringshare_add(path); + + return status; +} + +static Eina_List * +_edi_scm_git_status_get(void) +{ + char *output, *pos, *start, *end; + char *line; + size_t size; + Eina_Strbuf *command; + Edi_Scm_Status *status; + Eina_List *list = NULL; + + command = eina_strbuf_new(); + + eina_strbuf_append(command, "git status --porcelain"); + + output = _edi_scm_exec_response(eina_strbuf_string_get(command)); + + eina_strbuf_free(command); + + end = NULL; + + pos = output; + start = pos; + + while (*pos++) + { + if (*pos == '\n') + end = pos; + if (start && end) + { + size = end - start; + line = malloc(size + 1); + memcpy(line, start, size); + line[size] = '\0'; + + status = _parse_line(line); + if (status) + list = eina_list_append(list, status); + + free(line); + start = end + 1; + end = NULL; + } + } + + end = pos; + size = end - start; + if (size > 1) + { + line = malloc(size + 1); + memcpy(line, start, size); + line[size] = '\0'; + + status = _parse_line(line); + if (status) + list = eina_list_append(list, status); + + free(line); + } + + free(output); + + return list; +} + static int _edi_scm_git_commit(const char *message) { @@ -365,6 +477,19 @@ edi_scm_move(const char *src, const char *dest) return e->move(src, dest); } +EAPI Eina_Bool +edi_scm_status_get(void) +{ + Edi_Scm_Engine *e = edi_scm_engine_get(); + + e->statuses = e->status_get(); + + if (!e->statuses) + return EINA_FALSE; + + return EINA_TRUE; +} + static void _edi_scm_commit_thread_cb(void *data, Ecore_Thread *thread) { @@ -481,23 +606,24 @@ _edi_scm_git_init() return NULL; _edi_scm_global_object = engine = calloc(1, sizeof(Edi_Scm_Engine)); - engine->name = eina_stringshare_add("git"); - engine->directory = eina_stringshare_add(".git"); - engine->file_add = _edi_scm_git_file_add; - engine->file_mod = _edi_scm_git_file_mod; - engine->file_del = _edi_scm_git_file_del; - engine->move = _edi_scm_git_file_move; - engine->status = _edi_scm_git_status; - engine->commit = _edi_scm_git_commit; - engine->pull = _edi_scm_git_pull; - engine->push = _edi_scm_git_push; - engine->stash = _edi_scm_git_stash; + engine->name = eina_stringshare_add("git"); + engine->directory = eina_stringshare_add(".git"); + engine->file_add = _edi_scm_git_file_add; + engine->file_mod = _edi_scm_git_file_mod; + engine->file_del = _edi_scm_git_file_del; + engine->move = _edi_scm_git_file_move; + engine->status = _edi_scm_git_status; + engine->commit = _edi_scm_git_commit; + engine->pull = _edi_scm_git_pull; + engine->push = _edi_scm_git_push; + engine->stash = _edi_scm_git_stash; - engine->remote_add = _edi_scm_git_remote_add; - engine->remote_name_get = _edi_scm_git_remote_name_get; + engine->remote_add = _edi_scm_git_remote_add; + engine->remote_name_get = _edi_scm_git_remote_name_get; engine->remote_email_get = _edi_scm_git_remote_email_get; - engine->remote_url_get = _edi_scm_git_remote_url_get; - engine->credentials_set = _edi_scm_git_credentials_set; + engine->remote_url_get = _edi_scm_git_remote_url_get; + engine->credentials_set = _edi_scm_git_credentials_set; + engine->status_get = _edi_scm_git_status_get; return engine; } diff --git a/src/lib/edi_scm.h b/src/lib/edi_scm.h index a2fe542..6af404e 100644 --- a/src/lib/edi_scm.h +++ b/src/lib/edi_scm.h @@ -25,12 +25,30 @@ typedef const char * (scm_fn_remote_name)(void); typedef const char * (scm_fn_remote_email)(void); typedef const char * (scm_fn_remote_url)(void); typedef int (scm_fn_credentials)(const char *name, const char *email); +typedef Eina_List * (scm_fn_status_get)(void); + +typedef enum { + EDI_SCM_STATUS_ADDED = 1, + EDI_SCM_STATUS_DELETED, + EDI_SCM_STATUS_MODIFIED, + EDI_SCM_STATUS_RENAMED, + EDI_SCM_STATUS_UNTRACKED, + EDI_SCM_STATUS_UNKNOWN, +} Edi_Scm_Status_Code; + +typedef struct _Edi_Scm_Status +{ + Eina_Stringshare *path; + Edi_Scm_Status_Code change; + Eina_Bool staged; +} Edi_Scm_Status; typedef struct _Edi_Scm_Engine { const char *name; const char *directory; const char *path; + Eina_List *statuses; scm_fn_add *file_add; scm_fn_mod *file_mod; @@ -47,6 +65,7 @@ typedef struct _Edi_Scm_Engine scm_fn_remote_email *remote_email_get; scm_fn_remote_url *remote_url_get; scm_fn_credentials *credentials_set; + scm_fn_status_get *status_get; } Edi_Scm_Engine; /** @@ -138,6 +157,13 @@ void edi_scm_commit(const char *message); */ void edi_scm_status(void); +/** + * Get status of repository. + * + * @return State whether a change was registered (true/false). +*/ +Eina_Bool edi_scm_status_get(void); + /** * Move from src to dest. *