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
This commit is contained in:
Al Poole 2017-06-17 12:59:10 +01:00 committed by Andy Williams
parent 863b3d7ab3
commit a232dccaba
4 changed files with 269 additions and 23 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.
*