static GgitRepository * ide_git_vcs_load (IdeGitVcs *self, GError **error) { g_autoptr(GFile) location = NULL; GgitRepository *repository = NULL; IdeContext *context; GFile *project_file; g_assert (IDE_IS_GIT_VCS (self)); context = ide_object_get_context (IDE_OBJECT (self)); project_file = ide_context_get_project_file (context); if (!(location = ggit_repository_discover (project_file, error))) return NULL; if (!(repository = ggit_repository_open (location, error))) return NULL; /* Only set once, on load. Not thread-safe otherwise. */ if (self->working_directory == NULL) self->working_directory = ggit_repository_get_workdir (repository); return repository; }
static void ide_git_vcs_list_status_worker (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { ListStatus *state = task_data; g_autoptr(GListStore) store = NULL; g_autoptr(GFile) workdir = NULL; g_autoptr(GgitRepository) repository = NULL; g_autoptr(GgitStatusOptions) options = NULL; g_autoptr(GString) pathspec = NULL; g_autoptr(GError) error = NULL; g_autofree gchar *relative = NULL; gchar *strv[] = { NULL, NULL }; g_assert (G_IS_TASK (task)); g_assert (IDE_IS_GIT_VCS (source_object)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); g_assert (state != NULL); g_assert (G_IS_FILE (state->repository_location)); if (!(repository = ggit_repository_open (state->repository_location, &error))) { g_task_return_error (task, g_steal_pointer (&error)); return; } if (!(workdir = ggit_repository_get_workdir (repository))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to locate working directory"); return; } g_set_object (&state->workdir, workdir); if (state->directory_or_file != NULL) relative = g_file_get_relative_path (workdir, state->directory_or_file); strv[0] = relative; options = ggit_status_options_new (GGIT_STATUS_OPTION_DEFAULT, GGIT_STATUS_SHOW_INDEX_AND_WORKDIR, (const gchar **)strv); store = g_list_store_new (IDE_TYPE_VCS_FILE_INFO); g_set_object (&state->store, store); if (!ggit_repository_file_status_foreach (repository, options, ide_git_vcs_list_status_cb, state, &error)) g_task_return_error (task, g_steal_pointer (&error)); else g_task_return_pointer (task, g_steal_pointer (&store), g_object_unref); }
static void ide_git_clone_widget_worker (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { IdeGitCloneWidget *self = source_object; GgitRepository *repository; CloneRequest *req = task_data; GgitCloneOptions *clone_options; GgitFetchOptions *fetch_options; GgitRemoteCallbacks *callbacks; IdeProgress *progress; GError *error = NULL; g_assert (G_IS_TASK (task)); g_assert (IDE_IS_GIT_CLONE_WIDGET (self)); g_assert (req != NULL); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); callbacks = g_object_new (IDE_TYPE_GIT_REMOTE_CALLBACKS, NULL); progress = ide_git_remote_callbacks_get_progress (IDE_GIT_REMOTE_CALLBACKS (callbacks)); g_object_bind_property (progress, "fraction", self->clone_progress, "fraction", 0); fetch_options = ggit_fetch_options_new (); ggit_fetch_options_set_remote_callbacks (fetch_options, callbacks); clone_options = ggit_clone_options_new (); ggit_clone_options_set_is_bare (clone_options, FALSE); ggit_clone_options_set_checkout_branch (clone_options, "master"); ggit_clone_options_set_fetch_options (clone_options, fetch_options); g_clear_pointer (&fetch_options, ggit_fetch_options_free); repository = ggit_repository_clone (req->uri, req->location, clone_options, &error); g_clear_object (&callbacks); g_clear_object (&clone_options); if (repository == NULL) { g_task_return_error (task, error); return; } req->project_file = ggit_repository_get_workdir (repository); g_timeout_add (0, finish_animation_in_idle, g_object_ref (task)); g_clear_object (&repository); }
static GgitRepository * ide_git_vcs_load (IdeGitVcs *self, GError **error) { g_autofree gchar *uri = NULL; g_autoptr(GFile) location = NULL; GgitRepository *repository = NULL; IdeContext *context; GFile *project_file; g_assert (IDE_IS_GIT_VCS (self)); g_assert (error != NULL); context = ide_object_get_context (IDE_OBJECT (self)); project_file = ide_context_get_project_file (context); if (!(location = ide_git_vcs_discover (self, project_file, error))) { if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) return NULL; g_clear_error (error); /* Fallback to libgit2(-glib) discovery */ if (!(location = ggit_repository_discover (project_file, error))) return NULL; } uri = g_file_get_uri (location); g_debug ("Discovered .git location at “%s”", uri); if (!(repository = ggit_repository_open (location, error))) return NULL; /* Note: Only set this once on load, otherwise not thread-safe. */ if (self->working_directory == NULL) self->working_directory = ggit_repository_get_workdir (repository); return repository; }
/** * ggit_index_entries_get_by_path: * @entries: a #GgitIndexEntries. * @file: the path to search. * @stage: stage to search. * * Get a #GgitIndexEntry by index. Note that the returned #GgitIndexEntry is * _only_ valid as long as: * * 1) The associated index has not been closed * 2) The entry has not been removed (see ggit_index_remove()) * 3) The index has not been refreshed (see ggit_index_read()) * * Changes to the #GgitIndexEntry will be reflected in the index once written * back to disk using ggit_index_write(). * * @stage indicates the stage to search the file for. Stages are used in the * index when merge conflicts occur, such that multiple versions of the same * file can be represented in the index. Stage 0 is associated with the working * tree, while stages 1 to 3 are associated with the various versions of the * file in a merge conflict. The special value -1 can be used to match the first * file encountered in any stage. * * Returns: (transfer full): a #GgitIndexEntry or %NULL if it was not found. * **/ GgitIndexEntry * ggit_index_entries_get_by_path (GgitIndexEntries *entries, GFile *file, gint stage) { git_index *gidx; const git_index_entry *entry; gchar *path; GgitRepository *repo; GFile *wd; g_return_val_if_fail (entries != NULL, NULL); g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (stage >= 0 && stage <= 3, NULL); repo = ggit_index_get_owner (entries->owner); wd = ggit_repository_get_workdir (repo); path = g_file_get_relative_path (wd, file); g_object_unref (wd); g_object_unref (repo); g_return_val_if_fail (path != NULL, NULL); gidx = _ggit_index_get_index (entries->owner); entry = git_index_get_bypath (gidx, path, stage); g_free (path); if (entry) { return ggit_index_entry_wrap ((git_index_entry *)entry, FALSE); } else { return NULL; } }
static gboolean ide_git_buffer_change_monitor_calculate_threaded (IdeGitBufferChangeMonitor *self, DiffTask *diff, GError **error) { g_autofree gchar *relative_path = NULL; g_autoptr(GFile) workdir = NULL; const guint8 *data; gsize data_len = 0; g_assert (IDE_IS_GIT_BUFFER_CHANGE_MONITOR (self)); g_assert (diff); g_assert (G_IS_FILE (diff->file)); g_assert (diff->state); g_assert (GGIT_IS_REPOSITORY (diff->repository)); g_assert (diff->content); g_assert (!diff->blob || GGIT_IS_BLOB (diff->blob)); g_assert (error); g_assert (!*error); workdir = ggit_repository_get_workdir (diff->repository); if (!workdir) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, _("Repository does not have a working directory.")); return FALSE; } relative_path = g_file_get_relative_path (workdir, diff->file); if (!relative_path) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, _("File is not under control of git working directory.")); return FALSE; } diff->is_child_of_workdir = TRUE; /* * Find the blob if necessary. This will be cached by the main thread for us on the way out * of the async operation. */ if (!diff->blob) { GgitOId *entry_oid = NULL; GgitOId *oid = NULL; GgitObject *blob = NULL; GgitObject *commit = NULL; GgitRef *head = NULL; GgitTree *tree = NULL; GgitTreeEntry *entry = NULL; head = ggit_repository_get_head (diff->repository, error); if (!head) goto cleanup; oid = ggit_ref_get_target (head); if (!oid) goto cleanup; commit = ggit_repository_lookup (diff->repository, oid, GGIT_TYPE_COMMIT, error); if (!commit) goto cleanup; tree = ggit_commit_get_tree (GGIT_COMMIT (commit)); if (!tree) goto cleanup; entry = ggit_tree_get_by_path (tree, relative_path, error); if (!entry) goto cleanup; entry_oid = ggit_tree_entry_get_id (entry); if (!entry_oid) goto cleanup; blob = ggit_repository_lookup (diff->repository, entry_oid, GGIT_TYPE_BLOB, error); if (!blob) goto cleanup; diff->blob = g_object_ref (blob); cleanup: g_clear_object (&blob); g_clear_pointer (&entry_oid, ggit_oid_free); g_clear_pointer (&entry, ggit_tree_entry_unref); g_clear_object (&tree); g_clear_object (&commit); g_clear_pointer (&oid, ggit_oid_free); g_clear_object (&head); } if (!diff->blob) { if ((*error) == NULL) g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("The requested file does not exist within the git index.")); return FALSE; } data = g_bytes_get_data (diff->content, &data_len); ggit_diff_blob_to_buffer (diff->blob, relative_path, data, data_len, relative_path, NULL, NULL, NULL, NULL, diff_line_cb, (gpointer)diff->state, error); return ((*error) == NULL); }