mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-08-24 18:36:25 +00:00
Used hash table for storing files instead of gslist and implemented (untested) stage/unstage hunk
This commit is contained in:
parent
587610de89
commit
dad4c038fe
|
@ -32,7 +32,7 @@ struct _GitgCommitPrivate
|
||||||
guint update_id;
|
guint update_id;
|
||||||
guint end_id;
|
guint end_id;
|
||||||
|
|
||||||
GSList *files;
|
GHashTable *files;
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint commit_signals[LAST_SIGNAL] = { 0 };
|
static guint commit_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
@ -67,8 +67,7 @@ gitg_commit_finalize(GObject *object)
|
||||||
|
|
||||||
g_free(commit->priv->dotgit);
|
g_free(commit->priv->dotgit);
|
||||||
|
|
||||||
g_slist_foreach(commit->priv->files, (GFunc)g_object_unref, NULL);
|
g_hash_table_destroy(commit->priv->files);
|
||||||
g_slist_free(commit->priv->files);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS(gitg_commit_parent_class)->finalize(object);
|
G_OBJECT_CLASS(gitg_commit_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
@ -178,6 +177,7 @@ gitg_commit_init(GitgCommit *self)
|
||||||
self->priv = GITG_COMMIT_GET_PRIVATE(self);
|
self->priv = GITG_COMMIT_GET_PRIVATE(self);
|
||||||
|
|
||||||
self->priv->runner = gitg_runner_new(5000);
|
self->priv->runner = gitg_runner_new(5000);
|
||||||
|
self->priv->files = g_hash_table_new_full(g_file_hash, (GEqualFunc)g_file_equal, (GDestroyNotify)g_object_unref, (GDestroyNotify)g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
GitgCommit *
|
GitgCommit *
|
||||||
|
@ -229,50 +229,39 @@ add_files(GitgCommit *commit, gchar **buffer, gboolean cached)
|
||||||
gchar const *sha = parts[2];
|
gchar const *sha = parts[2];
|
||||||
GSList *item;
|
GSList *item;
|
||||||
|
|
||||||
gboolean new = TRUE;
|
|
||||||
gchar *path = g_build_filename(gitg_repository_get_path(commit->priv->repository), parts[5], NULL);
|
gchar *path = g_build_filename(gitg_repository_get_path(commit->priv->repository), parts[5], NULL);
|
||||||
|
|
||||||
GFile *file = g_file_new_for_path(path);
|
GFile *file = g_file_new_for_path(path);
|
||||||
g_free(path);
|
g_free(path);
|
||||||
|
|
||||||
for (item = commit->priv->files; item; item = item->next)
|
GitgChangedFile *f = GITG_CHANGED_FILE(g_hash_table_lookup(commit->priv->files, file));
|
||||||
{
|
|
||||||
GitgChangedFile *f = GITG_CHANGED_FILE(item->data);
|
|
||||||
|
|
||||||
if (gitg_changed_file_equal(f, file))
|
if (f)
|
||||||
|
{
|
||||||
|
GitgChangedFileChanges changes;
|
||||||
|
|
||||||
|
g_object_set_data(G_OBJECT(changes), CAN_DELETE_KEY, NULL);
|
||||||
|
|
||||||
|
if (cached)
|
||||||
{
|
{
|
||||||
GitgChangedFileChanges changes;
|
gitg_changed_file_set_sha(f, sha);
|
||||||
|
gitg_changed_file_set_mode(f, sha);
|
||||||
|
|
||||||
g_object_set_data(G_OBJECT(changes), CAN_DELETE_KEY, NULL);
|
changes = GITG_CHANGED_FILE_CHANGES_CACHED;
|
||||||
|
}
|
||||||
if (cached)
|
else
|
||||||
{
|
{
|
||||||
gitg_changed_file_set_sha(f, sha);
|
changes = GITG_CHANGED_FILE_CHANGES_UNSTAGED;
|
||||||
gitg_changed_file_set_mode(f, sha);
|
|
||||||
|
|
||||||
changes = GITG_CHANGED_FILE_CHANGES_CACHED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
changes = GITG_CHANGED_FILE_CHANGES_UNSTAGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
gitg_changed_file_set_changes(f, changes);
|
|
||||||
new = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!new)
|
gitg_changed_file_set_changes(f, changes);
|
||||||
{
|
|
||||||
g_object_unref(file);
|
g_object_unref(file);
|
||||||
g_strfreev(parts);
|
g_strfreev(parts);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GitgChangedFile *f = gitg_changed_file_new(file);
|
f = gitg_changed_file_new(file);
|
||||||
g_object_unref(file);
|
|
||||||
|
|
||||||
GitgChangedFileStatus status;
|
GitgChangedFileStatus status;
|
||||||
|
|
||||||
if (strcmp(parts[4], "D") == 0)
|
if (strcmp(parts[4], "D") == 0)
|
||||||
|
@ -291,8 +280,9 @@ add_files(GitgCommit *commit, gchar **buffer, gboolean cached)
|
||||||
changes = cached ? GITG_CHANGED_FILE_CHANGES_CACHED : GITG_CHANGED_FILE_CHANGES_UNSTAGED;
|
changes = cached ? GITG_CHANGED_FILE_CHANGES_CACHED : GITG_CHANGED_FILE_CHANGES_UNSTAGED;
|
||||||
gitg_changed_file_set_changes(f, changes);
|
gitg_changed_file_set_changes(f, changes);
|
||||||
|
|
||||||
commit->priv->files = g_slist_prepend(commit->priv->files, f);
|
g_hash_table_insert(commit->priv->files, file, f);
|
||||||
g_signal_emit(commit, commit_signals[INSERTED], 0, f);
|
g_signal_emit(commit, commit_signals[INSERTED], 0, f);
|
||||||
|
|
||||||
g_strfreev(parts);
|
g_strfreev(parts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,30 +293,20 @@ read_cached_files_update(GitgRunner *runner, gchar **buffer, GitgCommit *commit)
|
||||||
add_files(commit, buffer, TRUE);
|
add_files(commit, buffer, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
delete_file(GFile *key, GitgChangedFile *value, GitgCommit *commit)
|
||||||
|
{
|
||||||
|
if (!g_object_get_data(G_OBJECT(value), CAN_DELETE_KEY))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_signal_emit(commit, commit_signals[REMOVED], 0, value);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
refresh_done(GitgRunner *runner, GitgCommit *commit)
|
refresh_done(GitgRunner *runner, GitgCommit *commit)
|
||||||
{
|
{
|
||||||
GSList *item = commit->priv->files;
|
g_hash_table_foreach_remove(commit->priv->files, (GHRFunc)delete_file, commit);
|
||||||
|
|
||||||
while (item)
|
|
||||||
{
|
|
||||||
GitgChangedFile *file = GITG_CHANGED_FILE(item->data);
|
|
||||||
|
|
||||||
if (g_object_get_data(G_OBJECT(file), CAN_DELETE_KEY))
|
|
||||||
{
|
|
||||||
GSList *tmp = item->next;
|
|
||||||
|
|
||||||
commit->priv->files = g_slist_remove_link(commit->priv->files, item);
|
|
||||||
|
|
||||||
g_signal_emit(commit, commit_signals[REMOVED], 0, file);
|
|
||||||
g_object_unref(file);
|
|
||||||
item = tmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item = g_slist_next(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -385,31 +365,20 @@ read_other_files_update(GitgRunner *runner, gchar **buffer, GitgCommit *commit)
|
||||||
|
|
||||||
GFile *file = g_file_new_for_path(path);
|
GFile *file = g_file_new_for_path(path);
|
||||||
g_free(path);
|
g_free(path);
|
||||||
|
GitgChangedFile *f = g_hash_table_lookup(commit->priv->files, file);
|
||||||
|
|
||||||
for (item = commit->priv->files; item; item = item->next)
|
if (f)
|
||||||
{
|
|
||||||
GitgChangedFile *f = (GitgChangedFile *)item->data;
|
|
||||||
|
|
||||||
if (gitg_changed_file_equal(f, file))
|
|
||||||
{
|
|
||||||
added = TRUE;
|
|
||||||
changed_file_new(f);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added)
|
|
||||||
{
|
{
|
||||||
|
changed_file_new(f);
|
||||||
g_object_unref(file);
|
g_object_unref(file);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GitgChangedFile *f = gitg_changed_file_new(file);
|
f = gitg_changed_file_new(file);
|
||||||
|
|
||||||
changed_file_new(f);
|
changed_file_new(f);
|
||||||
g_object_unref(file);
|
g_hash_table_insert(commit->priv->files, file, f);
|
||||||
|
|
||||||
commit->priv->files = g_slist_prepend(commit->priv->files, f);
|
|
||||||
g_signal_emit(commit, commit_signals[INSERTED], 0, f);
|
g_signal_emit(commit, commit_signals[INSERTED], 0, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,9 +407,9 @@ update_index(GitgCommit *commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_can_delete(GitgChangedFile *file, GitgCommit *commit)
|
set_can_delete(GFile *key, GitgChangedFile *value, GitgCommit *commit)
|
||||||
{
|
{
|
||||||
g_object_set_data(G_OBJECT(file), CAN_DELETE_KEY, GINT_TO_POINTER(TRUE));
|
g_object_set_data(G_OBJECT(value), CAN_DELETE_KEY, GINT_TO_POINTER(TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -450,20 +419,50 @@ gitg_commit_refresh(GitgCommit *commit)
|
||||||
|
|
||||||
runner_cancel(commit);
|
runner_cancel(commit);
|
||||||
|
|
||||||
g_slist_foreach(commit->priv->files, (GFunc)set_can_delete, commit);
|
g_hash_table_foreach(commit->priv->files, (GHFunc)set_can_delete, commit);
|
||||||
|
|
||||||
/* Read other files */
|
/* Read other files */
|
||||||
update_index(commit);
|
update_index(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gitg_commit_stage(GitgCommit *commit)
|
apply_hunk(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, gboolean reverse, GError **error)
|
||||||
{
|
{
|
||||||
g_return_if_fail(GITG_IS_COMMIT(commit));
|
if (error)
|
||||||
|
*error = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail(GITG_IS_COMMIT(commit), FALSE);
|
||||||
|
g_return_val_if_fail(GITG_IS_CHANGED_FILE(file), FALSE);
|
||||||
|
|
||||||
|
g_return_val_if_fail(hunk != NULL, FALSE);
|
||||||
|
|
||||||
|
GitgRunner *runner = gitg_runner_new_synchronized(100);
|
||||||
|
gchar *dotgit = gitg_utils_dot_git_path(gitg_repository_get_path(commit->priv->repository));
|
||||||
|
|
||||||
|
gchar const *argv[] = {"git", "--git-dir", dotgit, "apply", "--cached", NULL, NULL};
|
||||||
|
|
||||||
|
if (reverse)
|
||||||
|
argv[5] = "--reverse";
|
||||||
|
|
||||||
|
gboolean ret = gitg_runner_run_with_input(runner, argv, hunk, error);
|
||||||
|
g_free(dotgit);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gitg_commit_unstage(GitgCommit *commit)
|
gitg_commit_stage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error)
|
||||||
{
|
{
|
||||||
g_return_if_fail(GITG_IS_COMMIT(commit));
|
return apply_hunk(commit, file, hunk, FALSE, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gitg_commit_unstage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error)
|
||||||
|
{
|
||||||
|
return apply_hunk(commit, file, hunk, FALSE, error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ GType gitg_commit_get_type(void) G_GNUC_CONST;
|
||||||
GitgCommit *gitg_commit_new(GitgRepository *repository);
|
GitgCommit *gitg_commit_new(GitgRepository *repository);
|
||||||
|
|
||||||
void gitg_commit_refresh(GitgCommit *commit);
|
void gitg_commit_refresh(GitgCommit *commit);
|
||||||
void gitg_commit_stage(GitgCommit *commit);
|
gboolean gitg_commit_stage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error);
|
||||||
void gitg_commit_unstage(GitgCommit *commit);
|
gboolean gitg_commit_unstage(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue