[gitg] Use remote pushes for push branch menu
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg] Use remote pushes for push branch menu
- Date: Sat, 29 May 2010 19:32:45 +0000 (UTC)
commit 19beb8e56951d3398b2b2d1fffc1bcadb2140f12
Author: Edward Rudd <urkle outoforder cc>
Date: Tue Jan 12 17:54:17 2010 -0500
Use remote pushes for push branch menu
https://bugzilla.gnome.org/show_bug.cgi?id=606792
gitg/gitg-repository.c | 135 ++++++++++++++++++++++++++++++++++++++++++++----
gitg/gitg-repository.h | 1 +
gitg/gitg-window.c | 131 +++++++++++++++++++++++++++++------------------
3 files changed, 206 insertions(+), 61 deletions(-)
---
diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c
index 402e281..9a64031 100644
--- a/gitg/gitg-repository.c
+++ b/gitg/gitg-repository.c
@@ -91,6 +91,9 @@ struct _GitgRepositoryPrivate
gint stamp;
GType column_types[N_COLUMNS];
+ GHashTable *ref_pushes;
+ GHashTable *ref_names;
+
GitgRevision **storage;
GitgLanes *lanes;
GHashTable *refs;
@@ -346,10 +349,12 @@ do_clear(GitgRepository *repository, gboolean emit)
repository->priv->current_ref = NULL;
/* clear hash tables */
- g_hash_table_remove_all(repository->priv->hashtable);
- g_hash_table_remove_all(repository->priv->refs);
+ g_hash_table_remove_all (repository->priv->hashtable);
+ g_hash_table_remove_all (repository->priv->refs);
+ g_hash_table_remove_all (repository->priv->ref_names);
+ g_hash_table_remove_all (repository->priv->ref_pushes);
- gitg_color_reset();
+ gitg_color_reset ();
}
static void
@@ -377,8 +382,10 @@ gitg_repository_finalize(GObject *object)
}
/* Free the hash */
- g_hash_table_destroy(rp->priv->hashtable);
- g_hash_table_destroy(rp->priv->refs);
+ g_hash_table_destroy (rp->priv->hashtable);
+ g_hash_table_destroy (rp->priv->refs);
+ g_hash_table_destroy (rp->priv->ref_names);
+ g_hash_table_destroy (rp->priv->ref_pushes);
/* Free cached args */
g_strfreev(rp->priv->last_args);
@@ -734,11 +741,15 @@ find_ref_custom (GitgRef *first, GitgRef *second)
}
static GitgRef *
-add_ref(GitgRepository *self, gchar const *sha1, gchar const *name)
+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));
+ GitgRef *ref = gitg_ref_new (sha1, name);
+ GSList *refs = (GSList *)g_hash_table_lookup (self->priv->refs,
+ gitg_ref_get_hash (ref));
+
+ g_hash_table_insert (self->priv->ref_names,
+ (gpointer)gitg_ref_get_name (ref),
+ ref);
if (refs == NULL)
{
@@ -1098,8 +1109,15 @@ initialize_bindings(GitgRepository *repository)
static void
gitg_repository_init(GitgRepository *object)
{
- object->priv = GITG_REPOSITORY_GET_PRIVATE(object);
- object->priv->hashtable = g_hash_table_new_full(gitg_utils_hash_hash, gitg_utils_hash_equal, NULL, NULL);
+ object->priv = GITG_REPOSITORY_GET_PRIVATE (object);
+
+ object->priv->hashtable = g_hash_table_new (gitg_utils_hash_hash,
+ gitg_utils_hash_equal);
+
+ object->priv->ref_pushes = g_hash_table_new (gitg_utils_hash_hash,
+ gitg_utils_hash_equal);
+
+ object->priv->ref_names = g_hash_table_new (g_str_hash, g_str_equal);
object->priv->column_types[0] = GITG_TYPE_REVISION;
object->priv->column_types[1] = G_TYPE_STRING;
@@ -1749,6 +1767,101 @@ gitg_repository_get_remotes (GitgRepository *repository)
return (gchar **)g_ptr_array_free (remotes, FALSE);
}
+GSList const *
+gitg_repository_get_ref_pushes (GitgRepository *repository, GitgRef *ref)
+{
+ gpointer ret;
+ GitgRef *my_ref;
+
+ g_return_val_if_fail (GITG_IS_REPOSITORY (repository), NULL);
+
+ my_ref = g_hash_table_lookup (repository->priv->ref_names,
+ gitg_ref_get_name (ref));
+
+ if (!my_ref)
+ {
+ return NULL;
+ }
+
+ if (g_hash_table_lookup_extended (repository->priv->ref_pushes,
+ my_ref,
+ NULL,
+ &ret))
+ {
+ return ret;
+ }
+
+ GitgConfig *config = gitg_config_new (repository);
+ gchar *escaped = g_regex_escape_string (gitg_ref_get_name (my_ref), -1);
+ gchar *value_regex = g_strdup_printf ("^%s:", escaped);
+
+ gchar *pushes = gitg_config_get_value_regex (config,
+ "remote\\..*\\.push",
+ value_regex);
+
+ g_free (escaped);
+ g_free (value_regex);
+
+ if (!pushes || !*pushes)
+ {
+ g_object_unref (config);
+ g_free (pushes);
+
+ g_hash_table_insert (repository->priv->ref_pushes,
+ my_ref,
+ NULL);
+
+ return NULL;
+ }
+
+ gchar **lines = g_strsplit (pushes, "\n", -1);
+ gchar **ptr = lines;
+
+ g_free (pushes);
+
+ GRegex *regex = g_regex_new ("remote\\.(.+?)\\.push\\s+.*:refs/heads/(.*)", 0, 0, NULL);
+ GSList *refs = NULL;
+
+ while (*ptr)
+ {
+ GMatchInfo *info = NULL;
+
+ if (g_regex_match (regex, *ptr, 0, &info))
+ {
+ gchar *remote = g_match_info_fetch (info, 1);
+ gchar *branch = g_match_info_fetch (info, 2);
+
+ gchar *rr = g_strconcat ("refs/remotes/", remote, "/", branch, NULL);
+
+ GitgRef *remref = g_hash_table_lookup (repository->priv->ref_names,
+ rr);
+
+ g_free (rr);
+ g_free (remote);
+ g_free (branch);
+
+ if (remref)
+ {
+ refs = g_slist_prepend (refs, remref);
+ }
+ }
+
+ g_match_info_free (info);
+ ++ptr;
+ }
+
+ g_object_unref (config);
+ g_strfreev (lines);
+
+ refs = g_slist_reverse (refs);
+
+ g_hash_table_insert (repository->priv->ref_pushes,
+ my_ref,
+ refs);
+
+ return refs;
+}
+
gboolean
gitg_repository_get_loaded (GitgRepository *repository)
{
diff --git a/gitg/gitg-repository.h b/gitg/gitg-repository.h
index a678b61..a631742 100644
--- a/gitg/gitg-repository.h
+++ b/gitg/gitg-repository.h
@@ -118,6 +118,7 @@ gchar *gitg_repository_parse_head(GitgRepository *repository);
void gitg_repository_reload(GitgRepository *repository);
gchar **gitg_repository_get_remotes (GitgRepository *repository);
+GSList const *gitg_repository_get_ref_pushes (GitgRepository *repository, GitgRef *ref);
gchar const **gitg_repository_get_current_selection (GitgRepository *repository);
G_END_DECLS
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 2b9a963..006a366 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -1954,16 +1954,64 @@ get_tracked_ref (GitgWindow *window, GitgRef *branch, gchar **retremote, gchar *
{
*retbranch = g_strdup (merge + 11);
}
+ else
+ {
+ *retbranch = NULL;
+ }
g_free (merge);
}
+static gboolean
+repository_has_ref (GitgWindow *window, gchar const *remote, gchar const *branch)
+{
+ GSList *refs = gitg_repository_get_refs (window->priv->repository);
+ gchar *combined = g_strconcat (remote, "/", branch, NULL);
+
+ while (refs)
+ {
+ GitgRef *r = (GitgRef *)refs->data;
+
+ if (gitg_ref_get_ref_type (r) == GITG_REF_TYPE_REMOTE &&
+ strcmp (gitg_ref_get_shortname (r), combined) == 0)
+ {
+ g_free (combined);
+ return TRUE;
+ }
+
+ refs = g_slist_next (refs);
+ }
+
+ g_free (combined);
+ return FALSE;
+}
+
static void
-add_push_action (GitgWindow *window, GtkActionGroup *group, gchar const *name, gchar const *remote, gchar const *branch)
+add_push_action (GitgWindow *window,
+ GtkActionGroup *group,
+ gchar const *remote,
+ gchar const *branch)
{
gchar *acname = g_strconcat ("Push", remote, branch, "Action", NULL);
- GtkAction *pushac = gtk_action_new (acname, name, NULL, NULL);
+ gchar *name;
+
+ if (gtk_action_group_get_action (group, acname) != NULL)
+ {
+ /* No need for twice the same */
+ g_free (acname);
+ return;
+ }
+
+ if (repository_has_ref (window, remote, branch))
+ {
+ name = g_strconcat (remote, "/", branch, NULL);
+ }
+ else
+ {
+ name = g_strconcat (remote, "/", branch, " (", _("new"), ")", NULL);
+ }
+ GtkAction *pushac = gtk_action_new (acname, name, NULL, NULL);
gtk_action_group_add_action (group, pushac);
gchar *nm = g_strconcat ("Push", remote, branch, NULL);
@@ -1989,30 +2037,10 @@ add_push_action (GitgWindow *window, GtkActionGroup *group, gchar const *name, g
"activate",
G_CALLBACK (on_push_activated),
window);
-}
-static gboolean
-repository_has_ref (GitgWindow *window, gchar const *remote, GitgRef *ref)
-{
- GSList *refs = gitg_repository_get_refs (window->priv->repository);
- gchar *combined = g_strconcat (remote, "/", gitg_ref_get_shortname (ref), NULL);
-
- while (refs)
- {
- GitgRef *r = (GitgRef *)refs->data;
-
- if (gitg_ref_get_ref_type (r) == GITG_REF_TYPE_REMOTE &&
- strcmp (gitg_ref_get_shortname (r), combined) == 0)
- {
- g_free (combined);
- return TRUE;
- }
-
- refs = g_slist_next (refs);
- }
-
- g_free (combined);
- return FALSE;
+ g_free (acname);
+ g_free (name);
+ g_free (nm);
}
static void
@@ -2169,47 +2197,50 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref)
/* Get the tracked remote of this ref (if any) */
gchar *remote = NULL;
gchar *branch = NULL;
- gchar *tracked = NULL;
-
- gchar **remotes = gitg_repository_get_remotes (window->priv->repository);
- gchar **ptr = remotes;
get_tracked_ref (window, ref, &remote, &branch);
if (remote)
{
- tracked = g_strconcat (remote, "/", branch, NULL);
- add_push_action (window, ac, tracked, remote, branch);
+ add_push_action (window,
+ ac,
+ remote,
+ branch ? branch : gitg_ref_get_shortname (ref));
+
+ g_free (remote);
+ g_free (branch);
}
- while (*ptr)
+ GSList const *ref_pushes = gitg_repository_get_ref_pushes (window->priv->repository,
+ ref);
+
+ /* Get configured ref pushes */
+ while (ref_pushes)
{
- if (!tracked || !g_str_has_prefix (tracked, *ptr))
- {
- gchar *name;
+ GitgRef *push_ref = ref_pushes->data;
- if (repository_has_ref (window, *ptr, ref))
- {
- name = g_strconcat (*ptr, "/", gitg_ref_get_shortname (ref), NULL);
- }
- else
- {
- name = g_strconcat (*ptr, "/", gitg_ref_get_shortname (ref), " (", _("new"), ")", NULL);
- }
+ add_push_action (window,
+ ac,
+ gitg_ref_get_prefix (push_ref),
+ gitg_ref_get_local_name (push_ref));
- add_push_action (window, ac, name, *ptr, gitg_ref_get_shortname (ref));
+ ref_pushes = g_slist_next (ref_pushes);
+ }
- g_free (name);
- }
+ gchar **remotes = gitg_repository_get_remotes (window->priv->repository);
+ gchar **ptr = remotes;
+
+ while (*ptr)
+ {
+ add_push_action (window,
+ ac,
+ *ptr,
+ gitg_ref_get_shortname (ref));
++ptr;
}
- g_free (tracked);
g_strfreev (remotes);
-
- g_free (remote);
- g_free (branch);
}
gtk_ui_manager_ensure_update (window->priv->menus_ui_manager);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]