mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-10-31 04:58:58 +00:00
Implemented cherry-picking
This commit is contained in:
parent
9c44c7e608
commit
684f9172e9
5 changed files with 253 additions and 8 deletions
|
@ -1594,3 +1594,185 @@ gitg_branch_actions_tag (GitgWindow *window, gchar const *sha1, gchar const *nam
|
|||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GitgRevision *revision;
|
||||
GitgRef *dest;
|
||||
|
||||
gchar *stashcommit;
|
||||
GitgRef *head;
|
||||
} CherryPickInfo;
|
||||
|
||||
static CherryPickInfo *
|
||||
cherry_pick_info_new (GitgRevision *revision, GitgRef *dest)
|
||||
{
|
||||
CherryPickInfo *ret = g_slice_new0 (CherryPickInfo);
|
||||
|
||||
ret->revision = gitg_revision_ref (revision);
|
||||
ret->dest = gitg_ref_copy (dest);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
cherry_pick_info_free (CherryPickInfo *info)
|
||||
{
|
||||
gitg_revision_unref (info->revision);
|
||||
gitg_ref_free (info->dest);
|
||||
|
||||
g_free (info->stashcommit);
|
||||
gitg_ref_free (info->head);
|
||||
|
||||
g_slice_free (CherryPickInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_cherry_pick_result (GitgWindow *window,
|
||||
GitgProgress progress,
|
||||
gpointer data)
|
||||
{
|
||||
CherryPickInfo *info = (CherryPickInfo *)data;
|
||||
|
||||
if (progress == GITG_PROGRESS_ERROR)
|
||||
{
|
||||
gchar const *message;
|
||||
|
||||
message_dialog (window,
|
||||
GTK_MESSAGE_ERROR,
|
||||
_("Failed to cherry-pick on <%s>"),
|
||||
NULL,
|
||||
NULL,
|
||||
gitg_ref_get_shortname (info->dest));
|
||||
}
|
||||
else if (progress == GITG_PROGRESS_SUCCESS)
|
||||
{
|
||||
GitgRepository *repository = gitg_window_get_repository (window);
|
||||
|
||||
// Checkout head
|
||||
if (!checkout_local_branch_real (window, info->head))
|
||||
{
|
||||
gchar const *message = NULL;
|
||||
|
||||
if (info->stashcommit)
|
||||
{
|
||||
gitg_repository_commandv (repository, NULL,
|
||||
"update-ref", "-m", "gitg autosave stash",
|
||||
"refs/stash", info->stashcommit, NULL);
|
||||
|
||||
message = _("The stashed changes have been stored to be reapplied manually");
|
||||
}
|
||||
|
||||
message_dialog (window,
|
||||
GTK_MESSAGE_ERROR,
|
||||
_("Failed to checkout previously checked out branch"),
|
||||
message,
|
||||
NULL);
|
||||
}
|
||||
else if (info->stashcommit)
|
||||
{
|
||||
// Reapply stash
|
||||
if (!gitg_repository_commandv (gitg_window_get_repository (window),
|
||||
NULL,
|
||||
"stash",
|
||||
"apply",
|
||||
"--index",
|
||||
info->stashcommit,
|
||||
NULL))
|
||||
{
|
||||
gitg_repository_commandv (repository, NULL,
|
||||
"update-ref", "-m", "gitg autosave stash",
|
||||
"refs/stash", info->stashcommit, NULL);
|
||||
|
||||
message_dialog (window,
|
||||
GTK_MESSAGE_ERROR,
|
||||
_("Failed to reapply stash correctly"),
|
||||
_("There might be unresolved conflicts in the working tree or index which you need to resolve manually"),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gitg_repository_reload (gitg_window_get_repository (window));
|
||||
}
|
||||
|
||||
cherry_pick_info_free (info);
|
||||
}
|
||||
|
||||
GitgRunner *
|
||||
gitg_branch_actions_cherry_pick (GitgWindow *window,
|
||||
GitgRevision *revision,
|
||||
GitgRef *dest)
|
||||
{
|
||||
g_return_val_if_fail (GITG_IS_WINDOW (window), NULL);
|
||||
g_return_val_if_fail (revision != NULL, NULL);
|
||||
g_return_val_if_fail (dest != NULL, NULL);
|
||||
|
||||
gchar *message = g_strdup_printf (_("Are you sure you want to cherry-pick that revision on <%s>?"),
|
||||
gitg_ref_get_shortname (dest));
|
||||
|
||||
if (message_dialog (window,
|
||||
GTK_MESSAGE_QUESTION,
|
||||
_("Cherry-pick"),
|
||||
message,
|
||||
_("Cherry-pick")) != GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
g_free (message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar *stashcommit;
|
||||
|
||||
if (!stash_changes (window, &stashcommit, FALSE))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GitgRepository *repository = gitg_window_get_repository (window);
|
||||
GitgRef *head = gitg_repository_get_current_working_ref (repository);
|
||||
|
||||
// First checkout the correct branch on which to cherry-pick
|
||||
if (!gitg_repository_commandv (repository,
|
||||
NULL,
|
||||
"checkout",
|
||||
gitg_ref_get_shortname (dest),
|
||||
NULL))
|
||||
{
|
||||
g_free (stashcommit);
|
||||
|
||||
message_dialog (window,
|
||||
GTK_MESSAGE_ERROR,
|
||||
_("Failed to checkout local branch <%s>"),
|
||||
_("The branch on which to cherry-pick could not be checked out"),
|
||||
NULL,
|
||||
gitg_ref_get_shortname (dest));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = g_strdup_printf (_("Cherry-picking on <%s>"),
|
||||
gitg_ref_get_shortname (dest));
|
||||
|
||||
GitgRunner *ret;
|
||||
|
||||
CherryPickInfo *info = cherry_pick_info_new (revision, dest);
|
||||
|
||||
info->stashcommit = stashcommit;
|
||||
info->head = gitg_ref_copy (head);
|
||||
|
||||
gchar *sha1 = gitg_revision_get_sha1 (revision);
|
||||
|
||||
ret = run_progress (window,
|
||||
_("Cherry-pick"),
|
||||
message,
|
||||
on_cherry_pick_result,
|
||||
info,
|
||||
"cherry-pick",
|
||||
sha1,
|
||||
NULL);
|
||||
|
||||
g_free (message);
|
||||
gitg_ref_free (head);
|
||||
g_free (sha1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ gboolean gitg_branch_actions_apply_stash (GitgWindow *window, GitgRef *stash, Gi
|
|||
|
||||
gboolean gitg_branch_actions_tag (GitgWindow *window, gchar const *sha1, gchar const *name, gchar const *message, gboolean sign);
|
||||
|
||||
GitgRunner *gitg_branch_actions_cherry_pick (GitgWindow *window, GitgRevision *revision, GitgRef *dest);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GITG_BRANCH_ACTIONS_H__ */
|
||||
|
|
|
@ -29,6 +29,7 @@ typedef struct
|
|||
GitgRef *cursor_ref;
|
||||
|
||||
GitgDndCallback callback;
|
||||
GitgDndRevisionCallback revision_callback;
|
||||
gpointer callback_data;
|
||||
|
||||
gdouble x;
|
||||
|
@ -554,7 +555,7 @@ gitg_drag_source_motion_cb (GtkWidget *widget,
|
|||
guint time,
|
||||
GitgDndData *data)
|
||||
{
|
||||
if (!data->ref)
|
||||
if (!data->ref && !data->revision)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -587,13 +588,18 @@ gitg_drag_source_motion_cb (GtkWidget *widget,
|
|||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
if (data->callback)
|
||||
if (data->ref && data->callback)
|
||||
{
|
||||
data->callback (data->ref, ref, FALSE, data->callback_data);
|
||||
}
|
||||
else if (data->revision && data->revision_callback)
|
||||
{
|
||||
data->revision_callback (data->revision, ref, FALSE, data->callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (ref && can_drop (data->ref, ref))
|
||||
if ((data->ref && ref && can_drop (data->ref, ref)) ||
|
||||
(data->revision && ref && gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH))
|
||||
{
|
||||
if (ref != data->target)
|
||||
{
|
||||
|
@ -627,17 +633,21 @@ gitg_drag_source_drop_cb (GtkWidget *widget,
|
|||
guint time,
|
||||
GitgDndData *data)
|
||||
{
|
||||
if (!data->ref || !data->target)
|
||||
if (!(data->ref || data->revision) || !data->target)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (data->callback)
|
||||
if (data->ref && data->callback)
|
||||
{
|
||||
ret = data->callback (data->ref, data->target, TRUE, data->callback_data);
|
||||
}
|
||||
else if (data->revision && data->revision_callback)
|
||||
{
|
||||
ret = data->revision_callback (data->revision, data->target, TRUE, data->callback_data);
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, ret, FALSE, time);
|
||||
return ret;
|
||||
|
@ -784,7 +794,10 @@ gitg_drag_source_data_get_cb (GtkWidget *widget,
|
|||
}
|
||||
|
||||
void
|
||||
gitg_dnd_enable (GtkTreeView *tree_view, GitgDndCallback callback, gpointer callback_data)
|
||||
gitg_dnd_enable (GtkTreeView *tree_view,
|
||||
GitgDndCallback callback,
|
||||
GitgDndRevisionCallback revision_callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
if (GITG_DND_GET_DATA (tree_view))
|
||||
{
|
||||
|
@ -795,6 +808,7 @@ gitg_dnd_enable (GtkTreeView *tree_view, GitgDndCallback callback, gpointer call
|
|||
|
||||
data->tree_view = tree_view;
|
||||
data->callback = callback;
|
||||
data->revision_callback = revision_callback;
|
||||
data->callback_data = callback_data;
|
||||
|
||||
g_object_set_data_full (G_OBJECT (tree_view),
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gitg-ref.h"
|
||||
#include "gitg-revision.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef gboolean (*GitgDndCallback)(GitgRef *source, GitgRef *dest, gboolean dropped, gpointer callback_data);
|
||||
typedef gboolean (*GitgDndRevisionCallback)(GitgRevision *source, GitgRef *dest, gboolean dropped, gpointer callback_data);
|
||||
|
||||
void gitg_dnd_enable (GtkTreeView *tree_view,
|
||||
GitgDndCallback callback,
|
||||
GitgDndRevisionCallback revision_callback,
|
||||
gpointer callback_data);
|
||||
|
||||
void gitg_dnd_enable (GtkTreeView *tree_view, GitgDndCallback callback, gpointer callback_data);
|
||||
void gitg_dnd_disable (GtkTreeView *tree_view);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -580,6 +580,44 @@ on_refs_dnd (GitgRef *source, GitgRef *dest, gboolean dropped, GitgWindow *windo
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
update_revision_dnd_status (GitgWindow *window, GitgRevision *source, GitgRef *dest)
|
||||
{
|
||||
if (!dest)
|
||||
{
|
||||
gtk_statusbar_push (window->priv->statusbar, 0, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *message = g_strdup_printf (_("Cherry-pick revision on <%s>"),
|
||||
gitg_ref_get_shortname (dest));
|
||||
|
||||
gtk_statusbar_push (window->priv->statusbar, 0, message);
|
||||
g_free (message);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_revision_dnd (GitgRevision *source,
|
||||
GitgRef *dest,
|
||||
gboolean dropped,
|
||||
GitgWindow *window)
|
||||
{
|
||||
if (!dropped)
|
||||
{
|
||||
update_revision_dnd_status (window, source, dest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gitg_ref_get_ref_type (dest) != GITG_REF_TYPE_BRANCH)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return add_branch_action (window,
|
||||
gitg_branch_actions_cherry_pick (window, source, dest));
|
||||
}
|
||||
|
||||
static void
|
||||
init_tree_view (GitgWindow *window, GtkBuilder *builder)
|
||||
{
|
||||
|
@ -589,7 +627,10 @@ init_tree_view (GitgWindow *window, GtkBuilder *builder)
|
|||
|
||||
gtk_tree_view_column_set_cell_data_func(col, GTK_CELL_RENDERER(window->priv->renderer_path), (GtkTreeCellDataFunc)on_renderer_path, window, NULL);
|
||||
|
||||
gitg_dnd_enable (window->priv->tree_view, (GitgDndCallback)on_refs_dnd, window);
|
||||
gitg_dnd_enable (window->priv->tree_view,
|
||||
(GitgDndCallback)on_refs_dnd,
|
||||
(GitgDndRevisionCallback)on_revision_dnd,
|
||||
window);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue