summaryrefslogtreecommitdiff
path: root/builtin/blame.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/blame.c')
-rw-r--r--builtin/blame.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/builtin/blame.c b/builtin/blame.c
index 191368bfab..3b80e8fd75 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -6,6 +6,7 @@
*/
#include "cache.h"
+#include "refs.h"
#include "builtin.h"
#include "blob.h"
#include "commit.h"
@@ -50,7 +51,7 @@ static int xdl_opts;
static int abbrev = -1;
static int no_whole_file_rename;
-static enum date_mode blame_date_mode = DATE_ISO8601;
+static struct date_mode blame_date_mode = { DATE_ISO8601 };
static size_t blame_date_width;
static struct string_list mailmap;
@@ -458,12 +459,13 @@ static void queue_blames(struct scoreboard *sb, struct origin *porigin,
static struct origin *make_origin(struct commit *commit, const char *path)
{
struct origin *o;
- o = xcalloc(1, sizeof(*o) + strlen(path) + 1);
+ size_t pathlen = strlen(path) + 1;
+ o = xcalloc(1, sizeof(*o) + pathlen);
o->commit = commit;
o->refcnt = 1;
o->next = commit->util;
commit->util = o;
- strcpy(o->path, path);
+ memcpy(o->path, path, pathlen); /* includes NUL */
return o;
}
@@ -1370,8 +1372,15 @@ static void pass_whole_blame(struct scoreboard *sb,
*/
static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
{
- if (!reverse)
+ if (!reverse) {
+ if (revs->first_parent_only &&
+ commit->parents &&
+ commit->parents->next) {
+ free_commit_list(commit->parents->next);
+ commit->parents->next = NULL;
+ }
return commit->parents;
+ }
return lookup_decoration(&revs->children, &commit->object);
}
@@ -1832,7 +1841,7 @@ static const char *format_time(unsigned long time, const char *tz_str,
size_t time_width;
int tz;
tz = atoi(tz_str);
- time_str = show_date(time, tz, blame_date_mode);
+ time_str = show_date(time, tz, &blame_date_mode);
strbuf_addstr(&time_buf, time_str);
/*
* Add space paddings to time_buf to display a fixed width
@@ -1871,9 +1880,9 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
int cnt;
const char *cp;
struct origin *suspect = ent->suspect;
- char hex[41];
+ char hex[GIT_SHA1_HEXSZ + 1];
- strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
+ sha1_to_hex_r(hex, suspect->commit->object.sha1);
printf("%s %d %d %d\n",
hex,
ent->s_lno + 1,
@@ -1909,11 +1918,11 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt)
const char *cp;
struct origin *suspect = ent->suspect;
struct commit_info ci;
- char hex[41];
+ char hex[GIT_SHA1_HEXSZ + 1];
int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
get_commit_info(suspect->commit, &ci, 1);
- strcpy(hex, sha1_to_hex(suspect->commit->object.sha1));
+ sha1_to_hex_r(hex, suspect->commit->object.sha1);
cp = nth_line(sb, ent->lno);
for (cnt = 0; cnt < ent->num_lines; cnt++) {
@@ -2192,7 +2201,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "blame.date")) {
if (!value)
return config_error_nonbool(var);
- blame_date_mode = parse_date_format(value);
+ parse_date_format(value, &blame_date_mode);
return 0;
}
@@ -2231,20 +2240,19 @@ static struct commit_list **append_parent(struct commit_list **tail, const unsig
static void append_merge_parents(struct commit_list **tail)
{
int merge_head;
- const char *merge_head_file = git_path("MERGE_HEAD");
struct strbuf line = STRBUF_INIT;
- merge_head = open(merge_head_file, O_RDONLY);
+ merge_head = open(git_path_merge_head(), O_RDONLY);
if (merge_head < 0) {
if (errno == ENOENT)
return;
- die("cannot open '%s' for reading", merge_head_file);
+ die("cannot open '%s' for reading", git_path_merge_head());
}
while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) {
unsigned char sha1[20];
if (line.len < 40 || get_sha1_hex(line.buf, sha1))
- die("unknown line in '%s': %s", merge_head_file, line.buf);
+ die("unknown line in '%s': %s", git_path_merge_head(), line.buf);
tail = append_parent(tail, sha1);
}
close(merge_head);
@@ -2574,13 +2582,13 @@ parse_done:
if (cmd_is_annotate) {
output_option |= OUTPUT_ANNOTATE_COMPAT;
- blame_date_mode = DATE_ISO8601;
+ blame_date_mode.type = DATE_ISO8601;
} else {
blame_date_mode = revs.date_mode;
}
/* The maximum width used to show the dates */
- switch (blame_date_mode) {
+ switch (blame_date_mode.type) {
case DATE_RFC2822:
blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
break;
@@ -2605,10 +2613,12 @@ parse_done:
fewer display columns. */
blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */
break;
- case DATE_LOCAL:
case DATE_NORMAL:
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
break;
+ case DATE_STRFTIME:
+ blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */
+ break;
}
blame_date_width -= 1; /* strip the null */
@@ -2681,7 +2691,9 @@ parse_done:
sb.commits.compare = compare_commits_by_commit_date;
}
else if (contents_from)
- die("--contents and --children do not blend well.");
+ die("--contents and --reverse do not blend well.");
+ else if (revs.first_parent_only)
+ die("combining --first-parent and --reverse is not supported");
else {
final_commit_name = prepare_initial(&sb);
sb.commits.compare = compare_commits_by_reverse_commit_date;