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); }
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); }
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; } }
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; }
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); }
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; }
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; } }
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; }
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; }