示例#1
0
static bool checkout_is_workdir_modified(
    checkout_data *data,
    const git_diff_file *baseitem,
    const git_index_entry *wditem)
{
    git_oid oid;
    const git_index_entry *ie;

    /* handle "modified" submodule */
    if (wditem->mode == GIT_FILEMODE_COMMIT) {
        git_submodule *sm;
        unsigned int sm_status = 0;
        const git_oid *sm_oid = NULL;

        if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0 ||
                git_submodule_status(&sm_status, sm) < 0)
            return true;

        if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status))
            return true;

        sm_oid = git_submodule_wd_id(sm);
        if (!sm_oid)
            return false;

        return (git_oid__cmp(&baseitem->oid, sm_oid) != 0);
    }

    /* Look at the cache to decide if the workdir is modified.  If not,
     * we can simply compare the oid in the cache to the baseitem instead
     * of hashing the file.
     */
    if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
        if (wditem->mtime.seconds == ie->mtime.seconds &&
                wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
                wditem->file_size == ie->file_size)
            return (git_oid__cmp(&baseitem->oid, &ie->oid) != 0);
    }

    /* depending on where base is coming from, we may or may not know
     * the actual size of the data, so we can't rely on this shortcut.
     */
    if (baseitem->size && wditem->file_size != baseitem->size)
        return true;

    if (git_diff__oid_for_file(
                data->repo, wditem->path, wditem->mode,
                wditem->file_size, &oid) < 0)
        return false;

    return (git_oid__cmp(&baseitem->oid, &oid) != 0);
}
示例#2
0
static int objects_cmp(const void *a, const void *b)
{
	const struct entry *entrya = (struct entry *)a;
	const struct entry *entryb = (struct entry *)b;

	return git_oid__cmp(&entrya->oid, &entryb->oid);
}
示例#3
0
int git_attr_file__out_of_date(git_repository *repo, git_attr_file *file)
{
	if (!file)
		return 1;

	switch (file->source) {
	case GIT_ATTR_FILE__IN_MEMORY:
		return 0;

	case GIT_ATTR_FILE__FROM_FILE:
		return git_futils_filestamp_check(
			&file->cache_data.stamp, file->entry->fullpath);

	case GIT_ATTR_FILE__FROM_INDEX: {
		int error;
		git_oid id;

		if ((error = attr_file_oid_from_index(
				&id, repo, file->entry->path)) < 0)
			return error;

		return (git_oid__cmp(&file->cache_data.oid, &id) != 0);
	}

	default:
		giterr_set(GITERR_INVALID, "Invalid file type %d", file->source);
		return -1;
	}
}
示例#4
0
int git_odb_exists_prefix(
	git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
{
	int error = GIT_ENOTFOUND, num_found = 0;
	size_t i;
	git_oid key = {{0}}, last_found = {{0}}, found;

	assert(db && short_id);

	if (len < GIT_OID_MINPREFIXLEN)
		return git_odb__error_ambiguous("prefix length too short");
	if (len > GIT_OID_HEXSZ)
		len = GIT_OID_HEXSZ;

	if (len == GIT_OID_HEXSZ) {
		if (git_odb_exists(db, short_id)) {
			if (out)
				git_oid_cpy(out, short_id);
			return 0;
		} else {
			return git_odb__error_notfound("no match for id prefix", short_id);
		}
	}

	/* just copy valid part of short_id */
	memcpy(&key.id, short_id->id, (len + 1) / 2);
	if (len & 1)
		key.id[len / 2] &= 0xF0;

	for (i = 0; i < db->backends.length; ++i) {
		backend_internal *internal = (backend_internal *) git_vector_get(&db->backends, i);
		git_odb_backend *b = internal->backend;

		if (!b->exists_prefix)
			continue;

		error = b->exists_prefix(&found, b, &key, len);
		if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
			continue;
		if (error)
			return error;

		/* make sure found item doesn't introduce ambiguity */
		if (num_found) {
			if (git_oid__cmp(&last_found, &found))
				return git_odb__error_ambiguous("multiple matches for prefix");
		} else {
			git_oid_cpy(&last_found, &found);
			num_found++;
		}
	}

	if (!num_found)
		return git_odb__error_notfound("no match for id prefix", &key);
	if (out)
		git_oid_cpy(out, &last_found);

	return 0;
}
示例#5
0
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
{
	git_ref_t type1, type2;
	assert(ref1 && ref2);

	type1 = git_reference_type(ref1);
	type2 = git_reference_type(ref2);

	/* let's put symbolic refs before OIDs */
	if (type1 != type2)
		return (type1 == GIT_REF_SYMBOLIC) ? -1 : 1;

	if (type1 == GIT_REF_SYMBOLIC)
		return strcmp(ref1->target.symbolic, ref2->target.symbolic);

	return git_oid__cmp(&ref1->target.oid, &ref2->target.oid);
}
示例#6
0
文件: clone.c 项目: benqian/repobuild
static int reference_matches_remote_head(
	const char *reference_name,
	void *payload)
{
	struct head_info *head_info = (struct head_info *)payload;
	git_oid oid;

	/* TODO: Should we guard against references
	 * which name doesn't start with refs/heads/ ?
	 */

	/* Stop looking if we've already found a match */
	if (head_info->found)
		return 0;

	if (git_reference_name_to_id(
		&oid,
		head_info->repo,
		reference_name) < 0) {
			/* If the reference doesn't exists, it obviously cannot match the expected oid. */
			giterr_clear();
			return 0;
	}

	if (git_oid__cmp(&head_info->remote_head_oid, &oid) == 0) {
		/* Determine the local reference name from the remote tracking one */
		if (git_refspec_transform_l(
			&head_info->branchname,
			head_info->refspec,
			reference_name) < 0)
				return -1;

		if (git_buf_len(&head_info->branchname) > 0) {
			if (git_buf_sets(
				&head_info->branchname,
				git_buf_cstr(&head_info->branchname) + strlen(GIT_REFS_HEADS_DIR)) < 0)
					return -1;

			head_info->found = 1;
		}
	}

	return 0;
}
示例#7
0
int git_attr_file__out_of_date(
	git_repository *repo,
	git_attr_session *attr_session,
	git_attr_file *file)
{
	if (!file)
		return 1;

	/* we are never out of date if we just created this data in the same
	 * attr_session; otherwise, nonexistent files must be invalidated
	 */
	if (attr_session && attr_session->key == file->session_key)
		return 0;
	else if (file->nonexistent)
		return 1;

	switch (file->source) {
	case GIT_ATTR_FILE__IN_MEMORY:
		return 0;

	case GIT_ATTR_FILE__FROM_FILE:
		return git_futils_filestamp_check(
			&file->cache_data.stamp, file->entry->fullpath);

	case GIT_ATTR_FILE__FROM_INDEX: {
		int error;
		git_oid id;

		if ((error = attr_file_oid_from_index(
				&id, repo, file->entry->path)) < 0)
			return error;

		return (git_oid__cmp(&file->cache_data.oid, &id) != 0);
	}

	default:
		giterr_set(GITERR_INVALID, "Invalid file type %d", file->source);
		return -1;
	}
}
示例#8
0
int git_futils_readbuffer_updated(
	git_buf *out, const char *path, git_oid *checksum, int *updated)
{
	int error;
	git_file fd;
	struct stat st;
	git_buf buf = GIT_BUF_INIT;
	git_oid checksum_new;

	assert(out && path && *path);

	if (updated != NULL)
		*updated = 0;

	if (p_stat(path, &st) < 0)
		return git_path_set_error(errno, path, "stat");


	if (S_ISDIR(st.st_mode)) {
		giterr_set(GITERR_INVALID, "requested file is a directory");
		return GIT_ENOTFOUND;
	}

	if (!git__is_sizet(st.st_size+1)) {
		giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path);
		return -1;
	}

	if ((fd = git_futils_open_ro(path)) < 0)
		return fd;

	if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) {
		p_close(fd);
		return -1;
	}

	p_close(fd);

	if (checksum) {
		if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
			git_buf_free(&buf);
			return error;
		}

		/*
		 * If we were given a checksum, we only want to use it if it's different
		 */
		if (!git_oid__cmp(checksum, &checksum_new)) {
			git_buf_free(&buf);
			if (updated)
				*updated = 0;

			return 0;
		}

		git_oid_cpy(checksum, &checksum_new);
	}

	/*
	 * If we're here, the file did change, or the user didn't have an old version
	 */
	if (updated != NULL)
		*updated = 1;

	git_buf_swap(out, &buf);
	git_buf_free(&buf);

	return 0;
}
示例#9
0
int git_odb_read_prefix(
	git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len)
{
	size_t i;
	int error = GIT_ENOTFOUND;
	git_oid key = {{0}}, found_full_oid = {{0}};
	git_rawobj raw;
	void *data = NULL;
	bool found = false;
	git_odb_object *object;

	assert(out && db);

	if (len < GIT_OID_MINPREFIXLEN)
		return git_odb__error_ambiguous("prefix length too short");
	if (len > GIT_OID_HEXSZ)
		len = GIT_OID_HEXSZ;

	if (len == GIT_OID_HEXSZ) {
		*out = git_cache_get_raw(odb_cache(db), short_id);
		if (*out != NULL)
			return 0;
	}

	/* just copy valid part of short_id */
	memcpy(&key.id, short_id->id, (len + 1) / 2);
	if (len & 1)
		key.id[len / 2] &= 0xF0;

	for (i = 0; i < db->backends.length; ++i) {
		backend_internal *internal = (backend_internal *) git_vector_get(&db->backends, i);
		git_odb_backend *b = internal->backend;

		if (b->read_prefix != NULL) {
			git_oid full_oid;
			error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, &key, len);
			if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
				continue;

			if (error)
				return error;

			git__free(data);
			data = raw.data;

			if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
				git__free(raw.data);
				return git_odb__error_ambiguous("multiple matches for prefix");
			}

			found_full_oid = full_oid;
			found = true;
		}
	}

	if (!found)
		return git_odb__error_notfound("no match for prefix", &key);

	if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
		return -1;

	*out = (git_odb_object*) git_cache_store_raw(odb_cache(db), object);
	return 0;
}