static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) { void *data; if (use_threads) { read_sha1_lock(); data = read_sha1_file(sha1, type, size); read_sha1_unlock(); } else { data = read_sha1_file(sha1, type, size); } return data; }
struct taginfo *cgit_parse_tag(struct tag *tag) { void *data; enum object_type type; unsigned long size; const char *p; struct taginfo *ret = NULL; data = read_sha1_file(tag->object.oid.hash, &type, &size); if (!data || type != OBJ_TAG) goto cleanup; ret = xcalloc(1, sizeof(struct taginfo)); for (p = data; !end_of_header(p); p = next_header_line(p)) { if (skip_prefix(p, "tagger ", &p)) { parse_user(p, &ret->tagger, &ret->tagger_email, &ret->tagger_date, &ret->tagger_tz); } } while (p && *p == '\n') p++; if (p && *p) ret->msg = xstrdup(p); cleanup: free(data); return ret; }
/* A file entry went away or appeared */ static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, struct strbuf *base) { unsigned mode; const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); int pathlen = tree_entry_len(path, sha1); int old_baselen = base->len; strbuf_add(base, path, pathlen); if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; struct tree_desc inner; void *tree; unsigned long size; tree = read_sha1_file(sha1, &type, &size); if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) opt->add_remove(opt, *prefix, mode, sha1, base->buf, 0); strbuf_addch(base, '/'); init_tree_desc(&inner, tree, size); show_tree(opt, prefix, &inner, base); free(tree); } else opt->add_remove(opt, prefix[0], mode, sha1, base->buf, 0); strbuf_setlen(base, old_baselen); }
static int is_tag_in_date_range(struct object *tag, struct rev_info *revs) { unsigned long size; enum object_type type; char *buf = NULL, *line, *lineend; unsigned long date; int result = 1; if (revs->max_age == -1 && revs->min_age == -1) goto out; buf = read_sha1_file(tag->oid.hash, &type, &size); if (!buf) goto out; line = memmem(buf, size, "\ntagger ", 8); if (!line++) goto out; lineend = memchr(line, '\n', buf + size - line); line = memchr(line, '>', lineend ? lineend - line : buf + size - line); if (!line++) goto out; date = strtoul(line, NULL, 10); result = (revs->max_age == -1 || revs->max_age < date) && (revs->min_age == -1 || revs->min_age > date); out: free(buf); return result; }
static int is_tag_in_date_range(struct object *tag, struct rev_info *revs) { unsigned long size; enum object_type type; char *buf, *line, *lineend; unsigned long date; if (revs->max_age == -1 && revs->min_age == -1) return 1; buf = read_sha1_file(tag->sha1, &type, &size); if (!buf) return 1; line = memmem(buf, size, "\ntagger ", 8); if (!line++) return 1; lineend = memchr(line, buf + size - line, '\n'); line = memchr(line, lineend ? lineend - line : buf + size - line, '>'); if (!line++) return 1; date = strtoul(line, NULL, 10); free(buf); return (revs->max_age == -1 || revs->max_age < date) && (revs->min_age == -1 || revs->min_age > date); }
static int verify_tag(const char *name, int verbose) { enum object_type type; unsigned char sha1[20]; char *buf; unsigned long size; int ret; if (get_sha1(name, sha1)) return error("tag '%s' not found.", name); type = sha1_object_info(sha1, NULL); if (type != OBJ_TAG) return error("%s: cannot verify a non-tag object of type %s.", name, typename(type)); buf = read_sha1_file(sha1, &type, &size); if (!buf) return error("%s: unable to read file.", name); ret = run_gpg_verify(buf, size, verbose); free(buf); return ret; }
int parse_commit(struct commit *item) { char type[20]; void *buffer; unsigned long size; int ret; if (item->object.parsed) return 0; buffer = read_sha1_file(item->object.sha1, type, &size); if (!buffer) return error("Could not read %s", sha1_to_hex(item->object.sha1)); if (strcmp(type, commit_type)) { free(buffer); return error("Object %s not a commit", sha1_to_hex(item->object.sha1)); } ret = parse_commit_buffer(item, buffer, size); if (save_commit_buffer && !ret) { item->buffer = buffer; return 0; } free(buffer); return ret; }
/* A file entry went away or appeared */ static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base) { unsigned mode; const char *path; const unsigned char *sha1 = extract(desc, &path, &mode); if (opt->recursive && S_ISDIR(mode)) { char type[20]; char *newbase = malloc_base(base, path, strlen(path)); struct tree_desc inner; void *tree; tree = read_sha1_file(sha1, type, &inner.size); if (!tree || strcmp(type, "tree")) die("corrupt tree sha %s", sha1_to_hex(sha1)); inner.buf = tree; show_tree(opt, prefix, &inner, newbase); free(tree); free(newbase); return 0; } opt->add_remove(opt, prefix[0], mode, sha1, base, path); return 0; }
/* A file entry went away or appeared */ static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen) { unsigned mode; const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); int pathlen = tree_entry_len(path, sha1); if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; char *newbase = malloc_base(base, baselen, path, pathlen); struct tree_desc inner; void *tree; unsigned long size; tree = read_sha1_file(sha1, &type, &size); if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); init_tree_desc(&inner, tree, size); show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen); free(tree); free(newbase); } else { char *fullname = malloc_fullname(base, baselen, path, pathlen); opt->add_remove(opt, prefix[0], mode, sha1, fullname); free(fullname); } }
static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; char *buf; unsigned char object[20]; enum object_type type; unsigned long len; if (d->buf.len) strbuf_addch(&d->buf, '\n'); if (get_sha1(arg, object)) die(_("Failed to resolve '%s' as a valid ref."), arg); if (!(buf = read_sha1_file(object, &type, &len))) { free(buf); die(_("Failed to read object '%s'."), arg); } if (type != OBJ_BLOB) { free(buf); die(_("Cannot read note data from non-blob object '%s'."), arg); } strbuf_add(&d->buf, buf, len); free(buf); d->given = 1; return 0; }
/* * Given an origin, prepare mmfile_t structure to be used by the * diff machinery */ static void fill_origin_blob(struct diff_options *opt, struct blame_origin *o, mmfile_t *file, int *num_read_blob) { if (!o->file.ptr) { enum object_type type; unsigned long file_size; (*num_read_blob)++; if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size)) ; else file->ptr = read_sha1_file(o->blob_oid.hash, &type, &file_size); file->size = file_size; if (!file->ptr) die("Cannot read blob %s for path %s", oid_to_hex(&o->blob_oid), o->path); o->file = *file; } else *file = o->file; }
static int show_object(const unsigned char *sha1, int show_tag_object, struct rev_info *rev) { unsigned long size; enum object_type type; char *buf = read_sha1_file(sha1, &type, &size); int offset = 0; if (!buf) return error("Could not read object %s", sha1_to_hex(sha1)); if (show_tag_object) while (offset < size && buf[offset] != '\n') { int new_offset = offset + 1; while (new_offset < size && buf[new_offset++] != '\n') ; /* do nothing */ if (!prefixcmp(buf + offset, "tagger ")) show_tagger(buf + offset + 7, new_offset - offset - 7, rev); offset = new_offset; } if (offset < size) fwrite(buf + offset, size - offset, 1, stdout); free(buf); return 0; }
/* * Add the lines from the named object to list, with trailing * newlines removed. */ static int string_list_add_note_lines(struct string_list *list, const unsigned char *sha1) { char *data; unsigned long len; enum object_type t; if (is_null_sha1(sha1)) return 0; /* read_sha1_file NUL-terminates */ data = read_sha1_file(sha1, &t, &len); if (t != OBJ_BLOB || !data || !len) { free(data); return t != OBJ_BLOB || !data; } /* * If the last line of the file is EOL-terminated, this will * add an empty string to the list. But it will be removed * later, along with any empty strings that came from empty * lines within the file. */ string_list_split(list, data, '\n', -1); free(data); return 0; }
static int read_mailmap_blob(struct string_list *map, const char *name, char **repo_abbrev) { unsigned char sha1[20]; char *buf; unsigned long size; enum object_type type; if (!name) return 0; if (get_sha1(name, sha1) < 0) return 0; buf = read_sha1_file(sha1, &type, &size); if (!buf) return error("unable to read mailmap object at %s", name); if (type != OBJ_BLOB) return error("mailmap is not a blob: %s", name); read_mailmap_string(map, buf, repo_abbrev); free(buf); return 0; }
static int fsck_tag_buffer(struct tag *tag, const char *data, unsigned long size, struct fsck_options *options) { unsigned char sha1[20]; int ret = 0; const char *buffer; char *to_free = NULL, *eol; struct strbuf sb = STRBUF_INIT; if (data) buffer = data; else { enum object_type type; buffer = to_free = read_sha1_file(tag->object.oid.hash, &type, &size); if (!buffer) return report(options, &tag->object, FSCK_MSG_MISSING_TAG_OBJECT, "cannot read tag object"); if (type != OBJ_TAG) { ret = report(options, &tag->object, FSCK_MSG_TAG_OBJECT_NOT_TAG, "expected tag got %s", typename(type)); goto done; } }
static int cat_one_file(int opt, const char *exp_type, const char *obj_name) { unsigned char sha1[20]; enum object_type type; void *buf; unsigned long size; if (get_sha1(obj_name, sha1)) die("Not a valid object name %s", obj_name); buf = NULL; switch (opt) { case 't': type = sha1_object_info(sha1, NULL); if (type > 0) { printf("%s\n", typename(type)); return 0; } break; case 's': type = sha1_object_info(sha1, &size); if (type > 0) { printf("%lu\n", size); return 0; } break; case 'e': return !has_sha1_file(sha1); case 'p': type = sha1_object_info(sha1, NULL); if (type < 0) die("Not a valid object name %s", obj_name); /* custom pretty-print here */ if (type == OBJ_TREE) { const char *ls_args[3] = {"ls-tree", obj_name, NULL}; return cmd_ls_tree(2, ls_args, NULL); } buf = read_sha1_file(sha1, &type, &size); if (!buf) die("Cannot read object %s", obj_name); if (type == OBJ_TAG) { pprint_tag(sha1, buf, size); return 0; } /* otherwise just spit out the data */ break; case 0: buf = read_object_with_reference(sha1, exp_type, &size, NULL); break; default: die("git cat-file: unknown option: %s", exp_type); }
/* * A tree "hash1" has a subdirectory at "prefix". Come up with a * tree object by replacing it with another tree "hash2". */ static int splice_tree(const unsigned char *hash1, const char *prefix, const unsigned char *hash2, unsigned char *result) { char *subpath; int toplen; char *buf; unsigned long sz; struct tree_desc desc; unsigned char *rewrite_here; const unsigned char *rewrite_with; unsigned char subtree[20]; enum object_type type; int status; subpath = strchrnul(prefix, '/'); toplen = subpath - prefix; if (*subpath) subpath++; buf = read_sha1_file(hash1, &type, &sz); if (!buf) die("cannot read tree %s", sha1_to_hex(hash1)); init_tree_desc(&desc, buf, sz); rewrite_here = NULL; while (desc.size) { const char *name; unsigned mode; const unsigned char *sha1; sha1 = tree_entry_extract(&desc, &name, &mode); if (strlen(name) == toplen && !memcmp(name, prefix, toplen)) { if (!S_ISDIR(mode)) die("entry %s in tree %s is not a tree", name, sha1_to_hex(hash1)); rewrite_here = (unsigned char *) sha1; break; } update_tree_entry(&desc); } if (!rewrite_here) die("entry %.*s not found in tree %s", toplen, prefix, sha1_to_hex(hash1)); if (*subpath) { status = splice_tree(rewrite_here, subpath, hash2, subtree); if (status) return status; rewrite_with = subtree; } else rewrite_with = hash2; hashcpy(rewrite_here, rewrite_with); status = write_sha1_file(buf, sz, tree_type, result); free(buf); return status; }
static int handle_cache(const char *path, unsigned char *sha1, const char *output) { mmfile_t mmfile[3]; mmbuffer_t result = {NULL, 0}; struct cache_entry *ce; int pos, len, i, hunk_no; struct rerere_io_mem io; int marker_size = ll_merge_marker_size(path); /* * Reproduce the conflicted merge in-core */ len = strlen(path); pos = cache_name_pos(path, len); if (0 <= pos) return -1; pos = -pos - 1; for (i = 0; i < 3; i++) { enum object_type type; unsigned long size; mmfile[i].size = 0; mmfile[i].ptr = NULL; if (active_nr <= pos) break; ce = active_cache[pos++]; if (ce_namelen(ce) != len || memcmp(ce->name, path, len) || ce_stage(ce) != i + 1) break; mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size); mmfile[i].size = size; } for (i = 0; i < 3; i++) { if (!mmfile[i].ptr && !mmfile[i].size) mmfile[i].ptr = xstrdup(""); } ll_merge(&result, path, &mmfile[0], &mmfile[1], "ours", &mmfile[2], "theirs", 0); for (i = 0; i < 3; i++) free(mmfile[i].ptr); memset(&io, 0, sizeof(io)); io.io.getline = rerere_mem_getline; if (output) io.io.output = fopen(output, "w"); else io.io.output = NULL; strbuf_init(&io.input, 0); strbuf_attach(&io.input, result.ptr, result.size, result.size); hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size); strbuf_release(&io.input); if (io.io.output) fclose(io.io.output); return hunk_no; }
static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) { void *data; grep_read_lock(); data = read_sha1_file(sha1, type, size); grep_read_unlock(); return data; }
static void *lock_and_read_oid_file(const struct object_id *oid, enum object_type *type, unsigned long *size) { void *data; grep_read_lock(); data = read_sha1_file(oid->hash, type, size); grep_read_unlock(); return data; }
static int grep_tree(struct grep_opt *opt, const char **paths, struct tree_desc *tree, const char *tree_name, const char *base) { int len; int hit = 0; struct name_entry entry; char *down; int tn_len = strlen(tree_name); struct strbuf pathbuf; strbuf_init(&pathbuf, PATH_MAX + tn_len); if (tn_len) { strbuf_add(&pathbuf, tree_name, tn_len); strbuf_addch(&pathbuf, ':'); tn_len = pathbuf.len; } strbuf_addstr(&pathbuf, base); len = pathbuf.len; while (tree_entry(tree, &entry)) { int te_len = tree_entry_len(entry.path, entry.sha1); pathbuf.len = len; strbuf_add(&pathbuf, entry.path, te_len); if (S_ISDIR(entry.mode)) /* Match "abc/" against pathspec to * decide if we want to descend into "abc" * directory. */ strbuf_addch(&pathbuf, '/'); down = pathbuf.buf + tn_len; if (!pathspec_matches(paths, down)) ; else if (S_ISREG(entry.mode)) hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len); else if (S_ISDIR(entry.mode)) { enum object_type type; struct tree_desc sub; void *data; unsigned long size; data = read_sha1_file(entry.sha1, &type, &size); if (!data) die("unable to read tree (%s)", sha1_to_hex(entry.sha1)); init_tree_desc(&sub, data, size); hit |= grep_tree(opt, paths, &sub, tree_name, down); free(data); } } strbuf_release(&pathbuf); return hit; }
int combine_notes_concatenate(unsigned char *cur_sha1, const unsigned char *new_sha1) { char *cur_msg = NULL, *new_msg = NULL, *buf; unsigned long cur_len, new_len, buf_len; enum object_type cur_type, new_type; int ret; /* read in both note blob objects */ if (!is_null_sha1(new_sha1)) new_msg = read_sha1_file(new_sha1, &new_type, &new_len); if (!new_msg || !new_len || new_type != OBJ_BLOB) { free(new_msg); return 0; } if (!is_null_sha1(cur_sha1)) cur_msg = read_sha1_file(cur_sha1, &cur_type, &cur_len); if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) { free(cur_msg); free(new_msg); hashcpy(cur_sha1, new_sha1); return 0; } /* we will separate the notes by two newlines anyway */ if (cur_msg[cur_len - 1] == '\n') cur_len--; /* concatenate cur_msg and new_msg into buf */ buf_len = cur_len + 2 + new_len; buf = (char *) xmalloc(buf_len); memcpy(buf, cur_msg, cur_len); buf[cur_len] = '\n'; buf[cur_len + 1] = '\n'; memcpy(buf + cur_len + 2, new_msg, new_len); free(cur_msg); free(new_msg); /* create a new blob object from buf */ ret = write_sha1_file(buf, buf_len, blob_type, cur_sha1); free(buf); return ret; }
static void *origin(struct merge_list *entry, unsigned long *size) { enum object_type type; while (entry) { if (entry->stage == 2) return read_sha1_file(entry->blob->object.sha1, &type, size); entry = entry->link; } return NULL; }
/* * Given an object name, read the object data and size, and return a * "struct object". If the object data we are returning is also borrowed * by the "struct object" representation, set *eaten as well---it is a * signal from parse_object_buffer to us not to free the buffer. */ static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten) { enum object_type type; void *buf = read_sha1_file(sha1, &type, sz); if (buf) *obj = parse_object_buffer(sha1, type, *sz, buf, eaten); else *obj = NULL; return buf; }
static void write_note_data(int fd, const unsigned char *sha1) { unsigned long size; enum object_type type; char *buf = read_sha1_file(sha1, &type, &size); if (buf) { if (size) write_or_die(fd, buf, size); free(buf); } }
static void fmt_merge_msg_sigs(struct strbuf *out) { int i, tag_number = 0, first_tag = 0; struct strbuf tagbuf = STRBUF_INIT; for (i = 0; i < origins.nr; i++) { unsigned char *sha1 = origins.items[i].util; enum object_type type; unsigned long size, len; char *buf = read_sha1_file(sha1, &type, &size); struct strbuf sig = STRBUF_INIT; if (!buf || type != OBJ_TAG) goto next; len = parse_signature(buf, size); if (size == len) ; /* merely annotated */ else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) { if (!sig.len) strbuf_addstr(&sig, "gpg verification failed.\n"); } if (!tag_number++) { fmt_tag_signature(&tagbuf, &sig, buf, len); first_tag = i; } else { if (tag_number == 2) { struct strbuf tagline = STRBUF_INIT; strbuf_addch(&tagline, '\n'); strbuf_add_commented_lines(&tagline, origins.items[first_tag].string, strlen(origins.items[first_tag].string)); strbuf_insert(&tagbuf, 0, tagline.buf, tagline.len); strbuf_release(&tagline); } strbuf_addch(&tagbuf, '\n'); strbuf_add_commented_lines(&tagbuf, origins.items[i].string, strlen(origins.items[i].string)); fmt_tag_signature(&tagbuf, &sig, buf, len); } strbuf_release(&sig); next: free(buf); } if (tagbuf.len) { strbuf_addch(out, '\n'); strbuf_addbuf(out, &tagbuf); } strbuf_release(&tagbuf); }
void format_note(struct notes_tree *t, const unsigned char *object_sha1, struct strbuf *sb, const char *output_encoding, int flags) { static const char utf8[] = "utf-8"; const unsigned char *sha1; char *msg, *msg_p; unsigned long linelen, msglen; enum object_type type; if (!t) t = &default_notes_tree; if (!t->initialized) init_notes(t, NULL, NULL, 0); sha1 = get_note(t, object_sha1); if (!sha1) return; if (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen || type != OBJ_BLOB) { free(msg); return; } if (output_encoding && *output_encoding && strcmp(utf8, output_encoding)) { char *reencoded = reencode_string(msg, output_encoding, utf8); if (reencoded) { free(msg); msg = reencoded; msglen = strlen(msg); } } /* we will end the annotation by a newline anyway */ if (msglen && msg[msglen - 1] == '\n') msglen--; if (flags & NOTES_SHOW_HEADER) strbuf_addstr(sb, "\nNotes:\n"); for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) { linelen = strchrnul(msg_p, '\n') - msg_p; if (flags & NOTES_INDENT) strbuf_addstr(sb, " "); strbuf_add(sb, msg_p, linelen); strbuf_addch(sb, '\n'); } free(msg); }
static int load_mmfile(mmfile_t *file, const unsigned char *sha1) { enum object_type type; if (is_null_sha1(sha1)) { file->ptr = (char *)""; file->size = 0; } else { file->ptr = read_sha1_file(sha1, &type, (unsigned long *)&file->size); } return 1; }
/* * Match one itself and its subtrees with two and pick the best match. */ static void match_trees(const unsigned char *hash1, const unsigned char *hash2, int *best_score, char **best_match, const char *base, int recurse_limit) { struct tree_desc one; void *one_buf; enum object_type type; unsigned long size; one_buf = read_sha1_file(hash1, &type, &size); if (!one_buf) die("unable to read tree (%s)", sha1_to_hex(hash1)); if (type != OBJ_TREE) die("%s is not a tree", sha1_to_hex(hash1)); init_tree_desc(&one, one_buf, size); while (one.size) { const char *path; const unsigned char *elem; unsigned mode; int score; elem = tree_entry_extract(&one, &path, &mode); if (!S_ISDIR(mode)) goto next; score = score_trees(elem, hash2); if (*best_score < score) { char *newpath; newpath = xmalloc(strlen(base) + strlen(path) + 1); sprintf(newpath, "%s%s", base, path); free(*best_match); *best_match = newpath; *best_score = score; } if (recurse_limit) { char *newbase; newbase = xmalloc(strlen(base) + strlen(path) + 2); sprintf(newbase, "%s%s/", base, path); match_trees(elem, hash2, best_score, best_match, newbase, recurse_limit - 1); free(newbase); } next: update_tree_entry(&one); } free(one_buf); }
static int grep_source_load_sha1(struct grep_source *gs) { enum object_type type; grep_read_lock(); gs->buf = read_sha1_file(gs->identifier, &type, &gs->size); grep_read_unlock(); if (!gs->buf) return error(_("'%s': unable to read %s"), gs->name, sha1_to_hex(gs->identifier)); return 0; }