/*
* Blame
*
* Copyright (c) 2006, 2014 by its authors
* See COPYING for licensing conditions
*/
#include "cache.h"
#include "config.h"
#include "color.h"
#include "builtin.h"
#include "repository.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "quote.h"
#include "string-list.h"
#include "mailmap.h"
#include "parse-options.h"
#include "prio-queue.h"
#include "utf8.h"
#include "userdiff.h"
#include "line-range.h"
#include "line-log.h"
#include "dir.h"
#include "progress.h"
#include "object-store.h"
#include "blame.h"
#include "refs.h"
#include "tag.h"
static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
static const char *blame_opt_usage[] = {
blame_usage,
"",
N_("<rev-opts> are documented in git-rev-list(1)"),
NULL
};
static int longest_file;
static int longest_author;
static int max_orig_digits;
static int max_digits;
static int max_score_digits;
static int show_root;
static int reverse;
static int blank_boundary;
static int incremental;
static int xdl_opts;
static int abbrev = -1;
static int no_whole_file_rename;
static int show_progress;
static char repeated_meta_color[COLOR_MAXLEN];
static int coloring_mode;
static struct string_list ignore_revs_file_list = STRING_LIST_INIT_NODUP;
static int mark_unblamable_lines;
static int mark_ignored_lines;
static struct date_mode blame_date_mode = { DATE_ISO8601 };
static size_t blame_date_width;
static struct string_list mailmap = STRING_LIST_INIT_NODUP;
#ifndef DEBUG_BLAME
#define DEBUG_BLAME 0
#endif
static unsigned blame_move_score;
static unsigned blame_copy_score;
/* Remember to update object flag allocation in object.h */
#define METAINFO_SHOWN (1u<<12)
#define MORE_THAN_ONE_PATH (1u<<13)
struct progress_info {
struct progress *progress;
int blamed_lines;
};
static const char *nth_line_cb(void *data, long lno)
{
return blame_nth_line((struct blame_scoreboard *)data, lno);
}
/*
* Information on commits, used for output.
*/
struct commit_info {
struct strbuf author;
struct strbuf author_mail;
timestamp_t author_time;
struct strbuf author_tz;
/* filled only when asked for details */
struct strbuf committer;
struct strbuf committer_mail;
timestamp_t committer_time;
struct strbuf committer_tz;
struct strbuf summary;
};
#define COMMIT_INFO_INIT { \
.author = STRBUF_INIT, \
.author_mail = STRBUF_INIT, \
.author_tz = STRBUF_INIT, \
.committer = STRBUF_INIT, \
.committer_mail = STRBUF_INIT, \
.committer_tz = STRBUF_INIT, \
.summary = STRBUF_INIT, \
}
/*
* Parse author/committer line in the commit object buffer
*/
static void get_ac_line(const char *inbuf, const char *what,
struct strbuf *name, struct strbuf *mail,
timestamp_t *time, struct strbuf *tz)
{
struct ident_split ident;
size_t len, maillen, namelen;
char *tmp, *endp;
const char *namebuf, *mailbuf;
tmp = strstr(inbuf, what);
if (!tmp)
goto error_out;
tmp += strlen(what);
endp = strchr(tmp, '\n');
if (!endp)
len = strlen(tmp);
else
len = endp - tmp;
if (split_ident_line(&ident, tmp, len)) {
error_out:
/* Ugh */
tmp = "(unknown)";
strbuf_addstr(name, tmp);
strbuf_addstr(mail, tmp);
strbuf_addstr(tz, tmp);
*time = 0;
return;
}
namelen = ident.name_end - ident.name_begin;
namebuf = ident.name_begin;
maillen = ident.mail_end - ident.mail_begin;
|