Improved GitgRunner/GitgCommand/GitgShell

This commit is contained in:
Jesse van den Kieboom 2010-10-25 09:50:05 +02:00 committed by Jesse van den Kieboom
parent c974834cb2
commit f9ef65b59d
33 changed files with 5275 additions and 2268 deletions

View file

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = libgitg gitg data po
SUBDIRS = libgitg gitg data po tests tools
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libgitg-1.0.pc

View file

@ -144,6 +144,8 @@ data/Makefile
data/gitg.desktop.in
data/icons/Makefile
po/Makefile.in
tests/Makefile
tools/Makefile
])
AC_OUTPUT

View file

@ -38,7 +38,7 @@ typedef void (*ProgressCallback) (GitgWindow *window, GitgProgress progress, gpo
typedef struct
{
GitgWindow *window;
GitgRunner *runner;
GitgShell *shell;
ProgressCallback callback;
gpointer callback_data;
@ -59,7 +59,7 @@ free_progress_info (ProgressInfo *info)
gtk_widget_destroy (GTK_WIDGET (info->dialog));
g_object_unref (info->runner);
g_object_unref (info->shell);
g_slice_free (ProgressInfo, info);
}
@ -81,7 +81,7 @@ parse_valist (va_list ap)
}
static void
on_progress_end (GitgRunner *runner, gboolean cancelled, ProgressInfo *info)
on_progress_end (GitgShell *shell, gboolean cancelled, ProgressInfo *info)
{
GitgProgress progress;
@ -89,7 +89,7 @@ on_progress_end (GitgRunner *runner, gboolean cancelled, ProgressInfo *info)
{
progress = GITG_PROGRESS_CANCELLED;
}
else if (gitg_runner_get_exit_status (runner) != 0)
else if (gitg_io_get_exit_status (GITG_IO (shell)) != 0)
{
progress = GITG_PROGRESS_ERROR;
}
@ -109,7 +109,7 @@ on_progress_end (GitgRunner *runner, gboolean cancelled, ProgressInfo *info)
static void
on_progress_response (GtkDialog *dialog, GtkResponseType response, ProgressInfo *info)
{
gitg_runner_cancel (info->runner);
gitg_io_cancel (GITG_IO (info->shell));
}
static gboolean
@ -119,7 +119,7 @@ on_progress_timeout (ProgressInfo *info)
return TRUE;
}
static GitgRunner *
static GitgShell *
run_progress (GitgWindow *window,
gchar const *title,
gchar const *message,
@ -129,19 +129,18 @@ run_progress (GitgWindow *window,
{
va_list ap;
// Create runner
va_start (ap, callback_data);
GitgRunner *runner = gitg_runner_new (1000);
GitgShell *shell = gitg_shell_new (1000);
gchar const **argv = parse_valist (ap);
if (!gitg_repository_run_command (gitg_window_get_repository (window),
runner,
argv,
NULL))
GitgCommand *cmd = gitg_command_new (gitg_window_get_repository (window),
(gchar const * const *)argv);
if (!gitg_shell_run (shell, cmd, NULL))
{
g_free (argv);
g_object_unref (runner);
g_object_unref (shell);
callback (window, GITG_PROGRESS_ERROR, callback_data);
@ -183,14 +182,14 @@ run_progress (GitgWindow *window,
info->callback = callback;
info->callback_data = callback_data;
info->window = window;
info->runner = g_object_ref (runner);
info->shell = g_object_ref (shell);
info->timeout_id = g_timeout_add (100, (GSourceFunc)on_progress_timeout, info);
g_signal_connect (dlg, "response", G_CALLBACK (on_progress_response), info);
g_signal_connect (runner, "end-loading", G_CALLBACK (on_progress_end), info);
g_signal_connect (shell, "end", G_CALLBACK (on_progress_end), info);
return runner;
return shell;
}
static gint
@ -257,14 +256,19 @@ message_dialog (GitgWindow *window,
return ret;
}
static GitgRunner *
static GitgShell *
remove_local_branch (GitgWindow *window,
GitgRef *ref)
{
gchar const *name = gitg_ref_get_shortname (ref);
GitgRepository *repository = gitg_window_get_repository (window);
if (!gitg_repository_commandv (repository, NULL, "branch", "-d", name, NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"branch",
"-d",
name,
NULL),
NULL))
{
gint ret = message_dialog (window,
GTK_MESSAGE_ERROR,
@ -275,7 +279,12 @@ remove_local_branch (GitgWindow *window,
if (ret == GTK_RESPONSE_ACCEPT)
{
if (!gitg_repository_commandv (repository, NULL, "branch", "-D", name, NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"branch",
"-D",
name,
NULL),
NULL))
{
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -325,7 +334,7 @@ on_remove_remote_result (GitgWindow *window, GitgProgress progress, gpointer dat
gitg_ref_free (ref);
}
static GitgRunner *
static GitgShell *
remove_remote_branch (GitgWindow *window,
GitgRef *ref)
{
@ -346,7 +355,7 @@ remove_remote_branch (GitgWindow *window,
gchar const *local = gitg_ref_get_local_name (ref);
gchar *rm = g_strconcat (":", local, NULL);
GitgRunner *ret;
GitgShell *ret;
gchar *message = g_strdup_printf ("Removing remote branch `%s'", name);
ret = run_progress (window,
@ -368,14 +377,15 @@ get_stash_refspec (GitgRepository *repository, GitgRef *stash)
{
gchar **out;
out = gitg_repository_command_with_outputv (repository,
NULL,
"log",
"--no-color",
"--pretty=oneline",
"-g",
"refs/stash",
NULL);
out = gitg_shell_run_sync_with_output (gitg_command_newv (repository,
"log",
"--no-color",
"--pretty=oneline",
"-g",
"refs/stash",
NULL),
FALSE,
NULL);
gchar **ptr = out;
gchar *sha1 = gitg_hash_hash_to_sha1_new (gitg_ref_get_hash (stash));
@ -403,7 +413,7 @@ get_stash_refspec (GitgRepository *repository, GitgRef *stash)
return ret;
}
static GitgRunner *
static GitgShell *
remove_stash (GitgWindow *window, GitgRef *ref)
{
gint r = message_dialog (window,
@ -425,14 +435,14 @@ remove_stash (GitgWindow *window, GitgRef *ref)
return NULL;
}
if (!gitg_repository_commandv (repository,
NULL,
"reflog",
"delete",
"--updateref",
"--rewrite",
spec,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"reflog",
"delete",
"--updateref",
"--rewrite",
spec,
NULL),
NULL))
{
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -442,19 +452,19 @@ remove_stash (GitgWindow *window, GitgRef *ref)
}
else
{
if (!gitg_repository_commandv (repository,
NULL,
"rev-parse",
"--verify",
"refs/stash@{0}",
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"rev-parse",
"--verify",
"refs/stash@{0}",
NULL),
NULL))
{
gitg_repository_commandv (repository,
NULL,
"update-ref",
"-d",
"refs/stash",
NULL);
gitg_shell_run_sync (gitg_command_newv (repository,
"update-ref",
"-d",
"refs/stash",
NULL),
NULL);
}
gitg_repository_reload (repository);
@ -464,7 +474,7 @@ remove_stash (GitgWindow *window, GitgRef *ref)
return NULL;
}
static GitgRunner *
static GitgShell *
remove_tag (GitgWindow *window, GitgRef *ref)
{
gchar const *name = gitg_ref_get_shortname (ref);
@ -484,12 +494,12 @@ remove_tag (GitgWindow *window, GitgRef *ref)
GitgRepository *repository = gitg_window_get_repository (window);
if (!gitg_repository_commandv (repository,
NULL,
"tag",
"-d",
name,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"tag",
"-d",
name,
NULL),
NULL))
{
message = g_strdup_printf (_ ("The tag <%s> could not be successfully removed"),
name);
@ -508,7 +518,7 @@ remove_tag (GitgWindow *window, GitgRef *ref)
}
}
GitgRunner *
GitgShell *
gitg_branch_actions_remove (GitgWindow *window,
GitgRef *ref)
{
@ -516,7 +526,7 @@ gitg_branch_actions_remove (GitgWindow *window,
g_return_val_if_fail (ref != NULL, NULL);
GitgRef *cp = gitg_ref_copy (ref);
GitgRunner *ret = NULL;
GitgShell *ret = NULL;
switch (gitg_ref_get_ref_type (cp))
{
@ -540,7 +550,7 @@ gitg_branch_actions_remove (GitgWindow *window,
return ret;
}
static GitgRunner *
static GitgShell *
rename_branch (GitgWindow *window,
GitgRef *ref,
const gchar *newname)
@ -548,7 +558,13 @@ rename_branch (GitgWindow *window,
gchar const *oldname = gitg_ref_get_shortname (ref);
GitgRepository *repository = gitg_window_get_repository (window);
if (!gitg_repository_commandv (repository, NULL, "branch", "-m", oldname, newname, NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"branch",
"-m",
oldname,
newname,
NULL),
NULL))
{
gint ret = message_dialog (window,
GTK_MESSAGE_ERROR,
@ -559,7 +575,13 @@ rename_branch (GitgWindow *window,
if (ret == GTK_RESPONSE_ACCEPT)
{
if (!gitg_repository_commandv (repository, NULL, "branch", "-M", oldname, newname, NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"branch",
"-M",
oldname,
newname,
NULL),
NULL))
{
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -635,7 +657,7 @@ rename_dialog (GitgWindow *window, const gchar *oldname)
return newname;
}
GitgRunner *
GitgShell *
gitg_branch_actions_rename (GitgWindow *window,
GitgRef *ref)
{
@ -649,7 +671,7 @@ gitg_branch_actions_rename (GitgWindow *window,
if (newname)
{
GitgRef *cp = gitg_ref_copy (ref);
GitgRunner *ret = NULL;
GitgShell *ret = NULL;
ret = rename_branch (window, cp, newname);
gitg_ref_free (cp);
g_free (newname);
@ -661,13 +683,13 @@ gitg_branch_actions_rename (GitgWindow *window,
}
static void
reset_buffer (GitgRunner *runner, GString *buffer)
reset_buffer (GitgShell *shell, GString *buffer)
{
g_string_erase (buffer, 0, -1);
}
static void
update_buffer (GitgRunner *runner, gchar **lines, GString *buffer)
update_buffer (GitgShell *shell, gchar **lines, GString *buffer)
{
gchar **ptr = lines;
@ -686,12 +708,26 @@ update_buffer (GitgRunner *runner, gchar **lines, GString *buffer)
static gboolean
no_changes (GitgRepository *repository)
{
return gitg_repository_commandv (repository, NULL,
"update-index", "--refresh", NULL) &&
gitg_repository_commandv (repository, NULL,
"diff-files", "--quiet", NULL) &&
gitg_repository_commandv (repository, NULL,
"diff-index", "--cached", "--quiet", "HEAD", "--", NULL);
return gitg_shell_run_sync (gitg_command_newv (repository,
"update-index",
"--refresh",
NULL),
NULL) &&
gitg_shell_run_sync (gitg_command_newv (repository,
"diff-files",
"--no-ext-diff",
"--quiet",
NULL),
NULL) &&
gitg_shell_run_sync (gitg_command_newv (repository,
"diff-index",
"--no-ext-diff",
"--cached",
"--quiet",
"HEAD",
"--",
NULL),
NULL);
}
static gboolean
@ -705,11 +741,11 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
gchar *msg = NULL;
gboolean showerror = FALSE;
GitgRunner *runner = gitg_runner_new_synchronized (1000);
GitgShell *shell = gitg_shell_new_synchronized (1000);
GString *buffer = g_string_new ("");
g_signal_connect (runner, "begin-loading", G_CALLBACK (reset_buffer), buffer);
g_signal_connect (runner, "update", G_CALLBACK (update_buffer), buffer);
g_signal_connect (shell, "begin", G_CALLBACK (reset_buffer), buffer);
g_signal_connect (shell, "update", G_CALLBACK (update_buffer), buffer);
gchar const *secondary;
@ -734,9 +770,17 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
goto cleanup;
}
gitg_repository_run_commandv (repository, runner, NULL,
"log", "--no-color", "--abbrev-commit",
"--pretty=oneline", "-n", "1", "HEAD", NULL);
gitg_shell_run (shell,
gitg_command_newv (repository,
"log",
"--no-color",
"--abbrev-commit",
"--pretty=oneline",
"-n",
"1",
"HEAD",
NULL),
NULL);
GitgRef *working = gitg_repository_get_current_working_ref (repository);
@ -750,8 +794,11 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
}
// Create tree object of the current index
gitg_repository_run_commandv (repository, runner, NULL,
"write-tree", NULL);
gitg_shell_run (shell,
gitg_command_newv (repository,
"write-tree",
NULL),
NULL);
if (buffer->len == 0)
{
@ -765,10 +812,22 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
head = gitg_repository_parse_head (repository);
gchar *idxmsg = g_strconcat ("index on ", msg, NULL);
gitg_repository_run_command_with_inputv (repository, runner, idxmsg, NULL,
"commit-tree", tree, "-p", head, NULL);
GInputStream *inp = g_memory_input_stream_new_from_data (idxmsg, -1, NULL);
gitg_io_set_input (GITG_IO (shell), inp);
g_object_unref (inp);
gitg_shell_run (shell,
gitg_command_newv (repository,
"commit-tree",
tree,
"-p",
head,
NULL),
NULL);
g_free (idxmsg);
gitg_io_set_input (GITG_IO (shell), NULL);
if (buffer->len == 0)
{
@ -814,23 +873,48 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
}
tmpname = g_file_get_path (customindex);
gitg_runner_add_environment (runner, "GIT_INDEX_FILE", tmpname);
GitgCommand *cmd_read_tree = gitg_command_newv (repository,
"read-tree",
"-m",
tree,
NULL);
gitg_command_add_environmentv (cmd_read_tree,
"GIT_INDEX_FILE",
tmpname,
NULL);
GitgCommand *cmd_add = gitg_command_newv (repository,
"add",
"-u",
NULL);
gitg_command_add_environmentv (cmd_add,
"GIT_INDEX_FILE",
tmpname,
NULL);
GitgCommand *cmd_write_tree = gitg_command_newv (repository,
"write-tree",
NULL);
gitg_command_add_environmentv (cmd_write_tree,
"GIT_INDEX_FILE",
tmpname,
NULL);
g_free (tmpname);
gboolean writestash;
writestash = gitg_repository_run_commandv (repository, runner, NULL,
"read-tree", "-m", tree, NULL) &&
gitg_repository_run_commandv (repository, runner, NULL,
"add", "-u", NULL) &&
gitg_repository_run_commandv (repository, runner, NULL,
"write-tree", NULL);
writestash = gitg_shell_run (shell, cmd_read_tree, NULL) &&
gitg_shell_run (shell, cmd_add, NULL) &&
gitg_shell_run (shell, cmd_write_tree, NULL);
g_file_delete (customindex, NULL, NULL);
g_object_unref (customindex);
gitg_runner_set_environment (runner, NULL);
if (!writestash)
{
ret = FALSE;
@ -842,10 +926,23 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
gchar *stashtree = g_strndup (buffer->str, buffer->len);
gchar *reason = g_strconcat ("gitg auto stash: ", msg, NULL);
gitg_repository_run_command_with_inputv (repository, runner, reason, NULL,
"commit-tree", stashtree,
"-p", head,
"-p", commit, NULL);
inp = g_memory_input_stream_new_from_data (reason, -1, NULL);
gitg_io_set_input (GITG_IO (shell), inp);
g_object_unref (inp);
gitg_shell_run (shell,
gitg_command_newv (repository,
"commit-tree",
stashtree,
"-p",
head,
"-p",
commit,
NULL),
NULL);
gitg_io_set_input (GITG_IO (shell), NULL);
g_free (stashtree);
if (buffer->len == 0)
@ -887,19 +984,30 @@ stash_changes_real (GitgWindow *window, gchar **ref, gboolean storeref)
g_free (path);
gitg_repository_run_commandv (repository, runner, NULL,
"update-ref", "-m", reason,
"refs/stash", rref, NULL);
gitg_shell_run (shell,
gitg_command_newv (repository,
"update-ref",
"-m",
reason,
"refs/stash",
rref,
NULL),
NULL);
g_free (rref);
gitg_repository_run_commandv (repository, runner, NULL,
"reset", "--hard", NULL);
gitg_shell_run (shell,
gitg_command_newv (repository,
"reset",
"--hard",
NULL),
NULL);
ret = TRUE;
cleanup:
g_string_free (buffer, TRUE);
g_object_unref (runner);
g_object_unref (shell);
g_free (commit);
g_free (tree);
g_free (head);
@ -938,14 +1046,11 @@ checkout_local_branch_real (GitgWindow *window, GitgRef *ref)
{
GitgRepository *repository = gitg_window_get_repository (window);
if (!gitg_repository_commandv (repository, NULL, "checkout", gitg_ref_get_shortname (ref), NULL))
{
return FALSE;
}
else
{
return TRUE;
}
return gitg_shell_run_sync (gitg_command_newv (repository,
"checkout",
gitg_ref_get_shortname (ref),
NULL),
NULL);
}
static gboolean
@ -990,14 +1095,14 @@ checkout_remote_branch (GitgWindow *window,
gchar const *local = gitg_ref_get_local_name (ref);
gboolean ret;
if (!gitg_repository_commandv (repository,
NULL,
"checkout",
"--track",
"-b",
local,
name,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"checkout",
"--track",
"-b",
local,
name,
NULL),
NULL))
{
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -1030,13 +1135,13 @@ checkout_tag (GitgWindow *window,
gchar const *name = gitg_ref_get_shortname (ref);
gboolean ret;
if (!gitg_repository_commandv (repository,
NULL,
"checkout",
"-b",
name,
name,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"checkout",
"-b",
name,
name,
NULL),
NULL))
{
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -1139,14 +1244,14 @@ on_merge_rebase_result (GitgWindow *window,
}
message_dialog (window,
GTK_MESSAGE_ERROR,
message,
NULL,
NULL,
gitg_ref_get_ref_type (info->source) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (info->source),
gitg_ref_get_ref_type (info->dest) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (info->dest));
GTK_MESSAGE_ERROR,
message,
NULL,
NULL,
gitg_ref_get_ref_type (info->source) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (info->source),
gitg_ref_get_ref_type (info->dest) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (info->dest));
}
else if (progress == GITG_PROGRESS_SUCCESS)
{
@ -1159,32 +1264,43 @@ on_merge_rebase_result (GitgWindow *window,
if (info->stashcommit)
{
gitg_repository_commandv (repository, NULL,
"update-ref", "-m", "gitg autosave stash",
"refs/stash", info->stashcommit, NULL);
gitg_shell_run_sync (gitg_command_newv (repository,
"update-ref",
"-m",
"gitg autosave stash",
"refs/stash",
info->stashcommit,
NULL),
NULL);
message = _ ("The stashed changes have been stored to be reapplied manually");
}
message_dialog (window,
GTK_MESSAGE_ERROR,
_ ("Failed to checkout previously checked out branch"),
message,
NULL);
GTK_MESSAGE_ERROR,
_ ("Failed to checkout previously checked out branch"),
message,
NULL);
}
else if (info->stashcommit)
{
// Reapply stash
if (!gitg_repository_commandv (gitg_window_get_repository (window),
NULL,
"stash",
"apply",
"--index",
info->stashcommit,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (gitg_window_get_repository (window),
"stash",
"apply",
"--index",
info->stashcommit,
NULL),
NULL))
{
gitg_repository_commandv (repository, NULL,
"update-ref", "-m", "gitg autosave stash",
"refs/stash", info->stashcommit, NULL);
gitg_shell_run_sync (gitg_command_newv (repository,
"update-ref",
"-m",
"gitg autosave stash",
"refs/stash",
info->stashcommit,
NULL),
NULL);
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -1200,7 +1316,7 @@ on_merge_rebase_result (GitgWindow *window,
ref_info_free (info);
}
GitgRunner *
GitgShell *
gitg_branch_actions_merge (GitgWindow *window,
GitgRef *source,
GitgRef *dest)
@ -1238,7 +1354,11 @@ gitg_branch_actions_merge (GitgWindow *window,
GitgRef *head = gitg_repository_get_current_working_ref (repository);
// First checkout the correct branch on which to merge, e.g. dest
if (!gitg_repository_commandv (repository, NULL, "checkout", gitg_ref_get_shortname (dest), NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"checkout",
gitg_ref_get_shortname (dest),
NULL),
NULL))
{
g_free (stashcommit);
@ -1257,7 +1377,7 @@ gitg_branch_actions_merge (GitgWindow *window,
gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (dest));
GitgRunner *ret;
GitgShell *ret;
RefInfo *info = ref_info_new (source, dest);
info->stashcommit = stashcommit;
info->head = gitg_ref_copy (head);
@ -1277,7 +1397,7 @@ gitg_branch_actions_merge (GitgWindow *window,
return ret;
}
GitgRunner *
GitgShell *
gitg_branch_actions_rebase (GitgWindow *window,
GitgRef *source,
GitgRef *dest)
@ -1340,7 +1460,7 @@ gitg_branch_actions_rebase (GitgWindow *window,
gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH ? _ ("local") : _ ("remote"),
gitg_ref_get_shortname (dest));
GitgRunner *ret;
GitgShell *ret;
RefInfo *info = ref_info_new (source, dest);
info->stashcommit = stashcommit;
info->head = gitg_ref_copy (gitg_repository_get_current_working_ref (repository));
@ -1387,7 +1507,7 @@ on_push_result (GitgWindow *window,
ref_info_free (info);
}
GitgRunner *
GitgShell *
gitg_branch_actions_push (GitgWindow *window,
GitgRef *source,
GitgRef *dest)
@ -1423,7 +1543,7 @@ gitg_branch_actions_push (GitgWindow *window,
gitg_ref_get_shortname (source),
gitg_ref_get_shortname (dest));
GitgRunner *ret;
GitgShell *ret;
RefInfo *info = ref_info_new (source, dest);
ret = run_progress (window,
@ -1442,7 +1562,7 @@ gitg_branch_actions_push (GitgWindow *window,
return ret;
}
GitgRunner *
GitgShell *
gitg_branch_actions_push_remote (GitgWindow *window,
GitgRef *source,
gchar const *remote,
@ -1475,7 +1595,7 @@ gitg_branch_actions_push_remote (GitgWindow *window,
gitg_ref_get_shortname (source),
remote, branch);
GitgRunner *ret;
GitgShell *ret;
gchar *rr = g_strconcat ("refs/remotes/", remote, "/", branch, NULL);
GitgRef *rmref = gitg_ref_new ("0000000000000000000000000000000000000000", rr);
g_free (rr);
@ -1546,13 +1666,13 @@ gitg_branch_actions_apply_stash (GitgWindow *window,
gchar *sha1 = gitg_hash_hash_to_sha1_new (gitg_ref_get_hash (stash));
gboolean ret;
if (!gitg_repository_commandv (repository,
NULL,
"stash",
"apply",
"--index",
sha1,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"stash",
"apply",
"--index",
sha1,
NULL),
NULL))
{
message = g_strdup_printf (_ ("The stash could not be applied to local branch <%s>"),
gitg_ref_get_shortname (branch));
@ -1590,12 +1710,12 @@ gitg_branch_actions_create (GitgWindow *window, gchar const *sha1, gchar const *
repository = gitg_window_get_repository (window);
result = gitg_repository_commandv (repository,
NULL,
"branch",
name,
sha1,
NULL);
result = gitg_shell_run_sync (gitg_command_newv (repository,
"branch",
name,
sha1,
NULL),
NULL);
if (!result)
{
@ -1631,24 +1751,24 @@ gitg_branch_actions_tag (GitgWindow *window, gchar const *sha1, gchar const *nam
if (message != NULL && message[0] != '\0')
{
result = gitg_repository_commandv (repository,
NULL,
"tag",
"-m",
message,
sign ? "-s" : "-a",
name,
sha1,
NULL);
result = gitg_shell_run_sync (gitg_command_newv (repository,
"tag",
"-m",
message,
sign ? "-s" : "-a",
name,
sha1,
NULL),
NULL);
}
else
{
result = gitg_repository_commandv (repository,
NULL,
"tag",
name,
sha1,
NULL);
result = gitg_shell_run_sync (gitg_command_newv (repository,
"tag",
name,
sha1,
NULL),
NULL);
}
if (!result)
@ -1737,9 +1857,14 @@ on_cherry_pick_result (GitgWindow *window,
if (info->stashcommit)
{
gitg_repository_commandv (repository, NULL,
"update-ref", "-m", "gitg autosave stash",
"refs/stash", info->stashcommit, NULL);
gitg_shell_run_sync (gitg_command_newv (repository,
"update-ref",
"-m",
"gitg autosave stash",
"refs/stash",
info->stashcommit,
NULL),
NULL);
message = _ ("The stashed changes have been stored to be reapplied manually");
}
@ -1753,17 +1878,22 @@ on_cherry_pick_result (GitgWindow *window,
else if (info->stashcommit)
{
// Reapply stash
if (!gitg_repository_commandv (gitg_window_get_repository (window),
NULL,
"stash",
"apply",
"--index",
info->stashcommit,
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (gitg_window_get_repository (window),
"stash",
"apply",
"--index",
info->stashcommit,
NULL),
NULL))
{
gitg_repository_commandv (repository, NULL,
"update-ref", "-m", "gitg autosave stash",
"refs/stash", info->stashcommit, NULL);
gitg_shell_run_sync (gitg_command_newv (repository,
"update-ref",
"-m",
"gitg autosave stash",
"refs/stash",
info->stashcommit,
NULL),
NULL);
message_dialog (window,
GTK_MESSAGE_ERROR,
@ -1779,7 +1909,7 @@ on_cherry_pick_result (GitgWindow *window,
cherry_pick_info_free (info);
}
GitgRunner *
GitgShell *
gitg_branch_actions_cherry_pick (GitgWindow *window,
GitgRevision *revision,
GitgRef *dest)
@ -1812,11 +1942,11 @@ gitg_branch_actions_cherry_pick (GitgWindow *window,
GitgRef *head = gitg_repository_get_current_working_ref (repository);
// First checkout the correct branch on which to cherry-pick
if (!gitg_repository_commandv (repository,
NULL,
"checkout",
gitg_ref_get_shortname (dest),
NULL))
if (!gitg_shell_run_sync (gitg_command_newv (repository,
"checkout",
gitg_ref_get_shortname (dest),
NULL),
NULL))
{
g_free (stashcommit);
@ -1833,7 +1963,7 @@ gitg_branch_actions_cherry_pick (GitgWindow *window,
message = g_strdup_printf (_ ("Cherry-picking on <%s>"),
gitg_ref_get_shortname (dest));
GitgRunner *ret;
GitgShell *ret;
CherryPickInfo *info = cherry_pick_info_new (revision, dest);
@ -1908,7 +2038,7 @@ on_format_patch_result (GitgWindow *window,
}
static void
on_format_patch_update (GitgRunner *runner,
on_format_patch_update (GitgShell *shell,
gchar **lines,
FormatPatchInfo *info)
{
@ -1920,7 +2050,7 @@ on_format_patch_update (GitgRunner *runner,
}
}
GitgRunner *
GitgShell *
gitg_branch_actions_format_patch (GitgWindow *window,
GitgRevision *revision,
gchar const *destination)
@ -1929,7 +2059,7 @@ gitg_branch_actions_format_patch (GitgWindow *window,
g_return_val_if_fail (revision != NULL, NULL);
g_return_val_if_fail (destination != NULL, NULL);
GitgRunner *ret;
GitgShell *ret;
GFile *file = g_file_new_for_uri (destination);
GFileOutputStream *stream = g_file_replace (file,

View file

@ -24,28 +24,28 @@
#define __GITG_BRANCH_ACTIONS_H__
#include <libgitg/gitg-ref.h>
#include "gitg-window.h"
#include <gitg/gitg-window.h>
G_BEGIN_DECLS
gboolean gitg_branch_actions_create (GitgWindow *window, gchar const *sha1, gchar const *name);
GitgRunner *gitg_branch_actions_remove (GitgWindow *window, GitgRef *ref);
GitgRunner *gitg_branch_actions_rename (GitgWindow *window, GitgRef *ref);
GitgShell *gitg_branch_actions_remove (GitgWindow *window, GitgRef *ref);
GitgShell *gitg_branch_actions_rename (GitgWindow *window, GitgRef *ref);
gboolean gitg_branch_actions_checkout (GitgWindow *window, GitgRef *ref);
GitgRunner *gitg_branch_actions_merge (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgRunner *gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgShell *gitg_branch_actions_merge (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgShell *gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgRunner *gitg_branch_actions_push (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgRunner *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote, gchar const *branch);
GitgShell *gitg_branch_actions_push (GitgWindow *window, GitgRef *source, GitgRef *dest);
GitgShell *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote, gchar const *branch);
gboolean gitg_branch_actions_apply_stash (GitgWindow *window, GitgRef *stash, GitgRef *branch);
gboolean gitg_branch_actions_tag (GitgWindow *window, gchar const *sha1, gchar const *name, gchar const *message, gboolean sign);
GitgRunner *gitg_branch_actions_cherry_pick (GitgWindow *window, GitgRevision *revision, GitgRef *dest);
GitgShell *gitg_branch_actions_cherry_pick (GitgWindow *window, GitgRevision *revision, GitgRef *dest);
GitgRunner *gitg_branch_actions_format_patch (GitgWindow *window, GitgRevision *revision, gchar const *destination);
GitgShell *gitg_branch_actions_format_patch (GitgWindow *window, GitgRevision *revision, gchar const *destination);
G_END_DECLS

View file

@ -26,6 +26,7 @@
#include <glib/gi18n.h>
#include <string.h>
#include <libgitg/gitg-commit.h>
#include <libgitg/gitg-shell.h>
#include "gitg-commit-view.h"
#include "gitg-diff-view.h"
@ -78,7 +79,7 @@ struct _GitgCommitViewPrivate
GtkHScale *hscale_context;
gint context_size;
GitgRunner *runner;
GitgShell *shell;
guint update_id;
gboolean is_diff;
@ -138,11 +139,11 @@ gitg_commit_view_finalize (GObject *object)
if (view->priv->update_id)
{
g_signal_handler_disconnect (view->priv->runner, view->priv->update_id);
g_signal_handler_disconnect (view->priv->shell, view->priv->update_id);
}
gitg_runner_cancel (view->priv->runner);
g_object_unref (view->priv->runner);
gitg_io_cancel (GITG_IO (view->priv->shell));
g_object_unref (view->priv->shell);
g_object_unref (view->priv->ui_manager);
gdk_cursor_unref (view->priv->hand);
@ -224,7 +225,7 @@ show_binary_information (GitgCommitView *view)
}
static void
on_changes_update (GitgRunner *runner, gchar **buffer, GitgCommitView *view)
on_changes_update (GitgShell *shell, gchar **buffer, GitgCommitView *view)
{
gchar *line;
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(view->priv->changes_view));
@ -261,7 +262,7 @@ on_changes_update (GitgRunner *runner, gchar **buffer, GitgCommitView *view)
if (content_type && !gitg_utils_can_display_content_type (content_type))
{
gitg_runner_cancel (runner);
gitg_io_cancel (GITG_IO (shell));
show_binary_information (view);
}
else if (content_type)
@ -283,7 +284,7 @@ on_changes_update (GitgRunner *runner, gchar **buffer, GitgCommitView *view)
static void
connect_update (GitgCommitView *view)
{
view->priv->update_id = g_signal_connect (view->priv->runner,
view->priv->update_id = g_signal_connect (view->priv->shell,
"update",
G_CALLBACK (on_changes_update),
view);
@ -384,9 +385,11 @@ check_selection(GtkTreeView *tree_view,
GitgCommitView *view)
{
if (view->priv->update_id)
g_signal_handler_disconnect(view->priv->runner, view->priv->update_id);
{
g_signal_handler_disconnect(view->priv->shell, view->priv->update_id);
}
gitg_runner_cancel(view->priv->runner);
gitg_io_cancel(GITG_IO (view->priv->shell));
view->priv->update_id = 0;
GtkTextView *tv = GTK_TEXT_VIEW(view->priv->changes_view);
@ -478,7 +481,7 @@ unstaged_selection_changed (GtkTreeSelection *selection,
view->priv->is_diff = FALSE;
connect_update (view);
gitg_runner_run_stream (view->priv->runner, stream, NULL);
gitg_shell_run_stream (view->priv->shell, stream, NULL);
g_object_unref (stream);
}
}
@ -487,6 +490,8 @@ unstaged_selection_changed (GtkTreeSelection *selection,
}
else
{
gboolean allow_external;
set_diff_language (view);
view->priv->is_diff = TRUE;
connect_update (view);
@ -496,15 +501,22 @@ unstaged_selection_changed (GtkTreeSelection *selection,
gchar ct[10];
g_snprintf (ct, sizeof(ct), "-U%d", view->priv->context_size);
gitg_repository_run_commandv (view->priv->repository,
view->priv->runner,
NULL,
"diff",
"--no-color",
ct,
"--",
path,
NULL);
g_object_get (gitg_preferences_get_default (),
"diff-external",
&allow_external,
NULL);
gitg_shell_run (view->priv->shell,
gitg_command_newv (view->priv->repository,
"diff",
allow_external ? "--ext-diff" : "--no-ext-diff",
"--no-color",
ct,
"--",
path,
NULL),
NULL);
g_free (path);
}
@ -521,7 +533,9 @@ staged_selection_changed (GtkTreeSelection *selection, GitgCommitView *view)
GtkTreeIter iter;
if (!check_selection (view->priv->tree_view_staged, &iter, view))
{
return;
}
model = gtk_tree_view_get_model (view->priv->tree_view_staged);
unselect_tree_view (view->priv->tree_view_unstaged);
@ -561,14 +575,15 @@ staged_selection_changed (GtkTreeSelection *selection, GitgCommitView *view)
connect_update (view);
gchar *indexpath = g_strconcat (":0:", path, NULL);
gitg_repository_run_commandv (view->priv->repository,
view->priv->runner,
NULL,
"show",
"--encoding=UTF-8",
"--no-color",
indexpath,
NULL);
gitg_shell_run (view->priv->shell,
gitg_command_newv (view->priv->repository,
"show",
"--encoding=UTF-8",
"--no-color",
indexpath,
NULL),
NULL);
g_free (indexpath);
}
@ -576,6 +591,8 @@ staged_selection_changed (GtkTreeSelection *selection, GitgCommitView *view)
}
else
{
gboolean allow_external;
view->priv->is_diff = TRUE;
set_diff_language (view);
connect_update (view);
@ -584,17 +601,24 @@ staged_selection_changed (GtkTreeSelection *selection, GitgCommitView *view)
gchar ct[10];
g_snprintf (ct, sizeof(ct), "-U%d", view->priv->context_size);
gitg_repository_run_commandv (view->priv->repository,
view->priv->runner,
NULL,
"diff-index",
ct,
"--cached",
"--no-color",
head,
"--",
path,
NULL);
g_object_get (gitg_preferences_get_default (),
"diff-external",
&allow_external,
NULL);
gitg_shell_run (view->priv->shell,
gitg_command_newv (view->priv->repository,
"diff-index",
allow_external ? "--ext-diff" : "--no-ext-diff",
ct,
"--cached",
"--no-color",
head,
"--",
path,
NULL),
NULL);
g_free(head);
}
@ -1659,8 +1683,8 @@ gitg_commit_view_init (GitgCommitView *self)
{
self->priv = GITG_COMMIT_VIEW_GET_PRIVATE (self);
self->priv->runner = gitg_runner_new (10000);
gitg_runner_set_preserve_line_endings (self->priv->runner, TRUE);
self->priv->shell = gitg_shell_new (10000);
gitg_shell_set_preserve_line_endings (self->priv->shell, TRUE);
self->priv->hand = gdk_cursor_new (GDK_HAND1);
}
@ -2174,7 +2198,10 @@ do_revert_changes(GitgCommitView *view)
for (item = files; item; item = g_list_next (item))
{
ret &= gitg_commit_revert(view->priv->commit, GITG_CHANGED_FILE (item->data), NULL, NULL);
ret &= gitg_commit_undo (view->priv->commit,
GITG_CHANGED_FILE (item->data),
NULL,
NULL);
g_object_unref (item->data);
}
@ -2185,11 +2212,17 @@ do_revert_changes(GitgCommitView *view)
GitgChangedFile *file = g_object_ref(view->priv->current_file);
gchar *hunk = get_hunk_patch(view, &view->priv->context_iter);
ret = gitg_commit_revert(view->priv->commit, view->priv->current_file, hunk, NULL);
ret = gitg_commit_undo (view->priv->commit,
view->priv->current_file,
hunk,
NULL);
g_free(hunk);
if (ret && view->priv->current_file == file)
gitg_diff_view_remove_hunk(GITG_DIFF_VIEW(view->priv->changes_view), &view->priv->context_iter);
{
gitg_diff_view_remove_hunk (GITG_DIFF_VIEW(view->priv->changes_view),
&view->priv->context_iter);
}
g_object_unref(file);
}

View file

@ -777,13 +777,14 @@ revision_to_text (GitgRepository *repository,
gchar **lines;
gchar *sha1 = gitg_revision_get_sha1 (revision);
lines = gitg_repository_command_with_outputv (repository,
NULL,
"log",
"-1",
"--pretty=format:%h: %s%n%n%b",
sha1,
NULL);
lines = gitg_shell_run_sync_with_output (gitg_command_newv (repository,
"log",
"-1",
"--pretty=format:%h: %s%n%n%b",
sha1,
NULL),
FALSE,
NULL);
remove_trailing_newlines (lines);
gchar *ret = g_strjoinv ("\n", lines);

View file

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <libgitg/gitg-config.h>
#include <libgitg/gitg-shell.h>
#include "gitg-repository-dialog.h"
#include "gitg-utils.h"
@ -100,7 +101,7 @@ G_DEFINE_TYPE (GitgRepositoryDialog, gitg_repository_dialog, GTK_TYPE_DIALOG)
typedef struct
{
GitgRepositoryDialog *dialog;
GitgRunner *runner;
GitgShell *shell;
GtkTreeRowReference *reference;
#ifdef BUILD_SPINNER
@ -149,7 +150,7 @@ fetch_cleanup (FetchInfo *info)
#endif
gtk_tree_row_reference_free (info->reference);
g_object_unref (info->runner);
g_object_unref (info->shell);
g_slice_free (FetchInfo, info);
}
@ -174,7 +175,7 @@ gitg_repository_dialog_finalize (GObject *object)
for (item = copy; item; item = g_list_next (item))
{
gitg_runner_cancel (((FetchInfo *)item->data)->runner);
gitg_io_cancel (GITG_IO (((FetchInfo *)item->data)->shell));
}
g_list_free (copy);
@ -341,7 +342,7 @@ pulse_row (FetchInfo *info)
#endif
static void
on_fetch_begin_loading (GitgRunner *runner, FetchInfo *info)
on_fetch_begin_loading (GitgShell *shell, FetchInfo *info)
{
GtkTreeIter iter;
GtkTreePath *path = gtk_tree_row_reference_get_path (info->reference);
@ -387,7 +388,7 @@ on_fetch_begin_loading (GitgRunner *runner, FetchInfo *info)
}
static void
on_fetch_end_loading (GitgRunner *runner, gboolean cancelled, FetchInfo *info)
on_fetch_end_loading (GitgShell *shell, gboolean cancelled, FetchInfo *info)
{
if (cancelled || !gtk_tree_row_reference_valid (info->reference))
{
@ -406,7 +407,7 @@ on_fetch_end_loading (GitgRunner *runner, gboolean cancelled, FetchInfo *info)
static void
fetch_remote (GitgRepositoryDialog *dialog, GtkTreeIter *iter)
{
GitgRunner *runner = gitg_runner_new (1000);
GitgShell *shell = gitg_shell_new (1000);
FetchInfo *info = g_slice_new0 (FetchInfo);
GtkTreeModel *model = GTK_TREE_MODEL (dialog->priv->list_store_remotes);
@ -414,17 +415,17 @@ fetch_remote (GitgRepositoryDialog *dialog, GtkTreeIter *iter)
info->dialog = dialog;
info->reference = gtk_tree_row_reference_new (model, path);
info->runner = runner;
info->shell = shell;
gtk_tree_path_free (path);
g_signal_connect (runner,
"begin-loading",
g_signal_connect (shell,
"begin",
G_CALLBACK (on_fetch_begin_loading),
info);
g_signal_connect (runner,
"end-loading",
g_signal_connect (shell,
"end",
G_CALLBACK (on_fetch_end_loading),
info);
@ -433,12 +434,12 @@ fetch_remote (GitgRepositoryDialog *dialog, GtkTreeIter *iter)
gchar *name;
gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
gitg_repository_run_commandv (dialog->priv->repository,
runner,
NULL,
"fetch",
name,
NULL);
gitg_shell_run (shell,
gitg_command_newv (dialog->priv->repository,
"fetch",
name,
NULL),
NULL);
g_free (name);
}
@ -684,7 +685,7 @@ fetch_remote_cancel (GitgRepositoryDialog *dialog,
if (equal)
{
gitg_runner_cancel (info->runner);
gitg_io_cancel (GITG_IO (info->shell));
break;
}
}
@ -736,12 +737,12 @@ on_button_fetch_remote_clicked (GtkButton *button,
static gboolean
remove_remote (GitgRepositoryDialog *dialog, gchar const *name)
{
return gitg_repository_commandv (dialog->priv->repository,
NULL,
"remote",
"rm",
name,
NULL);
return gitg_shell_run_sync (gitg_command_newv (dialog->priv->repository,
"remote",
"rm",
name,
NULL),
NULL);
}
void
@ -828,7 +829,13 @@ on_button_add_remote_clicked (GtkButton *button,
gchar *name = g_strdup_printf ("remote%d", num + 1);
gchar const url[] = "git://example.com/repository.git";
if (gitg_repository_commandv (dialog->priv->repository, NULL, "remote", "add", name, url, NULL))
if (gitg_shell_run_sync (gitg_command_newv (dialog->priv->repository,
"remote",
"add",
name,
url,
NULL),
NULL))
{
GtkTreeIter iter;
GtkTreePath *path;
@ -901,7 +908,13 @@ on_remote_name_edited (GtkCellRendererText *renderer,
COLUMN_URL, &url,
-1);
if (gitg_repository_commandv (dialog->priv->repository, NULL, "remote", "add", new_text, url, NULL))
if (gitg_shell_run_sync (gitg_command_newv (dialog->priv->repository,
"remote",
"add",
new_text,
url,
NULL),
NULL))
{
remove_remote (dialog, oldname);

View file

@ -6,12 +6,14 @@
#include <string.h>
#include <libgitg/gitg-repository.h>
#include <libgitg/gitg-revision.h>
#include <libgitg/gitg-runner.h>
#include <libgitg/gitg-shell.h>
#include <libgitg/gitg-hash.h>
#include "gitg-diff-view.h"
#include "gitg-utils.h"
#include "gitg-preferences.h"
#include <glib/gi18n.h>
#include "gitg-revision-panel.h"
#include "gitg-activatable.h"
@ -26,8 +28,8 @@ struct _GitgRevisionChangesPanelPrivate
GtkTreeView *diff_files;
GtkListStore *list_store_diff_files;
GitgRunner *diff_runner;
GitgRunner *diff_files_runner;
GitgShell *diff_shell;
GitgShell *diff_files_shell;
GitgRepository *repository;
GitgRevision *revision;
@ -520,16 +522,16 @@ gitg_revision_changes_panel_dispose (GObject *object)
set_revision (changes_panel, NULL, NULL);
if (changes_panel->priv->diff_files_runner)
if (changes_panel->priv->diff_files_shell)
{
g_object_unref (changes_panel->priv->diff_files_runner);
changes_panel->priv->diff_files_runner = NULL;
g_object_unref (changes_panel->priv->diff_files_shell);
changes_panel->priv->diff_files_shell = NULL;
}
if (changes_panel->priv->diff_files_runner)
if (changes_panel->priv->diff_files_shell)
{
g_object_unref (changes_panel->priv->diff_runner);
changes_panel->priv->diff_runner = NULL;
g_object_unref (changes_panel->priv->diff_shell);
changes_panel->priv->diff_shell = NULL;
}
if (changes_panel->priv->builder)
@ -564,8 +566,8 @@ reload_diff (GitgRevisionChangesPanel *changes_panel)
GtkTreeSelection *selection;
// First cancel a possibly still running diff
gitg_runner_cancel (changes_panel->priv->diff_runner);
gitg_runner_cancel (changes_panel->priv->diff_files_runner);
gitg_io_cancel (GITG_IO (changes_panel->priv->diff_shell));
gitg_io_cancel (GITG_IO (changes_panel->priv->diff_files_shell));
free_cached_headers (changes_panel);
@ -592,45 +594,54 @@ reload_diff (GitgRevisionChangesPanel *changes_panel)
}
gchar sign = gitg_revision_get_sign (changes_panel->priv->revision);
gboolean allow_external;
g_object_get (gitg_preferences_get_default (),
"diff-external",
&allow_external,
NULL);
switch (sign)
{
case 't':
gitg_repository_run_commandv (changes_panel->priv->repository,
changes_panel->priv->diff_runner,
NULL,
"diff",
"--cached",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL);
gitg_shell_run (changes_panel->priv->diff_shell,
gitg_command_newv (changes_panel->priv->repository,
"diff",
allow_external ? "--ext-diff" : "--no-ext-diff",
"--cached",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL),
NULL);
break;
case 'u':
gitg_repository_run_commandv (changes_panel->priv->repository,
changes_panel->priv->diff_runner,
NULL,
"diff",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL);
gitg_shell_run (changes_panel->priv->diff_shell,
gitg_command_newv (changes_panel->priv->repository,
"diff",
allow_external ? "--ext-diff" : "--no-ext-diff",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
NULL),
NULL);
break;
default:
{
gchar *hash = gitg_revision_get_sha1 (changes_panel->priv->revision);
gitg_repository_run_commandv (changes_panel->priv->repository,
changes_panel->priv->diff_runner,
NULL,
"show",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
hash,
NULL);
gitg_shell_run (changes_panel->priv->diff_shell,
gitg_command_newv (changes_panel->priv->repository,
"show",
"-M",
"--pretty=format:",
"--encoding=UTF-8",
"--no-color",
hash,
NULL),
NULL);
g_free (hash);
}
@ -649,14 +660,14 @@ set_revision (GitgRevisionChangesPanel *changes_panel,
return;
}
if (changes_panel->priv->diff_runner)
if (changes_panel->priv->diff_shell)
{
gitg_runner_cancel (changes_panel->priv->diff_runner);
gitg_io_cancel (GITG_IO (changes_panel->priv->diff_shell));
}
if (changes_panel->priv->diff_files_runner)
if (changes_panel->priv->diff_files_shell)
{
gitg_runner_cancel (changes_panel->priv->diff_files_runner);
gitg_io_cancel (GITG_IO (changes_panel->priv->diff_files_shell));
}
if (changes_panel->priv->repository)
@ -691,7 +702,7 @@ set_revision (GitgRevisionChangesPanel *changes_panel,
}
static void
on_diff_files_begin_loading (GitgRunner *runner,
on_diff_files_begin_loading (GitgShell *shell,
GitgRevisionChangesPanel *self)
{
GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
@ -703,7 +714,7 @@ on_diff_files_begin_loading (GitgRunner *runner,
}
static void
on_diff_files_end_loading (GitgRunner *runner,
on_diff_files_end_loading (GitgShell *shell,
gboolean cancelled,
GitgRevisionChangesPanel *self)
{
@ -766,7 +777,7 @@ add_diff_file (GitgRevisionChangesPanel *view,
}
static void
on_diff_files_update (GitgRunner *runner,
on_diff_files_update (GitgShell *shell,
gchar **buffer,
GitgRevisionChangesPanel *self)
{
@ -808,7 +819,7 @@ on_diff_files_update (GitgRunner *runner,
}
static void
on_diff_begin_loading (GitgRunner *runner,
on_diff_begin_loading (GitgShell *shell,
GitgRevisionChangesPanel *self)
{
GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
@ -818,7 +829,7 @@ on_diff_begin_loading (GitgRunner *runner,
}
static void
on_diff_end_loading (GitgRunner *runner,
on_diff_end_loading (GitgShell *shell,
gboolean cancelled,
GitgRevisionChangesPanel *self)
{
@ -831,6 +842,12 @@ on_diff_end_loading (GitgRunner *runner,
}
gchar sign = gitg_revision_get_sign (self->priv->revision);
gboolean allow_external;
g_object_get (gitg_preferences_get_default (),
"diff-external",
&allow_external,
NULL);
if (sign == 't' || sign == 'u')
{
@ -840,38 +857,39 @@ on_diff_end_loading (GitgRunner *runner,
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);
gitg_shell_run (self->priv->diff_files_shell,
gitg_command_newv (self->priv->repository,
"diff-index",
allow_external ? "--ext-diff" : "--no-ext-diff",
"--raw",
"-M",
"--abbrev=40",
head,
cached,
NULL),
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,
"show",
"--encoding=UTF-8",
"--raw",
"-M",
"--pretty=format:",
"--abbrev=40",
sha,
NULL);
gitg_shell_run (self->priv->diff_files_shell,
gitg_command_newv (self->priv->repository,
"show",
"--encoding=UTF-8",
"--raw",
"-M",
"--pretty=format:",
"--abbrev=40",
sha,
NULL),
NULL);
g_free (sha);
}
}
static void
on_diff_update (GitgRunner *runner,
on_diff_update (GitgShell *shell,
gchar **buffer,
GitgRevisionChangesPanel *self)
{
@ -893,37 +911,37 @@ gitg_revision_changes_panel_init (GitgRevisionChangesPanel *self)
{
self->priv = GITG_REVISION_CHANGES_PANEL_GET_PRIVATE (self);
self->priv->diff_runner = gitg_runner_new (2000);
self->priv->diff_shell = gitg_shell_new (2000);
g_signal_connect (self->priv->diff_runner,
"begin-loading",
g_signal_connect (self->priv->diff_shell,
"begin",
G_CALLBACK (on_diff_begin_loading),
self);
g_signal_connect (self->priv->diff_runner,
g_signal_connect (self->priv->diff_shell,
"update",
G_CALLBACK (on_diff_update),
self);
g_signal_connect (self->priv->diff_runner,
"end-loading",
g_signal_connect (self->priv->diff_shell,
"end",
G_CALLBACK (on_diff_end_loading),
self);
self->priv->diff_files_runner = gitg_runner_new (2000);
self->priv->diff_files_shell = gitg_shell_new (2000);
g_signal_connect (self->priv->diff_files_runner,
"begin-loading",
g_signal_connect (self->priv->diff_files_shell,
"begin",
G_CALLBACK(on_diff_files_begin_loading),
self);
g_signal_connect (self->priv->diff_files_runner,
g_signal_connect (self->priv->diff_files_shell,
"update",
G_CALLBACK(on_diff_files_update),
self);
g_signal_connect (self->priv->diff_files_runner,
"end-loading",
g_signal_connect (self->priv->diff_files_shell,
"end",
G_CALLBACK(on_diff_files_end_loading),
self);
}

View file

@ -54,7 +54,7 @@ struct _GitgRevisionDetailsPanelPrivate
GitgRepository *repository;
GitgRevision *revision;
GitgRunner *runner;
GitgShell *shell;
gboolean in_stat;
GSList *stats;
@ -202,12 +202,12 @@ gitg_revision_details_panel_dispose (GObject *object)
panel->priv->builder = NULL;
}
if (panel->priv->runner)
if (panel->priv->shell)
{
gitg_runner_cancel (panel->priv->runner);
g_object_unref (panel->priv->runner);
gitg_io_cancel (GITG_IO (panel->priv->shell));
g_object_unref (panel->priv->shell);
panel->priv->runner = NULL;
panel->priv->shell = NULL;
}
G_OBJECT_CLASS (gitg_revision_details_panel_parent_class)->dispose (object);
@ -224,8 +224,8 @@ gitg_revision_details_panel_class_init (GitgRevisionDetailsPanelClass *klass)
}
static void
on_runner_begin (GitgRunner *runner,
GitgRevisionDetailsPanel *panel)
on_shell_begin (GitgShell *shell,
GitgRevisionDetailsPanel *panel)
{
GdkCursor *cursor;
@ -363,9 +363,9 @@ make_stats_table (GitgRevisionDetailsPanel *panel)
}
static void
on_runner_end (GitgRunner *runner,
gboolean cancelled,
GitgRevisionDetailsPanel *panel)
on_shell_end (GitgShell *shell,
gboolean cancelled,
GitgRevisionDetailsPanel *panel)
{
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (panel->priv->text_view)),
NULL);
@ -432,9 +432,9 @@ add_stat (GitgRevisionDetailsPanel *panel,
}
static void
on_runner_update (GitgRunner *runner,
gchar **lines,
GitgRevisionDetailsPanel *panel)
on_shell_update (GitgShell *shell,
gchar **lines,
GitgRevisionDetailsPanel *panel)
{
GtkTextBuffer *buffer;
GtkTextIter end;
@ -476,21 +476,21 @@ gitg_revision_details_panel_init (GitgRevisionDetailsPanel *self)
{
self->priv = GITG_REVISION_DETAILS_PANEL_GET_PRIVATE(self);
self->priv->runner = gitg_runner_new (1000);
self->priv->shell = gitg_shell_new (1000);
g_signal_connect (self->priv->runner,
"begin-loading",
G_CALLBACK (on_runner_begin),
g_signal_connect (self->priv->shell,
"begin",
G_CALLBACK (on_shell_begin),
self);
g_signal_connect (self->priv->runner,
"end-loading",
G_CALLBACK (on_runner_end),
g_signal_connect (self->priv->shell,
"end",
G_CALLBACK (on_shell_end),
self);
g_signal_connect (self->priv->runner,
g_signal_connect (self->priv->shell,
"update",
G_CALLBACK (on_runner_update),
G_CALLBACK (on_shell_update),
self);
}
@ -644,7 +644,7 @@ update_details (GitgRevisionDetailsPanel *panel)
{
gchar *sha1;
gitg_runner_cancel (panel->priv->runner);
gitg_io_cancel (GITG_IO (panel->priv->shell));
gtk_text_buffer_set_text (gtk_text_view_get_buffer (panel->priv->text_view),
"",
@ -657,14 +657,14 @@ update_details (GitgRevisionDetailsPanel *panel)
sha1 = gitg_revision_get_sha1 (panel->priv->revision);
gitg_repository_run_commandv (panel->priv->repository,
panel->priv->runner,
NULL,
"show",
"--numstat",
"--pretty=format:%s%n%n%b%n\x01",
sha1,
NULL);
gitg_shell_run (panel->priv->shell,
gitg_command_newv (panel->priv->repository,
"show",
"--numstat",
"--pretty=format:%s%n%n%b%n\x01",
sha1,
NULL),
NULL);
g_free (sha1);
}

View file

@ -27,7 +27,7 @@
#include <gio/gio.h>
#include <stdlib.h>
#include <libgitg/gitg-revision.h>
#include <libgitg/gitg-runner.h>
#include <libgitg/gitg-shell.h>
#include "gitg-revision-files-panel.h"
#include "gitg-utils.h"
@ -54,7 +54,7 @@ struct _GitgRevisionFilesViewPrivate
{
GtkTreeView *tree_view;
GtkSourceView *contents;
GitgRunner *content_runner;
GitgShell *content_shell;
GtkTreeStore *store;
gchar *drag_dir;
@ -62,7 +62,7 @@ struct _GitgRevisionFilesViewPrivate
GitgRepository *repository;
GitgRevision *revision;
GitgRunner *loader;
GitgShell *loader;
GtkTreePath *load_path;
gboolean skipped_blank_line;
@ -127,7 +127,7 @@ gitg_revision_files_view_finalize (GObject *object)
g_strfreev (self->priv->drag_files);
}
gitg_runner_cancel (self->priv->loader);
gitg_io_cancel (GITG_IO (self->priv->loader));
g_object_unref (self->priv->loader);
G_OBJECT_CLASS (gitg_revision_files_view_parent_class)->finalize (object);
@ -150,7 +150,7 @@ set_revision (GitgRevisionFilesView *files_view,
return;
}
gitg_runner_cancel (files_view->priv->loader);
gitg_io_cancel (GITG_IO (files_view->priv->loader));
gtk_tree_store_clear (files_view->priv->store);
if (files_view->priv->repository)
@ -270,7 +270,7 @@ on_selection_changed (GtkTreeSelection *selection,
GtkTreeModel *model;
GtkTreeIter iter;
gitg_runner_cancel (tree->priv->content_runner);
gitg_io_cancel (GITG_IO (tree->priv->content_shell));
gtk_text_buffer_set_text (buffer, "", -1);
@ -326,13 +326,13 @@ on_selection_changed (GtkTreeSelection *selection,
gchar *id = node_identity (tree, &iter);
gitg_repository_run_commandv (tree->priv->repository,
tree->priv->content_runner,
NULL,
"show",
"--encoding=UTF-8",
id,
NULL);
gitg_shell_run (tree->priv->content_shell,
gitg_command_newv (tree->priv->repository,
"show",
"--encoding=UTF-8",
id,
NULL),
NULL);
g_free (id);
}
@ -857,8 +857,8 @@ append_node (GitgRevisionFilesView *tree,
}
static void
on_update (GitgRunner *runner,
gchar **buffer,
on_update (GitgShell *shell,
gchar **buffer,
GitgRevisionFilesView *tree)
{
gchar *line;
@ -919,9 +919,9 @@ compare_func (GtkTreeModel *model,
}
static void
on_contents_update (GitgRunner *runner,
gchar **buffer,
GitgRevisionFilesView *tree)
on_contents_update (GitgShell *shell,
gchar **buffer,
GitgRevisionFilesView *tree)
{
gchar *line;
GtkTextBuffer *buf;
@ -943,7 +943,7 @@ on_contents_update (GitgRunner *runner,
if (content_type && !gitg_utils_can_display_content_type (content_type))
{
gitg_runner_cancel (runner);
gitg_io_cancel (GITG_IO (shell));
show_binary_information (tree);
}
else
@ -978,14 +978,14 @@ gitg_revision_files_view_init (GitgRevisionFilesView *self)
NAME_COLUMN,
GTK_SORT_ASCENDING);
self->priv->loader = gitg_runner_new (1000);
self->priv->loader = gitg_shell_new (1000);
g_signal_connect (self->priv->loader,
"update",
G_CALLBACK (on_update),
self);
self->priv->content_runner = gitg_runner_new (5000);
g_signal_connect (self->priv->content_runner,
self->priv->content_shell = gitg_shell_new (5000);
g_signal_connect (self->priv->content_shell,
"update",
G_CALLBACK (on_contents_update),
self);
@ -1017,7 +1017,7 @@ static void
load_node (GitgRevisionFilesView *tree,
GtkTreeIter *parent)
{
if (gitg_runner_running (tree->priv->loader))
if (gitg_io_get_running (GITG_IO (tree->priv->loader)))
{
return;
}
@ -1041,12 +1041,12 @@ load_node (GitgRevisionFilesView *tree,
}
tree->priv->skipped_blank_line = FALSE;
gitg_repository_run_commandv (tree->priv->repository,
tree->priv->loader,
NULL,
"show",
"--encoding=UTF-8",
id,
NULL);
gitg_shell_run (tree->priv->loader,
gitg_command_newv (tree->priv->repository,
"show",
"--encoding=UTF-8",
id,
NULL),
NULL);
g_free (id);
}

View file

@ -26,7 +26,6 @@
#include <glib/gi18n.h>
#include <libgitg/gitg-config.h>
#include <libgitg/gitg-ref.h>
#include <libgitg/gitg-runner.h>
#include <libgitg/gitg-hash.h>
#include "config.h"
@ -158,31 +157,31 @@ static GtkBuildableIface parent_iface;
static GtkWindowClass *parent_class = NULL;
static void
on_branch_action_runner_end (GitgRunner *runner,
gboolean cancelled,
GitgWindow *window)
on_branch_action_shell_end (GitgShell *shell,
gboolean cancelled,
GitgWindow *window)
{
window->priv->branch_actions = g_list_remove (window->priv->branch_actions, runner);
g_object_unref (runner);
window->priv->branch_actions = g_list_remove (window->priv->branch_actions, shell);
g_object_unref (shell);
}
gboolean
gitg_window_add_branch_action (GitgWindow *window,
GitgRunner *runner)
GitgShell *shell)
{
if (runner != NULL && gitg_runner_running (runner))
if (shell != NULL && gitg_io_get_running (GITG_IO (shell)))
{
window->priv->branch_actions = g_list_prepend (window->priv->branch_actions, runner);
window->priv->branch_actions = g_list_prepend (window->priv->branch_actions, shell);
g_signal_connect (runner, "end-loading", G_CALLBACK (on_branch_action_runner_end), window);
g_signal_connect (shell, "end", G_CALLBACK (on_branch_action_shell_end), window);
}
else if (runner)
else if (shell)
{
g_object_unref (runner);
runner = NULL;
g_object_unref (shell);
shell = NULL;
}
return runner != NULL;
return shell != NULL;
}
static void
@ -198,7 +197,7 @@ gitg_window_finalize (GObject *object)
for (item = copy; item; item = g_list_next (item))
{
gitg_runner_cancel (GITG_RUNNER (item->data));
gitg_io_cancel (item->data);
}
g_list_free (copy);
@ -1217,7 +1216,7 @@ on_repository_loaded (GitgRepository *repository,
}
static void
on_update (GitgRunner *loader,
on_update (GitgShell *loader,
gchar **revisions,
GitgWindow *window)
{
@ -1782,7 +1781,7 @@ load_repository (GitgWindow *window,
gtk_tree_view_set_model (window->priv->tree_view,
GTK_TREE_MODEL (window->priv->repository));
GitgRunner *loader = gitg_repository_get_loader (window->priv->repository);
GitgShell *loader = gitg_repository_get_loader (window->priv->repository);
gitg_window_set_select_on_load (window, selection);

View file

@ -25,14 +25,15 @@
#include <gtk/gtk.h>
#include <libgitg/gitg-repository.h>
#include <libgitg/gitg-shell.h>
G_BEGIN_DECLS
#define GITG_TYPE_WINDOW (gitg_window_get_type ())
#define GITG_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_WINDOW, GitgWindow))
#define GITG_TYPE_WINDOW (gitg_window_get_type ())
#define GITG_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_WINDOW, GitgWindow))
#define GITG_WINDOW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_WINDOW, GitgWindow const))
#define GITG_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_WINDOW, GitgWindowClass))
#define GITG_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_WINDOW))
#define GITG_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_WINDOW))
#define GITG_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_WINDOW))
#define GITG_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_WINDOW, GitgWindowClass))
@ -40,13 +41,15 @@ typedef struct _GitgWindow GitgWindow;
typedef struct _GitgWindowClass GitgWindowClass;
typedef struct _GitgWindowPrivate GitgWindowPrivate;
struct _GitgWindow {
struct _GitgWindow
{
GtkWindow parent;
GitgWindowPrivate *priv;
};
struct _GitgWindowClass {
struct _GitgWindowClass
{
GtkWindowClass parent_class;
};
@ -71,10 +74,10 @@ gboolean gitg_window_load_repository_from_environment (GitgWindow *window,
void gitg_window_show_commit (GitgWindow *window);
GitgRepository *gitg_window_get_repository(GitgWindow *window);
GitgRepository *gitg_window_get_repository (GitgWindow *window);
void gitg_window_set_select_on_load (GitgWindow *window, gchar const *selection);
gboolean gitg_window_add_branch_action (GitgWindow *window, GitgRunner *runner);
gboolean gitg_window_add_branch_action (GitgWindow *window, GitgShell *shell);
gboolean gitg_window_select (GitgWindow *window, gchar const *selection);
gboolean gitg_window_activate (GitgWindow *window, gchar const *activatable, gchar const *action);

View file

@ -30,7 +30,11 @@ INST_H_FILES = \
gitg-ref.h \
gitg-repository.h \
gitg-revision.h \
gitg-runner.h
gitg-runner.h \
gitg-command.h \
gitg-shell.h \
gitg-io.h \
gitg-line-parser.h
NOINST_H_FILES = \
gitg-convert.h \
@ -57,7 +61,11 @@ C_FILES = \
gitg-revision.c \
gitg-runner.c \
gitg-smart-charset-converter.c \
gitg-encodings.c
gitg-encodings.c \
gitg-command.c \
gitg-io.c \
gitg-shell.c \
gitg-line-parser.c
ENUM_H_FILES = \
gitg-changed-file.h

491
libgitg/gitg-command.c Normal file
View file

@ -0,0 +1,491 @@
#include "gitg-command.h"
#define GITG_COMMAND_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_COMMAND, GitgCommandPrivate))
#define CONST_CONST(x) ((gchar const * const *)x)
struct _GitgCommandPrivate
{
GitgRepository *repository;
gchar **arguments;
gchar **environment;
GFile *working_directory;
};
G_DEFINE_TYPE (GitgCommand, gitg_command, G_TYPE_INITIALLY_UNOWNED)
enum
{
PROP_0,
PROP_REPOSITORY,
PROP_ARGUMENTS,
PROP_ENVIRONMENT,
PROP_WORKING_DIRECTORY
};
static void
gitg_command_finalize (GObject *object)
{
GitgCommand *command;
command = GITG_COMMAND (object);
g_strfreev (command->priv->arguments);
g_strfreev (command->priv->environment);
G_OBJECT_CLASS (gitg_command_parent_class)->finalize (object);
}
static void
gitg_command_dispose (GObject *object)
{
GitgCommand *command;
command = GITG_COMMAND (object);
if (command->priv->repository != NULL)
{
g_object_unref (command->priv->repository);
command->priv->repository = NULL;
}
G_OBJECT_CLASS (gitg_command_parent_class)->dispose (object);
}
static void
gitg_command_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GitgCommand *self = GITG_COMMAND (object);
switch (prop_id)
{
case PROP_REPOSITORY:
self->priv->repository = g_value_dup_object (value);
break;
case PROP_ARGUMENTS:
gitg_command_set_arguments (self,
g_value_get_boxed (value));
break;
case PROP_ENVIRONMENT:
gitg_command_set_environment (self,
g_value_get_boxed (value));
break;
case PROP_WORKING_DIRECTORY:
gitg_command_set_working_directory (self,
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_command_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GitgCommand *self = GITG_COMMAND (object);
switch (prop_id)
{
case PROP_REPOSITORY:
g_value_set_object (value, self->priv->repository);
break;
case PROP_ARGUMENTS:
g_value_set_boxed (value, self->priv->arguments);
break;
case PROP_ENVIRONMENT:
g_value_set_boxed (value, self->priv->environment);
break;
case PROP_WORKING_DIRECTORY:
g_value_take_object (value, gitg_command_get_working_directory (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_command_class_init (GitgCommandClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gitg_command_finalize;
object_class->dispose = gitg_command_dispose;
object_class->get_property = gitg_command_get_property;
object_class->set_property = gitg_command_set_property;
g_type_class_add_private (object_class, sizeof(GitgCommandPrivate));
g_object_class_install_property (object_class,
PROP_REPOSITORY,
g_param_spec_object ("repository",
"Repository",
"Repository",
GITG_TYPE_REPOSITORY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_ARGUMENTS,
g_param_spec_boxed ("arguments",
"Arguments",
"Arguments",
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_ENVIRONMENT,
g_param_spec_boxed ("environment",
"Environment",
"Environment",
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_WORKING_DIRECTORY,
g_param_spec_object ("working-directory",
"Working Directory",
"Working directory",
G_TYPE_FILE,
G_PARAM_READWRITE));
}
static void
gitg_command_init (GitgCommand *self)
{
self->priv = GITG_COMMAND_GET_PRIVATE (self);
}
static gchar **
collect_arguments (va_list ap)
{
GPtrArray *arguments;
gchar const *arg;
arguments = g_ptr_array_new ();
while ((arg = va_arg (ap, gchar const *)) != NULL)
{
g_ptr_array_add (arguments, g_strdup (arg));
}
g_ptr_array_add (arguments, NULL);
return (gchar **)g_ptr_array_free (arguments, FALSE);
}
static gchar **
combine_environment (gchar const * const *environment)
{
GPtrArray *ret;
ret = g_ptr_array_new ();
while (*environment)
{
gchar const *key = *environment++;
gchar const *value = *environment++;
gchar *combined = g_strconcat (key, "=", value, NULL);
g_ptr_array_add (ret, combined);
}
g_ptr_array_add (ret, NULL);
return (gchar **)g_ptr_array_free (ret, FALSE);
}
GitgCommand *
gitg_command_new (GitgRepository *repository,
gchar const * const *arguments)
{
g_return_val_if_fail (repository == NULL || GITG_IS_REPOSITORY (repository), NULL);
return g_object_new (GITG_TYPE_COMMAND,
"repository", repository,
"arguments", arguments,
NULL);
}
GitgCommand *
gitg_command_newv (GitgRepository *repository,
...)
{
va_list ap;
GitgCommand *ret;
gchar **arguments;
g_return_val_if_fail (repository == NULL || GITG_IS_REPOSITORY (repository), NULL);
va_start (ap, repository);
arguments = collect_arguments (ap);
ret = gitg_command_new (repository, CONST_CONST (arguments));
g_strfreev (arguments);
va_end (ap);
return ret;
}
GitgRepository *
gitg_command_get_repository (GitgCommand *command)
{
g_return_val_if_fail (GITG_IS_COMMAND (command), NULL);
return command->priv->repository;
}
void
gitg_command_set_arguments (GitgCommand *command,
gchar const * const *arguments)
{
GPtrArray *ret;
g_return_if_fail (GITG_IS_COMMAND (command));
ret = g_ptr_array_new ();
if (command->priv->repository)
{
GFile *git_dir;
GFile *work_tree;
gchar *git_dir_path;
gchar *work_tree_path;
git_dir = gitg_repository_get_git_dir (command->priv->repository);
work_tree = gitg_repository_get_work_tree (command->priv->repository);
git_dir_path = g_file_get_path (git_dir);
work_tree_path = g_file_get_path (work_tree);
g_object_unref (git_dir);
g_object_unref (work_tree);
g_ptr_array_add (ret, g_strdup ("git"));
g_ptr_array_add (ret, g_strdup ("--git-dir"));
g_ptr_array_add (ret, git_dir_path);
g_ptr_array_add (ret, g_strdup ("--work-tree"));
g_ptr_array_add (ret, work_tree_path);
}
while (*arguments)
{
g_ptr_array_add (ret, g_strdup (*arguments++));
}
g_ptr_array_add (ret, NULL);
g_strfreev (command->priv->arguments);
command->priv->arguments = (gchar **)g_ptr_array_free (ret, FALSE);
g_object_notify (G_OBJECT (command), "arguments");
}
void
gitg_command_set_argumentsv (GitgCommand *command,
...)
{
va_list ap;
gchar **arguments;
g_return_if_fail (GITG_IS_COMMAND (command));
va_start (ap, command);
arguments = collect_arguments (ap);
va_end (ap);
gitg_command_set_arguments (command, CONST_CONST (arguments));
g_strfreev (arguments);
}
void
gitg_command_add_arguments (GitgCommand *command,
gchar const * const *arguments)
{
GPtrArray *args;
gchar **ptr;
g_return_if_fail (GITG_IS_COMMAND (command));
args = g_ptr_array_new ();
for (ptr = command->priv->arguments; *ptr; ++ptr)
{
g_ptr_array_add (args, *ptr);
}
while (*arguments)
{
g_ptr_array_add (args, g_strdup (*arguments++));
}
g_free (command->priv->arguments);
g_ptr_array_add (args, NULL);
command->priv->arguments = (gchar **)g_ptr_array_free (args, FALSE);
g_object_notify (G_OBJECT (command), "arguments");
}
void
gitg_command_add_argumentsv (GitgCommand *command,
...)
{
va_list ap;
gchar **arguments;
g_return_if_fail (GITG_IS_COMMAND (command));
va_start (ap, command);
arguments = collect_arguments (ap);
va_end (ap);
gitg_command_add_arguments (command, CONST_CONST (arguments));
g_strfreev (arguments);
}
gchar const * const *
gitg_command_get_arguments (GitgCommand *command)
{
g_return_val_if_fail (GITG_IS_COMMAND (command), NULL);
return CONST_CONST (command->priv->arguments);
}
void
gitg_command_set_environment (GitgCommand *command,
gchar const * const *environment)
{
g_return_if_fail (GITG_IS_COMMAND (command));
g_strfreev (command->priv->environment);
command->priv->environment = combine_environment (environment);
g_object_notify (G_OBJECT (command), "environment");
}
void
gitg_command_set_environmentv (GitgCommand *command,
...)
{
va_list ap;
gchar **environment;
g_return_if_fail (GITG_IS_COMMAND (command));
va_start (ap, command);
environment = collect_arguments (ap);
va_end (ap);
gitg_command_set_environment (command, CONST_CONST (environment));
g_strfreev (environment);
}
void
gitg_command_add_environment (GitgCommand *command,
gchar const * const *environment)
{
GPtrArray *args;
gchar **combined;
gchar **ptr;
g_return_if_fail (GITG_IS_COMMAND (command));
args = g_ptr_array_new ();
for (ptr = command->priv->environment; *ptr; ++ptr)
{
g_ptr_array_add (args, *ptr);
}
combined = combine_environment (environment);
for (ptr = combined; *ptr; ++ptr)
{
g_ptr_array_add (args, *ptr);
}
g_free (combined);
g_free (command->priv->environment);
g_ptr_array_add (args, NULL);
command->priv->environment = (gchar **)g_ptr_array_free (args, FALSE);
g_object_notify (G_OBJECT (command), "arguments");
}
void
gitg_command_add_environmentv (GitgCommand *command,
...)
{
va_list ap;
gchar **environment;
g_return_if_fail (GITG_IS_COMMAND (command));
va_start (ap, command);
environment = collect_arguments (ap);
va_end (ap);
gitg_command_add_environment (command, CONST_CONST (environment));
g_strfreev (environment);
}
gchar const * const *
gitg_command_get_environment (GitgCommand *command)
{
g_return_val_if_fail (GITG_IS_COMMAND (command), NULL);
return CONST_CONST (command->priv->environment);
}
void
gitg_command_set_working_directory (GitgCommand *command,
GFile *working_directory)
{
g_return_if_fail (GITG_IS_COMMAND (command));
g_return_if_fail (working_directory == NULL || G_IS_FILE (working_directory));
if (command->priv->working_directory)
{
g_object_unref (command->priv->working_directory);
command->priv->working_directory = NULL;
}
if (working_directory)
{
command->priv->working_directory = g_file_dup (working_directory);
}
g_object_notify (G_OBJECT (command), "working-directory");
}
GFile *
gitg_command_get_working_directory (GitgCommand *command)
{
g_return_val_if_fail (GITG_IS_COMMAND (command), NULL);
if (command->priv->working_directory)
{
return g_file_dup (command->priv->working_directory);
}
else if (command->priv->repository)
{
return gitg_repository_get_work_tree (command->priv->repository);
}
return NULL;
}

76
libgitg/gitg-command.h Normal file
View file

@ -0,0 +1,76 @@
#ifndef __GITG_COMMAND_H__
#define __GITG_COMMAND_H__
#include <glib-object.h>
#include <libgitg/gitg-repository.h>
G_BEGIN_DECLS
#define GITG_TYPE_COMMAND (gitg_command_get_type ())
#define GITG_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_COMMAND, GitgCommand))
#define GITG_COMMAND_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_COMMAND, GitgCommand const))
#define GITG_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_COMMAND, GitgCommandClass))
#define GITG_IS_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_COMMAND))
#define GITG_IS_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_COMMAND))
#define GITG_COMMAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_COMMAND, GitgCommandClass))
typedef struct _GitgCommand GitgCommand;
typedef struct _GitgCommandClass GitgCommandClass;
typedef struct _GitgCommandPrivate GitgCommandPrivate;
struct _GitgCommand
{
/*< private >*/
GInitiallyUnowned parent;
GitgCommandPrivate *priv;
/*< public >*/
};
struct _GitgCommandClass
{
/*< private >*/
GInitiallyUnownedClass parent_class;
/*< public >*/
};
GType gitg_command_get_type (void) G_GNUC_CONST;
GitgCommand *gitg_command_new (GitgRepository *repository,
gchar const * const *arguments);
GitgCommand *gitg_command_newv (GitgRepository *repository,
...) G_GNUC_NULL_TERMINATED;
GitgRepository *gitg_command_get_repository (GitgCommand *command);
GFile *gitg_command_get_working_directory (GitgCommand *command);
void gitg_command_set_working_directory (GitgCommand *command,
GFile *file);
void gitg_command_set_arguments (GitgCommand *command,
gchar const * const *arguments);
void gitg_command_set_argumentsv (GitgCommand *command,
...) G_GNUC_NULL_TERMINATED;
void gitg_command_add_arguments (GitgCommand *command,
gchar const * const *arguments);
void gitg_command_add_argumentsv (GitgCommand *command,
...) G_GNUC_NULL_TERMINATED;
gchar const * const *gitg_command_get_arguments (GitgCommand *command);
void gitg_command_set_environment (GitgCommand *command,
gchar const * const *environment);
void gitg_command_set_environmentv (GitgCommand *command,
...) G_GNUC_NULL_TERMINATED;
void gitg_command_add_environment (GitgCommand *command,
gchar const * const *environment);
void gitg_command_add_environmentv (GitgCommand *command,
...) G_GNUC_NULL_TERMINATED;
gchar const * const *gitg_command_get_environment (GitgCommand *command);
G_END_DECLS
#endif /* __GITG_COMMAND_H__ */

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,8 @@ typedef struct _GitgCommitPrivate GitgCommitPrivate;
typedef enum
{
GITG_COMMIT_ERROR_NONE = 0,
GITG_COMMIT_ERROR_SIGNOFF
GITG_COMMIT_ERROR_SIGNOFF,
GITG_COMMIT_ERROR_MERGE
} GitgCommitError;
struct _GitgCommit {
@ -62,24 +63,45 @@ struct _GitgCommitClass {
void (*removed) (GitgCommit *commit, GitgChangedFile *file);
};
GQuark gitg_commit_error_quark(void);
GQuark gitg_commit_error_quark (void);
GType gitg_commit_get_type(void) G_GNUC_CONST;
GitgCommit *gitg_commit_new(GitgRepository *repository);
GType gitg_commit_get_type (void) G_GNUC_CONST;
GitgCommit *gitg_commit_new (GitgRepository *repository);
void gitg_commit_refresh(GitgCommit *commit);
gboolean gitg_commit_stage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error);
gboolean gitg_commit_unstage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error);
void gitg_commit_refresh (GitgCommit *commit);
gboolean gitg_commit_stage (GitgCommit *commit,
GitgChangedFile *file,
gchar const *hunk,
GError **error);
gboolean gitg_commit_unstage (GitgCommit *commit,
GitgChangedFile *file,
gchar const *hunk,
GError **error);
gboolean gitg_commit_has_changes (GitgCommit *commit);
gboolean gitg_commit_commit (GitgCommit *commit,
gchar const *comment,
gboolean signoff,
gboolean amend,
GError **error);
gboolean gitg_commit_has_changes(GitgCommit *commit);
gboolean gitg_commit_commit(GitgCommit *commit, gchar const *comment, gboolean signoff, gboolean amend, GError **error);
gboolean gitg_commit_revert (GitgCommit *commit,
GitgRevision *from,
GitgRevision *to,
GError **error);
gboolean gitg_commit_revert(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error);
gboolean gitg_commit_add_ignore(GitgCommit *commit, GitgChangedFile *file, GError **error);
gboolean gitg_commit_undo (GitgCommit *commit,
GitgChangedFile *file,
gchar const *hunk,
GError **error);
GitgChangedFile *gitg_commit_find_changed_file(GitgCommit *commit, GFile *file);
gboolean gitg_commit_add_ignore (GitgCommit *commit,
GitgChangedFile *file,
GError **error);
gchar *gitg_commit_amend_message (GitgCommit *commit);
GitgChangedFile *gitg_commit_find_changed_file (GitgCommit *commit,
GFile *file);
gchar *gitg_commit_amend_message (GitgCommit *commit);
G_END_DECLS

View file

@ -21,7 +21,7 @@
*/
#include "gitg-config.h"
#include "gitg-shell.h"
#define GITG_CONFIG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_CONFIG, GitgConfigPrivate))
@ -34,7 +34,7 @@ enum
struct _GitgConfigPrivate
{
GitgRepository *repository;
GitgRunner *runner;
GitgShell *shell;
GString *accumulated;
};
@ -113,24 +113,22 @@ gitg_config_class_init (GitgConfigClass *klass)
}
static void
gitg_config_accumulate (GitgRunner *runner, gchar **buffer, GitgConfig *config)
gitg_config_accumulate (GitgShell *shell,
gchar **buffer,
GitgConfig *config)
{
gchar **ptr = buffer;
while (*ptr)
{
if (config->priv->accumulated->len != 0)
{
g_string_append_c (config->priv->accumulated, '\n');
}
g_string_append (config->priv->accumulated, *ptr);
++ptr;
}
}
static void
gitg_config_begin_loading (GitgRunner *runner, GitgConfig *config)
gitg_config_begin (GitgShell *shell,
GitgConfig *config)
{
g_string_erase (config->priv->accumulated, 0, -1);
}
@ -140,18 +138,18 @@ gitg_config_init (GitgConfig *self)
{
self->priv = GITG_CONFIG_GET_PRIVATE (self);
self->priv->runner = gitg_runner_new_synchronized (1000);
self->priv->shell = gitg_shell_new_synchronized (1000);
self->priv->accumulated = g_string_new ("");
g_signal_connect (self->priv->runner,
"update",
g_signal_connect (self->priv->shell,
"update",
G_CALLBACK (gitg_config_accumulate),
self);
g_signal_connect (self->priv->runner,
"begin-loading",
G_CALLBACK (gitg_config_begin_loading),
g_signal_connect (self->priv->shell,
"begin",
G_CALLBACK (gitg_config_begin),
self);
}
@ -168,7 +166,8 @@ get_value_process (GitgConfig *config, gboolean ret)
if (ret)
{
res = g_strndup (config->priv->accumulated->str, config->priv->accumulated->len);
res = g_strndup (config->priv->accumulated->str,
config->priv->accumulated->len);
}
else
{
@ -181,15 +180,14 @@ get_value_process (GitgConfig *config, gboolean ret)
static gchar *
get_value_global (GitgConfig *config, gchar const *key)
{
gchar const *argv[] = {
"git",
"config",
"--global",
key,
NULL
};
gboolean ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--global",
key,
NULL),
NULL);
gboolean ret = gitg_runner_run (config->priv->runner, argv, NULL);
return get_value_process (config, ret);
}
@ -198,17 +196,14 @@ get_value_global_regex (GitgConfig *config,
gchar const *regex,
gchar const *value_regex)
{
gchar const *argv[] = {
"git",
"config",
"--global",
"--get-regexp",
regex,
value_regex,
NULL
};
gboolean ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--global",
"--get-regexp",
NULL),
NULL);
gboolean ret = gitg_runner_run (config->priv->runner, argv, NULL);
return get_value_process (config, ret);
}
@ -225,14 +220,14 @@ get_value_local (GitgConfig *config, gchar const *key)
cfg_file = g_file_get_child (git_dir, "config");
cfg = g_file_get_path (cfg_file);
ret = gitg_repository_run_commandv (config->priv->repository,
config->priv->runner,
NULL,
"config",
"--file",
cfg,
key,
NULL);
ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--file",
cfg,
key,
NULL),
NULL);
g_free (cfg);
@ -257,16 +252,16 @@ get_value_local_regex (GitgConfig *config,
cfg_file = g_file_get_child (git_dir, "config");
cfg = g_file_get_path (cfg_file);
ret = gitg_repository_run_commandv (config->priv->repository,
config->priv->runner,
NULL,
"config",
"--file",
cfg,
"--get-regexp",
regex,
value_regex,
NULL);
ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--file",
cfg,
"--get-regexp",
regex,
value_regex,
NULL),
NULL);
g_free (cfg);
@ -279,16 +274,14 @@ get_value_local_regex (GitgConfig *config,
static gboolean
set_value_global (GitgConfig *config, gchar const *key, gchar const *value)
{
gchar const *argv[] = {
"git",
"config",
"--global",
value == NULL ? "--unset" : key,
value == NULL ? key : value,
NULL
};
return gitg_runner_run (config->priv->runner, argv, NULL);
return gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--global",
value == NULL ? "--unset" : key,
value == NULL ? key : value,
NULL),
NULL);
}
static gboolean
@ -304,15 +297,15 @@ set_value_local (GitgConfig *config, gchar const *key, gchar const *value)
cfg_file = g_file_get_child (git_dir, "config");
cfg = g_file_get_path (cfg_file);
ret = gitg_repository_run_commandv (config->priv->repository,
config->priv->runner,
NULL,
"config",
"--file",
cfg,
value == NULL ? "--unset" : key,
value == NULL ? key : value,
NULL);
ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--file",
cfg,
value == NULL ? "--unset" : key,
value == NULL ? key : value,
NULL),
NULL);
g_free (cfg);
@ -325,17 +318,15 @@ set_value_local (GitgConfig *config, gchar const *key, gchar const *value)
static gboolean
rename_global (GitgConfig *config, gchar const *old, gchar const *nw)
{
gchar const *argv[] = {
"git",
"config",
"--global",
"--rename-section",
old,
nw,
NULL
};
return gitg_runner_run (config->priv->runner, argv, NULL);
return gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--global",
"--rename-section",
old,
nw,
NULL),
NULL);
}
static gboolean
@ -351,16 +342,16 @@ rename_local (GitgConfig *config, gchar const *old, gchar const *nw)
cfg_file = g_file_get_child (git_dir, "config");
cfg = g_file_get_path (cfg_file);
ret = gitg_repository_run_commandv (config->priv->repository,
config->priv->runner,
NULL,
"config",
"--file",
cfg,
"--rename-section",
old,
nw,
NULL);
ret = gitg_shell_run (config->priv->shell,
gitg_command_newv (config->priv->repository,
"config",
"--file",
cfg,
"--rename-section",
old,
nw,
NULL),
NULL);
g_free (cfg);

View file

@ -28,36 +28,47 @@
G_BEGIN_DECLS
#define GITG_TYPE_CONFIG (gitg_config_get_type ())
#define GITG_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_CONFIG, GitgConfig))
#define GITG_TYPE_CONFIG (gitg_config_get_type ())
#define GITG_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_CONFIG, GitgConfig))
#define GITG_CONFIG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_CONFIG, GitgConfig const))
#define GITG_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_CONFIG, GitgConfigClass))
#define GITG_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_CONFIG))
#define GITG_IS_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_CONFIG))
#define GITG_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_CONFIG))
#define GITG_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_CONFIG, GitgConfigClass))
typedef struct _GitgConfig GitgConfig;
typedef struct _GitgConfig GitgConfig;
typedef struct _GitgConfigClass GitgConfigClass;
typedef struct _GitgConfigPrivate GitgConfigPrivate;
struct _GitgConfig {
struct _GitgConfig
{
GObject parent;
GitgConfigPrivate *priv;
};
struct _GitgConfigClass {
struct _GitgConfigClass
{
GObjectClass parent_class;
};
GType gitg_config_get_type (void) G_GNUC_CONST;
GitgConfig *gitg_config_new (GitgRepository *repository);
GType gitg_config_get_type (void) G_GNUC_CONST;
GitgConfig *gitg_config_new (GitgRepository *repository);
gchar *gitg_config_get_value (GitgConfig *config, gchar const *key);
gchar *gitg_config_get_value_regex (GitgConfig *config, gchar const *regex, gchar const *value_regex);
gchar *gitg_config_get_value (GitgConfig *config,
gchar const *key);
gboolean gitg_config_rename (GitgConfig *config, gchar const *old, gchar const *nw);
gboolean gitg_config_set_value (GitgConfig *config, gchar const *key, gchar const *value);
gchar *gitg_config_get_value_regex (GitgConfig *config,
gchar const *regex,
gchar const *value_regex);
gboolean gitg_config_rename (GitgConfig *config,
gchar const *old,
gchar const *nw);
gboolean gitg_config_set_value (GitgConfig *config,
gchar const *key,
gchar const *value);
G_END_DECLS

406
libgitg/gitg-io.c Normal file
View file

@ -0,0 +1,406 @@
#include "gitg-io.h"
#define GITG_IO_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_IO, GitgIOPrivate))
struct _GitgIOPrivate
{
GInputStream *input;
GOutputStream *output;
gint exit_status;
guint cancelled : 1;
guint running : 1;
};
enum
{
PROP_0,
PROP_INPUT,
PROP_OUTPUT,
PROP_CANCELLED,
PROP_EXIT_STATUS,
PROP_RUNNING
};
enum
{
BEGIN,
END,
NUM_SIGNALS
};
G_DEFINE_TYPE (GitgIO, gitg_io, G_TYPE_OBJECT)
static guint signals[NUM_SIGNALS] = {0,};
static void
gitg_io_finalize (GObject *object)
{
G_OBJECT_CLASS (gitg_io_parent_class)->finalize (object);
}
static void
gitg_io_dispose (GObject *object)
{
GitgIO *io;
io = GITG_IO (object);
gitg_io_close (io);
G_OBJECT_CLASS (gitg_io_parent_class)->dispose (object);
}
static void
gitg_io_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GitgIO *self = GITG_IO (object);
switch (prop_id)
{
case PROP_INPUT:
gitg_io_set_input (self, g_value_get_object (value));
break;
case PROP_OUTPUT:
gitg_io_set_output (self, g_value_get_object (value));
break;
case PROP_CANCELLED:
gitg_io_set_cancelled (self, g_value_get_boolean (value));
break;
case PROP_EXIT_STATUS:
gitg_io_set_exit_status (self, g_value_get_int (value));
break;
case PROP_RUNNING:
gitg_io_set_running (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_io_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GitgIO *self = GITG_IO (object);
switch (prop_id)
{
case PROP_INPUT:
g_value_set_object (value, self->priv->input);
break;
case PROP_OUTPUT:
g_value_set_object (value, self->priv->output);
break;
case PROP_CANCELLED:
g_value_set_boolean (value, self->priv->cancelled);
break;
case PROP_EXIT_STATUS:
g_value_set_int (value, self->priv->exit_status);
break;
case PROP_RUNNING:
g_value_set_boolean (value, self->priv->running);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_io_cancel_impl (GitgIO *io)
{
io->priv->cancelled = TRUE;
}
static void
gitg_io_begin_impl (GitgIO *io)
{
gitg_io_set_running (io, TRUE);
}
static void
gitg_io_end_impl (GitgIO *io,
GError *error)
{
gitg_io_set_running (io, FALSE);
}
static void
gitg_io_class_init (GitgIOClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gitg_io_finalize;
object_class->dispose = gitg_io_dispose;
object_class->get_property = gitg_io_get_property;
object_class->set_property = gitg_io_set_property;
klass->cancel = gitg_io_cancel_impl;
klass->begin = gitg_io_begin_impl;
klass->end = gitg_io_end_impl;
g_object_class_install_property (object_class,
PROP_INPUT,
g_param_spec_object ("input",
"Input",
"Input",
G_TYPE_INPUT_STREAM,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_OUTPUT,
g_param_spec_object ("output",
"Output",
"Output",
G_TYPE_OUTPUT_STREAM,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_CANCELLED,
g_param_spec_boolean ("cancelled",
"Cancelled",
"Cancelled",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_EXIT_STATUS,
g_param_spec_int ("exit-status",
"Exit status",
"Exit Status",
G_MININT,
G_MAXINT,
0,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_RUNNING,
g_param_spec_boolean ("running",
"Running",
"Running",
FALSE,
G_PARAM_READWRITE));
signals[BEGIN] =
g_signal_new ("begin",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GitgIOClass, begin),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
signals[END] =
g_signal_new ("end",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GitgIOClass, end),
NULL,
NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE,
1,
G_TYPE_ERROR);
g_type_class_add_private (object_class, sizeof (GitgIOPrivate));
}
static void
gitg_io_init (GitgIO *self)
{
self->priv = GITG_IO_GET_PRIVATE (self);
}
GitgIO *
gitg_io_new ()
{
return g_object_new (GITG_TYPE_IO, NULL);
}
void
gitg_io_begin (GitgIO *io)
{
g_return_if_fail (GITG_IS_IO (io));
if (!io->priv->running)
{
g_signal_emit (io, signals[BEGIN], 0);
}
}
void
gitg_io_end (GitgIO *io,
GError *error)
{
g_return_if_fail (GITG_IS_IO (io));
if (io->priv->running)
{
g_signal_emit (io, signals[END], 0, error);
}
}
void
gitg_io_cancel (GitgIO *io)
{
if (GITG_IO_GET_CLASS (io)->cancel)
{
GITG_IO_GET_CLASS (io)->cancel (io);
}
}
gboolean
gitg_io_get_cancelled (GitgIO *io)
{
g_return_val_if_fail (GITG_IS_IO (io), FALSE);
return io->priv->cancelled;
}
void
gitg_io_set_cancelled (GitgIO *io,
gboolean cancelled)
{
g_return_if_fail (GITG_IS_IO (io));
if (io->priv->cancelled != cancelled)
{
io->priv->cancelled = cancelled;
g_object_notify (G_OBJECT (io), "cancelled");
}
}
void
gitg_io_set_output (GitgIO *io,
GOutputStream *stream)
{
g_return_if_fail (GITG_IS_IO (io));
g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
if (io->priv->output)
{
g_object_unref (io->priv->output);
io->priv->output = NULL;
}
if (stream)
{
io->priv->output = g_object_ref (stream);
}
}
void
gitg_io_set_input (GitgIO *io,
GInputStream *stream)
{
g_return_if_fail (GITG_IS_IO (io));
g_return_if_fail (G_IS_INPUT_STREAM (stream));
if (io->priv->input)
{
g_object_unref (io->priv->input);
io->priv->input = NULL;
}
if (stream)
{
io->priv->input = g_object_ref (stream);
}
}
GInputStream *
gitg_io_get_input (GitgIO *io)
{
g_return_val_if_fail (GITG_IS_IO (io), NULL);
return io->priv->input;
}
GOutputStream *
gitg_io_get_output (GitgIO *io)
{
g_return_val_if_fail (GITG_IS_IO (io), NULL);
return io->priv->output;
}
void
gitg_io_close (GitgIO *io)
{
g_return_if_fail (GITG_IS_IO (io));
if (io->priv->input)
{
g_input_stream_close (io->priv->input, NULL, NULL);
g_object_unref (io->priv->input);
io->priv->input = NULL;
}
if (io->priv->output)
{
g_output_stream_close (io->priv->output, NULL, NULL);
g_object_unref (io->priv->output);
io->priv->output = NULL;
}
}
gint
gitg_io_get_exit_status (GitgIO *io)
{
g_return_val_if_fail (GITG_IS_IO (io), 0);
return io->priv->exit_status;
}
void
gitg_io_set_exit_status (GitgIO *io,
gint exit_status)
{
g_return_if_fail (GITG_IS_IO (io));
if (io->priv->exit_status != exit_status)
{
io->priv->exit_status = exit_status;
g_object_notify (G_OBJECT (io), "exit-status");
}
}
gboolean
gitg_io_get_running (GitgIO *io)
{
g_return_val_if_fail (GITG_IS_IO (io), FALSE);
return io->priv->running;
}
void
gitg_io_set_running (GitgIO *io,
gboolean running)
{
g_return_if_fail (GITG_IS_IO (io));
if (io->priv->running != running)
{
io->priv->running = running;
if (running)
{
io->priv->cancelled = FALSE;
}
g_object_notify (G_OBJECT (io), "running");
}
}

70
libgitg/gitg-io.h Normal file
View file

@ -0,0 +1,70 @@
#ifndef __GITG_IO_H__
#define __GITG_IO_H__
#include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define GITG_TYPE_IO (gitg_io_get_type ())
#define GITG_IO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_IO, GitgIO))
#define GITG_IO_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_IO, GitgIO const))
#define GITG_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_IO, GitgIOClass))
#define GITG_IS_IO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_IO))
#define GITG_IS_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_IO))
#define GITG_IO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_IO, GitgIOClass))
typedef struct _GitgIO GitgIO;
typedef struct _GitgIOClass GitgIOClass;
typedef struct _GitgIOPrivate GitgIOPrivate;
struct _GitgIO
{
/*< private >*/
GObject parent;
GitgIOPrivate *priv;
/*< public >*/
};
struct _GitgIOClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (*cancel) (GitgIO *io);
/* Signals */
void (*begin) (GitgIO *io);
void (*end) (GitgIO *io, GError *error);
};
GType gitg_io_get_type (void) G_GNUC_CONST;
GitgIO *gitg_io_new (void);
void gitg_io_begin (GitgIO *io);
void gitg_io_end (GitgIO *io, GError *error);
void gitg_io_set_input (GitgIO *io, GInputStream *stream);
void gitg_io_set_output (GitgIO *io, GOutputStream *stream);
GInputStream *gitg_io_get_input (GitgIO *io);
GOutputStream *gitg_io_get_output (GitgIO *io);
void gitg_io_close (GitgIO *io);
void gitg_io_cancel (GitgIO *io);
gboolean gitg_io_get_cancelled (GitgIO *io);
void gitg_io_set_cancelled (GitgIO *io, gboolean cancelled);
gint gitg_io_get_exit_status (GitgIO *io);
void gitg_io_set_exit_status (GitgIO *io, gint status);
gboolean gitg_io_get_running (GitgIO *io);
void gitg_io_set_running (GitgIO *io, gboolean running);
G_END_DECLS
#endif /* __GITG_IO_H__ */

452
libgitg/gitg-line-parser.c Normal file
View file

@ -0,0 +1,452 @@
#include "gitg-line-parser.h"
#define GITG_LINE_PARSER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_LINE_PARSER, GitgLineParserPrivate))
struct _GitgLineParserPrivate
{
gchar *rest_buffer;
gsize rest_buffer_size;
gchar **lines;
guint buffer_size;
gchar *read_buffer;
gboolean preserve_line_endings;
};
enum
{
LINES,
DONE,
NUM_SIGNALS
};
G_DEFINE_TYPE (GitgLineParser, gitg_line_parser, G_TYPE_OBJECT)
enum
{
PROP_0,
PROP_BUFFER_SIZE,
PROP_PRESERVE_LINE_ENDINGS
};
static guint signals[NUM_SIGNALS] = {0,};
typedef struct
{
GitgLineParser *parser;
GInputStream *stream;
GCancellable *cancellable;
} AsyncData;
static AsyncData *
async_data_new (GitgLineParser *parser,
GInputStream *stream,
GCancellable *cancellable)
{
AsyncData *data;
data = g_slice_new (AsyncData);
data->parser = parser;
data->stream = stream;
data->cancellable = g_object_ref (cancellable);
return data;
}
static void
async_data_free (AsyncData *data)
{
g_object_unref (data->cancellable);
g_slice_free (AsyncData, data);
}
static void
free_lines (GitgLineParser *stream)
{
gint i = 0;
while (stream->priv->lines[i])
{
g_free (stream->priv->lines[i++]);
}
stream->priv->lines[0] = NULL;
}
static void
gitg_line_parser_finalize (GObject *object)
{
GitgLineParser *stream;
stream = GITG_LINE_PARSER (object);
free_lines (stream);
g_slice_free1 (sizeof (gchar *) * (stream->priv->buffer_size + 1), stream->priv->lines);
g_slice_free1 (sizeof (gchar) * (stream->priv->buffer_size + 1), stream->priv->read_buffer);
G_OBJECT_CLASS (gitg_line_parser_parent_class)->finalize (object);
}
static const gchar *
find_newline (const gchar *ptr,
const gchar *end,
const gchar **line_end)
{
while (ptr < end)
{
gunichar c;
c = g_utf8_get_char (ptr);
if (c == '\n')
{
/* That's it */
*line_end = g_utf8_next_char (ptr);
return ptr;
}
else if (c == '\r')
{
gchar *next;
next = g_utf8_next_char (ptr);
if (next < end)
{
gunichar n = g_utf8_get_char (next);
if (n == '\n')
{
/* Consume both! */
*line_end = g_utf8_next_char (next);
return ptr;
}
else
{
/* That's it! */
*line_end = next;
return ptr;
}
}
else
{
/* Need to save it, it might come later... */
break;
}
}
ptr = g_utf8_next_char (ptr);
}
return NULL;
}
static void
parse_lines (GitgLineParser *stream,
const gchar *buffer,
gssize size)
{
gchar const *ptr;
gchar const *newline = NULL;
gint i = 0;
gchar *all = NULL;
gchar const *end;
if (stream->priv->rest_buffer_size > 0)
{
GString *str = g_string_sized_new (stream->priv->rest_buffer_size + size);
g_string_append_len (str, stream->priv->rest_buffer, stream->priv->rest_buffer_size);
g_string_append_len (str, buffer, size);
all = g_string_free (str, FALSE);
size += stream->priv->rest_buffer_size;
g_free (stream->priv->rest_buffer);
stream->priv->rest_buffer = NULL;
stream->priv->rest_buffer_size = 0;
ptr = all;
}
else
{
ptr = buffer;
}
const gchar *line_end;
end = ptr + size;
while ((newline = find_newline (ptr, end, &line_end)))
{
if (stream->priv->preserve_line_endings)
{
stream->priv->lines[i++] = g_strndup (ptr, line_end - ptr);
}
else
{
stream->priv->lines[i++] = g_strndup (ptr, newline - ptr);
}
ptr = line_end;
if (i == stream->priv->buffer_size)
{
break;
}
}
if (ptr < end)
{
stream->priv->rest_buffer_size = end - ptr;
stream->priv->rest_buffer = g_strndup (ptr, stream->priv->rest_buffer_size);
}
stream->priv->lines[i] = NULL;
g_signal_emit (stream, signals[LINES], 0, stream->priv->lines);
g_free (all);
}
static void
emit_rest (GitgLineParser *stream)
{
if (stream->priv->rest_buffer_size > 0)
{
if (!stream->priv->preserve_line_endings &&
stream->priv->rest_buffer[stream->priv->rest_buffer_size - 1] == '\r')
{
stream->priv->rest_buffer[stream->priv->rest_buffer_size - 1] = '\0';
}
gchar *b[] = {stream->priv->rest_buffer, NULL};
g_signal_emit (stream, signals[LINES], 0, b);
g_free (stream->priv->rest_buffer);
stream->priv->rest_buffer = NULL;
stream->priv->rest_buffer_size = 0;
}
}
static void
parser_done (AsyncData *data,
GError *error)
{
if (!error)
{
emit_rest (data->parser);
}
g_signal_emit (data->parser, signals[DONE], 0, error);
async_data_free (data);
}
static void
gitg_line_parser_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GitgLineParser *self = GITG_LINE_PARSER (object);
switch (prop_id)
{
case PROP_BUFFER_SIZE:
self->priv->buffer_size = g_value_get_uint (value);
break;
case PROP_PRESERVE_LINE_ENDINGS:
self->priv->preserve_line_endings = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_line_parser_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GitgLineParser *self = GITG_LINE_PARSER (object);
switch (prop_id)
{
case PROP_BUFFER_SIZE:
g_value_set_uint (value, self->priv->buffer_size);
break;
case PROP_PRESERVE_LINE_ENDINGS:
g_value_set_boolean (value, self->priv->preserve_line_endings);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gitg_line_parser_constructed (GObject *object)
{
GitgLineParser *stream;
stream = GITG_LINE_PARSER (object);
stream->priv->lines = g_slice_alloc (sizeof (gchar *) * (stream->priv->buffer_size + 1));
stream->priv->lines[0] = NULL;
stream->priv->read_buffer = g_slice_alloc (sizeof (gchar) * (stream->priv->buffer_size + 1));
}
static void start_read_lines (AsyncData *data);
static void
read_ready (GInputStream *stream,
GAsyncResult *result,
AsyncData *data)
{
gssize read;
GError *error = NULL;
read = g_input_stream_read_finish (stream, result, &error);
if (g_cancellable_is_cancelled (data->cancellable))
{
if (error)
{
g_error_free (error);
}
async_data_free (data);
return;
}
if (read == -1)
{
parser_done (data, error);
if (error)
{
g_error_free (error);
}
}
else if (read == 0)
{
parser_done (data, NULL);
}
else
{
data->parser->priv->read_buffer[read] = '\0';
parse_lines (data->parser,
data->parser->priv->read_buffer,
read);
start_read_lines (data);
}
}
static void
start_read_lines (AsyncData *data)
{
g_input_stream_read_async (data->stream,
data->parser->priv->read_buffer,
data->parser->priv->buffer_size,
G_PRIORITY_DEFAULT,
data->cancellable,
(GAsyncReadyCallback)read_ready,
data);
}
static void
gitg_line_parser_class_init (GitgLineParserClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gitg_line_parser_finalize;
object_class->constructed = gitg_line_parser_constructed;
object_class->get_property = gitg_line_parser_get_property;
object_class->set_property = gitg_line_parser_set_property;
g_type_class_add_private (object_class, sizeof(GitgLineParserPrivate));
signals[LINES] =
g_signal_new ("lines",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
signals[DONE] =
g_signal_new ("done",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE,
1,
G_TYPE_ERROR);
g_object_class_install_property (object_class,
PROP_BUFFER_SIZE,
g_param_spec_uint ("buffer-size",
"Buffer size",
"Buffer Size",
1,
G_MAXUINT,
100,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_PRESERVE_LINE_ENDINGS,
g_param_spec_boolean ("preserve-line-endings",
"Preserve line endings",
"Preserve Line Endings",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
static void
gitg_line_parser_init (GitgLineParser *self)
{
self->priv = GITG_LINE_PARSER_GET_PRIVATE (self);
}
GitgLineParser *
gitg_line_parser_new (guint buffer_size,
gboolean preserve_line_endings)
{
return g_object_new (GITG_TYPE_LINE_PARSER,
"buffer-size", buffer_size,
"preserve-line-endings", preserve_line_endings,
NULL);
}
void
gitg_line_parser_parse (GitgLineParser *parser,
GInputStream *stream,
GCancellable *cancellable)
{
AsyncData *data;
g_return_if_fail (GITG_IS_LINE_PARSER (parser));
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
data = async_data_new (parser, stream, cancellable);
start_read_lines (data);
}

View file

@ -0,0 +1,45 @@
#ifndef __GITG_LINE_PARSER_H__
#define __GITG_LINE_PARSER_H__
#include <gio/gio.h>
G_BEGIN_DECLS
#define GITG_TYPE_LINE_PARSER (gitg_line_parser_get_type ())
#define GITG_LINE_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_LINE_PARSER, GitgLineParser))
#define GITG_LINE_PARSER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_LINE_PARSER, GitgLineParser const))
#define GITG_LINE_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_LINE_PARSER, GitgLineParserClass))
#define GITG_IS_LINE_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_LINE_PARSER))
#define GITG_IS_LINE_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_LINE_PARSER))
#define GITG_LINE_PARSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_LINE_PARSER, GitgLineParserClass))
typedef struct _GitgLineParser GitgLineParser;
typedef struct _GitgLineParserClass GitgLineParserClass;
typedef struct _GitgLineParserPrivate GitgLineParserPrivate;
struct _GitgLineParser
{
/*< private >*/
GObject parent;
GitgLineParserPrivate *priv;
};
struct _GitgLineParserClass
{
/*< private >*/
GObjectClass parent_class;
};
GType gitg_line_parser_get_type (void) G_GNUC_CONST;
GitgLineParser *gitg_line_parser_new (guint buffer_size,
gboolean preserve_line_endings);
void gitg_line_parser_parse (GitgLineParser *parser,
GInputStream *stream,
GCancellable *cancellable);
G_END_DECLS
#endif /* __GITG_LINE_PARSER_H__ */

View file

@ -26,6 +26,7 @@
#include "gitg-lanes.h"
#include "gitg-ref.h"
#include "gitg-config.h"
#include "gitg-shell.h"
#include <gio/gio.h>
#include <sys/time.h>
@ -91,7 +92,7 @@ struct _GitgRepositoryPrivate
GFile *git_dir;
GFile *work_tree;
GitgRunner *loader;
GitgShell *loader;
GHashTable *hashtable;
gint stamp;
GType column_types[N_COLUMNS];
@ -416,7 +417,7 @@ gitg_repository_finalize (GObject *object)
GitgRepository *rp = GITG_REPOSITORY (object);
/* Make sure to cancel the loader */
gitg_runner_cancel (rp->priv->loader);
gitg_io_cancel (GITG_IO (rp->priv->loader));
g_object_unref (rp->priv->loader);
g_object_unref (rp->priv->lanes);
@ -610,16 +611,19 @@ parse_ref_intern (GitgRepository *repository,
gchar const *ref,
gboolean symbolic)
{
gchar **ret = gitg_repository_command_with_outputv (repository,
NULL,
"rev-parse",
"--verify",
symbolic ? "--symbolic-full-name" : ref,
symbolic ? ref : NULL,
NULL);
gchar **ret = gitg_shell_run_sync_with_output (gitg_command_newv (repository,
"rev-parse",
"--verify",
symbolic ? "--symbolic-full-name" : ref,
symbolic ? ref : NULL,
NULL),
FALSE,
NULL);
if (!ret)
{
return NULL;
}
gchar *r = g_strdup (*ret);
g_strfreev (ret);
@ -748,7 +752,7 @@ gitg_repository_class_init (GitgRepositoryClass *klass)
g_param_spec_object ("loader",
"LOADER",
"The repository loader",
GITG_TYPE_RUNNER,
GITG_TYPE_SHELL,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
@ -902,11 +906,11 @@ add_dummy_commit (GitgRepository *repository,
}
static void
on_loader_end_loading (GitgRunner *object,
gboolean cancelled,
on_loader_end_loading (GitgShell *object,
GError *error,
GitgRepository *repository)
{
if (cancelled)
if (gitg_io_get_cancelled (GITG_IO (object)))
{
g_signal_emit (repository, repository_signals[LOADED], 0);
return;
@ -931,7 +935,7 @@ on_loader_end_loading (GitgRunner *object,
if (current == LOAD_STAGE_STAGED)
{
/* Check if there are unstaged changes */
if (show_staged && gitg_runner_get_exit_status (object) != 0)
if (show_staged && gitg_io_get_exit_status (GITG_IO (object)) != 0)
{
add_dummy_commit (repository, TRUE);
}
@ -941,28 +945,29 @@ on_loader_end_loading (GitgRunner *object,
cached = "--cached";
}
gitg_repository_run_commandv (repository,
object,
NULL,
"diff-index",
"--quiet",
head,
cached,
NULL);
gitg_shell_run (object,
gitg_command_newv (repository,
"diff-index",
"--no-ext-diff",
"--quiet",
head,
cached,
NULL),
NULL);
g_free (head);
}
break;
case LOAD_STAGE_UNSTAGED:
if (show_unstaged && gitg_runner_get_exit_status (object) != 0)
if (show_unstaged && gitg_io_get_exit_status (GITG_IO (object)) != 0)
{
add_dummy_commit (repository, FALSE);
}
gitg_repository_run_command (repository,
object,
(gchar const **)repository->priv->last_args,
NULL);
gitg_shell_run (object,
gitg_command_new (repository,
(gchar const * const *)repository->priv->last_args),
NULL);
break;
default:
break;
@ -1106,7 +1111,7 @@ loader_update_commits (GitgRepository *self,
}
static void
on_loader_update (GitgRunner *object,
on_loader_update (GitgShell *object,
gchar **buffer,
GitgRepository *repository)
{
@ -1294,7 +1299,7 @@ gitg_repository_init (GitgRepository *object)
NULL,
(GDestroyNotify)free_refs);
object->priv->loader = gitg_runner_new (10000);
object->priv->loader = gitg_shell_new (10000);
g_signal_connect (object->priv->loader,
"update",
@ -1302,7 +1307,7 @@ gitg_repository_init (GitgRepository *object)
object);
g_signal_connect (object->priv->loader,
"end-loading",
"end",
G_CALLBACK (on_loader_end_loading),
object);
}
@ -1361,11 +1366,11 @@ gitg_repository_get_git_dir (GitgRepository *self)
return g_file_dup (self->priv->git_dir);
}
GitgRunner *
GitgShell *
gitg_repository_get_loader (GitgRepository *self)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (self), NULL);
return GITG_RUNNER (g_object_ref (self->priv->loader));
return GITG_SHELL (g_object_ref (self->priv->loader));
}
static gboolean
@ -1382,15 +1387,15 @@ reload_revisions (GitgRepository *repository,
repository->priv->load_stage = LOAD_STAGE_STASH;
return gitg_repository_run_commandv (repository,
repository->priv->loader,
error,
"log",
"--pretty=format:%H\x01%an\x01%ae\x01%at\x01%s",
"--encoding=UTF-8",
"-g",
"refs/stash",
NULL);
return gitg_shell_run (repository->priv->loader,
gitg_command_newv (repository,
"log",
"--pretty=format:%H\x01%an\x01%ae\x01%at\x01%s",
"--encoding=UTF-8",
"-g",
"refs/stash",
NULL),
error);
}
static gchar *
@ -1402,7 +1407,9 @@ load_current_ref (GitgRepository *self)
gint numargs;
if (self->priv->last_args == NULL)
{
return NULL;
}
numargs = g_strv_length (self->priv->last_args);
@ -1417,14 +1424,16 @@ load_current_ref (GitgRepository *self)
argv[2 + i] = self->priv->last_args[i];
}
out = gitg_repository_command_with_output (self, argv, NULL);
out = gitg_shell_run_sync_with_output (gitg_command_new (self, argv),
FALSE,
NULL);
if (!out)
{
return NULL;
}
if (*out && !* (out + 1))
if (*out && !*(out + 1))
{
ret = g_strdup (*out);
}
@ -1438,12 +1447,13 @@ load_refs (GitgRepository *self)
{
gchar **refs;
refs = gitg_repository_command_with_outputv (self,
NULL,
"for-each-ref",
"--format=%(refname) %(objectname) %(*objectname)",
"refs",
NULL);
refs = gitg_shell_run_sync_with_output (gitg_command_newv (self,
"for-each-ref",
"--format=%(refname) %(objectname) %(*objectname)",
"refs",
NULL),
FALSE,
NULL);
if (!refs)
{
@ -1491,7 +1501,7 @@ gitg_repository_reload (GitgRepository *repository)
g_return_if_fail (GITG_IS_REPOSITORY (repository));
g_return_if_fail (repository->priv->git_dir != NULL);
gitg_runner_cancel (repository->priv->loader);
gitg_io_cancel (GITG_IO (repository->priv->loader));
repository->priv->load_stage = LOAD_STAGE_NONE;
gitg_repository_clear (repository);
@ -1520,7 +1530,7 @@ gitg_repository_load (GitgRepository *self,
return FALSE;
}
gitg_runner_cancel (self->priv->loader);
gitg_io_cancel (GITG_IO (self->priv->loader));
gitg_repository_clear (self);
build_log_args (self, argc, av);
@ -1622,6 +1632,24 @@ gitg_repository_find (GitgRepository *store,
iter);
}
static gint
ref_compare (GitgRef *a,
GitgRef *b)
{
GitgRefType t1 = gitg_ref_get_ref_type (a);
GitgRefType t2 = gitg_ref_get_ref_type (b);
if (t1 != t2)
{
return t1 < t2 ? -1 : 1;
}
else
{
return g_strcmp0 (gitg_ref_get_shortname (a),
gitg_ref_get_shortname (b));
}
}
GSList *
gitg_repository_get_refs (GitgRepository *repository)
{
@ -1635,13 +1663,14 @@ gitg_repository_get_refs (GitgRepository *repository)
{
GSList *val;
for (val = (GSList *)item->data; val; val = val->next)
for (val = item->data; val; val = val->next)
{
ret = g_slist_prepend (ret, gitg_ref_copy ( (GitgRef *)val->data));
ret = g_slist_insert_sorted (ret,
gitg_ref_copy (val->data),
(GCompareFunc)ref_compare);
}
}
ret = g_slist_reverse (ret);
g_list_free (values);
return ret;
@ -1673,297 +1702,6 @@ gitg_repository_relative (GitgRepository *repository,
return g_file_get_relative_path (repository->priv->work_tree, file);
}
gboolean
gitg_repository_run_command_with_input (GitgRepository *repository,
GitgRunner *runner,
gchar const **argv,
gchar const *input,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
g_return_val_if_fail (GITG_IS_RUNNER (runner), FALSE);
g_return_val_if_fail (repository->priv->git_dir != NULL, FALSE);
guint num = g_strv_length ( (gchar **)argv);
guint i;
gchar const **args = g_new0 (gchar const *, num + 6);
gchar *git_dir_path = g_file_get_path (repository->priv->git_dir);
gchar *work_tree_path = g_file_get_path (repository->priv->work_tree);
args[0] = "git";
args[1] = "--git-dir";
args[2] = git_dir_path;
args[3] = "--work-tree";
args[4] = work_tree_path;
for (i = 0; i < num; ++i)
{
args[i + 5] = argv[i];
}
gboolean ret = gitg_runner_run_with_arguments (runner,
repository->priv->work_tree,
args,
input,
error);
g_free (args);
g_free (git_dir_path);
g_free (work_tree_path);
return ret;
}
gboolean
gitg_repository_run_command (GitgRepository *repository,
GitgRunner *runner,
gchar const **argv,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
g_return_val_if_fail (GITG_IS_RUNNER (runner), FALSE);
g_return_val_if_fail (repository->priv->git_dir != NULL, FALSE);
return gitg_repository_run_command_with_input (repository,
runner,
argv,
NULL,
error);
}
gboolean
gitg_repository_command_with_input (GitgRepository *repository,
gchar const **argv,
gchar const *input,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
g_return_val_if_fail (repository->priv->git_dir != NULL, FALSE);
GitgRunner *runner = gitg_runner_new_synchronized (1000);
gboolean ret = gitg_repository_run_command_with_input (repository,
runner,
argv,
input,
error);
g_object_unref (runner);
return ret;
}
gboolean
gitg_repository_command (GitgRepository *repository,
gchar const **argv,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
g_return_val_if_fail (repository->priv->git_dir != NULL, FALSE);
return gitg_repository_command_with_input (repository,
argv,
NULL,
error);
}
typedef struct
{
gchar **buffer;
guint size;
} CommandOutput;
static void
command_with_output_update (GitgRunner *runner,
gchar **buffer,
CommandOutput *output)
{
guint num = g_strv_length (buffer);
guint i;
output->buffer = g_realloc (output->buffer,
sizeof (gchar *) * (output->size + num + 1));
for (i = 0; i < num; ++i)
{
output->buffer[output->size + i] = g_strdup (buffer[i]);
}
output->size += num;
output->buffer[output->size] = NULL;
}
gchar **
gitg_repository_command_with_input_and_output (GitgRepository *repository,
gchar const **argv,
gchar const *input,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), NULL);
g_return_val_if_fail (repository->priv->git_dir != NULL, NULL);
GitgRunner *runner = gitg_runner_new_synchronized (1000);
CommandOutput output = {NULL, 0};
g_signal_connect (runner, "update", G_CALLBACK (command_with_output_update), &output);
gboolean ret = gitg_repository_run_command_with_input (repository,
runner,
argv,
input,
error);
if (!ret)
{
g_strfreev (output.buffer);
output.buffer = NULL;
}
g_object_unref (runner);
return output.buffer;
}
gchar **
gitg_repository_command_with_output (GitgRepository *repository,
gchar const **argv,
GError **error)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), NULL);
g_return_val_if_fail (repository->priv->git_dir != NULL, NULL);
return gitg_repository_command_with_input_and_output (repository,
argv,
NULL,
error);
}
static gchar const **
parse_valist (va_list ap)
{
gchar const *a;
gchar const **ret = NULL;
guint num = 0;
while ( (a = va_arg (ap, gchar const *)) != NULL)
{
ret = g_realloc (ret, sizeof (gchar const *) * (++num + 1));
ret[num - 1] = a;
}
ret[num] = NULL;
return ret;
}
gboolean
gitg_repository_commandv (GitgRepository *repository,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gboolean ret = gitg_repository_command (repository, argv, error);
g_free (argv);
return ret;
}
gboolean
gitg_repository_command_with_inputv (GitgRepository *repository,
gchar const *input,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gboolean ret = gitg_repository_command_with_input (repository,
argv,
input,
error);
g_free (argv);
return ret;
}
gboolean
gitg_repository_run_commandv (GitgRepository *repository,
GitgRunner *runner,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gboolean ret = gitg_repository_run_command (repository,
runner,
argv,
error);
g_free (argv);
return ret;
}
gboolean
gitg_repository_run_command_with_inputv (GitgRepository *repository,
GitgRunner *runner,
gchar const *input,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gboolean ret = gitg_repository_run_command_with_input (repository,
runner,
argv,
input,
error);
g_free (argv);
return ret;
}
gchar **
gitg_repository_command_with_outputv (GitgRepository *repository,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gchar **ret = gitg_repository_command_with_output (repository,
argv,
error);
g_free (argv);
return ret;
}
gchar **
gitg_repository_command_with_input_and_outputv (GitgRepository *repository,
gchar const *input,
GError **error,
...)
{
va_list ap;
va_start (ap, error);
gchar const **argv = parse_valist (ap);
va_end (ap);
gchar **ret = gitg_repository_command_with_input_and_output (repository,
argv,
input,
error);
g_free (argv);
return ret;
}
gchar *
gitg_repository_parse_ref (GitgRepository *repository,
gchar const *ref)
@ -2148,8 +1886,9 @@ gboolean
gitg_repository_get_loaded (GitgRepository *repository)
{
g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
return repository->priv->load_stage == LOAD_STAGE_LAST &&
!gitg_runner_running (repository->priv->loader);
!gitg_io_get_running (GITG_IO (repository->priv->loader));
}
gchar const **

View file

@ -26,7 +26,6 @@
#include <gtk/gtk.h>
#include <libgitg/gitg-revision.h>
#include <libgitg/gitg-runner.h>
#include <libgitg/gitg-ref.h>
G_BEGIN_DECLS
@ -43,7 +42,9 @@ typedef struct _GitgRepository GitgRepository;
typedef struct _GitgRepositoryClass GitgRepositoryClass;
typedef struct _GitgRepositoryPrivate GitgRepositoryPrivate;
typedef enum
struct _GitgShell;
typedef enum
{
GITG_REPOSITORY_NO_ERROR = 0,
GITG_REPOSITORY_ERROR_NOT_FOUND
@ -74,8 +75,6 @@ GFile *gitg_repository_get_git_dir (GitgRepository *repository);
gboolean gitg_repository_exists (GitgRepository *repository);
GitgRunner *gitg_repository_get_loader(GitgRepository *repository);
gboolean gitg_repository_load(GitgRepository *repository, int argc, gchar const **argv, GError **error);
gboolean gitg_repository_get_loaded(GitgRepository *repository);
@ -93,30 +92,13 @@ GitgRef *gitg_repository_get_current_working_ref(GitgRepository *repository);
gchar *gitg_repository_relative(GitgRepository *repository, GFile *file);
/* Running git commands */
gboolean gitg_repository_run_command(GitgRepository *repository, GitgRunner *runner, gchar const **argv, GError **error);
gboolean gitg_repository_run_commandv(GitgRepository *repository, GitgRunner *runner, GError **error, ...) G_GNUC_NULL_TERMINATED;
gboolean gitg_repository_run_command_with_input(GitgRepository *repository, GitgRunner *runner, gchar const **argv, gchar const *input, GError **error);
gboolean gitg_repository_run_command_with_inputv(GitgRepository *repository, GitgRunner *runner, gchar const *input, GError **error, ...) G_GNUC_NULL_TERMINATED;
gboolean gitg_repository_command_with_input(GitgRepository *repository, gchar const **argv, gchar const *input, GError **error);
gboolean gitg_repository_command_with_inputv(GitgRepository *repository, gchar const *input, GError **error, ...) G_GNUC_NULL_TERMINATED;
gboolean gitg_repository_command(GitgRepository *repository, gchar const **argv, GError **error);
gboolean gitg_repository_commandv(GitgRepository *repository, GError **error, ...) G_GNUC_NULL_TERMINATED;
gchar **gitg_repository_command_with_output(GitgRepository *repository, gchar const **argv, GError **error);
gchar **gitg_repository_command_with_outputv(GitgRepository *repository, GError **error, ...) G_GNUC_NULL_TERMINATED;
gchar **gitg_repository_command_with_input_and_output(GitgRepository *repository, gchar const **argv, gchar const *input, GError **error);
gchar **gitg_repository_command_with_input_and_outputv(GitgRepository *repository, gchar const *input, GError **error, ...) G_GNUC_NULL_TERMINATED;
gchar *gitg_repository_parse_ref(GitgRepository *repository, gchar const *ref);
gchar *gitg_repository_parse_head(GitgRepository *repository);
void gitg_repository_reload(GitgRepository *repository);
struct _GitgShell *gitg_repository_get_loader (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);

File diff suppressed because it is too large Load diff

View file

@ -1,102 +1,53 @@
/*
* gitg-runner.h
* This file is part of gitg - git repository viewer
*
* Copyright (C) 2009 - Jesse van den Kieboom
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GITG_RUNNER_H__
#define __GITG_RUNNER_H__
#include <glib-object.h>
#include <libgitg/gitg-command.h>
#include <libgitg/gitg-io.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define GITG_TYPE_RUNNER (gitg_runner_get_type ())
#define GITG_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_RUNNER, GitgRunner))
#define GITG_TYPE_RUNNER (gitg_runner_get_type ())
#define GITG_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_RUNNER, GitgRunner))
#define GITG_RUNNER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_RUNNER, GitgRunner const))
#define GITG_RUNNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_RUNNER, GitgRunnerClass))
#define GITG_IS_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_RUNNER))
#define GITG_IS_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_RUNNER))
#define GITG_IS_RUNNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_RUNNER))
#define GITG_RUNNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_RUNNER, GitgRunnerClass))
#define GITG_RUNNER_ERROR (gitg_runner_error_quark())
typedef struct _GitgRunner GitgRunner;
typedef struct _GitgRunner GitgRunner;
typedef struct _GitgRunnerClass GitgRunnerClass;
typedef struct _GitgRunnerPrivate GitgRunnerPrivate;
typedef enum
struct _GitgRunner
{
GITG_RUNNER_ERROR_NONE = 0,
GITG_RUNNER_ERROR_EXIT
} GitgRunnerError;
struct _GitgRunner {
GObject parent;
/*< private >*/
GitgIO parent;
GitgRunnerPrivate *priv;
/*< public >*/
};
struct _GitgRunnerClass {
GObjectClass parent_class;
struct _GitgRunnerClass
{
/*< private >*/
GitgIOClass parent_class;
/* signals */
void (* begin_loading) (GitgRunner *runner);
void (* update) (GitgRunner *runner, gchar **buffer);
void (* end_loading) (GitgRunner *runner, gboolean cancelled);
/*< public >*/
};
GType gitg_runner_get_type (void) G_GNUC_CONST;
GitgRunner *gitg_runner_new (guint buffer_size);
GitgRunner *gitg_runner_new_synchronized (guint buffer_size);
GitgRunner *gitg_runner_new (GitgCommand *command);
guint gitg_runner_get_buffer_size (GitgRunner *runner);
void gitg_runner_run (GitgRunner *runner);
gboolean gitg_runner_run_stream (GitgRunner *runner,
GInputStream *stream,
GError **error);
GitgCommand *gitg_runner_get_command (GitgRunner *runner);
void gitg_runner_set_command (GitgRunner *runner, GitgCommand *command);
gboolean gitg_runner_run_with_arguments (GitgRunner *runner,
GFile *work_tree,
gchar const **argv,
gchar const *input,
GError **error);
gboolean gitg_runner_run (GitgRunner *runner,
gchar const **argv,
GError **error);
gboolean gitg_runner_running (GitgRunner *runner);
gint gitg_runner_get_exit_status (GitgRunner *runner);
void gitg_runner_cancel (GitgRunner *runner);
void gitg_runner_set_environment (GitgRunner *runner, gchar const **environment);
void gitg_runner_add_environment (GitgRunner *runner, gchar const *key, gchar const *value);
void gitg_runner_set_preserve_line_endings (GitgRunner *runner,
gboolean preserve_line_endings);
gboolean gitg_runner_get_preserve_line_endings (GitgRunner *runner);
GQuark gitg_runner_error_quark (void);
GInputStream *gitg_runner_get_stream (GitgRunner *runner);
void gitg_runner_stream_close (GitgRunner *runner, GError *error);
G_END_DECLS

1052
libgitg/gitg-shell.c Normal file

File diff suppressed because it is too large Load diff

153
libgitg/gitg-shell.h Normal file
View file

@ -0,0 +1,153 @@
/*
* gitg-shell.h
* This file is part of gitg - git repository viewer
*
* Copyright (C) 2009 - Jesse van den Kieboom
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GITG_SHELL_H__
#define __GITG_SHELL_H__
#include <glib-object.h>
#include <libgitg/gitg-io.h>
#include <libgitg/gitg-command.h>
#include <libgitg/gitg-repository.h>
G_BEGIN_DECLS
#define GITG_TYPE_SHELL (gitg_shell_get_type ())
#define GITG_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_SHELL, GitgShell))
#define GITG_SHELL_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_SHELL, GitgShell const))
#define GITG_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_SHELL, GitgShellClass))
#define GITG_IS_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_SHELL))
#define GITG_IS_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_SHELL))
#define GITG_SHELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_SHELL, GitgShellClass))
#define GITG_SHELL_ERROR (gitg_shell_error_quark())
typedef struct _GitgShell GitgShell;
typedef struct _GitgShellClass GitgShellClass;
typedef struct _GitgShellPrivate GitgShellPrivate;
struct _GitgShell
{
GitgIO parent;
GitgShellPrivate *priv;
};
struct _GitgShellClass
{
GitgIOClass parent_class;
/* signals */
void (* update) (GitgShell *shell,
gchar const * const *buffer);
};
GType gitg_shell_get_type (void) G_GNUC_CONST;
GitgShell *gitg_shell_new (guint buffer_size);
GitgShell *gitg_shell_new_synchronized (guint buffer_size);
void gitg_shell_set_preserve_line_endings (GitgShell *shell,
gboolean preserve_line_endings);
gboolean gitg_shell_get_preserve_line_endings (GitgShell *shell);
guint gitg_shell_get_buffer_size (GitgShell *shell);
GitgCommand **gitg_shell_parse_commands (GitgRepository *repository,
const gchar *cmdstr,
GError **error);
gboolean gitg_shell_run_parse (GitgShell *shell,
GitgRepository *repository,
const gchar *cmd,
GError **error);
gboolean gitg_shell_runva (GitgShell *shell,
va_list ap,
GError **error);
gboolean gitg_shell_run_stream (GitgShell *shell,
GInputStream *stream,
GError **error);
gboolean gitg_shell_run (GitgShell *shell,
GitgCommand *command,
GError **error);
gboolean gitg_shell_run_list (GitgShell *shell,
GitgCommand **commands,
GError **error);
gboolean gitg_shell_runv (GitgShell *shell,
GError **error,
...) G_GNUC_NULL_TERMINATED;
gchar **gitg_shell_run_sync_with_output (GitgCommand *command,
gboolean preserve_line_endings,
GError **error);
gchar **gitg_shell_run_sync_with_output_list (GitgCommand **commands,
gboolean preserve_line_endings,
GError **error);
gchar **gitg_shell_run_sync_with_outputv (gboolean preserve_line_endings,
GError **error,
...) G_GNUC_NULL_TERMINATED;
gboolean gitg_shell_run_sync (GitgCommand *command,
GError **error);
gboolean gitg_shell_run_sync_list (GitgCommand **commands,
GError **error);
gboolean gitg_shell_run_syncv (GError **error,
...) G_GNUC_NULL_TERMINATED;
gboolean gitg_shell_run_sync_with_input (GitgCommand *command,
const gchar *input,
GError **error);
gboolean gitg_shell_run_sync_with_input_list (GitgCommand **commands,
const gchar *input,
GError **error);
gboolean gitg_shell_run_sync_with_inputv (const gchar *input,
GError **error,
...) G_GNUC_NULL_TERMINATED;
gchar **gitg_shell_run_sync_with_input_and_output (GitgCommand *command,
gboolean preserve_line_endings,
const gchar *input,
GError **error);
gchar **gitg_shell_run_sync_with_input_and_output_list (GitgCommand **commands,
gboolean preserve_line_endings,
const gchar *input,
GError **error);
gchar **gitg_shell_run_sync_with_input_and_outputv (gboolean preserve_line_endings,
const gchar *input,
GError **error,
...) G_GNUC_NULL_TERMINATED;
G_END_DECLS
#endif /* __GITG_SHELL_H__ */

12
tests/Makefile.am Normal file
View file

@ -0,0 +1,12 @@
INCLUDES = -g -I$(top_srcdir) -I$(top_srcdir)/gitg -I$(top_srcdir)/libgitg $(GITG_DEBUG_FLAGS) $(GITG_CFLAGS)
noinst_PROGRAMS = $(TEST_PROGS)
progs_ldadd = $(top_builddir)/libgitg/libgitg-1.0.la
TEST_PROGS = shell
shell_SOURCES = shell.c
shell_LDADD = $(progs_ldadd)
TESTS = $(TEST_PROGS)
-include $(top_srcdir)/git.mk

273
tests/shell.c Normal file
View file

@ -0,0 +1,273 @@
#include <libgitg/gitg-shell.h>
#include <string.h>
#define test_add_repo(name, callback) g_test_add (name, RepositoryInfo, NULL, repository_setup, callback, repository_cleanup)
typedef struct
{
GitgRepository *repository;
} RepositoryInfo;
static gboolean
remove_all (gchar const *path,
GError **error)
{
gchar const *argv[] = {
"rm",
"-rf",
path,
NULL
};
g_spawn_sync ("/",
(gchar **)argv,
NULL,
G_SPAWN_SEARCH_PATH |
G_SPAWN_STDOUT_TO_DEV_NULL |
G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
error);
}
static void
repository_setup (RepositoryInfo *info,
gconstpointer data)
{
/* Create repository */
gchar const *tmp = g_get_tmp_dir ();
gchar *repo_path;
GError *error = NULL;
repo_path = g_build_filename (tmp, "gitg-test-repo", NULL);
if (g_file_test (repo_path, G_FILE_TEST_EXISTS))
{
remove_all (repo_path, &error);
g_assert_no_error (error);
}
g_assert (g_mkdir (repo_path, 0700) == 0);
gchar const *argv[] = {
"git",
"init",
NULL,
NULL,
NULL
};
g_spawn_sync (repo_path,
(gchar **)argv,
NULL,
G_SPAWN_SEARCH_PATH |
G_SPAWN_STDOUT_TO_DEV_NULL |
G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&error);
g_assert_no_error (error);
argv[0] = "/bin/bash";
argv[1] = "-c";
argv[2] = "echo haha > test.txt && git add test.txt && git commit -m 'Initial import'";
g_spawn_sync (repo_path,
(gchar **)argv,
NULL,
G_SPAWN_STDOUT_TO_DEV_NULL |
G_SPAWN_STDERR_TO_DEV_NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&error);
g_assert_no_error (error);
GFile *work_tree = g_file_new_for_path (repo_path);
gchar *git_dir_path = g_build_filename (repo_path, ".git", NULL);
GFile *git_dir = g_file_new_for_path (git_dir_path);
g_free (git_dir_path);
info->repository = gitg_repository_new (git_dir, work_tree);
g_object_unref (work_tree);
g_object_unref (git_dir);
}
static void
repository_cleanup (RepositoryInfo *info,
gconstpointer data)
{
GFile *work_tree;
GError *error = NULL;
work_tree = gitg_repository_get_work_tree (info->repository);
gchar *path = g_file_get_path (work_tree);
g_object_unref (work_tree);
remove_all (path, &error);
g_free (path);
g_assert_no_error (error);
g_object_unref (info->repository);
}
static void
test_success (RepositoryInfo *info,
gconstpointer data)
{
gboolean ret;
GError *error = NULL;
ret = gitg_shell_run_sync (gitg_command_newv (info->repository,
"rev-parse",
"HEAD",
NULL),
&error);
g_assert_no_error (error);
g_assert (ret);
}
static void
test_fail (RepositoryInfo *info,
gconstpointer data)
{
gboolean ret;
GError *error = NULL;
ret = gitg_shell_run_sync (gitg_command_newv (info->repository,
"bogus",
NULL),
&error);
g_assert (!ret);
g_assert (error != NULL);
g_error_free (error);
}
static void
test_output (RepositoryInfo *info,
gconstpointer data)
{
gchar **ret;
GError *error = NULL;
ret = gitg_shell_run_sync_with_output (gitg_command_newv (info->repository,
"rev-parse",
"HEAD",
NULL),
FALSE,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_strv_length (ret) == 1);
g_assert (strlen (ret[0]) == 40);
}
static void
test_input (void)
{
gchar **ret;
gchar const *input = "Hello world";
GError *error = NULL;
ret = gitg_shell_run_sync_with_input_and_output (gitg_command_newv (NULL,
"cat",
"-",
NULL),
FALSE,
input,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_strv_length (ret) == 1);
g_assert_cmpstr (ret[0], ==, input);
}
static void
test_pipe (void)
{
gchar **ret;
GError *error = NULL;
gchar const *input = "Hello world";
ret = gitg_shell_run_sync_with_outputv (FALSE,
&error,
gitg_command_newv (NULL, "echo", input, NULL),
gitg_command_newv (NULL, "cat", "-", NULL),
NULL);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_strv_length (ret) == 1);
g_assert_cmpstr (ret[0], ==, input);
}
static void
test_pipestr (void)
{
gchar **ret;
GError *error = NULL;
gchar const *input = "Hello world";
gchar *cmdstr;
GitgCommand **commands;
cmdstr = g_strconcat ("echo '", input, "' | cat -", NULL);
commands = gitg_shell_parse_commands (NULL, cmdstr, &error);
g_assert_no_error (error);
g_assert (commands);
ret = gitg_shell_run_sync_with_output_list (commands,
FALSE,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert (g_strv_length (ret) == 1);
g_assert_cmpstr (ret[0], ==, input);
}
int
main (int argc,
char *argv[])
{
g_type_init ();
g_test_init (&argc, &argv, NULL);
gitg_debug_init ();
test_add_repo ("/shell/success", test_success);
test_add_repo ("/shell/fail", test_fail);
test_add_repo ("/shell/output", test_output);
g_test_add_func ("/shell/input", test_input);
g_test_add_func ("/shell/pipe", test_pipe);
g_test_add_func ("/shell/pipestr", test_pipestr);
return g_test_run ();
}
/* ex:ts=8:noet: */

10
tools/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
INCLUDES = -g -I$(top_srcdir) -I$(top_srcdir)/gitg -I$(top_srcdir)/libgitg $(GITG_DEBUG_FLAGS) $(GITG_CFLAGS)
noinst_PROGRAMS = $(TOOLS_PROGS)
tools_ldadd = $(top_builddir)/libgitg/libgitg-1.0.la
TOOLS_PROGS = gitg-shell
gitg_shell_SOURCES = gitg-shell.c
gitg_shell_LDADD = $(tools_ldadd)
-include $(top_srcdir)/git.mk

206
tools/gitg-shell.c Normal file
View file

@ -0,0 +1,206 @@
#include <glib.h>
#include <stdlib.h>
#include <libgitg/gitg-shell.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <libgitg/gitg-debug.h>
static gchar *repository_path = NULL;
static GOptionEntry entries[] =
{
{ "repository", 'r', 0, G_OPTION_ARG_FILENAME, &repository_path, "Repository path" },
{ NULL }
};
static GFile *
find_git_dir (GFile *work_tree)
{
GFile *ret;
work_tree = g_file_dup (work_tree);
while (work_tree)
{
ret = g_file_get_child (work_tree, ".git");
if (g_file_query_exists (ret, NULL))
{
g_object_unref (work_tree);
return ret;
}
else
{
GFile *tmp;
tmp = g_file_get_parent (work_tree);
g_object_unref (work_tree);
work_tree = tmp;
}
}
return NULL;
}
static void
parse_options (int *argc,
char ***argv)
{
GError *error = NULL;
GOptionContext *context;
context = g_option_context_new ("- git shell tool");
g_option_context_set_ignore_unknown_options (context, TRUE);
g_option_context_add_main_entries (context, entries, "gitg");
if (!g_option_context_parse (context, argc, argv, &error))
{
g_print ("option parsing failed: %s\n", error->message);
g_error_free (error);
exit (1);
}
g_option_context_free (context);
}
static void
on_shell_end (GitgShell *shell,
GError *error,
GMainLoop *loop)
{
g_main_loop_quit (loop);
}
int
main (int argc, char *argv[])
{
GitgRepository *repository;
GFile *work_tree;
GFile *git_dir;
gint i;
GString *cmdstr;
gchar *cs;
GitgCommand **commands;
GitgShell *shell;
GMainLoop *loop;
GError *error = NULL;
GInputStream *input;
GOutputStream *output;
g_type_init ();
parse_options (&argc, &argv);
gitg_debug_init ();
if (i == 1)
{
g_print ("Please specify a command...\n");
return 1;
}
if (!repository_path)
{
gchar *path;
GFile *file;
path = g_get_current_dir ();
file = g_file_new_for_path (path);
git_dir = find_git_dir (file);
g_free (path);
g_object_unref (file);
if (git_dir)
{
work_tree = g_file_get_parent (git_dir);
}
}
else
{
work_tree = g_file_new_for_commandline_arg (repository_path);
git_dir = find_git_dir (work_tree);
}
if (!git_dir)
{
g_print ("Could not find git dir...\n");
return 1;
}
repository = gitg_repository_new (git_dir, work_tree);
g_object_unref (work_tree);
g_object_unref (git_dir);
cmdstr = g_string_new ("");
/* Create commands */
for (i = 1; i < argc; ++i)
{
gchar *quoted;
if (strcmp (argv[i], "!") == 0)
{
quoted = g_strdup ("|");
}
else
{
quoted = g_shell_quote (argv[i]);
}
if (i != 1)
{
g_string_append_c (cmdstr, ' ');
}
g_string_append (cmdstr, quoted);
}
cs = g_string_free (cmdstr, FALSE);
g_print ("Running: %s\n\n", cs);
commands = gitg_shell_parse_commands (repository, cs, &error);
g_free (cs);
g_object_unref (repository);
if (error)
{
g_print ("Could not parse arguments: %s\n", error->message);
g_error_free (error);
return 1;
}
loop = g_main_loop_new (NULL, FALSE);
shell = gitg_shell_new (1000);
input = g_unix_input_stream_new (STDIN_FILENO, TRUE);
output = g_unix_output_stream_new (STDOUT_FILENO, TRUE);
gitg_io_set_input (GITG_IO (shell), input);
gitg_io_set_output (GITG_IO (shell), output);
g_signal_connect (shell,
"end",
G_CALLBACK (on_shell_end),
loop);
if (!gitg_shell_run_list (shell, commands, &error))
{
g_print ("Error launching shell: %s\n", error->message);
return 1;
}
g_free (commands);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_object_unref (shell);
return 0;
}