filter.c 2.08 KB
Newer Older
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
3 4 5 6 7 8 9 10 11
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "common.h"
#include "fileops.h"
#include "hash.h"
#include "filter.h"
12 13
#include "repository.h"
#include "git2/config.h"
14
#include "blob.h"
15

16
int git_filters_load(git_vector *filters, git_repository *repo, const char *path, int mode)
17
{
18 19 20
	int error;

	if (mode == GIT_FILTER_TO_ODB) {
21 22
		/* Load the CRLF cleanup filter when writing to the ODB */
		error = git_filter_add__crlf_to_odb(filters, repo, path);
23
		if (error < 0)
24 25
			return error;
	} else {
26 27 28
		error = git_filter_add__crlf_to_workdir(filters, repo, path);
		if (error < 0)
			return error;
29 30
	}

31
	return (int)filters->length;
32 33
}

34
void git_filters_free(git_vector *filters)
35 36 37 38 39 40 41 42
{
	size_t i;
	git_filter *filter;

	git_vector_foreach(filters, i, filter) {
		if (filter->do_free != NULL)
			filter->do_free(filter);
		else
43
			git__free(filter);
44 45 46 47 48
	}

	git_vector_free(filters);
}

49
int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
50
{
51 52
	size_t i;
	unsigned int src;
53 54 55 56 57 58 59
	git_buf *dbuffer[2];

	dbuffer[0] = source;
	dbuffer[1] = dest;

	src = 0;

nulltoken committed
60
	if (git_buf_len(source) == 0) {
61
		git_buf_clear(dest);
62
		return 0;
63 64
	}

65 66
	/* Pre-grow the destination buffer to more or less the size
	 * we expect it to have */
nulltoken committed
67
	if (git_buf_grow(dest, git_buf_len(source)) < 0)
68
		return -1;
69 70

	for (i = 0; i < filters->length; ++i) {
71
		git_filter *filter = git_vector_get(filters, i);
72
		unsigned int dst = 1 - src;
73 74 75

		git_buf_clear(dbuffer[dst]);

76
		/* Apply the filter from dbuffer[src] to the other buffer;
77 78 79 80 81
		 * if the filtering is canceled by the user mid-filter,
		 * we skip to the next filter without changing the source
		 * of the double buffering (so that the text goes through
		 * cleanly).
		 */
82 83
		if (filter->apply(filter, dbuffer[dst], dbuffer[src]) == 0)
			src = dst;
84 85

		if (git_buf_oom(dbuffer[dst]))
86
			return -1;
87 88 89
	}

	/* Ensure that the output ends up in dbuffer[1] (i.e. the dest) */
90
	if (src != 1)
91 92
		git_buf_swap(dest, source);

93
	return 0;
94
}