Exemple #1
0
int git_blob_filtered_content(
	git_buf *out,
	git_blob *blob,
	const char *path,
	int check_for_binary_data)
{
	int error = 0;
	git_filter_list *fl = NULL;

	assert(blob && path && out);

	git_buf_sanitize(out);

	if (check_for_binary_data && git_blob_is_binary(blob))
		return 0;

	if (!(error = git_filter_list_load(
			&fl, git_blob_owner(blob), blob, path,
			GIT_FILTER_TO_WORKTREE, GIT_FILTER_DEFAULT))) {

		error = git_filter_list_apply_to_blob(out, fl, blob);

		git_filter_list_free(fl);
	}

	return error;
}
Exemple #2
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	const char *from_star, *to_star;
	size_t replacement_len, star_offset;

	git_buf_sanitize(out);
	git_buf_clear(out);

	/*
	 * There are two parts to each side of a refspec, the bit
	 * before the star and the bit after it. The star can be in
	 * the middle of the pattern, so we need to look at each bit
	 * individually.
	 */
	from_star = strchr(from, '*');
	to_star = strchr(to, '*');

	assert(from_star && to_star);

	/* star offset, both in 'from' and in 'name' */
	star_offset = from_star - from;

	/* the first half is copied over */
	git_buf_put(out, to, to_star - to);

	/*
	 * Copy over the name, but exclude the trailing part in "from" starting
	 * after the glob
	 */
	replacement_len = strlen(name + star_offset) - strlen(from_star + 1);
	git_buf_put(out, name + star_offset, replacement_len);

	return git_buf_puts(out, to_star + 1);
}
Exemple #3
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	size_t to_len   = to   ? strlen(to)   : 0;
	size_t from_len = from ? strlen(from) : 0;
	size_t name_len = name ? strlen(name) : 0;

	git_buf_sanitize(out);

	if (git_buf_set(out, to, to_len) < 0)
		return -1;

	if (to_len > 0) {
		/* No '*' at the end of 'to' means that refspec is mapped to one
		 * specific branch, so no actual transformation is needed.
		 */
		if (out->ptr[to_len - 1] != '*')
			return 0;
		git_buf_shorten(out, 1); /* remove trailing '*' copied from 'to' */
	}

	if (from_len > 0) /* ignore trailing '*' from 'from' */
		from_len--;
	if (from_len > name_len)
		from_len = name_len;

	return git_buf_put(out, name + from_len, name_len - from_len);
}
Exemple #4
0
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
{
    const char *eol, *buf = commit->raw_header;

    git_buf_sanitize(out);

    while ((eol = strchr(buf, '\n'))) {
        /* We can skip continuations here */
        if (buf[0] == ' ') {
            buf = eol + 1;
            continue;
        }

        /* Skip until we find the field we're after */
        if (git__prefixcmp(buf, field)) {
            buf = eol + 1;
            continue;
        }

        buf += strlen(field);
        /* Check that we're not matching a prefix but the field itself */
        if (buf[0] != ' ') {
            buf = eol + 1;
            continue;
        }

        buf++; /* skip the SP */

        git_buf_put(out, buf, eol - buf);
        if (git_buf_oom(out))
            goto oom;

        /* If the next line starts with SP, it's multi-line, we must continue */
        while (eol[1] == ' ') {
            git_buf_putc(out, '\n');
            buf = eol + 2;
            eol = strchr(buf, '\n');
            if (!eol)
                goto malformed;

            git_buf_put(out, buf, eol - buf);
        }

        if (git_buf_oom(out))
            goto oom;

        return 0;
    }

    giterr_set(GITERR_OBJECT, "no such field '%s'", field);
    return GIT_ENOTFOUND;

malformed:
    giterr_set(GITERR_OBJECT, "malformed header");
    return -1;
oom:
    giterr_set_oom();
    return -1;
}
Exemple #5
0
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
{
        git_buf_sanitize(out);

	if (!spec->pattern)
		return git_buf_puts(out, spec->src);

	return refspec_transform(out, spec->dst, spec->src, name);
}
Exemple #6
0
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
{
	const char *buf = commit->raw_header;
	const char *h, *eol;

	git_buf_sanitize(out);
	while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
		h++;
		if (git__prefixcmp(h, field)) {
			buf = h;
			continue;
		}

		h += strlen(field);
		eol = strchr(h, '\n');
		if (h[0] != ' ') {
			buf = h;
			continue;
		}
		if (!eol)
			goto malformed;

		h++; /* skip the SP */

		git_buf_put(out, h, eol - h);
		if (git_buf_oom(out))
			goto oom;

		/* If the next line starts with SP, it's multi-line, we must continue */
		while (eol[1] == ' ') {
			git_buf_putc(out, '\n');
			h = eol + 2;
			eol = strchr(h, '\n');
			if (!eol)
				goto malformed;

			git_buf_put(out, h, eol - h);
		}

		if (git_buf_oom(out))
			goto oom;

		return 0;
	}

	return GIT_ENOTFOUND;

malformed:
	giterr_set(GITERR_OBJECT, "malformed header");
	return -1;
oom:
	giterr_set_oom();
	return -1;
}
int git_repository_discover(
	git_buf *out,
	const char *start_path,
	int across_fs,
	const char *ceiling_dirs)
{
	uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;

	assert(start_path);

	git_buf_sanitize(out);

	return find_repo(out, NULL, start_path, flags, ceiling_dirs);
}
Exemple #8
0
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
{
	assert(out && spec && name);
	git_buf_sanitize(out);

	if (!git_refspec_dst_matches(spec, name)) {
		giterr_set(GITERR_INVALID, "ref '%s' doesn't match the destination", name);
		return -1;
	}

	if (!spec->pattern)
		return git_buf_puts(out, spec->src);

	return refspec_transform(out, spec->dst, spec->src, name);
}
Exemple #9
0
int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
{
	assert(out && spec && name);
	git_buf_sanitize(out);

	if (!git_refspec_src_matches(spec, name)) {
		git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the source", name);
		return -1;
	}

	if (!spec->pattern)
		return git_buf_puts(out, spec->dst ? spec->dst : "");

	return refspec_transform(out, spec->src, spec->dst, name);
}
Exemple #10
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	const char *from_star, *to_star;
	const char *name_slash, *from_slash;
	size_t replacement_len, star_offset;

	git_buf_sanitize(out);
	git_buf_clear(out);

	/*
	 * There are two parts to each side of a refspec, the bit
	 * before the star and the bit after it. The star can be in
	 * the middle of the pattern, so we need to look at each bit
	 * individually.
	 */
	from_star = strchr(from, '*');
	to_star = strchr(to, '*');

	assert(from_star && to_star);

	/* star offset, both in 'from' and in 'name' */
	star_offset = from_star - from;

	/* the first half is copied over */
	git_buf_put(out, to, to_star - to);

	/* then we copy over the replacement, from the star's offset to the next slash in 'name' */
	name_slash = strchr(name + star_offset, '/');
	if (!name_slash)
		name_slash = strrchr(name, '\0');

	/* if there is no slash after the star in 'from', we want to copy everything over */
	from_slash = strchr(from + star_offset, '/');
	if (!from_slash)
		name_slash = strrchr(name, '\0');

	replacement_len = (name_slash - name) - star_offset;
	git_buf_put(out, name + star_offset, replacement_len);

	return git_buf_puts(out, to_star + 1);
}
Exemple #11
0
int git_object_short_id(git_buf *out, const git_object *obj)
{
	git_repository *repo;
	int len = GIT_ABBREV_DEFAULT, error;
	git_oid id = {{0}};
	git_odb *odb;

	assert(out && obj);

	git_buf_sanitize(out);
	repo = git_object_owner(obj);

	if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0)
		return error;

	if ((error = git_repository_odb(&odb, repo)) < 0)
		return error;

	while (len < GIT_OID_HEXSZ) {
		/* set up short oid */
		memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
		if (len & 1)
			id.id[len / 2] &= 0xf0;

		error = git_odb_exists_prefix(NULL, odb, &id, len);
		if (error != GIT_EAMBIGUOUS)
			break;

		giterr_clear();
		len++;
	}

	if (!error && !(error = git_buf_grow(out, len + 1))) {
		git_oid_tostr(out->ptr, len + 1, &id);
		out->size = len;
	}

	git_odb_free(odb);

	return error;
}
Exemple #12
0
int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
{
	int error;
	git_config *cfg;

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);

	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
		return error;

	git_buf_sanitize(buf);

	if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0)
		return error;

	if (git_buf_len(buf) == 0) {
		giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream remote", refname);
		error = GIT_ENOTFOUND;
		git_buf_clear(buf);
	}

	return error;
}
Exemple #13
0
int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
{
	git_strarray remote_list = {0};
	size_t i;
	git_remote *remote;
	const git_refspec *fetchspec;
	int error = 0;
	char *remote_name = NULL;

	assert(buf && repo && refname);

	git_buf_sanitize(buf);

	/* Verify that this is a remote branch */
	if (!git_reference__is_remote(refname)) {
		giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
			refname);
		error = GIT_ERROR;
		goto cleanup;
	}

	/* Get the remotes */
	if ((error = git_remote_list(&remote_list, repo)) < 0)
		goto cleanup;

	/* Find matching remotes */
	for (i = 0; i < remote_list.count; i++) {
		if ((error = git_remote_lookup(&remote, repo, remote_list.strings[i])) < 0)
			continue;

		fetchspec = git_remote__matching_dst_refspec(remote, refname);
		if (fetchspec) {
			/* If we have not already set out yet, then set
			 * it to the matching remote name. Otherwise
			 * multiple remotes match this reference, and it
			 * is ambiguous. */
			if (!remote_name) {
				remote_name = remote_list.strings[i];
			} else {
				git_remote_free(remote);

				giterr_set(GITERR_REFERENCE,
					"Reference '%s' is ambiguous", refname);
				error = GIT_EAMBIGUOUS;
				goto cleanup;
			}
		}

		git_remote_free(remote);
	}

	if (remote_name) {
		git_buf_clear(buf);
		error = git_buf_puts(buf, remote_name);
	} else {
		giterr_set(GITERR_REFERENCE,
			"Could not determine remote for '%s'", refname);
		error = GIT_ENOTFOUND;
	}

cleanup:
	if (error < 0)
		git_buf_free(buf);

	git_strarray_free(&remote_list);
	return error;
}
Exemple #14
0
int git_branch_upstream_name(
	git_buf *out,
	git_repository *repo,
	const char *refname)
{
	git_buf remote_name = GIT_BUF_INIT;
	git_buf merge_name = GIT_BUF_INIT;
	git_buf buf = GIT_BUF_INIT;
	int error = -1;
	git_remote *remote = NULL;
	const git_refspec *refspec;
	git_config *config;

	assert(out && refname);

	git_buf_sanitize(out);

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);

	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
		return error;

	if ((error = retrieve_upstream_configuration(
		&remote_name, config, refname, "branch.%s.remote")) < 0)
			goto cleanup;

	if ((error = retrieve_upstream_configuration(
		&merge_name, config, refname, "branch.%s.merge")) < 0)
			goto cleanup;

	if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) {
		giterr_set(GITERR_REFERENCE,
			"branch '%s' does not have an upstream", refname);
		error = GIT_ENOTFOUND;
		goto cleanup;
	}

	if (strcmp(".", git_buf_cstr(&remote_name)) != 0) {
		if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0)
			goto cleanup;

		refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name));
		if (!refspec) {
			error = GIT_ENOTFOUND;
			goto cleanup;
		}

		if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0)
			goto cleanup;
	} else
		if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0)
			goto cleanup;

	error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));

cleanup:
	git_config_free(config);
	git_remote_free(remote);
	git_buf_free(&remote_name);
	git_buf_free(&merge_name);
	git_buf_free(&buf);
	return error;
}
Exemple #15
0
int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field)
{
    git_odb_object *obj;
    git_odb *odb;
    const char *buf;
    const char *h, *eol;
    int error;

    git_buf_sanitize(signature);
    git_buf_sanitize(signed_data);

    if (!field)
        field = "gpgsig";

    if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
        return error;

    if ((error = git_odb_read(&obj, odb, commit_id)) < 0)
        return error;

    if (obj->cached.type != GIT_OBJ_COMMIT) {
        giterr_set(GITERR_INVALID, "the requested type does not match the type in ODB");
        error = GIT_ENOTFOUND;
        goto cleanup;
    }

    buf = git_odb_object_data(obj);

    while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
        h++;
        if (git__prefixcmp(buf, field)) {
            if (git_buf_put(signed_data, buf, h - buf) < 0)
                return -1;

            buf = h;
            continue;
        }

        h = buf;
        h += strlen(field);
        eol = strchr(h, '\n');
        if (h[0] != ' ') {
            buf = h;
            continue;
        }
        if (!eol)
            goto malformed;

        h++; /* skip the SP */

        git_buf_put(signature, h, eol - h);
        if (git_buf_oom(signature))
            goto oom;

        /* If the next line starts with SP, it's multi-line, we must continue */
        while (eol[1] == ' ') {
            git_buf_putc(signature, '\n');
            h = eol + 2;
            eol = strchr(h, '\n');
            if (!eol)
                goto malformed;

            git_buf_put(signature, h, eol - h);
        }

        if (git_buf_oom(signature))
            goto oom;

        git_odb_object_free(obj);
        return git_buf_puts(signed_data, eol+1);
    }

    giterr_set(GITERR_OBJECT, "this commit is not signed");
    error = GIT_ENOTFOUND;
    goto cleanup;

malformed:
    giterr_set(GITERR_OBJECT, "malformed header");
    error = -1;
    goto cleanup;
oom:
    giterr_set_oom();
    error = -1;
    goto cleanup;

cleanup:
    git_odb_object_free(obj);
    git_buf_clear(signature);
    git_buf_clear(signed_data);
    return error;
}