Пример #1
0
int git_config_parse_parameter(const char *text)
{
	struct config_item *ct;
	struct strbuf tmp = STRBUF_INIT;
	struct strbuf **pair;
	strbuf_addstr(&tmp, text);
	pair = strbuf_split(&tmp, '=');
	if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
		strbuf_setlen(pair[0], pair[0]->len - 1);
	strbuf_trim(pair[0]);
	if (!pair[0]->len) {
		strbuf_list_free(pair);
		return -1;
	}
	ct = xcalloc(1, sizeof(struct config_item));
	ct->name = strbuf_detach(pair[0], NULL);
	if (pair[1]) {
		strbuf_trim(pair[1]);
		ct->value = strbuf_detach(pair[1], NULL);
	}
	strbuf_list_free(pair);
	lowercase(ct->name);
	*config_parameters_tail = ct;
	config_parameters_tail = &ct->next;
	return 0;
}
Пример #2
0
static void read_bisect_paths(struct argv_array *array)
{
	struct strbuf str = STRBUF_INIT;
	const char *filename = git_path("BISECT_NAMES");
	FILE *fp = fopen(filename, "r");

	if (!fp)
		die_errno("Could not open file '%s'", filename);

	while (strbuf_getline(&str, fp, '\n') != EOF) {
		char *quoted;
		int res;

		strbuf_trim(&str);
		quoted = strbuf_detach(&str, NULL);
		res = sq_dequote_to_argv(quoted, &array->argv,
					 &array->argv_nr, &array->argv_alloc);
		if (res)
			die("Badly quoted content in file '%s': %s",
			    filename, quoted);
	}

	strbuf_release(&str);
	fclose(fp);
}
Пример #3
0
/*
 * Turn
 * "pick d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some message"
 * into
 * "pick d6a2f03 some message"
 *
 * The function assumes that the line does not contain useless spaces
 * before or after the command.
 */
static void abbrev_sha1_in_line(struct strbuf *line)
{
	struct strbuf **split;
	int i;

	if (starts_with(line->buf, "exec ") ||
	    starts_with(line->buf, "x "))
		return;

	split = strbuf_split_max(line, ' ', 3);
	if (split[0] && split[1]) {
		unsigned char sha1[20];
		const char *abbrev;

		/*
		 * strbuf_split_max left a space. Trim it and re-add
		 * it after abbreviation.
		 */
		strbuf_trim(split[1]);
		if (!get_sha1(split[1]->buf, sha1)) {
			abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
			strbuf_reset(split[1]);
			strbuf_addf(split[1], "%s ", abbrev);
			strbuf_reset(line);
			for (i = 0; split[i]; i++)
				strbuf_addf(line, "%s", split[i]->buf);
		}
	}
	for (i = 0; split[i]; i++)
		strbuf_release(split[i]);

}
Пример #4
0
static void parse_bogus_from(const struct strbuf *line)
{
	/* John Doe <johndoe> */

	char *bra, *ket;
	/* This is fallback, so do not bother if we already have an
	 * e-mail address.
	 */
	if (email.len)
		return;

	bra = strchr(line->buf, '<');
	if (!bra)
		return;
	ket = strchr(bra, '>');
	if (!ket)
		return;

	strbuf_reset(&email);
	strbuf_add(&email, bra + 1, ket - bra - 1);

	strbuf_reset(&name);
	strbuf_add(&name, line->buf, bra - line->buf);
	strbuf_trim(&name);
	get_sane_name(&name, &name, &email);
}
Пример #5
0
static void cleanup_subject(struct strbuf *subject)
{
	char *pos;
	size_t remove;
	while (subject->len) {
		switch (*subject->buf) {
		case 'r': case 'R':
			if (subject->len <= 3)
				break;
			if (!memcmp(subject->buf + 1, "e:", 2)) {
				strbuf_remove(subject, 0, 3);
				continue;
			}
			break;
		case ' ': case '\t': case ':':
			strbuf_remove(subject, 0, 1);
			continue;
		case '[':
			if ((pos = strchr(subject->buf, ']'))) {
				remove = pos - subject->buf;
				if (remove <= (subject->len - remove) * 2) {
					strbuf_remove(subject, 0, remove + 1);
					continue;
				}
			} else
				strbuf_remove(subject, 0, 1);
			break;
		}
		strbuf_trim(subject);
		return;
	}
}
Пример #6
0
static int notes_cache_match_validity(struct repository *r,
				      const char *ref,
				      const char *validity)
{
	struct object_id oid;
	struct commit *commit;
	struct pretty_print_context pretty_ctx;
	struct strbuf msg = STRBUF_INIT;
	int ret;

	if (read_ref(ref, &oid) < 0)
		return 0;

	commit = lookup_commit_reference_gently(r, &oid, 1);
	if (!commit)
		return 0;

	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
	format_commit_message(commit, "%s", &msg, &pretty_ctx);
	strbuf_trim(&msg);

	ret = !strcmp(msg.buf, validity);
	strbuf_release(&msg);

	return ret;
}
Пример #7
0
static int show_http_message(struct strbuf *type, struct strbuf *charset,
			     struct strbuf *msg)
{
	const char *p, *eol;

	/*
	 * We only show text/plain parts, as other types are likely
	 * to be ugly to look at on the user's terminal.
	 */
	if (strcmp(type->buf, "text/plain"))
		return -1;
	if (charset->len)
		strbuf_reencode(msg, charset->buf, get_log_output_encoding());

	strbuf_trim(msg);
	if (!msg->len)
		return -1;

	p = msg->buf;
	do {
		eol = strchrnul(p, '\n');
		fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p);
		p = eol + 1;
	} while(*eol);
	return 0;
}
Пример #8
0
// normalize reference:  collapse internal whitespace to single space,
// remove leading/trailing whitespace, case fold
// Return NULL if the reference name is actually empty (i.e. composed
// solely from whitespace)
static unsigned char *normalize_reference(chunk *ref)
{
	strbuf normalized = GH_BUF_INIT;
	unsigned char *result;

	if(ref == NULL)
		return NULL;

	if (ref->len == 0)
		return NULL;

	utf8proc_case_fold(&normalized, ref->data, ref->len);
	strbuf_trim(&normalized);
	strbuf_normalize_whitespace(&normalized);

	result = strbuf_detach(&normalized);
	assert(result);

	if (result[0] == '\0') {
		free(result);
		return NULL;
	}

	return result;
}
Пример #9
0
static int show_http_message(struct strbuf *type, struct strbuf *msg)
{
	const char *p, *eol;

	/*
	 * We only show text/plain parts, as other types are likely
	 * to be ugly to look at on the user's terminal.
	 *
	 * TODO should handle "; charset=XXX", and re-encode into
	 * logoutputencoding
	 */
	if (strcasecmp(type->buf, "text/plain"))
		return -1;

	strbuf_trim(msg);
	if (!msg->len)
		return -1;

	p = msg->buf;
	do {
		eol = strchrnul(p, '\n');
		fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p);
		p = eol + 1;
	} while(*eol);
	return 0;
}
Пример #10
0
const char *ident_default_name(void)
{
	if (!git_default_name.len) {
		copy_gecos(xgetpwuid_self(&default_name_is_bogus), &git_default_name);
		strbuf_trim(&git_default_name);
	}
	return git_default_name.buf;
}
Пример #11
0
Файл: shell.c Проект: Advael/git
static void run_shell(void)
{
	int done = 0;
	static const char *help_argv[] = { HELP_COMMAND, NULL };
	/* Print help if enabled */
	run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE);

	do {
		struct strbuf line = STRBUF_INIT;
		const char *prog;
		char *full_cmd;
		char *rawargs;
		char *split_args;
		const char **argv;
		int code;
		int count;

		fprintf(stderr, "git> ");
		if (strbuf_getline(&line, stdin, '\n') == EOF) {
			fprintf(stderr, "\n");
			strbuf_release(&line);
			break;
		}
		strbuf_trim(&line);
		rawargs = strbuf_detach(&line, NULL);
		split_args = xstrdup(rawargs);
		count = split_cmdline(split_args, &argv);
		if (count < 0) {
			fprintf(stderr, "invalid command format '%s': %s\n", rawargs,
				split_cmdline_strerror(count));
			free(split_args);
			free(rawargs);
			continue;
		}

		prog = argv[0];
		if (!strcmp(prog, "")) {
		} else if (!strcmp(prog, "quit") || !strcmp(prog, "logout") ||
			   !strcmp(prog, "exit") || !strcmp(prog, "bye")) {
			done = 1;
		} else if (is_valid_cmd_name(prog)) {
			full_cmd = make_cmd(prog);
			argv[0] = full_cmd;
			code = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
			if (code == -1 && errno == ENOENT) {
				fprintf(stderr, "unrecognized command '%s'\n", prog);
			}
			free(full_cmd);
		} else {
			fprintf(stderr, "invalid command format '%s'\n", prog);
		}

		free(argv);
		free(rawargs);
	} while (!done);
}
Пример #12
0
static int is_expected_rev(const char *expected_hex)
{
	struct strbuf actual_hex = STRBUF_INIT;
	int res = 0;
	if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
		strbuf_trim(&actual_hex);
		res = !strcmp(actual_hex.buf, expected_hex);
	}
	strbuf_release(&actual_hex);
	return res;
}
Пример #13
0
static int merge_commit(struct notes_merge_options *o)
{
	struct strbuf msg = STRBUF_INIT;
	unsigned char sha1[20], parent_sha1[20];
	struct notes_tree *t;
	struct commit *partial;
	struct pretty_print_context pretty_ctx;
	void *local_ref_to_free;
	int ret;

	/*
	 * Read partial merge result from .git/NOTES_MERGE_PARTIAL,
	 * and target notes ref from .git/NOTES_MERGE_REF.
	 */

	if (get_sha1("NOTES_MERGE_PARTIAL", sha1))
		die("Failed to read ref NOTES_MERGE_PARTIAL");
	else if (!(partial = lookup_commit_reference(sha1)))
		die("Could not find commit from NOTES_MERGE_PARTIAL.");
	else if (parse_commit(partial))
		die("Could not parse commit from NOTES_MERGE_PARTIAL.");

	if (partial->parents)
		hashcpy(parent_sha1, partial->parents->item->object.sha1);
	else
		hashclr(parent_sha1);

	t = xcalloc(1, sizeof(struct notes_tree));
	init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);

	o->local_ref = local_ref_to_free =
		resolve_refdup("NOTES_MERGE_REF", 0, sha1, NULL);
	if (!o->local_ref)
		die("Failed to resolve NOTES_MERGE_REF");

	if (notes_merge_commit(o, t, partial, sha1))
		die("Failed to finalize notes merge");

	/* Reuse existing commit message in reflog message */
	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
	format_commit_message(partial, "%s", &msg, &pretty_ctx);
	strbuf_trim(&msg);
	strbuf_insert(&msg, 0, "notes: ", 7);
	update_ref(msg.buf, o->local_ref, sha1,
		   is_null_sha1(parent_sha1) ? NULL : parent_sha1,
		   0, UPDATE_REFS_DIE_ON_ERR);

	free_notes(t);
	strbuf_release(&msg);
	ret = merge_abort(o);
	free(local_ref_to_free);
	return ret;
}
Пример #14
0
/**
 * xargs_read: read a record from xargs stream
 *
 *	@param[in]	xp	xargs structure
 *	@return		result line
 */
char *
xargs_read(XARGS *xp)
{
	assert(xp != NULL);
	if (xp->end_of_arg)
		return NULL;
	if (xp->unread) {
		xp->unread = 0;
		return strbuf_value(xp->result);
	}
	if (xp->pipe && strbuf_fgets(xp->result, xp->pipe, STRBUF_NOCRLF) != NULL) {
		if (xp->trim_line)
			strbuf_trim(xp->result);
		return strbuf_value(xp->result);
	}
	if (xp->pipe)
		if (pclose(xp->pipe) != 0 && !xp->ignore_error)
			die("command failed in xargs_read().");
	/*
	 * Switch to the next segment.
	 */
	do {
		xp->pipe = execute_command(xp);
		if (xp->pipe && strbuf_fgets(xp->result, xp->pipe, STRBUF_NOCRLF) != NULL) {
			if (xp->trim_line)
				strbuf_trim(xp->result);
			return strbuf_value(xp->result);
		}
		if (xp->pipe) {
			if (pclose(xp->pipe) != 0 && !xp->ignore_error)
				die("command failed in xargs_read().");
		} else {
			xp->end_of_arg = 1;
		}
	} while (!xp->end_of_arg);

	return NULL;
}
Пример #15
0
Файл: mailinfo.c Проект: 9b/git
static void cleanup_subject(struct mailinfo *mi, struct strbuf *subject)
{
	size_t at = 0;

	while (at < subject->len) {
		char *pos;
		size_t remove;

		switch (subject->buf[at]) {
		case 'r': case 'R':
			if (subject->len <= at + 3)
				break;
			if ((subject->buf[at + 1] == 'e' ||
			     subject->buf[at + 1] == 'E') &&
			    subject->buf[at + 2] == ':') {
				strbuf_remove(subject, at, 3);
				continue;
			}
			at++;
			break;
		case ' ': case '\t': case ':':
			strbuf_remove(subject, at, 1);
			continue;
		case '[':
			pos = strchr(subject->buf + at, ']');
			if (!pos)
				break;
			remove = pos - subject->buf + at + 1;
			if (!mi->keep_non_patch_brackets_in_subject ||
			    (7 <= remove &&
			     memmem(subject->buf + at, remove, "PATCH", 5)))
				strbuf_remove(subject, at, remove);
			else {
				at += remove;
				/*
				 * If the input had a space after the ], keep
				 * it.  We don't bother with finding the end of
				 * the space, since we later normalize it
				 * anyway.
				 */
				if (isspace(subject->buf[at]))
					at += 1;
			}
			continue;
		}
		break;
	}
	strbuf_trim(subject);
}
Пример #16
0
/*
 * NEEDSWORK: this function can go once the legacy-difftool Perl script is
 * retired.
 *
 * We intentionally avoid reading the config directly here, to avoid messing up
 * the GIT_* environment variables when we need to fall back to exec()ing the
 * Perl script.
 */
static int use_builtin_difftool(void) {
    struct child_process cp = CHILD_PROCESS_INIT;
    struct strbuf out = STRBUF_INIT;
    int ret;

    argv_array_pushl(&cp.args,
                     "config", "--bool", "difftool.usebuiltin", NULL);
    cp.git_cmd = 1;
    if (capture_command(&cp, &out, 6))
        return 0;
    strbuf_trim(&out);
    ret = !strcmp("true", out.buf);
    strbuf_release(&out);
    return ret;
}
Пример #17
0
static char *find_linked_symref(const char *symref, const char *branch,
				const char *id)
{
	struct strbuf sb = STRBUF_INIT;
	struct strbuf path = STRBUF_INIT;
	struct strbuf gitdir = STRBUF_INIT;
	char *existing = NULL;

	/*
	 * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
	 * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
	 * git_path). Parse the ref ourselves.
	 */
	if (id)
		strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref);
	else
		strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref);

	if (!strbuf_readlink(&sb, path.buf, 0)) {
		if (!starts_with(sb.buf, "refs/") ||
		    check_refname_format(sb.buf, 0))
			goto done;
	} else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
	    starts_with(sb.buf, "ref:")) {
		strbuf_remove(&sb, 0, strlen("ref:"));
		strbuf_trim(&sb);
	} else
		goto done;
	if (strcmp(sb.buf, branch))
		goto done;
	if (id) {
		strbuf_reset(&path);
		strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
		if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
			goto done;
		strbuf_rtrim(&gitdir);
	} else
		strbuf_addstr(&gitdir, get_git_common_dir());
	strbuf_strip_suffix(&gitdir, ".git");

	existing = strbuf_detach(&gitdir, NULL);
done:
	strbuf_release(&path);
	strbuf_release(&sb);
	strbuf_release(&gitdir);

	return existing;
}
Пример #18
0
const char *ident_default_email(void)
{
	if (!git_default_email.len) {
		const char *email = getenv("EMAIL");

		if (email && email[0]) {
			strbuf_addstr(&git_default_email, email);
			committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
			author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
		} else
			copy_email(xgetpwuid_self(&default_email_is_bogus),
				   &git_default_email, &default_email_is_bogus);
		strbuf_trim(&git_default_email);
	}
	return git_default_email.buf;
}
Пример #19
0
static void read_rebase_todolist(const char *fname, struct string_list *lines)
{
	struct strbuf line = STRBUF_INIT;
	FILE *f = fopen(git_path("%s", fname), "r");

	if (!f)
		die_errno("Could not open file %s for reading",
			  git_path("%s", fname));
	while (!strbuf_getline(&line, f, '\n')) {
		if (line.len && line.buf[0] == comment_line_char)
			continue;
		strbuf_trim(&line);
		if (!line.len)
			continue;
		abbrev_sha1_in_line(&line);
		string_list_append(lines, line.buf);
	}
}
Пример #20
0
static void read_bisect_paths(struct argv_array *array)
{
	struct strbuf str = STRBUF_INIT;
	const char *filename = git_path_bisect_names();
	FILE *fp = fopen(filename, "r");

	if (!fp)
		die_errno("Could not open file '%s'", filename);

	while (strbuf_getline(&str, fp, '\n') != EOF) {
		strbuf_trim(&str);
		if (sq_dequote_to_argv_array(str.buf, array))
			die("Badly quoted content in file '%s': %s",
			    filename, str.buf);
	}

	strbuf_release(&str);
	fclose(fp);
}
Пример #21
0
int git_config_parse_parameter(const char *text,
			       config_fn_t fn, void *data)
{
	struct strbuf **pair;
	pair = strbuf_split_str(text, '=', 2);
	if (!pair[0])
		return error("bogus config parameter: %s", text);
	if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
		strbuf_setlen(pair[0], pair[0]->len - 1);
	strbuf_trim(pair[0]);
	if (!pair[0]->len) {
		strbuf_list_free(pair);
		return error("bogus config parameter: %s", text);
	}
	lowercase(pair[0]->buf);
	if (fn(pair[0]->buf, pair[1] ? pair[1]->buf : NULL, data) < 0) {
		strbuf_list_free(pair);
		return -1;
	}
	strbuf_list_free(pair);
	return 0;
}
Пример #22
0
const char *worktree_lock_reason(struct worktree *wt)
{
	assert(!is_main_worktree(wt));

	if (!wt->lock_reason_valid) {
		struct strbuf path = STRBUF_INIT;

		strbuf_addstr(&path, worktree_git_path(wt, "locked"));
		if (file_exists(path.buf)) {
			struct strbuf lock_reason = STRBUF_INIT;
			if (strbuf_read_file(&lock_reason, path.buf, 0) < 0)
				die_errno(_("failed to read '%s'"), path.buf);
			strbuf_trim(&lock_reason);
			wt->lock_reason = strbuf_detach(&lock_reason, NULL);
		} else
			wt->lock_reason = NULL;
		wt->lock_reason_valid = 1;
		strbuf_release(&path);
	}

	return wt->lock_reason;
}
Пример #23
0
static int use_builtin_stash(void)
{
	struct child_process cp = CHILD_PROCESS_INIT;
	struct strbuf out = STRBUF_INIT;
	int ret, env = git_env_bool("GIT_TEST_STASH_USE_BUILTIN", -1);

	if (env != -1)
		return env;

	argv_array_pushl(&cp.args,
			 "config", "--bool", "stash.usebuiltin", NULL);
	cp.git_cmd = 1;
	if (capture_command(&cp, &out, 6)) {
		strbuf_release(&out);
		return 1;
	}

	strbuf_trim(&out);
	ret = !strcmp("true", out.buf);
	strbuf_release(&out);
	return ret;
}
Пример #24
0
static int rollback_is_safe(void)
{
	struct strbuf sb = STRBUF_INIT;
	struct object_id expected_head, actual_head;

	if (strbuf_read_file(&sb, git_path_abort_safety_file(), 0) >= 0) {
		strbuf_trim(&sb);
		if (get_oid_hex(sb.buf, &expected_head)) {
			strbuf_release(&sb);
			die(_("could not parse %s"), git_path_abort_safety_file());
		}
		strbuf_release(&sb);
	}
	else if (errno == ENOENT)
		oidclr(&expected_head);
	else
		die_errno(_("could not read '%s'"), git_path_abort_safety_file());

	if (get_oid("HEAD", &actual_head))
		oidclr(&actual_head);

	return !oidcmp(&actual_head, &expected_head);
}
Пример #25
0
Файл: worktree.c Проект: 9b/git
/*
 * read 'path_to_ref' into 'ref'.  Also if is_detached is not NULL,
 * set is_detached to 1 (0) if the ref is detached (is not detached).
 *
 * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside $GIT_DIR so
 * for linked worktrees, `resolve_ref_unsafe()` won't work (it uses
 * git_path). Parse the ref ourselves.
 *
 * return -1 if the ref is not a proper ref, 0 otherwise (success)
 */
static int parse_ref(char *path_to_ref, struct strbuf *ref, int *is_detached)
{
	if (is_detached)
		*is_detached = 0;
	if (!strbuf_readlink(ref, path_to_ref, 0)) {
		/* HEAD is symbolic link */
		if (!starts_with(ref->buf, "refs/") ||
				check_refname_format(ref->buf, 0))
			return -1;
	} else if (strbuf_read_file(ref, path_to_ref, 0) >= 0) {
		/* textual symref or detached */
		if (!starts_with(ref->buf, "ref:")) {
			if (is_detached)
				*is_detached = 1;
		} else {
			strbuf_remove(ref, 0, strlen("ref:"));
			strbuf_trim(ref);
			if (check_refname_format(ref->buf, 0))
				return -1;
		}
	} else
		return -1;
	return 0;
}
Пример #26
0
static int notes_cache_match_validity(const char *ref, const char *validity)
{
	unsigned char sha1[20];
	struct commit *commit;
	struct pretty_print_context pretty_ctx;
	struct strbuf msg = STRBUF_INIT;
	int ret;

	if (read_ref(ref, sha1) < 0)
		return 0;

	commit = lookup_commit_reference_gently(sha1, 1);
	if (!commit)
		return 0;

	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
	format_commit_message(commit, "%s", &msg, &pretty_ctx);
	strbuf_trim(&msg);

	ret = !strcmp(msg.buf, validity);
	strbuf_release(&msg);

	return ret;
}
Пример #27
0
static void handle_from(const struct strbuf *from)
{
	char *at;
	size_t el;
	struct strbuf f;

	strbuf_init(&f, from->len);
	strbuf_addbuf(&f, from);

	at = strchr(f.buf, '@');
	if (!at) {
		parse_bogus_from(from);
		return;
	}

	/*
	 * If we already have one email, don't take any confusing lines
	 */
	if (email.len && strchr(at + 1, '@')) {
		strbuf_release(&f);
		return;
	}

	/* Pick up the string around '@', possibly delimited with <>
	 * pair; that is the email part.
	 */
	while (at > f.buf) {
		char c = at[-1];
		if (isspace(c))
			break;
		if (c == '<') {
			at[-1] = ' ';
			break;
		}
		at--;
	}
	el = strcspn(at, " \n\t\r\v\f>");
	strbuf_reset(&email);
	strbuf_add(&email, at, el);
	strbuf_remove(&f, at - f.buf, el + (at[el] ? 1 : 0));

	/* The remainder is name.  It could be
	 *
	 * - "John Doe <john.doe@xz>"			(a), or
	 * - "john.doe@xz (John Doe)"			(b), or
	 * - "John (zzz) Doe <john.doe@xz> (Comment)"	(c)
	 *
	 * but we have removed the email part, so
	 *
	 * - remove extra spaces which could stay after email (case 'c'), and
	 * - trim from both ends, possibly removing the () pair at the end
	 *   (cases 'a' and 'b').
	 */
	cleanup_space(&f);
	strbuf_trim(&f);
	if (f.buf[0] == '(' && f.len && f.buf[f.len - 1] == ')') {
		strbuf_remove(&f, 0, 1);
		strbuf_setlen(&f, f.len - 1);
	}

	get_sane_name(&name, &f, &email);
	strbuf_release(&f);
}
Пример #28
0
static void finalize(cmark_doc_parser *parser, cmark_node* b, int line_number)
{
	int firstlinelen;
	int pos;
	cmark_node* item;
	cmark_node* subitem;

	if (!b->open)
		return; // don't do anything if the cmark_node is already closed

	b->open = false;
	if (line_number > b->start_line) {
		b->end_line = line_number - 1;
	} else {
		b->end_line = line_number;
	}

	switch (b->type) {
		case NODE_PARAGRAPH:
			pos = 0;
			while (strbuf_at(&b->string_content, 0) == '[' &&
					(pos = parse_reference_inline(&b->string_content, parser->refmap))) {

				strbuf_drop(&b->string_content, pos);
			}
			if (is_blank(&b->string_content, 0)) {
				b->type = NODE_REFERENCE_DEF;
			}
			break;

		case NODE_INDENTED_CODE:
			remove_trailing_blank_lines(&b->string_content);
			strbuf_putc(&b->string_content, '\n');
			break;

		case NODE_FENCED_CODE:
			// first line of contents becomes info
			firstlinelen = strbuf_strchr(&b->string_content, '\n', 0);

			strbuf_init(&b->as.code.info, 0);
			houdini_unescape_html_f(
					&b->as.code.info,
					b->string_content.ptr,
					firstlinelen
					);

			strbuf_drop(&b->string_content, firstlinelen + 1);

			strbuf_trim(&b->as.code.info);
			strbuf_unescape(&b->as.code.info);
			break;

		case NODE_LIST: // determine tight/loose status
			b->as.list.tight = true; // tight by default
			item = b->first_child;

			while (item) {
				// check for non-final non-empty list item ending with blank line:
				if (item->last_line_blank && item->next) {
					b->as.list.tight = false;
					break;
				}
				// recurse into children of list item, to see if there are
				// spaces between them:
				subitem = item->first_child;
				while (subitem) {
					if (ends_with_blank_line(subitem) &&
							(item->next || subitem->next)) {
						b->as.list.tight = false;
						break;
					}
					subitem = subitem->next;
				}
				if (!(b->as.list.tight)) {
					break;
				}
				item = item->next;
			}

			break;

		default:
			break;
	}
}
Пример #29
0
void print_commit(struct commit *commit, struct rev_info *revs)
{
	struct commitinfo *info;
	int cols = revs->graph ? 3 : 2;
	struct strbuf graphbuf = STRBUF_INIT;
	struct strbuf msgbuf = STRBUF_INIT;

	if (ctx.repo->enable_log_filecount)
		cols++;
	if (ctx.repo->enable_log_linecount)
		cols++;

	if (revs->graph) {
		/* Advance graph until current commit */
		while (!graph_next_line(revs->graph, &graphbuf)) {
			/* Print graph segment in otherwise empty table row */
			html("<tr class='nohover'><td class='commitgraph'>");
			html(graphbuf.buf);
			htmlf("</td><td colspan='%d' /></tr>\n", cols);
			strbuf_setlen(&graphbuf, 0);
		}
		/* Current commit's graph segment is now ready in graphbuf */
	}

	info = cgit_parse_commit(commit);
	htmlf("<tr%s>", ctx.qry.showmsg ? " class='logheader'" : "");

	if (revs->graph) {
		/* Print graph segment for current commit */
		html("<td class='commitgraph'>");
		html(graphbuf.buf);
		html("</td>");
		strbuf_setlen(&graphbuf, 0);
	}
	else {
		html("<td>");
		cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
		html("</td>");
	}

	htmlf("<td%s>", ctx.qry.showmsg ? " class='logsubject'" : "");
	if (ctx.qry.showmsg) {
		/* line-wrap long commit subjects instead of truncating them */
		size_t subject_len = strlen(info->subject);

		if (subject_len > ctx.cfg.max_msg_len &&
		    ctx.cfg.max_msg_len >= 15) {
			/* symbol for signaling line-wrap (in PAGE_ENCODING) */
			const char wrap_symbol[] = { ' ', 0xE2, 0x86, 0xB5, 0 };
			int i = ctx.cfg.max_msg_len - strlen(wrap_symbol);

			/* Rewind i to preceding space character */
			while (i > 0 && !isspace(info->subject[i]))
				--i;
			if (!i) /* Oops, zero spaces. Reset i */
				i = ctx.cfg.max_msg_len - strlen(wrap_symbol);

			/* add remainder starting at i to msgbuf */
			strbuf_add(&msgbuf, info->subject + i, subject_len - i);
			strbuf_trim(&msgbuf);
			strbuf_add(&msgbuf, "\n\n", 2);

			/* Place wrap_symbol at position i in info->subject */
			strcpy(info->subject + i, wrap_symbol);
		}
	}
	cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
			 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
	show_commit_decorations(commit);
	html("</td><td>");
	html_txt(info->author);

	if (revs->graph) {
		html("</td><td>");
		cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
	}

	if (ctx.repo->enable_log_filecount || ctx.repo->enable_log_linecount) {
		files = 0;
		add_lines = 0;
		rem_lines = 0;
		cgit_diff_commit(commit, inspect_files, ctx.qry.vpath);
	}

	if (ctx.repo->enable_log_filecount)
		htmlf("</td><td>%d", files);
	if (ctx.repo->enable_log_linecount)
		htmlf("</td><td>-%d/+%d", rem_lines, add_lines);

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

	if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */
		html("<tr class='nohover'>");

		if (ctx.qry.showmsg) {
			/* Concatenate commit message + notes in msgbuf */
			if (info->msg && *(info->msg)) {
				strbuf_addstr(&msgbuf, info->msg);
				strbuf_addch(&msgbuf, '\n');
			}
			format_note(NULL, commit->object.sha1, &msgbuf,
			            PAGE_ENCODING,
			            NOTES_SHOW_HEADER | NOTES_INDENT);
			strbuf_addch(&msgbuf, '\n');
			strbuf_ltrim(&msgbuf);
		}

		if (revs->graph) {
			int lines = 0;

			/* Calculate graph padding */
			if (ctx.qry.showmsg) {
				/* Count #lines in commit message + notes */
				const char *p = msgbuf.buf;
				lines = 1;
				while ((p = strchr(p, '\n'))) {
					p++;
					lines++;
				}
			}

			/* Print graph padding */
			html("<td class='commitgraph'>");
			while (lines > 0 || !graph_is_commit_finished(revs->graph)) {
				if (graphbuf.len)
					html("\n");
				strbuf_setlen(&graphbuf, 0);
				graph_next_line(revs->graph, &graphbuf);
				html(graphbuf.buf);
				lines--;
			}
			html("</td>\n");
		}
		else
			html("<td/>"); /* Empty 'Age' column */

		/* Print msgbuf into remainder of table row */
		htmlf("<td colspan='%d'%s>\n", cols,
			ctx.qry.showmsg ? " class='logmsg'" : "");
		html_txt(msgbuf.buf);
		html("</td></tr>\n");
	}

	strbuf_release(&msgbuf);
	strbuf_release(&graphbuf);
	cgit_free_commitinfo(info);
}
Пример #30
0
static int
parse_commit(struct strbuf* input, struct string_list* files, struct strbuf* message)
{
    int err;
    int pos;
    struct strbuf line;
    int lineno = 0;
    enum { BEGIN, FILES, MESSAGE } state = BEGIN;
    enum { OK, FAILED } result = OK;

    // if there is no data, just return
    if (input->len == 0) {
        return 0;
    }

    strbuf_init(&line, 0);
    pos = 0;

    while (result == OK) {
        err = get_strbuf_line(input, &pos, &line);
        lineno++;
        if (err != 0) {
            break;
        }
        if (is_comment(&line)) {
            continue;
        }
        switch (state) {
        case BEGIN:
            strbuf_trim(&line);
            if (line.len != 0) {
                if (0 == strcmp(line.buf, "Files:")) {
                    state = FILES;
                } else {
                    result = FAILED;
                }
            }
            break;
        case FILES:
            strbuf_trim(&line);
            if (line.len != 0) {
                if (0 == strcmp(line.buf, "Commit Message:")) {
                    state = MESSAGE;
                }
                else if (0 == strip_file_info(&line)) {
                    string_list_insert(line.buf, files);
                }
                else {
                    result = FAILED;
                }
            }
            break;
        case MESSAGE:
            strbuf_rtrim(&line);
            strbuf_addbuf(message, &line);
            strbuf_addch(message, '\n');
            break;
        }
    }
    strbuf_trim(message);
    return result == OK ? 0 : 1;
}