[gitg/wip/fetch: 6/9] Add remote management
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg/wip/fetch: 6/9] Add remote management
- Date: Tue, 23 Dec 2014 17:37:49 +0000 (UTC)
commit 1a8960b3fca5b0cebf0d69fa9044ef52726eb87b
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Tue Dec 23 17:39:18 2014 +0100
Add remote management
gitg/Makefile.am | 1 +
gitg/gitg-remote-manager.vala | 214 +++++++++++++++++++++++++++++++
gitg/gitg-window.vala | 11 ++
libgitg-ext/Makefile.am | 1 +
libgitg-ext/gitg-ext-application.vala | 2 +
libgitg-ext/gitg-ext-remote-lookup.vala | 30 +++++
libgitg/Makefile.am | 3 +-
libgitg/gitg-init.vala | 3 +
libgitg/gitg-remote.vala | 183 ++++++++++++++++++++++++++
9 files changed, 447 insertions(+), 1 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index 7654b40..5ec9391 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -69,6 +69,7 @@ gitg_gitg_VALASOURCES = \
gitg/gitg-commit-action-create-tag.vala \
gitg/gitg-create-tag-dialog.vala \
gitg/gitg-commit-action-create-patch.vala \
+ gitg/gitg-remote-manager.vala \
gitg/preferences/gitg-preferences-commit.vala \
gitg/preferences/gitg-preferences-dialog.vala \
gitg/preferences/gitg-preferences-interface.vala \
diff --git a/gitg/gitg-remote-manager.vala b/gitg/gitg-remote-manager.vala
new file mode 100644
index 0000000..ed67160
--- /dev/null
+++ b/gitg/gitg-remote-manager.vala
@@ -0,0 +1,214 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2012 - 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
+{
+
+class RemoteManager : Object, GitgExt.RemoteLookup
+{
+ class CredSshInteractive : Ggit.CredSshInteractive
+ {
+ public CredSshInteractive(string username) throws Error
+ {
+ Object(username: username);
+
+ ((Initable)this).init(null);
+ }
+
+ protected override void prompt(Ggit.CredSshInteractivePrompt[] prompts)
+ {
+ // TODO
+ }
+ }
+
+ class Callbacks : Ggit.RemoteCallbacks
+ {
+ private weak Remote d_remote;
+ private Window d_window;
+
+ public Callbacks(Remote remote, Window window)
+ {
+ d_remote = remote;
+ d_window = window;
+ }
+
+ protected override bool credentials(string url,
+ string username,
+ Ggit.Credtype allowed_types,
+ out Ggit.Cred cred) throws Error
+ {
+ cred = null;
+
+ if ((allowed_types & Ggit.Credtype.SSH_KEY) != 0)
+ {
+ cred = new Ggit.CredSshKeyFromAgent(username);
+ }
+ else if ((allowed_types & Ggit.Credtype.SSH_INTERACTIVE) != 0)
+ {
+ cred = new CredSshInteractive(username);
+ }
+ else if ((allowed_types & Ggit.Credtype.USERPASS_PLAINTEXT) != 0)
+ {
+ // TODO: query for user + pass
+ }
+
+ return cred != null;
+ }
+ }
+
+ struct InsteadOf
+ {
+ string prefix;
+ string replacement;
+ }
+
+ private Gee.HashMap<string, Gitg.Remote> d_remotes;
+ private InsteadOf[] d_insteadof;
+ private Window d_window;
+
+ public RemoteManager(Window window)
+ {
+ d_window = window;
+ d_remotes = new Gee.HashMap<string, Gitg.Remote>();
+
+ extract_insteadof();
+ }
+
+ private void extract_insteadof()
+ {
+ d_insteadof = new InsteadOf[10];
+ d_insteadof.length = 0;
+
+ Ggit.Config config;
+
+ try
+ {
+ config = d_window.repository.get_config();
+ } catch { return; }
+
+ Regex r;
+
+ try
+ {
+ r = new Regex("url\\.(.*)\\.insteadof");
+ }
+ catch (Error e)
+ {
+ stderr.printf("Failed to compile regex: %s\n", e.message);
+ return;
+ }
+
+ try
+ {
+ config.match_foreach(r, (info, value) => {
+ d_insteadof += InsteadOf() {
+ prefix = value,
+ replacement = info.fetch(1)
+ };
+
+ return 0;
+ });
+ } catch {}
+ }
+
+ public Gitg.Remote? lookup(string name)
+ {
+ if (d_window.repository == null)
+ {
+ return null;
+ }
+
+ if (d_remotes == null)
+ {
+ d_remotes = new Gee.HashMap<string, Gitg.Remote>();
+ }
+
+ if (d_remotes.has_key(name))
+ {
+ return d_remotes[name];
+ }
+
+ Gitg.Remote remote;
+
+ try
+ {
+ remote = d_window.repository.get_remote(name) as Gitg.Remote;
+ } catch { return null; }
+
+ var url = remote.get_url();
+
+ foreach (var io in d_insteadof)
+ {
+ if (url.has_prefix(io.prefix))
+ {
+ url = io.replacement + url.substring(io.prefix.length);
+
+ string[] fetch_specs;
+ string[] push_specs;
+
+ try
+ {
+ fetch_specs = remote.get_fetch_specs();
+ } catch { break; }
+
+ try
+ {
+ push_specs = remote.get_push_specs();
+ } catch { break; }
+
+ var defspec = "+refs/heads/*:refs/remotes/" + name + "/*";
+ Gitg.Remote? tmp = null;
+
+ try
+ {
+ tmp = (new Ggit.Remote.anonymous(d_window.repository, url, defspec))
as Gitg.Remote;
+ }
+ catch (Error e)
+ {
+ stderr.printf("Failed to create remote: %s\n", e.message);
+ }
+
+ if (tmp == null)
+ {
+ break;
+ }
+
+ try
+ {
+ tmp.set_fetch_specs(fetch_specs);
+ } catch { break; }
+
+ try
+ {
+ tmp.set_push_specs(push_specs);
+ } catch { break; }
+
+ remote = tmp;
+ break;
+ }
+ }
+
+ remote.set_callbacks(new Callbacks(remote, d_window));
+
+ d_remotes[name] = remote;
+ return remote;
+ }
+}
+
+}
diff --git a/gitg/gitg-window.vala b/gitg/gitg-window.vala
index b6f92b1..a2e6633 100644
--- a/gitg/gitg-window.vala
+++ b/gitg/gitg-window.vala
@@ -38,6 +38,8 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
private UIElements<GitgExt.Activity> d_activities;
+ private RemoteManager d_remote_manager;
+
// Widgets
[GtkChild]
private Gtk.HeaderBar d_header_bar;
@@ -333,6 +335,7 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
set
{
d_repository = value;
+ d_remote_manager = new RemoteManager(this);
notify_property("repository");
repository_changed();
@@ -487,6 +490,8 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
d_repository = new Gitg.Repository(this.repository.get_location(),
null);
+ d_remote_manager = new RemoteManager(this);
+
notify_property("repository");
update_title();
}
@@ -698,6 +703,7 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
{
ret.application = app;
ret.d_repository = repository;
+ ret.d_remote_manager = new RemoteManager(ret);
ret.d_action = action;
}
@@ -935,6 +941,11 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
selectable_mode = GitgExt.SelectionMode.NORMAL;
}
}
+
+ public GitgExt.RemoteLookup remote_lookup
+ {
+ owned get { return d_remote_manager; }
+ }
}
}
diff --git a/libgitg-ext/Makefile.am b/libgitg-ext/Makefile.am
index babe367..5833173 100644
--- a/libgitg-ext/Makefile.am
+++ b/libgitg-ext/Makefile.am
@@ -57,6 +57,7 @@ libgitg_ext_libgitg_ext_1_0_la_VALASOURCES = \
libgitg-ext/gitg-ext-history-panel.vala \
libgitg-ext/gitg-ext-command-line.vala \
libgitg-ext/gitg-ext-preferences.vala \
+ libgitg-ext/gitg-ext-remote-lookup.vala \
libgitg-ext/gitg-ext-searchable.vala \
libgitg-ext/gitg-ext-selectable.vala \
libgitg-ext/gitg-ext-ui.vala \
diff --git a/libgitg-ext/gitg-ext-application.vala b/libgitg-ext/gitg-ext-application.vala
index 379647f..c5350cd 100644
--- a/libgitg-ext/gitg-ext-application.vala
+++ b/libgitg-ext/gitg-ext-application.vala
@@ -66,6 +66,8 @@ public interface Application : Object
public abstract Gee.Map<string, string> environment { owned get; }
public abstract Application open_new(Ggit.Repository repository, string? hint = null);
+
+ public abstract RemoteLookup remote_lookup { owned get; }
}
}
diff --git a/libgitg-ext/gitg-ext-remote-lookup.vala b/libgitg-ext/gitg-ext-remote-lookup.vala
new file mode 100644
index 0000000..58b392f
--- /dev/null
+++ b/libgitg-ext/gitg-ext-remote-lookup.vala
@@ -0,0 +1,30 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2014 - 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 GitgExt
+{
+
+public interface RemoteLookup : Object
+{
+ public abstract Gitg.Remote? lookup(string name);
+}
+
+}
+
+// ex:set ts=4 noet:
diff --git a/libgitg/Makefile.am b/libgitg/Makefile.am
index 5eb7b91..26c58eb 100644
--- a/libgitg/Makefile.am
+++ b/libgitg/Makefile.am
@@ -72,7 +72,8 @@ libgitg_libgitg_1_0_la_VALASOURCES = \
libgitg/gitg-hook.vala \
libgitg/gitg-date.vala \
libgitg/gitg-avatar-cache.vala \
- libgitg/gitg-diff-stat.vala
+ libgitg/gitg-diff-stat.vala \
+ libgitg/gitg-remote.vala
libgitg_libgitg_1_0_la_SOURCES = \
$(libgitg_libgitg_1_0_la_VALASOURCES) \
diff --git a/libgitg/gitg-init.vala b/libgitg/gitg-init.vala
index ad3d2d3..63d8df5 100644
--- a/libgitg/gitg-init.vala
+++ b/libgitg/gitg-init.vala
@@ -65,6 +65,9 @@ public void init() throws Error
factory.register(typeof(Ggit.Commit),
typeof(Gitg.Commit));
+
+ factory.register(typeof(Ggit.Remote),
+ typeof(Gitg.Remote));
}
}
diff --git a/libgitg/gitg-remote.vala b/libgitg/gitg-remote.vala
new file mode 100644
index 0000000..df7763c
--- /dev/null
+++ b/libgitg/gitg-remote.vala
@@ -0,0 +1,183 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2014 - 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 enum RemoteState
+{
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ TRANSFERRING
+}
+
+public errordomain RemoteError
+{
+ ALREADY_CONNECTED,
+ ALREADY_CONNECTING,
+ ALREADY_DISCONNECTED,
+ STILL_CONNECTING
+}
+
+public class Remote : Ggit.Remote
+{
+ private RemoteState d_state;
+
+ public RemoteState state
+ {
+ get { return d_state; }
+ private set
+ {
+ if (d_state != value)
+ {
+ d_state = value;
+ notify_property("state");
+ }
+ }
+ }
+
+ private void update_state(bool force_disconnect = false)
+ {
+ if (get_connected())
+ {
+ if (force_disconnect)
+ {
+ disconnect.begin((obj, res) => {
+ try
+ {
+ disconnect.end(res);
+ } catch {}
+ });
+ }
+ else
+ {
+ state = RemoteState.CONNECTED;
+ }
+ }
+ else
+ {
+ state = RemoteState.DISCONNECTED;
+ }
+ }
+
+ public new async void connect(Ggit.Direction direction) throws Error
+ {
+ if (get_connected())
+ {
+ if (state != RemoteState.CONNECTED)
+ {
+ state = RemoteState.CONNECTED;
+ }
+
+ throw new RemoteError.ALREADY_CONNECTED("already connected");
+ }
+ else if (state == RemoteState.CONNECTING)
+ {
+ throw new RemoteError.ALREADY_CONNECTING("already connecting");
+ }
+
+ state = RemoteState.CONNECTING;
+
+ try
+ {
+ yield Async.thread(() => {
+ base.connect(direction);
+ });
+ }
+ catch (Error e)
+ {
+ update_state();
+ throw e;
+ }
+
+ update_state();
+ }
+
+ public new async void disconnect() throws Error
+ {
+ if (!get_connected())
+ {
+ if (state != RemoteState.DISCONNECTED)
+ {
+ state = RemoteState.DISCONNECTED;
+ }
+
+ throw new RemoteError.ALREADY_DISCONNECTED("already disconnected");
+ }
+
+ try
+ {
+ yield Async.thread(() => {
+ base.disconnect();
+ });
+ }
+ catch (Error e)
+ {
+ update_state();
+ throw e;
+ }
+
+ update_state();
+ }
+
+ private async void download_intern(Ggit.Signature? signature, string? message) throws Error
+ {
+ bool dis = false;
+
+ if (!get_connected())
+ {
+ dis = true;
+ yield connect(Ggit.Direction.FETCH);
+ }
+
+ state = RemoteState.TRANSFERRING;
+
+ try
+ {
+ yield Async.thread(() => {
+ base.download();
+
+ if (signature != null)
+ {
+ base.update_tips(signature, message);
+ }
+ });
+ }
+ catch (Error e)
+ {
+ update_state(dis);
+ throw e;
+ }
+
+ update_state(dis);
+ }
+
+ public new async void download() throws Error
+ {
+ yield download_intern(null, null);
+ }
+
+ public new async void fetch(Ggit.Signature signature, string? message) throws Error
+ {
+ yield download_intern(signature, message);
+ }
+}
+
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]