Exemplo n.º 1
0
static int git_diff_driver_builtin(
	git_diff_driver **out,
	git_diff_driver_registry *reg,
	const char *driver_name)
{
	int error = 0;
	git_diff_driver_definition *ddef = NULL;
	git_diff_driver *drv = NULL;
	size_t namelen, idx;

	for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) {
		if (!strcasecmp(driver_name, builtin_defs[idx].name)) {
			ddef = &builtin_defs[idx];
			break;
		}
	}
	if (!ddef)
		goto done;

	namelen = strlen(ddef->name);

	drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
	GITERR_CHECK_ALLOC(drv);

	drv->type = DIFF_DRIVER_PATTERNLIST;
	memcpy(drv->name, ddef->name, namelen);

	if (ddef->fns &&
		(error = diff_driver_add_patterns(
			drv, ddef->fns, ddef->flags | REG_EXTENDED)) < 0)
		goto done;

	if (ddef->words &&
		(error = regcomp(
			&drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED)))
	{
		error = giterr_set_regex(&drv->word_pattern, error);
		goto done;
	}

	git_strmap_insert(reg->drivers, drv->name, drv, error);
	if (error > 0)
		error = 0;

done:
	if (error && drv)
		git_diff_driver_free(drv);
	else
		*out = drv;

	return error;
}
Exemplo n.º 2
0
static int build_regex(regex_t *regex, const char *pattern)
{
	int error;

	if (*pattern == '\0') {
		giterr_set(GITERR_REGEX, "Empty pattern");
		return -1;
	}

	error = regcomp(regex, pattern, REG_EXTENDED);
	if (!error)
		return 0;
	
	giterr_set_regex(regex, error);
	regfree(regex);

	return -1;
}
Exemplo n.º 3
0
static int diff_driver_add_patterns(
	git_diff_driver *drv, const char *regex_str, int regex_flags)
{
	int error = 0;
	const char *scan, *end;
	git_diff_driver_pattern *pat = NULL;
	git_buf buf = GIT_BUF_INIT;

	for (scan = regex_str; scan; scan = end) {
		/* get pattern to fill in */
		if ((pat = git_array_alloc(drv->fn_patterns)) == NULL) {
			error = -1;
			break;
		}

		pat->flags = regex_flags;
		if (*scan == '!') {
			pat->flags |= REG_NEGATE;
			++scan;
		}

		if ((end = strchr(scan, '\n')) != NULL) {
			error = git_buf_set(&buf, scan, end - scan);
			end++;
		} else {
			error = git_buf_sets(&buf, scan);
		}
		if (error < 0)
			break;

		if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) < 0) {
			/* if regex fails to compile, warn? fail? */
			error = giterr_set_regex(&pat->re, error);
			regfree(&pat->re);
			break;
		}
	}

	if (error && pat != NULL)
		(void)git_array_pop(drv->fn_patterns); /* release last item */
	git_buf_free(&buf);

	return error;
}
Exemplo n.º 4
0
static int build_regex(regex_t *regex, const char *pattern)
{
	int error;

	if (*pattern == '\0') {
		giterr_set(GITERR_REGEX, "empty pattern");
		return GIT_EINVALIDSPEC;
	}

	error = p_regcomp(regex, pattern, REG_EXTENDED);
	if (!error)
		return 0;

	error = giterr_set_regex(regex, error);

	regfree(regex);

	return error;
}
Exemplo n.º 5
0
static int git_diff_driver_load(
	git_diff_driver **out, git_repository *repo, const char *driver_name)
{
	int error = 0;
	git_diff_driver_registry *reg;
	git_diff_driver *drv = NULL;
	size_t namelen = strlen(driver_name);
	khiter_t pos;
	git_config *cfg;
	git_buf name = GIT_BUF_INIT;
	const git_config_entry *ce;
	bool found_driver = false;

	if ((reg = git_repository_driver_registry(repo)) == NULL)
		return -1;

	pos = git_strmap_lookup_index(reg->drivers, driver_name);
	if (git_strmap_valid_index(reg->drivers, pos)) {
		*out = git_strmap_value_at(reg->drivers, pos);
		return 0;
	}

	drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
	GITERR_CHECK_ALLOC(drv);
	drv->type = DIFF_DRIVER_AUTO;
	memcpy(drv->name, driver_name, namelen);

	/* if you can't read config for repo, just use default driver */
	if (git_repository_config_snapshot(&cfg, repo) < 0) {
		giterr_clear();
		goto done;
	}

	if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0)
		goto done;

	switch (git_config__get_bool_force(cfg, name.ptr, -1)) {
	case true:
		/* if diff.<driver>.binary is true, just return the binary driver */
		*out = &global_drivers[DIFF_DRIVER_BINARY];
		goto done;
	case false:
		/* if diff.<driver>.binary is false, force binary checks off */
		/* but still may have custom function context patterns, etc. */
		drv->binary_flags = GIT_DIFF_FORCE_TEXT;
		found_driver = true;
		break;
	default:
		/* diff.<driver>.binary unspecified or "auto", so just continue */
		break;
	}

	/* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "xfuncname", strlen("xfuncname"));
	if ((error = git_config_get_multivar_foreach(
			cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) {
		if (error != GIT_ENOTFOUND)
			goto done;
		giterr_clear(); /* no diff.<driver>.xfuncname, so just continue */
	}

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "funcname", strlen("funcname"));
	if ((error = git_config_get_multivar_foreach(
			cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) {
		if (error != GIT_ENOTFOUND)
			goto done;
		giterr_clear(); /* no diff.<driver>.funcname, so just continue */
	}

	/* if we found any patterns, set driver type to use correct callback */
	if (git_array_size(drv->fn_patterns) > 0) {
		drv->type = DIFF_DRIVER_PATTERNLIST;
		found_driver = true;
	}

	git_buf_truncate(&name, namelen + strlen("diff.."));
	git_buf_put(&name, "wordregex", strlen("wordregex"));
	if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0)
		goto done;
	if (!ce || !ce->value)
		/* no diff.<driver>.wordregex, so just continue */;
	else if (!(error = regcomp(&drv->word_pattern, ce->value, REG_EXTENDED)))
		found_driver = true;
	else {
		/* TODO: warn about bad regex instead of failure */
		error = giterr_set_regex(&drv->word_pattern, error);
		goto done;
	}

	/* TODO: look up diff.<driver>.algorithm to turn on minimal / patience
	 * diff in drv->other_flags
	 */

	/* if no driver config found at all, fall back on AUTO driver */
	if (!found_driver)
		goto done;

	/* store driver in registry */
	git_strmap_insert(reg->drivers, drv->name, drv, error);
	if (error < 0)
		goto done;
	error = 0;

	*out = drv;

done:
	git_buf_free(&name);
	git_config_free(cfg);

	if (!*out) {
		int error2 = git_diff_driver_builtin(out, reg, driver_name);
		if (!error)
			error = error2;
	}

	if (drv && drv != *out)
		git_diff_driver_free(drv);

	return error;
}