ajwillia-ms pushed a commit to branch master.

http://git.enlightenment.org/tools/edi.git/commit/?id=a232dccaba988d61d920f0c3b2627c0a71a025d7

commit a232dccaba988d61d920f0c3b2627c0a71a025d7
Author: Al Poole <nets...@gmail.com>
Date:   Sat Jun 17 12:59:10 2017 +0100

    edi_scm: add support to add status of changes to the commit dialogue.
    
    Reviewers: ajwillia.ms
    
    Reviewed By: ajwillia.ms
    
    Differential Revision: https://phab.enlightenment.org/D4959
---
 src/bin/screens/edi_scm_screens.c |  90 +++++++++++++++++++++-
 src/lib/edi_exe.c                 |  20 ++++-
 src/lib/edi_scm.c                 | 158 ++++++++++++++++++++++++++++++++++----
 src/lib/edi_scm.h                 |  26 +++++++
 4 files changed, 270 insertions(+), 24 deletions(-)

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, "<b>Summary<b>");
+   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<br><br>And change 
details");
+   elm_object_text_set(input, "Enter commit summary<br><br>And change 
details<br>");
    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);
+
+   out = strdup(eina_strbuf_string_get(lines));
+
+   eina_strbuf_free(lines);
 
-   return strndup(buf, strlen(buf) - 1);
+   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->remote_add       = _edi_scm_git_remote_add;
-   engine->remote_name_get  = _edi_scm_git_remote_name_get;
+   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_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;
 
 /**
@@ -139,6 +158,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.
  *
  * @param src The source file,

-- 


Reply via email to