int git_status_list_new()

in src/status.c [261:390]


int git_status_list_new(
	git_status_list **out,
	git_repository *repo,
	const git_status_options *opts)
{
	git_index *index = NULL;
	git_status_list *status = NULL;
	git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT;
	git_diff_find_options findopt = GIT_DIFF_FIND_OPTIONS_INIT;
	git_tree *head = NULL;
	git_status_show_t show =
		opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	int error = 0;
	unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS;

	*out = NULL;

	if (status_validate_options(opts) < 0)
		return -1;

	if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 ||
		(error = git_repository_index(&index, repo)) < 0)
		return error;

	if (opts != NULL && opts->baseline != NULL) {
		head = opts->baseline;
	} else {
		/* if there is no HEAD, that's okay - we'll make an empty iterator */
		if ((error = git_repository_head_tree(&head, repo)) < 0) {
			if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH)
				goto done;
			git_error_clear();
		}
	}

	/* refresh index from disk unless prevented */
	if ((flags & GIT_STATUS_OPT_NO_REFRESH) == 0 &&
		git_index_read_safely(index) < 0)
		git_error_clear();

	status = git_status_list_alloc(index);
	GIT_ERROR_CHECK_ALLOC(status);

	if (opts) {
		memcpy(&status->opts, opts, sizeof(git_status_options));
		memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
	}

	diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE;
	findopt.flags = GIT_DIFF_FIND_FOR_UNTRACKED;

	if ((flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED;
	if ((flags & GIT_STATUS_OPT_INCLUDE_IGNORED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_IGNORED;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNMODIFIED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNMODIFIED;
	if ((flags & GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
	if ((flags & GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
	if ((flags & GIT_STATUS_OPT_RECURSE_IGNORED_DIRS) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_IGNORED_DIRS;
	if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES;
	if ((flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_UPDATE_INDEX;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED;

	if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0)
		findopt.flags = findopt.flags |
			GIT_DIFF_FIND_AND_BREAK_REWRITES |
			GIT_DIFF_FIND_RENAMES_FROM_REWRITES |
			GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY;

	if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) {
		if ((error = git_diff_tree_to_index(
				&status->head2idx, repo, head, index, &diffopt)) < 0)
			goto done;

		if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 &&
			(error = git_diff_find_similar(status->head2idx, &findopt)) < 0)
			goto done;
	}

	if (show != GIT_STATUS_SHOW_INDEX_ONLY) {
		if ((error = git_diff_index_to_workdir(
				&status->idx2wd, repo, index, &diffopt)) < 0) {
			goto done;
		}

		if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 &&
			(error = git_diff_find_similar(status->idx2wd, &findopt)) < 0)
			goto done;
	}

	error = git_diff__paired_foreach(
		status->head2idx, status->idx2wd, status_collect, status);
	if (error < 0)
		goto done;

	if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY)
		git_vector_set_cmp(&status->paired, status_entry_cmp);
	if (flags & GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY)
		git_vector_set_cmp(&status->paired, status_entry_icmp);

	if ((flags &
		 (GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
		  GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR |
		  GIT_STATUS_OPT_SORT_CASE_SENSITIVELY |
		  GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY)) != 0)
		git_vector_sort(&status->paired);

done:
	if (error < 0) {
		git_status_list_free(status);
		status = NULL;
	}

	*out = status;

	if (opts == NULL || opts->baseline != head)
		git_tree_free(head);
	git_index_free(index);

	return error;
}