ajwillia-ms pushed a commit to branch master.

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

commit d208afac91273917a312d313a18847b80615cce8
Author: Al Poole <[email protected]>
Date:   Tue Jun 6 17:45:44 2017 -0700

    scm: add support for SCM (git) in library and the UI.
    
    Reviewers: ajwillia.ms
    
    Reviewed By: ajwillia.ms
    
    Tags: #edi
    
    Differential Revision: https://phab.enlightenment.org/D4938
---
 src/bin/Makefile.am                |   2 +
 src/bin/edi_config.c               |   3 +
 src/bin/edi_config.h               |   2 +
 src/bin/edi_filepanel.c            |  38 ++-
 src/bin/edi_main.c                 | 170 ++++++++++--
 src/bin/mainview/edi_mainview.c    |  43 ++-
 src/bin/mainview/edi_mainview.h    |  20 +-
 src/bin/screens/edi_file_screens.c |   6 +-
 src/bin/screens/edi_scm_screens.c  | 132 +++++++++
 src/bin/screens/edi_scm_screens.h  |  54 ++++
 src/bin/screens/edi_settings.c     | 156 ++++++++++-
 src/lib/Edi.h                      |   1 +
 src/lib/Makefile.am                |   2 +
 src/lib/edi_create.c               |  18 +-
 src/lib/edi_exe.c                  |  20 +-
 src/lib/edi_exe.h                  |  10 +
 src/lib/edi_scm.c                  | 543 +++++++++++++++++++++++++++++++++++++
 src/lib/edi_scm.h                  | 213 +++++++++++++++
 18 files changed, 1397 insertions(+), 36 deletions(-)

diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 97a3d66..c159a8c 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -27,6 +27,7 @@ editor/edi_editor.h \
 edi_content_provider.h \
 screens/edi_screens.h \
 screens/edi_file_screens.h \
+screens/edi_scm_screens.h \
 edi_filepanel.h \
 edi_file.h \
 edi_logpanel.h \
@@ -48,6 +49,7 @@ screens/edi_about.c \
 screens/edi_settings_font.c \
 screens/edi_settings.c \
 screens/edi_file_screens.c \
+screens/edi_scm_screens.c \
 edi_filepanel.c \
 edi_file.c \
 edi_logpanel.c \
diff --git a/src/bin/edi_config.c b/src/bin/edi_config.c
index 3ba0342..20ef53c 100644
--- a/src/bin/edi_config.c
+++ b/src/bin/edi_config.c
@@ -259,6 +259,9 @@ _edi_config_init(void)
    EDI_CONFIG_VAL(D, T, launch.path, EET_T_STRING);
    EDI_CONFIG_VAL(D, T, launch.args, EET_T_STRING);
 
+   EDI_CONFIG_VAL(D, T, user_fullname, EET_T_STRING);
+   EDI_CONFIG_VAL(D, T, user_email, EET_T_STRING);
+
    _edi_config_load();
 
    return EINA_TRUE;
diff --git a/src/bin/edi_config.h b/src/bin/edi_config.h
index 82ffae0..b8e42cd 100644
--- a/src/bin/edi_config.h
+++ b/src/bin/edi_config.h
@@ -82,6 +82,8 @@ struct _Edi_Project_Config
 
    Eina_List *tabs;
    Edi_Project_Config_Launch launch;
+   Eina_Stringshare *user_fullname;
+   Eina_Stringshare *user_email;
 };
 
 extern Edi_Config *_edi_config;
diff --git a/src/bin/edi_filepanel.c b/src/bin/edi_filepanel.c
index aff6a6b..bbfd4d3 100644
--- a/src/bin/edi_filepanel.c
+++ b/src/bin/edi_filepanel.c
@@ -155,6 +155,29 @@ _item_menu_del_cb(void *data, Evas_Object *obj EINA_UNUSED,
 }
 
 static void
+_item_menu_scm_add_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                      void *event_info EINA_UNUSED)
+{
+   Edi_Dir_Data *sd;
+
+   sd = data;
+
+   edi_scm_add(sd->path);
+}
+
+static void
+_item_menu_scm_del_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                      void *event_info EINA_UNUSED)
+{
+   Edi_Dir_Data *sd;
+
+   sd = data;
+   edi_mainview_item_close_path(sd->path);
+
+   edi_scm_del(sd->path);
+}
+
+static void
 _item_menu_dismissed_cb(void *data EINA_UNUSED, Evas_Object *obj,
                         void *ev EINA_UNUSED)
 {
@@ -191,8 +214,19 @@ _item_menu_create(Evas_Object *win, Edi_Dir_Data *sd)
    _item_menu_filetype_create(menu, menu_it, "text", 
_item_menu_open_as_text_cb, sd);
    _item_menu_filetype_create(menu, menu_it, "code", 
_item_menu_open_as_code_cb, sd);
    _item_menu_filetype_create(menu, menu_it, "image", 
_item_menu_open_as_image_cb, sd);
-   menu_it = elm_menu_item_add(menu, NULL, "document-save-as", "rename", 
_item_menu_rename_cb, sd);
-   menu_it = elm_menu_item_add(menu, NULL, "edit-delete", "delete", 
_item_menu_del_cb, sd);
+
+   if (edi_scm_enabled())
+     {
+        menu_it = elm_menu_item_add(menu, NULL, NULL, "source control", NULL, 
NULL);
+        elm_menu_item_add(menu, menu_it, "document-save-as", "add changes", 
_item_menu_scm_add_cb, sd);
+        elm_menu_item_add(menu, menu_it, "document-save-as", "rename file", 
_item_menu_rename_cb, sd);
+        elm_menu_item_add(menu, menu_it, "edit-delete", "delete file", 
_item_menu_scm_del_cb, sd);
+     }
+   else
+     {
+        menu_it = elm_menu_item_add(menu, NULL, "document-save-as", "rename 
file", _item_menu_rename_cb, sd);
+        menu_it = elm_menu_item_add(menu, NULL, "edit-delete", "delete file", 
_item_menu_del_cb, sd);
+     }
 }
 
 static void
diff --git a/src/bin/edi_main.c b/src/bin/edi_main.c
index e442fcf..816c5d7 100644
--- a/src/bin/edi_main.c
+++ b/src/bin/edi_main.c
@@ -26,6 +26,7 @@
 #include "mainview/edi_mainview.h"
 #include "screens/edi_screens.h"
 #include "screens/edi_file_screens.h"
+#include "screens/edi_scm_screens.h"
 
 #include "edi_private.h"
 
@@ -51,6 +52,7 @@ static Elm_Object_Item *_edi_selected_bottompanel;
 static Evas_Object *_edi_filepanel, *_edi_filepanel_icon;
 
 static Evas_Object *_edi_menu_undo, *_edi_menu_redo, *_edi_toolbar_undo, 
*_edi_toolbar_redo;
+static Evas_Object *_edi_menu_init, *_edi_menu_commit, *_edi_menu_push, 
*_edi_menu_pull, *_edi_menu_status, *_edi_menu_stash;
 static Evas_Object *_edi_menu_save, *_edi_toolbar_save;
 static Evas_Object *_edi_main_win, *_edi_main_box, *_edi_message_popup;
 int _edi_log_dom = -1;
@@ -521,6 +523,35 @@ edi_content_setup(Evas_Object *win, const char *path)
 }
 
 static void
+_edi_icon_update()
+{
+   Eina_Bool modified, can_scm, can_remote, can_undo, can_redo;
+
+   can_undo = edi_mainview_can_undo();
+   can_redo = edi_mainview_can_redo();
+   can_scm = edi_scm_enabled();
+   can_remote = can_scm && edi_scm_remote_enabled();
+   modified = edi_mainview_modified();
+
+   elm_object_item_disabled_set(_edi_menu_save, !modified);
+   elm_object_disabled_set(_edi_toolbar_save, !modified);
+
+   elm_object_item_disabled_set(_edi_menu_undo, !can_undo);
+   elm_object_item_disabled_set(_edi_menu_redo, !can_redo);
+
+   elm_object_disabled_set(_edi_toolbar_undo, !can_undo);
+   elm_object_disabled_set(_edi_toolbar_redo, !can_redo);
+
+   elm_object_item_disabled_set(_edi_menu_init, can_scm);
+   elm_object_item_disabled_set(_edi_menu_push, !can_remote);
+   elm_object_item_disabled_set(_edi_menu_pull, !can_remote);
+   elm_object_item_disabled_set(_edi_menu_status, !can_scm);
+   elm_object_item_disabled_set(_edi_menu_commit, !can_scm);
+   elm_object_item_disabled_set(_edi_menu_stash, !can_scm);
+
+}
+
+static void
 _edi_popup_cancel_cb(void *data, Evas_Object *obj EINA_UNUSED,
                      void *event_info EINA_UNUSED)
 {
@@ -571,6 +602,36 @@ _edi_launcher_run(Edi_Project_Config_Launch *launch)
 }
 
 static void
+_edi_project_credentials_missing()
+
+{
+   Evas_Object *popup, *button;
+
+   popup = elm_popup_add(_edi_main_win);
+   elm_object_part_text_set(popup, "title,text", "User information");
+   elm_object_text_set(popup, "No user information found, please configure in 
Settings");
+
+   button = elm_button_add(popup);
+   elm_object_text_set(button, "OK");
+   elm_object_part_content_set(popup, "button1", button);
+   evas_object_smart_callback_add(button, "clicked", _edi_popup_cancel_cb, 
popup);
+
+   evas_object_show(popup);
+}
+
+static Eina_Bool
+_edi_project_credentials_check(void)
+{
+   if (!_edi_project_config->user_fullname || 
strlen(_edi_project_config->user_fullname) == 0)
+     return EINA_FALSE;
+
+   if (!_edi_project_config->user_email || 
strlen(_edi_project_config->user_email) == 0)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static void
 _tb_new_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info 
EINA_UNUSED)
 {
    const char *path, *selected;
@@ -896,6 +957,84 @@ _edi_menu_debug_cb(void *data EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED,
 }
 
 static void
+_edi_menu_scm_init_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                        void *event_info EINA_UNUSED)
+{
+   if (!_edi_project_credentials_check())
+     {
+        _edi_project_credentials_missing();
+        return;
+     }
+
+   if (!ecore_file_app_installed("git"))
+     {
+        edi_scm_screens_binary_missing(_edi_main_win, "git");
+        return;
+     }
+
+   edi_consolepanel_clear();
+   edi_consolepanel_show();
+   edi_scm_git_new();
+   _edi_icon_update();
+}
+
+static void
+_edi_menu_scm_commit_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                        void *event_info EINA_UNUSED)
+{
+   if (!_edi_project_credentials_check())
+     {
+        _edi_project_credentials_missing();
+        return;
+     }
+
+   edi_scm_credits(_edi_project_config->user_fullname, 
_edi_project_config->user_email);
+   edi_scm_screens_commit(_edi_main_win);
+}
+
+static void
+_edi_menu_scm_stash_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                       void *event_info EINA_UNUSED)
+{
+   edi_scm_stash();
+   edi_mainview_refresh_all();
+}
+
+static void
+_edi_menu_scm_status_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                        void *event_info EINA_UNUSED)
+{
+   edi_consolepanel_clear();
+   edi_consolepanel_show();
+   edi_scm_status();
+}
+
+static void
+_edi_menu_scm_pull_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                        void *event_info EINA_UNUSED)
+{
+   edi_consolepanel_clear();
+   edi_consolepanel_show();
+   edi_scm_pull();
+}
+
+static void
+_edi_menu_scm_push_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+                        void *event_info EINA_UNUSED)
+{
+   if (!_edi_project_credentials_check())
+     {
+        _edi_project_credentials_missing();
+        return;
+     }
+
+   edi_scm_credits(_edi_project_config->user_fullname, 
_edi_project_config->user_email);
+   edi_consolepanel_clear();
+   edi_consolepanel_show();
+   edi_scm_push();
+}
+
+static void
 _edi_menu_website_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
                      void *event_info EINA_UNUSED)
 {
@@ -951,6 +1090,15 @@ _edi_menu_setup(Evas_Object *obj)
    elm_menu_item_add(menu, menu_it, "utilities-terminal", "Debug", 
_edi_menu_debug_cb, NULL);
    elm_menu_item_add(menu, menu_it, "edit-clear", "Clean", _edi_menu_clean_cb, 
NULL);
 
+   menu_it = elm_menu_item_add(menu, NULL, NULL, "Project", NULL, NULL);
+   _edi_menu_init = elm_menu_item_add(menu, menu_it, "media-playback-start", 
"Init", _edi_menu_scm_init_cb, NULL);
+   _edi_menu_commit = elm_menu_item_add(menu, menu_it, "mail-send", "Commit", 
_edi_menu_scm_commit_cb, NULL);
+   _edi_menu_stash = elm_menu_item_add(menu, menu_it, "edit-undo", "Stash", 
_edi_menu_scm_stash_cb, NULL);
+   _edi_menu_status = elm_menu_item_add(menu, menu_it, "dialog-error", 
"Status", _edi_menu_scm_status_cb, NULL);
+   _edi_menu_push = elm_menu_item_add(menu, menu_it, "go-up", "Push", 
_edi_menu_scm_push_cb, NULL);
+   _edi_menu_pull = elm_menu_item_add(menu, menu_it, "go-down", "Pull", 
_edi_menu_scm_pull_cb, NULL);
+
+
    menu_it = elm_menu_item_add(menu, NULL, NULL, "Help", NULL, NULL);
    elm_menu_item_add(menu, menu_it, "go-home", "Website", 
_edi_menu_website_cb, NULL);
    elm_menu_item_separator_add(menu, menu_it);
@@ -1070,26 +1218,6 @@ _edi_resize_cb(void *data EINA_UNUSED, Evas *e 
EINA_UNUSED, Evas_Object *obj,
 }
 
 static void
-_edi_icon_update()
-{
-   Eina_Bool modified, can_undo, can_redo = EINA_FALSE;
-
-   can_undo = edi_mainview_can_undo();
-   can_redo = edi_mainview_can_redo();
-
-   modified = edi_mainview_modified();
-
-   elm_object_item_disabled_set(_edi_menu_save, !modified);
-   elm_object_disabled_set(_edi_toolbar_save, !modified);
-
-   elm_object_item_disabled_set(_edi_menu_undo, !can_undo);
-   elm_object_item_disabled_set(_edi_menu_redo, !can_redo);
-
-   elm_object_disabled_set(_edi_toolbar_undo, !can_undo);
-   elm_object_disabled_set(_edi_toolbar_redo, !can_redo);
-}
-
-static void
 _edi_toolbar_set_visible(Eina_Bool visible)
 {
    elm_box_unpack(_edi_main_box, _edi_toolbar);
@@ -1238,6 +1366,7 @@ edi_open(const char *inputpath)
 
    _edi_config_project_add(path);
    _edi_open_tabs();
+   edi_scm_init();
    _edi_icon_update();
 
    evas_object_smart_callback_add(win, "delete,request", _win_delete_cb, NULL);
@@ -1412,6 +1541,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
  end:
    _edi_log_shutdown();
    elm_shutdown();
+   edi_scm_shutdown();
    edi_shutdown();
 
  config_error:
diff --git a/src/bin/mainview/edi_mainview.c b/src/bin/mainview/edi_mainview.c
index 3cdba92..6652376 100644
--- a/src/bin/mainview/edi_mainview.c
+++ b/src/bin/mainview/edi_mainview.c
@@ -466,19 +466,52 @@ edi_mainview_open_window(Edi_Path_Options *options)
 }
 
 void
+edi_mainview_close_all(void)
+{
+   Eina_List *item;
+   Edi_Mainview_Item *it;
+
+   EINA_LIST_FOREACH(_edi_mainview_items, item, it)
+     {
+        if (it)
+          _edi_mainview_item_close(it);
+     }
+}
+
+void
+edi_mainview_refresh_all(void)
+{
+   Eina_List *item;
+   Edi_Mainview_Item *it;
+   char *path;
+
+   EINA_LIST_FOREACH(_edi_mainview_items, item, it)
+     {
+        if (it)
+          {
+             path = strdup(it->path);
+             _edi_mainview_item_close(it);
+             if (ecore_file_exists(path))
+               edi_mainview_open_path(path);
+             free(path);
+          }
+     }
+}
+
+void
 edi_mainview_item_close_path(const char *path)
 {
    Eina_List *item;
    Edi_Mainview_Item *it;
 
    EINA_LIST_FOREACH(_edi_mainview_items, item, it)
-    {
-       if (it && !strcmp(it->path, path))
-         {
+     {
+        if (it && !strcmp(it->path, path))
+          {
              _edi_mainview_item_close(it);
              return;
-         }
-    }
+          }
+     }
 }
 
 void
diff --git a/src/bin/mainview/edi_mainview.h b/src/bin/mainview/edi_mainview.h
index 55496a4..d98b601 100644
--- a/src/bin/mainview/edi_mainview.h
+++ b/src/bin/mainview/edi_mainview.h
@@ -38,13 +38,27 @@ extern "C" {
 void edi_mainview_add(Evas_Object *parent, Evas_Object *win);
 
 /**
- * Delete a mainview by its path
- * @param parh The path of the file associated with tab to close.
+ * Close mainview by path.
  *
- * @ingroup UI
+ * @praram path The path of file to close.
+ *
+ * @ingroup Content
  */
 void edi_mainview_item_close_path(const char *path);
 
+/**
+ * Refresh all existing open files.
+ *
+ * @ingroup Content
+ */
+void edi_mainview_refresh_all(void);
+
+/**
+ * Close all existing open files.
+ *
+ * @ingroup Content
+ */
+void edi_mainview_close_all(void);
 
 /**
  * @}
diff --git a/src/bin/screens/edi_file_screens.c 
b/src/bin/screens/edi_file_screens.c
index 6b1aebe..609ec12 100644
--- a/src/bin/screens/edi_file_screens.c
+++ b/src/bin/screens/edi_file_screens.c
@@ -151,7 +151,11 @@ _edi_file_screens_rename_cb(void *data,
      {
         if (!ecore_file_is_dir(existing_path))
           edi_mainview_item_close_path(existing_path);
-        ecore_file_mv(existing_path, path);
+
+        if (!edi_scm_enabled())
+          ecore_file_mv(existing_path, path);
+        else
+          edi_scm_move(existing_path, path);
      }
 
    evas_object_del(_popup);
diff --git a/src/bin/screens/edi_scm_screens.c 
b/src/bin/screens/edi_scm_screens.c
new file mode 100644
index 0000000..ab659a8
--- /dev/null
+++ b/src/bin/screens/edi_scm_screens.c
@@ -0,0 +1,132 @@
+#include "Edi.h"
+#include "mainview/edi_mainview.h"
+#include "edi_consolepanel.h"
+#include "edi_scm_screens.h"
+#include "edi_private.h"
+
+static Evas_Object *_parent_obj, *_popup, *_edi_scm_screens_message_popup;
+
+static void
+_edi_scm_screens_message_close_cb(void *data EINA_UNUSED,
+                     Evas_Object *obj EINA_UNUSED,
+                     void *event_info EINA_UNUSED)
+{
+   Evas_Object *popup = data;
+   evas_object_del(popup);
+}
+
+static void
+_edi_scm_screens_message_open(const char *message)
+{
+   Evas_Object *popup, *button;
+
+   _edi_scm_screens_message_popup = popup = elm_popup_add(_parent_obj);
+   elm_object_part_text_set(popup, "title,text",
+                           message);
+
+   button = elm_button_add(popup);
+   elm_object_text_set(button, "Ok");
+   elm_object_part_content_set(popup, "button1", button);
+   evas_object_smart_callback_add(button, "clicked",
+                                 _edi_scm_screens_message_close_cb, popup);
+
+   evas_object_show(popup);
+}
+
+static void
+_edi_scm_screens_popup_cancel_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                     void *event_info EINA_UNUSED)
+{
+   evas_object_del((Evas_Object *)data);
+}
+
+static void
+_edi_scm_screens_commit_cb(void *data,
+                           Evas_Object *obj EINA_UNUSED,
+                           void *event_info EINA_UNUSED)
+{
+   Edi_Scm_Engine *e;
+   const char *message;
+
+   e = edi_scm_engine_get();
+   if (!e) 
+     {
+        _edi_scm_screens_message_open("SCM engine is not available.");
+        return;
+     }
+
+   message = elm_entry_entry_get((Evas_Object *) data);
+   if (!message || strlen(message) == 0)
+     {
+        _edi_scm_screens_message_open("Please enter a valid commit message.");
+        return;
+     }
+
+   edi_consolepanel_clear();
+   edi_consolepanel_show();
+   edi_scm_commit(message);
+
+   evas_object_del(_popup);
+}
+
+void
+edi_scm_screens_commit(Evas_Object *parent)
+{
+   Evas_Object *popup, *box, *input, *button;
+
+   _parent_obj = parent;
+   _popup = popup = elm_popup_add(parent);
+   
+   elm_object_part_text_set(popup, "title,text",
+                                     "Enter commit message");
+   box = elm_box_add(popup);
+   elm_box_horizontal_set(box, EINA_FALSE);
+   elm_object_content_set(popup, box);
+
+   input = elm_entry_add(box);
+   elm_entry_single_line_set(input, EINA_TRUE);
+   elm_entry_editable_set(input, EINA_TRUE);
+   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);
+   evas_object_show(input);
+   elm_box_pack_end(box, input);
+
+   button = elm_button_add(popup);
+   elm_object_text_set(button, "cancel");
+   elm_object_part_content_set(popup, "button1", button);
+   evas_object_smart_callback_add(button, "clicked",
+                                  _edi_scm_screens_popup_cancel_cb, popup);
+
+   button = elm_button_add(popup);
+   evas_object_data_set(button, "input", input);
+   elm_object_text_set(button, "commit message");
+   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);
+}
+
+void
+edi_scm_screens_binary_missing(Evas_Object *parent, const char *binary)
+{
+   Evas_Object *popup, *button;
+   Eina_Strbuf *text = eina_strbuf_new();
+
+   eina_strbuf_append_printf(text, "No %s binary found, please install %s.", 
binary, binary);
+
+   popup = elm_popup_add(parent);
+   elm_object_part_text_set(popup, "title,text", "SCM: Unable to launch");
+   elm_object_text_set(popup, eina_strbuf_string_get(text));
+
+   eina_strbuf_free(text);
+
+   button = elm_button_add(popup);
+   elm_object_text_set(button, "OK");
+   elm_object_part_content_set(popup, "button1", button);
+   evas_object_smart_callback_add(button, "clicked", 
_edi_scm_screens_popup_cancel_cb, popup);
+
+   evas_object_show(popup);
+}
+
diff --git a/src/bin/screens/edi_scm_screens.h 
b/src/bin/screens/edi_scm_screens.h
new file mode 100644
index 0000000..7ea2b18
--- /dev/null
+++ b/src/bin/screens/edi_scm_screens.h
@@ -0,0 +1,54 @@
+#ifndef __EDI_SCM_SCREENS_H__
+#define __EDI_SCM_SCREENS_H__
+
+#include <Elementary.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ * @brief These routines used for managing Edi SCM actions from UI.
+ */
+
+/**
+ * @brief Scm management functions.
+ * @defgroup Scm 
+ *
+ * @{
+ *
+ * Management of SCM with the UI
+ *
+ */
+
+/**
+ * Create a SCM commit dialogue in the parent obj.
+ *
+ * @param parent The object into which the UI will load.
+ * @ingroup Scm
+ */
+void edi_scm_screens_commit(Evas_Object *parent);
+
+/**
+ * SCM binary is not installed, show dialogue.
+ *
+ * @param parent The object into which the UI will load.
+ * @param binary The name of the missing binary.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_screens_binary_missing(Evas_Object *parent, const char *binary);
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
diff --git a/src/bin/screens/edi_settings.c b/src/bin/screens/edi_settings.c
index e8840db..0220325 100644
--- a/src/bin/screens/edi_settings.c
+++ b/src/bin/screens/edi_settings.c
@@ -5,13 +5,14 @@
 #include <Elementary.h>
 #include <Ecore.h>
 
+#include "Edi.h"
 #include "edi_screens.h"
 #include "edi_config.h"
 
 #include "edi_private.h"
 
 static Elm_Object_Item *_edi_settings_display, *_edi_settings_builds,
-                       *_edi_settings_behaviour;
+                       *_edi_settings_behaviour, *_edi_settings_project;
 
 static void
 _edi_settings_exit(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
@@ -361,6 +362,151 @@ _edi_settings_builds_create(Evas_Object *parent)
 }
 
 static void
+_edi_settings_project_remote_cb(void *data EINA_UNUSED, Evas_Object *obj,
+                                void *event EINA_UNUSED)
+{
+   Evas_Object *entry;
+   const char *url;
+
+   entry = (Evas_Object *) obj;
+   url = elm_object_text_get(entry);
+
+   if (!url || strlen(url) == 0)
+     return;
+
+   if (!edi_scm_enabled())
+     return;
+
+   edi_scm_remote_add(elm_object_text_get(entry));
+}
+
+static void
+_edi_settings_project_email_cb(void *data EINA_UNUSED, Evas_Object *obj,
+                             void *event EINA_UNUSED)
+{
+   Evas_Object *entry;
+
+   entry = (Evas_Object *)obj;
+
+   if (_edi_project_config->user_email)
+     eina_stringshare_del(_edi_project_config->user_email);
+
+   _edi_project_config->user_email = 
eina_stringshare_add(elm_object_text_get(entry));
+   _edi_project_config_save();
+}
+
+static void
+_edi_settings_project_name_cb(void *data EINA_UNUSED, Evas_Object *obj,
+                             void *event EINA_UNUSED)
+{
+   Evas_Object *entry;
+
+   entry = (Evas_Object *)obj;
+
+   if (_edi_project_config->user_fullname)
+     eina_stringshare_del(_edi_project_config->user_fullname);
+
+   _edi_project_config->user_fullname = 
eina_stringshare_add(elm_object_text_get(entry));
+   _edi_project_config_save();
+}
+
+static Evas_Object *
+_edi_settings_project_create(Evas_Object *parent)
+{
+   Edi_Scm_Engine *engine;
+   Evas_Object *box, *frame, *hbox, *label, *entry_name, *entry_email;
+   Evas_Object *entry_remote;
+   Eina_Strbuf *text;
+
+   frame = _edi_settings_panel_create(parent, "Project");
+   box = elm_object_part_content_get(frame, "default");
+
+   hbox = elm_box_add(parent);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, hbox);
+   evas_object_show(hbox);
+
+   label = elm_label_add(hbox);
+   elm_object_text_set(label, "Author Name: ");
+   evas_object_size_hint_weight_set(label, 0.0, 0.0);
+   evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, label);
+   evas_object_show(label);
+
+   entry_name = elm_entry_add(hbox);
+   elm_object_text_set(entry_name, _edi_project_config->user_fullname);
+   evas_object_size_hint_weight_set(entry_name, 0.75, 0.0);
+   evas_object_size_hint_align_set(entry_name, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, entry_name);
+   evas_object_show(entry_name);
+   evas_object_smart_callback_add(entry_name, "changed",
+                                  _edi_settings_project_name_cb, NULL);
+
+   hbox = elm_box_add(parent);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, hbox);
+   evas_object_show(hbox);
+
+   label = elm_label_add(hbox);
+   elm_object_text_set(label, "Author E-mail: ");
+   evas_object_size_hint_weight_set(label, 0.0, 0.0);
+   evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, label);
+   evas_object_show(label);
+
+   entry_email = elm_entry_add(hbox);
+   elm_object_text_set(entry_email, _edi_project_config->user_email);
+   evas_object_size_hint_weight_set(entry_email, 0.75, 0.0);
+   evas_object_size_hint_align_set(entry_email, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, entry_email);
+   evas_object_show(entry_email);
+   evas_object_smart_callback_add(entry_email, "changed",
+                                  _edi_settings_project_email_cb, NULL);
+
+   hbox = elm_box_add(parent);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(box, hbox);
+   evas_object_show(hbox);
+
+   text = eina_strbuf_new();
+   if (edi_scm_enabled())
+     {
+        engine = edi_scm_engine_get();
+        eina_strbuf_append_printf(text, "Remote URL (%s):", engine->name);
+     }
+   else
+     eina_strbuf_append(text, "Remote URL:");
+
+   label = elm_label_add(hbox);
+   elm_object_text_set(label, eina_strbuf_string_get(text));
+   evas_object_size_hint_weight_set(label, 0.0, 0.0);
+   evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, label);
+   evas_object_show(label);
+
+   entry_remote = elm_entry_add(hbox);
+   if (edi_scm_remote_enabled())
+     elm_object_text_set(entry_remote, engine->remote_url);
+
+   evas_object_size_hint_weight_set(entry_remote, 0.75, 0.0);
+   evas_object_size_hint_align_set(entry_remote, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+   elm_box_pack_end(hbox, entry_remote);
+   evas_object_show(entry_remote);
+   evas_object_smart_callback_add(entry_remote, "changed",
+                                  _edi_settings_project_remote_cb, NULL);
+
+   eina_strbuf_free(text);
+
+   return frame;
+}
+
+static void
 _edi_settings_behaviour_autosave_cb(void *data EINA_UNUSED, Evas_Object *obj,
                                     void *event EINA_UNUSED)
 {
@@ -452,6 +598,9 @@ edi_settings_show(Evas_Object *mainwin)
    evas_object_size_hint_align_set(naviframe, EVAS_HINT_FILL, EVAS_HINT_FILL);
    elm_table_pack(table, naviframe, 1, 0, 4, 5);
 
+   _edi_settings_project = elm_naviframe_item_push(naviframe, "", NULL, NULL,
+                                                  
_edi_settings_project_create(naviframe), NULL);
+   elm_naviframe_item_title_enabled_set(_edi_settings_project, EINA_FALSE, 
EINA_FALSE);
    _edi_settings_display = elm_naviframe_item_push(naviframe, "", NULL, NULL,
                                                    
_edi_settings_display_create(naviframe), NULL);
    elm_naviframe_item_title_enabled_set(_edi_settings_display, EINA_FALSE, 
EINA_FALSE);
@@ -462,7 +611,8 @@ edi_settings_show(Evas_Object *mainwin)
                                                    
_edi_settings_behaviour_create(naviframe), NULL);
    elm_naviframe_item_title_enabled_set(_edi_settings_behaviour, EINA_FALSE, 
EINA_FALSE);
 
-   elm_toolbar_item_append(tb, NULL, "Project", NULL, NULL);
+
+   elm_toolbar_item_append(tb, "applications-development", 
"Project",_edi_settings_category_cb, _edi_settings_project);
    default_it = elm_toolbar_item_append(tb, "preferences-desktop", "Display",
                                         _edi_settings_category_cb, 
_edi_settings_display);
    elm_toolbar_item_append(tb, "system-run", "Builds",
@@ -470,7 +620,7 @@ edi_settings_show(Evas_Object *mainwin)
 
    tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL);
    elm_toolbar_item_separator_set(tb_it, EINA_TRUE);
-   elm_toolbar_item_append(tb, NULL, "Global", NULL, NULL);
+   elm_toolbar_item_append(tb, "application-internet", "Global", NULL, NULL);
    elm_toolbar_item_append(tb, "preferences-other", "Behaviour",
                            _edi_settings_category_cb, _edi_settings_behaviour);
    elm_toolbar_item_selected_set(default_it, EINA_TRUE);
diff --git a/src/lib/Edi.h b/src/lib/Edi.h
index 04772a7..f95964e 100644
--- a/src/lib/Edi.h
+++ b/src/lib/Edi.h
@@ -38,6 +38,7 @@ extern "C" {
 #include <edi_builder.h>
 #include <edi_path.h>
 #include <edi_exe.h>
+#include <edi_scm.h>
 
 /**
  * @file
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index a4a011c..e065388 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -17,6 +17,7 @@ edi_builder.h \
 edi_create.h \
 edi_path.h \
 edi_exe.h \
+edi_scm.h \
 Edi.h
 includesdir = $(includedir)/edi-@VMAJ@
 
@@ -29,6 +30,7 @@ edi_build_provider.c \
 edi_builder.c \
 edi_create.c \
 edi_path.c \
+edi_scm.c \
 edi_exe.c \
 edi.c
 libedi_la_LIBADD = @EFL_LIBS@ -lm
diff --git a/src/lib/edi_create.c b/src/lib/edi_create.c
index 7ee9c3a..f389db6 100644
--- a/src/lib/edi_create.c
+++ b/src/lib/edi_create.c
@@ -150,6 +150,7 @@ _edi_create_filter_file_done(void *data, int type 
EINA_UNUSED, void *event EINA_
 {
    Edi_Create *create;
    Ecore_Event_Handler *handler;
+   Eina_Strbuf *command;
 
    create = (Edi_Create *)data;
 
@@ -162,7 +163,22 @@ _edi_create_filter_file_done(void *data, int type 
EINA_UNUSED, void *event EINA_
    create->handler = handler;
 
    chdir(create->path);
-   ecore_exe_run("sh -c 'git init && git add .'", data);
+
+   command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "sh -c 'git init && git add .");
+
+   if (create->user && strlen(create->user))
+     eina_strbuf_append_printf(command, " && git config user.name \"%s\"", 
create->user);
+
+   if (create->email && strlen(create->email))
+     eina_strbuf_append_printf(command, " && git config user.email \"%s\"", 
create->email);
+
+   eina_strbuf_append(command, " ' ");
+
+   ecore_exe_run(eina_strbuf_string_get(command), data);
+
+   eina_strbuf_free(command);
 
    return ECORE_CALLBACK_PASS_ON;
 }
diff --git a/src/lib/edi_exe.c b/src/lib/edi_exe.c
index 71c9bc4..50bb800 100644
--- a/src/lib/edi_exe.c
+++ b/src/lib/edi_exe.c
@@ -29,7 +29,25 @@ edi_exe_wait(const char *command)
    ecore_thread_main_loop_begin();
    ecore_exe_free(exe);
    ecore_thread_main_loop_end();
-
    return exit;
 }
 
+EAPI char *
+edi_exe_response(const char *command)
+{
+   FILE *p;
+   char buf[8192];
+
+   p = popen(command, "r");
+   if (!p)
+     return NULL;
+
+   buf[0] = '\0';
+   fgets(buf, sizeof(buf), p);
+
+   pclose(p);
+
+   if (strlen(buf) <= 1) return NULL;
+
+   return strndup(buf, strlen(buf) - 1);
+}
diff --git a/src/lib/edi_exe.h b/src/lib/edi_exe.h
index ae0bbe4..ab665e0 100644
--- a/src/lib/edi_exe.h
+++ b/src/lib/edi_exe.h
@@ -31,6 +31,16 @@ extern "C" {
 EAPI int edi_exe_wait(const char *command);
 
 /**
+ * Run an executable command and return command string.
+ *
+ * @param command The command to execute in a child process.
+ * @return The output string of the command.
+ *
+ * @ingroup Exe
+ */
+EAPI char *edi_exe_response(const char *command);
+
+/**
  * @}
  */
 
diff --git a/src/lib/edi_scm.c b/src/lib/edi_scm.c
new file mode 100644
index 0000000..655605b
--- /dev/null
+++ b/src/lib/edi_scm.c
@@ -0,0 +1,543 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_File.h>
+
+#include "Edi.h"
+#include "edi_private.h"
+#include <edi_exe.h>
+#include "edi_path.h"
+#include "edi_scm.h"
+
+Edi_Scm_Engine *_edi_scm_global_object = NULL;
+
+static int
+_edi_scm_exec(const char *command)
+{
+   int code;
+   char *oldpwd;
+   Edi_Scm_Engine *self = _edi_scm_global_object;
+
+   if (!self) return -1;
+
+   oldpwd = getcwd(NULL, PATH_MAX);
+
+   chdir(edi_project_get());
+   code = edi_exe_wait(command);
+   chdir(oldpwd);
+
+   free(oldpwd);
+
+   return code;
+}
+
+static char *
+_edi_scm_exec_response(const char *command)
+{
+   char *oldpwd, *response;
+   Edi_Scm_Engine *self = _edi_scm_global_object;
+
+   if (!self) return NULL;
+
+   oldpwd = getcwd(NULL, PATH_MAX);
+
+   chdir(edi_project_get());
+   response = edi_exe_response(command);
+   chdir(oldpwd);
+
+   free(oldpwd);
+
+   return response;
+}
+
+EAPI int
+edi_scm_git_new(void)
+{
+   return _edi_scm_exec("git init .");
+}
+
+static int
+_edi_scm_git_file_add(const char *path)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git add '%s'", path);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_file_mod(const char *path)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git mod '%s'", path);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_file_move(const char *source, const char *dest)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git mv %s %s", source, dest);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_file_del(const char *path)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git rm '%s'", path);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_status(void)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "git status");
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_commit(const char *message)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git commit -m '%s'", message);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_push(void)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "git push");
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+   if (code != 0)
+     {
+        eina_strbuf_reset(command);
+        eina_strbuf_append(command, "git push --set-upstream origin master");
+        code = _edi_scm_exec(eina_strbuf_string_get(command));
+     }
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_pull(void)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "git pull");
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_stash(void)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "git stash");
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static int
+_edi_scm_git_remote_add(const char *remote_url)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append(command, "git remote rm origin");
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_reset(command);
+
+   eina_strbuf_append_printf(command, "git remote add origin %s", remote_url);
+
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static const char *
+_edi_scm_git_remote_name_get(void)
+{
+   char *fullname;
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+
+   if (!engine)
+     return NULL;
+
+   if (!engine->remote_name)
+     {
+        fullname = _edi_scm_exec_response("git config --get user.name");
+        if (fullname)
+          {
+             engine->remote_name = eina_stringshare_add(fullname);
+             free(fullname);
+          }
+     }
+
+   return engine->remote_name;
+}
+
+static const char *
+_edi_scm_git_remote_email_get(void)
+{
+   char *email;
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+
+   if (!engine)
+     return NULL;
+
+   if (!engine->remote_email)
+     {
+        email = _edi_scm_exec_response("git config --get user.email");
+        if (email)
+          {
+             engine->remote_email = eina_stringshare_add(email);
+             free(email);
+          }
+     }
+
+   return engine->remote_email;
+}
+
+static const char *
+_edi_scm_git_remote_url_get(void)
+{
+   char *remote;
+   Eina_Strbuf *command;
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+
+   if (!engine)
+     return NULL;
+
+   if (!engine->remote_url)
+     {
+        remote = _edi_scm_exec_response("git remote");
+        if (remote)
+          {
+             command = eina_strbuf_new();
+             eina_strbuf_append_printf(command, "git remote get-url %s", 
remote);
+             engine->remote_url = 
eina_stringshare_add(_edi_scm_exec_response(eina_strbuf_string_get(command)));
+             eina_strbuf_free(command);
+             free(remote);
+          }
+     }
+
+   return engine->remote_url;
+}
+
+static int
+_edi_scm_credits(const char *name, const char *email)
+{
+   int code;
+   Eina_Strbuf *command = eina_strbuf_new();
+
+   eina_strbuf_append_printf(command, "git config user.name '%s'", name);
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+   eina_strbuf_reset(command);
+   eina_strbuf_append_printf(command, "git config user.email '%s'", email);
+   code = _edi_scm_exec(eina_strbuf_string_get(command));
+
+   eina_strbuf_free(command);
+
+   return code;
+}
+
+static Eina_Bool
+_edi_scm_enabled(Edi_Scm_Engine *engine)
+{
+   char *path;
+   if (!engine) return EINA_FALSE;
+
+   if (!engine->path)
+     {
+        path = edi_path_append(edi_project_get(), engine->directory);
+        engine->path = eina_stringshare_add(path);
+        free(path);
+     }
+
+   return ecore_file_exists(engine->path);
+}
+
+EAPI Eina_Bool
+edi_scm_remote_enabled(void)
+{
+   Edi_Scm_Engine *e = _edi_scm_global_object;
+   if (!e)
+     return EINA_FALSE;
+
+   return !!e->_remote_url_get();
+}
+
+EAPI Eina_Bool
+edi_scm_enabled(void)
+{
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+   if (!engine)
+     return EINA_FALSE;
+
+   return _edi_scm_enabled(engine);
+}
+
+EAPI Edi_Scm_Engine *
+edi_scm_engine_get(void)
+{
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+   if (!engine)
+     return NULL;
+
+   return engine;
+}
+
+EAPI void
+edi_scm_shutdown()
+{
+   Edi_Scm_Engine *engine = _edi_scm_global_object;
+
+   if (!engine)
+     return;
+
+   eina_stringshare_del(engine->name);
+   eina_stringshare_del(engine->directory);
+   eina_stringshare_del(engine->path);
+   eina_stringshare_del(engine->remote_url);
+   free(engine);
+
+   _edi_scm_global_object = NULL;
+}
+
+EAPI int
+edi_scm_add(const char *path)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   return e->file_add(path);
+}
+
+EAPI int
+edi_scm_del(const char *path)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   return e->file_del(path);
+}
+
+EAPI int
+edi_scm_move(const char *src, const char *dest)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   return e->move(src, dest);
+}
+
+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);
+}
+
+static void
+_edi_scm_status_thread_cb(void *data, Ecore_Thread *thread)
+{
+   Edi_Scm_Engine *e = data;
+
+   e->status();
+
+   ecore_thread_cancel(thread);
+}
+
+EAPI void
+edi_scm_status(void)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   ecore_thread_run(_edi_scm_status_thread_cb, NULL, NULL, e);
+}
+
+EAPI int
+edi_scm_remote_add(const char *remote_url)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   return e->remote_add(remote_url);
+}
+
+static void
+_edi_scm_stash_thread_cb(void *data, Ecore_Thread *thread)
+{
+   Edi_Scm_Engine *e = data;
+
+   e->stash();
+
+   ecore_thread_cancel(thread);
+}
+
+EAPI void
+edi_scm_stash(void)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   ecore_thread_run(_edi_scm_stash_thread_cb, NULL, NULL, e);
+}
+
+EAPI int
+edi_scm_credits(const char *user, const char *email)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   return e->credits(user, email);
+}
+
+static void
+_edi_scm_pull_thread_cb(void *data, Ecore_Thread *thread)
+{
+   Edi_Scm_Engine *e = data;
+
+   e->pull();
+
+   ecore_thread_cancel(thread);
+}
+
+EAPI void
+edi_scm_pull(void)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   ecore_thread_run(_edi_scm_pull_thread_cb, NULL, NULL, e);
+}
+
+static void
+_edi_scm_push_thread_cb(void *data, Ecore_Thread *thread)
+{
+   Edi_Scm_Engine *e = data;
+
+   e->push();
+
+   ecore_thread_cancel(thread);
+}
+
+EAPI void
+edi_scm_push(void)
+{
+   Edi_Scm_Engine *e = edi_scm_engine_get();
+
+   ecore_thread_run(_edi_scm_push_thread_cb, NULL, NULL, e);
+}
+
+static Edi_Scm_Engine *
+_edi_scm_git_init()
+{
+   Edi_Scm_Engine *engine;
+
+   if (!ecore_file_app_installed("git"))
+     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->credits    = _edi_scm_credits;
+   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;
+
+   return engine;
+}
+
+EAPI Edi_Scm_Engine *
+edi_scm_init(void)
+{
+   if (edi_project_file_exists(".git"))
+     return _edi_scm_git_init();
+
+   return NULL;
+}
+
diff --git a/src/lib/edi_scm.h b/src/lib/edi_scm.h
new file mode 100644
index 0000000..64e4a73
--- /dev/null
+++ b/src/lib/edi_scm.h
@@ -0,0 +1,213 @@
+#ifndef EDI_SCM_H_
+# define EDI_SCM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ * @brief These routines are used for Edi SCM management.
+ */
+
+typedef int (scm_fn_add)(const char *path);
+typedef int (scm_fn_mod)(const char *path);
+typedef int (scm_fn_del)(const char *path);
+typedef int (scm_fn_credits)(const char *name, const char *email);
+typedef int (scm_fn_move)(const char *src, const char *dest);
+typedef int (scm_fn_commit)(const char *message);
+typedef int (scm_fn_remote_add)(const char *remote_url);
+typedef int (scm_fn_status)(void);
+typedef int (scm_fn_push)(void);
+typedef int (scm_fn_pull)(void);
+typedef int (scm_fn_stash)(void);
+
+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 struct _Edi_Scm_Engine
+{
+   const char     *name;
+   const char     *directory;
+   const char     *path;
+
+   scm_fn_remote_add *remote_add;
+   const char        *remote_url;
+   const char        *remote_name;
+   const char        *remote_email;
+
+   scm_fn_credits *credits;
+   scm_fn_add     *file_add;
+   scm_fn_mod     *file_mod;
+   scm_fn_del     *file_del;
+   scm_fn_move    *move;
+   scm_fn_commit  *commit;
+   scm_fn_status  *status;
+   scm_fn_push    *push;
+   scm_fn_pull    *pull;
+   scm_fn_stash   *stash;
+
+   scm_fn_remote_name  *_remote_name_get;
+   scm_fn_remote_email *_remote_email_get;
+   scm_fn_remote_url   *_remote_url_get;
+} Edi_Scm_Engine;
+
+/**
+ * @brief Executable helpers
+ * @defgroup Scm
+ *
+ * @{
+ *
+ * Functions of source code management.
+ *
+ */
+
+/**
+ * Init the SCM system for the current project.
+ *
+ * @ingroup Scm
+ */
+Edi_Scm_Engine *edi_scm_init();
+
+/**
+ * Shutdown and free memory in use by SCM system.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_shutdown();
+
+/**
+ * Set up a new git repository for the current project.
+ *
+ * @ingroup Scm
+ */
+EAPI int edi_scm_git_new(void);
+
+/**
+ * Get a pointer to the SCM engine in use.
+ *
+ * @return The pointer to the engine or NULL.
+ *
+ * @ingroup Scm
+ */
+Edi_Scm_Engine *edi_scm_engine_get(void);
+
+/**
+ * Add file to be monitored by SCM.
+ *
+ * @param path The file path.
+ * @return The status code of command executed.
+ *
+ * @ingroup Scm
+ */
+int edi_scm_add(const char *path);
+
+/**
+ * Del file from those monitored by SCM.
+ *
+ * @param path The file path.
+ * @return The status code of command executed.
+ *
+ * @ingroup Scm
+ */
+int edi_scm_del(const char *path);
+
+/**
+ * Set commit message for next commit to SCM.
+ *
+ * @param message The commit mesage to send.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_commit(const char *message);
+
+/**
+ * Get status of repository.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_status(void);
+
+/**
+ * Move from src to dest.
+ *
+ * @param src The source file,
+ * @param dest The destination.
+ *
+ * @return The status code of command executed.
+ * @ingroup Scm
+ */
+int edi_scm_move(const char *src, const char *dest);
+
+/**
+ * Set user credentials for the SCM system.
+ *
+ * @param user The name of the user.
+ * @param email The email of the user.
+ *
+ * @return The status code of command executed.
+ *
+ * @ingroup Scm
+ */
+int edi_scm_credits(const char *user, const char *email);
+
+/**
+ * Push to SCM remote repository.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_push(void);
+
+/**
+ * Pull from SCM remote repository.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_pull(void);
+
+/**
+ * Stash local changes.
+ *
+ * @ingroup Scm
+ */
+void edi_scm_stash(void);
+
+/**
+ * Set remote url for SCM.
+ *
+ * @param message The remote_url to add.
+ *
+ * @return The status code of command executed.
+ *
+ * @ingroup Scm
+ */
+int edi_scm_remote_add(const char *remote_url);
+
+/**
+ * Test whether SCM is enabled for this project.
+ *
+ * @return Whether SCM is enabled or not (true/false);
+ *
+ * @ingroup Scm
+ */
+Eina_Bool edi_scm_enabled(void);
+
+/**
+ * Test whether SCM has a remote enabled for this project.
+ *
+ * @return Whether SCM is remote enabled or not (true/false);
+ *
+ * @ingroup Scm
+ */
+Eina_Bool edi_scm_remote_enabled(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EDI_SCM_H_ */

-- 


Reply via email to