示例#1
0
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;
}
示例#2
0
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);
}
示例#4
0
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;
}
示例#5
0
/**
 * 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);
}