[gitg] Implemented basic virtual commit objects in history view



commit fd5f631825c12ab7d9c4353c15f9ac648cb6087f
Author: Jesse van den Kieboom <jesse icecrew nl>
Date:   Tue Apr 21 09:08:00 2009 +0200

    Implemented basic virtual commit objects in history view
    
    This still needs some work in the configure dialog
---
 gitg/gitg-cell-renderer-path.c |   46 +++++++++--
 gitg/gitg-lane.h               |    5 +-
 gitg/gitg-preferences-dialog.c |   72 +++++++++++++++-
 gitg/gitg-preferences.c        |   44 ++++++++++-
 gitg/gitg-preferences.xml      |   74 +++++++++++++----
 gitg/gitg-repository.c         |  178 +++++++++++++++++++++++++++++++++++----
 gitg/gitg-revision-view.c      |   60 +++++++++++--
 gitg/gitg-revision.c           |   47 ++++++++---
 gitg/gitg-window.c             |   36 ++++++++-
 9 files changed, 487 insertions(+), 75 deletions(-)

diff --git a/gitg/gitg-cell-renderer-path.c b/gitg/gitg-cell-renderer-path.c
index 115f679..57c6773 100644
--- a/gitg/gitg-cell-renderer-path.c
+++ b/gitg/gitg-cell-renderer-path.c
@@ -66,13 +66,34 @@ num_lanes(GitgCellRendererPath *self)
 	return g_slist_length (gitg_revision_get_lanes(self->priv->revision));
 }
 
-inline static gint
+static gboolean
+is_dummy(GitgRevision *revision)
+{
+	switch (gitg_revision_get_sign(revision))
+	{
+		case 's':
+		case 't':
+		case 'u':
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+static gint
 total_width(GitgCellRendererPath *self, GtkWidget *widget)
 {
 	PangoFontDescription *font;
 	g_object_get(self, "font-desc", &font, NULL);
-		
-	return num_lanes(self) * self->priv->lane_width + gitg_label_renderer_width(widget, font, self->priv->labels);
+	
+	gint offset = 0;
+	
+	if (is_dummy(self->priv->revision))
+		offset = self->priv->lane_width;
+	
+	return num_lanes(self) * self->priv->lane_width + 
+	       gitg_label_renderer_width(widget, font, self->priv->labels) +
+	       offset;
 }
 
 static void
@@ -215,6 +236,9 @@ draw_labels(GitgCellRendererPath *self, GtkWidget *widget, cairo_t *context, Gdk
 	gint offset = num_lanes(self) * self->priv->lane_width;
 	PangoFontDescription *font;
 	
+	if (is_dummy(self->priv->revision))
+		offset += self->priv->lane_width;
+	
 	g_object_get(self, "font-desc", &font, NULL);
 	
 	cairo_translate(context, offset, 0.0);
@@ -259,14 +283,24 @@ draw_indicator_circle(GitgCellRendererPath *self, GitgLane *lane, cairo_t *conte
 	gdouble offset = gitg_revision_get_mylane(self->priv->revision) * self->priv->lane_width + (self->priv->lane_width - self->priv->dot_width) / 2.0;
 	gdouble radius = self->priv->dot_width / 2.0;
 	
+	if (is_dummy(self->priv->revision))
+		offset += self->priv->lane_width;
+
 	cairo_set_line_width(context, 2.0);
 	cairo_arc(context, area->x + offset + radius, area->y + area->height / 2.0, radius, 0, 2 * M_PI);
 	cairo_set_source_rgb(context, 0, 0, 0);
 	
-	cairo_stroke_preserve(context);
-	gitg_color_set_cairo_source(lane->color, context);
+	if (is_dummy(self->priv->revision))
+	{
+		cairo_stroke(context);
+	}
+	else
+	{
+		cairo_stroke_preserve(context);
+		gitg_color_set_cairo_source(lane->color, context);
 	
-	cairo_fill(context);
+		cairo_fill(context);
+	}
 }
 
 static void
diff --git a/gitg/gitg-lane.h b/gitg/gitg-lane.h
index 045e962..d679c32 100644
--- a/gitg/gitg-lane.h
+++ b/gitg/gitg-lane.h
@@ -34,7 +34,10 @@ typedef enum
 	GITG_LANE_TYPE_START = 1 << 0,
 	GITG_LANE_TYPE_END = 1 << 1,
 	GITG_LANE_SIGN_LEFT = 1 << 2,
-	GITG_LANE_SIGN_RIGHT = 1 << 3
+	GITG_LANE_SIGN_RIGHT = 1 << 3,
+	GITG_LANE_SIGN_STASH = 1 << 4,
+	GITG_LANE_SIGN_STAGED = 1 << 5,
+	GITG_LANE_SIGN_UNSTAGED = 1 << 6,
 } GitgLaneType;
 
 typedef struct
diff --git a/gitg/gitg-preferences-dialog.c b/gitg/gitg-preferences-dialog.c
index 8ba26e6..8f3d394 100644
--- a/gitg/gitg-preferences-dialog.c
+++ b/gitg/gitg-preferences-dialog.c
@@ -44,6 +44,11 @@ struct _GitgPreferencesDialogPrivate
 {
 	GtkCheckButton *history_search_filter;
 	GtkAdjustment *collapse_inactive_lanes;
+	GtkHScale *hscale_collapse_inactive_lanes;
+	GtkCheckButton *history_show_virtual_stash;
+	GtkCheckButton *history_show_virtual_staged;
+	GtkCheckButton *history_show_virtual_unstaged;
+	GtkCheckButton *check_button_collapse_inactive;
 
 	gint prev_value;
 };
@@ -87,6 +92,19 @@ on_response(GtkWidget *dialog, gint response, gpointer data)
 }
 
 static gboolean
+convert_collapsed_from(GValue const *source, GValue *dest, gpointer userdata)
+{
+	GitgPreferencesDialog *dialog = GITG_PREFERENCES_DIALOG(userdata);
+	gint val = g_value_get_int(source);
+	
+	gtk_widget_set_sensitive(GTK_WIDGET(dialog->priv->hscale_collapse_inactive_lanes),
+	                         val != 0);
+	
+	g_value_set_double(dest, (gdouble)val);
+	return TRUE;
+}
+
+static gboolean
 convert_collapsed(GValue const *source, GValue *dest, gpointer userdata)
 {
 	GitgPreferencesDialog *dialog = GITG_PREFERENCES_DIALOG(userdata);
@@ -100,6 +118,26 @@ convert_collapsed(GValue const *source, GValue *dest, gpointer userdata)
 	return g_value_transform(source, dest);
 }
 
+static gboolean
+convert_collapsed_to_active(GValue const *source, GValue *dest, gpointer userdata)
+{
+	gboolean v = g_value_get_boolean(source);
+	
+	if (v)
+		g_value_set_int(dest, 2);
+	else
+		g_value_set_int(dest, 0);
+	
+	return TRUE;
+}
+
+static gboolean
+convert_collapsed_from_active(GValue const *source, GValue *dest, gpointer userdata)
+{
+	g_value_set_boolean(dest, FALSE);	
+	return TRUE;
+}
+
 static void
 initialize_view(GitgPreferencesDialog *dialog)
 {
@@ -110,9 +148,24 @@ initialize_view(GitgPreferencesDialog *dialog)
 
 	gitg_data_binding_new_mutual_full(preferences, "history-collapse-inactive-lanes",
 						              dialog->priv->collapse_inactive_lanes, "value",
-						              (GitgDataBindingConversion)g_value_transform,
+						              convert_collapsed_from,
 						              convert_collapsed,
 						              dialog);
+
+	gitg_data_binding_new_mutual_full(preferences, "history-collapse-inactive-lanes",
+						              dialog->priv->check_button_collapse_inactive, "active",
+						              convert_collapsed_from_active,
+						              convert_collapsed_to_active,
+						              dialog);
+
+	gitg_data_binding_new_mutual(preferences, "history-show-virtual-stash",
+	                             dialog->priv->history_show_virtual_stash, "active");
+
+	gitg_data_binding_new_mutual(preferences, "history-show-virtual-staged",
+	                             dialog->priv->history_show_virtual_staged, "active");
+
+	gitg_data_binding_new_mutual(preferences, "history-show-virtual-unstaged",
+	                             dialog->priv->history_show_virtual_unstaged, "active");
 }
 
 static void
@@ -124,9 +177,17 @@ create_preferences_dialog()
 	g_object_add_weak_pointer(G_OBJECT(preferences_dialog), (gpointer *)&preferences_dialog);
 	
 	GitgPreferencesDialogPrivate *priv = preferences_dialog->priv;
+	
 	priv->history_search_filter = GTK_CHECK_BUTTON(gtk_builder_get_object(b, "check_button_history_search_filter"));
 	priv->collapse_inactive_lanes = GTK_ADJUSTMENT(gtk_builder_get_object(b, "adjustment_collapse_inactive_lanes"));
 	
+	priv->history_show_virtual_stash = GTK_CHECK_BUTTON(gtk_builder_get_object(b, "check_button_history_show_virtual_stash"));
+	priv->history_show_virtual_staged = GTK_CHECK_BUTTON(gtk_builder_get_object(b, "check_button_history_show_virtual_staged"));
+	priv->history_show_virtual_unstaged = GTK_CHECK_BUTTON(gtk_builder_get_object(b, "check_button_history_show_virtual_unstaged"));
+	
+	priv->check_button_collapse_inactive = GTK_CHECK_BUTTON(gtk_builder_get_object(b, "check_button_collapse_inactive"));
+	priv->hscale_collapse_inactive_lanes = GTK_HSCALE(gtk_builder_get_object(b, "hscale_collapse_inactive_lanes"));
+	
 	priv->prev_value = (gint)gtk_adjustment_get_value(priv->collapse_inactive_lanes);
 	g_signal_connect(preferences_dialog, "response", G_CALLBACK(on_response), NULL);
 	
@@ -153,7 +214,10 @@ on_collapse_inactive_lanes_changed(GtkAdjustment *adjustment, GParamSpec *spec,
 {
 	gint val = round_val(gtk_adjustment_get_value(adjustment));
 
-	g_signal_handlers_block_by_func(adjustment, G_CALLBACK(on_collapse_inactive_lanes_changed), dialog);
-	gtk_adjustment_set_value(adjustment, val);
-	g_signal_handlers_unblock_by_func(adjustment, G_CALLBACK(on_collapse_inactive_lanes_changed), dialog);
+	if (val > 0)
+	{
+		g_signal_handlers_block_by_func(adjustment, G_CALLBACK(on_collapse_inactive_lanes_changed), dialog);
+		gtk_adjustment_set_value(adjustment, val);
+		g_signal_handlers_unblock_by_func(adjustment, G_CALLBACK(on_collapse_inactive_lanes_changed), dialog);
+	}
 }
diff --git a/gitg/gitg-preferences.c b/gitg/gitg-preferences.c
index e9dd2eb..2beab58 100644
--- a/gitg/gitg-preferences.c
+++ b/gitg/gitg-preferences.c
@@ -36,6 +36,9 @@ enum
 	
 	PROP_HISTORY_SEARCH_FILTER,
 	PROP_HISTORY_COLLAPSE_INACTIVE_LANES,
+	PROP_HISTORY_SHOW_VIRTUAL_STASH,
+	PROP_HISTORY_SHOW_VIRTUAL_STAGED,
+	PROP_HISTORY_SHOW_VIRTUAL_UNSTAGED,
 
 	PROP_STYLE_TEXT_FOREGROUND,
 	PROP_STYLE_TEXT_BACKGROUND,
@@ -321,11 +324,50 @@ gitg_preferences_class_init(GitgPreferencesClass *klass)
 					 g_param_spec_int("history-collapse-inactive-lanes",
 							      "HISTORY_COLLAPSE_INACTIVE_LANES",
 							      "Rule for collapsing inactive lanes",
-							      0,
+							      -1,
 							      5,
 							      2,
 							      G_PARAM_READWRITE));
 
+	install_property_binding(PROP_HISTORY_SHOW_VIRTUAL_STASH, 
+							 "view/history",
+							 "show-virtual-stash", 
+							 wrap_get_boolean,
+							 wrap_set_boolean);
+
+	g_object_class_install_property(object_class, PROP_HISTORY_SHOW_VIRTUAL_STASH,
+					 g_param_spec_boolean("history-show-virtual-stash",
+							      "HISTORY_SHOW_VIRTUAL_STASH",
+							      "Show stash in history",
+							      TRUE,
+							      G_PARAM_READWRITE));
+
+	install_property_binding(PROP_HISTORY_SHOW_VIRTUAL_STAGED, 
+							 "view/history",
+							 "show-virtual-staged", 
+							 wrap_get_boolean,
+							 wrap_set_boolean);
+
+	g_object_class_install_property(object_class, PROP_HISTORY_SHOW_VIRTUAL_STAGED,
+					 g_param_spec_boolean("history-show-virtual-staged",
+							      "HISTORY_SHOW_VIRTUAL_STAGED",
+							      "Show staged changes in history",
+							      TRUE,
+							      G_PARAM_READWRITE));
+
+	install_property_binding(PROP_HISTORY_SHOW_VIRTUAL_UNSTAGED, 
+							 "view/history",
+							 "show-virtual-unstaged", 
+							 wrap_get_boolean,
+							 wrap_set_boolean);
+
+	g_object_class_install_property(object_class, PROP_HISTORY_SHOW_VIRTUAL_UNSTAGED,
+					 g_param_spec_boolean("history-show-virtual-unstaged",
+							      "HISTORY_SHOW_VIRTUAL_UNSTAGED",
+							      "Show unstaged changes in history",
+							      TRUE,
+							      G_PARAM_READWRITE));
+
 	install_style_properties(object_class, PROP_STYLE_TEXT_FOREGROUND, "text");
 	install_style_properties(object_class, PROP_STYLE_ADDED_LINE_FOREGROUND, "added-line");
 	install_style_properties(object_class, PROP_STYLE_REMOVED_LINE_FOREGROUND, "removed-line");
diff --git a/gitg/gitg-preferences.xml b/gitg/gitg-preferences.xml
index 11cda6a..2dc611d 100644
--- a/gitg/gitg-preferences.xml
+++ b/gitg/gitg-preferences.xml
@@ -76,23 +76,25 @@
                               </packing>
                             </child>
                             <child>
+                              <object class="GtkCheckButton" id="check_button_collapse_inactive">
+                                <property name="label" translatable="yes">Collapse inactive lanes</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
                               <object class="GtkTable" id="table2">
                                 <property name="visible">True</property>
                                 <property name="n_rows">2</property>
-                                <property name="n_columns">3</property>
+                                <property name="n_columns">2</property>
                                 <property name="column_spacing">3</property>
                                 <property name="row_spacing">3</property>
                                 <child>
-                                  <object class="GtkLabel" id="label14">
-                                    <property name="visible">True</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Collapse inactive lanes:</property>
-                                  </object>
-                                  <packing>
-                                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                                  </packing>
-                                </child>
-                                <child>
                                   <object class="GtkHScale" id="hscale_collapse_inactive_lanes">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
@@ -101,8 +103,8 @@
                                     <property name="digits">0</property>
                                   </object>
                                   <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">3</property>
+                                    <property name="left_attach">0</property>
+                                    <property name="right_attach">2</property>
                                   </packing>
                                 </child>
                                 <child>
@@ -112,8 +114,8 @@
                                     <property name="label" translatable="yes">Early</property>
                                   </object>
                                   <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
+                                    <property name="left_attach">0</property>
+                                    <property name="right_attach">1</property>
                                     <property name="top_attach">1</property>
                                     <property name="bottom_attach">2</property>
                                   </packing>
@@ -135,15 +137,51 @@
                                     <property name="label" translatable="yes">Late</property>
                                   </object>
                                   <packing>
-                                    <property name="left_attach">2</property>
-                                    <property name="right_attach">3</property>
+                                    <property name="left_attach">1</property>
+                                    <property name="right_attach">2</property>
                                     <property name="top_attach">1</property>
                                     <property name="bottom_attach">2</property>
                                   </packing>
                                 </child>
                               </object>
                               <packing>
-                                <property name="position">1</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="check_button_history_show_virtual_stash">
+                                <property name="label" translatable="yes">Show stash in history</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="check_button_history_show_virtual_staged">
+                                <property name="label" translatable="yes">Show staged changes in history</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="position">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="check_button_history_show_virtual_unstaged">
+                                <property name="label" translatable="yes">Show unstaged changes in history</property>
+                                <property name="visible">true</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="position">5</property>
                               </packing>
                             </child>
                           </object>
diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c
index ec7a033..bfdd52b 100644
--- a/gitg/gitg-repository.c
+++ b/gitg/gitg-repository.c
@@ -30,6 +30,7 @@
 
 #include <gio/gio.h>
 #include <glib/gi18n.h>
+#include <sys/time.h>
 #include <time.h>
 #include <string.h>
 
@@ -66,6 +67,16 @@ enum
 	N_COLUMNS
 };
 
+typedef enum
+{
+	LOAD_STAGE_NONE = 0,
+	LOAD_STAGE_STASH,
+	LOAD_STAGE_STAGED,
+	LOAD_STAGE_UNSTAGED,
+	LOAD_STAGE_COMMITS,
+	LOAD_STAGE_LAST
+} LoadStage;
+
 struct _GitgRepositoryPrivate
 {
 	gchar *path;
@@ -85,6 +96,8 @@ struct _GitgRepositoryPrivate
 	
 	gchar **last_args;
 	guint idle_relane_id;
+	
+	LoadStage load_stage;
 };
 
 inline static gint
@@ -429,7 +442,117 @@ gitg_repository_class_init(GitgRepositoryClass *klass)
 }
 
 static void
-on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *self)
+append_revision(GitgRepository *repository, GitgRevision *rv)
+{
+	GSList *lanes;
+	gint8 mylane = 0;
+	
+	if (repository->priv->size == 0)
+		gitg_lanes_reset(repository->priv->lanes);
+
+	lanes = gitg_lanes_next(repository->priv->lanes, rv, &mylane);
+	gitg_revision_set_lanes(rv, lanes, mylane);
+
+	gitg_repository_add(repository, rv, NULL);
+	gitg_revision_unref(rv);
+}
+
+static void
+add_dummy_commit(GitgRepository *repository, gboolean staged)
+{
+	GitgRevision *revision;
+	gchar const *subject;
+	struct timeval tv;
+	
+	gettimeofday(&tv, NULL);
+	
+	if (staged)
+		subject = _("Staged changes");
+	else
+		subject = _("Unstaged changes");
+
+	revision = gitg_revision_new("0000000000000000000000000000000000000000", "", subject, NULL, tv.tv_sec);
+	gitg_revision_set_sign(revision, staged ? 't' : 'u');
+
+	append_revision(repository, revision);
+}
+
+static void
+on_loader_end_loading(GitgRunner *object, gboolean cancelled, GitgRepository *repository)
+{
+	if (cancelled)
+		return;
+
+	LoadStage current = repository->priv->load_stage++;
+
+	switch (current)
+	{
+		case LOAD_STAGE_STASH:
+		case LOAD_STAGE_STAGED:
+		{
+			/* Check if there are staged changes */
+			gchar *head = gitg_repository_parse_head(repository);
+			const gchar *cached = NULL;
+			
+			if (current == LOAD_STAGE_STAGED)
+			{
+				/* Check if there are unstaged changes */
+				if (gitg_runner_get_exit_status(object) != 0)
+				{
+					add_dummy_commit(repository, TRUE);
+				}
+			}
+			else
+			{
+				cached = "--cached";
+			}
+			
+			gitg_repository_run_commandv(repository, object, NULL, "diff-index", "--quiet", head, cached, NULL);
+			g_free(head);
+		}
+		break;
+		case LOAD_STAGE_UNSTAGED:
+			if (gitg_runner_get_exit_status(object) != 0)
+			{
+				add_dummy_commit(repository, FALSE);
+			}
+
+			gitg_repository_run_command(repository, object, (gchar const **)repository->priv->last_args, NULL);
+
+		break;
+		default:
+		break;
+	}
+}
+
+static void
+loader_update_stash(GitgRepository *repository, gchar **buffer)
+{
+	gchar *line;
+	
+	while ((line = *buffer++) != NULL)
+	{
+		gchar **components = g_strsplit(line, "\01", 0);
+		guint len = g_strv_length(components);
+		
+		if (len < 4)
+		{
+			g_strfreev(components);
+			continue;
+		}
+		
+		/* components -> [hash, author, subject, timestamp] */
+		gint64 timestamp = g_ascii_strtoll(components[3], NULL, 0);
+		GitgRevision *rv = gitg_revision_new(components[0], components[1], components[2], NULL, timestamp);
+		
+		gitg_revision_set_sign(rv, 's');
+		append_revision(repository, rv);
+		g_strfreev(components);
+	}
+}
+
+static void
+loader_update_commits(GitgRepository *self, gchar **buffer)
 {
 	gchar *line;
 	
@@ -454,22 +577,32 @@ on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *self)
 		if (len > 5 && strlen(components[5]) == 1 && strchr("<>-^", *components[5]) != NULL)
 			gitg_revision_set_sign(rv, *components[5]);
 
-		gint8 mylane = 0;
-		
-		if (self->priv->size == 0)
-			gitg_lanes_reset(self->priv->lanes);
-
-		lanes = gitg_lanes_next(self->priv->lanes, rv, &mylane);
-		gitg_revision_set_lanes(rv, lanes, mylane);
-
-		gitg_repository_add(self, rv, NULL);
-
-		gitg_revision_unref(rv);
+		append_revision(self, rv);
 		g_strfreev(components);
 	}
 }
 
 static void
+on_loader_update(GitgRunner *object, gchar **buffer, GitgRepository *repository)
+{
+	switch (repository->priv->load_stage)
+	{
+		case LOAD_STAGE_STASH:
+			loader_update_stash(repository, buffer);
+		break;
+		case LOAD_STAGE_STAGED:
+		break;
+		case LOAD_STAGE_UNSTAGED:
+		break;
+		case LOAD_STAGE_COMMITS:
+			loader_update_commits(repository, buffer);
+		break;
+		default:
+		break;
+	}
+}
+
+static void
 free_refs(GSList *refs)
 {
 	g_slist_foreach(refs, (GFunc)gitg_ref_free, NULL);
@@ -591,6 +724,7 @@ gitg_repository_init(GitgRepository *object)
 	
 	object->priv->loader = gitg_runner_new(10000);
 	g_signal_connect(object->priv->loader, "update", G_CALLBACK(on_loader_update), object);
+	g_signal_connect(object->priv->loader, "end-loading", G_CALLBACK(on_loader_end_loading), object);
 	
 	initialize_lanes_bindings(object);
 }
@@ -666,8 +800,10 @@ static gboolean
 reload_revisions(GitgRepository *repository, GError **error)
 {
 	g_signal_emit(repository, repository_signals[LOAD], 0);
+	
+	repository->priv->load_stage = LOAD_STAGE_STASH;
 
-	return gitg_repository_run_command(repository, repository->priv->loader, (gchar const **)repository->priv->last_args, error);
+	return gitg_repository_run_commandv(repository, repository->priv->loader, error, "log", "--pretty=format:%H\x01%an\x01%s\x01%at", "-g", "refs/stash", NULL);
 }
 
 static gboolean
@@ -747,13 +883,17 @@ load_refs(GitgRepository *self)
 		gchar **components = g_strsplit(buf, " ", 3);
 		guint len = g_strv_length(components);
 		
-		if (len == 2 || len == 3)
+		/* Skip refs/stash */
+		if (strcmp(components[0], "refs/stash") != 0)
 		{
-			gchar const *obj = len == 3 && *components[2] ? components[2] : components[1];
-			GitgRef *ref = add_ref(self, obj, components[0]);
+			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 && strncmp(obj, current, strlen(current)) == 0)
-				self->priv->current_ref = gitg_ref_copy(ref);
+				if (current != NULL && strncmp(obj, current, strlen(current)) == 0)
+					self->priv->current_ref = gitg_ref_copy(ref);
+			}
 		}
 		
 		g_strfreev(components);
@@ -794,7 +934,7 @@ gitg_repository_load(GitgRepository *self, int argc, gchar const **av, GError **
 	
 	/* first get the refs */
 	load_refs(self);
-
+	
 	/* request log (all the revision) */
 	return load_revisions(self, argc, av, error);
 }
diff --git a/gitg/gitg-revision-view.c b/gitg/gitg-revision-view.c
index 02c3e3d..7d03b32 100644
--- a/gitg/gitg-revision-view.c
+++ b/gitg/gitg-revision-view.c
@@ -450,7 +450,9 @@ on_diff_files_end_loading(GitgRunner *runner, gboolean cancelled, GitgRevisionVi
 static gboolean
 match_indices(DiffFile *f, gchar const *from, gchar const *to)
 {
-	return g_str_has_prefix(f->index_from, from) && g_str_has_prefix(f->index_to, to);
+	return g_str_has_prefix(f->index_from, from) && 
+	       (g_str_has_prefix(f->index_to, to) ||
+	        g_str_has_prefix(f->index_to, "0000000"));
 }
 
 static void
@@ -463,6 +465,8 @@ visible_from_cached_headers(GitgRevisionView *view, DiffFile *f)
 		CachedHeader *header = (CachedHeader *)item->data;
 		gchar *from;
 		gchar *to;
+		
+		gitg_diff_iter_get_index(&header->iter, &from, &to);
 
 		if (gitg_diff_iter_get_index(&header->iter, &from, &to) && match_indices(f, from, to))
 		{
@@ -507,7 +511,8 @@ on_diff_files_update(GitgRunner *runner, gchar **buffer, GitgRevisionView *self)
 
 			g_strfreev(files);
 		}
-		
+		else
+
 		g_strfreev(parts);
 	}
 }
@@ -525,7 +530,24 @@ on_diff_end_loading(GitgRunner *runner, gboolean cancelled, GitgRevisionView *se
 {
 	gdk_window_set_cursor(GTK_WIDGET(self->priv->diff)->window, NULL);
 	
-	if (!cancelled)
+	if (cancelled)
+		return;
+
+	gchar sign = gitg_revision_get_sign(self->priv->revision);
+	
+	if (sign == 't' || sign == 'u')
+	{
+		gchar *head = gitg_repository_parse_head(self->priv->repository);
+		const gchar *cached = NULL;
+		
+		if (sign == 't')
+			cached == "--cached";
+
+		gitg_repository_run_commandv(self->priv->repository, self->priv->diff_files_runner, NULL,
+									"diff-index", "--raw", "-M", "--abbrev=40", head, cached, NULL);
+		g_free(head);
+	}
+	else
 	{
 		gchar *sha = gitg_revision_get_sha1(self->priv->revision);
 		gitg_repository_run_commandv(self->priv->repository, self->priv->diff_files_runner, NULL,
@@ -685,12 +707,31 @@ update_diff(GitgRevisionView *self, GitgRepository *repository)
 	if (!self->priv->revision)
 		return;
 
-	gchar *hash = gitg_revision_get_sha1(self->priv->revision);
-	gitg_repository_run_commandv(self->priv->repository, self->priv->diff_runner, NULL,
-								 "show", "-M", "--pretty=format:%s%n%n%b", 
-								 "--encoding=UTF-8", hash, NULL);
+	gchar sign = gitg_revision_get_sign(self->priv->revision);
+	
+	switch (sign)
+	{
+		case 't':
+			gitg_repository_run_commandv(self->priv->repository, self->priv->diff_runner, NULL,
+										"diff", "--cached", "-M", "--pretty=format:%s%n%n%b",
+										"--encoding=UTF-8", NULL);
+		break;
+		case 'u':
+			gitg_repository_run_commandv(self->priv->repository, self->priv->diff_runner, NULL,
+										"diff", "-M", "--pretty=format:%s%n%n%b",
+										"--encoding=UTF-8", NULL);
+		break;
+		default:
+		{
+			gchar *hash = gitg_revision_get_sha1(self->priv->revision);
+			gitg_repository_run_commandv(self->priv->repository, self->priv->diff_runner, NULL,
+										 "show", "-M", "--pretty=format:%s%n%n%b", 
+										 "--encoding=UTF-8", hash, NULL);
 
-	g_free(hash);
+			g_free(hash);
+		}
+		break;
+	}
 }
 
 void
@@ -831,7 +872,6 @@ foreach_selection_changed(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *i
 	DiffFile *f = NULL;
 	gtk_tree_model_get(model, iter, 0, &f, -1);
 	
-	
 	if (f->visible)
 	{
 		gitg_diff_iter_set_visible(&f->iter, visible);
@@ -845,6 +885,6 @@ static void
 on_diff_files_selection_changed(GtkTreeSelection *selection, GitgRevisionView *self)
 {
 	ForeachSelectionData data = {gtk_tree_selection_count_selected_rows(selection), selection};
-	gtk_tree_model_foreach(GTK_TREE_MODEL(self->priv->list_store_diff_files), (GtkTreeModelForeachFunc)foreach_selection_changed, &data);
+	gtk_tree_model_foreach(gtk_tree_view_get_model(self->priv->diff_files), (GtkTreeModelForeachFunc)foreach_selection_changed, &data);
 }
 
diff --git a/gitg/gitg-revision.c b/gitg/gitg-revision.c
index 4c8fdb1..479da26 100644
--- a/gitg/gitg-revision.c
+++ b/gitg/gitg-revision.c
@@ -97,16 +97,19 @@ GitgRevision *gitg_revision_new(gchar const *sha,
 	rv->subject = g_strdup(subject);
 	rv->timestamp = timestamp;
 	
-	gchar **shas = g_strsplit(parents, " ", 0);
-	gint num = g_strv_length(shas);
-	rv->parents = g_new(Hash, num + 1);
+	if (parents)
+	{
+		gchar **shas = g_strsplit(parents, " ", 0);
+		gint num = g_strv_length(shas);
+		rv->parents = g_new(Hash, num + 1);
 	
-	int i;
-	for (i = 0; i < num; ++i)
-		gitg_utils_sha1_to_hash(shas[i], rv->parents[i]);
+		gint i;
+		for (i = 0; i < num; ++i)
+			gitg_utils_sha1_to_hash(shas[i], rv->parents[i]);
 	
-	g_strfreev(shas);
-	rv->num_parents = num;
+		g_strfreev(shas);
+		rv->num_parents = num;
+	}
 	
 	return rv;
 }
@@ -203,12 +206,30 @@ update_lane_type(GitgRevision *revision)
 	if (lane == NULL)
 		return;
 	
-	lane->type &= ~(GITG_LANE_SIGN_LEFT | GITG_LANE_SIGN_RIGHT);
+	lane->type &= ~(GITG_LANE_SIGN_LEFT | 
+	                GITG_LANE_SIGN_RIGHT | 
+	                GITG_LANE_SIGN_STASH |
+	                GITG_LANE_SIGN_STAGED |
+	                GITG_LANE_SIGN_UNSTAGED);
 	
-	if (revision->sign == '<')
-		lane->type |= GITG_LANE_SIGN_LEFT;
-	else if (revision->sign == '>')
-		lane->type |= GITG_LANE_SIGN_RIGHT;
+	switch (revision->sign)
+	{
+		case '<':
+			lane->type |= GITG_LANE_SIGN_LEFT;
+		break;
+		case '>':
+			lane->type |= GITG_LANE_SIGN_RIGHT;
+		break;
+		case 's':
+			lane->type |= GITG_LANE_SIGN_STASH;
+		break;
+		case 't':
+			lane->type |= GITG_LANE_SIGN_STAGED;
+		break;
+		case 'u':
+			lane->type |= GITG_LANE_SIGN_UNSTAGED;
+		break;
+	}
 }
 
 void 
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 47ddc95..d1632d1 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -262,9 +262,39 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT
 	if (gtk_tree_model_iter_next(model, &iter1))
 		gtk_tree_model_get(model, &iter1, 0, &next_revision, -1);
 	
-	GSList *labels = gitg_repository_get_refs_for_hash(GITG_REPOSITORY(model), gitg_revision_get_hash(rv));
+	GSList *labels;
+	const gchar *lbl = NULL;
+	switch (gitg_revision_get_sign(rv))
+	{
+
+		case 's':
+			lbl = "stash";
+		break;
+		case 't':
+			lbl = "staged";
+		break;
+		case 'u':
+			lbl = "unstaged";
+		break;
+		default:
+		break;
+	}
+	
+	if (lbl != NULL)
+	{
+		g_object_set(renderer, "style", PANGO_STYLE_ITALIC, NULL);
+		labels = g_slist_append(NULL, gitg_ref_new(gitg_revision_get_hash(rv), lbl));
+	}
+	else
+	{
+		labels = gitg_repository_get_refs_for_hash(GITG_REPOSITORY(model), gitg_revision_get_hash(rv));
+	}
 
-	g_object_set(renderer, "revision", rv, "next_revision", next_revision, "labels", labels, NULL);
+	g_object_set(renderer, 
+	             "revision", rv, 
+	             "next_revision", next_revision, 
+	             "labels", labels,
+	             NULL);
 
 	gitg_revision_unref(next_revision);
 	gitg_revision_unref(rv);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]