static int process_tree(struct walker *walker, struct tree *tree) { struct tree_desc desc; struct name_entry entry; if (parse_tree(tree)) return -1; init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { struct object *obj = NULL; /* submodule commits are not stored in the superproject */ if (S_ISGITLINK(entry.mode)) continue; if (S_ISDIR(entry.mode)) { struct tree *tree = lookup_tree(entry.sha1); if (tree) obj = &tree->object; } else { struct blob *blob = lookup_blob(entry.sha1); if (blob) obj = &blob->object; } if (!obj || process(walker, obj)) return -1; } free(tree->buffer); tree->buffer = NULL; tree->size = 0; tree->object.parsed = 0; return 0; }
struct object *parse_object(unsigned char *sha1) { unsigned long mapsize; void *map = map_sha1_file(sha1, &mapsize); if (map) { char type[100]; unsigned long size; void *buffer = unpack_sha1_file(map, mapsize, type, &size); if (!buffer) return NULL; if (check_sha1_signature(sha1, buffer, size, type) < 0) printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); munmap(map, mapsize); if (!strcmp(type, "blob")) { struct blob *ret = lookup_blob(sha1); parse_blob(ret); return &ret->object; } else if (!strcmp(type, "tree")) { struct tree *ret = lookup_tree(sha1); parse_tree(ret); return &ret->object; } else if (!strcmp(type, "commit")) { struct commit *ret = lookup_commit(sha1); parse_commit(ret); return &ret->object; } else if (!strcmp(type, "tag")) { struct tag *ret = lookup_tag(sha1); parse_tag(ret); return &ret->object; } else { return NULL; } } return NULL; }
static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data) { struct tree_desc desc; struct name_entry entry; int res = 0; if (parse_tree(tree)) return -1; init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { int result; if (S_ISGITLINK(entry.mode)) continue; if (S_ISDIR(entry.mode)) result = walk(&lookup_tree(entry.sha1)->object, OBJ_TREE, data); else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) result = walk(&lookup_blob(entry.sha1)->object, OBJ_BLOB, data); else { result = error("in tree %s: entry %s has bad mode %.6o\n", sha1_to_hex(tree->object.sha1), entry.path, entry.mode); } if (result < 0) return result; if (!res) res = result; } return res; }
int parse_tag_buffer(struct tag *item, const void *data, unsigned long size) { unsigned char sha1[20]; char type[20]; const char *bufptr = data; const char *tail = bufptr + size; const char *nl; if (item->object.parsed) return 0; item->object.parsed = 1; if (size < 64) return -1; if (memcmp("object ", bufptr, 7) || get_sha1_hex(bufptr + 7, sha1) || bufptr[47] != '\n') return -1; bufptr += 48; /* "object " + sha1 + "\n" */ if (!starts_with(bufptr, "type ")) return -1; bufptr += 5; nl = memchr(bufptr, '\n', tail - bufptr); if (!nl || sizeof(type) <= (nl - bufptr)) return -1; memcpy(type, bufptr, nl - bufptr); type[nl - bufptr] = '\0'; bufptr = nl + 1; if (!strcmp(type, blob_type)) { item->tagged = &lookup_blob(sha1)->object; } else if (!strcmp(type, tree_type)) { item->tagged = &lookup_tree(sha1)->object; } else if (!strcmp(type, commit_type)) { item->tagged = &lookup_commit(sha1)->object; } else if (!strcmp(type, tag_type)) { item->tagged = &lookup_tag(sha1)->object; } else { error("Unknown type %s", type); item->tagged = NULL; } if (bufptr + 4 < tail && starts_with(bufptr, "tag ")) ; /* good */ else return -1; bufptr += 4; nl = memchr(bufptr, '\n', tail - bufptr); if (!nl) return -1; item->tag = xmemdupz(bufptr, nl - bufptr); bufptr = nl + 1; if (bufptr + 7 < tail && starts_with(bufptr, "tagger ")) item->date = parse_tag_date(bufptr, tail); else item->date = 0; return 0; }
int parse_tag_buffer(struct tag *item, const void *data, unsigned long size) { struct object_id oid; char type[20]; const char *bufptr = data; const char *tail = bufptr + size; const char *nl; if (item->object.parsed) return 0; item->object.parsed = 1; if (size < GIT_SHA1_HEXSZ + 24) return -1; if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n') return -1; if (!starts_with(bufptr, "type ")) return -1; bufptr += 5; nl = memchr(bufptr, '\n', tail - bufptr); if (!nl || sizeof(type) <= (nl - bufptr)) return -1; memcpy(type, bufptr, nl - bufptr); type[nl - bufptr] = '\0'; bufptr = nl + 1; if (!strcmp(type, blob_type)) { item->tagged = (struct object *)lookup_blob(&oid); } else if (!strcmp(type, tree_type)) { item->tagged = (struct object *)lookup_tree(&oid); } else if (!strcmp(type, commit_type)) { item->tagged = (struct object *)lookup_commit(&oid); } else if (!strcmp(type, tag_type)) { item->tagged = (struct object *)lookup_tag(&oid); } else { error("Unknown type %s", type); item->tagged = NULL; } if (bufptr + 4 < tail && starts_with(bufptr, "tag ")) ; /* good */ else return -1; bufptr += 4; nl = memchr(bufptr, '\n', tail - bufptr); if (!nl) return -1; item->tag = xmemdupz(bufptr, nl - bufptr); bufptr = nl + 1; if (bufptr + 7 < tail && starts_with(bufptr, "tagger ")) item->date = parse_tag_date(bufptr, tail); else item->date = 0; return 0; }
static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path) { struct merge_list *res = xcalloc(1, sizeof(*res)); res->stage = stage; res->path = path; res->mode = mode; res->blob = lookup_blob(the_repository, oid); return res; }
static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsigned char *sha1, const char *path) { struct merge_list *res = xcalloc(1, sizeof(*res)); res->stage = stage; res->path = path; res->mode = mode; res->blob = lookup_blob(sha1); return res; }
static int inode_export_blobs(struct wim_inode *inode, struct blob_table *src_blob_table, struct blob_table *dest_blob_table, bool gift) { unsigned i; const u8 *hash; struct blob_descriptor *src_blob, *dest_blob; for (i = 0; i < inode->i_num_streams; i++) { /* Retrieve SHA-1 message digest of blob to export. */ hash = stream_hash(&inode->i_streams[i]); if (is_zero_hash(hash)) /* Empty stream? */ continue; /* Search for the blob (via SHA-1 message digest) in the * destination WIM. */ dest_blob = lookup_blob(dest_blob_table, hash); if (!dest_blob) { /* Blob not yet present in destination WIM. Search for * it in the source WIM, then export it into the * destination WIM. */ src_blob = stream_blob(&inode->i_streams[i], src_blob_table); if (!src_blob) return blob_not_found_error(inode, hash); if (gift) { dest_blob = src_blob; blob_table_unlink(src_blob_table, src_blob); } else { dest_blob = clone_blob_descriptor(src_blob); if (!dest_blob) return WIMLIB_ERR_NOMEM; } dest_blob->refcnt = 0; dest_blob->out_refcnt = 0; dest_blob->was_exported = 1; blob_table_insert(dest_blob_table, dest_blob); } /* Blob is present in destination WIM (either pre-existing, * already exported, or just exported above). Increment its * reference count appropriately. Note: we use 'refcnt' for * the raw reference count, but 'out_refcnt' for references * arising just from the export operation; this is used to roll * back a failed export if needed. */ dest_blob->refcnt += inode->i_nlink; dest_blob->out_refcnt += inode->i_nlink; } return 0; }
int fsck_finish(struct fsck_options *options) { int ret = 0; struct oidset_iter iter; const struct object_id *oid; oidset_iter_init(&gitmodules_found, &iter); while ((oid = oidset_iter_next(&iter))) { struct blob *blob; enum object_type type; unsigned long size; char *buf; if (oidset_contains(&gitmodules_done, oid)) continue; blob = lookup_blob(oid); if (!blob) { struct object *obj = lookup_unknown_object(oid->hash); ret |= report(options, obj, FSCK_MSG_GITMODULES_BLOB, "non-blob found at .gitmodules"); continue; } buf = read_object_file(oid, &type, &size); if (!buf) { if (is_promisor_object(&blob->object.oid)) continue; ret |= report(options, &blob->object, FSCK_MSG_GITMODULES_MISSING, "unable to read .gitmodules blob"); continue; } if (type == OBJ_BLOB) ret |= fsck_blob(blob, buf, size, options); else ret |= report(options, &blob->object, FSCK_MSG_GITMODULES_BLOB, "non-blob found at .gitmodules"); free(buf); } oidset_clear(&gitmodules_found); oidset_clear(&gitmodules_done); return ret; }
struct object *parse_object_buffer(const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p) { struct object *obj; *eaten_p = 0; obj = NULL; if (type == OBJ_BLOB) { struct blob *blob = lookup_blob(oid); if (blob) { if (parse_blob_buffer(blob, buffer, size)) return NULL; obj = &blob->object; } } else if (type == OBJ_TREE) { struct tree *tree = lookup_tree(oid); if (tree) { obj = &tree->object; if (!tree->buffer) tree->object.parsed = 0; if (!tree->object.parsed) { if (parse_tree_buffer(tree, buffer, size)) return NULL; *eaten_p = 1; } } } else if (type == OBJ_COMMIT) { struct commit *commit = lookup_commit(oid); if (commit) { if (parse_commit_buffer(commit, buffer, size)) return NULL; if (!get_cached_commit_buffer(commit, NULL)) { set_commit_buffer(commit, buffer, size); *eaten_p = 1; } obj = &commit->object; } } else if (type == OBJ_TAG) { struct tag *tag = lookup_tag(oid); if (tag) { if (parse_tag_buffer(tag, buffer, size)) return NULL; obj = &tag->object; } } else { warning("object %s has unknown type id %d", oid_to_hex(oid), type); obj = NULL; } return obj; }
static void export_blob(const unsigned char *sha1) { unsigned long size; enum object_type type; char *buf; struct object *object; int eaten; if (no_data) return; if (is_null_sha1(sha1)) return; object = lookup_object(sha1); if (object && object->flags & SHOWN) return; if (anonymize) { buf = anonymize_blob(&size); object = (struct object *)lookup_blob(sha1); eaten = 0; } else { buf = read_sha1_file(sha1, &type, &size); if (!buf) die ("Could not read blob %s", sha1_to_hex(sha1)); if (check_sha1_signature(sha1, buf, size, typename(type)) < 0) die("sha1 mismatch in blob %s", sha1_to_hex(sha1)); object = parse_object_buffer(sha1, type, size, buf, &eaten); } if (!object) die("Could not read blob %s", sha1_to_hex(sha1)); mark_next_object(object); printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size); if (size && fwrite(buf, size, 1, stdout) != 1) die_errno ("Could not write blob '%s'", sha1_to_hex(sha1)); printf("\n"); show_progress(); object->flags |= SHOWN; if (!eaten) free(buf); }
static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *options) { struct tree_desc desc; struct name_entry entry; int res = 0; const char *name; if (parse_tree(tree)) return -1; name = get_object_name(options, &tree->object); if (init_tree_desc_gently(&desc, tree->buffer, tree->size)) return -1; while (tree_entry_gently(&desc, &entry)) { struct object *obj; int result; if (S_ISGITLINK(entry.mode)) continue; if (S_ISDIR(entry.mode)) { obj = (struct object *)lookup_tree(entry.oid); if (name && obj) put_object_name(options, obj, "%s%s/", name, entry.path); result = options->walk(obj, OBJ_TREE, data, options); } else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) { obj = (struct object *)lookup_blob(entry.oid); if (name && obj) put_object_name(options, obj, "%s%s", name, entry.path); result = options->walk(obj, OBJ_BLOB, data, options); } else { result = error("in tree %s: entry %s has bad mode %.6o", describe_object(options, &tree->object), entry.path, entry.mode); } if (result < 0) return result; if (!res) res = result; } return res; }
static void process_tree(struct rev_info *revs, struct tree *tree, struct object_array *p, struct name_path *path, const char *name) { struct object *obj = &tree->object; struct tree_desc desc; struct name_entry entry; struct name_path me; if (!revs->tree_objects) return; if (!obj) die("bad tree object"); if (obj->flags & (UNINTERESTING | SEEN)) return; if (parse_tree(tree) < 0) die("bad tree object %s", sha1_to_hex(obj->sha1)); obj->flags |= SEEN; name = xstrdup(name); add_object(obj, p, path, name); me.up = path; me.elem = name; me.elem_len = strlen(name); init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) process_tree(revs, lookup_tree(entry.sha1), p, &me, entry.path); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, p, &me, entry.path); else process_blob(revs, lookup_blob(entry.sha1), p, &me, entry.path); } free(tree->buffer); tree->buffer = NULL; }
struct object *parse_object(const struct object_id *oid) { unsigned long size; enum object_type type; int eaten; const struct object_id *repl = lookup_replace_object(the_repository, oid); void *buffer; struct object *obj; obj = lookup_object(oid->hash); if (obj && obj->parsed) return obj; if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) || (!obj && has_object_file(oid) && oid_object_info(the_repository, oid, NULL) == OBJ_BLOB)) { if (check_object_signature(repl, NULL, 0, NULL) < 0) { error("sha1 mismatch %s", oid_to_hex(oid)); return NULL; } parse_blob_buffer(lookup_blob(oid), NULL, 0); return lookup_object(oid->hash); } buffer = read_object_file(oid, &type, &size); if (buffer) { if (check_object_signature(repl, buffer, size, type_name(type)) < 0) { free(buffer); error("sha1 mismatch %s", oid_to_hex(repl)); return NULL; } obj = parse_object_buffer(oid, type, size, buffer, &eaten); if (!eaten) free(buffer); return obj; } return NULL; }
void mark_tree_uninteresting(struct tree *tree) { struct tree_desc desc; struct name_entry entry; struct object *obj = &tree->object; if (!tree) return; if (obj->flags & UNINTERESTING) return; obj->flags |= UNINTERESTING; if (!has_sha1_file(obj->sha1)) return; if (parse_tree(tree) < 0) die("bad tree %s", sha1_to_hex(obj->sha1)); init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { switch (object_type(entry.mode)) { case OBJ_TREE: mark_tree_uninteresting(lookup_tree(entry.sha1)); break; case OBJ_BLOB: mark_blob_uninteresting(lookup_blob(entry.sha1)); break; default: /* Subproject commit - not in this repository */ break; } } /* * We don't care about the tree any more * after it has been marked uninteresting. */ free(tree->buffer); tree->buffer = NULL; }
static void process_tree(struct rev_info *revs, struct tree *tree, show_object_fn show, struct name_path *path, struct strbuf *base, const char *name) { struct object *obj = &tree->object; struct tree_desc desc; struct name_entry entry; struct name_path me; int all_interesting = (revs->diffopt.pathspec.nr == 0); int baselen = base->len; if (!revs->tree_objects) return; if (!obj) die("bad tree object"); if (obj->flags & (UNINTERESTING | SEEN)) return; if (parse_tree(tree) < 0) die("bad tree object %s", sha1_to_hex(obj->sha1)); obj->flags |= SEEN; show(obj, path, name); me.up = path; me.elem = name; me.elem_len = strlen(name); if (!all_interesting) { strbuf_addstr(base, name); if (base->len) strbuf_addch(base, '/'); } init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (!all_interesting) { int showit = tree_entry_interesting(&entry, base, 0, &revs->diffopt.pathspec); if (showit < 0) break; else if (!showit) continue; else if (showit == 2) all_interesting = 1; } if (S_ISDIR(entry.mode)) process_tree(revs, lookup_tree(entry.sha1), show, &me, base, entry.path); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, show, &me, entry.path); else process_blob(revs, lookup_blob(entry.sha1), show, &me, entry.path); } strbuf_setlen(base, baselen); free(tree->buffer); tree->buffer = NULL; }
static void process_tree(struct rev_info *revs, struct tree *tree, show_object_fn show, struct strbuf *base, const char *name, void *cb_data) { struct object *obj = &tree->object; struct tree_desc desc; struct name_entry entry; enum interesting match = revs->diffopt.pathspec.nr == 0 ? all_entries_interesting: entry_not_interesting; int baselen = base->len; if (!revs->tree_objects) return; if (!obj) die("bad tree object"); if (obj->flags & (UNINTERESTING | SEEN)) return; if (parse_tree_gently(tree, revs->ignore_missing_links) < 0) { if (revs->ignore_missing_links) return; die("bad tree object %s", oid_to_hex(&obj->oid)); } obj->flags |= SEEN; strbuf_addstr(base, name); show(obj, base->buf, cb_data); if (base->len) strbuf_addch(base, '/'); init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { match = tree_entry_interesting(&entry, base, 0, &revs->diffopt.pathspec); if (match == all_entries_not_interesting) break; if (match == entry_not_interesting) continue; } if (S_ISDIR(entry.mode)) process_tree(revs, lookup_tree(entry.sha1), show, base, entry.path, cb_data); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, show, base, entry.path, cb_data); else process_blob(revs, lookup_blob(entry.sha1), show, base, entry.path, cb_data); } strbuf_setlen(base, baselen); free_tree_buffer(tree); }
int cmd_fsck(int argc, const char **argv, const char *prefix) { int i; struct alternate_object_database *alt; /* fsck knows how to handle missing promisor objects */ fetch_if_missing = 0; errors_found = 0; check_replace_refs = 0; argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); fsck_walk_options.walk = mark_object; fsck_obj_options.walk = mark_used; fsck_obj_options.error_func = fsck_error_func; if (check_strict) fsck_obj_options.strict = 1; if (show_progress == -1) show_progress = isatty(2); if (verbose) show_progress = 0; if (write_lost_and_found) { check_full = 1; include_reflogs = 0; } if (name_objects) fsck_walk_options.object_names = xcalloc(1, sizeof(struct decoration)); git_config(fsck_config, NULL); fsck_head_link(); if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(mark_packed_for_connectivity, NULL, 0); } else { struct alternate_object_database *alt_odb_list; fsck_object_dir(get_object_directory()); prepare_alt_odb(the_repository); alt_odb_list = the_repository->objects->alt_odb_list; for (alt = alt_odb_list; alt; alt = alt->next) fsck_object_dir(alt->path); if (check_full) { struct packed_git *p; uint32_t total = 0, count = 0; struct progress *progress = NULL; if (show_progress) { for (p = get_packed_git(the_repository); p; p = p->next) { if (open_pack_index(p)) continue; total += p->num_objects; } progress = start_progress(_("Checking objects"), total); } for (p = get_packed_git(the_repository); p; p = p->next) { /* verify gives error messages itself */ if (verify_pack(p, fsck_obj_buffer, progress, count)) errors_found |= ERROR_PACK; count += p->num_objects; } stop_progress(&progress); } } for (i = 0; i < argc; i++) { const char *arg = argv[i]; struct object_id oid; if (!get_oid(arg, &oid)) { struct object *obj = lookup_object(oid.hash); if (!obj || !(obj->flags & HAS_OBJ)) { if (is_promisor_object(&oid)) continue; error("%s: object missing", oid_to_hex(&oid)); errors_found |= ERROR_OBJECT; continue; } obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrdup(arg)); mark_object_reachable(obj); continue; } error("invalid parameter: expected sha1, got '%s'", arg); errors_found |= ERROR_OBJECT; } /* * If we've not been given any explicit head information, do the * default ones from .git/refs. We also consider the index file * in this case (ie this implies --cache). */ if (!argc) { get_default_heads(); keep_cache_objects = 1; } if (keep_cache_objects) { verify_index_checksum = 1; verify_ce_order = 1; read_cache(); for (i = 0; i < active_nr; i++) { unsigned int mode; struct blob *blob; struct object *obj; mode = active_cache[i]->ce_mode; if (S_ISGITLINK(mode)) continue; blob = lookup_blob(&active_cache[i]->oid); if (!blob) continue; obj = &blob->object; obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrfmt(":%s", active_cache[i]->name)); mark_object_reachable(obj); } if (active_cache_tree) fsck_cache_tree(active_cache_tree); } check_connectivity(); return errors_found; }