[gitg] Factor out common action functionality



commit bac2c9843bcbd1b7acd96c037551bdbbb91c7345
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Fri Aug 14 08:30:33 2015 +0200

    Factor out common action functionality

 gitg/Makefile.am                |    1 +
 gitg/gitg-action-support.vala   |  189 +++++++++++++++++++++++++++++++++
 gitg/gitg-ref-action-merge.vala |  218 ++++++++-------------------------------
 po/POTFILES.in                  |    1 +
 po/POTFILES.skip                |    2 +
 tests/gitg/Makefile.am          |    3 +-
 6 files changed, 237 insertions(+), 177 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index d3d70e8..5cdbaa1 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -55,6 +55,7 @@ gitg_gitg_VALASOURCES =                                               \
        gitg/commit/gitg-commit-submodule-history-view.vala     \
        gitg/commit/gitg-commit-submodule-info.vala             \
        gitg/commit/gitg-commit.vala                            \
+       gitg/gitg-action-support.vala                           \
        gitg/gitg-animated-paned.vala                           \
        gitg/gitg-application.vala                              \
        gitg/gitg-author-details-dialog.vala                    \
diff --git a/gitg/gitg-action-support.vala b/gitg/gitg-action-support.vala
new file mode 100644
index 0000000..50ac09b
--- /dev/null
+++ b/gitg/gitg-action-support.vala
@@ -0,0 +1,189 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2015 - Jesse van den Kieboom
+ *
+ * gitg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gitg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gitg. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Gitg
+{
+
+public class ActionSupport : Object
+{
+       // Do this to pull in config.h before glib.h (for gettext...)
+       private const string version = Gitg.Config.VERSION;
+
+       public GitgExt.Application? application { owned get; construct set; }
+       public GitgExt.RefActionInterface action_interface { owned get; construct set; }
+
+       public ActionSupport(GitgExt.Application application, GitgExt.RefActionInterface action_interface)
+       {
+               Object(application: application, action_interface: action_interface);
+       }
+
+       public async bool working_directory_dirty()
+       {
+               var options = new Ggit.StatusOptions(0, Ggit.StatusShow.WORKDIR_ONLY, null);
+               var is_dirty = false;
+
+               yield Async.thread_try(() => {
+                       application.repository.file_status_foreach(options, (path, flags) => {
+                               is_dirty = true;
+                               return -1;
+                       });
+               });
+
+               return is_dirty;
+       }
+
+       public async bool save_stash(SimpleNotification notification, Gitg.Ref? head)
+       {
+               var committer = application.get_verified_committer();
+
+               if (committer == null)
+               {
+                       return false;
+               }
+
+               try
+               {
+                       yield Async.thread(() => {
+                               // Try to stash changes
+                               string message;
+
+                               if (head != null)
+                               {
+                                       var headname = head.parsed_name.shortname;
+
+                                       try
+                                       {
+                                               var head_commit = head.resolve().lookup() as Ggit.Commit;
+                                               var shortid = head_commit.get_id().to_string()[0:6];
+                                               var subject = head_commit.get_subject();
+
+                                               message = @"WIP on $(headname): $(shortid) $(subject)";
+                                       }
+                                       catch
+                                       {
+                                               message = @"WIP on $(headname)";
+                                       }
+                               }
+                               else
+                               {
+                                       message = "WIP on HEAD";
+                               }
+
+                               application.repository.save_stash(committer, message, 
Ggit.StashFlags.DEFAULT);
+                       });
+               }
+               catch (Error err)
+               {
+                       notification.error(_("Failed to stash changes: %s").printf(err.message));
+                       return false;
+               }
+
+               return true;
+       }
+
+       public bool reference_is_head(Gitg.Ref reference, ref Gitg.Ref? head)
+       {
+               var branch = reference as Ggit.Branch;
+               head = null;
+
+               if (branch == null)
+               {
+                       return false;
+               }
+
+               try
+               {
+                       if (!branch.is_head())
+                       {
+                               return false;
+                       }
+
+                       head = application.repository.lookup_reference("HEAD");
+               } catch {}
+
+               return head != null;
+       }
+
+       public async bool stash_if_needed(SimpleNotification notification, Gitg.Ref head)
+       {
+               // Offer to stash if there are any local changes
+               if ((yield working_directory_dirty()))
+               {
+                       var q = new GitgExt.UserQuery.full(_("Unstaged changes"),
+                                                          _("You appear to have unstaged changes in your 
working directory. Would you like to stash the changes before the checkout?"),
+                                                          Gtk.MessageType.QUESTION,
+                                                          _("Cancel"), Gtk.ResponseType.CANCEL,
+                                                          _("Stash changes"), Gtk.ResponseType.OK);
+
+                       if ((yield application.user_query_async(q)) != Gtk.ResponseType.OK)
+                       {
+                               notification.error(_("Merge failed with conflicts"));
+                               return false;
+                       }
+
+                       if (!(yield save_stash(notification, head)))
+                       {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       public async bool checkout_conflicts(SimpleNotification notification, Gitg.Ref reference, Ggit.Index 
index, Gitg.Ref source, Gitg.Ref? head)
+       {
+               if (!(yield stash_if_needed(notification, head)))
+               {
+                       return false;
+               }
+
+               if (head == null)
+               {
+                       // Perform checkout of the local branch first
+                       var checkout = new RefActionCheckout(application, action_interface, reference);
+
+                       if (!(yield checkout.checkout()))
+                       {
+                               notification.error(_("Failed with conflicts"));
+                               return false;
+                       }
+               }
+
+               // Finally, checkout the conflicted index
+               try
+               {
+                       yield Async.thread(() => {
+                               var opts = new Ggit.CheckoutOptions();
+                               opts.set_strategy(Ggit.CheckoutStrategy.SAFE);
+                               application.repository.checkout_index(index, opts);
+                       });
+               }
+               catch (Error err)
+               {
+                       notification.error(_("Failed to checkout conflicts: %s").printf(err.message));
+                       return false;
+               }
+
+               return true;
+       }
+}
+
+}
+
+// ex:set ts=4 noet
diff --git a/gitg/gitg-ref-action-merge.vala b/gitg/gitg-ref-action-merge.vala
index 346fa82..a368294 100644
--- a/gitg/gitg-ref-action-merge.vala
+++ b/gitg/gitg-ref-action-merge.vala
@@ -40,6 +40,7 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
        private Gitg.Ref[]? d_local_sources;
        private RemoteSource[]? d_remote_sources;
        private Gitg.Ref[]? d_tag_sources;
+       private ActionSupport d_support;
 
        public RefActionMerge(GitgExt.Application        application,
                              GitgExt.RefActionInterface action_interface,
@@ -48,6 +49,8 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
                Object(application:      application,
                       action_interface: action_interface,
                       reference:        reference);
+
+               d_support = new ActionSupport(application, action_interface);
        }
 
        public string id
@@ -108,117 +111,60 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
                return index;
        }
 
-       private async bool working_directory_dirty()
-       {
-               var options = new Ggit.StatusOptions(0, Ggit.StatusShow.WORKDIR_ONLY, null);
-               var is_dirty = false;
-
-               yield Async.thread_try(() => {
-                       application.repository.file_status_foreach(options, (path, flags) => {
-                               is_dirty = true;
-                               return -1;
-                       });
-               });
-
-               return is_dirty;
-       }
-
-       private async bool save_stash(SimpleNotification notification, Gitg.Ref? head)
+       private void write_merge_state_files(Ggit.Index index, Gitg.Ref source)
        {
-               var committer = application.get_verified_committer();
-
-               if (committer == null)
-               {
-                       return false;
-               }
+               var wd = application.repository.get_location().get_path();
+               var theirs_name = source.parsed_name.shortname;
 
                try
                {
-                       yield Async.thread(() => {
-                               // Try to stash changes
-                               string message;
-
-                               if (head != null)
-                               {
-                                       var headname = head.parsed_name.shortname;
-
-                                       try
-                                       {
-                                               var head_commit = head.resolve().lookup() as Ggit.Commit;
-                                               var shortid = head_commit.get_id().to_string()[0:6];
-                                               var subject = head_commit.get_subject();
-
-                                               message = @"WIP on $(headname): $(shortid) $(subject)";
-                                       }
-                                       catch
-                                       {
-                                               message = @"WIP on $(headname)";
-                                       }
-                               }
-                               else
-                               {
-                                       message = "WIP on HEAD";
-                               }
+                       var dest_oid = reference.resolve().get_target();
+                       FileUtils.set_contents(Path.build_filename(wd, "ORIG_HEAD"), 
"%s\n".printf(dest_oid.to_string()));
+               } catch {}
 
-                               application.repository.save_stash(committer, message, 
Ggit.StashFlags.DEFAULT);
-                       });
-               }
-               catch (Error err)
+               try
                {
-                       notification.error(_("Failed to stash changes: %s").printf(err.message));
-                       return false;
-               }
-
-               return true;
-       }
-
-       private bool reference_is_head(ref Gitg.Ref? head)
-       {
-               var branch = reference as Ggit.Branch;
-               head = null;
+                       var source_oid = source.resolve().get_target();
+                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_HEAD"), 
"%s\n".printf(source_oid.to_string()));
+               } catch {}
 
-               if (branch == null)
+               try
                {
-                       return false;
-               }
+                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_MODE"), "no-ff\n");
+               } catch {}
 
                try
                {
-                       if (!branch.is_head())
+                       string msg;
+
+                       if (source.parsed_name.rtype == RefType.REMOTE)
                        {
-                               return false;
+                               msg = @"Merge remote branch '$theirs_name'";
+                       }
+                       else
+                       {
+                               msg = @"Merge branch '$theirs_name'";
                        }
 
-                       head = application.repository.lookup_reference("HEAD");
-               } catch {}
-
-               return head != null;
-       }
+                       msg += "\n\nConflicts:\n";
 
-       private async bool stash_if_needed(SimpleNotification notification, Gitg.Ref head)
-       {
-               // Offer to stash if there are any local changes
-               if ((yield working_directory_dirty()))
-               {
-                       var q = new GitgExt.UserQuery.full(_("Unstaged changes"),
-                                                          _("You appear to have unstaged changes in your 
working directory. Would you like to stash the changes before the checkout?"),
-                                                          Gtk.MessageType.QUESTION,
-                                                          _("Cancel"), Gtk.ResponseType.CANCEL,
-                                                          _("Stash changes"), Gtk.ResponseType.OK);
+                       var entries = index.get_entries();
+                       var seen = new Gee.HashSet<string>();
 
-                       if ((yield application.user_query_async(q)) != Gtk.ResponseType.OK)
+                       for (var i = 0; i < entries.size(); i++)
                        {
-                               notification.error(_("Merge failed with conflicts"));
-                               return false;
-                       }
+                               var entry = entries.get_by_index(i);
+                               var p = entry.get_path();
 
-                       if (!(yield save_stash(notification, head)))
-                       {
-                               return false;
+                               if (entry.is_conflict() && !seen.contains(p))
+                               {
+                                       msg += "\t%s\n".printf(p);
+                                       seen.add(p);
+                               }
                        }
-               }
 
-               return true;
+                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_MSG"), msg);
+               } catch {}
        }
 
        private async bool checkout_conflicts(SimpleNotification notification, Ggit.Index index, Gitg.Ref 
source)
@@ -229,7 +175,7 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
                notification.message = _("Merge has conflicts");
 
                Gitg.Ref? head = null;
-               var ishead = reference_is_head(ref head);
+               var ishead = d_support.reference_is_head(reference, ref head);
 
                string message;
 
@@ -254,92 +200,12 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
                        return false;
                }
 
-               if (!(yield stash_if_needed(notification, head)))
-               {
-                       return false;
-               }
-
-               if (!ishead)
-               {
-                       // Perform checkout of the local branch first
-                       var checkout = new RefActionCheckout(application, action_interface, reference);
-
-                       if (!(yield checkout.checkout()))
-                       {
-                               notification.error(_("Merge failed with conflicts"));
-                               return false;
-                       }
-               }
-
-               // Finally, checkout the conflicted index
-               try
-               {
-                       yield Async.thread(() => {
-                               var opts = new Ggit.CheckoutOptions();
-                               opts.set_strategy(Ggit.CheckoutStrategy.SAFE);
-                               application.repository.checkout_index(index, opts);
-                       });
-               }
-               catch (Error err)
+               if (!(yield d_support.checkout_conflicts(notification, reference, index, source, head)))
                {
-                       notification.error(_("Failed to checkout conflicts: %s").printf(err.message));
                        return false;
                }
 
-               // Write the merge state files
-               var wd = application.repository.get_location().get_path();
-
-               try
-               {
-                       var dest_oid = reference.resolve().get_target();
-
-                       FileUtils.set_contents(Path.build_filename(wd, "ORIG_HEAD"), 
"%s\n".printf(dest_oid.to_string()));
-               } catch {}
-
-               try
-               {
-                       var source_oid = source.resolve().get_target();
-
-                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_HEAD"), 
"%s\n".printf(source_oid.to_string()));
-               } catch {}
-
-               try
-               {
-                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_MODE"), "no-ff\n");
-               } catch {}
-
-               try
-               {
-                       string msg;
-
-                       if (source.parsed_name.rtype == RefType.REMOTE)
-                       {
-                               msg = @"Merge remote branch '$theirs_name'";
-                       }
-                       else
-                       {
-                               msg = @"Merge branch '$theirs_name'";
-                       }
-
-                       msg += "\n\nConflicts:\n";
-
-                       var entries = index.get_entries();
-                       var seen = new Gee.HashSet<string>();
-
-                       for (var i = 0; i < entries.size(); i++)
-                       {
-                               var entry = entries.get_by_index(i);
-                               var p = entry.get_path();
-
-                               if (entry.is_conflict() && !seen.contains(p))
-                               {
-                                       msg += "\t%s\n".printf(p);
-                                       seen.add(p);
-                               }
-                       }
-
-                       FileUtils.set_contents(Path.build_filename(wd, "MERGE_MSG"), msg);
-               } catch {}
+               write_merge_state_files(index, source);
 
                notification.success(_("Finished merge with conflicts in working directory"));
                return true;
@@ -411,14 +277,14 @@ class RefActionMerge : GitgExt.UIElement, GitgExt.Action, GitgExt.RefAction, Obj
                var stage = application.repository.stage;
 
                Gitg.Ref? head = null;
-               var ishead = reference_is_head(ref head);
+               var ishead = d_support.reference_is_head(reference, ref head);
 
                Ggit.OId? oid = null;
                Ggit.Tree? head_tree = null;
 
                if (ishead)
                {
-                       if (!(yield stash_if_needed(notification, head)))
+                       if (!(yield d_support.stash_if_needed(notification, head)))
                        {
                                return null;
                        }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f359c33..a25d51f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,6 +5,7 @@ data/gitg.desktop.in.in
 data/org.gnome.gitg.gschema.xml.in.in
 gitg/commit/gitg-commit-dialog.vala
 gitg/commit/gitg-commit.vala
+gitg/gitg-action-support.vala
 gitg/gitg-application.vala
 gitg/gitg-author-details-dialog.vala
 gitg/gitg-clone-dialog.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 6c93760..6c4f38b 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -4,6 +4,7 @@ sub/data/gitg.desktop.in
 sub/data/org.gnome.gitg.gschema.xml.in
 gitg/commit/gitg-commit.c
 gitg/commit/gitg-commit-dialog.c
+gitg/gitg-action-support.c
 gitg/gitg-application.c
 gitg/gitg-author-details-dialog.c
 gitg/gitg.c
@@ -39,3 +40,4 @@ plugins/diff/gitg-diff.c
 plugins/files/gitg-files.c
 tests/gitg/gitg-ref-action-checkout.c
 tests/gitg/gitg-ref-action-merge.c
+tests/gitg/gitg-action-support.c
diff --git a/tests/gitg/Makefile.am b/tests/gitg/Makefile.am
index 4b8b6f4..b3925ca 100644
--- a/tests/gitg/Makefile.am
+++ b/tests/gitg/Makefile.am
@@ -48,7 +48,8 @@ TESTS_GITG_TEST_GITG_COPIED_SOURCES =                         \
        tests/gitg/support-main.vala                    \
        tests/gitg/support-repository.vala              \
        tests/gitg/gitg-ref-action-checkout.vala        \
-       tests/gitg/gitg-ref-action-merge.vala
+       tests/gitg/gitg-ref-action-merge.vala           \
+       tests/gitg/gitg-action-support.vala
 
 tests_gitg_test_gitg_SOURCES =                         \
        tests/gitg/main.vala                            \


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