예제 #1
0
static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
{
	unsigned char sha1[20];
	enum object_type type;
	char *buf;
	unsigned long size;
	struct object_context obj_context;

	if (get_sha1_with_context(obj_name, sha1, &obj_context))
		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] = { NULL };
			ls_args[0] =  "ls-tree";
			ls_args[1] =  obj_name;
			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 'c':
		if (!obj_context.path[0])
			die("git cat-file --textconv %s: <object> must be <sha1:path>",
			    obj_name);

		if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size))
			die("git cat-file --textconv: unable to run textconv on %s",
			    obj_name);
		break;

	case 0:
		buf = read_object_with_reference(sha1, exp_type, &size, NULL);
		break;

	default:
		die("git cat-file: unknown option: %s", exp_type);
	}
예제 #2
0
파일: archive-tar.c 프로젝트: asmeurer/git
static int write_tar_entry(struct archiver_args *args,
                           const unsigned char *sha1,
                           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;
    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, sha1_to_hex(sha1));
    }
    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 {
            sprintf(header.name, "%s.data",
                    sha1_to_hex(sha1));
            strbuf_append_ext_header(&ext_header, "path",
                                     path, pathlen);
        }
    } else
        memcpy(header.name, path, pathlen);

    if (S_ISREG(mode) && !args->convert &&
            sha1_object_info(sha1, &size) == OBJ_BLOB &&
            size > big_file_threshold)
        buffer = NULL;
    else if (S_ISLNK(mode) || S_ISREG(mode)) {
        enum object_type type;
        buffer = sha1_file_to_archive(args, path, sha1, old_mode, &type, &size);
        if (!buffer)
            return error("cannot read %s", sha1_to_hex(sha1));
    } else {
        buffer = NULL;
        size = 0;
    }

    if (S_ISLNK(mode)) {
        if (size > sizeof(header.linkname)) {
            sprintf(header.linkname, "see %s.paxheader",
                    sha1_to_hex(sha1));
            strbuf_append_ext_header(&ext_header, "linkpath",
                                     buffer, size);
        } else
            memcpy(header.linkname, buffer, size);
    }

    prepare_header(args, &header, mode, size);

    if (ext_header.len > 0) {
        err = write_extended_header(args, sha1, ext_header.buf,
                                    ext_header.len);
        if (err) {
            free(buffer);
            return err;
        }
    }
    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(sha1);
    }
    free(buffer);
    return err;
}
예제 #3
0
static int update_local_ref(struct ref *ref,
			    const char *remote,
			    int verbose,
			    char *display)
{
	struct commit *current = NULL, *updated;
	enum object_type type;
	struct branch *current_branch = branch_get(NULL);
	const char *pretty_ref = ref->name + (
		!prefixcmp(ref->name, "refs/heads/") ? 11 :
		!prefixcmp(ref->name, "refs/tags/") ? 10 :
		!prefixcmp(ref->name, "refs/remotes/") ? 13 :
		0);

	*display = 0;
	type = sha1_object_info(ref->new_sha1, NULL);
	if (type < 0)
		die("object %s not found", sha1_to_hex(ref->new_sha1));

	if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
		if (verbose)
			sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
				"[up to date]", REFCOL_WIDTH, remote,
				pretty_ref);
		return 0;
	}

	if (current_branch &&
	    !strcmp(ref->name, current_branch->name) &&
	    !(update_head_ok || is_bare_repository()) &&
	    !is_null_sha1(ref->old_sha1)) {
		/*
		 * If this is the head, and it's not okay to update
		 * the head, and the old value of the head isn't empty...
		 */
		sprintf(display, "! %-*s %-*s -> %s  (can't fetch in current branch)",
			SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
			pretty_ref);
		return 1;
	}

	if (!is_null_sha1(ref->old_sha1) &&
	    !prefixcmp(ref->name, "refs/tags/")) {
		sprintf(display, "- %-*s %-*s -> %s",
			SUMMARY_WIDTH, "[tag update]", REFCOL_WIDTH, remote,
			pretty_ref);
		return s_update_ref("updating tag", ref, 0);
	}

	current = lookup_commit_reference_gently(ref->old_sha1, 1);
	updated = lookup_commit_reference_gently(ref->new_sha1, 1);
	if (!current || !updated) {
		const char *msg;
		const char *what;
		if (!strncmp(ref->name, "refs/tags/", 10)) {
			msg = "storing tag";
			what = "[new tag]";
		}
		else {
			msg = "storing head";
			what = "[new branch]";
		}

		sprintf(display, "* %-*s %-*s -> %s", SUMMARY_WIDTH, what,
			REFCOL_WIDTH, remote, pretty_ref);
		return s_update_ref(msg, ref, 0);
	}

	if (in_merge_bases(current, &updated, 1)) {
		char quickref[83];
		strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
		strcat(quickref, "..");
		strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
		sprintf(display, "  %-*s %-*s -> %s", SUMMARY_WIDTH, quickref,
			REFCOL_WIDTH, remote, pretty_ref);
		return s_update_ref("fast forward", ref, 1);
	} else if (force || ref->force) {
		char quickref[84];
		strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
		strcat(quickref, "...");
		strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
		sprintf(display, "+ %-*s %-*s -> %s  (forced update)",
			SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote, pretty_ref);
		return s_update_ref("forced-update", ref, 1);
	} else {
		sprintf(display, "! %-*s %-*s -> %s  (non fast forward)",
			SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
			pretty_ref);
		return 1;
	}
}
예제 #4
0
파일: ui-blame.c 프로젝트: johnkeeping/cgit
static void print_object(const unsigned char *sha1, const char *path,
			 const char *basename, const char *rev)
{
	enum object_type type;
	char *buf;
	unsigned long size;
	struct argv_array rev_argv = ARGV_ARRAY_INIT;
	struct rev_info revs;
	struct blame_scoreboard sb;
	struct blame_origin *o;
	struct blame_entry *ent = NULL;

	type = sha1_object_info(sha1, &size);
	if (type == OBJ_BAD) {
		cgit_print_error_page(404, "Not found", "Bad object name: %s",
				      sha1_to_hex(sha1));
		return;
	}

	buf = read_sha1_file(sha1, &type, &size);
	if (!buf) {
		cgit_print_error_page(500, "Internal server error",
			"Error reading object %s", sha1_to_hex(sha1));
		return;
	}

	argv_array_push(&rev_argv, "blame");
	argv_array_push(&rev_argv, rev);
	init_revisions(&revs, NULL);
	revs.diffopt.flags.allow_textconv = 1;
	setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL);
	init_scoreboard(&sb);
	sb.revs = &revs;
	setup_scoreboard(&sb, path, &o);
	o->suspects = blame_entry_prepend(NULL, 0, sb.num_lines, o);
	prio_queue_put(&sb.commits, o->commit);
	blame_origin_decref(o);
	sb.ent = NULL;
	sb.path = path;
	assign_blame(&sb, 0);
	blame_sort_final(&sb);
	blame_coalesce(&sb);

	cgit_set_title_from_path(path);

	cgit_print_layout_start();
	htmlf("blob: %s (", sha1_to_hex(sha1));
	cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path);
	html(") (");
	cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path);
	html(")\n");

	if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
		htmlf("<div class='error'>blob size (%ldKB)"
		      " exceeds display size limit (%dKB).</div>",
		      size / 1024, ctx.cfg.max_blob_size);
		return;
	}

	html("<table class='blame blob'>\n<tr>\n");

	/* Commit hashes */
	html("<td class='hashes'>");
	for (ent = sb.ent; ent; ent = ent->next) {
		html("<div class='alt'><pre>");
		emit_blame_entry_hash(ent);
		html("</pre></div>");
	}
	html("</td>\n");

	/* Line numbers */
	if (ctx.cfg.enable_tree_linenumbers) {
		html("<td class='linenumbers'>");
		for (ent = sb.ent; ent; ent = ent->next) {
			html("<div class='alt'><pre>");
			emit_blame_entry_linenumber(ent);
			html("</pre></div>");
		}
		html("</td>\n");
	}

	html("<td class='lines'><div>");

	/* Colored bars behind lines */
	html("<div>");
	for (ent = sb.ent; ent; ) {
		struct blame_entry *e = ent->next;
		html("<div class='alt'><pre>");
		emit_blame_entry_line_background(&sb, ent);
		html("</pre></div>");
		free(ent);
		ent = e;
	}
	html("</div>");

	free((void *)sb.final_buf);

	/* Lines */
	html("<pre><code>");
	if (ctx.repo->source_filter) {
		char *filter_arg = xstrdup(basename);
		cgit_open_filter(ctx.repo->source_filter, filter_arg);
		html_raw(buf, size);
		cgit_close_filter(ctx.repo->source_filter);
		free(filter_arg);
	} else {
		html_txt(buf);
	}
	html("</code></pre>");

	html("</div></td>\n");

	html("</tr>\n</table>\n");

	cgit_print_layout_end();
}
예제 #5
0
파일: cat-file.c 프로젝트: 7sOddities/git
static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
{
	unsigned char sha1[20];
	enum object_type type;
	char *buf;
	unsigned long size;
	struct object_context obj_context;

	if (get_sha1_with_context(obj_name, 0, sha1, &obj_context))
		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 'c':
		if (!obj_context.path[0])
			die("git cat-file --textconv %s: <object> must be <sha1:path>",
			    obj_name);

		if (textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size))
			break;

	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] = { NULL };
			ls_args[0] =  "ls-tree";
			ls_args[1] =  obj_name;
			return cmd_ls_tree(2, ls_args, NULL);
		}

		if (type == OBJ_BLOB)
			return stream_blob_to_fd(1, sha1, NULL, 0);
		buf = read_sha1_file(sha1, &type, &size);
		if (!buf)
			die("Cannot read object %s", obj_name);

		/* otherwise just spit out the data */
		break;

	case 0:
		if (type_from_string(exp_type) == OBJ_BLOB) {
			unsigned char blob_sha1[20];
			if (sha1_object_info(sha1, NULL) == OBJ_TAG) {
				enum object_type type;
				unsigned long size;
				char *buffer = read_sha1_file(sha1, &type, &size);
				if (memcmp(buffer, "object ", 7) ||
				    get_sha1_hex(buffer + 7, blob_sha1))
					die("%s not a valid tag", sha1_to_hex(sha1));
				free(buffer);
			} else
				hashcpy(blob_sha1, sha1);

			if (sha1_object_info(blob_sha1, NULL) == OBJ_BLOB)
				return stream_blob_to_fd(1, blob_sha1, NULL, 0);
			/*
			 * we attempted to dereference a tag to a blob
			 * and failed; there may be new dereference
			 * mechanisms this code is not aware of.
			 * fall-back to the usual case.
			 */
		}
		buf = read_object_with_reference(sha1, exp_type, &size, NULL);
		break;

	default:
		die("git cat-file: unknown option: %s", exp_type);
	}
예제 #6
0
파일: ui-blob.c 프로젝트: 5victor/cgit
int cgit_print_file(char *path, const char *head)
{
	unsigned char sha1[20];
	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_sha1 = sha1,
		.found_path = 0
	};

	if (get_sha1(head, sha1))
		return -1;
	type = sha1_object_info(sha1, &size);
	if (type == OBJ_COMMIT && path) {
		commit = lookup_commit_reference(sha1);
		read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
		if (!walk_tree_ctx.found_path)
			return -1;
		type = sha1_object_info(sha1, &size);
	}
	if (type == OBJ_BAD)
		return -1;
	buf = read_sha1_file(sha1, &type, &size);
	if (!buf)
		return -1;
	buf[size] = '\0';
	html_raw(buf, size);
	return 0;
}

void cgit_print_blob(const char *hex, char *path, const char *head)
{
	unsigned char sha1[20];
	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_sha1 = sha1,
	};

	if (hex) {
		if (get_sha1_hex(hex, sha1)) {
			cgit_print_error(fmt("Bad hex value: %s", hex));
			return;
		}
	} else {
		if (get_sha1(head, sha1)) {
			cgit_print_error(fmt("Bad ref: %s", head));
			return;
		}
	}

	type = sha1_object_info(sha1, &size);

	if ((!hex) && type == OBJ_COMMIT && path) {
		commit = lookup_commit_reference(sha1);
		read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
		type = sha1_object_info(sha1,&size);
	}

	if (type == OBJ_BAD) {
		cgit_print_error(fmt("Bad object name: %s", hex));
		return;
	}

	buf = read_sha1_file(sha1, &type, &size);
	if (!buf) {
		cgit_print_error(fmt("Error reading object %s", hex));
		return;
	}

	buf[size] = '\0';
	ctx.page.mimetype = ctx.qry.mimetype;
	if (!ctx.page.mimetype) {
		if (buffer_is_binary(buf, size))
			ctx.page.mimetype = "application/octet-stream";
		else
			ctx.page.mimetype = "text/plain";
	}
	ctx.page.filename = path;
	cgit_print_http_headers(&ctx);
	html_raw(buf, size);
}
예제 #7
0
파일: tag.c 프로젝트: 136357477/git
static void create_tag(const unsigned char *object, const char *tag,
		       struct strbuf *buf, struct create_tag_options *opt,
		       unsigned char *prev, unsigned char *result)
{
	enum object_type type;
	char header_buf[1024];
	int header_len;
	char *path = NULL;

	type = sha1_object_info(object, NULL);
	if (type <= OBJ_NONE)
	    die(_("bad object type."));

	header_len = snprintf(header_buf, sizeof(header_buf),
			  "object %s\n"
			  "type %s\n"
			  "tag %s\n"
			  "tagger %s\n\n",
			  sha1_to_hex(object),
			  typename(type),
			  tag,
			  git_committer_info(IDENT_STRICT));

	if (header_len > sizeof(header_buf) - 1)
		die(_("tag header too big."));

	if (!opt->message_given) {
		int fd;

		/* write the template message before editing: */
		path = git_pathdup("TAG_EDITMSG");
		fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
		if (fd < 0)
			die_errno(_("could not create file '%s'"), path);

		if (!is_null_sha1(prev)) {
			write_tag_body(fd, prev);
		} else {
			struct strbuf buf = STRBUF_INIT;
			strbuf_addch(&buf, '\n');
			if (opt->cleanup_mode == CLEANUP_ALL)
				strbuf_commented_addf(&buf, _(tag_template), tag, comment_line_char);
			else
				strbuf_commented_addf(&buf, _(tag_template_nocleanup), tag, comment_line_char);
			write_or_die(fd, buf.buf, buf.len);
			strbuf_release(&buf);
		}
		close(fd);

		if (launch_editor(path, buf, NULL)) {
			fprintf(stderr,
			_("Please supply the message using either -m or -F option.\n"));
			exit(1);
		}
	}

	if (opt->cleanup_mode != CLEANUP_NONE)
		strbuf_stripspace(buf, opt->cleanup_mode == CLEANUP_ALL);

	if (!opt->message_given && !buf->len)
		die(_("no tag message?"));

	strbuf_insert(buf, 0, header_buf, header_len);

	if (build_tag_object(buf, opt->sign, result) < 0) {
		if (path)
			fprintf(stderr, _("The tag message has been left in %s\n"),
				path);
		exit(128);
	}
	if (path) {
		unlink_or_warn(path);
		free(path);
	}
}