netstar pushed a commit to branch master.

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

commit d54d156cd39f23b3276e6c414ffaa0bf22e3b701
Author: Al Poole <nets...@gmail.com>
Date:   Sun Sep 17 16:34:35 2017 +0100

    scm: reimplement support for file listing file status.
    
    This method is far more efficient and works well with large
    software trees. e.g. enlightenment.git.
---
 src/bin/edi_filepanel.c           | 219 ++++++++++++++++++++++++++++++++++++--
 src/bin/edi_filepanel.h           |  37 +++++++
 src/bin/edi_main.c                |   3 +
 src/bin/screens/edi_scm_screens.c |   2 +-
 src/lib/edi_scm.c                 |  23 ++--
 src/lib/edi_scm.h                 |   1 +
 6 files changed, 261 insertions(+), 24 deletions(-)

diff --git a/src/bin/edi_filepanel.c b/src/bin/edi_filepanel.c
index 3975608..a2fc3a2 100644
--- a/src/bin/edi_filepanel.c
+++ b/src/bin/edi_filepanel.c
@@ -29,7 +29,7 @@ typedef struct _Edi_Dir_Data
 
 static Elm_Genlist_Item_Class itc, itc2;
 static Evas_Object *list;
-static Eina_Hash *_list_items;
+static Eina_Hash *_list_items, *_list_statuses;
 static edi_filepanel_item_clicked_cb _open_cb;
 
 static Evas_Object *menu, *_main_win, *_filepanel_box, *_filter_box, *_filter;
@@ -38,10 +38,9 @@ static regex_t _filter_regex;
 static Eina_Bool _filter_set = EINA_FALSE;
 static Edi_Dir_Data *_root_dir;
 
-static void
-_file_listing_fill(Edi_Dir_Data *dir, Elm_Object_Item *parent_it);
-static void
-_file_listing_empty(Edi_Dir_Data *dir, Elm_Object_Item *parent_it);
+static Elm_Object_Item * _file_listing_item_find(const char *path);
+static void _file_listing_fill(Edi_Dir_Data *dir, Elm_Object_Item *parent_it);
+static void _file_listing_empty(Edi_Dir_Data *dir, Elm_Object_Item *parent_it);
 
 static Eina_Bool
 _file_path_hidden(const char *path, Eina_Bool filter)
@@ -58,6 +57,183 @@ _file_path_hidden(const char *path, Eina_Bool filter)
    return regexec(&_filter_regex, relative, 0, NULL, 0);
 }
 
+static const char *
+_icon_status(Edi_Scm_Status_Code code)
+{
+   switch (code)
+     {
+        case EDI_SCM_STATUS_NONE:
+        case EDI_SCM_STATUS_RENAMED:
+        case EDI_SCM_STATUS_DELETED:
+        case EDI_SCM_STATUS_RENAMED_STAGED:
+        case EDI_SCM_STATUS_DELETED_STAGED:
+        case EDI_SCM_STATUS_UNKNOWN:
+        case EDI_SCM_STATUS_ADDED:
+           return NULL;
+        case EDI_SCM_STATUS_ADDED_STAGED:
+           return "document-new";
+        case EDI_SCM_STATUS_MODIFIED:
+        case EDI_SCM_STATUS_MODIFIED_STAGED:
+          return "document-save-as";
+        case EDI_SCM_STATUS_UNTRACKED:
+          return "dialog-question";
+     }
+
+   return NULL;
+}
+
+static char *
+_file_status(const char *path, Edi_Scm_Status_Code code)
+{
+   char *orig;
+   static char text[4096];
+
+   orig = basename((char *)path);
+
+   text[0] = '\0';
+   strcat(text, orig);
+
+   switch (code)
+     {
+        case EDI_SCM_STATUS_NONE:
+        case EDI_SCM_STATUS_DELETED:
+        case EDI_SCM_STATUS_DELETED_STAGED:
+        case EDI_SCM_STATUS_UNKNOWN:
+           return text;
+        case EDI_SCM_STATUS_ADDED:
+           return strcat(text, _(" (Added & Unstaged)"));
+        case EDI_SCM_STATUS_ADDED_STAGED:
+           return strcat(text, _(" (Added)"));
+        case EDI_SCM_STATUS_RENAMED:
+           return strcat(text, _(" (Renamed & Unstaged)"));
+        case EDI_SCM_STATUS_RENAMED_STAGED:
+           return strcat(text, _(" (Renamed)"));
+        case EDI_SCM_STATUS_MODIFIED:
+           return strcat(text, _(" (Modified & Unstaged)"));
+        case EDI_SCM_STATUS_MODIFIED_STAGED:
+           return strcat(text, _(" (Modified)"));
+        case EDI_SCM_STATUS_UNTRACKED:
+           return strcat(text, _(" (Untracked)"));
+     }
+
+   return text;
+}
+
+static Edi_Scm_Status_Code *
+_file_status_item_find(const char *path)
+{
+   return eina_hash_find(_list_statuses, path);
+}
+
+static void
+_file_status_item_delete(const char *path)
+{
+   Edi_Scm_Status_Code *code;
+
+   code = _file_status_item_find(path);
+   if (!code)
+     return;
+
+   eina_hash_del(_list_statuses, path, NULL);
+}
+
+static void
+_file_status_item_add(const char *path, Edi_Scm_Status_Code status)
+{
+   Edi_Scm_Status_Code *code;
+
+   code = _file_status_item_find(path);
+   if (code)
+     _file_status_item_delete(path);
+
+   code = malloc(sizeof(Edi_Scm_Status_Code));
+   memcpy(code, &status, sizeof(Edi_Scm_Status_Code));
+
+   eina_hash_add(_list_statuses, path, code);
+}
+
+void edi_filepanel_item_update(const char *path)
+{
+   Elm_Object_Item *item = _file_listing_item_find(path);
+   if (!item)
+     return;
+
+   elm_genlist_item_update(item);
+}
+
+static void
+_edi_filepanel_update_dir(const char *directory)
+{
+   Eina_List *files;
+   char *path, *file;
+
+   files = ecore_file_ls(directory);
+
+   EINA_LIST_FREE(files, file)
+     {
+        if (file[0] != '.')
+          {
+             path = edi_path_append(directory, file);
+             if (ecore_file_is_dir(path))
+               _edi_filepanel_update_dir(path);
+             else
+               edi_filepanel_item_update(path);
+             free(path);
+          }
+        free(file);
+     }
+
+   if (files)
+     eina_list_free(files);
+}
+
+void edi_filepanel_item_update_all(void)
+{
+  _edi_filepanel_update_dir(edi_project_get());
+}
+
+static void _list_status_free_cb(void *data)
+{
+   Edi_Scm_Status_Code *code = data;
+   free(code);
+}
+
+void edi_filepanel_scm_status_reset(void)
+{
+   eina_hash_free_buckets(_list_statuses);
+}
+
+void
+edi_filepanel_scm_status_update(void)
+{
+   Edi_Scm_Engine *e;
+   Edi_Scm_Status *status;
+
+   e = edi_scm_engine_get();
+   if (!e)
+     return;
+
+   if (edi_scm_status_get())
+     {
+        EINA_LIST_FREE(e->statuses, status)
+          {
+             _file_status_item_add(status->fullpath, status->change);
+             eina_stringshare_del(status->path);
+             eina_stringshare_del(status->fullpath);
+             free(status);
+          }
+        eina_list_free(e->statuses);
+        e->statuses = NULL;
+     }
+}
+
+void edi_filepanel_status_refresh(void)
+{
+   edi_filepanel_scm_status_reset();
+   edi_filepanel_scm_status_update();
+   edi_filepanel_item_update_all();
+}
+
 static void
 _item_menu_open_cb(void *data, Evas_Object *obj EINA_UNUSED,
                    void *event_info EINA_UNUSED)
@@ -210,6 +386,8 @@ _item_menu_scm_add_cb(void *data, Evas_Object *obj 
EINA_UNUSED,
    sd = data;
 
    edi_scm_add(sd->path);
+   edi_filepanel_scm_status_update();
+   edi_filepanel_item_update(sd->path);
 }
 
 static void
@@ -426,6 +604,13 @@ static char *
 _text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *source 
EINA_UNUSED)
 {
    Edi_Dir_Data *sd = data;
+   Edi_Scm_Status_Code *code;
+
+   code = _file_status_item_find(sd->path);
+   if (code)
+     {
+        return strdup(_file_status(sd->path, *code));
+     }
 
    return strdup(basename((char *)sd->path));
 }
@@ -454,6 +639,8 @@ _content_get(void *data, Evas_Object *obj, const char 
*source)
    Edi_Content_Provider *provider;
    Edi_Dir_Data *sd = data;
    Evas_Object *ic;
+   Edi_Scm_Status_Code *code;
+   const char *icon_name;
 
    if (strcmp(source, "elm.swallow.icon"))
      return NULL;
@@ -462,10 +649,19 @@ _content_get(void *data, Evas_Object *obj, const char 
*source)
 
    ic = elm_icon_add(obj);
 
-   if (provider)
-     elm_icon_standard_set(ic, provider->icon);
+   code = _file_status_item_find(sd->path);
+   if (code)
+     {
+        icon_name = _icon_status(*code);
+        elm_icon_standard_set(ic, icon_name);
+     }
    else
-     elm_icon_standard_set(ic, "empty");
+     {
+        if (provider)
+          elm_icon_standard_set(ic, provider->icon);
+        else
+          elm_icon_standard_set(ic, "empty");
+     }
 
    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
    evas_object_show(ic);
@@ -657,6 +853,7 @@ _ls_done_cb(void *data, Eio_File *handler EINA_UNUSED)
 {
    Listing_Request *lreq = data;
 
+   edi_filepanel_scm_status_update();
    _listing_request_cleanup(lreq);
 }
 
@@ -729,6 +926,9 @@ _file_listing_updated(void *data EINA_UNUSED, int type 
EINA_UNUSED,
      _file_listing_item_delete(ev->filename);
    else
     DBG("Ignoring file update event for %s", ev->filename);
+
+   edi_filepanel_scm_status_update();
+   edi_filepanel_item_update(ev->filename);
 }
 
 /* Panel filtering */
@@ -897,9 +1097,12 @@ edi_filepanel_add(Evas_Object *parent, Evas_Object *win,
    _main_win = win;
 
    _list_items = eina_hash_string_superfast_new(NULL);
+   _list_statuses = eina_hash_string_superfast_new(NULL);
+   eina_hash_free_cb_set(_list_statuses, _list_status_free_cb);
    _root_dir = calloc(1, sizeof(Edi_Dir_Data));
    _root_dir->path = path;
    _file_listing_fill(_root_dir, NULL);
+   edi_filepanel_scm_status_update();
    evas_object_smart_callback_add(filter, "changed", _filter_key_down_cb, 
list);
 }
 
diff --git a/src/bin/edi_filepanel.h b/src/bin/edi_filepanel.h
index 83e08f7..29c09d6 100644
--- a/src/bin/edi_filepanel.h
+++ b/src/bin/edi_filepanel.h
@@ -66,6 +66,43 @@ void edi_filepanel_select_path(const char *path);
 void edi_filepanel_search();
 
 /**
+ * Clear cache of file statuses, update the cache and update file panel items.
+ *
+ * @ingroup UI
+ */
+void edi_filepanel_status_refresh(void);
+
+/**
+ * Update the cache of scm statuses in memory.
+ *
+ * @ingroup UI
+ */
+void edi_filepanel_scm_status_update(void);
+
+/**
+ * Clear the caches list of scm statuses.
+ *
+ * @ingroup UI
+ */
+void edi_filepanel_scm_status_reset(void);
+
+/**
+ * Update a single item's state in the filepanel by path.
+ *
+ * @param path The path of the file to be updated.
+ *
+ * @ingroup UI
+ */
+void edi_filepanel_item_update(const char *path);
+
+/**
+ * Update all items' state in the filepanel.
+ *
+ * @ingroup UI
+ */
+void edi_filepanel_item_update_all(void);
+
+/**
  * @}
  */
 
diff --git a/src/bin/edi_main.c b/src/bin/edi_main.c
index cf48f3c..ef4a1d1 100644
--- a/src/bin/edi_main.c
+++ b/src/bin/edi_main.c
@@ -1003,6 +1003,8 @@ _edi_menu_scm_init_cb(void *data EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED,
    edi_consolepanel_show();
    edi_scm_git_new();
    edi_scm_init();
+   edi_filepanel_scm_status_update();
+   edi_filepanel_status_refresh();
    _edi_icon_update();
 }
 
@@ -1024,6 +1026,7 @@ static void
 _edi_scm_stash_do_cb(void *data EINA_UNUSED)
 {
    edi_scm_stash();
+   edi_filepanel_scm_status_reset();
 }
 
 static void
diff --git a/src/bin/screens/edi_scm_screens.c 
b/src/bin/screens/edi_scm_screens.c
index 8abb686..0e9c315 100644
--- a/src/bin/screens/edi_scm_screens.c
+++ b/src/bin/screens/edi_scm_screens.c
@@ -73,7 +73,7 @@ _edi_scm_screens_commit_cb(void *data,
    edi_consolepanel_clear();
    edi_consolepanel_show();
    edi_scm_commit(message);
-
+   edi_filepanel_status_refresh();
    evas_object_del(_popup);
 
    free(message);
diff --git a/src/lib/edi_scm.c b/src/lib/edi_scm.c
index 7c30c1b..b8d4574 100644
--- a/src/lib/edi_scm.c
+++ b/src/lib/edi_scm.c
@@ -163,7 +163,7 @@ _edi_scm_git_status(void)
 static Edi_Scm_Status *
 _parse_line(char *line)
 {
-   char *path, *change;
+   char *path, *fullpath, *change;
    Edi_Scm_Status *status;
 
    change = line;
@@ -216,6 +216,9 @@ _parse_line(char *line)
         status->change = EDI_SCM_STATUS_UNKNOWN;
 
    status->path = eina_stringshare_add(path);
+   fullpath = edi_path_append(edi_project_get(), path);
+   status->fullpath = eina_stringshare_add(fullpath);
+   free(fullpath);
 
    return status;
 }
@@ -240,6 +243,7 @@ _edi_scm_git_file_status(const char *path)
         status = _parse_line(line);
         result = status->change;
         eina_stringshare_del(status->path);
+        eina_stringshare_del(status->fullpath);
         free(status);
      }
 
@@ -569,23 +573,12 @@ edi_scm_file_status(const char *path)
    return e->file_status(path);
 }
 
-static void
-_edi_scm_commit_thread_cb(void *data, Ecore_Thread *thread)
-{
-   Edi_Scm_Engine *e;
-   const char *message = data;
-
-   e = edi_scm_engine_get();
-
-   e->commit(message);
-
-   ecore_thread_cancel(thread);
-}
-
 EAPI void
 edi_scm_commit(const char *message)
 {
-   ecore_thread_run(_edi_scm_commit_thread_cb, NULL, NULL, message);
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   e->commit(message);
 }
 
 static void
diff --git a/src/lib/edi_scm.h b/src/lib/edi_scm.h
index c3842ca..a405cfb 100644
--- a/src/lib/edi_scm.h
+++ b/src/lib/edi_scm.h
@@ -27,6 +27,7 @@ typedef enum {
 typedef struct _Edi_Scm_Status
 {
    Eina_Stringshare *path;
+   Eina_Stringshare *fullpath;
    Edi_Scm_Status_Code change;
    Eina_Bool staged;
 } Edi_Scm_Status;

-- 


Reply via email to