From: Junio C Hamano Date: Fri, 2 Mar 2007 08:37:12 +0000 (-0800) Subject: Merge branch 'js/commit-format' X-Git-Tag: v1.5.1-rc1~108 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/8ab3e1858676b91bf351537b8afd5599c6640e6f?ds=inline;hp=-c Merge branch 'js/commit-format' * js/commit-format: show_date(): rename the "relative" parameter to "mode" Actually make print_wrapped_text() useful pretty-formats: add 'format:' --- 8ab3e1858676b91bf351537b8afd5599c6640e6f diff --combined cache.h index b84e3decfc,75418c0a4c..8018b2cd3b --- a/cache.h +++ b/cache.h @@@ -106,16 -106,6 +106,16 @@@ static inline unsigned int create_ce_mo return htonl(S_IFLNK); return htonl(S_IFREG | ce_permissions(mode)); } +static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode) +{ + extern int trust_executable_bit; + if (!trust_executable_bit && S_ISREG(mode)) { + if (ce && S_ISREG(ntohl(ce->ce_mode))) + return ce->ce_mode; + return create_ce_mode(0666); + } + return create_ce_mode(mode); +} #define canon_mode(mode) \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ S_ISLNK(mode) ? S_IFLNK : S_IFDIR) @@@ -127,19 -117,6 +127,19 @@@ extern unsigned int active_nr, active_a extern struct cache_tree *active_cache_tree; extern int cache_errno; +enum object_type { + OBJ_BAD = -1, + OBJ_NONE = 0, + OBJ_COMMIT = 1, + OBJ_TREE = 2, + OBJ_BLOB = 3, + OBJ_TAG = 4, + /* 5 for future expansion */ + OBJ_OFS_DELTA = 6, + OBJ_REF_DELTA = 7, + OBJ_MAX, +}; + #define GIT_DIR_ENVIRONMENT "GIT_DIR" #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" @@@ -190,7 -167,7 +190,7 @@@ extern int ce_same_name(struct cache_en extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int); extern int ce_modified(struct cache_entry *ce, struct stat *st, int); extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); -extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type); +extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path); extern int read_pipe(int fd, char** return_buf, unsigned long* return_size); extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object); extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object); @@@ -224,7 -201,6 +224,7 @@@ extern const char *apply_default_whites extern int zlib_compression_level; extern size_t packed_git_window_size; extern size_t packed_git_limit; +extern int auto_crlf; #define GIT_REPO_VERSION 0 extern int repository_format_version; @@@ -276,12 -252,12 +276,12 @@@ int safe_create_leading_directories(cha char *enter_repo(char *path, int strict); /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ -extern int sha1_object_info(const unsigned char *, char *, unsigned long *); -extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size); -extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size); +extern int sha1_object_info(const unsigned char *, unsigned long *); +extern void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size); +extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size); extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1); -extern int pretend_sha1_file(void *, unsigned long, const char *, unsigned char *); +extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); @@@ -298,6 -274,18 +298,6 @@@ extern int legacy_loose_object(unsigne extern int has_pack_file(const unsigned char *sha1); extern int has_pack_index(const unsigned char *sha1); -enum object_type { - OBJ_NONE = 0, - OBJ_COMMIT = 1, - OBJ_TREE = 2, - OBJ_BLOB = 3, - OBJ_TAG = 4, - /* 5 for future expansion */ - OBJ_OFS_DELTA = 6, - OBJ_REF_DELTA = 7, - OBJ_BAD, -}; - extern signed char hexval_table[256]; static inline unsigned int hexval(unsigned int c) { @@@ -327,7 -315,8 +327,8 @@@ extern void *read_object_with_reference unsigned long *size, unsigned char *sha1_ret); - const char *show_date(unsigned long time, int timezone, int relative); + enum date_mode { DATE_NORMAL = 0, DATE_RELATIVE, DATE_SHORT }; + const char *show_date(unsigned long time, int timezone, enum date_mode mode); const char *show_rfc2822_date(unsigned long time, int timezone); int parse_date(const char *date, char *buf, int bufsize); void datestamp(char *buf, int bufsize); @@@ -423,9 -412,9 +424,9 @@@ extern struct packed_git *add_packed_gi extern int num_packed_objects(const struct packed_git *p); extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *); -extern void *unpack_entry(struct packed_git *, unsigned long, char *, unsigned long *); +extern void *unpack_entry(struct packed_git *, unsigned long, enum object_type *, unsigned long *); extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); -extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *); +extern const char *packed_object_info_detail(struct packed_git *, unsigned long, unsigned long *, unsigned long *, unsigned int *, unsigned char *); /* Dumb servers support */ extern int update_server_info(int); @@@ -480,8 -469,4 +481,8 @@@ extern int nfvasprintf(char **str, cons extern void trace_printf(const char *format, ...); extern void trace_argv_printf(const char **argv, int count, const char *format, ...); +/* convert.c */ +extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep); +extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep); + #endif /* CACHE_H */ diff --combined commit.c index da515a4973,f78ce262f6..5552527342 --- a/commit.c +++ b/commit.c @@@ -3,6 -3,7 +3,7 @@@ #include "commit.h" #include "pkt-line.h" #include "utf8.h" + #include "interpolate.h" int save_commit_buffer = 1; @@@ -36,8 -37,11 +37,11 @@@ struct cmt_fmt_map { "full", 5, CMIT_FMT_FULL }, { "fuller", 5, CMIT_FMT_FULLER }, { "oneline", 1, CMIT_FMT_ONELINE }, + { "format:", 7, CMIT_FMT_USERFORMAT}, }; + static char *user_format; + enum cmit_fmt get_commit_format(const char *arg) { int i; @@@ -46,6 -50,12 +50,12 @@@ return CMIT_FMT_DEFAULT; if (*arg == '=') arg++; + if (!prefixcmp(arg, "format:")) { + if (user_format) + free(user_format); + user_format = xstrdup(arg + 7); + return CMIT_FMT_USERFORMAT; + } for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) { if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) && !strncmp(arg, cmt_fmts[i].n, strlen(arg))) @@@ -342,18 -352,18 +352,18 @@@ int parse_commit_buffer(struct commit * int parse_commit(struct commit *item) { - char type[20]; + enum object_type type; void *buffer; unsigned long size; int ret; if (item->object.parsed) return 0; - buffer = read_sha1_file(item->object.sha1, type, &size); + buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) return error("Could not read %s", sha1_to_hex(item->object.sha1)); - if (strcmp(type, commit_type)) { + if (type != OBJ_COMMIT) { free(buffer); return error("Object %s not a commit", sha1_to_hex(item->object.sha1)); @@@ -710,6 -720,188 +720,188 @@@ static char *logmsg_reencode(const stru return out; } + static char *xstrndup(const char *text, int len) + { + char *result = xmalloc(len + 1); + memcpy(result, text, len); + result[len] = '\0'; + return result; + } + + static void fill_person(struct interp *table, const char *msg, int len) + { + int start, end, tz = 0; + unsigned long date; + char *ep; + + /* parse name */ + for (end = 0; end < len && msg[end] != '<'; end++) + ; /* do nothing */ + start = end + 1; + while (end > 0 && isspace(msg[end - 1])) + end--; + table[0].value = xstrndup(msg, end); + + if (start >= len) + return; + + /* parse email */ + for (end = start + 1; end < len && msg[end] != '>'; end++) + ; /* do nothing */ + + if (end >= len) + return; + + table[1].value = xstrndup(msg + start, end - start); + + /* parse date */ + for (start = end + 1; start < len && isspace(msg[start]); start++) + ; /* do nothing */ + if (start >= len) + return; + date = strtoul(msg + start, &ep, 10); + if (msg + start == ep) + return; + + table[5].value = xstrndup(msg + start, ep - msg + start); + + /* parse tz */ + for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) + ; /* do nothing */ + if (start + 1 < len) { + tz = strtoul(msg + start + 1, NULL, 10); + if (msg[start] == '-') + tz = -tz; + } + + interp_set_entry(table, 2, show_date(date, tz, 0)); + interp_set_entry(table, 3, show_rfc2822_date(date, tz)); + interp_set_entry(table, 4, show_date(date, tz, 1)); + } + + static long format_commit_message(const struct commit *commit, + const char *msg, char *buf, unsigned long space) + { + struct interp table[] = { + { "%H" }, /* commit hash */ + { "%h" }, /* abbreviated commit hash */ + { "%T" }, /* tree hash */ + { "%t" }, /* abbreviated tree hash */ + { "%P" }, /* parent hashes */ + { "%p" }, /* abbreviated parent hashes */ + { "%an" }, /* author name */ + { "%ae" }, /* author email */ + { "%ad" }, /* author date */ + { "%aD" }, /* author date, RFC2822 style */ + { "%ar" }, /* author date, relative */ + { "%at" }, /* author date, UNIX timestamp */ + { "%cn" }, /* committer name */ + { "%ce" }, /* committer email */ + { "%cd" }, /* committer date */ + { "%cD" }, /* committer date, RFC2822 style */ + { "%cr" }, /* committer date, relative */ + { "%ct" }, /* committer date, UNIX timestamp */ + { "%e" }, /* encoding */ + { "%s" }, /* subject */ + { "%b" }, /* body */ + { "%Cred" }, /* red */ + { "%Cgreen" }, /* green */ + { "%Cblue" }, /* blue */ + { "%Creset" }, /* reset color */ + { "%n" } /* newline */ + }; + enum interp_index { + IHASH = 0, IHASH_ABBREV, + ITREE, ITREE_ABBREV, + IPARENTS, IPARENTS_ABBREV, + IAUTHOR_NAME, IAUTHOR_EMAIL, + IAUTHOR_DATE, IAUTHOR_DATE_RFC2822, IAUTHOR_DATE_RELATIVE, + IAUTHOR_TIMESTAMP, + ICOMMITTER_NAME, ICOMMITTER_EMAIL, + ICOMMITTER_DATE, ICOMMITTER_DATE_RFC2822, + ICOMMITTER_DATE_RELATIVE, ICOMMITTER_TIMESTAMP, + IENCODING, + ISUBJECT, + IBODY, + IRED, IGREEN, IBLUE, IRESET_COLOR, + INEWLINE + }; + struct commit_list *p; + char parents[1024]; + int i; + enum { HEADER, SUBJECT, BODY } state; + + if (INEWLINE + 1 != ARRAY_SIZE(table)) + die("invalid interp table!"); + + /* these are independent of the commit */ + interp_set_entry(table, IRED, "\033[31m"); + interp_set_entry(table, IGREEN, "\033[32m"); + interp_set_entry(table, IBLUE, "\033[34m"); + interp_set_entry(table, IRESET_COLOR, "\033[m"); + interp_set_entry(table, INEWLINE, "\n"); + + /* these depend on the commit */ + if (!commit->object.parsed) + parse_object(commit->object.sha1); + interp_set_entry(table, IHASH, sha1_to_hex(commit->object.sha1)); + interp_set_entry(table, IHASH_ABBREV, + find_unique_abbrev(commit->object.sha1, + DEFAULT_ABBREV)); + interp_set_entry(table, ITREE, sha1_to_hex(commit->tree->object.sha1)); + interp_set_entry(table, ITREE_ABBREV, + find_unique_abbrev(commit->tree->object.sha1, + DEFAULT_ABBREV)); + for (i = 0, p = commit->parents; + p && i < sizeof(parents) - 1; + p = p->next) + i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + sha1_to_hex(p->item->object.sha1)); + interp_set_entry(table, IPARENTS, parents); + for (i = 0, p = commit->parents; + p && i < sizeof(parents) - 1; + p = p->next) + i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + find_unique_abbrev(p->item->object.sha1, + DEFAULT_ABBREV)); + interp_set_entry(table, IPARENTS_ABBREV, parents); + + for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { + int eol; + for (eol = i; msg[eol] && msg[eol] != '\n'; eol++) + ; /* do nothing */ + + if (state == SUBJECT) { + table[ISUBJECT].value = xstrndup(msg + i, eol - i); + i = eol; + } + if (i == eol) { + state++; + /* strip empty lines */ + while (msg[eol + 1] == '\n') + eol++; + } else if (!prefixcmp(msg + i, "author ")) + fill_person(table + IAUTHOR_NAME, + msg + i + 7, eol - i - 7); + else if (!prefixcmp(msg + i, "committer ")) + fill_person(table + ICOMMITTER_NAME, + msg + i + 10, eol - i - 10); + else if (!prefixcmp(msg + i, "encoding ")) + table[IENCODING].value = xstrndup(msg + i, eol - i); + i = eol; + } + if (msg[i]) + table[IBODY].value = xstrdup(msg + i); + for (i = 0; i < ARRAY_SIZE(table); i++) + if (!table[i].value) + interp_set_entry(table, i, ""); + + interpolate(buf, space, user_format, table, ARRAY_SIZE(table)); + interp_clear_table(table, ARRAY_SIZE(table)); + + return strlen(buf); + } + unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, @@@ -727,6 -919,9 +919,9 @@@ char *reencoded; char *encoding; + if (fmt == CMIT_FMT_USERFORMAT) + return format_commit_message(commit, msg, buf, space); + encoding = (git_log_output_encoding ? git_log_output_encoding : git_commit_encoding); @@@ -1187,17 -1382,14 +1382,17 @@@ struct commit_list *get_merge_bases(str return result; } -int in_merge_bases(struct commit *rev1, struct commit *rev2) +int in_merge_bases(struct commit *commit, struct commit **reference, int num) { struct commit_list *bases, *b; int ret = 0; - bases = get_merge_bases(rev1, rev2, 1); + if (num == 1) + bases = get_merge_bases(commit, *reference, 1); + else + die("not yet"); for (b = bases; b; b = b->next) { - if (!hashcmp(rev1->object.sha1, b->item->object.sha1)) { + if (!hashcmp(commit->object.sha1, b->item->object.sha1)) { ret = 1; break; } diff --combined commit.h index c73744463c,8feeb2c7ba..83507a07e4 --- a/commit.h +++ b/commit.h @@@ -47,6 -47,7 +47,7 @@@ enum cmit_fmt CMIT_FMT_FULLER, CMIT_FMT_ONELINE, CMIT_FMT_EMAIL, + CMIT_FMT_USERFORMAT, CMIT_FMT_UNSPECIFIED, }; @@@ -114,5 -115,5 +115,5 @@@ extern int is_repository_shallow(void) extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); -int in_merge_bases(struct commit *rev1, struct commit *rev2); +int in_merge_bases(struct commit *, struct commit **, int); #endif /* COMMIT_H */