edi_scm: Add support for staging and unstaging.

Also refactor some of the API to be less clashy.
This commit is contained in:
Al Poole 2017-12-20 21:47:21 +00:00
parent cf5a1c9bdc
commit 817c291bce
4 changed files with 210 additions and 15 deletions

View File

@ -140,6 +140,30 @@ _file_status_item_add(const char *path, Edi_Scm_Status_Code status)
eina_hash_add(_list_statuses, path, code);
}
typedef enum {
EDI_FILE_STATUS_UNMODIFIED,
EDI_FILE_STATUS_STAGED,
EDI_FILE_STATUS_UNSTAGED,
} Edi_File_Status;
static Edi_File_Status
_edi_filepanel_file_scm_status(const char *path)
{
Edi_Scm_Status_Code *code;
char *escaped = ecore_file_escape_name(path);
code = _file_status_item_find(escaped);
free(escaped);
if (!code) return EDI_FILE_STATUS_UNMODIFIED;
if (*code == EDI_SCM_STATUS_RENAMED_STAGED || *code == EDI_SCM_STATUS_DELETED_STAGED ||
*code == EDI_SCM_STATUS_ADDED_STAGED || *code == EDI_SCM_STATUS_MODIFIED_STAGED)
return EDI_FILE_STATUS_STAGED;
return EDI_FILE_STATUS_UNSTAGED;
}
void edi_filepanel_item_update(const char *path)
{
Elm_Object_Item *item = _file_listing_item_find(path);
@ -349,14 +373,25 @@ _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,
_item_menu_scm_stage_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Edi_Dir_Data *sd;
sd = data;
edi_scm_add(sd->path);
edi_scm_stage(sd->path);
edi_filepanel_scm_status_update();
edi_filepanel_item_update(sd->path);
}
static void
_item_menu_scm_unstage_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Edi_Dir_Data *sd = data;
edi_scm_unstage(sd->path);
edi_filepanel_scm_status_update();
edi_filepanel_item_update(sd->path);
}
@ -415,7 +450,8 @@ _item_menu_filetype_create(Evas_Object *menu, Elm_Object_Item *parent, const cha
static void
_item_menu_create(Evas_Object *win, Edi_Dir_Data *sd)
{
Elm_Object_Item *menu_it;
Elm_Object_Item *menu_it, *menu_it2;
Edi_File_Status status;
menu = elm_menu_add(win);
evas_object_smart_callback_add(menu, "dismissed", _item_menu_dismissed_cb, NULL);
@ -436,12 +472,23 @@ _item_menu_create(Evas_Object *win, Edi_Dir_Data *sd)
menu_it = elm_menu_item_add(menu, NULL, "gtk-execute", _("Open External"),
_item_menu_xdgopen_cb, sd);
elm_menu_item_separator_add(menu, NULL);
if (edi_scm_enabled())
{
status = _edi_filepanel_file_scm_status(sd->path);
menu_it = elm_menu_item_add(menu, NULL, NULL, eina_slstr_printf("%s...", _("Source Control")), NULL, NULL);
elm_menu_item_add(menu, menu_it, "document-save-as", _("Add Changes"), _item_menu_scm_add_cb, sd);
menu_it2 = elm_menu_item_add(menu, menu_it, "document-save-as", _("Stage Changes"), _item_menu_scm_stage_cb, sd);
if (status == EDI_FILE_STATUS_UNMODIFIED || status == EDI_FILE_STATUS_STAGED)
elm_object_item_disabled_set(menu_it2, EINA_TRUE);
menu_it2 = elm_menu_item_add(menu, menu_it, "edit-undo", _("Unstage Changes"), _item_menu_scm_unstage_cb, sd);
if (status == EDI_FILE_STATUS_UNMODIFIED || status == EDI_FILE_STATUS_UNSTAGED)
elm_object_item_disabled_set(menu_it2, EINA_TRUE);
elm_menu_item_separator_add(menu, menu_it);
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);
}

View File

@ -547,6 +547,108 @@ _edi_scm_ui_workdir_get(void)
return workdir;
}
static void
_item_menu_dismissed_cb(void *data EINA_UNUSED, Evas_Object *obj,
void *ev EINA_UNUSED)
{
evas_object_del(obj);
}
static void
_item_menu_scm_stage_cb(void *data, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
Edi_Scm_Status *status;
Edi_Scm_Ui *edi_scm = evas_object_data_get(obj, "edi_scm_ui");
status = data;
edi_scm_stage(status->path);
_edi_scm_ui_refresh(edi_scm);
}
static void
_item_menu_scm_unstage_cb(void *data, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
Edi_Scm_Status *status;
Edi_Scm_Ui *edi_scm = evas_object_data_get(obj, "edi_scm_ui");
status = data;
edi_scm_unstage(status->path);
_edi_scm_ui_refresh(edi_scm);
}
static void
_item_menu_scm_staged_toggle(Edi_Scm_Status *status, Edi_Scm_Ui *edi_scm)
{
if (status->staged)
edi_scm_unstage(status->path);
else
edi_scm_stage(status->path);
_edi_scm_ui_refresh(edi_scm);
}
static Evas_Object *
_item_menu_create(Edi_Scm_Ui *edi_scm, Edi_Scm_Status *status)
{
Evas_Object *menu, *parent;
Elm_Object_Item *menu_it;
parent = edi_scm->parent;
menu = elm_menu_add(parent);
evas_object_data_set(menu, "edi_scm_ui", edi_scm);
evas_object_smart_callback_add(menu, "dismissed", _item_menu_dismissed_cb, NULL);
menu_it = elm_menu_item_add(menu, NULL, "document-properties", basename((char *)status->path), NULL, NULL);
elm_object_item_disabled_set(menu_it, EINA_TRUE);
elm_menu_item_separator_add(menu, NULL);
menu_it = elm_menu_item_add(menu, NULL, "document-save-as", _("Stage Changes"), _item_menu_scm_stage_cb, status);
if (status->staged)
elm_object_item_disabled_set(menu_it, EINA_TRUE);
menu_it = elm_menu_item_add(menu, NULL, "edit-undo", _("Unstage Changes"), _item_menu_scm_unstage_cb, status);
if (!status->staged)
elm_object_item_disabled_set(menu_it, EINA_TRUE);
return menu;
}
static void
_list_item_clicked_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
void *event_info)
{
Evas_Object *menu;
Evas_Event_Mouse_Up *ev;
Elm_Object_Item *it;
Edi_Scm_Status *status;
Edi_Scm_Ui *edi_scm = data;
ev = event_info;
it = elm_genlist_at_xy_item_get(obj, ev->output.x, ev->output.y, NULL);
status = elm_object_item_data_get(it);
if (!status)
return;
if (ev->button != 3)
{
if (ev->button == 1 && ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
_item_menu_scm_staged_toggle(status, edi_scm);
return;
}
menu = _item_menu_create(edi_scm, status);
elm_menu_move(menu, ev->canvas.x, ev->canvas.y);
evas_object_show(menu);
}
void
edi_scm_ui_add(Evas_Object *parent)
{
@ -568,6 +670,7 @@ edi_scm_ui_add(Evas_Object *parent)
edi_scm->workdir = engine->workdir;
edi_scm->monitor = eio_monitor_add(edi_scm->workdir);
edi_scm->parent = parent;
edi_scm->results_max = isatty(fileno(stdin));
ecore_event_handler_add(EIO_MONITOR_FILE_CREATED, _edi_scm_ui_file_changes_cb, edi_scm);
ecore_event_handler_add(EIO_MONITOR_FILE_MODIFIED, _edi_scm_ui_file_changes_cb, edi_scm);
@ -642,7 +745,7 @@ edi_scm_ui_add(Evas_Object *parent)
edi_scm->check = check = elm_check_add(parent);
elm_object_text_set(check, _("Show unstaged changes"));
elm_check_state_set(check, EINA_FALSE);
elm_check_state_set(check, edi_scm->results_max);
evas_object_show(check);
evas_object_smart_callback_add(check, "changed",
_edi_scm_ui_refresh_cb, edi_scm);
@ -659,12 +762,13 @@ edi_scm_ui_add(Evas_Object *parent)
edi_scm->list = list = elm_genlist_add(box);
elm_genlist_mode_set(list, ELM_LIST_SCROLL);
elm_list_select_mode_set(list, ELM_OBJECT_SELECT_MODE_NONE);
elm_genlist_select_mode_set(list, ELM_OBJECT_SELECT_MODE_NONE);
elm_scroller_bounce_set(list, EINA_TRUE, EINA_TRUE);
elm_scroller_policy_set(list, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
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);
evas_object_show(list);
evas_object_event_callback_add(list, EVAS_CALLBACK_MOUSE_UP, _list_item_clicked_cb, edi_scm);
table = elm_table_add(parent);
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);

View File

@ -86,7 +86,7 @@ edi_scm_git_clone(const char *url, const char *dir)
}
static int
_edi_scm_git_file_add(const char *path)
_edi_scm_git_file_stage(const char *path)
{
int code;
Eina_Strbuf *command = eina_strbuf_new();
@ -100,6 +100,21 @@ _edi_scm_git_file_add(const char *path)
return code;
}
static int
_edi_scm_git_file_unstage(const char *path)
{
int code;
Eina_Strbuf *command = eina_strbuf_new();
eina_strbuf_append_printf(command, "git reset HEAD %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)
{
@ -539,7 +554,7 @@ edi_scm_shutdown()
}
EAPI int
edi_scm_add(const char *path)
edi_scm_stage(const char *path)
{
char *escaped;
int result;
@ -547,7 +562,7 @@ edi_scm_add(const char *path)
escaped = ecore_file_escape_name(path);
result = e->file_add(escaped);
result = e->file_stage(escaped);
free(escaped);
@ -570,6 +585,22 @@ edi_scm_del(const char *path)
return result;
}
EAPI int
edi_scm_unstage(const char *path)
{
char *escaped;
int result;
Edi_Scm_Engine *e = edi_scm_engine_get();
escaped = ecore_file_escape_name(path);
result = e->file_unstage(escaped);
free(escaped);
return result;
}
EAPI int
edi_scm_move(const char *src, const char *dest)
{
@ -722,9 +753,10 @@ _edi_scm_git_init()
_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_stage = _edi_scm_git_file_stage;
engine->file_mod = _edi_scm_git_file_mod;
engine->file_del = _edi_scm_git_file_del;
engine->file_unstage = _edi_scm_git_file_unstage;
engine->move = _edi_scm_git_file_move;
engine->status = _edi_scm_git_status;
engine->diff = _edi_scm_git_diff;

View File

@ -33,7 +33,8 @@ typedef struct _Edi_Scm_Status
Eina_Bool staged;
} Edi_Scm_Status;
typedef int (scm_fn_add)(const char *path);
typedef int (scm_fn_stage)(const char *path);
typedef int (scm_fn_unstage)(const char *path);
typedef int (scm_fn_mod)(const char *path);
typedef int (scm_fn_del)(const char *path);
typedef int (scm_fn_move)(const char *src, const char *dest);
@ -60,7 +61,8 @@ typedef struct _Edi_Scm_Engine
char *workdir;
Eina_List *statuses;
scm_fn_add *file_add;
scm_fn_stage *file_stage;
scm_fn_unstage *file_unstage;
scm_fn_mod *file_mod;
scm_fn_del *file_del;
scm_fn_move *move;
@ -142,14 +144,24 @@ EAPI int edi_scm_git_clone(const char *url, const char *dir);
Edi_Scm_Engine *edi_scm_engine_get(void);
/**
* Add file to be monitored by SCM.
* Stage file for commit with SCM.
*
* @param path The file path.
* @return The status code of command executed.
*
* @ingroup Scm
*/
int edi_scm_add(const char *path);
int edi_scm_stage(const char *path);
/**
* Unstage file from commit.
*
* @param path The file path.
* @return The status code of command executed.
*
* @ingroup Scm
*/
int edi_scm_unstage(const char *path);
/**
* Del file from those monitored by SCM.