예제 #1
0
파일: gitg-commit.c 프로젝트: mpe/gitg
gboolean 
gitg_commit_add_ignore(GitgCommit *commit, GitgChangedFile *file, GError **error)
{
	g_return_if_fail(GITG_IS_COMMIT(commit));
	g_return_if_fail(GITG_IS_CHANGED_FILE(file));
	
	GFile *f = gitg_changed_file_get_file(file);
	gchar *path = gitg_repository_relative(commit->priv->repository, f);
	
	gchar *ignore = g_strdup_printf("%s/.gitignore", gitg_repository_get_path(commit->priv->repository));
	GFile *ig = g_file_new_for_path(ignore);
	
	GFileOutputStream *stream = g_file_append_to(ig, G_FILE_CREATE_NONE, NULL, error);
	gboolean ret = FALSE;
	
	if (stream)
	{
		gchar *line = g_strdup_printf("/%s\n", path);
		ret = g_output_stream_write_all(G_OUTPUT_STREAM(stream), line, strlen(line), NULL, NULL, error);
		g_output_stream_close(G_OUTPUT_STREAM(stream), NULL, NULL);

		g_object_unref(stream);
		g_free(line);
	}
	
	if (ret)
		remove_file(commit, file);

	g_object_unref(f);	
	g_free(ignore);
	g_free(path);
}
예제 #2
0
파일: gitg-commit.c 프로젝트: mpe/gitg
gboolean
gitg_commit_revert(GitgCommit *commit, GitgChangedFile *file, gchar const *hunk, GError **error)
{
	gboolean ret;
	
	if (!hunk)
	{
		GFile *f = gitg_changed_file_get_file(file);
		gchar *path = gitg_repository_relative(commit->priv->repository, f);
	
		ret = gitg_repository_command_with_inputv(commit->priv->repository, path, error, "checkout-index", "--index", "--quiet", "--force", "--stdin", NULL);
		
		g_free(path);
		
		remove_file(commit, file);
		g_object_unref(f);
	}
	else
	{
		GitgRunner *runner = gitg_runner_new_synchronized(1000);
		gchar const *argv[] = {"patch", "-p1", "-R", NULL};
		
		ret = gitg_runner_run_with_arguments(runner, argv, gitg_repository_get_path(commit->priv->repository), hunk, NULL); 
	
		update_index_file(commit, file);
		update_index_unstaged(commit, file);
		
		g_object_unref(runner);
	}
	
	return ret;
}
예제 #3
0
파일: gitg-commit.c 프로젝트: mpe/gitg
static void
read_other_files_update(GitgRunner *runner, gchar **buffer, GitgCommit *commit)
{
	gchar *line;

	while ((line = *buffer++))
	{
		/* Skip empty lines */
		if (!*line)
			continue;
			
		/* Check if file is already in our index */
		gboolean added = FALSE;
		GSList *item;
		gchar *path = g_build_filename(gitg_repository_get_path(commit->priv->repository), line, NULL);
		
		GFile *file = g_file_new_for_path(path);
		g_free(path);
		GitgChangedFile *f = g_hash_table_lookup(commit->priv->files, file);
		
		if (f)
		{
			changed_file_new(f);
			g_object_unref(file);
			continue;
		}
		
		f = gitg_changed_file_new(file);

		changed_file_new(f);		
		g_hash_table_insert(commit->priv->files, file, f);
		
		g_signal_emit(commit, commit_signals[INSERTED], 0, f);
	}
}
예제 #4
0
파일: gitg-window.c 프로젝트: mpe/gitg
static void
add_recent_item(GitgWindow *window)
{
	GtkRecentManager *manager = gtk_recent_manager_get_default();
	GtkRecentData data = { 0 };
	gchar *groups[] = {"gitg", NULL};
	gchar const *path = gitg_repository_get_path(window->priv->repository);
	gchar *basename = g_path_get_basename(path);
	
	data.display_name = basename;
	data.app_name = "gitg";
	data.mime_type = "inode/directory";
	data.app_exec = "gitg %f";
	data.groups = groups;

	GFile *file = g_file_new_for_path(gitg_repository_get_path(window->priv->repository));
	gchar *uri = g_file_get_uri(file);
	gtk_recent_manager_add_full(manager, uri, &data);
	
	g_free(basename);
	g_free(uri);
	g_object_unref(file);
}
예제 #5
0
파일: gitg-utils.c 프로젝트: hb/gitg
gboolean
gitg_utils_export_files(GitgRepository *repository, GitgRevision *revision,
                        gchar const *todir, gchar * const *paths)
{
    GString *gstr = g_string_new("sh -c \"git --git-dir");

    // Append the git path
    gchar *gitpath = gitg_utils_dot_git_path(gitg_repository_get_path(repository));
    append_escape(gstr, gitpath);
    g_free(gitpath);

    // Append the revision
    gchar *sha = gitg_revision_get_sha1(revision);
    g_string_append_printf(gstr, " archive --format=tar %s", sha);
    g_free(sha);

    // Append the files
    while (*paths)
    {
        append_escape(gstr, *paths);
        paths++;
    }

    g_string_append(gstr, " | tar -xC");
    append_escape(gstr, todir);
    g_string_append(gstr, "\"");

    GError *error = NULL;
    gint status;

    gboolean ret = g_spawn_command_line_sync(gstr->str, NULL, NULL, &status, &error);

    if (!ret)
    {
        g_warning("Export failed:\n%s\n%s", gstr->str, error->message);
        g_error_free(error);
    }

    g_string_free(gstr, TRUE);
    return ret;
}
예제 #6
0
파일: gitg-window.c 프로젝트: mpe/gitg
static gboolean
create_repository(GitgWindow *window, gchar const *path, gboolean usewd)
{
	gboolean ret = TRUE;

	if (path)
	{
		gchar realp[PATH_MAX];
		
		if (realpath(path, realp))
		{
			window->priv->repository = gitg_repository_new(realp);
		
			if (!gitg_repository_get_path(window->priv->repository))
			{
				// Try current directory
				path = NULL;
				g_object_unref(window->priv->repository);
				window->priv->repository = NULL;
			
				ret = FALSE;
			}
		}
		else
		{
			ret = FALSE;
			path = NULL;
		}
	}
	
	if (!path && usewd)
	{
		gchar *curdir = g_get_current_dir();
		window->priv->repository = gitg_repository_new(curdir);
		g_free(curdir);
	}
	
	return ret;	
}
예제 #7
0
파일: gitg-window.c 프로젝트: mpe/gitg
static void
load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **argv, gboolean usewd)
{
	if (window->priv->repository)
	{
		gtk_tree_view_set_model(window->priv->tree_view, NULL);
		g_signal_handlers_disconnect_by_func(window->priv->repository, G_CALLBACK(on_repository_load), window);

		g_object_unref(window->priv->repository);
		window->priv->repository = NULL;
	}
	
	gboolean haspath = create_repository(window, path, usewd);
	
	if (window->priv->repository && gitg_repository_get_path(window->priv->repository))
	{
		gtk_tree_view_set_model(window->priv->tree_view, GTK_TREE_MODEL(window->priv->repository));
		GitgRunner *loader = gitg_repository_get_loader(window->priv->repository);
	
		g_signal_connect(loader, "begin-loading", G_CALLBACK(on_begin_loading), window);
		g_signal_connect(loader, "end-loading", G_CALLBACK(on_end_loading), window);
		g_signal_connect(loader, "update", G_CALLBACK(on_update), window);
		
		g_object_unref(loader);
		
		gchar const **ar = argv;

		if (!haspath && path)
		{
			ar = (gchar const **)g_new(gchar *, ++argc);
			
			int i;
			for (i = 0; i < argc - 1; ++i)
				ar[i] = argv[i];

			ar[argc - 1] = path;
		}
예제 #8
0
파일: gitg-commit.c 프로젝트: mpe/gitg
static void
add_files(GitgCommit *commit, gchar **buffer, gboolean cached)
{
	gchar *line;
	
	while (line = *buffer++)
	{
		gchar **parts = g_strsplit_set(line, " \t", 0);
		guint len = g_strv_length(parts);
		
		if (len < 6)
		{
			g_warning("Invalid line: %s (%d)", line, len);
			g_strfreev(parts);
			continue;
		}
		
		gchar const *mode = parts[0] + 1;
		gchar const *sha = parts[2];
		GSList *item;
		
		gchar *path = g_build_filename(gitg_repository_get_path(commit->priv->repository), parts[5], NULL);
		
		GFile *file = g_file_new_for_path(path);
		g_free(path);

		GitgChangedFile *f = GITG_CHANGED_FILE(g_hash_table_lookup(commit->priv->files, file));
		
		if (f)
		{
			GitgChangedFileChanges changes = gitg_changed_file_get_changes(f);
			
			g_object_set_data(G_OBJECT(f), CAN_DELETE_KEY, NULL);
			
			if (cached)
			{
				gitg_changed_file_set_sha(f, sha);
				gitg_changed_file_set_mode(f, mode);
				
				changes |= GITG_CHANGED_FILE_CHANGES_CACHED;
			}
			else
			{
				changes |= GITG_CHANGED_FILE_CHANGES_UNSTAGED;
			}
			
			gitg_changed_file_set_changes(f, changes);
			
			g_object_unref(file);
			g_strfreev(parts);
			continue;
		}
		
		f = gitg_changed_file_new(file);
		GitgChangedFileStatus status;
		
		if (strcmp(parts[4], "D") == 0)
			status = GITG_CHANGED_FILE_STATUS_DELETED;
		else if (strcmp(mode, "000000") == 0)
			status = GITG_CHANGED_FILE_STATUS_NEW;
		else
			status = GITG_CHANGED_FILE_STATUS_MODIFIED;
		
		gitg_changed_file_set_status(f, status);
		gitg_changed_file_set_sha(f, sha);
		gitg_changed_file_set_mode(f, mode);

		GitgChangedFileChanges changes;
		
		changes = cached ? GITG_CHANGED_FILE_CHANGES_CACHED : GITG_CHANGED_FILE_CHANGES_UNSTAGED;
		gitg_changed_file_set_changes(f, changes);
		
		g_hash_table_insert(commit->priv->files, file, f);
		g_signal_emit(commit, commit_signals[INSERTED], 0, f);

		g_strfreev(parts);
	}
}