[gitg] Factor out common action functionality
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg] Factor out common action functionality
- Date: Fri, 14 Aug 2015 06:32:05 +0000 (UTC)
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]