From 72bc8371afa34a28e4c59c7bbce98ebd9406e1bf Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sun, 5 Jul 2009 16:53:43 +0200 Subject: [PATCH] Implemented stash actions (remove, apply) --- gitg/gitg-branch-actions.c | 186 ++++++++++++++++++++++- gitg/gitg-branch-actions.h | 1 + gitg/gitg-dnd.c | 12 +- gitg/gitg-label-renderer.c | 5 + gitg/gitg-menus.xml | 8 + gitg/gitg-ref.c | 13 +- gitg/gitg-ref.h | 3 +- gitg/gitg-repository.c | 73 +++++---- gitg/gitg-window.c | 298 ++++++++++++++++++++++++------------- 9 files changed, 455 insertions(+), 144 deletions(-) diff --git a/gitg/gitg-branch-actions.c b/gitg/gitg-branch-actions.c index 0a13e94d..cbf0ae9c 100644 --- a/gitg/gitg-branch-actions.c +++ b/gitg/gitg-branch-actions.c @@ -342,6 +342,109 @@ remove_remote_branch (GitgWindow *window, return ret; } +static gchar * +get_stash_refspec (GitgRepository *repository, GitgRef *stash) +{ + gchar **out; + + out = gitg_repository_command_with_outputv (repository, + NULL, + "log", + "--no-color", + "--pretty=oneline", + "-g", + "refs/stash", + NULL); + + gchar **ptr = out; + gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (stash)); + gchar *ret = NULL; + + while (ptr && *ptr) + { + if (g_str_has_prefix (*ptr, sha1)) + { + gchar *start = *ptr + HASH_SHA_SIZE + 1; + gchar *end = strchr (start, ':'); + + if (end) + { + ret = g_strndup (start, end - start); + } + break; + } + } + + g_strfreev (out); + g_free (sha1); + + return ret; +} + +static GitgRunner * +remove_stash (GitgWindow *window, GitgRef *ref) +{ + gint r = message_dialog (window, + GTK_MESSAGE_QUESTION, + _("Are you sure you want to remove this stash item?"), + _("This permanently removes the stash item"), + _("Remove stash")); + + if (r != GTK_RESPONSE_ACCEPT) + { + return NULL; + } + + GitgRepository *repository = gitg_window_get_repository (window); + gchar *spec = get_stash_refspec (repository, ref); + + if (!spec) + { + return NULL; + } + + if (!gitg_repository_commandv (repository, + NULL, + "reflog", + "delete", + "--updateref", + "--rewrite", + spec, + NULL)) + { + message_dialog (window, + GTK_MESSAGE_ERROR, + _("Failed to remove stash"), + _("The stash item could not be successfully removed"), + NULL); + } + else + { + if (!gitg_repository_commandv (repository, + NULL, + "rev-parse", + "--verify", + "refs/stash@{0}", + NULL)) + { + gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (ref)); + gitg_repository_commandv (repository, + NULL, + "update-ref", + "-d", + "refs/stash", + sha1, + NULL); + g_free (sha1); + } + + gitg_repository_reload (repository); + } + + g_free (spec); + return NULL; +} + GitgRunner * gitg_branch_actions_remove (GitgWindow *window, GitgRef *ref) @@ -360,6 +463,8 @@ gitg_branch_actions_remove (GitgWindow *window, case GITG_REF_TYPE_REMOTE: ret = remove_remote_branch (window, cp); break; + case GITG_REF_TYPE_STASH: + ret = remove_stash (window, cp); default: break; } @@ -588,7 +693,11 @@ stash_changes (GitgWindow *window, gchar **ref, gboolean storeref) { if (no_changes (gitg_window_get_repository (window))) { - *ref = NULL; + if (ref) + { + *ref = NULL; + } + return TRUE; } @@ -1126,11 +1235,80 @@ gitg_branch_actions_push_remote (GitgWindow *window, gboolean gitg_branch_actions_apply_stash (GitgWindow *window, - GitgRef *stash) + GitgRef *stash, + GitgRef *branch) { g_return_val_if_fail (GITG_IS_WINDOW (window), FALSE); - g_return_val_if_fail (stash != NULL, FALSE); + g_return_val_if_fail (gitg_ref_get_ref_type (stash) == GITG_REF_TYPE_STASH, FALSE); + g_return_val_if_fail (gitg_ref_get_ref_type (branch) == GITG_REF_TYPE_BRANCH, FALSE); - return FALSE; + gchar *message = g_strdup_printf (_("Are you sure you want to apply the stash item to local branch <%s>?"), + gitg_ref_get_shortname (branch)); + + if (message_dialog (window, + GTK_MESSAGE_QUESTION, + _("Apply stash"), + message, + _("Apply stash")) != GTK_RESPONSE_ACCEPT) + { + g_free (message); + return FALSE; + } + + GitgRepository *repository = gitg_window_get_repository (window); + GitgRef *current = gitg_repository_get_current_working_ref (repository); + + if (!gitg_ref_equal (branch, current)) + { + if (!stash_changes (window, NULL, TRUE)) + { + return FALSE; + } + + if (!checkout_local_branch_real (window, branch)) + { + message_dialog (window, + GTK_MESSAGE_ERROR, + _("Failed to checkout local branch <%s>"), + NULL, + NULL, + gitg_ref_get_shortname (branch)); + return FALSE; + } + } + + gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (stash)); + gboolean ret; + + if (!gitg_repository_commandv (repository, + NULL, + "stash", + "apply", + "--index", + sha1, + NULL)) + { + message = g_strdup_printf (_("The stash could not be applied to local branch <%s>"), + gitg_ref_get_shortname (branch)); + message_dialog (window, + GTK_MESSAGE_ERROR, + _("Failed to apply stash"), + message, + NULL); + g_free (message); + ret = FALSE; + + if (!gitg_ref_equal (current, branch) && no_changes (repository)) + { + checkout_local_branch_real (window, current); + } + } + else + { + ret = TRUE; + gitg_repository_reload (repository); + } + + return ret; } diff --git a/gitg/gitg-branch-actions.h b/gitg/gitg-branch-actions.h index 4cc8cdb6..1cb9d647 100644 --- a/gitg/gitg-branch-actions.h +++ b/gitg/gitg-branch-actions.h @@ -37,6 +37,7 @@ GitgRunner *gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, Git GitgRunner *gitg_branch_actions_push (GitgWindow *window, GitgRef *source, GitgRef *dest); GitgRunner *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote); +gboolean gitg_branch_actions_apply_stash (GitgWindow *window, GitgRef *stash, GitgRef *branch); G_END_DECLS #endif /* __GITG_BRANCH_ACTIONS_H__ */ diff --git a/gitg/gitg-dnd.c b/gitg/gitg-dnd.c index ebd9d819..522cb55b 100644 --- a/gitg/gitg-dnd.c +++ b/gitg/gitg-dnd.c @@ -128,6 +128,7 @@ can_drag (GitgRef *ref) { case GITG_REF_TYPE_BRANCH: case GITG_REF_TYPE_REMOTE: + case GITG_REF_TYPE_STASH: return TRUE; break; default: @@ -155,6 +156,10 @@ can_drop (GitgRef *source, GitgRef *dest) { return dest_type == GITG_REF_TYPE_BRANCH; } + else if (source_type == GITG_REF_TYPE_STASH) + { + return dest_type == GITG_REF_TYPE_BRANCH; + } return FALSE; } @@ -219,11 +224,6 @@ update_highlight (GitgDndData *data, gint x, gint y) NULL, NULL); - if (ref && !can_drag (ref)) - { - ref = NULL; - } - if (ref != data->cursor_ref) { if (data->cursor_ref) @@ -231,7 +231,7 @@ update_highlight (GitgDndData *data, gint x, gint y) gitg_ref_set_state (data->cursor_ref, GITG_REF_STATE_NONE); } - if (ref) + if (ref && gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_NONE) { gitg_ref_set_state (ref, GITG_REF_STATE_PRELIGHT); diff --git a/gitg/gitg-label-renderer.c b/gitg/gitg-label-renderer.c index 9fc86cde..b48ab8ad 100644 --- a/gitg/gitg-label-renderer.c +++ b/gitg/gitg-label-renderer.c @@ -108,6 +108,11 @@ get_type_color (GitgRefType type, gdouble *r, gdouble *g, gdouble *b) *g = 1; *b = 0; break; + case GITG_REF_TYPE_STASH: + *r = 1; + *g = 0.8; + *b = 0.5; + break; default: *r = 1; *g = 1; diff --git a/gitg/gitg-menus.xml b/gitg/gitg-menus.xml index 675d9053..2a154700 100644 --- a/gitg/gitg-menus.xml +++ b/gitg/gitg-menus.xml @@ -63,6 +63,11 @@ Push branch to... + + + Apply stash to... + + @@ -101,6 +106,9 @@ + + + diff --git a/gitg/gitg-ref.c b/gitg/gitg-ref.c index b6201709..c62bf9a0 100644 --- a/gitg/gitg-ref.c +++ b/gitg/gitg-ref.c @@ -68,7 +68,8 @@ gitg_ref_new(gchar const *hash, gchar const *name) PrefixTypeMap map[] = { {"refs/heads/", GITG_REF_TYPE_BRANCH}, {"refs/remotes/", GITG_REF_TYPE_REMOTE}, - {"refs/tags/", GITG_REF_TYPE_TAG} + {"refs/tags/", GITG_REF_TYPE_TAG}, + {"refs/stash", GITG_REF_TYPE_STASH} }; inst->prefix = NULL; @@ -83,7 +84,15 @@ gitg_ref_new(gchar const *hash, gchar const *name) continue; inst->type = map[i].type; - inst->shortname = g_strdup(name + strlen(map[i].prefix)); + + if (inst->type == GITG_REF_TYPE_STASH) + { + inst->shortname = g_strdup("stash"); + } + else + { + inst->shortname = g_strdup(name + strlen(map[i].prefix)); + } if (map[i].type == GITG_REF_TYPE_REMOTE && (pos = strchr(inst->shortname, '/'))) { diff --git a/gitg/gitg-ref.h b/gitg/gitg-ref.h index 8a4da070..a9f19be9 100644 --- a/gitg/gitg-ref.h +++ b/gitg/gitg-ref.h @@ -37,7 +37,8 @@ typedef enum GITG_REF_TYPE_NONE = 0, GITG_REF_TYPE_BRANCH, GITG_REF_TYPE_REMOTE, - GITG_REF_TYPE_TAG + GITG_REF_TYPE_TAG, + GITG_REF_TYPE_STASH } GitgRefType; typedef enum diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c index 91a9e7a3..7e12acc7 100644 --- a/gitg/gitg-repository.c +++ b/gitg/gitg-repository.c @@ -550,6 +550,40 @@ on_loader_end_loading(GitgRunner *object, gboolean cancelled, GitgRepository *re } } +static gint +find_ref_custom (GitgRef *first, GitgRef *second) +{ + return gitg_ref_equal (first, second) ? 0 : 1; +} + +static GitgRef * +add_ref(GitgRepository *self, gchar const *sha1, gchar const *name) +{ + GitgRef *ref = gitg_ref_new(sha1, name); + GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs, + gitg_ref_get_hash(ref)); + + if (refs == NULL) + { + g_hash_table_insert(self->priv->refs, + (gpointer)gitg_ref_get_hash(ref), + g_slist_append(NULL, ref)); + } + else + { + if (!g_slist_find_custom (refs, ref, (GCompareFunc)find_ref_custom)) + { + refs = g_slist_append(refs, ref); + } + else + { + gitg_ref_free (ref); + } + } + + return ref; +} + static void loader_update_stash(GitgRepository *repository, gchar **buffer) { @@ -577,6 +611,8 @@ loader_update_stash(GitgRepository *repository, gchar **buffer) gint64 timestamp = g_ascii_strtoll(components[3], NULL, 0); GitgRevision *rv = gitg_revision_new(components[0], components[1], components[2], NULL, timestamp); + add_ref (repository, components[0], "refs/stash"); + gitg_revision_set_sign(rv, 's'); append_revision(repository, rv); g_strfreev(components); @@ -842,27 +878,6 @@ gitg_repository_get_loader(GitgRepository *self) return GITG_RUNNER(g_object_ref(self->priv->loader)); } -static GitgRef * -add_ref(GitgRepository *self, gchar const *sha1, gchar const *name) -{ - GitgRef *ref = gitg_ref_new(sha1, name); - GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs, - gitg_ref_get_hash(ref)); - - if (refs == NULL) - { - g_hash_table_insert(self->priv->refs, - (gpointer)gitg_ref_get_hash(ref), - g_slist_append(NULL, ref)); - } - else - { - refs = g_slist_append(refs, ref); - } - - return ref; -} - static gboolean has_left_right(gchar const **av, int argc) { @@ -986,18 +1001,14 @@ load_refs(GitgRepository *self) gchar **components = g_strsplit(buf, " ", 3); guint len = g_strv_length(components); - /* Skip refs/stash */ - if (strcmp(components[0], "refs/stash") != 0) + if (len == 2 || len == 3) { - if (len == 2 || len == 3) + gchar const *obj = len == 3 && *components[2] ? components[2] : components[1]; + GitgRef *ref = add_ref(self, obj, components[0]); + + if (current != NULL && strcmp(gitg_ref_get_name(ref), current) == 0) { - gchar const *obj = len == 3 && *components[2] ? components[2] : components[1]; - GitgRef *ref = add_ref(self, obj, components[0]); - - if (current != NULL && strcmp(gitg_ref_get_name(ref), current) == 0) - { - self->priv->current_ref = gitg_ref_copy(ref); - } + self->priv->current_ref = gitg_ref_copy(ref); } } diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c index 602ee11a..8f4d4e5a 100644 --- a/gitg/gitg-window.c +++ b/gitg/gitg-window.c @@ -312,12 +312,9 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT GSList *labels; const gchar *lbl = NULL; + switch (gitg_revision_get_sign(rv)) { - - case 's': - lbl = "stash"; - break; case 't': lbl = "staged"; break; @@ -475,21 +472,35 @@ update_dnd_status (GitgWindow *window, GitgRef *source, GitgRef *dest) else { gchar *message = NULL; + GitgRefType source_type = gitg_ref_get_ref_type (source); + GitgRefType dest_type = gitg_ref_get_ref_type (dest); - if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH && - gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_REMOTE) + if (source_type == GITG_REF_TYPE_BRANCH && + dest_type== GITG_REF_TYPE_REMOTE) { - message = g_strdup_printf (_("Push local branch <%s> to remote branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest)); + message = g_strdup_printf (_("Push local branch <%s> to remote branch <%s>"), + gitg_ref_get_shortname (source), + gitg_ref_get_shortname (dest)); } - else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH && - gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH) + else if (source_type == GITG_REF_TYPE_BRANCH && + dest_type == GITG_REF_TYPE_BRANCH) { - message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on local branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest)); + message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on local branch <%s>"), + gitg_ref_get_shortname (source), + gitg_ref_get_shortname (dest)); } - else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_REMOTE && - gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH) + else if (source_type == GITG_REF_TYPE_REMOTE && + dest_type == GITG_REF_TYPE_BRANCH) { - message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on remote branch <%s>"), gitg_ref_get_shortname (dest), gitg_ref_get_shortname (source)); + message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on remote branch <%s>"), + gitg_ref_get_shortname (dest), + gitg_ref_get_shortname (source)); + } + else if (source_type == GITG_REF_TYPE_STASH && + dest_type == GITG_REF_TYPE_BRANCH) + { + message = g_strdup_printf (_("Apply stash to local branch <%s>"), + gitg_ref_get_shortname (dest)); } if (message) @@ -511,13 +522,22 @@ on_refs_dnd (GitgRef *source, GitgRef *dest, gboolean dropped, GitgWindow *windo } gboolean ret = FALSE; + GitgRefType source_type = gitg_ref_get_ref_type (source); + GitgRefType dest_type = gitg_ref_get_ref_type (dest); - if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH && - gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_REMOTE) + if (source_type == GITG_REF_TYPE_BRANCH && + dest_type == GITG_REF_TYPE_REMOTE) { ret = add_branch_action (window, gitg_branch_actions_push (window, source, dest)); } - else if (gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH) + else if (source_type == GITG_REF_TYPE_STASH) + { + if (dest_type == GITG_REF_TYPE_BRANCH) + { + ret = gitg_branch_actions_apply_stash (window, source, dest); + } + } + else if (dest_type == GITG_REF_TYPE_BRANCH) { GtkWidget *popup = gtk_ui_manager_get_widget (window->priv->menus_ui_manager, "/ui/dnd_popup"); @@ -976,6 +996,33 @@ fill_branches_combo(GitgWindow *window) g_slist_free(refs); } +static void +update_window_title (GitgWindow *window) +{ + if (!window->priv->repository) + { + gtk_window_set_title (GTK_WINDOW (window), _("gitg")); + return; + } + + GitgRef *ref = gitg_repository_get_current_working_ref (window->priv->repository); + gchar *refname = NULL; + + if (ref) + { + refname = g_strconcat (" (", gitg_ref_get_shortname (ref), ")", NULL); + } + + gchar *basename = g_path_get_basename(gitg_repository_get_path(window->priv->repository)); + gchar *title = g_strconcat(_("gitg"), " - ", basename, refname, NULL); + + gtk_window_set_title(GTK_WINDOW(window), title); + + g_free(basename); + g_free(title); + g_free (refname); +} + static void on_repository_load(GitgRepository *repository, GitgWindow *window) { @@ -983,6 +1030,8 @@ on_repository_load(GitgRepository *repository, GitgWindow *window) clear_branches_combo(window); fill_branches_combo(window); g_signal_handlers_unblock_by_func(window->priv->combo_branches, on_branches_combo_changed, window); + + update_window_title (window); } static void @@ -1062,13 +1111,6 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const ** gitg_commit_view_set_repository(window->priv->commit_view, window->priv->repository); gitg_revision_view_set_repository(window->priv->revision_view, window->priv->repository); - gchar *basename = g_path_get_basename(gitg_repository_get_path(window->priv->repository)); - gchar *title = g_strdup_printf("%s - %s", _("gitg"), basename); - gtk_window_set_title(GTK_WINDOW(window), title); - - g_free(basename); - g_free(title); - add_recent_item(window); gtk_widget_set_sensitive(GTK_WIDGET(window->priv->notebook_main), TRUE); } @@ -1081,7 +1123,7 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const ** if (path || argc > 1) handle_no_gitdir(window); - gtk_window_set_title(GTK_WINDOW(window), _("gitg")); + update_window_title (window); gtk_widget_set_sensitive(GTK_WIDGET(window->priv->notebook_main), FALSE); } } @@ -1449,6 +1491,15 @@ on_merge_activated (GtkAction *action, GitgWindow *window) window->priv->popup_refs[0])); } +static void +on_stash_activated (GtkAction *action, GitgWindow *window) +{ + GitgRef *dest = g_object_get_data (G_OBJECT (action), + DYNAMIC_ACTION_DATA_KEY); + + gitg_branch_actions_apply_stash (window, window->priv->popup_refs[0], dest); +} + static void update_merge_rebase (GitgWindow *window, GitgRef *ref) { @@ -1473,7 +1524,8 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref) g_list_free (actions); } - if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH) + if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH && + gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_STASH) { return; } @@ -1494,7 +1546,7 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref) GSList *refs = gitg_repository_get_refs (window->priv->repository); GSList *item; - + for (item = refs; item; item = g_slist_next (item)) { GitgRef *r = GITG_REF (item->data); @@ -1503,95 +1555,132 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref) { gchar const *rname = gitg_ref_get_shortname (r); - gchar *rebase = g_strconcat ("Rebase", rname, "Action", NULL); - gchar *merge = g_strconcat ("Merge", rname, "Action", NULL); + if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH) + { + gchar *rebase = g_strconcat ("Rebase", rname, "Action", NULL); + gchar *merge = g_strconcat ("Merge", rname, "Action", NULL); - GtkAction *rebaseac = gtk_action_new (rebase, rname, NULL, NULL); - GtkAction *mergeac = gtk_action_new (merge, rname, NULL, NULL); + GtkAction *rebaseac = gtk_action_new (rebase, rname, NULL, NULL); + GtkAction *mergeac = gtk_action_new (merge, rname, NULL, NULL); - g_object_set_data_full (G_OBJECT (rebaseac), - DYNAMIC_ACTION_DATA_KEY, - gitg_ref_copy (r), - (GDestroyNotify)gitg_ref_free); - g_object_set_data_full (G_OBJECT (mergeac), - DYNAMIC_ACTION_DATA_KEY, - gitg_ref_copy (r), - (GDestroyNotify)gitg_ref_free); + g_object_set_data_full (G_OBJECT (rebaseac), + DYNAMIC_ACTION_DATA_KEY, + gitg_ref_copy (r), + (GDestroyNotify)gitg_ref_free); + g_object_set_data_full (G_OBJECT (mergeac), + DYNAMIC_ACTION_DATA_KEY, + gitg_ref_copy (r), + (GDestroyNotify)gitg_ref_free); - g_signal_connect (rebaseac, - "activate", - G_CALLBACK (on_rebase_activated), - window); - g_signal_connect (mergeac, - "activate", - G_CALLBACK (on_merge_activated), - window); + g_signal_connect (rebaseac, + "activate", + G_CALLBACK (on_rebase_activated), + window); + g_signal_connect (mergeac, + "activate", + G_CALLBACK (on_merge_activated), + window); - gtk_action_group_add_action (ac, rebaseac); - gtk_action_group_add_action (ac, mergeac); + gtk_action_group_add_action (ac, rebaseac); + gtk_action_group_add_action (ac, mergeac); - gchar *name = g_strconcat ("Rebase", rname, NULL); + gchar *name = g_strconcat ("Rebase", rname, NULL); - gtk_ui_manager_add_ui (window->priv->menus_ui_manager, - window->priv->merge_rebase_uid, - "/ui/revision_popup/Rebase/Placeholder", - name, - rebase, - GTK_UI_MANAGER_MENUITEM, - FALSE); - g_free (name); + gtk_ui_manager_add_ui (window->priv->menus_ui_manager, + window->priv->merge_rebase_uid, + "/ui/revision_popup/Rebase/Placeholder", + name, + rebase, + GTK_UI_MANAGER_MENUITEM, + FALSE); + g_free (name); - name = g_strconcat ("Merge", rname, NULL); + name = g_strconcat ("Merge", rname, NULL); - gtk_ui_manager_add_ui (window->priv->menus_ui_manager, - window->priv->merge_rebase_uid, - "/ui/revision_popup/Merge/Placeholder", - name, - merge, - GTK_UI_MANAGER_MENUITEM, - FALSE); - g_free (name); + gtk_ui_manager_add_ui (window->priv->menus_ui_manager, + window->priv->merge_rebase_uid, + "/ui/revision_popup/Merge/Placeholder", + name, + merge, + GTK_UI_MANAGER_MENUITEM, + FALSE); + g_free (name); - g_object_unref (rebaseac); - g_object_unref (mergeac); + g_object_unref (rebaseac); + g_object_unref (mergeac); + } + else + { + gchar *stash = g_strconcat ("Stash", rname, "Action", NULL); + + GtkAction *stashac = gtk_action_new (stash, rname, NULL, NULL); + + g_object_set_data_full (G_OBJECT (stashac), + DYNAMIC_ACTION_DATA_KEY, + gitg_ref_copy (r), + (GDestroyNotify)gitg_ref_free); + + g_signal_connect (stashac, + "activate", + G_CALLBACK (on_stash_activated), + window); + + gtk_action_group_add_action (ac, stashac); + + gchar *name = g_strconcat ("Stash", rname, NULL); + + gtk_ui_manager_add_ui (window->priv->menus_ui_manager, + window->priv->merge_rebase_uid, + "/ui/revision_popup/Stash/Placeholder", + name, + stash, + GTK_UI_MANAGER_MENUITEM, + FALSE); + g_free (name); + + g_object_unref (stashac); + } } } g_slist_foreach (refs, (GFunc)gitg_ref_free, NULL); g_slist_free (refs); - gchar **remotes = gitg_repository_get_remotes (window->priv->repository); - gchar **ptr = remotes; - - while (*ptr) + if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH) { - gchar *push = g_strconcat ("Push", *ptr, "Action", NULL); - GtkAction *pushac = gtk_action_new (push, *ptr, NULL, NULL); - - gtk_action_group_add_action (ac, pushac); - - gchar *name = g_strconcat ("Push", *ptr, NULL); - gtk_ui_manager_add_ui (window->priv->menus_ui_manager, - window->priv->merge_rebase_uid, - "/ui/revision_popup/Push/Placeholder", - name, - push, - GTK_UI_MANAGER_MENUITEM, - FALSE); - - g_object_set_data_full (G_OBJECT (pushac), - DYNAMIC_ACTION_DATA_KEY, - g_strdup (*ptr), - (GDestroyNotify)g_free); - - g_signal_connect (pushac, - "activate", - G_CALLBACK (on_push_activated), - window); - ++ptr; - } + gchar **remotes = gitg_repository_get_remotes (window->priv->repository); + gchar **ptr = remotes; - g_strfreev (remotes); + while (*ptr) + { + gchar *push = g_strconcat ("Push", *ptr, "Action", NULL); + GtkAction *pushac = gtk_action_new (push, *ptr, NULL, NULL); + + gtk_action_group_add_action (ac, pushac); + + gchar *name = g_strconcat ("Push", *ptr, NULL); + gtk_ui_manager_add_ui (window->priv->menus_ui_manager, + window->priv->merge_rebase_uid, + "/ui/revision_popup/Push/Placeholder", + name, + push, + GTK_UI_MANAGER_MENUITEM, + FALSE); + + g_object_set_data_full (G_OBJECT (pushac), + DYNAMIC_ACTION_DATA_KEY, + g_strdup (*ptr), + (GDestroyNotify)g_free); + + g_signal_connect (pushac, + "activate", + G_CALLBACK (on_push_activated), + window); + ++ptr; + } + + g_strfreev (remotes); + } gtk_ui_manager_ensure_update (window->priv->menus_ui_manager); } @@ -1663,7 +1752,8 @@ popup_revision (GitgWindow *window, GdkEventButton *event) gtk_tree_path_free (path); if (!ref || (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH && - gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_REMOTE)) + gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_REMOTE && + gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_STASH)) { return FALSE; } @@ -1703,6 +1793,11 @@ popup_revision (GitgWindow *window, GdkEventButton *event) gtk_action_set_visible (checkout, !gitg_ref_equal (working, ref)); } + else if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_STASH) + { + gtk_action_set_label (remove, _("Remove stash")); + gtk_action_set_visible (checkout, FALSE); + } update_merge_rebase (window, ref); window->priv->popup_refs[0] = ref; @@ -1726,7 +1821,10 @@ on_tree_view_rv_button_press_event (GtkWidget *widget, GdkEventButton *event, Gi void on_checkout_branch_action_activate (GtkAction *action, GitgWindow *window) { - gitg_branch_actions_checkout (window, window->priv->popup_refs[0]); + if (gitg_branch_actions_checkout (window, window->priv->popup_refs[0])) + { + update_window_title (window); + } } void