summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ea5ed3a)
raw | patch | inline | side by side (parent: ea5ed3a)
author | Fredrik Kuivinen <freku045@student.liu.se> | |
Sun, 5 Mar 2006 11:03:51 +0000 (12:03 +0100) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Sun, 5 Mar 2006 22:49:58 +0000 (14:49 -0800) |
The default output mode is slightly different from git-annotate's.
However, git-annotate's output mode can be obtained by using the
'-c' flag.
Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>
Signed-off-by: Junio C Hamano <junkio@cox.net>
However, git-annotate's output mode can be obtained by using the
'-c' flag.
Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Makefile | patch | blob | history | |
blame.c | patch | blob | history |
diff --git a/Makefile b/Makefile
index b6d8804d4b0cac60d1dd4943c5b9a791f26e006f..eb1887d7718a631fb72fddc1f42f94318d68e9aa 100644 (file)
--- a/Makefile
+++ b/Makefile
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(OPENSSL_LIBSSL)
+git-blame$X: blame.o $(LIB_FILE)
+ $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(LIBS) -lm
+
init-db.o: init-db.c
$(CC) -c $(ALL_CFLAGS) \
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
index 562940ecedbd4f89aee89b9b4c96e8e2f21451df..168b1f5fe5555b9e0697f211fb10859dbef327a3 100644 (file)
--- a/blame.c
+++ b/blame.c
#include <assert.h>
#include <time.h>
#include <sys/time.h>
+#include <math.h>
#include "cache.h"
#include "refs.h"
#define DEBUG 0
-struct commit **blame_lines;
-int num_blame_lines;
+static const char blame_usage[] = "[-c] [-l] [--] file [commit]\n"
+ " -c, --compability Use the same output mode as git-annotate (Default: off)\n"
+ " -l, --long Show long commit SHA1 (Default: off)\n"
+ " -h, --help This message";
+
+static struct commit **blame_lines;
+static int num_blame_lines;
+static char* blame_contents;
+static int blame_len;
struct util_info {
int *line_map;
alloc_line_map(commit);
util = commit->object.util;
- num_blame_lines = util->num_lines;
- for (i = 0; i < num_blame_lines; i++)
+ for (i = 0; i < util->num_lines; i++)
util->line_map[i] = i;
}
util = commit->object.util;
num_blame_lines = util->num_lines;
blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
+ blame_contents = util->buf;
+ blame_len = util->size;
+
for (i = 0; i < num_blame_lines; i++)
blame_lines[i] = NULL;
} while ((commit = get_revision(rev)) != NULL);
}
+struct commit_info
+{
+ char* author;
+ char* author_mail;
+ unsigned long author_time;
+ char* author_tz;
+};
+
+static void get_commit_info(struct commit* commit, struct commit_info* ret)
+{
+ int len;
+ char* tmp;
+ static char author_buf[1024];
+
+ tmp = strstr(commit->buffer, "\nauthor ") + 8;
+ len = index(tmp, '\n') - tmp;
+ ret->author = author_buf;
+ memcpy(ret->author, tmp, len);
+
+ tmp = ret->author;
+ tmp += len;
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_tz = tmp+1;
+
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_time = strtoul(tmp, NULL, 10);
+
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_mail = tmp + 1;
+
+ *tmp = 0;
+}
+
+char* format_time(unsigned long time, const char* tz)
+{
+ static char time_buf[128];
+ time_t t = time;
+
+ strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", gmtime(&t));
+ strcat(time_buf, tz);
+ return time_buf;
+}
+
int main(int argc, const char **argv)
{
int i;
struct commit *initial = NULL;
unsigned char sha1[20];
- const char* filename;
+
+ const char *filename = NULL, *commit = NULL;
+ char filename_buf[256];
+ int sha1_len = 8;
+ int compability = 0;
+ int options = 1;
+
int num_args;
const char* args[10];
struct rev_info rev;
- setup_git_directory();
+ struct commit_info ci;
+ const char *buf;
+ int max_digits;
- if (argc != 3)
- die("Usage: blame commit-ish file");
+ const char* prefix = setup_git_directory();
+ for(i = 1; i < argc; i++) {
+ if(options) {
+ if(!strcmp(argv[i], "-h") ||
+ !strcmp(argv[i], "--help"))
+ usage(blame_usage);
+ else if(!strcmp(argv[i], "-l") ||
+ !strcmp(argv[i], "--long")) {
+ sha1_len = 20;
+ continue;
+ } else if(!strcmp(argv[i], "-c") ||
+ !strcmp(argv[i], "--compability")) {
+ compability = 1;
+ continue;
+ } else if(!strcmp(argv[i], "--")) {
+ options = 0;
+ continue;
+ } else if(argv[i][0] == '-')
+ usage(blame_usage);
+ else
+ options = 0;
+ }
- filename = argv[2];
+ if(!options) {
+ if(!filename)
+ filename = argv[i];
+ else if(!commit)
+ commit = argv[i];
+ else
+ usage(blame_usage);
+ }
+ }
+
+ if(!filename)
+ usage(blame_usage);
+ if(!commit)
+ commit = "HEAD";
+
+ if(prefix)
+ sprintf(filename_buf, "%s%s", prefix, filename);
+ else
+ strcpy(filename_buf, filename);
+ filename = filename_buf;
{
- struct commit* commit;
- if (get_sha1(argv[1], sha1))
- die("get_sha1 failed");
- commit = lookup_commit_reference(sha1);
+ struct commit* c;
+ if (get_sha1(commit, sha1))
+ die("get_sha1 failed, commit '%s' not found", commit);
+ c = lookup_commit_reference(sha1);
- if (fill_util_info(commit, filename)) {
- printf("%s not found in %s\n", filename, argv[1]);
+ if (fill_util_info(c, filename)) {
+ printf("%s not found in %s\n", filename, commit);
return 1;
}
}
args[num_args++] = NULL;
args[num_args++] = "--topo-order";
args[num_args++] = "--remove-empty";
- args[num_args++] = argv[1];
+ args[num_args++] = commit;
args[num_args++] = "--";
args[num_args++] = filename;
args[num_args] = NULL;
prepare_revision_walk(&rev);
process_commits(&rev, filename, &initial);
+ buf = blame_contents;
+ max_digits = 1 + log(num_blame_lines+1)/log(10);
for (i = 0; i < num_blame_lines; i++) {
struct commit *c = blame_lines[i];
if (!c)
c = initial;
- printf("%d %.8s\n", i, sha1_to_hex(c->object.sha1));
-// printf("%d %s\n", i, find_unique_abbrev(blame_lines[i]->object.sha1, 6));
+ get_commit_info(c, &ci);
+ fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
+ if(compability)
+ printf("\t(%10s\t%10s\t%d)", ci.author,
+ format_time(ci.author_time, ci.author_tz), i+1);
+ else
+ printf(" (%-15.15s %10s %*d) ", ci.author,
+ format_time(ci.author_time, ci.author_tz),
+ max_digits, i+1);
+
+ if(i == num_blame_lines - 1) {
+ fwrite(buf, blame_len - (buf - blame_contents),
+ 1, stdout);
+ if(blame_contents[blame_len-1] != '\n')
+ putc('\n', stdout);
+ } else {
+ char* next_buf = index(buf, '\n') + 1;
+ fwrite(buf, next_buf - buf, 1, stdout);
+ buf = next_buf;
+ }
}
if (DEBUG) {