Merge branch 'jc/request-pull-show-head-4'
* jc/request-pull-show-head-4: request-pull: use the annotated tag contents fmt-merge-msg.c: Fix an "dubious one-bit signed bitfield" sparse error environment.c: Fix an sparse "symbol not declared" warning builtin/log.c: Fix an "Using plain integer as NULL pointer" warning fmt-merge-msg: use branch.$name.description request-pull: use the branch description request-pull: state what commit to expect request-pull: modernize style branch: teach --edit-description option format-patch: use branch description in cover letter branch: add read_branch_desc() helper function Conflicts: builtin/branch.c
This commit is contained in:
commit
a4043aeafe
@ -14,6 +14,7 @@ SYNOPSIS
|
||||
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
|
||||
'git branch' (-m | -M) [<oldbranch>] <newbranch>
|
||||
'git branch' (-d | -D) [-r] <branchname>...
|
||||
'git branch' --edit-description [<branchname>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -158,6 +159,10 @@ start-point is either a local or remote-tracking branch.
|
||||
like '--track' would when creating the branch, except that where
|
||||
branch points to is not changed.
|
||||
|
||||
--edit-description::
|
||||
Open an editor and edit the text to explain what the branch is
|
||||
for, to be used by various other commands (e.g. `request-pull`).
|
||||
|
||||
--contains <commit>::
|
||||
Only list branches which contain the specified commit.
|
||||
|
||||
|
1
Makefile
1
Makefile
@ -532,6 +532,7 @@ LIB_H += diffcore.h
|
||||
LIB_H += diff.h
|
||||
LIB_H += dir.h
|
||||
LIB_H += exec_cmd.h
|
||||
LIB_H += fmt-merge-msg.h
|
||||
LIB_H += fsck.h
|
||||
LIB_H += gettext.h
|
||||
LIB_H += git-compat-util.h
|
||||
|
31
branch.c
31
branch.c
@ -136,6 +136,37 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct branch_desc_cb {
|
||||
const char *config_name;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
static int read_branch_desc_cb(const char *var, const char *value, void *cb)
|
||||
{
|
||||
struct branch_desc_cb *desc = cb;
|
||||
if (strcmp(desc->config_name, var))
|
||||
return 0;
|
||||
free((char *)desc->value);
|
||||
return git_config_string(&desc->value, var, value);
|
||||
}
|
||||
|
||||
int read_branch_desc(struct strbuf *buf, const char *branch_name)
|
||||
{
|
||||
struct branch_desc_cb cb;
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
strbuf_addf(&name, "branch.%s.description", branch_name);
|
||||
cb.config_name = name.buf;
|
||||
cb.value = NULL;
|
||||
if (git_config(read_branch_desc_cb, &cb) < 0) {
|
||||
strbuf_release(&name);
|
||||
return -1;
|
||||
}
|
||||
if (cb.value)
|
||||
strbuf_addstr(buf, cb.value);
|
||||
strbuf_release(&name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int validate_new_branchname(const char *name, struct strbuf *ref,
|
||||
int force, int attr_only)
|
||||
{
|
||||
|
5
branch.h
5
branch.h
@ -46,4 +46,9 @@ void remove_branch_state(void);
|
||||
#define BRANCH_CONFIG_VERBOSE 01
|
||||
extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote);
|
||||
|
||||
/*
|
||||
* Read branch description
|
||||
*/
|
||||
extern int read_branch_desc(struct strbuf *, const char *branch_name);
|
||||
|
||||
#endif
|
||||
|
@ -623,11 +623,49 @@ static int opt_parse_merge_filter(const struct option *opt, const char *arg, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char edit_description[] = "BRANCH_DESCRIPTION";
|
||||
|
||||
static int edit_branch_description(const char *branch_name)
|
||||
{
|
||||
FILE *fp;
|
||||
int status;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
|
||||
read_branch_desc(&buf, branch_name);
|
||||
if (!buf.len || buf.buf[buf.len-1] != '\n')
|
||||
strbuf_addch(&buf, '\n');
|
||||
strbuf_addf(&buf,
|
||||
"# Please edit the description for the branch\n"
|
||||
"# %s\n"
|
||||
"# Lines starting with '#' will be stripped.\n",
|
||||
branch_name);
|
||||
fp = fopen(git_path(edit_description), "w");
|
||||
if ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {
|
||||
strbuf_release(&buf);
|
||||
return error(_("could not write branch description template: %s\n"),
|
||||
strerror(errno));
|
||||
}
|
||||
strbuf_reset(&buf);
|
||||
if (launch_editor(git_path(edit_description), &buf, NULL)) {
|
||||
strbuf_release(&buf);
|
||||
return -1;
|
||||
}
|
||||
stripspace(&buf, 1);
|
||||
|
||||
strbuf_addf(&name, "branch.%s.description", branch_name);
|
||||
status = git_config_set(name.buf, buf.buf);
|
||||
strbuf_release(&name);
|
||||
strbuf_release(&buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int delete = 0, rename = 0, force_create = 0, list = 0;
|
||||
int verbose = 0, abbrev = -1, detached = 0;
|
||||
int reflog = 0;
|
||||
int reflog = 0, edit_description = 0;
|
||||
enum branch_track track;
|
||||
int kinds = REF_LOCAL_BRANCH;
|
||||
struct commit_list *with_commit = NULL;
|
||||
@ -666,6 +704,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
|
||||
OPT_BOOLEAN(0, "list", &list, "list branch names"),
|
||||
OPT_BOOLEAN('l', "create-reflog", &reflog, "create the branch's reflog"),
|
||||
OPT_BOOLEAN(0, "edit-description", &edit_description,
|
||||
"edit the description for the branch"),
|
||||
OPT__FORCE(&force_create, "force creation (when already exists)"),
|
||||
{
|
||||
OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
|
||||
@ -705,7 +745,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
|
||||
0);
|
||||
|
||||
if (!delete && !rename && argc == 0)
|
||||
if (!delete && !rename && !edit_description && argc == 0)
|
||||
list = 1;
|
||||
|
||||
if (!!delete + !!rename + !!force_create + !!list > 1)
|
||||
@ -719,7 +759,19 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
else if (list)
|
||||
return print_ref_list(kinds, detached, verbose, abbrev,
|
||||
with_commit, argv);
|
||||
else if (rename) {
|
||||
else if (edit_description) {
|
||||
const char *branch_name;
|
||||
if (detached)
|
||||
die("Cannot give description to detached HEAD");
|
||||
if (!argc)
|
||||
branch_name = head;
|
||||
else if (argc == 1)
|
||||
branch_name = argv[0];
|
||||
else
|
||||
usage_with_options(builtin_branch_usage, options);
|
||||
if (edit_branch_description(branch_name))
|
||||
return 1;
|
||||
} else if (rename) {
|
||||
if (argc == 1)
|
||||
rename_branch(head, argv[0], rename > 1);
|
||||
else if (argc == 2)
|
||||
|
@ -5,23 +5,27 @@
|
||||
#include "revision.h"
|
||||
#include "tag.h"
|
||||
#include "string-list.h"
|
||||
#include "branch.h"
|
||||
#include "fmt-merge-msg.h"
|
||||
|
||||
static const char * const fmt_merge_msg_usage[] = {
|
||||
"git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int shortlog_len;
|
||||
static int use_branch_desc;
|
||||
|
||||
static int fmt_merge_msg_config(const char *key, const char *value, void *cb)
|
||||
int fmt_merge_msg_config(const char *key, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
|
||||
int is_bool;
|
||||
shortlog_len = git_config_bool_or_int(key, value, &is_bool);
|
||||
if (!is_bool && shortlog_len < 0)
|
||||
merge_log_config = git_config_bool_or_int(key, value, &is_bool);
|
||||
if (!is_bool && merge_log_config < 0)
|
||||
return error("%s: negative length %s", key, value);
|
||||
if (is_bool && shortlog_len)
|
||||
shortlog_len = DEFAULT_MERGE_LOG_LEN;
|
||||
if (is_bool && merge_log_config)
|
||||
merge_log_config = DEFAULT_MERGE_LOG_LEN;
|
||||
} else if (!strcmp(key, "merge.branchdesc")) {
|
||||
use_branch_desc = git_config_bool(key, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -31,6 +35,11 @@ struct src_data {
|
||||
int head_status;
|
||||
};
|
||||
|
||||
struct origin_data {
|
||||
unsigned char sha1[20];
|
||||
unsigned is_local_branch:1;
|
||||
};
|
||||
|
||||
static void init_src_data(struct src_data *data)
|
||||
{
|
||||
data->branch.strdup_strings = 1;
|
||||
@ -45,7 +54,7 @@ static struct string_list origins = STRING_LIST_INIT_DUP;
|
||||
static int handle_line(char *line)
|
||||
{
|
||||
int i, len = strlen(line);
|
||||
unsigned char *sha1;
|
||||
struct origin_data *origin_data;
|
||||
char *src, *origin;
|
||||
struct src_data *src_data;
|
||||
struct string_list_item *item;
|
||||
@ -61,11 +70,13 @@ static int handle_line(char *line)
|
||||
return 2;
|
||||
|
||||
line[40] = 0;
|
||||
sha1 = xmalloc(20);
|
||||
i = get_sha1(line, sha1);
|
||||
origin_data = xcalloc(1, sizeof(struct origin_data));
|
||||
i = get_sha1(line, origin_data->sha1);
|
||||
line[40] = '\t';
|
||||
if (i)
|
||||
if (i) {
|
||||
free(origin_data);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (line[len - 1] == '\n')
|
||||
line[len - 1] = 0;
|
||||
@ -93,6 +104,7 @@ static int handle_line(char *line)
|
||||
origin = src;
|
||||
src_data->head_status |= 1;
|
||||
} else if (!prefixcmp(line, "branch ")) {
|
||||
origin_data->is_local_branch = 1;
|
||||
origin = line + 7;
|
||||
string_list_append(&src_data->branch, origin);
|
||||
src_data->head_status |= 2;
|
||||
@ -119,7 +131,9 @@ static int handle_line(char *line)
|
||||
sprintf(new_origin, "%s of %s", origin, src);
|
||||
origin = new_origin;
|
||||
}
|
||||
string_list_append(&origins, origin)->util = sha1;
|
||||
if (strcmp(".", src))
|
||||
origin_data->is_local_branch = 0;
|
||||
string_list_append(&origins, origin)->util = origin_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -140,8 +154,29 @@ static void print_joined(const char *singular, const char *plural,
|
||||
}
|
||||
}
|
||||
|
||||
static void shortlog(const char *name, unsigned char *sha1,
|
||||
struct commit *head, struct rev_info *rev, int limit,
|
||||
static void add_branch_desc(struct strbuf *out, const char *name)
|
||||
{
|
||||
struct strbuf desc = STRBUF_INIT;
|
||||
|
||||
if (!read_branch_desc(&desc, name)) {
|
||||
const char *bp = desc.buf;
|
||||
while (*bp) {
|
||||
const char *ep = strchrnul(bp, '\n');
|
||||
if (*ep)
|
||||
ep++;
|
||||
strbuf_addf(out, " : %.*s", (int)(ep - bp), bp);
|
||||
bp = ep;
|
||||
}
|
||||
if (out->buf[out->len - 1] != '\n')
|
||||
strbuf_addch(out, '\n');
|
||||
}
|
||||
strbuf_release(&desc);
|
||||
}
|
||||
|
||||
static void shortlog(const char *name,
|
||||
struct origin_data *origin_data,
|
||||
struct commit *head,
|
||||
struct rev_info *rev, int limit,
|
||||
struct strbuf *out)
|
||||
{
|
||||
int i, count = 0;
|
||||
@ -150,6 +185,7 @@ static void shortlog(const char *name, unsigned char *sha1,
|
||||
struct string_list subjects = STRING_LIST_INIT_DUP;
|
||||
int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
const unsigned char *sha1 = origin_data->sha1;
|
||||
|
||||
branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
|
||||
if (!branch || branch->type != OBJ_COMMIT)
|
||||
@ -188,6 +224,9 @@ static void shortlog(const char *name, unsigned char *sha1,
|
||||
else
|
||||
strbuf_addf(out, "\n* %s:\n", name);
|
||||
|
||||
if (origin_data->is_local_branch && use_branch_desc)
|
||||
add_branch_desc(out, name);
|
||||
|
||||
for (i = 0; i < subjects.nr; i++)
|
||||
if (i >= limit)
|
||||
strbuf_addf(out, " ...\n");
|
||||
@ -303,7 +342,8 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
|
||||
strbuf_addch(out, '\n');
|
||||
|
||||
for (i = 0; i < origins.nr; i++)
|
||||
shortlog(origins.items[i].string, origins.items[i].util,
|
||||
shortlog(origins.items[i].string,
|
||||
origins.items[i].util,
|
||||
head, &rev, shortlog_len, out);
|
||||
}
|
||||
return 0;
|
||||
@ -318,6 +358,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *inpath = NULL;
|
||||
const char *message = NULL;
|
||||
int shortlog_len = -1;
|
||||
struct option options[] = {
|
||||
{ OPTION_INTEGER, 0, "log", &shortlog_len, "n",
|
||||
"populate log with at most <n> entries from shortlog",
|
||||
@ -341,6 +382,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
||||
0);
|
||||
if (argc > 0)
|
||||
usage_with_options(fmt_merge_msg_usage, options);
|
||||
if (shortlog_len < 0)
|
||||
shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
|
||||
if (message && !shortlog_len) {
|
||||
char nl = '\n';
|
||||
write_in_full(STDOUT_FILENO, message, strlen(message));
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "remote.h"
|
||||
#include "string-list.h"
|
||||
#include "parse-options.h"
|
||||
#include "branch.h"
|
||||
|
||||
/* Set a default date-time format for git log ("log.date" config variable) */
|
||||
static const char *default_date_mode = NULL;
|
||||
@ -746,10 +747,24 @@ static void print_signature(void)
|
||||
printf("-- \n%s\n\n", signature);
|
||||
}
|
||||
|
||||
static void add_branch_description(struct strbuf *buf, const char *branch_name)
|
||||
{
|
||||
struct strbuf desc = STRBUF_INIT;
|
||||
if (!branch_name || !*branch_name)
|
||||
return;
|
||||
read_branch_desc(&desc, branch_name);
|
||||
if (desc.len) {
|
||||
strbuf_addch(buf, '\n');
|
||||
strbuf_add(buf, desc.buf, desc.len);
|
||||
strbuf_addch(buf, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
int numbered, int numbered_files,
|
||||
struct commit *origin,
|
||||
int nr, struct commit **list, struct commit *head,
|
||||
const char *branch_name,
|
||||
int quiet)
|
||||
{
|
||||
const char *committer;
|
||||
@ -807,6 +822,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
pp_user_info(&pp, NULL, &sb, committer, encoding);
|
||||
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
|
||||
pp_remainder(&pp, &msg, &sb, 0);
|
||||
add_branch_description(&sb, branch_name);
|
||||
printf("%s\n", sb.buf);
|
||||
|
||||
strbuf_release(&sb);
|
||||
@ -1006,6 +1022,35 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *find_branch_name(struct rev_info *rev)
|
||||
{
|
||||
int i, positive = -1;
|
||||
unsigned char branch_sha1[20];
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
const char *branch;
|
||||
|
||||
for (i = 0; i < rev->cmdline.nr; i++) {
|
||||
if (rev->cmdline.rev[i].flags & UNINTERESTING)
|
||||
continue;
|
||||
if (positive < 0)
|
||||
positive = i;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (positive < 0)
|
||||
return NULL;
|
||||
strbuf_addf(&buf, "refs/heads/%s", rev->cmdline.rev[positive].name);
|
||||
branch = resolve_ref(buf.buf, branch_sha1, 1, NULL);
|
||||
if (!branch ||
|
||||
prefixcmp(branch, "refs/heads/") ||
|
||||
hashcmp(rev->cmdline.rev[positive].item->sha1, branch_sha1))
|
||||
branch = NULL;
|
||||
strbuf_release(&buf);
|
||||
if (branch)
|
||||
return xstrdup(rev->cmdline.rev[positive].name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct commit *commit;
|
||||
@ -1027,6 +1072,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int use_patch_format = 0;
|
||||
int quiet = 0;
|
||||
char *branch_name = NULL;
|
||||
const struct option builtin_format_patch_options[] = {
|
||||
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
|
||||
"use [PATCH n/m] even with a single patch",
|
||||
@ -1217,8 +1263,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
* origin" that prepares what the origin side still
|
||||
* does not have.
|
||||
*/
|
||||
unsigned char sha1[20];
|
||||
const char *ref;
|
||||
|
||||
rev.pending.objects[0].item->flags |= UNINTERESTING;
|
||||
add_head_to_pending(&rev);
|
||||
ref = resolve_ref("HEAD", sha1, 1, NULL);
|
||||
if (ref && !prefixcmp(ref, "refs/heads/"))
|
||||
branch_name = xstrdup(ref + strlen("refs/heads/"));
|
||||
else
|
||||
branch_name = xstrdup(""); /* no branch */
|
||||
}
|
||||
/*
|
||||
* Otherwise, it is "format-patch -22 HEAD", and/or
|
||||
@ -1234,16 +1288,26 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
rev.show_root_diff = 1;
|
||||
|
||||
if (cover_letter) {
|
||||
/* remember the range */
|
||||
/*
|
||||
* NEEDSWORK:randomly pick one positive commit to show
|
||||
* diffstat; this is often the tip and the command
|
||||
* happens to do the right thing in most cases, but a
|
||||
* complex command like "--cover-letter a b c ^bottom"
|
||||
* picks "c" and shows diffstat between bottom..c
|
||||
* which may not match what the series represents at
|
||||
* all and totally broken.
|
||||
*/
|
||||
int i;
|
||||
for (i = 0; i < rev.pending.nr; i++) {
|
||||
struct object *o = rev.pending.objects[i].item;
|
||||
if (!(o->flags & UNINTERESTING))
|
||||
head = (struct commit *)o;
|
||||
}
|
||||
/* We can't generate a cover letter without any patches */
|
||||
/* There is nothing to show; it is not an error, though. */
|
||||
if (!head)
|
||||
return 0;
|
||||
if (!branch_name)
|
||||
branch_name = find_branch_name(&rev);
|
||||
}
|
||||
|
||||
if (ignore_if_in_upstream) {
|
||||
@ -1294,7 +1358,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
if (thread)
|
||||
gen_message_id(&rev, "cover");
|
||||
make_cover_letter(&rev, use_stdout, numbered, numbered_files,
|
||||
origin, nr, list, head, quiet);
|
||||
origin, nr, list, head, branch_name, quiet);
|
||||
total++;
|
||||
start_number--;
|
||||
}
|
||||
@ -1366,6 +1430,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
fclose(stdout);
|
||||
}
|
||||
free(list);
|
||||
free(branch_name);
|
||||
string_list_clear(&extra_to, 0);
|
||||
string_list_clear(&extra_cc, 0);
|
||||
string_list_clear(&extra_hdr, 0);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "merge-recursive.h"
|
||||
#include "resolve-undo.h"
|
||||
#include "remote.h"
|
||||
#include "fmt-merge-msg.h"
|
||||
|
||||
#define DEFAULT_TWOHEAD (1<<0)
|
||||
#define DEFAULT_OCTOPUS (1<<1)
|
||||
@ -44,7 +45,7 @@ static const char * const builtin_merge_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int show_diffstat = 1, shortlog_len, squash;
|
||||
static int show_diffstat = 1, shortlog_len = -1, squash;
|
||||
static int option_commit = 1, allow_fast_forward = 1;
|
||||
static int fast_forward_only, option_edit;
|
||||
static int allow_trivial = 1, have_message;
|
||||
@ -542,6 +543,8 @@ static void parse_branch_merge_options(char *bmo)
|
||||
|
||||
static int git_merge_config(const char *k, const char *v, void *cb)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (branch && !prefixcmp(k, "branch.") &&
|
||||
!prefixcmp(k + 7, branch) &&
|
||||
!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
|
||||
@ -558,15 +561,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
|
||||
return git_config_string(&pull_octopus, k, v);
|
||||
else if (!strcmp(k, "merge.renormalize"))
|
||||
option_renormalize = git_config_bool(k, v);
|
||||
else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) {
|
||||
int is_bool;
|
||||
shortlog_len = git_config_bool_or_int(k, v, &is_bool);
|
||||
if (!is_bool && shortlog_len < 0)
|
||||
return error(_("%s: negative length %s"), k, v);
|
||||
if (is_bool && shortlog_len)
|
||||
shortlog_len = DEFAULT_MERGE_LOG_LEN;
|
||||
return 0;
|
||||
} else if (!strcmp(k, "merge.ff")) {
|
||||
else if (!strcmp(k, "merge.ff")) {
|
||||
int boolval = git_config_maybe_bool(k, v);
|
||||
if (0 <= boolval) {
|
||||
allow_fast_forward = boolval;
|
||||
@ -579,6 +574,9 @@ static int git_merge_config(const char *k, const char *v, void *cb)
|
||||
default_to_upstream = git_config_bool(k, v);
|
||||
return 0;
|
||||
}
|
||||
status = fmt_merge_msg_config(k, v, cb);
|
||||
if (status)
|
||||
return status;
|
||||
return git_diff_ui_config(k, v, cb);
|
||||
}
|
||||
|
||||
@ -1118,6 +1116,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
parse_branch_merge_options(branch_mergeoptions);
|
||||
argc = parse_options(argc, argv, prefix, builtin_merge_options,
|
||||
builtin_merge_usage, 0);
|
||||
if (shortlog_len < 0)
|
||||
shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
|
||||
|
||||
if (verbosity < 0 && show_progress == -1)
|
||||
show_progress = 0;
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "fmt-merge-msg.h"
|
||||
|
||||
char git_default_email[MAX_GITNAME];
|
||||
char git_default_name[MAX_GITNAME];
|
||||
@ -59,6 +60,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
|
||||
char *notes_ref_name;
|
||||
int grafts_replace_parents = 1;
|
||||
int core_apply_sparse_checkout;
|
||||
int merge_log_config = -1;
|
||||
struct startup_info *startup_info;
|
||||
|
||||
/* Parallel index stat data preload? */
|
||||
|
7
fmt-merge-msg.h
Normal file
7
fmt-merge-msg.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef FMT_MERGE_MSG_H
|
||||
#define FMT_MERGE_MSG_H
|
||||
|
||||
extern int merge_log_config;
|
||||
extern int fmt_merge_msg_config(const char *key, const char *value, void *cb);
|
||||
|
||||
#endif /* FMT_MERGE_MSG_H */
|
@ -35,44 +35,77 @@ do
|
||||
shift
|
||||
done
|
||||
|
||||
base=$1
|
||||
url=$2
|
||||
head=${3-HEAD}
|
||||
base=$1 url=$2 head=${3-HEAD} status=0 branch_name=
|
||||
|
||||
[ "$base" ] || usage
|
||||
[ "$url" ] || usage
|
||||
headref=$(git symbolic-ref -q "$head")
|
||||
if git show-ref -q --verify "$headref"
|
||||
then
|
||||
branch_name=${headref#refs/heads/}
|
||||
if test "z$branch_name" = "z$headref" ||
|
||||
! git config "branch.$branch_name.description" >/dev/null
|
||||
then
|
||||
branch_name=
|
||||
fi
|
||||
fi
|
||||
|
||||
baserev=`git rev-parse --verify "$base"^0` &&
|
||||
headrev=`git rev-parse --verify "$head"^0` || exit
|
||||
tag_name=$(git describe --exact "$head^0" 2>/dev/null)
|
||||
|
||||
merge_base=`git merge-base $baserev $headrev` ||
|
||||
test -n "$base" && test -n "$url" || usage
|
||||
baserev=$(git rev-parse --verify "$base"^0) &&
|
||||
headrev=$(git rev-parse --verify "$head"^0) || exit
|
||||
|
||||
merge_base=$(git merge-base $baserev $headrev) ||
|
||||
die "fatal: No commits in common between $base and $head"
|
||||
|
||||
branch=$(git ls-remote "$url" \
|
||||
| sed -n -e "/^$headrev refs.heads./{
|
||||
s/^.* refs.heads.//
|
||||
find_matching_branch="/^$headrev "'refs\/heads\//{
|
||||
s/^.* refs\/heads\///
|
||||
p
|
||||
q
|
||||
}")
|
||||
}'
|
||||
branch=$(git ls-remote "$url" | sed -n -e "$find_matching_branch")
|
||||
url=$(git ls-remote --get-url "$url")
|
||||
if [ -z "$branch" ]; then
|
||||
echo "warn: No branch of $url is at:" >&2
|
||||
git log --max-count=1 --pretty='tformat:warn: %h: %s' $headrev >&2
|
||||
echo "warn: Are you sure you pushed $head there?" >&2
|
||||
echo >&2
|
||||
echo >&2
|
||||
branch=..BRANCH.NOT.VERIFIED..
|
||||
status=1
|
||||
fi
|
||||
|
||||
git show -s --format='The following changes since commit %H:
|
||||
|
||||
%s (%ci)
|
||||
|
||||
are available in the git repository at:' $baserev &&
|
||||
echo " $url $branch" &&
|
||||
echo &&
|
||||
are available in the git repository at:
|
||||
' $baserev &&
|
||||
echo " $url${branch+ $branch}" &&
|
||||
git show -s --format='
|
||||
for you to fetch changes up to %H:
|
||||
|
||||
%s (%ci)
|
||||
|
||||
----------------------------------------------------------------' $headrev &&
|
||||
|
||||
if test -n "$branch_name"
|
||||
then
|
||||
echo "(from the branch description for $branch local branch)"
|
||||
echo
|
||||
git config "branch.$branch_name.description"
|
||||
fi &&
|
||||
|
||||
if test -n "$tag_name"
|
||||
then
|
||||
git cat-file tag "$tag_name" |
|
||||
sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
|
||||
echo
|
||||
fi &&
|
||||
|
||||
if test -n "$branch_name" || test -n "$tag_name"
|
||||
then
|
||||
echo "----------------------------------------------------------------"
|
||||
fi &&
|
||||
|
||||
git shortlog ^$baserev $headrev &&
|
||||
git diff -M --stat --summary $patch $merge_base..$headrev || exit
|
||||
git diff -M --stat --summary $patch $merge_base..$headrev || status=1
|
||||
|
||||
if test -z "$branch"
|
||||
then
|
||||
echo "warn: No branch of $url is at:" >&2
|
||||
git show -s --format='warn: %h: %s' $headrev >&2
|
||||
echo "warn: Are you sure you pushed '$head' there?" >&2
|
||||
status=1
|
||||
fi
|
||||
exit $status
|
||||
|
@ -86,6 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
|
||||
s/$downstream_url_for_sed/URL/g
|
||||
s/for-upstream/BRANCH/g
|
||||
s/mnemonic.txt/FILENAME/g
|
||||
s/^version [0-9]/VERSION/
|
||||
/^ FILENAME | *[0-9]* [-+]*\$/ b diffstat
|
||||
/^AUTHOR ([0-9]*):\$/ b shortlog
|
||||
p
|
||||
@ -193,8 +194,17 @@ test_expect_success 'pull request format' '
|
||||
SUBJECT (DATE)
|
||||
|
||||
are available in the git repository at:
|
||||
|
||||
URL BRANCH
|
||||
|
||||
for you to fetch changes up to OBJECT_NAME:
|
||||
|
||||
SUBJECT (DATE)
|
||||
|
||||
----------------------------------------------------------------
|
||||
VERSION
|
||||
|
||||
----------------------------------------------------------------
|
||||
SHORTLOG
|
||||
|
||||
DIFFSTAT
|
||||
|
Loading…
Reference in New Issue
Block a user