static int show_reference(const char *refname, const struct object_id *oid, int flag, void *cb_data) { struct show_data *data = cb_data; if (!wildmatch(data->pattern, refname, 0)) { if (data->format == REPLACE_FORMAT_SHORT) printf("%s\n", refname); else if (data->format == REPLACE_FORMAT_MEDIUM) printf("%s -> %s\n", refname, oid_to_hex(oid)); else { /* data->format == REPLACE_FORMAT_LONG */ struct object_id object; enum object_type obj_type, repl_type; if (get_oid(refname, &object)) return error("Failed to resolve '%s' as a valid ref.", refname); obj_type = oid_object_info(the_repository, &object, NULL); repl_type = oid_object_info(the_repository, oid, NULL); printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type), oid_to_hex(oid), type_name(repl_type)); } } return 0; }
int gpg_verify_tag(const struct object_id *oid, const char *name_to_report, unsigned flags) { enum object_type type; char *buf; unsigned long size; int ret; type = oid_object_info(the_repository, oid, NULL); if (type != OBJ_TAG) return error("%s: cannot verify a non-tag object of type %s.", name_to_report ? name_to_report : find_unique_abbrev(oid, DEFAULT_ABBREV), type_name(type)); buf = read_object_file(oid, &type, &size); if (!buf) return error("%s: unable to read file.", name_to_report ? name_to_report : find_unique_abbrev(oid, DEFAULT_ABBREV)); ret = run_gpg_verify(buf, size, flags); free(buf); return ret; }
static int prune_object(const struct object_id *oid, const char *fullpath, void *data) { struct stat st; /* * Do we know about this object? * It must have been reachable */ if (lookup_object(oid->hash)) return 0; if (lstat(fullpath, &st)) { /* report errors, but do not stop pruning */ error("Could not stat '%s'", fullpath); return 0; } if (st.st_mtime > expire) return 0; if (show_only || verbose) { enum object_type type = oid_object_info(the_repository, oid, NULL); printf("%s %s\n", oid_to_hex(oid), (type > 0) ? type_name(type) : "unknown"); } if (!show_only) unlink_or_warn(fullpath); return 0; }
static int show_tree(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { int retval = 0; int baselen; const char *type = blob_type; if (S_ISGITLINK(mode)) { /* * Maybe we want to have some recursive version here? * * Something similar to this incomplete example: * if (show_subprojects(base, baselen, pathname)) retval = READ_TREE_RECURSIVE; * */ type = commit_type; } else if (S_ISDIR(mode)) { if (show_recursive(base->buf, base->len, pathname)) { retval = READ_TREE_RECURSIVE; if (!(ls_options & LS_SHOW_TREES)) return retval; } type = tree_type; } else if (ls_options & LS_TREE_ONLY) return 0; if (!(ls_options & LS_NAME_ONLY)) { if (ls_options & LS_SHOW_SIZE) { char size_text[24]; if (!strcmp(type, blob_type)) { unsigned long size; if (oid_object_info(oid, &size) == OBJ_BAD) xsnprintf(size_text, sizeof(size_text), "BAD"); else xsnprintf(size_text, sizeof(size_text), "%lu", size); } else xsnprintf(size_text, sizeof(size_text), "-"); printf("%06o %s %s %7s\t", mode, type, find_unique_abbrev(oid, abbrev), size_text); } else printf("%06o %s %s\t", mode, type, find_unique_abbrev(oid, abbrev)); } baselen = base->len; strbuf_addstr(base, pathname); write_name_quoted_relative(base->buf, chomp_prefix ? ls_tree_prefix : NULL, stdout, line_termination); strbuf_setlen(base, baselen); return retval; }
/** * Build the initial type index for the packfile */ void bitmap_writer_build_type_index(struct packing_data *to_pack, struct pack_idx_entry **index, uint32_t index_nr) { uint32_t i; writer.commits = ewah_new(); writer.trees = ewah_new(); writer.blobs = ewah_new(); writer.tags = ewah_new(); ALLOC_ARRAY(to_pack->in_pack_pos, to_pack->nr_objects); for (i = 0; i < index_nr; ++i) { struct object_entry *entry = (struct object_entry *)index[i]; enum object_type real_type; oe_set_in_pack_pos(to_pack, entry, i); switch (oe_type(entry)) { case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: real_type = oe_type(entry); break; default: real_type = oid_object_info(to_pack->repo, &entry->idx.oid, NULL); break; } switch (real_type) { case OBJ_COMMIT: ewah_set(writer.commits, i); break; case OBJ_TREE: ewah_set(writer.trees, i); break; case OBJ_BLOB: ewah_set(writer.blobs, i); break; case OBJ_TAG: ewah_set(writer.tags, i); break; default: die("Missing type information for %s (%d/%d)", oid_to_hex(&entry->idx.oid), real_type, oe_type(entry)); } } }
static enum list_objects_filter_result filter_blobs_limit( struct repository *r, enum list_objects_filter_situation filter_situation, struct object *obj, const char *pathname, const char *filename, void *filter_data_) { struct filter_blobs_limit_data *filter_data = filter_data_; unsigned long object_length; enum object_type t; switch (filter_situation) { default: BUG("unknown filter_situation: %d", filter_situation); case LOFS_BEGIN_TREE: assert(obj->type == OBJ_TREE); /* always include all tree objects */ return LOFR_MARK_SEEN | LOFR_DO_SHOW; case LOFS_END_TREE: assert(obj->type == OBJ_TREE); return LOFR_ZERO; case LOFS_BLOB: assert(obj->type == OBJ_BLOB); assert((obj->flags & SEEN) == 0); t = oid_object_info(r, &obj->oid, &object_length); if (t != OBJ_BLOB) { /* probably OBJ_NONE */ /* * We DO NOT have the blob locally, so we cannot * apply the size filter criteria. Be conservative * and force show it (and let the caller deal with * the ambiguity). */ goto include_it; } if (object_length < filter_data->max_bytes) goto include_it; if (filter_data->omits) oidset_insert(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN; /* but not LOFR_DO_SHOW (hard omit) */ } include_it: if (filter_data->omits) oidset_remove(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN | LOFR_DO_SHOW; }
static int replace_object_oid(const char *object_ref, struct object_id *object, const char *replace_ref, struct object_id *repl, int force) { struct object_id prev; enum object_type obj_type, repl_type; struct strbuf ref = STRBUF_INIT; struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; int res = 0; obj_type = oid_object_info(the_repository, object, NULL); repl_type = oid_object_info(the_repository, repl, NULL); if (!force && obj_type != repl_type) return error("Objects must be of the same type.\n" "'%s' points to a replaced object of type '%s'\n" "while '%s' points to a replacement object of " "type '%s'.", object_ref, type_name(obj_type), replace_ref, type_name(repl_type)); if (check_ref_valid(object, &prev, &ref, force)) { strbuf_release(&ref); return -1; } transaction = ref_transaction_begin(&err); if (!transaction || ref_transaction_update(transaction, ref.buf, repl, &prev, 0, NULL, &err) || ref_transaction_commit(transaction, &err)) res = error("%s", err.buf); ref_transaction_free(transaction); strbuf_release(&ref); return res; }
/* * Fill the blob_sha1 field of an origin if it hasn't, so that later * call to fill_origin_blob() can use it to locate the data. blob_sha1 * for an origin is also used to pass the blame for the entire file to * the parent to detect the case where a child's blob is identical to * that of its parent's. * * This also fills origin->mode for corresponding tree path. */ static int fill_blob_sha1_and_mode(struct blame_origin *origin) { if (!is_null_oid(&origin->blob_oid)) return 0; if (get_tree_entry(&origin->commit->object.oid, origin->path, &origin->blob_oid, &origin->mode)) goto error_out; if (oid_object_info(the_repository, &origin->blob_oid, NULL) != OBJ_BLOB) goto error_out; return 0; error_out: oidclr(&origin->blob_oid); origin->mode = S_IFINVALID; return -1; }
static const char *printable_type(struct object *obj) { const char *ret; if (obj->type == OBJ_NONE) { enum object_type type = oid_object_info(&obj->oid, NULL); if (type > 0) object_as_type(obj, type, 0); } ret = type_name(obj->type); if (!ret) ret = "unknown"; return ret; }
static int edit_and_replace(const char *object_ref, int force, int raw) { char *tmpfile; enum object_type type; struct object_id old_oid, new_oid, prev; struct strbuf ref = STRBUF_INIT; if (get_oid(object_ref, &old_oid) < 0) return error("Not a valid object name: '%s'", object_ref); type = oid_object_info(the_repository, &old_oid, NULL); if (type < 0) return error("unable to get object type for %s", oid_to_hex(&old_oid)); if (check_ref_valid(&old_oid, &prev, &ref, force)) { strbuf_release(&ref); return -1; } strbuf_release(&ref); tmpfile = git_pathdup("REPLACE_EDITOBJ"); if (export_object(&old_oid, type, raw, tmpfile)) { free(tmpfile); return -1; } if (launch_editor(tmpfile, NULL, NULL) < 0) { free(tmpfile); return error("editing object file failed"); } if (import_object(&new_oid, type, raw, tmpfile)) { free(tmpfile); return -1; } free(tmpfile); if (!oidcmp(&old_oid, &new_oid)) return error("new object is the same as the old one: '%s'", oid_to_hex(&old_oid)); return replace_object_oid(object_ref, &old_oid, "replacement", &new_oid, force); }
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; }
static void verify_working_tree_path(struct commit *work_tree, const char *path) { struct commit_list *parents; int pos; for (parents = work_tree->parents; parents; parents = parents->next) { const struct object_id *commit_oid = &parents->item->object.oid; struct object_id blob_oid; unsigned mode; if (!get_tree_entry(commit_oid, path, &blob_oid, &mode) && oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB) return; } pos = cache_name_pos(path, strlen(path)); if (pos >= 0) ; /* path is in the index */ else if (-1 - pos < active_nr && !strcmp(active_cache[-1 - pos]->name, path)) ; /* path is in the index, unmerged */ else die("no such path '%s' in HEAD", path); }
static int write_tar_entry(struct archiver_args *args, const struct object_id *oid, const char *path, size_t pathlen, unsigned int mode) { struct ustar_header header; struct strbuf ext_header = STRBUF_INIT; unsigned int old_mode = mode; unsigned long size, size_in_header; void *buffer; int err = 0; memset(&header, 0, sizeof(header)); if (S_ISDIR(mode) || S_ISGITLINK(mode)) { *header.typeflag = TYPEFLAG_DIR; mode = (mode | 0777) & ~tar_umask; } else if (S_ISLNK(mode)) { *header.typeflag = TYPEFLAG_LNK; mode |= 0777; } else if (S_ISREG(mode)) { *header.typeflag = TYPEFLAG_REG; mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask; } else { return error(_("unsupported file mode: 0%o (SHA1: %s)"), mode, oid_to_hex(oid)); } if (pathlen > sizeof(header.name)) { size_t plen = get_path_prefix(path, pathlen, sizeof(header.prefix)); size_t rest = pathlen - plen - 1; if (plen > 0 && rest <= sizeof(header.name)) { memcpy(header.prefix, path, plen); memcpy(header.name, path + plen + 1, rest); } else { xsnprintf(header.name, sizeof(header.name), "%s.data", oid_to_hex(oid)); strbuf_append_ext_header(&ext_header, "path", path, pathlen); } } else memcpy(header.name, path, pathlen); if (S_ISREG(mode) && !args->convert && oid_object_info(args->repo, oid, &size) == OBJ_BLOB && size > big_file_threshold) buffer = NULL; else if (S_ISLNK(mode) || S_ISREG(mode)) { enum object_type type; buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size); if (!buffer) return error(_("cannot read %s"), oid_to_hex(oid)); } else { buffer = NULL; size = 0; } if (S_ISLNK(mode)) { if (size > sizeof(header.linkname)) { xsnprintf(header.linkname, sizeof(header.linkname), "see %s.paxheader", oid_to_hex(oid)); strbuf_append_ext_header(&ext_header, "linkpath", buffer, size); } else memcpy(header.linkname, buffer, size); } size_in_header = size; if (S_ISREG(mode) && size > USTAR_MAX_SIZE) { size_in_header = 0; strbuf_append_ext_header_uint(&ext_header, "size", size); } prepare_header(args, &header, mode, size_in_header); if (ext_header.len > 0) { write_extended_header(args, oid, ext_header.buf, ext_header.len); } strbuf_release(&ext_header); write_blocked(&header, sizeof(header)); if (S_ISREG(mode) && size > 0) { if (buffer) write_blocked(buffer, size); else err = stream_blocked(oid); } free(buffer); return err; }
int cgit_ref_path_exists(const char *path, const char *ref, int file_only) { struct object_id oid; unsigned long size; struct pathspec_item path_items = { .match = xstrdup(path), .len = strlen(path) }; struct pathspec paths = { .nr = 1, .items = &path_items }; struct walk_tree_context walk_tree_ctx = { .match_path = path, .matched_oid = &oid, .found_path = 0, .file_only = file_only }; if (get_oid(ref, &oid)) goto done; if (oid_object_info(the_repository, &oid, &size) != OBJ_COMMIT) goto done; read_tree_recursive(lookup_commit_reference(the_repository, &oid)->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); done: free(path_items.match); return walk_tree_ctx.found_path; } int cgit_print_file(char *path, const char *head, int file_only) { struct object_id oid; enum object_type type; char *buf; unsigned long size; struct commit *commit; struct pathspec_item path_items = { .match = path, .len = strlen(path) }; struct pathspec paths = { .nr = 1, .items = &path_items }; struct walk_tree_context walk_tree_ctx = { .match_path = path, .matched_oid = &oid, .found_path = 0, .file_only = file_only }; if (get_oid(head, &oid)) return -1; type = oid_object_info(the_repository, &oid, &size); if (type == OBJ_COMMIT) { commit = lookup_commit_reference(the_repository, &oid); read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); if (!walk_tree_ctx.found_path) return -1; type = oid_object_info(the_repository, &oid, &size); } if (type == OBJ_BAD) return -1; buf = read_object_file(&oid, &type, &size); if (!buf) return -1; buf[size] = '\0'; html_raw(buf, size); free(buf); return 0; } void cgit_print_blob(const char *hex, char *path, const char *head, int file_only) { struct object_id oid; enum object_type type; char *buf; unsigned long size; struct commit *commit; struct pathspec_item path_items = { .match = path, .len = path ? strlen(path) : 0 }; struct pathspec paths = { .nr = 1, .items = &path_items }; struct walk_tree_context walk_tree_ctx = { .match_path = path, .matched_oid = &oid, .found_path = 0, .file_only = file_only }; if (hex) { if (get_oid_hex(hex, &oid)) { cgit_print_error_page(400, "Bad request", "Bad hex value: %s", hex); return; } } else { if (get_oid(head, &oid)) { cgit_print_error_page(404, "Not found", "Bad ref: %s", head); return; } } type = oid_object_info(the_repository, &oid, &size); if ((!hex) && type == OBJ_COMMIT && path) { commit = lookup_commit_reference(the_repository, &oid); read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); type = oid_object_info(the_repository, &oid, &size); } if (type == OBJ_BAD) { cgit_print_error_page(404, "Not found", "Bad object name: %s", hex); return; } buf = read_object_file(&oid, &type, &size); if (!buf) { cgit_print_error_page(500, "Internal server error", "Error reading object %s", hex); return; } buf[size] = '\0'; if (buffer_is_binary(buf, size)) ctx.page.mimetype = "application/octet-stream"; else ctx.page.mimetype = "text/plain"; ctx.page.filename = path; html("X-Content-Type-Options: nosniff\n"); html("Content-Security-Policy: default-src 'none'\n"); cgit_print_http_headers(); html_raw(buf, size); free(buf); }