/*
* Pickaxe
*
* Copyright (c) 2006, Junio C Hamano
*/
#include "cache.h"
#include "builtin.h"
#include "blob.h"
#include "commit.h"
#include "tag.h"
#include "tree-walk.h"
#include "diff.h"
#include "diffcore.h"
#include "revision.h"
#include "xdiff-interface.h"
#include <time.h>
#include <sys/time.h>
static char pickaxe_usage[] =
"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [-M] [commit] [--] file\n"
" -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
" -l, --long Show long commit SHA1 (Default: off)\n"
" -t, --time Show raw timestamp (Default: off)\n"
" -f, --show-name Show original filename (Default: auto)\n"
" -n, --show-number Show original linenumber (Default: off)\n"
" -p, --porcelain Show in a format designed for machine consumption\n"
" -L n,m Process only line range n,m, counting from 1\n"
" -M Find line movements within the file\n"
" -S revs-file Use revisions from revs-file instead of calling git-rev-list\n";
static int longest_file;
static int longest_author;
static int max_orig_digits;
static int max_digits;
#define DEBUG 0
#define PICKAXE_BLAME_MOVE 01
/* bits #0..7 in revision.h, #8..11 used for merge_bases() in commit.c */
#define METAINFO_SHOWN (1u<<12)
#define MORE_THAN_ONE_PATH (1u<<13)
/*
* One blob in a commit
*/
struct origin {
struct commit *commit;
unsigned char blob_sha1[20];
char path[FLEX_ARRAY];
};
struct blame_entry {
struct blame_entry *prev;
struct blame_entry *next;
/* the first line of this group in the final image;
* internally all line numbers are 0 based.
*/
int lno;
/* how many lines this group has */
int num_lines;
/* the commit that introduced this group into the final image */
struct origin *suspect;
/* true if the suspect is truly guilty; false while we have not
* checked if the group came from one of its parents.
*/
char guilty;
/* the line number of the first line of this group in the
* suspect's file; internally all line numbers are 0 based.
*/
int s_lno;
};
struct scoreboard {
/* the final commit (i.e. where we started digging from) */
struct commit *final;
const char *path;
/* the contents in the final; pointed into by buf pointers of
* blame_entries
*/
const char *final_buf;
unsigned long final_buf_size;
/* linked list of blames */
struct blame_entry *ent;
int num_lines;
int *lineno;
};
static void coalesce(struct scoreboard *sb)
{
struct blame_entry *ent, *next;
for (ent = sb->ent; ent && (next = ent->next); ent = next) {
if (ent->suspect == next->suspect &&
ent->guilty == next->guilty &&
ent->s_lno + ent->num_lines == next->s_lno) {
ent->num_lines += next->num_lines;
ent->next = next->next;
if (ent->next)
ent->next->prev = ent;
free(next);
next = ent; /* again */
}
}
}
static void free_origin(struct origin *o)
{
free(o);
}
static struct origin *find_origin(struct scoreboard *sb,
struct commit *commit,
const char *path)
{
struct blame_entry *ent;
struct origin *o;
unsigned mode;
char type[10];
|