diff -Nru git-1.7.4.1/abspath.c git-1.7.1/abspath.c --- git-1.7.4.1/abspath.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/abspath.c 2010-04-24 02:38:35.000000000 +0000 @@ -108,14 +108,10 @@ if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) die("Too long path: %.*s", 60, path); } else { - size_t len; - const char *fmt; const char *cwd = get_pwd_cwd(); if (!cwd) die_errno("Cannot determine the current working directory"); - len = strlen(cwd); - fmt = (len > 0 && is_dir_sep(cwd[len-1])) ? "%s%s" : "%s/%s"; - if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX) + if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX) die("Too long path: %.*s", 60, path); } return buf; diff -Nru git-1.7.4.1/aclocal.m4 git-1.7.1/aclocal.m4 --- git-1.7.4.1/aclocal.m4 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/aclocal.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -dnl Check for socklen_t: historically on BSD it is an int, and in -dnl POSIX 1g it is a type of its own, but some platforms use different -dnl types for the argument to getsockopt, getpeername, etc. So we -dnl have to test to find something that will work. -AC_DEFUN([TYPE_SOCKLEN_T], -[ - AC_CHECK_TYPE([socklen_t], ,[ - AC_MSG_CHECKING([for socklen_t equivalent]) - AC_CACHE_VAL([git_cv_socklen_t_equiv], - [ - # Systems have either "struct sockaddr *" or - # "void *" as the second argument to getpeername - git_cv_socklen_t_equiv= - for arg2 in "struct sockaddr" void; do - for t in int size_t unsigned long "unsigned long"; do - AC_TRY_COMPILE([ - #include - #include - - int getpeername (int, $arg2 *, $t *); - ],[ - $t len; - getpeername(0,0,&len); - ],[ - git_cv_socklen_t_equiv="$t" - break 2 - ]) - done - done - - if test "x$git_cv_socklen_t_equiv" = x; then - AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) - fi - ]) - AC_MSG_RESULT($git_cv_socklen_t_equiv) - AC_DEFINE_UNQUOTED(socklen_t, $git_cv_socklen_t_equiv, - [type to use in place of socklen_t if not defined])], - [#include -#include ]) -]) diff -Nru git-1.7.4.1/alias.c git-1.7.1/alias.c --- git-1.7.4.1/alias.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/alias.c 2010-04-24 02:38:35.000000000 +0000 @@ -22,13 +22,6 @@ return alias_val; } -#define SPLIT_CMDLINE_BAD_ENDING 1 -#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2 -static const char *split_cmdline_errors[] = { - "cmdline ends with \\", - "unclosed quote" -}; - int split_cmdline(char *cmdline, const char ***argv) { int src, dst, count = 0, size = 16; @@ -60,7 +53,7 @@ if (!c) { free(*argv); *argv = NULL; - return -SPLIT_CMDLINE_BAD_ENDING; + return error("cmdline ends with \\"); } } cmdline[dst++] = c; @@ -73,7 +66,7 @@ if (quoted) { free(*argv); *argv = NULL; - return -SPLIT_CMDLINE_UNCLOSED_QUOTE; + return error("unclosed quote"); } ALLOC_GROW(*argv, count+1, size); @@ -82,6 +75,3 @@ return count; } -const char *split_cmdline_strerror(int split_cmdline_errno) { - return split_cmdline_errors[-split_cmdline_errno-1]; -} diff -Nru git-1.7.4.1/archive.c git-1.7.1/archive.c --- git-1.7.4.1/archive.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/archive.c 2010-04-24 02:38:35.000000000 +0000 @@ -7,9 +7,9 @@ #include "unpack-trees.h" static char const * const archive_usage[] = { - "git archive [options] [...]", + "git archive [options] [path...]", "git archive --list", - "git archive --remote [--exec ] [options] [...]", + "git archive --remote [--exec ] [options] [path...]", "git archive --remote [--exec ] --list", NULL }; @@ -33,7 +33,6 @@ struct strbuf fmt = STRBUF_INIT; struct pretty_print_context ctx = {0}; ctx.date_mode = DATE_NORMAL; - ctx.abbrev = DEFAULT_ABBREV; if (src == buf->buf) to_free = strbuf_detach(buf, NULL); @@ -314,7 +313,7 @@ "write the archive to this file"), OPT_BOOLEAN(0, "worktree-attributes", &worktree_attributes, "read .gitattributes in working directory"), - OPT__VERBOSE(&verbose, "report archived files on stderr"), + OPT__VERBOSE(&verbose), OPT__COMPR('0', &compression_level, "store only", 0), OPT__COMPR('1', &compression_level, "compress faster", 1), OPT__COMPR_HIDDEN('2', &compression_level, 2), diff -Nru git-1.7.4.1/attr.c git-1.7.1/attr.c --- git-1.7.4.1/attr.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/attr.c 2010-04-24 02:38:35.000000000 +0000 @@ -1,6 +1,5 @@ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" -#include "exec_cmd.h" #include "attr.h" const char git_attr__true[] = "(builtin)true"; @@ -11,8 +10,6 @@ #define ATTR__UNSET NULL #define ATTR__UNKNOWN git_attr__unknown -static const char *attributes_file; - /* * The basic design decision here is that we are not going to have * insanely large number of attributes. @@ -290,7 +287,7 @@ } static const char *builtin_attr[] = { - "[attr]binary -diff -text", + "[attr]binary -diff -crlf", NULL, }; @@ -465,32 +462,6 @@ } } -const char *git_etc_gitattributes(void) -{ - static const char *system_wide; - if (!system_wide) - system_wide = system_path(ETC_GITATTRIBUTES); - return system_wide; -} - -int git_attr_system(void) -{ - return !git_env_bool("GIT_ATTR_NOSYSTEM", 0); -} - -int git_attr_global(void) -{ - return !git_env_bool("GIT_ATTR_NOGLOBAL", 0); -} - -static int git_attr_config(const char *var, const char *value, void *dummy) -{ - if (!strcmp(var, "core.attributesfile")) - return git_config_pathname(&attributes_file, var, value); - - return 0; -} - static void bootstrap_attr_stack(void) { if (!attr_stack) { @@ -501,25 +472,6 @@ elem->prev = attr_stack; attr_stack = elem; - if (git_attr_system()) { - elem = read_attr_from_file(git_etc_gitattributes(), 1); - if (elem) { - elem->origin = NULL; - elem->prev = attr_stack; - attr_stack = elem; - } - } - - git_config(git_attr_config, NULL); - if (git_attr_global() && attributes_file) { - elem = read_attr_from_file(attributes_file, 1); - if (elem) { - elem->origin = NULL; - elem->prev = attr_stack; - attr_stack = elem; - } - } - if (!is_bare_repository() || direction == GIT_ATTR_INDEX) { elem = read_attr(GITATTRIBUTES_FILE, 1); elem->origin = strdup(""); @@ -547,9 +499,7 @@ /* * At the bottom of the attribute stack is the built-in - * set of attribute definitions, followed by the contents - * of $(prefix)/etc/gitattributes and a file specified by - * core.attributesfile. Then, contents from + * set of attribute definitions. Then, contents from * .gitattribute files from directories closer to the * root to the ones in deeper directories are pushed * to the stack. Finally, at the very top of the stack @@ -644,25 +594,20 @@ return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0; } -static int macroexpand_one(int attr_nr, int rem); - static int fill_one(const char *what, struct match_attr *a, int rem) { struct git_attr_check *check = check_all_attr; int i; - for (i = a->num_attr - 1; 0 < rem && 0 <= i; i--) { + for (i = 0; 0 < rem && i < a->num_attr; i++) { struct git_attr *attr = a->state[i].attr; const char **n = &(check[attr->attr_nr].value); const char *v = a->state[i].setto; if (*n == ATTR__UNKNOWN) { - debug_set(what, - a->is_macro ? a->u.attr->name : a->u.pattern, - attr, v); + debug_set(what, a->u.pattern, attr, v); *n = v; rem--; - rem = macroexpand_one(attr->attr_nr, rem); } } return rem; @@ -684,27 +629,19 @@ return rem; } -static int macroexpand_one(int attr_nr, int rem) +static int macroexpand(struct attr_stack *stk, int rem) { - struct attr_stack *stk; - struct match_attr *a = NULL; int i; + struct git_attr_check *check = check_all_attr; - if (check_all_attr[attr_nr].value != ATTR__TRUE) - return rem; - - for (stk = attr_stack; !a && stk; stk = stk->prev) - for (i = stk->num_matches - 1; !a && 0 <= i; i--) { - struct match_attr *ma = stk->attrs[i]; - if (!ma->is_macro) - continue; - if (ma->u.attr->attr_nr == attr_nr) - a = ma; - } - - if (a) + for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) { + struct match_attr *a = stk->attrs[i]; + if (!a->is_macro) + continue; + if (check[a->u.attr->attr_nr].value != ATTR__TRUE) + continue; rem = fill_one("expand", a, rem); - + } return rem; } @@ -729,6 +666,9 @@ for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) rem = fill(path, pathlen, stk, rem); + for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) + rem = macroexpand(stk, rem); + for (i = 0; i < num; i++) { const char *value = check_all_attr[check[i].attr->attr_nr].value; if (value == ATTR__UNKNOWN) diff -Nru git-1.7.4.1/attr.h git-1.7.1/attr.h --- git-1.7.4.1/attr.h 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/attr.h 2010-04-24 02:38:35.000000000 +0000 @@ -34,7 +34,7 @@ enum git_attr_direction { GIT_ATTR_CHECKIN, GIT_ATTR_CHECKOUT, - GIT_ATTR_INDEX + GIT_ATTR_INDEX, }; void git_attr_set_direction(enum git_attr_direction, struct index_state *); diff -Nru git-1.7.4.1/base85.c git-1.7.1/base85.c --- git-1.7.4.1/base85.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/base85.c 2010-04-24 02:38:35.000000000 +0000 @@ -7,9 +7,9 @@ #define say1(a,b) fprintf(stderr, a, b) #define say2(a,b,c) fprintf(stderr, a, b, c) #else -#define say(a) do { /* nothing */ } while (0) -#define say1(a,b) do { /* nothing */ } while (0) -#define say2(a,b,c) do { /* nothing */ } while (0) +#define say(a) do {} while(0) +#define say1(a,b) do {} while(0) +#define say2(a,b,c) do {} while(0) #endif static const char en85[] = { diff -Nru git-1.7.4.1/bisect.c git-1.7.1/bisect.c --- git-1.7.4.1/bisect.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/bisect.c 2010-04-24 02:38:35.000000000 +0000 @@ -141,8 +141,7 @@ enum object_type type; unsigned long size; char *buf = read_sha1_file(commit->object.sha1, &type, &size); - const char *subject_start; - int subject_len; + char *ep, *sp; fprintf(stderr, "%c%c%c ", (flags & TREESAME) ? ' ' : 'T', @@ -157,9 +156,13 @@ fprintf(stderr, " %.*s", 8, sha1_to_hex(pp->item->object.sha1)); - subject_len = find_commit_subject(buf, &subject_start); - if (subject_len) - fprintf(stderr, " %.*s", subject_len, subject_start); + sp = strstr(buf, "\n\n"); + if (sp) { + sp += 2; + for (ep = sp; *ep && *ep != '\n'; ep++) + ; + fprintf(stderr, " %.*s", (int)(ep - sp), sp); + } fprintf(stderr, "\n"); } } diff -Nru git-1.7.4.1/block-sha1/sha1.c git-1.7.1/block-sha1/sha1.c --- git-1.7.4.1/block-sha1/sha1.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/block-sha1/sha1.c 2010-04-24 02:38:35.000000000 +0000 @@ -70,7 +70,6 @@ */ #if defined(__i386__) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(_M_X64) || \ defined(__ppc__) || defined(__ppc64__) || \ defined(__powerpc__) || defined(__powerpc64__) || \ defined(__s390__) || defined(__s390x__) @@ -237,13 +236,13 @@ void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len) { - unsigned int lenW = ctx->size & 63; + int lenW = ctx->size & 63; ctx->size += len; /* Read the data into W and process blocks as they get full */ if (lenW) { - unsigned int left = 64 - lenW; + int left = 64 - lenW; if (len < left) left = len; memcpy(lenW + (char *)ctx->W, data, left); @@ -270,8 +269,8 @@ int i; /* Pad with a binary 1 (ie 0x80), then zeroes, then length */ - padlen[0] = htonl((uint32_t)(ctx->size >> 29)); - padlen[1] = htonl((uint32_t)(ctx->size << 3)); + padlen[0] = htonl(ctx->size >> 29); + padlen[1] = htonl(ctx->size << 3); i = ctx->size & 63; blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i))); diff -Nru git-1.7.4.1/branch.c git-1.7.1/branch.c --- git-1.7.4.1/branch.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/branch.c 2010-04-24 02:38:35.000000000 +0000 @@ -159,7 +159,7 @@ dont_change_ref = 1; else if (!force) die("A branch named '%s' already exists.", name); - else if (!is_bare_repository() && head && !strcmp(head, name)) + else if (!is_bare_repository() && !strcmp(head, name)) die("Cannot force update the current branch."); forcing = 1; } diff -Nru git-1.7.4.1/branch.h git-1.7.1/branch.h --- git-1.7.4.1/branch.h 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/branch.h 2010-04-24 02:38:35.000000000 +0000 @@ -22,8 +22,8 @@ void remove_branch_state(void); /* - * Configure local branch "local" as downstream to branch "remote" - * from remote "origin". Used by git branch --set-upstream. + * Configure local branch "local" to merge remote branch "remote" + * taken from origin "origin". */ #define BRANCH_CONFIG_VERBOSE 01 extern void install_branch_config(int flag, const char *local, const char *origin, const char *remote); diff -Nru git-1.7.4.1/builtin/add.c git-1.7.1/builtin/add.c --- git-1.7.4.1/builtin/add.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/add.c 2010-04-24 02:38:35.000000000 +0000 @@ -261,14 +261,12 @@ { char *file = xstrdup(git_path("ADD_EDIT.patch")); const char *apply_argv[] = { "apply", "--recount", "--cached", - NULL, NULL }; + file, NULL }; struct child_process child; struct rev_info rev; int out; struct stat st; - apply_argv[3] = file; - git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ if (read_cache() < 0) @@ -310,29 +308,27 @@ "The following paths are ignored by one of your .gitignore files:\n"; static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0; -static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0; +static int ignore_add_errors, addremove, intent_to_add; static struct option builtin_add_options[] = { - OPT__DRY_RUN(&show_only, "dry run"), - OPT__VERBOSE(&verbose, "be verbose"), + OPT__DRY_RUN(&show_only), + OPT__VERBOSE(&verbose), OPT_GROUP(""), OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"), OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"), OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"), - OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"), + OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"), OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"), OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"), OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"), OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"), - OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"), OPT_END(), }; static int add_config(const char *var, const char *value, void *cb) { - if (!strcasecmp(var, "add.ignoreerrors") || - !strcasecmp(var, "add.ignore-errors")) { + if (!strcasecmp(var, "add.ignore-errors")) { ignore_add_errors = git_config_bool(var, value); return 0; } @@ -387,8 +383,6 @@ if (addremove && take_worktree_changes) die("-A and -u are mutually incompatible"); - if (!show_only && ignore_missing) - die("Option --ignore-missing can only be used together with --dry-run"); if ((addremove || take_worktree_changes) && !argc) { static const char *here[2] = { ".", NULL }; argc = 1; @@ -445,15 +439,9 @@ seen = find_used_pathspec(pathspec); for (i = 0; pathspec[i]; i++) { if (!seen[i] && pathspec[i][0] - && !file_exists(pathspec[i])) { - if (ignore_missing) { - int dtype = DT_UNKNOWN; - if (excluded(&dir, pathspec[i], &dtype)) - dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i])); - } else - die("pathspec '%s' did not match any files", - pathspec[i]); - } + && !file_exists(pathspec[i])) + die("pathspec '%s' did not match any files", + pathspec[i]); } free(seen); } diff -Nru git-1.7.4.1/builtin/apply.c git-1.7.1/builtin/apply.c --- git-1.7.4.1/builtin/apply.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/apply.c 2010-04-24 02:38:35.000000000 +0000 @@ -56,7 +56,7 @@ nowarn_ws_error, warn_on_ws_error, die_on_ws_error, - correct_ws_error + correct_ws_error, } ws_error_action = warn_on_ws_error; static int whitespace_error; static int squelch_whitespace_errors = 5; @@ -64,7 +64,7 @@ static enum ws_ignore { ignore_ws_none, - ignore_ws_change + ignore_ws_change, } ws_ignore_action = ignore_ws_none; @@ -416,210 +416,48 @@ return name; } -static char *find_name_gnu(const char *line, char *def, int p_value) -{ - struct strbuf name = STRBUF_INIT; - char *cp; - - /* - * Proposed "new-style" GNU patch/diff format; see - * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2 - */ - if (unquote_c_style(&name, line, NULL)) { - strbuf_release(&name); - return NULL; - } - - for (cp = name.buf; p_value; p_value--) { - cp = strchr(cp, '/'); - if (!cp) { - strbuf_release(&name); - return NULL; - } - cp++; - } - - /* name can later be freed, so we need - * to memmove, not just return cp - */ - strbuf_remove(&name, 0, cp - name.buf); - free(def); - if (root) - strbuf_insert(&name, 0, root, root_len); - return squash_slash(strbuf_detach(&name, NULL)); -} - -static size_t sane_tz_len(const char *line, size_t len) -{ - const char *tz, *p; - - if (len < strlen(" +0500") || line[len-strlen(" +0500")] != ' ') - return 0; - tz = line + len - strlen(" +0500"); - - if (tz[1] != '+' && tz[1] != '-') - return 0; - - for (p = tz + 2; p != line + len; p++) - if (!isdigit(*p)) - return 0; - - return line + len - tz; -} - -static size_t tz_with_colon_len(const char *line, size_t len) -{ - const char *tz, *p; - - if (len < strlen(" +08:00") || line[len - strlen(":00")] != ':') - return 0; - tz = line + len - strlen(" +08:00"); - - if (tz[0] != ' ' || (tz[1] != '+' && tz[1] != '-')) - return 0; - p = tz + 2; - if (!isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++)) - return 0; - - return line + len - tz; -} - -static size_t date_len(const char *line, size_t len) -{ - const char *date, *p; - - if (len < strlen("72-02-05") || line[len-strlen("-05")] != '-') - return 0; - p = date = line + len - strlen("72-02-05"); - - if (!isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || - !isdigit(*p++) || !isdigit(*p++)) /* Not a date. */ - return 0; - - if (date - line >= strlen("19") && - isdigit(date[-1]) && isdigit(date[-2])) /* 4-digit year */ - date -= strlen("19"); - - return line + len - date; -} - -static size_t short_time_len(const char *line, size_t len) -{ - const char *time, *p; - - if (len < strlen(" 07:01:32") || line[len-strlen(":32")] != ':') - return 0; - p = time = line + len - strlen(" 07:01:32"); - - /* Permit 1-digit hours? */ - if (*p++ != ' ' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++)) /* Not a time. */ - return 0; - - return line + len - time; -} - -static size_t fractional_time_len(const char *line, size_t len) -{ - const char *p; - size_t n; - - /* Expected format: 19:41:17.620000023 */ - if (!len || !isdigit(line[len - 1])) - return 0; - p = line + len - 1; - - /* Fractional seconds. */ - while (p > line && isdigit(*p)) - p--; - if (*p != '.') - return 0; - - /* Hours, minutes, and whole seconds. */ - n = short_time_len(line, p - line); - if (!n) - return 0; - - return line + len - p + n; -} - -static size_t trailing_spaces_len(const char *line, size_t len) -{ - const char *p; - - /* Expected format: ' ' x (1 or more) */ - if (!len || line[len - 1] != ' ') - return 0; - - p = line + len; - while (p != line) { - p--; - if (*p != ' ') - return line + len - (p + 1); - } - - /* All spaces! */ - return len; -} - -static size_t diff_timestamp_len(const char *line, size_t len) +static char *find_name(const char *line, char *def, int p_value, int terminate) { - const char *end = line + len; - size_t n; - - /* - * Posix: 2010-07-05 19:41:17 - * GNU: 2010-07-05 19:41:17.620000023 -0500 - */ + int len; + const char *start = NULL; - if (!isdigit(end[-1])) - return 0; + if (p_value == 0) + start = line; - n = sane_tz_len(line, end - line); - if (!n) - n = tz_with_colon_len(line, end - line); - end -= n; - - n = short_time_len(line, end - line); - if (!n) - n = fractional_time_len(line, end - line); - end -= n; + if (*line == '"') { + struct strbuf name = STRBUF_INIT; - n = date_len(line, end - line); - if (!n) /* No date. Too bad. */ - return 0; - end -= n; + /* + * Proposed "new-style" GNU patch/diff format; see + * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2 + */ + if (!unquote_c_style(&name, line, NULL)) { + char *cp; - if (end == line) /* No space before date. */ - return 0; - if (end[-1] == '\t') { /* Success! */ - end--; - return line + len - end; + for (cp = name.buf; p_value; p_value--) { + cp = strchr(cp, '/'); + if (!cp) + break; + cp++; + } + if (cp) { + /* name can later be freed, so we need + * to memmove, not just return cp + */ + strbuf_remove(&name, 0, cp - name.buf); + free(def); + if (root) + strbuf_insert(&name, 0, root, root_len); + return squash_slash(strbuf_detach(&name, NULL)); + } + } + strbuf_release(&name); } - if (end[-1] != ' ') /* No space before date. */ - return 0; - - /* Whitespace damage. */ - end -= trailing_spaces_len(line, end - line); - return line + len - end; -} -static char *find_name_common(const char *line, char *def, int p_value, - const char *end, int terminate) -{ - int len; - const char *start = NULL; - - if (p_value == 0) - start = line; - while (line != end) { + for (;;) { char c = *line; - if (!end && isspace(c)) { + if (isspace(c)) { if (c == '\n') break; if (name_terminate(start, line-start, c, terminate)) @@ -659,37 +497,6 @@ return squash_slash(xmemdupz(start, len)); } -static char *find_name(const char *line, char *def, int p_value, int terminate) -{ - if (*line == '"') { - char *name = find_name_gnu(line, def, p_value); - if (name) - return name; - } - - return find_name_common(line, def, p_value, NULL, terminate); -} - -static char *find_name_traditional(const char *line, char *def, int p_value) -{ - size_t len = strlen(line); - size_t date_len; - - if (*line == '"') { - char *name = find_name_gnu(line, def, p_value); - if (name) - return name; - } - - len = strchrnul(line, '\n') - line; - date_len = diff_timestamp_len(line, len); - if (!date_len) - return find_name_common(line, def, p_value, NULL, TERM_TAB); - len -= date_len; - - return find_name_common(line, def, p_value, line + len, 0); -} - static int count_slashes(const char *cp) { int cnt = 0; @@ -712,7 +519,7 @@ if (is_dev_null(nameline)) return -1; - name = find_name_traditional(nameline, NULL, 0); + name = find_name(nameline, NULL, 0, TERM_SPACE | TERM_TAB); if (!name) return -1; cp = strchr(name, '/'); @@ -753,8 +560,8 @@ " " "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?" " " - "([-+][0-2][0-9]:?[0-5][0-9])\n"; - const char *timestamp = NULL, *cp, *colon; + "([-+][0-2][0-9][0-5][0-9])\n"; + const char *timestamp = NULL, *cp; static regex_t *stamp; regmatch_t m[10]; int zoneoffset; @@ -784,11 +591,8 @@ return 0; } - zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10); - if (*colon == ':') - zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10); - else - zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100); + zoneoffset = strtol(timestamp + m[3].rm_so + 1, NULL, 10); + zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100); if (timestamp[m[3].rm_so] == '-') zoneoffset = -zoneoffset; @@ -834,16 +638,16 @@ if (is_dev_null(first)) { patch->is_new = 1; patch->is_delete = 0; - name = find_name_traditional(second, NULL, p_value); + name = find_name(second, NULL, p_value, TERM_SPACE | TERM_TAB); patch->new_name = name; } else if (is_dev_null(second)) { patch->is_new = 0; patch->is_delete = 1; - name = find_name_traditional(first, NULL, p_value); + name = find_name(first, NULL, p_value, TERM_SPACE | TERM_TAB); patch->old_name = name; } else { - name = find_name_traditional(first, NULL, p_value); - name = find_name_traditional(second, name, p_value); + name = find_name(first, NULL, p_value, TERM_SPACE | TERM_TAB); + name = find_name(second, name, p_value, TERM_SPACE | TERM_TAB); if (has_epoch_timestamp(first)) { patch->is_new = 1; patch->is_delete = 0; @@ -942,28 +746,28 @@ static int gitdiff_copysrc(const char *line, struct patch *patch) { patch->is_copy = 1; - patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_copydst(const char *line, struct patch *patch) { patch->is_copy = 1; - patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_renamesrc(const char *line, struct patch *patch) { patch->is_rename = 1; - patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_renamedst(const char *line, struct patch *patch) { patch->is_rename = 1; - patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, 0, 0); return 0; } @@ -1048,7 +852,7 @@ { const char *name; const char *second = NULL; - size_t len, line_len; + size_t len; line += strlen("diff --git "); llen -= strlen("diff --git "); @@ -1148,10 +952,6 @@ * Accept a name only if it shows up twice, exactly the same * form. */ - second = strchr(name, '\n'); - if (!second) - return NULL; - line_len = second - name; for (len = 0 ; ; len++) { switch (name[len]) { default: @@ -1159,11 +959,15 @@ case '\n': return NULL; case '\t': case ' ': - second = stop_at_slash(name + len, line_len - len); - if (!second) - return NULL; - second++; - if (second[len] == '\n' && !strncmp(name, second, len)) { + second = name+len; + for (;;) { + char c = *second++; + if (c == '\n') + return NULL; + if (c == '/') + break; + } + if (second[len] == '\n' && !memcmp(name, second, len)) { return xmemdupz(name, len); } } @@ -2050,8 +1854,6 @@ { int i; char *fixed_buf, *buf, *orig, *target; - struct strbuf fixed; - size_t fixed_len; int preimage_limit; if (preimage->nr + try_lno <= img->nr) { @@ -2062,13 +1864,13 @@ if (match_end && (preimage->nr + try_lno != img->nr)) return 0; } else if (ws_error_action == correct_ws_error && - (ws_rule & WS_BLANK_AT_EOF)) { + (ws_rule & WS_BLANK_AT_EOF) && match_end) { /* - * This hunk extends beyond the end of img, and we are - * removing blank lines at the end of the file. This - * many lines from the beginning of the preimage must - * match with img, and the remainder of the preimage - * must be blank. + * This hunk that matches at the end extends beyond + * the end of img, and we are removing blank lines + * at the end of the file. This many lines from the + * beginning of the preimage must match with img, and + * the remainder of the preimage must be blank. */ preimage_limit = img->nr - try_lno; } else { @@ -2175,12 +1977,12 @@ * use the whitespace from the preimage. */ extra_chars = preimage_end - preimage_eof; - strbuf_init(&fixed, imgoff + extra_chars); - strbuf_add(&fixed, img->buf + try, imgoff); - strbuf_add(&fixed, preimage_eof, extra_chars); - fixed_buf = strbuf_detach(&fixed, &fixed_len); + fixed_buf = xmalloc(imgoff + extra_chars); + memcpy(fixed_buf, img->buf + try, imgoff); + memcpy(fixed_buf + imgoff, preimage_eof, extra_chars); + imgoff += extra_chars; update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, postlen); + fixed_buf, imgoff, postlen); return 1; } @@ -2197,22 +1999,27 @@ * but in this loop we will only handle the part of the * preimage that falls within the file. */ - strbuf_init(&fixed, preimage->len + 1); + fixed_buf = xmalloc(preimage->len + 1); + buf = fixed_buf; orig = preimage->buf; target = img->buf + try; for (i = 0; i < preimage_limit; i++) { + size_t fixlen; /* length after fixing the preimage */ size_t oldlen = preimage->line[i].len; size_t tgtlen = img->line[try_lno + i].len; - size_t fixstart = fixed.len; - struct strbuf tgtfix; + size_t tgtfixlen; /* length after fixing the target line */ + char tgtfixbuf[1024], *tgtfix; int match; /* Try fixing the line in the preimage */ - ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); + fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL); /* Try fixing the line in the target */ - strbuf_init(&tgtfix, tgtlen); - ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL); + if (sizeof(tgtfixbuf) > tgtlen) + tgtfix = tgtfixbuf; + else + tgtfix = xmalloc(tgtlen); + tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL); /* * If they match, either the preimage was based on @@ -2224,15 +2031,15 @@ * so we might as well take the fix together with their * real change. */ - match = (tgtfix.len == fixed.len - fixstart && - !memcmp(tgtfix.buf, fixed.buf + fixstart, - fixed.len - fixstart)); + match = (tgtfixlen == fixlen && !memcmp(tgtfix, buf, fixlen)); - strbuf_release(&tgtfix); + if (tgtfix != tgtfixbuf) + free(tgtfix); if (!match) goto unmatch_exit; orig += oldlen; + buf += fixlen; target += tgtlen; } @@ -2244,18 +2051,19 @@ * false). */ for ( ; i < preimage->nr; i++) { - size_t fixstart = fixed.len; /* start of the fixed preimage */ + size_t fixlen; /* length after fixing the preimage */ size_t oldlen = preimage->line[i].len; int j; /* Try fixing the line in the preimage */ - ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); + fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL); - for (j = fixstart; j < fixed.len; j++) - if (!isspace(fixed.buf[j])) + for (j = 0; j < fixlen; j++) + if (!isspace(buf[j])) goto unmatch_exit; orig += oldlen; + buf += fixlen; } /* @@ -2263,13 +2071,12 @@ * has whitespace breakages unfixed, and fixing them makes the * hunk match. Update the context lines in the postimage. */ - fixed_buf = strbuf_detach(&fixed, &fixed_len); update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, 0); + fixed_buf, buf - fixed_buf, 0); return 1; unmatch_exit: - strbuf_release(&fixed); + free(fixed_buf); return 0; } @@ -2437,8 +2244,7 @@ int match_beginning, match_end; const char *patch = frag->patch; int size = frag->size; - char *old, *oldlines; - struct strbuf newlines; + char *old, *new, *oldlines, *newlines; int new_blank_lines_at_end = 0; unsigned long leading, trailing; int pos, applied_pos; @@ -2448,16 +2254,16 @@ memset(&preimage, 0, sizeof(preimage)); memset(&postimage, 0, sizeof(postimage)); oldlines = xmalloc(size); - strbuf_init(&newlines, size); + newlines = xmalloc(size); old = oldlines; + new = newlines; while (size > 0) { char first; int len = linelen(patch, size); - int plen; + int plen, added; int added_blank_line = 0; int is_blank_context = 0; - size_t start; if (!len) break; @@ -2487,7 +2293,7 @@ /* ... followed by '\No newline'; nothing */ break; *old++ = '\n'; - strbuf_addch(&newlines, '\n'); + *new++ = '\n'; add_line_info(&preimage, "\n", 1, LINE_COMMON); add_line_info(&postimage, "\n", 1, LINE_COMMON); is_blank_context = 1; @@ -2509,17 +2315,18 @@ if (first == '+' && no_add) break; - start = newlines.len; if (first != '+' || !whitespace_error || ws_error_action != correct_ws_error) { - strbuf_add(&newlines, patch + 1, plen); + memcpy(new, patch + 1, plen); + added = plen; } else { - ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &applied_after_fixing_ws); + added = ws_fix_copy(new, patch + 1, plen, ws_rule, &applied_after_fixing_ws); } - add_line_info(&postimage, newlines.buf + start, newlines.len - start, + add_line_info(&postimage, new, added, (first == '+' ? 0 : LINE_COMMON)); + new += added; if (first == '+' && (ws_rule & WS_BLANK_AT_EOF) && ws_blank_line(patch + 1, plen, ws_rule)) @@ -2544,9 +2351,9 @@ } if (inaccurate_eof && old > oldlines && old[-1] == '\n' && - newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') { + new > newlines && new[-1] == '\n') { old--; - strbuf_setlen(&newlines, newlines.len - 1); + new--; } leading = frag->leading; @@ -2578,8 +2385,8 @@ pos = frag->newpos ? (frag->newpos - 1) : 0; preimage.buf = oldlines; preimage.len = old - oldlines; - postimage.buf = newlines.buf; - postimage.len = newlines.len; + postimage.buf = newlines; + postimage.len = new - newlines; preimage.line = preimage.line_allocated; postimage.line = postimage.line_allocated; @@ -2655,7 +2462,7 @@ } free(oldlines); - strbuf_release(&newlines); + free(newlines); free(preimage.line_allocated); free(postimage.line_allocated); @@ -2668,12 +2475,6 @@ unsigned long len; void *dst; - if (!fragment) - return error("missing binary patch data for '%s'", - patch->new_name ? - patch->new_name : - patch->old_name); - /* Binary patch is irreversible without the optional second hunk */ if (apply_in_reverse) { if (!fragment->next) @@ -2830,7 +2631,7 @@ if (name == NULL) return NULL; - item = string_list_lookup(&fn_table, name); + item = string_list_lookup(name, &fn_table); if (item != NULL) return (struct patch *)item->util; @@ -2866,7 +2667,7 @@ * file creations and copies */ if (patch->new_name != NULL) { - item = string_list_insert(&fn_table, patch->new_name); + item = string_list_insert(patch->new_name, &fn_table); item->util = patch; } @@ -2875,7 +2676,7 @@ * later chunks shouldn't patch old names */ if ((patch->new_name == NULL) || (patch->is_rename)) { - item = string_list_insert(&fn_table, patch->old_name); + item = string_list_insert(patch->old_name, &fn_table); item->util = PATH_WAS_DELETED; } } @@ -2888,7 +2689,7 @@ while (patch) { if ((patch->new_name == NULL) || (patch->is_rename)) { struct string_list_item *item; - item = string_list_insert(&fn_table, patch->old_name); + item = string_list_insert(patch->old_name, &fn_table); item->util = PATH_TO_BE_DELETED; } patch = patch->next; @@ -3181,7 +2982,8 @@ else if (get_sha1(patch->old_sha1_prefix, sha1)) /* git diff has no index line for mode/type changes */ if (!patch->lines_added && !patch->lines_deleted) { - if (get_current_sha1(patch->old_name, sha1)) + if (get_current_sha1(patch->new_name, sha1) || + get_current_sha1(patch->old_name, sha1)) die("mode change for %s, which is not " "in current HEAD", name); sha1_ptr = sha1; @@ -3339,7 +3141,11 @@ die("unable to remove %s from index", patch->old_name); } if (!cached) { - if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) { + if (S_ISGITLINK(patch->old_mode)) { + if (rmdir(patch->old_name)) + warning("unable to remove submodule %s", + patch->old_name); + } else if (!unlink_or_warn(patch->old_name) && rmdir_empty) { remove_path(patch->old_name); } } @@ -3595,7 +3401,7 @@ { struct string_list_item *it; - it = string_list_append(&limit_by_name, name); + it = string_list_append(name, &limit_by_name); it->util = exclude ? NULL : (void *) 1; } @@ -3808,11 +3614,11 @@ return 0; } -int cmd_apply(int argc, const char **argv, const char *prefix_) +int cmd_apply(int argc, const char **argv, const char *unused_prefix) { int i; int errs = 0; - int is_not_gitdir = !startup_info->have_repository; + int is_not_gitdir; int binary; int force_apply = 0; @@ -3872,7 +3678,7 @@ "don't expect at least one line of context"), OPT_BOOLEAN(0, "reject", &apply_with_reject, "leave the rejected hunks in corresponding *.rej files"), - OPT__VERBOSE(&apply_verbosely, "be verbose"), + OPT__VERBOSE(&apply_verbosely), OPT_BIT(0, "inaccurate-eof", &options, "tolerate incorrectly detected missing new-line at the end of file", INACCURATE_EOF), @@ -3885,7 +3691,7 @@ OPT_END() }; - prefix = prefix_; + prefix = setup_git_directory_gently(&is_not_gitdir); prefix_length = prefix ? strlen(prefix) : 0; git_config(git_apply_config, NULL); if (apply_default_whitespace) diff -Nru git-1.7.4.1/builtin/blame.c git-1.7.1/builtin/blame.c --- git-1.7.4.1/builtin/blame.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/blame.c 2010-04-24 02:38:35.000000000 +0000 @@ -20,7 +20,6 @@ #include "mailmap.h" #include "parse-options.h" #include "utf8.h" -#include "userdiff.h" static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file"; @@ -40,7 +39,7 @@ static int reverse; static int blank_boundary; static int incremental; -static int xdl_opts; +static int xdl_opts = XDF_NEED_MINIMAL; static enum date_mode blame_date_mode = DATE_ISO8601; static size_t blame_date_width; @@ -83,56 +82,20 @@ struct commit *commit; mmfile_t file; unsigned char blob_sha1[20]; - unsigned mode; char path[FLEX_ARRAY]; }; /* - * Prepare diff_filespec and convert it using diff textconv API - * if the textconv driver exists. - * Return 1 if the conversion succeeds, 0 otherwise. - */ -int textconv_object(const char *path, - unsigned mode, - const unsigned char *sha1, - char **buf, - unsigned long *buf_size) -{ - struct diff_filespec *df; - struct userdiff_driver *textconv; - - df = alloc_filespec(path); - fill_filespec(df, sha1, mode); - textconv = get_textconv(df); - if (!textconv) { - free_filespec(df); - return 0; - } - - *buf_size = fill_textconv(textconv, df, buf); - free_filespec(df); - return 1; -} - -/* * Given an origin, prepare mmfile_t structure to be used by the * diff machinery */ -static void fill_origin_blob(struct diff_options *opt, - struct origin *o, mmfile_t *file) +static void fill_origin_blob(struct origin *o, mmfile_t *file) { if (!o->file.ptr) { enum object_type type; - unsigned long file_size; - num_read_blob++; - if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size)) - ; - else - file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size); - file->size = file_size; - + file->ptr = read_sha1_file(o->blob_sha1, &type, + (unsigned long *)(&(file->size))); if (!file->ptr) die("Cannot read blob %s for path %s", sha1_to_hex(o->blob_sha1), @@ -315,23 +278,22 @@ * for an origin is also used to pass the blame for the entire file to * the parent to detect the case where a child's blob is identical to * that of its parent's. - * - * This also fills origin->mode for corresponding tree path. */ -static int fill_blob_sha1_and_mode(struct origin *origin) +static int fill_blob_sha1(struct origin *origin) { + unsigned mode; + if (!is_null_sha1(origin->blob_sha1)) return 0; if (get_tree_entry(origin->commit->object.sha1, origin->path, - origin->blob_sha1, &origin->mode)) + origin->blob_sha1, &mode)) goto error_out; if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB) goto error_out; return 0; error_out: hashclr(origin->blob_sha1); - origin->mode = S_IFINVALID; return -1; } @@ -364,14 +326,12 @@ /* * If the origin was newly created (i.e. get_origin * would call make_origin if none is found in the - * scoreboard), it does not know the blob_sha1/mode, + * scoreboard), it does not know the blob_sha1, * so copy it. Otherwise porigin was in the - * scoreboard and already knows blob_sha1/mode. + * scoreboard and already knows blob_sha1. */ - if (porigin->refcnt == 1) { + if (porigin->refcnt == 1) hashcpy(porigin->blob_sha1, cached->blob_sha1); - porigin->mode = cached->mode; - } return porigin; } /* otherwise it was not very useful; free it */ @@ -406,7 +366,6 @@ /* The path is the same as parent */ porigin = get_origin(sb, parent, origin->path); hashcpy(porigin->blob_sha1, origin->blob_sha1); - porigin->mode = origin->mode; } else { /* * Since origin->path is a pathspec, if the parent @@ -432,7 +391,6 @@ case 'M': porigin = get_origin(sb, parent, origin->path); hashcpy(porigin->blob_sha1, p->one->sha1); - porigin->mode = p->one->mode; break; case 'A': case 'T': @@ -452,7 +410,6 @@ cached = make_origin(porigin->commit, porigin->path); hashcpy(cached->blob_sha1, porigin->blob_sha1); - cached->mode = porigin->mode; parent->util = cached; } return porigin; @@ -495,7 +452,6 @@ !strcmp(p->two->path, origin->path)) { porigin = get_origin(sb, parent, p->one->path); hashcpy(porigin->blob_sha1, p->one->sha1); - porigin->mode = p->one->mode; break; } } @@ -777,17 +733,16 @@ { int last_in_target; mmfile_t file_p, file_o; - struct blame_chunk_cb_data d; + struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 }; xpparam_t xpp; xdemitconf_t xecfg; - memset(&d, 0, sizeof(d)); - d.sb = sb; d.target = target; d.parent = parent; + last_in_target = find_last_in_target(sb, target); if (last_in_target < 0) return 1; /* nothing remains for this target */ - fill_origin_blob(&sb->revs->diffopt, parent, &file_p); - fill_origin_blob(&sb->revs->diffopt, target, &file_o); + fill_origin_blob(parent, &file_p); + fill_origin_blob(target, &file_o); num_get_patch++; memset(&xpp, 0, sizeof(xpp)); @@ -920,11 +875,10 @@ const char *cp; int cnt; mmfile_t file_o; - struct handle_split_cb_data d; + struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 }; xpparam_t xpp; xdemitconf_t xecfg; - memset(&d, 0, sizeof(d)); - d.sb = sb; d.ent = ent; d.parent = parent; d.split = split; + /* * Prepare mmfile that contains only the lines in ent. */ @@ -968,7 +922,7 @@ if (last_in_target < 0) return 1; /* nothing remains for this target */ - fill_origin_blob(&sb->revs->diffopt, parent, &file_p); + fill_origin_blob(parent, &file_p); if (!file_p.ptr) return 0; @@ -1109,8 +1063,7 @@ norigin = get_origin(sb, parent, p->one->path); hashcpy(norigin->blob_sha1, p->one->sha1); - norigin->mode = p->one->mode; - fill_origin_blob(&sb->revs->diffopt, norigin, &file_p); + fill_origin_blob(norigin, &file_p); if (!file_p.ptr) continue; @@ -1418,8 +1371,7 @@ int detailed) { int len; - const char *subject; - char *reencoded, *message; + char *tmp, *endp, *reencoded, *message; static char author_name[1024]; static char author_mail[1024]; static char committer_name[1024]; @@ -1461,13 +1413,22 @@ &ret->committer_time, &ret->committer_tz); ret->summary = summary_buf; - len = find_commit_subject(message, &subject); - if (len && len < sizeof(summary_buf)) { - memcpy(summary_buf, subject, len); - summary_buf[len] = 0; - } else { + tmp = strstr(message, "\n\n"); + if (!tmp) { + error_out: sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1)); + free(reencoded); + return; } + tmp += 2; + endp = strchr(tmp, '\n'); + if (!endp) + endp = tmp + strlen(tmp); + len = endp - tmp; + if (len >= sizeof(summary_buf) || len == 0) + goto error_out; + memcpy(summary_buf, tmp, len); + summary_buf[len] = 0; free(reencoded); } @@ -1617,7 +1578,6 @@ #define OUTPUT_SHOW_NUMBER 040 #define OUTPUT_SHOW_SCORE 0100 #define OUTPUT_NO_AUTHOR 0200 -#define OUTPUT_SHOW_EMAIL 0400 static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent) { @@ -1629,7 +1589,7 @@ strcpy(hex, sha1_to_hex(suspect->commit->object.sha1)); printf("%s%c%d %d %d\n", hex, - ent->guilty ? ' ' : '*', /* purely for debugging */ + ent->guilty ? ' ' : '*', // purely for debugging ent->s_lno + 1, ent->lno + 1, ent->num_lines); @@ -1683,17 +1643,12 @@ } printf("%.*s", length, hex); - if (opt & OUTPUT_ANNOTATE_COMPAT) { - const char *name; - if (opt & OUTPUT_SHOW_EMAIL) - name = ci.author_mail; - else - name = ci.author; - printf("\t(%10s\t%10s\t%d)", name, + if (opt & OUTPUT_ANNOTATE_COMPAT) + printf("\t(%10s\t%10s\t%d)", ci.author, format_time(ci.author_time, ci.author_tz, show_raw_time), ent->lno + 1 + cnt); - } else { + else { if (opt & OUTPUT_SHOW_SCORE) printf(" %*d %02d", max_score_digits, ent->score, @@ -1706,15 +1661,9 @@ ent->s_lno + 1 + cnt); if (!(opt & OUTPUT_NO_AUTHOR)) { - const char *name; - int pad; - if (opt & OUTPUT_SHOW_EMAIL) - name = ci.author_mail; - else - name = ci.author; - pad = longest_author - utf8_strwidth(name); + int pad = longest_author - utf8_strwidth(ci.author); printf(" (%s%*s %10s", - name, pad, "", + ci.author, pad, "", format_time(ci.author_time, ci.author_tz, show_raw_time)); @@ -1852,10 +1801,7 @@ if (!(suspect->commit->object.flags & METAINFO_SHOWN)) { suspect->commit->object.flags |= METAINFO_SHOWN; get_commit_info(suspect->commit, &ci, 1); - if (*option & OUTPUT_SHOW_EMAIL) - num = utf8_strwidth(ci.author_mail); - else - num = utf8_strwidth(ci.author); + num = utf8_strwidth(ci.author); if (longest_author < num) longest_author = num; } @@ -2037,16 +1983,6 @@ blame_date_mode = parse_date_format(value); return 0; } - - switch (userdiff_config(var, value)) { - case 0: - break; - case -1: - return -1; - default: - return 0; - } - return git_default_config(var, value, cb); } @@ -2054,9 +1990,7 @@ * Prepare a dummy commit that represents the work tree (or staged) item. * Note that annotating work tree item never works in the reverse. */ -static struct commit *fake_working_tree_commit(struct diff_options *opt, - const char *path, - const char *contents_from) +static struct commit *fake_working_tree_commit(const char *path, const char *contents_from) { struct commit *commit; struct origin *origin; @@ -2084,7 +2018,6 @@ if (!contents_from || strcmp("-", contents_from)) { struct stat st; const char *read_from; - unsigned long buf_len; if (contents_from) { if (stat(contents_from, &st) < 0) @@ -2097,13 +2030,9 @@ read_from = path; } mode = canon_mode(st.st_mode); - switch (st.st_mode & S_IFMT) { case S_IFREG: - if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(read_from, mode, null_sha1, &buf.buf, &buf_len)) - buf.len = buf_len; - else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) + if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) die_errno("cannot open or read '%s'", read_from); break; case S_IFLNK: @@ -2304,7 +2233,6 @@ OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP), OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME), OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR), - OPT_BIT('e', "show-email", &output_option, "Show author email instead of name (Default: off)", OUTPUT_SHOW_EMAIL), OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE), OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from instead of calling git-rev-list"), OPT_STRING(0, "contents", &contents_from, "file", "Use 's contents as the final image"), @@ -2320,13 +2248,12 @@ git_config(git_blame_config, NULL); init_revisions(&revs, NULL); revs.date_mode = blame_date_mode; - DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV); save_commit_buffer = 0; dashdash_pos = 0; - parse_options_start(&ctx, argc, argv, prefix, options, - PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0); + parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH | + PARSE_OPT_KEEP_ARGV0); for (;;) { switch (parse_options_step(&ctx, options, blame_opt_usage)) { case PARSE_OPT_HELP: @@ -2395,11 +2322,11 @@ * * The remaining are: * - * (1) if dashdash_pos != 0, it is either + * (1) if dashdash_pos != 0, its either * "blame [revisions] -- " or * "blame -- " * - * (2) otherwise, it is one of the two: + * (2) otherwise, its one of the two: * "blame [revisions] " * "blame " * @@ -2457,8 +2384,7 @@ * or "--contents". */ setup_work_tree(); - sb.final = fake_working_tree_commit(&sb.revs->diffopt, - path, contents_from); + sb.final = fake_working_tree_commit(path, contents_from); add_pending_object(&revs, &(sb.final->object), ":"); } else if (contents_from) @@ -2482,17 +2408,11 @@ } else { o = get_origin(&sb, sb.final, path); - if (fill_blob_sha1_and_mode(o)) + if (fill_blob_sha1(o)) die("no such path %s in %s", path, final_commit_name); - if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) && - textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf, - &sb.final_buf_size)) - ; - else - sb.final_buf = read_sha1_file(o->blob_sha1, &type, - &sb.final_buf_size); - + sb.final_buf = read_sha1_file(o->blob_sha1, &type, + &sb.final_buf_size); if (!sb.final_buf) die("Cannot read blob %s for path %s", sha1_to_hex(o->blob_sha1), diff -Nru git-1.7.4.1/builtin/branch.c git-1.7.1/builtin/branch.c --- git-1.7.4.1/builtin/branch.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/branch.c 2010-04-24 02:38:35.000000000 +0000 @@ -43,13 +43,13 @@ BRANCH_COLOR_PLAIN = 1, BRANCH_COLOR_REMOTE = 2, BRANCH_COLOR_LOCAL = 3, - BRANCH_COLOR_CURRENT = 4 + BRANCH_COLOR_CURRENT = 4, }; static enum merge_filter { NO_FILTER = 0, SHOW_NOT_MERGED, - SHOW_MERGED + SHOW_MERGED, } merge_filter; static unsigned char merge_filter_ref[20]; @@ -257,15 +257,9 @@ return xstrdup(dst); } -struct append_ref_cb { - struct ref_list *ref_list; - int ret; -}; - static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { - struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data); - struct ref_list *ref_list = cb->ref_list; + struct ref_list *ref_list = (struct ref_list*)(cb_data); struct ref_item *newitem; struct commit *commit; int kind, i; @@ -299,10 +293,8 @@ commit = NULL; if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) { commit = lookup_commit_reference_gently(sha1, 1); - if (!commit) { - cb->ret = error("branch '%s' does not point at a commit", refname); - return 0; - } + if (!commit) + return error("branch '%s' does not point at a commit", refname); /* Filter with with_commit if specified */ if (!is_descendant_of(commit, ref_list->with_commit)) @@ -313,7 +305,12 @@ (struct object *)commit, refname); } - ALLOC_GROW(ref_list->list, ref_list->index + 1, ref_list->alloc); + /* Resize buffer */ + if (ref_list->index >= ref_list->alloc) { + ref_list->alloc = alloc_nr(ref_list->alloc); + ref_list->list = xrealloc(ref_list->list, + ref_list->alloc * sizeof(struct ref_item)); + } /* Record the new item */ newitem = &(ref_list->list[ref_list->index++]); @@ -487,10 +484,9 @@ } } -static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) +static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; - struct append_ref_cb cb; struct ref_list ref_list; memset(&ref_list, 0, sizeof(ref_list)); @@ -500,9 +496,7 @@ ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); - cb.ref_list = &ref_list; - cb.ret = 0; - for_each_rawref(append_ref, &cb); + for_each_rawref(append_ref, &ref_list); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); @@ -533,11 +527,6 @@ } free_ref_list(&ref_list); - - if (cb.ret) - error("some refs could not be read"); - - return cb.ret; } static void rename_branch(const char *oldname, const char *newname, int force) @@ -616,8 +605,7 @@ struct option options[] = { OPT_GROUP("Generic options"), - OPT__VERBOSE(&verbose, - "show hash and subject, give twice for upstream branch"), + OPT__VERBOSE(&verbose), OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))", BRANCH_TRACK_EXPLICIT), OPT_SET_INT( 0, "set-upstream", &track, "change upstream info", @@ -647,7 +635,7 @@ OPT_BIT('m', NULL, &rename, "move/rename a branch and its reflog", 1), OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2), OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"), - OPT__FORCE(&force_create, "force creation (when already exists)"), + OPT_BOOLEAN('f', "force", &force_create, "force creation (when already exists)"), { OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref, "commit", "print only not merged branches", @@ -663,9 +651,6 @@ OPT_END(), }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_branch_usage, options); - git_config(git_branch_config, NULL); if (branch_use_color == -1) @@ -694,7 +679,7 @@ if (delete) return delete_branches(argc, argv, delete > 1, kinds); else if (argc == 0) - return print_ref_list(kinds, detached, verbose, abbrev, with_commit); + print_ref_list(kinds, detached, verbose, abbrev, with_commit); else if (rename && (argc == 1)) rename_branch(head, argv[0], rename > 1); else if (rename && (argc == 2)) diff -Nru git-1.7.4.1/builtin/bundle.c git-1.7.1/builtin/bundle.c --- git-1.7.4.1/builtin/bundle.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/bundle.c 2010-04-24 02:38:35.000000000 +0000 @@ -12,12 +12,13 @@ static const char builtin_bundle_usage[] = "git bundle create \n" " or: git bundle verify \n" - " or: git bundle list-heads [...]\n" - " or: git bundle unbundle [...]"; + " or: git bundle list-heads [refname...]\n" + " or: git bundle unbundle [refname...]"; int cmd_bundle(int argc, const char **argv, const char *prefix) { struct bundle_header header; + int nongit; const char *cmd, *bundle_file; int bundle_fd = -1; char buffer[PATH_MAX]; @@ -30,6 +31,7 @@ argc -= 2; argv += 2; + prefix = setup_git_directory_gently(&nongit); if (prefix && bundle_file[0] != '/') { snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file); bundle_file = buffer; @@ -52,11 +54,11 @@ return !!list_bundle_refs(&header, argc, argv); } if (!strcmp(cmd, "create")) { - if (!startup_info->have_repository) + if (nongit) die("Need a repository to create a bundle."); return !!create_bundle(&header, bundle_file, argc, argv); } else if (!strcmp(cmd, "unbundle")) { - if (!startup_info->have_repository) + if (nongit) die("Need a repository to unbundle."); return !!unbundle(&header, bundle_fd) || list_bundle_refs(&header, argc, argv); diff -Nru git-1.7.4.1/builtin/cat-file.c git-1.7.1/builtin/cat-file.c --- git-1.7.4.1/builtin/cat-file.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/cat-file.c 2010-04-24 02:38:35.000000000 +0000 @@ -9,8 +9,6 @@ #include "tree.h" #include "builtin.h" #include "parse-options.h" -#include "diff.h" -#include "userdiff.h" #define BATCH 1 #define BATCH_CHECK 2 @@ -86,11 +84,10 @@ { unsigned char sha1[20]; enum object_type type; - char *buf; + void *buf; unsigned long size; - struct object_context obj_context; - if (get_sha1_with_context(obj_name, sha1, &obj_context)) + if (get_sha1(obj_name, sha1)) die("Not a valid object name %s", obj_name); buf = NULL; @@ -121,9 +118,7 @@ /* custom pretty-print here */ if (type == OBJ_TREE) { - const char *ls_args[3] = { NULL }; - ls_args[0] = "ls-tree"; - ls_args[1] = obj_name; + const char *ls_args[3] = {"ls-tree", obj_name, NULL}; return cmd_ls_tree(2, ls_args, NULL); } @@ -137,17 +132,6 @@ /* otherwise just spit out the data */ break; - - case 'c': - if (!obj_context.path[0]) - die("git cat-file --textconv %s: must be ", - obj_name); - - if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size)) - die("git cat-file --textconv: unable to run textconv on %s", - obj_name); - break; - case 0: buf = read_object_with_reference(sha1, exp_type, &size, NULL); break; @@ -217,25 +201,11 @@ } static const char * const cat_file_usage[] = { - "git cat-file (-t|-s|-e|-p||--textconv) ", + "git cat-file (-t|-s|-e|-p|) ", "git cat-file (--batch|--batch-check) < ", NULL }; -static int git_cat_file_config(const char *var, const char *value, void *cb) -{ - switch (userdiff_config(var, value)) { - case 0: - break; - case -1: - return -1; - default: - return 0; - } - - return git_default_config(var, value, cb); -} - int cmd_cat_file(int argc, const char **argv, const char *prefix) { int opt = 0, batch = 0; @@ -248,8 +218,6 @@ OPT_SET_INT('e', NULL, &opt, "exit with zero when there's no error", 'e'), OPT_SET_INT('p', NULL, &opt, "pretty-print object's content", 'p'), - OPT_SET_INT(0, "textconv", &opt, - "for blob objects, run textconv on object's content", 'c'), OPT_SET_INT(0, "batch", &batch, "show info and content of objects fed from the standard input", BATCH), @@ -259,7 +227,7 @@ OPT_END() }; - git_config(git_cat_file_config, NULL); + git_config(git_default_config, NULL); if (argc != 3 && argc != 2) usage_with_options(cat_file_usage, options); diff -Nru git-1.7.4.1/builtin/checkout.c git-1.7.1/builtin/checkout.c --- git-1.7.4.1/builtin/checkout.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/checkout.c 2010-04-24 02:38:35.000000000 +0000 @@ -18,7 +18,6 @@ #include "xdiff-interface.h" #include "ll-merge.h" #include "resolve-undo.h" -#include "submodule.h" static const char * const checkout_usage[] = { "git checkout [options] ", @@ -33,15 +32,9 @@ int writeout_stage; int writeout_error; - /* not set by parse_options */ - int branch_exists; - const char *new_branch; - const char *new_branch_force; - const char *new_orphan_branch; int new_branch_log; enum branch_track track; - struct diff_options diff_options; }; static int post_checkout_hook(struct commit *old, struct commit *new, @@ -156,12 +149,8 @@ read_mmblob(&ours, active_cache[pos+1]->sha1); read_mmblob(&theirs, active_cache[pos+2]->sha1); - /* - * NEEDSWORK: re-create conflicts from merges with - * merge.renormalize set, too - */ status = ll_merge(&result_buf, path, &ancestor, "base", - &ours, "ours", &theirs, "theirs", NULL); + &ours, "ours", &theirs, "theirs", 0); free(ancestor.ptr); free(ours.ptr); free(theirs.ptr); @@ -284,12 +273,12 @@ return errs; } -static void show_local_changes(struct object *head, struct diff_options *opts) +static void show_local_changes(struct object *head) { struct rev_info rev; /* I think we want full paths, even if we're in a subdirectory. */ init_revisions(&rev, NULL); - rev.diffopt.flags = opts->flags; + rev.abbrev = 0; rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS; if (diff_setup_done(&rev.diffopt) < 0) die("diff_setup_done failed"); @@ -383,7 +372,7 @@ topts.src_index = &the_index; topts.dst_index = &the_index; - setup_unpack_trees_porcelain(&topts, "checkout"); + topts.msgs.not_uptodate_file = "You have local changes to '%s'; cannot switch branches."; refresh_cache(REFRESH_QUIET); @@ -443,13 +432,6 @@ */ add_files_to_cache(NULL, NULL, 0); - /* - * NEEDSWORK: carrying over local changes - * when branches have different end-of-line - * normalization (or clean+smudge rules) is - * a pain; plumb in an option to set - * o.renormalize? - */ init_merge_options(&o); o.verbosity = 0; work = write_tree_from_memory(&o); @@ -473,7 +455,7 @@ die("unable to write new index file"); if (!opts->force && !opts->quiet) - show_local_changes(&new->commit->object, &opts->diff_options); + show_local_changes(&new->commit->object); return 0; } @@ -510,27 +492,8 @@ struct strbuf msg = STRBUF_INIT; const char *old_desc; if (opts->new_branch) { - if (opts->new_orphan_branch) { - if (opts->new_branch_log && !log_all_ref_updates) { - int temp; - char log_file[PATH_MAX]; - char *ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch); - - temp = log_all_ref_updates; - log_all_ref_updates = 1; - if (log_ref_setup(ref_name, log_file, sizeof(log_file))) { - fprintf(stderr, "Can not do reflog for '%s'\n", - opts->new_orphan_branch); - log_all_ref_updates = temp; - return; - } - log_all_ref_updates = temp; - } - } - else - create_branch(old->name, opts->new_branch, new->name, - opts->new_branch_force ? 1 : 0, - opts->new_branch_log, opts->track); + create_branch(old->name, opts->new_branch, new->name, 0, + opts->new_branch_log, opts->track); new->name = opts->new_branch; setup_branch_path(new); } @@ -547,22 +510,11 @@ if (old->path && !strcmp(new->path, old->path)) fprintf(stderr, "Already on '%s'\n", new->name); - else if (opts->new_branch) - fprintf(stderr, "Switched to%s branch '%s'\n", - opts->branch_exists ? " and reset" : " a new", - new->name); else - fprintf(stderr, "Switched to branch '%s'\n", + fprintf(stderr, "Switched to%s branch '%s'\n", + opts->new_branch ? " a new" : "", new->name); } - if (old->path && old->name) { - char log_file[PATH_MAX], ref_file[PATH_MAX]; - - git_snpath(log_file, sizeof(log_file), "logs/%s", old->path); - git_snpath(ref_file, sizeof(ref_file), "%s", old->path); - if (!file_exists(ref_file) && file_exists(log_file)) - remove_path(log_file); - } } else if (strcmp(new->name, "HEAD")) { update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL, REF_NODEREF, DIE_ON_ERR); @@ -621,16 +573,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) { - if (!strcmp(var, "diff.ignoresubmodules")) { - struct checkout_opts *opts = cb; - handle_ignore_submodules_arg(&opts->diff_options, value); - return 0; - } - - if (!prefixcmp(var, "submodule.")) - return parse_submodule_config_option(var, value); - - return git_xmerge_config(var, value, NULL); + return git_xmerge_config(var, value, cb); } static int interactive_checkout(const char *revision, const char **pathspec, @@ -666,8 +609,7 @@ static const char *unique_tracking_name(const char *name) { - struct tracking_name_data cb_data = { NULL, NULL, 1 }; - cb_data.name = name; + struct tracking_name_data cb_data = { name, NULL, 1 }; for_each_ref(check_tracking_name, &cb_data); if (cb_data.unique) return cb_data.remote; @@ -686,21 +628,17 @@ int patch_mode = 0; int dwim_new_local_branch = 1; struct option options[] = { - OPT__QUIET(&opts.quiet, "suppress progress reporting"), - OPT_STRING('b', NULL, &opts.new_branch, "branch", - "create and checkout a new branch"), - OPT_STRING('B', NULL, &opts.new_branch_force, "branch", - "create/reset and checkout a branch"), - OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "create reflog for new branch"), - OPT_SET_INT('t', "track", &opts.track, "set upstream info for new branch", + OPT__QUIET(&opts.quiet), + OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"), + OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "log for new branch"), + OPT_SET_INT('t', "track", &opts.track, "track", BRANCH_TRACK_EXPLICIT), - OPT_STRING(0, "orphan", &opts.new_orphan_branch, "new branch", "new unparented branch"), - OPT_SET_INT('2', "ours", &opts.writeout_stage, "checkout our version for unmerged files", + OPT_SET_INT('2', "ours", &opts.writeout_stage, "stage", 2), - OPT_SET_INT('3', "theirs", &opts.writeout_stage, "checkout their version for unmerged files", + OPT_SET_INT('3', "theirs", &opts.writeout_stage, "stage", 3), - OPT__FORCE(&opts.force, "force checkout (throw away local modifications)"), - OPT_BOOLEAN('m', "merge", &opts.merge, "perform a 3-way merge with the new branch"), + OPT_BOOLEAN('f', "force", &opts.force, "force"), + OPT_BOOLEAN('m', "merge", &opts.merge, "merge"), OPT_STRING(0, "conflict", &conflict_style, "style", "conflict style (merge or diff3)"), OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"), @@ -714,22 +652,13 @@ memset(&opts, 0, sizeof(opts)); memset(&new, 0, sizeof(new)); - gitmodules_config(); - git_config(git_checkout_config, &opts); + git_config(git_checkout_config, NULL); opts.track = BRANCH_TRACK_UNSPECIFIED; argc = parse_options(argc, argv, prefix, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); - /* we can assume from now on new_branch = !new_branch_force */ - if (opts.new_branch && opts.new_branch_force) - die("-B cannot be used with -b"); - - /* copy -B over to -b, so that we can just check the latter */ - if (opts.new_branch_force) - opts.new_branch = opts.new_branch_force; - if (patch_mode && (opts.track > 0 || opts.new_branch || opts.new_branch_log || opts.merge || opts.force)) die ("--patch is incompatible with all other options"); @@ -749,14 +678,6 @@ opts.new_branch = argv0 + 1; } - if (opts.new_orphan_branch) { - if (opts.new_branch) - die("--orphan and -b|-B are mutually exclusive"); - if (opts.track > 0) - die("--orphan cannot be used with -t"); - opts.new_branch = opts.new_orphan_branch; - } - if (conflict_style) { opts.merge = 1; /* implied */ git_xmerge_config("merge.conflictstyle", conflict_style, NULL); @@ -784,9 +705,9 @@ * between A and B, A...B names that merge base. * * With no paths, if is _not_ a commit, no -t nor -b - * was given, and there is a remote-tracking branch whose name is + * was given, and there is a tracking branch whose name is * in one and only one remote, then this is a short-hand - * to fork local from that remote-tracking branch. + * to fork local from that remote tracking branch. * * Otherwise shall not be ambiguous. * - If it's *only* a reference, treat it like case (1). @@ -900,12 +821,8 @@ if (strbuf_check_branch_ref(&buf, opts.new_branch)) die("git checkout: we do not like '%s' as a branch name.", opts.new_branch); - if (!get_sha1(buf.buf, rev)) { - opts.branch_exists = 1; - if (!opts.new_branch_force) - die("git checkout: branch %s already exists", - opts.new_branch); - } + if (!get_sha1(buf.buf, rev)) + die("git checkout: branch %s already exists", opts.new_branch); strbuf_release(&buf); } diff -Nru git-1.7.4.1/builtin/checkout-index.c git-1.7.1/builtin/checkout-index.c --- git-1.7.4.1/builtin/checkout-index.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/checkout-index.c 2010-04-24 02:38:35.000000000 +0000 @@ -155,7 +155,7 @@ } static const char * const builtin_checkout_index_usage[] = { - "git checkout-index [options] [--] [...]", + "git checkout-index [options] [--] ...", NULL }; @@ -217,9 +217,9 @@ struct option builtin_checkout_index_options[] = { OPT_BOOLEAN('a', "all", &all, "checks out all files in the index"), - OPT__FORCE(&force, "forces overwrite of existing files"), - OPT__QUIET(&quiet, - "no warning for existing files and files not in index"), + OPT_BOOLEAN('f', "force", &force, + "forces overwrite of existing files"), + OPT__QUIET(&quiet), OPT_BOOLEAN('n', "no-create", ¬_new, "don't checkout new files"), { OPTION_CALLBACK, 'u', "index", &newfd, NULL, @@ -241,9 +241,6 @@ OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_checkout_index_usage, - builtin_checkout_index_options); git_config(git_default_config, NULL); state.base_dir = ""; prefix_length = prefix ? strlen(prefix) : 0; diff -Nru git-1.7.4.1/builtin/check-ref-format.c git-1.7.1/builtin/check-ref-format.c --- git-1.7.4.1/builtin/check-ref-format.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/check-ref-format.c 2010-04-24 02:38:35.000000000 +0000 @@ -33,38 +33,28 @@ *dst = '\0'; } -static int check_ref_format_branch(const char *arg) -{ - struct strbuf sb = STRBUF_INIT; - int nongit; - - setup_git_directory_gently(&nongit); - if (strbuf_check_branch_ref(&sb, arg)) - die("'%s' is not a valid branch name", arg); - printf("%s\n", sb.buf + 11); - return 0; -} - -static int check_ref_format_print(const char *arg) -{ - char *refname = xmalloc(strlen(arg) + 1); - - if (check_ref_format(arg)) - return 1; - collapse_slashes(refname, arg); - printf("%s\n", refname); - return 0; -} - int cmd_check_ref_format(int argc, const char **argv, const char *prefix) { if (argc == 2 && !strcmp(argv[1], "-h")) usage(builtin_check_ref_format_usage); - if (argc == 3 && !strcmp(argv[1], "--branch")) - return check_ref_format_branch(argv[2]); - if (argc == 3 && !strcmp(argv[1], "--print")) - return check_ref_format_print(argv[2]); + if (argc == 3 && !strcmp(argv[1], "--branch")) { + struct strbuf sb = STRBUF_INIT; + + if (strbuf_check_branch_ref(&sb, argv[2])) + die("'%s' is not a valid branch name", argv[2]); + printf("%s\n", sb.buf + 11); + exit(0); + } + if (argc == 3 && !strcmp(argv[1], "--print")) { + char *refname = xmalloc(strlen(argv[2]) + 1); + + if (check_ref_format(argv[2])) + exit(1); + collapse_slashes(refname, argv[2]); + printf("%s\n", refname); + exit(0); + } if (argc != 2) usage(builtin_check_ref_format_usage); return !!check_ref_format(argv[1]); diff -Nru git-1.7.4.1/builtin/clean.c git-1.7.1/builtin/clean.c --- git-1.7.4.1/builtin/clean.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/clean.c 2010-04-24 02:38:35.000000000 +0000 @@ -10,13 +10,12 @@ #include "cache.h" #include "dir.h" #include "parse-options.h" -#include "string-list.h" #include "quote.h" static int force = -1; /* unset */ static const char *const builtin_clean_usage[] = { - "git clean [-d] [-f] [-n] [-q] [-e ] [-x | -X] [--] ...", + "git clean [-d] [-f] [-n] [-q] [-x | -X] [--] ...", NULL }; @@ -27,34 +26,24 @@ return git_default_config(var, value, cb); } -static int exclude_cb(const struct option *opt, const char *arg, int unset) -{ - struct string_list *exclude_list = opt->value; - string_list_append(exclude_list, arg); - return 0; -} - int cmd_clean(int argc, const char **argv, const char *prefix) { int i; int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0; - int ignored_only = 0, config_set = 0, errors = 0; + int ignored_only = 0, baselen = 0, config_set = 0, errors = 0; int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT; struct strbuf directory = STRBUF_INIT; struct dir_struct dir; static const char **pathspec; struct strbuf buf = STRBUF_INIT; - struct string_list exclude_list = STRING_LIST_INIT_NODUP; const char *qname; char *seen = NULL; struct option options[] = { - OPT__QUIET(&quiet, "do not print names of files removed"), - OPT__DRY_RUN(&show_only, "dry run"), - OPT__FORCE(&force, "force"), + OPT__QUIET(&quiet), + OPT__DRY_RUN(&show_only), + OPT_BOOLEAN('f', "force", &force, "force"), OPT_BOOLEAN('d', NULL, &remove_directories, "remove whole directories"), - { OPTION_CALLBACK, 'e', "exclude", &exclude_list, "pattern", - "exclude ", PARSE_OPT_NONEG, exclude_cb }, OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"), OPT_BOOLEAN('X', NULL, &ignored_only, "remove only ignored files"), @@ -92,9 +81,6 @@ if (!ignored) setup_standard_excludes(&dir); - for (i = 0; i < exclude_list.nr; i++) - add_exclude(exclude_list.items[i].string, "", 0, dir.exclude_list); - pathspec = get_pathspec(prefix, argv); fill_directory(&dir, pathspec); @@ -138,7 +124,7 @@ if (pathspec) { memset(seen, 0, argc > 0 ? argc : 1); matches = match_pathspec(pathspec, ent->name, len, - 0, seen); + baselen, seen); } if (S_ISDIR(st.st_mode)) { @@ -153,7 +139,7 @@ printf("Removing %s\n", qname); if (remove_dir_recursively(&directory, rm_flags) != 0) { - warning("failed to remove %s", qname); + warning("failed to remove '%s'", qname); errors++; } } else if (show_only) { @@ -173,7 +159,7 @@ printf("Removing %s\n", qname); } if (unlink(ent->name) != 0) { - warning("failed to remove %s", qname); + warning("failed to remove '%s'", qname); errors++; } } @@ -181,6 +167,5 @@ free(seen); strbuf_release(&directory); - string_list_clear(&exclude_list, 0); return (errors != 0); } diff -Nru git-1.7.4.1/builtin/clone.c git-1.7.1/builtin/clone.c --- git-1.7.4.1/builtin/clone.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/clone.c 2010-04-24 02:38:35.000000000 +0000 @@ -66,8 +66,6 @@ "setup as shared repository"), OPT_BOOLEAN(0, "recursive", &option_recursive, "initialize submodules in the clone"), - OPT_BOOLEAN(0, "recurse-submodules", &option_recursive, - "initialize submodules in the clone"), OPT_STRING(0, "template", &option_template, "path", "path the template repository"), OPT_STRING(0, "reference", &option_reference, "repo", @@ -304,8 +302,6 @@ transport = transport_get(remote, src_repo); ret = transport_get_remote_refs(transport); transport_disconnect(transport); - if (0 <= option_verbosity) - printf("done.\n"); return ret; } @@ -363,7 +359,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) { - int is_bundle = 0, is_local; + int is_bundle = 0; struct stat buf; const char *repo_name, *repo, *work_tree, *git_dir; char *path, *dir; @@ -416,9 +412,6 @@ repo = xstrdup(make_absolute_path(repo_name)); else repo = repo_name; - is_local = path && !is_bundle; - if (is_local && option_depth) - warning("--depth is ignored in local clones; use file:// instead."); if (argc == 2) dir = xstrdup(argv[1]); @@ -468,10 +461,7 @@ die("could not create leading directories of '%s'", git_dir); set_git_dir(make_absolute_path(git_dir)); - if (0 <= option_verbosity) - printf("Cloning into %s%s...\n", - option_bare ? "bare repository " : "", dir); - init_db(option_template, INIT_DB_QUIET); + init_db(option_template, (option_verbosity < 0) ? INIT_DB_QUIET : 0); /* * At this point, the config exists, so we do not need the @@ -480,6 +470,9 @@ */ unsetenv(CONFIG_ENVIRONMENT); + if (option_reference) + setup_reference(git_dir); + git_config(git_default_config, NULL); if (option_bare) { @@ -505,25 +498,22 @@ git_config_set(key.buf, "true"); strbuf_reset(&key); } - } - strbuf_addf(&key, "remote.%s.url", option_origin); - git_config_set(key.buf, repo); - strbuf_reset(&key); - - if (option_reference) - setup_reference(git_dir); + strbuf_addf(&key, "remote.%s.url", option_origin); + git_config_set(key.buf, repo); + strbuf_reset(&key); + } fetch_pattern = value.buf; refspec = parse_fetch_refspec(1, &fetch_pattern); strbuf_reset(&value); - if (is_local) { + if (path && !is_bundle) { refs = clone_local(path, git_dir); mapped_refs = wanted_peer_refs(refs, refspec); } else { - struct remote *remote = remote_get(option_origin); + struct remote *remote = remote_get(argv[0]); transport = transport_get(remote, remote->url[0]); if (!transport->get_refs_list || !transport->fetch) diff -Nru git-1.7.4.1/builtin/commit.c git-1.7.1/builtin/commit.c --- git-1.7.4.1/builtin/commit.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/commit.c 2010-04-24 02:38:35.000000000 +0000 @@ -25,7 +25,6 @@ #include "rerere.h" #include "unpack-trees.h" #include "quote.h" -#include "submodule.h" static const char * const builtin_commit_usage[] = { "git commit [options] [--] ...", @@ -45,14 +44,9 @@ " git config --global user.name \"Your Name\"\n" " git config --global user.email you@example.com\n" "\n" -"After doing this, you may fix the identity used for this commit with:\n" +"If the identity used for this commit is wrong, you can fix it with:\n" "\n" -" git commit --amend --reset-author\n"; - -static const char empty_amend_advice[] = -"You asked to amend the most recent commit, but doing so would make\n" -"it empty. You can repeat your command with --allow-empty, or you can\n" -"remove the commit entirely with \"git reset HEAD^\".\n"; +" git commit --amend --author='Your Name '\n"; static unsigned char head_sha1[20]; @@ -63,17 +57,17 @@ static enum { COMMIT_AS_IS = 1, COMMIT_NORMAL, - COMMIT_PARTIAL + COMMIT_PARTIAL, } commit_style; static const char *logfile, *force_author; static const char *template_file; static char *edit_message, *use_message; -static char *fixup_message, *squash_message; +static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; -static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static int no_post_rewrite; +static char *untracked_files_arg, *force_date; /* * The default commit message cleanup mode will remove the lines * beginning with # (shell comments) and leading and trailing @@ -84,12 +78,11 @@ static enum { CLEANUP_SPACE, CLEANUP_NONE, - CLEANUP_ALL + CLEANUP_ALL, } cleanup_mode; static char *cleanup_arg; static int use_editor = 1, initial_commit, in_merge, include_status = 1; -static int show_ignored_in_status; static const char *only_include_assumed; static struct strbuf message; @@ -97,9 +90,8 @@ static enum { STATUS_FORMAT_LONG, STATUS_FORMAT_SHORT, - STATUS_FORMAT_PORCELAIN + STATUS_FORMAT_PORCELAIN, } status_format = STATUS_FORMAT_LONG; -static int status_show_branch; static int opt_parse_m(const struct option *opt, const char *arg, int unset) { @@ -114,8 +106,8 @@ } static struct option builtin_commit_options[] = { - OPT__QUIET(&quiet, "suppress summary after successful commit"), - OPT__VERBOSE(&verbose, "show diff in commit message template"), + OPT__QUIET(&quiet), + OPT__VERBOSE(&verbose), OPT_GROUP("Commit message options"), OPT_FILENAME('F', "file", &logfile, "read log from file"), @@ -124,8 +116,6 @@ OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m), OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"), OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"), - OPT_STRING(0, "fixup", &fixup_message, "COMMIT", "use autosquash formatted message to fixup specified commit"), - OPT_STRING(0, "squash", &squash_message, "COMMIT", "use autosquash formatted message to squash specified commit"), OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"), OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"), OPT_FILENAME('t', "template", &template_file, "use specified template file"), @@ -143,23 +133,16 @@ OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"), OPT_SET_INT(0, "short", &status_format, "show status concisely", STATUS_FORMAT_SHORT), - OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"), OPT_SET_INT(0, "porcelain", &status_format, "show porcelain output format", STATUS_FORMAT_PORCELAIN), OPT_BOOLEAN('z', "null", &null_termination, "terminate entries with NUL"), OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"), - { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"), /* end commit contents options */ - { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL, - "ok to record an empty change", - PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, - { OPTION_BOOLEAN, 0, "allow-empty-message", &allow_empty_message, NULL, - "ok to record a change with an empty message", - PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, - OPT_END() }; @@ -222,7 +205,7 @@ continue; if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m)) continue; - item = string_list_insert(list, ce->name); + item = string_list_insert(ce->name, list); if (ce_skip_worktree(ce)) item->util = item; /* better a valid pointer than a fake one */ } @@ -346,13 +329,9 @@ if (!pathspec || !*pathspec) { fd = hold_locked_index(&index_lock, 1); refresh_cache_or_die(refresh_flags); - if (active_cache_changed) { - if (write_cache(fd, active_cache, active_nr) || - commit_locked_index(&index_lock)) - die("unable to write new_index file"); - } else { - rollback_lock_file(&index_lock); - } + if (write_cache(fd, active_cache, active_nr) || + commit_locked_index(&index_lock)) + die("unable to write new_index file"); commit_style = COMMIT_AS_IS; return get_index_file(); } @@ -438,7 +417,7 @@ switch (status_format) { case STATUS_FORMAT_SHORT: - wt_shortstatus_print(s, null_termination, status_show_branch); + wt_shortstatus_print(s, null_termination); break; case STATUS_FORMAT_PORCELAIN: wt_porcelain_print(s, null_termination); @@ -461,7 +440,7 @@ static const char sign_off_header[] = "Signed-off-by: "; -static void determine_author_info(struct strbuf *author_ident) +static void determine_author_info(void) { char *name, *email, *date; @@ -476,21 +455,15 @@ if (!a) die("invalid commit: %s", use_message); - lb = strchrnul(a + strlen("\nauthor "), '<'); - rb = strchrnul(lb, '>'); - eol = strchrnul(rb, '\n'); - if (!*lb || !*rb || !*eol) + lb = strstr(a + 8, " <"); + rb = strstr(a + 8, "> "); + eol = strchr(a + 8, '\n'); + if (!lb || !rb || !eol) die("invalid commit: %s", use_message); - if (lb == a + strlen("\nauthor ")) - /* \nauthor */ - name = xcalloc(1, 1); - else - name = xmemdupz(a + strlen("\nauthor "), - (lb - strlen(" ") - - (a + strlen("\nauthor ")))); - email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<"))); - date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> "))); + name = xstrndup(a + 8, lb - (a + 8)); + email = xstrndup(lb + 2, rb - (lb + 2)); + date = xstrndup(rb + 2, eol - (rb + 2)); } if (force_author) { @@ -505,8 +478,10 @@ if (force_date) date = force_date; - strbuf_addstr(author_ident, fmt_ident(name, email, date, - IDENT_ERROR_ON_NO_NAME)); + + author_name = name; + author_email = email; + author_date = date; } static int ends_rfc2822_footer(struct strbuf *sb) @@ -550,21 +525,10 @@ return 1; } -static char *cut_ident_timestamp_part(char *string) -{ - char *ket = strrchr(string, '>'); - if (!ket || ket[1] != ' ') - die("Malformed ident string: '%s'", string); - *++ket = '\0'; - return ket; -} - static int prepare_to_commit(const char *index_file, const char *prefix, - struct wt_status *s, - struct strbuf *author_ident) + struct wt_status *s) { struct stat statbuf; - struct strbuf committer_ident = STRBUF_INIT; int commitable, saved_color_setting; struct strbuf sb = STRBUF_INIT; char *buffer; @@ -576,25 +540,6 @@ if (!no_verify && run_hook(index_file, "pre-commit", NULL)) return 0; - if (squash_message) { - /* - * Insert the proper subject line before other commit - * message options add their content. - */ - if (use_message && !strcmp(use_message, squash_message)) - strbuf_addstr(&sb, "squash! "); - else { - struct pretty_print_context ctx = {0}; - struct commit *c; - c = lookup_commit_reference_by_name(squash_message); - if (!c) - die("could not lookup commit %s", squash_message); - ctx.output_encoding = get_commit_output_encoding(); - format_commit_message(c, "squash! %s\n\n", &sb, - &ctx); - } - } - if (message.len) { strbuf_addbuf(&sb, &message); hook_arg1 = "message"; @@ -616,16 +561,6 @@ strbuf_add(&sb, buffer + 2, strlen(buffer + 2)); hook_arg1 = "commit"; hook_arg2 = use_message; - } else if (fixup_message) { - struct pretty_print_context ctx = {0}; - struct commit *commit; - commit = lookup_commit_reference_by_name(fixup_message); - if (!commit) - die("could not lookup commit %s", fixup_message); - ctx.output_encoding = get_commit_output_encoding(); - format_commit_message(commit, "fixup! %s\n\n", - &sb, &ctx); - hook_arg1 = "message"; } else if (!stat(git_path("MERGE_MSG"), &statbuf)) { if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0) die_errno("could not read MERGE_MSG"); @@ -647,16 +582,6 @@ else if (in_merge) hook_arg1 = "merge"; - if (squash_message) { - /* - * If squash_commit was used for the commit subject, - * then we're possibly hijacking other commit log options. - * Reset the hook args to tell the real story. - */ - hook_arg1 = "message"; - hook_arg2 = ""; - } - fp = fopen(git_path(commit_editmsg), "w"); if (fp == NULL) die_errno("could not open '%s'", git_path(commit_editmsg)); @@ -687,13 +612,14 @@ strbuf_release(&sb); - /* This checks and barfs if author is badly specified */ - determine_author_info(author_ident); + determine_author_info(); /* This checks if committer ident is explicitly given */ - strbuf_addstr(&committer_ident, git_committer_info(0)); + git_committer_info(0); if (use_editor && include_status) { - char *ai_tmp, *ci_tmp; + char *author_ident; + const char *committer_ident; + if (in_merge) fprintf(fp, "#\n" @@ -721,21 +647,23 @@ if (only_include_assumed) fprintf(fp, "# %s\n", only_include_assumed); - ai_tmp = cut_ident_timestamp_part(author_ident->buf); - ci_tmp = cut_ident_timestamp_part(committer_ident.buf); - if (strcmp(author_ident->buf, committer_ident.buf)) + author_ident = xstrdup(fmt_name(author_name, author_email)); + committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"), + getenv("GIT_COMMITTER_EMAIL")); + if (strcmp(author_ident, committer_ident)) fprintf(fp, "%s" "# Author: %s\n", ident_shown++ ? "" : "#\n", - author_ident->buf); + author_ident); + free(author_ident); if (!user_ident_sufficiently_given()) fprintf(fp, "%s" "# Committer: %s\n", ident_shown++ ? "" : "#\n", - committer_ident.buf); + committer_ident); if (ident_shown) fprintf(fp, "#\n"); @@ -744,9 +672,6 @@ s->use_color = 0; commitable = run_status(fp, index_file, prefix, 1, s); s->use_color = saved_color_setting; - - *ai_tmp = ' '; - *ci_tmp = ' '; } else { unsigned char sha1[20]; const char *parent = "HEAD"; @@ -762,15 +687,12 @@ else commitable = index_differs_from(parent, 0); } - strbuf_release(&committer_ident); fclose(fp); if (!commitable && !in_merge && !allow_empty && !(amend && is_a_merge(head_sha1))) { run_status(stdout, index_file, prefix, 0, s); - if (amend) - fputs(empty_amend_advice, stderr); return 0; } @@ -795,8 +717,7 @@ if (use_editor) { char index[PATH_MAX]; - const char *env[2] = { NULL }; - env[0] = index; + const char *env[2] = { index, NULL }; snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file); if (launch_editor(git_path(commit_editmsg), NULL, env)) { fprintf(stderr, @@ -914,7 +835,7 @@ if (force_author && renew_authorship) die("Using both --reset-author and --author does not make sense"); - if (logfile || message.len || use_message || fixup_message) + if (logfile || message.len || use_message) use_editor = 0; if (edit_flag) use_editor = 1; @@ -929,35 +850,48 @@ die("You have nothing to amend."); if (amend && in_merge) die("You are in the middle of a merge -- cannot amend."); - if (fixup_message && squash_message) - die("Options --squash and --fixup cannot be used together"); + if (use_message) f++; if (edit_message) f++; - if (fixup_message) - f++; if (logfile) f++; if (f > 1) - die("Only one of -c/-C/-F/--fixup can be used."); + die("Only one of -c/-C/-F can be used."); if (message.len && f > 0) - die("Option -m cannot be combined with -c/-C/-F/--fixup."); + die("Option -m cannot be combined with -c/-C/-F."); if (edit_message) use_message = edit_message; - if (amend && !use_message && !fixup_message) + if (amend && !use_message) use_message = "HEAD"; if (!use_message && renew_authorship) die("--reset-author can be used only with -C, -c or --amend."); if (use_message) { + unsigned char sha1[20]; + static char utf8[] = "UTF-8"; const char *out_enc; + char *enc, *end; struct commit *commit; - commit = lookup_commit_reference_by_name(use_message); - if (!commit) + if (get_sha1(use_message, sha1)) die("could not lookup commit %s", use_message); - out_enc = get_commit_output_encoding(); - use_message_buffer = logmsg_reencode(commit, out_enc); + commit = lookup_commit_reference(sha1); + if (!commit || parse_commit(commit)) + die("could not parse commit %s", use_message); + + enc = strstr(commit->buffer, "\nencoding"); + if (enc) { + end = strchr(enc + 10, '\n'); + enc = xstrndup(enc + 10, end - (enc + 10)); + } else { + enc = utf8; + } + out_enc = git_commit_encoding ? git_commit_encoding : utf8; + + if (strcmp(out_enc, enc)) + use_message_buffer = + reencode_string(commit->buffer, out_enc, enc); /* * If we failed to reencode the buffer, just copy it @@ -967,6 +901,8 @@ */ if (use_message_buffer == NULL) use_message_buffer = xstrdup(commit->buffer); + if (enc != utf8) + free(enc); } if (!!also + !!only + !!all + !!interactive > 1) @@ -1020,8 +956,6 @@ { if (!strcasecmp(var+offset, "header")) return WT_STATUS_HEADER; - if (!strcasecmp(var+offset, "branch")) - return WT_STATUS_ONBRANCH; if (!strcasecmp(var+offset, "updated") || !strcasecmp(var+offset, "added")) return WT_STATUS_UPDATED; @@ -1083,14 +1017,11 @@ int cmd_status(int argc, const char **argv, const char *prefix) { struct wt_status s; - int fd; unsigned char sha1[20]; static struct option builtin_status_options[] = { - OPT__VERBOSE(&verbose, "be verbose"), + OPT__VERBOSE(&verbose), OPT_SET_INT('s', "short", &status_format, "show status concisely", STATUS_FORMAT_SHORT), - OPT_BOOLEAN('b', "branch", &status_show_branch, - "show branch information"), OPT_SET_INT(0, "porcelain", &status_format, "show porcelain output format", STATUS_FORMAT_PORCELAIN), @@ -1100,48 +1031,27 @@ "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, - OPT_BOOLEAN(0, "ignored", &show_ignored_in_status, - "show ignored files"), - { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, "when", - "ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)", - PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, OPT_END(), }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_status_usage, builtin_status_options); - if (null_termination && status_format == STATUS_FORMAT_LONG) status_format = STATUS_FORMAT_PORCELAIN; wt_status_prepare(&s); - gitmodules_config(); git_config(git_status_config, &s); in_merge = file_exists(git_path("MERGE_HEAD")); argc = parse_options(argc, argv, prefix, builtin_status_options, builtin_status_usage, 0); handle_untracked_files_arg(&s); - if (show_ignored_in_status) - s.show_ignored_files = 1; + if (*argv) s.pathspec = get_pathspec(prefix, argv); read_cache_preload(s.pathspec); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL); - - fd = hold_locked_index(&index_lock, 0); - if (0 <= fd) { - if (active_cache_changed && - !write_cache(fd, active_cache, active_nr)) - commit_locked_index(&index_lock); - else - rollback_lock_file(&index_lock); - } - s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0; s.in_merge = in_merge; - s.ignore_submodule_arg = ignore_submodule_arg; wt_status_collect(&s); if (s.relative_paths) @@ -1153,14 +1063,13 @@ switch (status_format) { case STATUS_FORMAT_SHORT: - wt_shortstatus_print(&s, null_termination, status_show_branch); + wt_shortstatus_print(&s, null_termination); break; case STATUS_FORMAT_PORCELAIN: wt_porcelain_print(&s, null_termination); break; case STATUS_FORMAT_LONG: s.verbose = verbose; - s.ignore_submodule_arg = ignore_submodule_arg; wt_status_print(&s); break; } @@ -1206,6 +1115,7 @@ init_revisions(&rev, prefix); setup_revisions(0, NULL, &rev, NULL); + rev.abbrev = 0; rev.diff = 1; rev.diffopt.output_format = DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY; @@ -1228,11 +1138,13 @@ initial_commit ? " (root-commit)" : ""); if (!log_tree_commit(&rev, commit)) { - rev.always_show_header = 1; - rev.use_terminator = 1; - log_tree_commit(&rev, commit); + struct pretty_print_context ctx = {0}; + struct strbuf buf = STRBUF_INIT; + ctx.date_mode = DATE_NORMAL; + format_commit_message(commit, format.buf + 7, &buf, &ctx); + printf("%s\n", buf.buf); + strbuf_release(&buf); } - strbuf_release(&format); } @@ -1287,7 +1199,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix) { struct strbuf sb = STRBUF_INIT; - struct strbuf author_ident = STRBUF_INIT; const char *index_file, *reflog_msg; char *nl, *p; unsigned char commit_sha1[20]; @@ -1297,9 +1208,6 @@ int allow_fast_forward = 1; struct wt_status s; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_commit_usage, builtin_commit_options); - wt_status_prepare(&s); git_config(git_commit_config, &s); in_merge = file_exists(git_path("MERGE_HEAD")); @@ -1318,22 +1226,19 @@ /* Set up everything for writing the commit object. This includes running hooks, writing the trees, and interacting with the user. */ - if (!prepare_to_commit(index_file, prefix, &s, &author_ident)) { + if (!prepare_to_commit(index_file, prefix, &s)) { rollback_index_files(); return 1; } /* Determine parents */ - reflog_msg = getenv("GIT_REFLOG_ACTION"); if (initial_commit) { - if (!reflog_msg) - reflog_msg = "commit (initial)"; + reflog_msg = "commit (initial)"; } else if (amend) { struct commit_list *c; struct commit *commit; - if (!reflog_msg) - reflog_msg = "commit (amend)"; + reflog_msg = "commit (amend)"; commit = lookup_commit(head_sha1); if (!commit || parse_commit(commit)) die("could not parse HEAD commit"); @@ -1344,8 +1249,7 @@ struct strbuf m = STRBUF_INIT; FILE *fp; - if (!reflog_msg) - reflog_msg = "commit (merge)"; + reflog_msg = "commit (merge)"; pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; fp = fopen(git_path("MERGE_HEAD"), "r"); if (fp == NULL) @@ -1368,8 +1272,7 @@ if (allow_fast_forward) parents = reduce_heads(parents); } else { - if (!reflog_msg) - reflog_msg = "commit"; + reflog_msg = "commit"; pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; } @@ -1390,18 +1293,18 @@ if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, cleanup_mode == CLEANUP_ALL); - if (message_is_empty(&sb) && !allow_empty_message) { + if (message_is_empty(&sb)) { rollback_index_files(); fprintf(stderr, "Aborting commit due to empty commit message.\n"); exit(1); } if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1, - author_ident.buf)) { + fmt_ident(author_name, author_email, author_date, + IDENT_ERROR_ON_NO_NAME))) { rollback_index_files(); die("failed to write commit object"); } - strbuf_release(&author_ident); ref_lock = lock_any_ref_for_update("HEAD", initial_commit ? NULL : head_sha1, diff -Nru git-1.7.4.1/builtin/commit-tree.c git-1.7.1/builtin/commit-tree.c --- git-1.7.4.1/builtin/commit-tree.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/commit-tree.c 2010-04-24 02:38:35.000000000 +0000 @@ -9,7 +9,20 @@ #include "builtin.h" #include "utf8.h" -static const char commit_tree_usage[] = "git commit-tree [(-p )...] < changelog"; +/* + * FIXME! Share the code with "write-tree.c" + */ +static void check_valid(unsigned char *sha1, enum object_type expect) +{ + enum object_type type = sha1_object_info(sha1, NULL); + if (type < 0) + die("%s is not a valid object", sha1_to_hex(sha1)); + if (type != expect) + die("%s is not a valid '%s' object", sha1_to_hex(sha1), + typename(expect)); +} + +static const char commit_tree_usage[] = "git commit-tree [-p ]* < changelog"; static void new_parent(struct commit *parent, struct commit_list **parents_p) { @@ -25,6 +38,61 @@ commit_list_insert(parent, parents_p); } +static const char commit_utf8_warn[] = +"Warning: commit message does not conform to UTF-8.\n" +"You may want to amend it after fixing the message, or set the config\n" +"variable i18n.commitencoding to the encoding your project uses.\n"; + +int commit_tree(const char *msg, unsigned char *tree, + struct commit_list *parents, unsigned char *ret, + const char *author) +{ + int result; + int encoding_is_utf8; + struct strbuf buffer; + + check_valid(tree, OBJ_TREE); + + /* Not having i18n.commitencoding is the same as having utf-8 */ + encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); + + strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */ + strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree)); + + /* + * NOTE! This ordering means that the same exact tree merged with a + * different order of parents will be a _different_ changeset even + * if everything else stays the same. + */ + while (parents) { + struct commit_list *next = parents->next; + strbuf_addf(&buffer, "parent %s\n", + sha1_to_hex(parents->item->object.sha1)); + free(parents); + parents = next; + } + + /* Person/date information */ + if (!author) + author = git_author_info(IDENT_ERROR_ON_NO_NAME); + strbuf_addf(&buffer, "author %s\n", author); + strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME)); + if (!encoding_is_utf8) + strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding); + strbuf_addch(&buffer, '\n'); + + /* And add the comment */ + strbuf_addstr(&buffer, msg); + + /* And check the encoding */ + if (encoding_is_utf8 && !is_utf8(buffer.buf)) + fprintf(stderr, commit_utf8_warn); + + result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret); + strbuf_release(&buffer); + return result; +} + int cmd_commit_tree(int argc, const char **argv, const char *prefix) { int i; @@ -49,19 +117,17 @@ if (get_sha1(b, sha1)) die("Not a valid object name %s", b); - assert_sha1_type(sha1, OBJ_COMMIT); + check_valid(sha1, OBJ_COMMIT); new_parent(lookup_commit(sha1), &parents); } if (strbuf_read(&buffer, 0, 0) < 0) die_errno("git commit-tree: failed to read"); - if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) { - strbuf_release(&buffer); - return 1; + if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) { + printf("%s\n", sha1_to_hex(commit_sha1)); + return 0; } - - printf("%s\n", sha1_to_hex(commit_sha1)); - strbuf_release(&buffer); - return 0; + else + return 1; } diff -Nru git-1.7.4.1/builtin/config.c git-1.7.1/builtin/config.c --- git-1.7.4.1/builtin/config.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/config.c 2010-04-24 02:38:35.000000000 +0000 @@ -20,7 +20,7 @@ static char key_delim = ' '; static char term = '\n'; -static int use_global_config, use_system_config, use_local_config; +static int use_global_config, use_system_config; static const char *given_config_file; static int actions, types; static const char *get_color_slot, *get_colorbool_slot; @@ -51,7 +51,6 @@ OPT_GROUP("Config file location"), OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"), OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"), - OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"), OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"), OPT_GROUP("Action"), OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET), @@ -198,11 +197,7 @@ git_config_from_file(show_config, system_wide, NULL); if (do_all && global) git_config_from_file(show_config, global, NULL); - if (do_all) - git_config_from_file(show_config, local, NULL); - git_config_from_parameters(show_config, NULL); - if (!do_all && !seen) - git_config_from_file(show_config, local, NULL); + git_config_from_file(show_config, local, NULL); if (!do_all && !seen && global) git_config_from_file(show_config, global, NULL); if (!do_all && !seen && system_wide) @@ -331,10 +326,11 @@ return get_colorbool_found ? 0 : 1; } -int cmd_config(int argc, const char **argv, const char *prefix) +int cmd_config(int argc, const char **argv, const char *unused_prefix) { - int nongit = !startup_info->have_repository; + int nongit; char *value; + const char *prefix = setup_git_directory_gently(&nongit); config_exclusive_filename = getenv(CONFIG_ENVIRONMENT); @@ -342,7 +338,7 @@ builtin_config_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) { + if (use_global_config + use_system_config + !!given_config_file > 1) { error("only one config file at a time."); usage_with_options(builtin_config_usage, builtin_config_options); } @@ -358,8 +354,6 @@ } else if (use_system_config) config_exclusive_filename = git_etc_gitconfig(); - else if (use_local_config) - config_exclusive_filename = git_pathdup("config"); else if (given_config_file) { if (!is_absolute_path(given_config_file) && prefix) config_exclusive_filename = prefix_filename(prefix, diff -Nru git-1.7.4.1/builtin/count-objects.c git-1.7.1/builtin/count-objects.c --- git-1.7.4.1/builtin/count-objects.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/count-objects.c 2010-04-24 02:38:35.000000000 +0000 @@ -79,7 +79,7 @@ unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0; off_t loose_size = 0; struct option opts[] = { - OPT__VERBOSE(&verbose, "be verbose"), + OPT__VERBOSE(&verbose), OPT_END(), }; diff -Nru git-1.7.4.1/builtin/describe.c git-1.7.1/builtin/describe.c --- git-1.7.4.1/builtin/describe.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/describe.c 2010-04-24 02:38:35.000000000 +0000 @@ -6,7 +6,6 @@ #include "exec_cmd.h" #include "parse-options.h" #include "diff.h" -#include "hash.h" #define SEEN (1u<<0) #define MAX_TAGS (FLAG_BITS - 1) @@ -23,8 +22,7 @@ static int longformat; static int abbrev = DEFAULT_ABBREV; static int max_candidates = 10; -static struct hash_table names; -static int have_util; +static int found_names; static const char *pattern; static int always; static const char *dirty; @@ -36,108 +34,39 @@ struct commit_name { - struct commit_name *next; - unsigned char peeled[20]; struct tag *tag; - unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */ - unsigned name_checked:1; + int prio; /* annotated tag = 2, tag = 1, head = 0 */ unsigned char sha1[20]; - const char *path; + char path[FLEX_ARRAY]; /* more */ }; static const char *prio_names[] = { "head", "lightweight", "annotated", }; -static inline unsigned int hash_sha1(const unsigned char *sha1) -{ - unsigned int hash; - memcpy(&hash, sha1, sizeof(hash)); - return hash; -} - -static inline struct commit_name *find_commit_name(const unsigned char *peeled) -{ - struct commit_name *n = lookup_hash(hash_sha1(peeled), &names); - while (n && !!hashcmp(peeled, n->peeled)) - n = n->next; - return n; -} - -static int set_util(void *chain) -{ - struct commit_name *n; - for (n = chain; n; n = n->next) { - struct commit *c = lookup_commit_reference_gently(n->peeled, 1); - if (c) - c->util = n; - } - return 0; -} - -static int replace_name(struct commit_name *e, - int prio, - const unsigned char *sha1, - struct tag **tag) -{ - if (!e || e->prio < prio) - return 1; - - if (e->prio == 2 && prio == 2) { - /* Multiple annotated tags point to the same commit. - * Select one to keep based upon their tagger date. - */ - struct tag *t; - - if (!e->tag) { - t = lookup_tag(e->sha1); - if (!t || parse_tag(t)) - return 1; - e->tag = t; - } - - t = lookup_tag(sha1); - if (!t || parse_tag(t)) - return 0; - *tag = t; - - if (e->tag->date < t->date) - return 1; - } - - return 0; -} - static void add_to_known_names(const char *path, - const unsigned char *peeled, + struct commit *commit, int prio, const unsigned char *sha1) { - struct commit_name *e = find_commit_name(peeled); - struct tag *tag = NULL; - if (replace_name(e, prio, sha1, &tag)) { - if (!e) { - void **pos; - e = xmalloc(sizeof(struct commit_name)); - hashcpy(e->peeled, peeled); - pos = insert_hash(hash_sha1(peeled), e, &names); - if (pos) { - e->next = *pos; - *pos = e; - } else { - e->next = NULL; - } - } - e->tag = tag; + struct commit_name *e = commit->util; + if (!e || e->prio < prio) { + size_t len = strlen(path)+1; + free(e); + e = xmalloc(sizeof(struct commit_name) + len); + e->tag = NULL; e->prio = prio; - e->name_checked = 0; hashcpy(e->sha1, sha1); - e->path = path; + memcpy(e->path, path, len); + commit->util = e; } + found_names = 1; } static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data) { int might_be_tag = !prefixcmp(path, "refs/tags/"); + struct commit *commit; + struct object *object; unsigned char peeled[20]; int is_tag, prio; @@ -145,10 +74,16 @@ return 0; if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) { - is_tag = !!hashcmp(sha1, peeled); + commit = lookup_commit_reference_gently(peeled, 1); + if (!commit) + return 0; + is_tag = !!hashcmp(sha1, commit->object.sha1); } else { - hashcpy(peeled, sha1); - is_tag = 0; + commit = lookup_commit_reference_gently(sha1, 1); + object = parse_object(sha1); + if (!commit || !object) + return 0; + is_tag = object->type == OBJ_TAG; } /* If --all, then any refs are used. @@ -171,7 +106,7 @@ if (!prio) return 0; } - add_to_known_names(all ? path + 5 : path + 10, peeled, prio, sha1); + add_to_known_names(all ? path + 5 : path + 10, commit, prio, sha1); return 0; } @@ -218,7 +153,7 @@ struct commit *p = parents->item; parse_commit(p); if (!(p->object.flags & SEEN)) - commit_list_insert_by_date(p, list); + insert_by_date(p, list); p->object.flags |= c->object.flags; parents = parents->next; } @@ -230,15 +165,10 @@ { if (n->prio == 2 && !n->tag) { n->tag = lookup_tag(n->sha1); - if (!n->tag || parse_tag(n->tag)) + if (!n->tag || parse_tag(n->tag) || !n->tag->tag) die("annotated tag %s not available", n->path); - } - if (n->tag && !n->name_checked) { - if (!n->tag->tag) - die("annotated tag %s has no embedded name", n->path); if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) warning("tag '%s' is really '%s' here", n->tag->tag, n->path); - n->name_checked = 1; } if (n->tag) @@ -269,7 +199,7 @@ if (!cmit) die("%s is not a valid '%s' object", arg, commit_type); - n = find_commit_name(cmit->object.sha1); + n = cmit->util; if (n && (tags || all || n->prio == 2)) { /* * Exact match to an existing ref. @@ -288,11 +218,6 @@ if (debug) fprintf(stderr, "searching to describe %s\n", arg); - if (!have_util) { - for_each_hash(&names, set_util); - have_util = 1; - } - list = NULL; cmit->object.flags = SEEN; commit_list_insert(cmit, &list); @@ -334,7 +259,7 @@ struct commit *p = parents->item; parse_commit(p); if (!(p->object.flags & SEEN)) - commit_list_insert_by_date(p, &list); + insert_by_date(p, &list); p->object.flags |= c->object.flags; parents = parents->next; } @@ -362,7 +287,7 @@ qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt); if (gave_up_on) { - commit_list_insert_by_date(gave_up_on, &list); + insert_by_date(gave_up_on, &list); seen_commits--; } seen_commits += finish_depth_computation(&list, &all_matches[0]); @@ -452,9 +377,8 @@ return cmd_name_rev(i + argc, args, prefix); } - init_hash(&names); - for_each_rawref(get_name, NULL); - if (!names.nr && !always) + for_each_ref(get_name, NULL); + if (!found_names && !always) die("No names found, cannot describe anything."); if (argc == 0) { diff -Nru git-1.7.4.1/builtin/diff.c git-1.7.1/builtin/diff.c --- git-1.7.4.1/builtin/diff.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/diff.c 2010-04-24 02:38:35.000000000 +0000 @@ -13,7 +13,6 @@ #include "revision.h" #include "log-tree.h" #include "builtin.h" -#include "submodule.h" struct blobinfo { unsigned char sha1[20]; @@ -22,7 +21,7 @@ }; static const char builtin_diff_usage[] = -"git diff [] [ []] [--] [...]"; +"git diff {0,2} -- *"; static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, @@ -280,7 +279,6 @@ */ prefix = setup_git_directory_gently(&nongit); - gitmodules_config(); git_config(git_diff_ui_config, NULL); if (diff_use_color_default == -1) @@ -330,11 +328,8 @@ else if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged")) { add_head_to_pending(&rev); - if (!rev.pending.nr) { - struct tree *tree; - tree = lookup_tree((const unsigned char*)EMPTY_TREE_SHA1_BIN); - add_pending_object(&rev, &tree->object, "HEAD"); - } + if (!rev.pending.nr) + die("No HEAD commit to compare with (yet)"); break; } } @@ -412,19 +407,17 @@ result = builtin_diff_index(&rev, argc, argv); else if (ents == 2) result = builtin_diff_tree(&rev, argc, argv, ent); - else if (ent[0].item->flags & UNINTERESTING) { - /* - * diff A...B where there is at least one merge base - * between A and B. We have ent[0] == merge-base, - * ent[ents-2] == A, and ent[ents-1] == B. Show diff - * between the base and B. Note that we pick one - * merge base at random if there are more than one. + else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) { + /* diff A...B where there is one sane merge base between + * A and B. We have ent[0] == merge-base, ent[1] == A, + * and ent[2] == B. Show diff between the base and B. */ - ent[1] = ent[ents-1]; + ent[1] = ent[2]; result = builtin_diff_tree(&rev, argc, argv, ent); - } else + } + else result = builtin_diff_combined(&rev, argc, argv, - ent, ents); + ent, ents); result = diff_result_code(&rev.diffopt, result); if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); diff -Nru git-1.7.4.1/builtin/diff-files.c git-1.7.1/builtin/diff-files.c --- git-1.7.4.1/builtin/diff-files.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/diff-files.c 2010-04-24 02:38:35.000000000 +0000 @@ -8,7 +8,6 @@ #include "commit.h" #include "revision.h" #include "builtin.h" -#include "submodule.h" static const char diff_files_usage[] = "git diff-files [-q] [-0/-1/2/3 |-c|--cc] [] [...]" @@ -21,7 +20,6 @@ unsigned options = 0; init_revisions(&rev, prefix); - gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; diff -Nru git-1.7.4.1/builtin/diff-index.c git-1.7.1/builtin/diff-index.c --- git-1.7.4.1/builtin/diff-index.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/diff-index.c 2010-04-24 02:38:35.000000000 +0000 @@ -3,7 +3,6 @@ #include "commit.h" #include "revision.h" #include "builtin.h" -#include "submodule.h" static const char diff_cache_usage[] = "git diff-index [-m] [--cached] " @@ -18,7 +17,6 @@ int result; init_revisions(&rev, prefix); - gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; diff -Nru git-1.7.4.1/builtin/diff-tree.c git-1.7.1/builtin/diff-tree.c --- git-1.7.4.1/builtin/diff-tree.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/diff-tree.c 2010-04-24 02:38:35.000000000 +0000 @@ -3,7 +3,6 @@ #include "commit.h" #include "log-tree.h" #include "builtin.h" -#include "submodule.h" static struct rev_info log_tree_opt; @@ -113,7 +112,6 @@ int read_stdin = 0; init_revisions(opt, prefix); - gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ opt->abbrev = 0; opt->diff = 1; diff -Nru git-1.7.4.1/builtin/fast-export.c git-1.7.1/builtin/fast-export.c --- git-1.7.4.1/builtin/fast-export.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/fast-export.c 2010-04-24 02:38:35.000000000 +0000 @@ -27,7 +27,6 @@ static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT; static int fake_missing_tagger; static int no_data; -static int full_tree; static int parse_opt_signed_tag_mode(const struct option *opt, const char *arg, int unset) @@ -148,47 +147,10 @@ free(buf); } -static int depth_first(const void *a_, const void *b_) -{ - const struct diff_filepair *a = *((const struct diff_filepair **)a_); - const struct diff_filepair *b = *((const struct diff_filepair **)b_); - const char *name_a, *name_b; - int len_a, len_b, len; - int cmp; - - name_a = a->one ? a->one->path : a->two->path; - name_b = b->one ? b->one->path : b->two->path; - - len_a = strlen(name_a); - len_b = strlen(name_b); - len = (len_a < len_b) ? len_a : len_b; - - /* strcmp will sort 'd' before 'd/e', we want 'd/e' before 'd' */ - cmp = memcmp(name_a, name_b, len); - if (cmp) - return cmp; - cmp = len_b - len_a; - if (cmp) - return cmp; - /* - * Move 'R'ename entries last so that all references of the file - * appear in the output before it is renamed (e.g., when a file - * was copied and renamed in the same commit). - */ - return (a->status == 'R') - (b->status == 'R'); -} - static void show_filemodify(struct diff_queue_struct *q, struct diff_options *options, void *data) { int i; - - /* - * Handle files below a directory first, in case they are all deleted - * and the directory changes to a file or symlink. - */ - qsort(q->queue, q->nr, sizeof(q->queue[0]), depth_first); - for (i = 0; i < q->nr; i++) { struct diff_filespec *ospec = q->queue[i]->one; struct diff_filespec *spec = q->queue[i]->two; @@ -279,8 +241,7 @@ message += 2; if (commit->parents && - get_object_mark(&commit->parents->item->object) != 0 && - !full_tree) { + get_object_mark(&commit->parents->item->object) != 0) { parse_commit(commit->parents->item); diff_tree_sha1(commit->parents->item->tree->object.sha1, commit->tree->object.sha1, "", &rev->diffopt); @@ -320,8 +281,6 @@ i++; } - if (full_tree) - printf("deleteall\n"); log_tree_diff_flush(rev); rev->diffopt.output_format = saved_output_format; @@ -479,7 +438,7 @@ /* handle nested tags */ while (tag && tag->object.type == OBJ_TAG) { parse_object(tag->object.sha1); - string_list_append(extra_refs, full_name)->util = tag; + string_list_append(full_name, extra_refs)->util = tag; tag = (struct tag *)tag->tagged; } if (!tag) @@ -505,7 +464,7 @@ } if (commit->util) /* more than one name for the same object */ - string_list_append(extra_refs, full_name)->util = commit; + string_list_append(full_name, extra_refs)->util = commit; else commit->util = full_name; } @@ -606,8 +565,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) { struct rev_info revs; - struct object_array commits = OBJECT_ARRAY_INIT; - struct string_list extra_refs = STRING_LIST_INIT_NODUP; + struct object_array commits = { 0, 0, NULL }; + struct string_list extra_refs = { NULL, 0, 0, 0 }; struct commit *commit; char *export_filename = NULL, *import_filename = NULL; struct option options[] = { @@ -625,8 +584,6 @@ "Import marks from this file"), OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger, "Fake a tagger when tags lack one"), - OPT_BOOLEAN(0, "full-tree", &full_tree, - "Output full tree for each commit"), { OPTION_NEGBIT, 0, "data", &no_data, NULL, "Skip output of blob data", PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 }, @@ -651,9 +608,6 @@ if (import_filename) import_marks(import_filename); - if (import_filename && revs.prune_data) - full_tree = 1; - get_tags_and_duplicates(&revs.pending, &extra_refs); if (prepare_revision_walk(&revs)) diff -Nru git-1.7.4.1/builtin/fetch.c git-1.7.1/builtin/fetch.c --- git-1.7.4.1/builtin/fetch.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/fetch.c 2010-04-24 02:38:35.000000000 +0000 @@ -12,12 +12,11 @@ #include "parse-options.h" #include "sigchain.h" #include "transport.h" -#include "submodule.h" static const char * const builtin_fetch_usage[] = { "git fetch [] [ [...]]", "git fetch [] ", - "git fetch --multiple [] [( | )...]", + "git fetch --multiple [] [ | ]...", "git fetch --all []", NULL }; @@ -28,20 +27,13 @@ TAGS_SET = 2 }; -enum { - RECURSE_SUBMODULES_OFF = 0, - RECURSE_SUBMODULES_DEFAULT = 1, - RECURSE_SUBMODULES_ON = 2 -}; - static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity; -static int progress, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; +static int progress; static int tags = TAGS_DEFAULT; static const char *depth; static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; static struct transport *transport; -static const char *submodule_prefix = ""; static struct option builtin_fetch_options[] = { OPT__VERBOSITY(&verbosity), @@ -51,7 +43,8 @@ "append to .git/FETCH_HEAD instead of overwriting"), OPT_STRING(0, "upload-pack", &upload_pack, "PATH", "path to upload pack on remote end"), - OPT__FORCE(&force, "force overwrite of local branch"), + OPT_BOOLEAN('f', "force", &force, + "force overwrite of local branch"), OPT_BOOLEAN('m', "multiple", &multiple, "fetch from multiple remotes"), OPT_SET_INT('t', "tags", &tags, @@ -59,10 +52,7 @@ OPT_SET_INT('n', NULL, &tags, "do not fetch all tags (--no-tags)", TAGS_UNSET), OPT_BOOLEAN('p', "prune", &prune, - "prune remote-tracking branches no longer on remote"), - OPT_SET_INT(0, "recurse-submodules", &recurse_submodules, - "control recursive fetching of submodules", - RECURSE_SUBMODULES_ON), + "prune tracking branches no longer on remote"), OPT_BOOLEAN(0, "dry-run", &dry_run, "dry run"), OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"), @@ -71,8 +61,6 @@ OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"), OPT_STRING(0, "depth", &depth, "DEPTH", "deepen history of shallow clone"), - { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR", - "prepend this to submodule path output", PARSE_OPT_HIDDEN }, OPT_END() }; @@ -110,7 +98,7 @@ continue; /* - * Not fetched to a remote-tracking branch? We need to fetch + * Not fetched to a tracking branch? We need to fetch * it anyway to allow this branch's "branch.$name.merge" * to be honored by 'git pull', but we do not have to * fail if branch.$name.merge is misconfigured to point @@ -158,10 +146,7 @@ struct remote *remote = transport->remote; struct branch *branch = branch_get(NULL); int has_merge = branch_has_merge_config(branch); - if (remote && - (remote->fetch_refspec_nr || - /* Note: has_merge implies non-NULL branch->remote_name */ - (has_merge && !strcmp(branch->remote_name, remote->name)))) { + if (remote && (remote->fetch_refspec_nr || has_merge)) { for (i = 0; i < remote->fetch_refspec_nr; i++) { get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0); if (remote->fetch[i].dst && @@ -175,8 +160,6 @@ * if the remote we're fetching from is the same * as given in branch..remote, we add the * ref given in branch..merge, too. - * - * Note: has_merge implies non-NULL branch->remote_name */ if (has_merge && !strcmp(branch->remote_name, remote->name)) @@ -371,7 +354,7 @@ what = rm->name + 10; } else if (!prefixcmp(rm->name, "refs/remotes/")) { - kind = "remote-tracking branch"; + kind = "remote branch"; what = rm->name + 13; } else { @@ -545,7 +528,7 @@ int flag, void *cbdata) { struct string_list *list = (struct string_list *)cbdata; - struct string_list_item *item = string_list_insert(list, refname); + struct string_list_item *item = string_list_insert(refname, list); item->util = (void *)sha1; return 0; } @@ -561,12 +544,37 @@ return 0; } +struct tag_data { + struct ref **head; + struct ref ***tail; +}; + +static int add_to_tail(struct string_list_item *item, void *cb_data) +{ + struct tag_data *data = (struct tag_data *)cb_data; + struct ref *rm = NULL; + + /* We have already decided to ignore this item */ + if (!item->util) + return 0; + + rm = alloc_ref(item->string); + rm->peer_ref = alloc_ref(item->string); + hashcpy(rm->old_sha1, item->util); + + **data->tail = rm; + *data->tail = &rm->next; + + return 0; +} + static void find_non_local_tags(struct transport *transport, struct ref **head, struct ref ***tail) { - struct string_list existing_refs = STRING_LIST_INIT_NODUP; - struct string_list remote_refs = STRING_LIST_INIT_NODUP; + struct string_list existing_refs = { NULL, 0, 0, 0 }; + struct string_list remote_refs = { NULL, 0, 0, 0 }; + struct tag_data data = {head, tail}; const struct ref *ref; struct string_list_item *item = NULL; @@ -608,7 +616,7 @@ string_list_has_string(&existing_refs, ref->name)) continue; - item = string_list_insert(&remote_refs, ref->name); + item = string_list_insert(ref->name, &remote_refs); item->util = (void *)ref->old_sha1; } string_list_clear(&existing_refs, 0); @@ -622,20 +630,10 @@ item->util = NULL; /* - * For all the tags in the remote_refs string list, - * add them to the list of refs to be fetched + * For all the tags in the remote_refs string list, call + * add_to_tail to add them to the list of refs to be fetched */ - for_each_string_list_item(item, &remote_refs) { - /* Unless we have already decided to ignore this item... */ - if (item->util) - { - struct ref *rm = alloc_ref(item->string); - rm->peer_ref = alloc_ref(item->string); - hashcpy(rm->old_sha1, item->util); - **tail = rm; - *tail = &rm->next; - } - } + for_each_string_list(add_to_tail, &remote_refs, &data); string_list_clear(&remote_refs, 0); } @@ -668,7 +666,7 @@ static int do_fetch(struct transport *transport, struct refspec *refs, int ref_count) { - struct string_list existing_refs = STRING_LIST_INIT_NODUP; + struct string_list existing_refs = { NULL, 0, 0, 0 }; struct string_list_item *peer_item = NULL; struct ref *ref_map; struct ref *rm; @@ -676,12 +674,10 @@ for_each_ref(add_existing, &existing_refs); - if (tags == TAGS_DEFAULT) { - if (transport->remote->fetch_tags == 2) - tags = TAGS_SET; - if (transport->remote->fetch_tags == -1) - tags = TAGS_UNSET; - } + if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET) + tags = TAGS_SET; + if (transport->remote->fetch_tags == -1) + tags = TAGS_UNSET; if (!transport->get_refs_list || !transport->fetch) die("Don't know how to fetch from %s", transport->url); @@ -699,8 +695,8 @@ for (rm = ref_map; rm; rm = rm->next) { if (rm->peer_ref) { - peer_item = string_list_lookup(&existing_refs, - rm->peer_ref->name); + peer_item = string_list_lookup(rm->peer_ref->name, + &existing_refs); if (peer_item) hashcpy(rm->peer_ref->old_sha1, peer_item->util); @@ -749,7 +745,7 @@ { struct string_list *list = priv; if (!remote->skip_default_update) - string_list_append(list, remote->name); + string_list_append(remote->name, list); return 0; } @@ -768,8 +764,8 @@ int space = strcspn(value, " \t\n"); while (*value) { if (space > 1) { - string_list_append(g->list, - xstrndup(value, space)); + string_list_append(xstrndup(value, space), + g->list); } value += space + (value[space] != '\0'); space = strcspn(value, " \t\n"); @@ -782,8 +778,7 @@ static int add_remote_or_group(const char *name, struct string_list *list) { int prev_nr = list->nr; - struct remote_group_data g; - g.name = name; g.list = list; + struct remote_group_data g = { name, list }; git_config(get_remote_group, &g); if (list->nr == prev_nr) { @@ -791,41 +786,33 @@ if (!remote_is_configured(name)) return 0; remote = remote_get(name); - string_list_append(list, remote->name); + string_list_append(remote->name, list); } return 1; } -static void add_options_to_argv(int *argc, const char **argv) +static int fetch_multiple(struct string_list *list) { + int i, result = 0; + const char *argv[11] = { "fetch", "--append" }; + int argc = 2; + if (dry_run) - argv[(*argc)++] = "--dry-run"; + argv[argc++] = "--dry-run"; if (prune) - argv[(*argc)++] = "--prune"; + argv[argc++] = "--prune"; if (update_head_ok) - argv[(*argc)++] = "--update-head-ok"; + argv[argc++] = "--update-head-ok"; if (force) - argv[(*argc)++] = "--force"; + argv[argc++] = "--force"; if (keep) - argv[(*argc)++] = "--keep"; - if (recurse_submodules == RECURSE_SUBMODULES_ON) - argv[(*argc)++] = "--recurse-submodules"; + argv[argc++] = "--keep"; if (verbosity >= 2) - argv[(*argc)++] = "-v"; + argv[argc++] = "-v"; if (verbosity >= 1) - argv[(*argc)++] = "-v"; + argv[argc++] = "-v"; else if (verbosity < 0) - argv[(*argc)++] = "-q"; - -} - -static int fetch_multiple(struct string_list *list) -{ - int i, result = 0; - const char *argv[12] = { "fetch", "--append" }; - int argc = 2; - - add_options_to_argv(&argc, argv); + argv[argc++] = "-q"; if (!append && !dry_run) { int errcode = truncate_fetch_head(); @@ -856,8 +843,7 @@ int exit_code; if (!remote) - die("No remote repository specified. Please, specify either a URL or a\n" - "remote name from which new revisions should be fetched."); + die("Where do you want to fetch from today?"); transport = transport_get(remote, NULL); transport_set_verbosity(transport, verbosity, progress); @@ -902,7 +888,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) { int i; - struct string_list list = STRING_LIST_INIT_NODUP; + struct string_list list = { NULL, 0, 0, 0 }; struct remote *remote; int result = 0; @@ -946,21 +932,6 @@ } } - if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { - const char *options[10]; - int num_options = 0; - /* Set recursion as default when we already are recursing */ - if (submodule_prefix[0]) - set_config_fetch_recurse_submodules(1); - gitmodules_config(); - git_config(submodule_config, NULL); - add_options_to_argv(&num_options, options); - result = fetch_populated_submodules(num_options, options, - submodule_prefix, - recurse_submodules == RECURSE_SUBMODULES_ON, - verbosity < 0); - } - /* All names were strdup()ed or strndup()ed */ list.strdup_strings = 1; string_list_clear(&list, 0); diff -Nru git-1.7.4.1/builtin/fetch-pack.c git-1.7.1/builtin/fetch-pack.c --- git-1.7.4.1/builtin/fetch-pack.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/fetch-pack.c 2010-04-24 02:38:35.000000000 +0000 @@ -47,7 +47,7 @@ if (parse_commit(commit)) return; - commit_list_insert_by_date(commit, &rev_list); + insert_by_date(commit, &rev_list); if (!(commit->object.flags & COMMON)) non_common_revs++; @@ -436,7 +436,7 @@ if (o && o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; commit->object.flags |= COMPLETE; - commit_list_insert_by_date(commit, &complete); + insert_by_date(commit, &complete); } return 0; } diff -Nru git-1.7.4.1/builtin/fmt-merge-msg.c git-1.7.1/builtin/fmt-merge-msg.c --- git-1.7.4.1/builtin/fmt-merge-msg.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/fmt-merge-msg.c 2010-04-24 02:38:35.000000000 +0000 @@ -7,22 +7,21 @@ #include "string-list.h" static const char * const fmt_merge_msg_usage[] = { - "git fmt-merge-msg [-m ] [--log[=]|--no-log] [--file ]", + "git fmt-merge-msg [--log|--no-log] [--file ]", NULL }; -static int shortlog_len; +static int merge_summary; static int fmt_merge_msg_config(const char *key, const char *value, void *cb) { - if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) { - int is_bool; - shortlog_len = git_config_bool_or_int(key, value, &is_bool); - if (!is_bool && shortlog_len < 0) - return error("%s: negative length %s", key, value); - if (is_bool && shortlog_len) - shortlog_len = DEFAULT_MERGE_LOG_LEN; + static int found_merge_log = 0; + if (!strcmp("merge.log", key)) { + found_merge_log = 1; + merge_summary = git_config_bool(key, value); } + if (!found_merge_log && !strcmp("merge.summary", key)) + merge_summary = git_config_bool(key, value); return 0; } @@ -39,8 +38,8 @@ data->generic.strdup_strings = 1; } -static struct string_list srcs = STRING_LIST_INIT_DUP; -static struct string_list origins = STRING_LIST_INIT_DUP; +static struct string_list srcs = { NULL, 0, 0, 1 }; +static struct string_list origins = { NULL, 0, 0, 1 }; static int handle_line(char *line) { @@ -83,7 +82,7 @@ item = unsorted_string_list_lookup(&srcs, src); if (!item) { - item = string_list_append(&srcs, src); + item = string_list_append(src, &srcs); item->util = xcalloc(1, sizeof(struct src_data)); init_src_data(item->util); } @@ -94,19 +93,19 @@ src_data->head_status |= 1; } else if (!prefixcmp(line, "branch ")) { origin = line + 7; - string_list_append(&src_data->branch, origin); + string_list_append(origin, &src_data->branch); src_data->head_status |= 2; } else if (!prefixcmp(line, "tag ")) { origin = line; - string_list_append(&src_data->tag, origin + 4); + string_list_append(origin + 4, &src_data->tag); src_data->head_status |= 2; - } else if (!prefixcmp(line, "remote-tracking branch ")) { - origin = line + strlen("remote-tracking branch "); - string_list_append(&src_data->r_branch, origin); + } else if (!prefixcmp(line, "remote branch ")) { + origin = line + 14; + string_list_append(origin, &src_data->r_branch); src_data->head_status |= 2; } else { origin = src; - string_list_append(&src_data->generic, line); + string_list_append(line, &src_data->generic); src_data->head_status |= 2; } @@ -119,7 +118,7 @@ sprintf(new_origin, "%s of %s", origin, src); origin = new_origin; } - string_list_append(&origins, origin)->util = sha1; + string_list_append(origin, &origins)->util = sha1; return 0; } @@ -147,7 +146,7 @@ int i, count = 0; struct commit *commit; struct object *branch; - struct string_list subjects = STRING_LIST_INIT_DUP; + struct string_list subjects = { NULL, 0, 0, 1 }; int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED; struct strbuf sb = STRBUF_INIT; @@ -177,10 +176,10 @@ strbuf_ltrim(&sb); if (!sb.len) - string_list_append(&subjects, - sha1_to_hex(commit->object.sha1)); + string_list_append(sha1_to_hex(commit->object.sha1), + &subjects); else - string_list_append(&subjects, strbuf_detach(&sb, NULL)); + string_list_append(strbuf_detach(&sb, NULL), &subjects); } if (count > limit) @@ -203,10 +202,35 @@ string_list_clear(&subjects, 0); } -static void do_fmt_merge_msg_title(struct strbuf *out, - const char *current_branch) { - int i = 0; +int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) { + int limit = 20, i = 0, pos = 0; char *sep = ""; + unsigned char head_sha1[20]; + const char *current_branch; + + /* get current branch */ + current_branch = resolve_ref("HEAD", head_sha1, 1, NULL); + if (!current_branch) + die("No current branch"); + if (!prefixcmp(current_branch, "refs/heads/")) + current_branch += 11; + + /* get a line */ + while (pos < in->len) { + int len; + char *newline, *p = in->buf + pos; + + newline = strchr(p, '\n'); + len = newline ? newline - p : strlen(p); + pos += len + !!newline; + i++; + p[len] = 0; + if (handle_line(p)) + die ("Error in line %d: %.*s", i, len, p); + } + + if (!srcs.nr) + return 0; strbuf_addstr(out, "Merge "); for (i = 0; i < srcs.nr; i++) { @@ -233,7 +257,7 @@ if (src_data->r_branch.nr) { strbuf_addstr(out, subsep); subsep = ", "; - print_joined("remote-tracking branch ", "remote-tracking branches ", + print_joined("remote branch ", "remote branches ", &src_data->r_branch, out); } if (src_data->tag.nr) { @@ -254,42 +278,8 @@ strbuf_addch(out, '\n'); else strbuf_addf(out, " into %s\n", current_branch); -} - -static int do_fmt_merge_msg(int merge_title, struct strbuf *in, - struct strbuf *out, int shortlog_len) { - int i = 0, pos = 0; - unsigned char head_sha1[20]; - const char *current_branch; - - /* get current branch */ - current_branch = resolve_ref("HEAD", head_sha1, 1, NULL); - if (!current_branch) - die("No current branch"); - if (!prefixcmp(current_branch, "refs/heads/")) - current_branch += 11; - - /* get a line */ - while (pos < in->len) { - int len; - char *newline, *p = in->buf + pos; - newline = strchr(p, '\n'); - len = newline ? newline - p : strlen(p); - pos += len + !!newline; - i++; - p[len] = 0; - if (handle_line(p)) - die ("Error in line %d: %.*s", i, len, p); - } - - if (!srcs.nr) - return 0; - - if (merge_title) - do_fmt_merge_msg_title(out, current_branch); - - if (shortlog_len) { + if (merge_summary) { struct commit *head; struct rev_info rev; @@ -299,35 +289,21 @@ rev.ignore_merges = 1; rev.limited = 1; - if (suffixcmp(out->buf, "\n")) - strbuf_addch(out, '\n'); - for (i = 0; i < origins.nr; i++) shortlog(origins.items[i].string, origins.items[i].util, - head, &rev, shortlog_len, out); + head, &rev, limit, out); } return 0; } -int fmt_merge_msg(struct strbuf *in, struct strbuf *out, - int merge_title, int shortlog_len) { - return do_fmt_merge_msg(merge_title, in, out, shortlog_len); -} - int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) { const char *inpath = NULL; - const char *message = NULL; struct option options[] = { - { OPTION_INTEGER, 0, "log", &shortlog_len, "n", - "populate log with at most entries from shortlog", - PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, - { OPTION_INTEGER, 0, "summary", &shortlog_len, "n", + OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"), + { OPTION_BOOLEAN, 0, "summary", &merge_summary, NULL, "alias for --log (deprecated)", - PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL, - DEFAULT_MERGE_LOG_LEN }, - OPT_STRING('m', "message", &message, "text", - "use as start of message"), + PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, OPT_FILENAME('F', "file", &inpath, "file to read from"), OPT_END() }; @@ -341,14 +317,6 @@ 0); if (argc > 0) usage_with_options(fmt_merge_msg_usage, options); - if (message && !shortlog_len) { - char nl = '\n'; - write_in_full(STDOUT_FILENO, message, strlen(message)); - write_in_full(STDOUT_FILENO, &nl, 1); - return 0; - } - if (shortlog_len < 0) - die("Negative --log=%d", shortlog_len); if (inpath && strcmp(inpath, "-")) { in = fopen(inpath, "r"); @@ -358,13 +326,7 @@ if (strbuf_read(&input, fileno(in), 0) < 0) die_errno("could not read input file"); - - if (message) - strbuf_addstr(&output, message); - ret = fmt_merge_msg(&input, &output, - message ? 0 : 1, - shortlog_len); - + ret = fmt_merge_msg(merge_summary, &input, &output); if (ret) return ret; write_in_full(STDOUT_FILENO, output.buf, output.len); diff -Nru git-1.7.4.1/builtin/for-each-ref.c git-1.7.1/builtin/for-each-ref.c --- git-1.7.4.1/builtin/for-each-ref.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/for-each-ref.c 2010-04-24 02:38:35.000000000 +0000 @@ -227,10 +227,6 @@ strcpy(s, sha1_to_hex(obj->sha1)); v->s = s; } - else if (!strcmp(name, "objectname:short")) { - v->s = xstrdup(find_unique_abbrev(obj->sha1, - DEFAULT_ABBREV)); - } } } @@ -553,10 +549,10 @@ grab_person("committer", val, deref, obj, buf, sz); break; case OBJ_TREE: - /* grab_tree_values(val, deref, obj, buf, sz); */ + // grab_tree_values(val, deref, obj, buf, sz); break; case OBJ_BLOB: - /* grab_blob_values(val, deref, obj, buf, sz); */ + // grab_blob_values(val, deref, obj, buf, sz); break; default: die("Eh? Object of type %d?", obj->type); diff -Nru git-1.7.4.1/builtin/fsck.c git-1.7.1/builtin/fsck.c --- git-1.7.4.1/builtin/fsck.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/fsck.c 2010-04-24 02:38:35.000000000 +0000 @@ -74,13 +74,7 @@ { struct object *parent = data; - /* - * The only case data is NULL or type is OBJ_ANY is when - * mark_object_reachable() calls us. All the callers of - * that function has non-NULL obj hence ... - */ if (!obj) { - /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", typename(parent->type), sha1_to_hex(parent->sha1)); printf("broken link from %7s %s\n", @@ -90,7 +84,6 @@ } if (type != OBJ_ANY && obj->type != type) - /* ... and the reference to parent is safe here */ objerror(parent, "wrong object type in link"); if (obj->flags & REACHABLE) @@ -116,7 +109,7 @@ mark_object(obj, OBJ_ANY, NULL); } -static int traverse_one_object(struct object *obj) +static int traverse_one_object(struct object *obj, struct object *parent) { int result; struct tree *tree = NULL; @@ -145,7 +138,7 @@ entry = pending.objects + --pending.nr; obj = entry->item; parent = (struct object *) entry->name; - result |= traverse_one_object(obj); + result |= traverse_one_object(obj, parent); } return !!result; } @@ -392,20 +385,10 @@ sha1_list.nr = ++nr; } -static inline int is_loose_object_file(struct dirent *de, - char *name, unsigned char *sha1) -{ - if (strlen(de->d_name) != 38) - return 0; - memcpy(name + 2, de->d_name, 39); - return !get_sha1_hex(name, sha1); -} - static void fsck_dir(int i, char *path) { DIR *dir = opendir(path); struct dirent *de; - char name[100]; if (!dir) return; @@ -413,13 +396,17 @@ if (verbose) fprintf(stderr, "Checking directory %s\n", path); - sprintf(name, "%02x", i); while ((de = readdir(dir)) != NULL) { + char name[100]; unsigned char sha1[20]; if (is_dot_or_dotdot(de->d_name)) continue; - if (is_loose_object_file(de, name, sha1)) { + if (strlen(de->d_name) == 38) { + sprintf(name, "%02x", i); + memcpy(name+2, de->d_name, 39); + if (get_sha1_hex(name, sha1) < 0) + break; add_sha1_list(sha1, DIRENT_SORT_HINT(de)); continue; } @@ -569,8 +556,8 @@ sha1_to_hex(it->sha1)); return 1; } - obj->used = 1; mark_object_reachable(obj); + obj->used = 1; if (obj->type != OBJ_TREE) err |= objerror(obj, "non-tree in cache-tree"); } @@ -585,7 +572,7 @@ }; static struct option fsck_opts[] = { - OPT__VERBOSE(&verbose, "be verbose"), + OPT__VERBOSE(&verbose), OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"), OPT_BOOLEAN(0, "tags", &show_tags, "report tags"), OPT_BOOLEAN(0, "root", &show_root, "report root nodes"), diff -Nru git-1.7.4.1/builtin/gc.c git-1.7.1/builtin/gc.c --- git-1.7.4.1/builtin/gc.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/gc.c 2010-04-24 02:38:35.000000000 +0000 @@ -180,7 +180,7 @@ char buf[80]; struct option builtin_gc_options[] = { - OPT__QUIET(&quiet, "suppress progress reporting"), + OPT__QUIET(&quiet), { OPTION_STRING, 0, "prune", &prune_expire, "date", "prune unreferenced objects", PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire }, @@ -189,9 +189,6 @@ OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_gc_usage, builtin_gc_options); - git_config(gc_config, NULL); if (pack_refs < 0) diff -Nru git-1.7.4.1/builtin/grep.c git-1.7.1/builtin/grep.c --- git-1.7.4.1/builtin/grep.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/grep.c 2010-04-24 02:38:35.000000000 +0000 @@ -11,16 +11,18 @@ #include "tree-walk.h" #include "builtin.h" #include "parse-options.h" -#include "string-list.h" -#include "run-command.h" #include "userdiff.h" #include "grep.h" #include "quote.h" #include "dir.h" + +#ifndef NO_PTHREADS #include "thread-utils.h" +#include +#endif static char const * const grep_usage[] = { - "git grep [options] [-e] [...] [[--] ...]", + "git grep [options] [-e] [...] [[--] path...]", NULL }; @@ -554,33 +556,6 @@ } } -static void append_path(struct grep_opt *opt, const void *data, size_t len) -{ - struct string_list *path_list = opt->output_priv; - - if (len == 1 && *(const char *)data == '\0') - return; - string_list_append(path_list, xstrndup(data, len)); -} - -static void run_pager(struct grep_opt *opt, const char *prefix) -{ - struct string_list *path_list = opt->output_priv; - const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1)); - int i, status; - - for (i = 0; i < path_list->nr; i++) - argv[i] = path_list->items[i].string; - argv[path_list->nr] = NULL; - - if (prefix && chdir(prefix)) - die("Failed to chdir: %s", prefix); - status = run_command_v_opt(argv, RUN_USING_SHELL); - if (status) - exit(status); - free(argv); -} - static int grep_cache(struct grep_opt *opt, const char **paths, int cached) { int hit = 0; @@ -615,6 +590,7 @@ if (hit && opt->status_only) break; } + free_grep_patterns(opt); return hit; } @@ -699,25 +675,6 @@ die("unable to grep from object of type %s", typename(obj->type)); } -static int grep_objects(struct grep_opt *opt, const char **paths, - const struct object_array *list) -{ - unsigned int i; - int hit = 0; - const unsigned int nr = list->nr; - - for (i = 0; i < nr; i++) { - struct object *real_obj; - real_obj = deref_tag(list->objects[i].item, NULL, 0); - if (grep_object(opt, paths, real_obj, list->objects[i].name)) { - hit = 1; - if (opt->status_only) - break; - } - } - return hit; -} - static int grep_directory(struct grep_opt *opt, const char **paths) { struct dir_struct dir; @@ -732,6 +689,7 @@ if (hit && opt->status_only) break; } + free_grep_patterns(opt); return hit; } @@ -766,15 +724,11 @@ if (!patterns) die_errno("cannot open '%s'", arg); while (strbuf_getline(&sb, patterns, '\n') == 0) { - char *s; - size_t len; - /* ignore empty line like grep does */ if (sb.len == 0) continue; - - s = strbuf_detach(&sb, &len); - append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN); + append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg, + ++lno, GREP_PATTERN); } fclose(patterns); strbuf_release(&sb); @@ -828,14 +782,12 @@ int cached = 0; int seen_dashdash = 0; int external_grep_allowed__ignored; - const char *show_in_pager = NULL, *default_pager = "dummy"; struct grep_opt opt; - struct object_array list = OBJECT_ARRAY_INIT; + struct object_array list = { 0, 0, NULL }; const char **paths = NULL; - struct string_list path_list = STRING_LIST_INIT_NODUP; int i; int dummy; - int use_index = 1; + int nongit = 0, use_index = 1; struct option options[] = { OPT_BOOLEAN(0, "cached", &cached, "search in index instead of in the work tree"), @@ -911,14 +863,11 @@ { OPTION_CALLBACK, ')', NULL, &opt, NULL, "", PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH, close_callback }, - OPT__QUIET(&opt.status_only, - "indicate hit with exit status without output"), + OPT_BOOLEAN('q', "quiet", &opt.status_only, + "indicate hit with exit status without output"), OPT_BOOLEAN(0, "all-match", &opt.all_match, "show only matches from files that match all patterns"), OPT_GROUP(""), - { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager, - "pager", "show matching files in the pager", - PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager }, OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored, "allow calling of grep(1) (ignored by this build)"), { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage", @@ -926,6 +875,8 @@ OPT_END() }; + prefix = setup_git_directory_gently(&nongit); + /* * 'git grep -h', unlike 'git grep -h ', is a request * to show usage information and exit. @@ -970,7 +921,7 @@ PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_NO_INTERNAL_HELP); - if (use_index && !startup_info->have_repository) + if (use_index && nongit) /* die the same way as if we did it at the beginning */ setup_git_directory(); @@ -992,18 +943,6 @@ argc--; } - if (show_in_pager == default_pager) - show_in_pager = git_pager(1); - if (show_in_pager) { - opt.color = 0; - opt.name_only = 1; - opt.null_following_name = 1; - opt.output_priv = &path_list; - opt.output = append_path; - string_list_append(&path_list, show_in_pager); - use_threads = 0; - } - if (!opt.pattern_list) die("no pattern given."); if (!opt.fixed && opt.ignore_case) @@ -1060,51 +999,44 @@ paths[1] = NULL; } - if (show_in_pager && (cached || list.nr)) - die("--open-files-in-pager only works on the worktree"); - - if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) { - const char *pager = path_list.items[0].string; - int len = strlen(pager); - - if (len > 4 && is_dir_sep(pager[len - 5])) - pager += len - 4; - - if (!strcmp("less", pager) || !strcmp("vi", pager)) { - struct strbuf buf = STRBUF_INIT; - strbuf_addf(&buf, "+/%s%s", - strcmp("less", pager) ? "" : "*", - opt.pattern_list->pattern); - string_list_append(&path_list, buf.buf); - strbuf_detach(&buf, NULL); - } - } - - if (!show_in_pager) - setup_pager(); - - if (!use_index) { + int hit; if (cached) die("--cached cannot be used with --no-index."); if (list.nr) die("--no-index cannot be used with revs."); hit = grep_directory(&opt, paths); - } else if (!list.nr) { + if (use_threads) + hit |= wait_all(); + return !hit; + } + + if (!list.nr) { + int hit; if (!cached) setup_work_tree(); hit = grep_cache(&opt, paths, cached); - } else { - if (cached) - die("both --cached and trees are given."); - hit = grep_objects(&opt, paths, &list); + if (use_threads) + hit |= wait_all(); + return !hit; + } + + if (cached) + die("both --cached and trees are given."); + + for (i = 0; i < list.nr; i++) { + struct object *real_obj; + real_obj = deref_tag(list.objects[i].item, NULL, 0); + if (grep_object(&opt, paths, real_obj, list.objects[i].name)) { + hit = 1; + if (opt.status_only) + break; + } } if (use_threads) hit |= wait_all(); - if (hit && show_in_pager) - run_pager(&opt, prefix); free_grep_patterns(&opt); return !hit; } diff -Nru git-1.7.4.1/builtin/help.c git-1.7.1/builtin/help.c --- git-1.7.4.1/builtin/help.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/help.c 2010-04-24 02:38:35.000000000 +0000 @@ -26,7 +26,7 @@ HELP_FORMAT_NONE, HELP_FORMAT_MAN, HELP_FORMAT_INFO, - HELP_FORMAT_WEB + HELP_FORMAT_WEB, }; static int show_all = 0; @@ -120,7 +120,7 @@ if (!path) path = "emacsclient"; strbuf_addf(&man_page, "(woman \"%s\")", page); - execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL); + execlp(path, "emacsclient", "-e", man_page.buf, NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } } @@ -148,7 +148,7 @@ } else path = "kfmclient"; strbuf_addf(&man_page, "man:%s(1)", page); - execlp(path, filename, "newTab", man_page.buf, (char *)NULL); + execlp(path, filename, "newTab", man_page.buf, NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } } @@ -157,7 +157,7 @@ { if (!path) path = "man"; - execlp(path, "man", page, (char *)NULL); + execlp(path, "man", page, NULL); warning("failed to exec '%s': %s", path, strerror(errno)); } @@ -165,7 +165,7 @@ { struct strbuf shell_cmd = STRBUF_INIT; strbuf_addf(&shell_cmd, "%s %s", cmd, page); - execl("/bin/sh", "sh", "-c", shell_cmd.buf, (char *)NULL); + execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); warning("failed to exec '%s': %s", cmd, strerror(errno)); } @@ -372,7 +372,7 @@ { const char *page = cmd_to_page(git_cmd); setenv("INFOPATH", system_path(GIT_INFO_PATH), 1); - execlp("info", "info", "gitman", page, (char *)NULL); + execlp("info", "info", "gitman", page, NULL); die("no info viewer handled the request"); } @@ -398,7 +398,7 @@ #ifndef open_html static void open_html(const char *path) { - execl_git_cmd("web--browse", "-c", "help.browser", path, (char *)NULL); + execl_git_cmd("web--browse", "-c", "help.browser", path, NULL); } #endif diff -Nru git-1.7.4.1/builtin/index-pack.c git-1.7.1/builtin/index-pack.c --- git-1.7.4.1/builtin/index-pack.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/index-pack.c 2010-04-24 02:38:35.000000000 +0000 @@ -11,7 +11,7 @@ #include "exec_cmd.h" static const char index_pack_usage[] = -"git index-pack [-v] [-o ] [ --keep | --keep= ] [--strict] ( | --stdin [--fix-thin] [])"; +"git index-pack [-v] [-o ] [{ ---keep | --keep= }] [--strict] { | --stdin [--fix-thin] [] }"; struct object_entry { @@ -161,7 +161,7 @@ input_offset += bytes; /* make sure off_t is sufficiently large not to wrap */ - if (signed_add_overflows(consumed_bytes, bytes)) + if (consumed_bytes > consumed_bytes + bytes) die("pack too large for current definition of off_t"); consumed_bytes += bytes; } @@ -266,23 +266,26 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size) { - int status; z_stream stream; void *buf = xmalloc(size); memset(&stream, 0, sizeof(stream)); - git_inflate_init(&stream); stream.next_out = buf; stream.avail_out = size; + stream.next_in = fill(1); + stream.avail_in = input_len; + git_inflate_init(&stream); - do { + for (;;) { + int ret = git_inflate(&stream, 0); + use(input_len - stream.avail_in); + if (stream.total_out == size && ret == Z_STREAM_END) + break; + if (ret != Z_OK) + bad_object(offset, "inflate returned %d", ret); stream.next_in = fill(1); stream.avail_in = input_len; - status = git_inflate(&stream, 0); - use(input_len - stream.avail_in); - } while (status == Z_OK); - if (stream.total_out != size || status != Z_STREAM_END) - bad_object(offset, "inflate returned %d", status); + } git_inflate_end(&stream); return buf; } @@ -356,38 +359,34 @@ { off_t from = obj[0].idx.offset + obj[0].hdr_size; unsigned long len = obj[1].idx.offset - from; - unsigned char *data, *inbuf; + unsigned long rdy = 0; + unsigned char *src, *data; z_stream stream; - int status; - - data = xmalloc(obj->size); - inbuf = xmalloc((len < 64*1024) ? len : 64*1024); - - memset(&stream, 0, sizeof(stream)); - git_inflate_init(&stream); - stream.next_out = data; - stream.avail_out = obj->size; + int st; + src = xmalloc(len); + data = src; do { - ssize_t n = (len < 64*1024) ? len : 64*1024; - n = pread(pack_fd, inbuf, n, from); + ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy); if (n < 0) die_errno("cannot pread pack file"); if (!n) - die("premature end of pack file, %lu bytes missing", len); - from += n; - len -= n; - stream.next_in = inbuf; - stream.avail_in = n; - status = git_inflate(&stream, 0); - } while (len && status == Z_OK && !stream.avail_in); - - /* This has been inflated OK when first encountered, so... */ - if (status != Z_STREAM_END || stream.total_out != obj->size) - die("serious inflate inconsistency"); - + die("premature end of pack file, %lu bytes missing", + len - rdy); + rdy += n; + } while (rdy < len); + data = xmalloc(obj->size); + memset(&stream, 0, sizeof(stream)); + stream.next_out = data; + stream.avail_out = obj->size; + stream.next_in = src; + stream.avail_in = len; + git_inflate_init(&stream); + while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK); git_inflate_end(&stream); - free(inbuf); + if (st != Z_STREAM_END || stream.total_out != obj->size) + die("serious inflate inconsistency"); + free(src); return data; } @@ -669,25 +668,25 @@ static int write_compressed(struct sha1file *f, void *in, unsigned int size) { z_stream stream; - int status; - unsigned char outbuf[4096]; + unsigned long maxsize; + void *out; memset(&stream, 0, sizeof(stream)); deflateInit(&stream, zlib_compression_level); + maxsize = deflateBound(&stream, size); + out = xmalloc(maxsize); + + /* Compress it */ stream.next_in = in; stream.avail_in = size; + stream.next_out = out; + stream.avail_out = maxsize; + while (deflate(&stream, Z_FINISH) == Z_OK); + deflateEnd(&stream); - do { - stream.next_out = outbuf; - stream.avail_out = sizeof(outbuf); - status = deflate(&stream, Z_FINISH); - sha1write(f, outbuf, sizeof(outbuf) - stream.avail_out); - } while (status == Z_OK); - - if (status != Z_STREAM_END) - die("unable to deflate appended object (%d)", status); size = stream.total_out; - deflateEnd(&stream); + sha1write(f, out, size); + free(out); return size; } @@ -884,11 +883,25 @@ if (argc == 2 && !strcmp(argv[1], "-h")) usage(index_pack_usage); - read_replace_refs = 0; + /* + * We wish to read the repository's config file if any, and + * for that it is necessary to call setup_git_directory_gently(). + * However if the cwd was inside .git/objects/pack/ then we need + * to go back there or all the pack name arguments will be wrong. + * And in that case we cannot rely on any prefix returned by + * setup_git_directory_gently() either. + */ + { + char cwd[PATH_MAX+1]; + int nongit; - git_config(git_index_pack_config, NULL); - if (prefix && chdir(prefix)) - die("Cannot come back to cwd"); + if (!getcwd(cwd, sizeof(cwd)-1)) + die("Unable to get current working directory"); + setup_git_directory_gently(&nongit); + git_config(git_index_pack_config, NULL); + if (chdir(cwd)) + die("Cannot come back to cwd"); + } for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff -Nru git-1.7.4.1/builtin/init-db.c git-1.7.1/builtin/init-db.c --- git-1.7.4.1/builtin/init-db.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/init-db.c 2010-04-24 02:38:35.000000000 +0000 @@ -294,26 +294,11 @@ return reinit; } -static void create_object_directory(void) -{ - const char *object_directory = get_object_directory(); - int len = strlen(object_directory); - char *path = xmalloc(len + 40); - - memcpy(path, object_directory, len); - - safe_create_dir(object_directory, 1); - strcpy(path+len, "/pack"); - safe_create_dir(path, 1); - strcpy(path+len, "/info"); - safe_create_dir(path, 1); - - free(path); -} - int init_db(const char *template_dir, unsigned int flags) { - int reinit; + const char *sha1_dir; + char *path; + int len, reinit; safe_create_dir(get_git_dir(), 0); @@ -328,7 +313,16 @@ reinit = create_default_files(template_dir); - create_object_directory(); + sha1_dir = get_object_directory(); + len = strlen(sha1_dir); + path = xmalloc(len + 40); + memcpy(path, sha1_dir, len); + + safe_create_dir(sha1_dir, 1); + strcpy(path+len, "/pack"); + safe_create_dir(path, 1); + strcpy(path+len, "/info"); + safe_create_dir(path, 1); if (shared_repository) { char buf[10]; @@ -414,7 +408,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) { const char *git_dir; - const char *work_tree; const char *template_dir = NULL; unsigned int flags = 0; const struct option init_db_options[] = { @@ -470,7 +463,7 @@ static char git_dir[PATH_MAX+1]; setenv(GIT_DIR_ENVIRONMENT, - getcwd(git_dir, sizeof(git_dir)), argc > 0); + getcwd(git_dir, sizeof(git_dir)), 0); } if (init_shared_repository != -1) @@ -481,8 +474,8 @@ * without --bare. Catch the error early. */ git_dir = getenv(GIT_DIR_ENVIRONMENT); - work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT); - if ((!git_dir || is_bare_repository_cfg == 1) && work_tree) + if ((!git_dir || is_bare_repository_cfg == 1) + && getenv(GIT_WORK_TREE_ENVIRONMENT)) die("%s (or --work-tree=) not allowed without " "specifying %s (or --git-dir=)", GIT_WORK_TREE_ENVIRONMENT, @@ -511,18 +504,10 @@ if (!getcwd(git_work_tree_cfg, PATH_MAX)) die_errno ("Cannot access current working directory"); } - if (work_tree) - set_git_work_tree(make_absolute_path(work_tree)); - else - set_git_work_tree(git_work_tree_cfg); if (access(get_git_work_tree(), X_OK)) die_errno ("Cannot access work tree '%s'", get_git_work_tree()); } - else { - if (work_tree) - set_git_work_tree(make_absolute_path(work_tree)); - } set_git_dir(make_absolute_path(git_dir)); diff -Nru git-1.7.4.1/builtin/log.c git-1.7.1/builtin/log.c --- git-1.7.4.1/builtin/log.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/log.c 2010-04-24 02:38:35.000000000 +0000 @@ -24,7 +24,6 @@ static const char *default_date_mode = NULL; static int default_show_root = 1; -static int decoration_style; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; @@ -32,28 +31,11 @@ "git log [] [..] [[--] ...]\n" " or: git show [options] ..."; -static int parse_decoration_style(const char *var, const char *value) -{ - switch (git_config_maybe_bool(var, value)) { - case 1: - return DECORATE_SHORT_REFS; - case 0: - return 0; - default: - break; - } - if (!strcmp(value, "full")) - return DECORATE_FULL_REFS; - else if (!strcmp(value, "short")) - return DECORATE_SHORT_REFS; - return -1; -} - static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev, struct setup_revision_opt *opt) { int i; - int decoration_given = 0; + int decoration_style = 0; struct userformat_want w; rev->abbrev = DEFAULT_ABBREV; @@ -96,15 +78,14 @@ const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { decoration_style = DECORATE_SHORT_REFS; - decoration_given = 1; } else if (!prefixcmp(arg, "--decorate=")) { const char *v = skip_prefix(arg, "--decorate="); - decoration_style = parse_decoration_style(arg, v); - if (decoration_style < 0) + if (!strcmp(v, "full")) + decoration_style = DECORATE_FULL_REFS; + else if (!strcmp(v, "short")) + decoration_style = DECORATE_SHORT_REFS; + else die("invalid --decorate option: %s", arg); - decoration_given = 1; - } else if (!strcmp(arg, "--no-decorate")) { - decoration_style = 0; } else if (!strcmp(arg, "--source")) { rev->show_source = 1; } else if (!strcmp(arg, "-h")) { @@ -112,20 +93,10 @@ } else die("unrecognized argument: %s", arg); } - - /* - * defeat log.decorate configuration interacting with --pretty=raw - * from the command line. - */ - if (!decoration_given && rev->pretty_given - && rev->commit_format == CMIT_FMT_RAW) - decoration_style = 0; - if (decoration_style) { rev->show_decorations = 1; load_ref_decorations(decoration_style); } - setup_pager(); } /* @@ -287,19 +258,10 @@ return git_config_string(&fmt_patch_subject_prefix, var, value); if (!strcmp(var, "log.date")) return git_config_string(&default_date_mode, var, value); - if (!strcmp(var, "log.decorate")) { - decoration_style = parse_decoration_style(var, value); - if (decoration_style < 0) - decoration_style = 0; /* maybe warn? */ - return 0; - } if (!strcmp(var, "log.showroot")) { default_show_root = git_config_bool(var, value); return 0; } - if (!prefixcmp(var, "color.decorate.")) - return parse_decorate_color_config(var, 15, value); - return git_diff_ui_config(var, value, cb); } @@ -329,7 +291,8 @@ struct strbuf out = STRBUF_INIT; pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode, - get_log_output_encoding()); + git_log_output_encoding ? + git_log_output_encoding: git_commit_encoding); printf("%s", out.buf); strbuf_release(&out); } @@ -491,6 +454,12 @@ rev.use_terminator = 1; rev.always_show_header = 1; + /* + * We get called through "git reflog", so unlike the other log + * routines, we need to set up our pager manually.. + */ + setup_pager(); + return cmd_log_walk(&rev); } @@ -532,13 +501,13 @@ len--; if (!strncasecmp(value, "to: ", 4)) { - item = string_list_append(&extra_to, value + 4); + item = string_list_append(value + 4, &extra_to); len -= 4; } else if (!strncasecmp(value, "cc: ", 4)) { - item = string_list_append(&extra_cc, value + 4); + item = string_list_append(value + 4, &extra_cc); len -= 4; } else { - item = string_list_append(&extra_hdr, value); + item = string_list_append(value, &extra_hdr); } item->string[len] = '\0'; @@ -546,9 +515,8 @@ #define THREAD_SHALLOW 1 #define THREAD_DEEP 2 -static int thread; -static int do_signoff; -static const char *signature = git_version_string; +static int thread = 0; +static int do_signoff = 0; static int git_format_config(const char *var, const char *value, void *cb) { @@ -563,13 +531,13 @@ if (!strcmp(var, "format.to")) { if (!value) return config_error_nonbool(var); - string_list_append(&extra_to, value); + string_list_append(value, &extra_to); return 0; } if (!strcmp(var, "format.cc")) { if (!value) return config_error_nonbool(var); - string_list_append(&extra_cc, value); + string_list_append(value, &extra_cc); return 0; } if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { @@ -607,8 +575,6 @@ do_signoff = git_config_bool(var, value); return 0; } - if (!strcmp(var, "format.signature")) - return git_config_string(&signature, var, value); return git_log_config(var, value, cb); } @@ -703,12 +669,6 @@ info->message_id = strbuf_detach(&buf, NULL); } -static void print_signature(void) -{ - if (signature && *signature) - printf("-- \n%s\n\n", signature); -} - static void make_cover_letter(struct rev_info *rev, int use_stdout, int numbered, int numbered_files, struct commit *origin, @@ -802,7 +762,6 @@ diff_flush(&opts); printf("\n"); - print_signature(); } static const char *clean_message_id(const char *msg_id) @@ -956,7 +915,7 @@ if (unset) string_list_clear(&extra_to, 0); else - string_list_append(&extra_to, arg); + string_list_append(arg, &extra_to); return 0; } @@ -965,7 +924,7 @@ if (unset) string_list_clear(&extra_cc, 0); else - string_list_append(&extra_cc, arg); + string_list_append(arg, &extra_cc); return 0; } @@ -1042,8 +1001,6 @@ { OPTION_CALLBACK, 0, "thread", &thread, "style", "enable message threading, styles: shallow, deep", PARSE_OPT_OPTARG, thread_callback }, - OPT_STRING(0, "signature", &signature, "signature", - "add a signature"), OPT_END() }; @@ -1055,7 +1012,8 @@ rev.commit_format = CMIT_FMT_EMAIL; rev.verbose_header = 1; rev.diff = 1; - rev.no_merges = 1; + rev.combine_merges = 0; + rev.ignore_merges = 1; DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; memset(&s_r_opt, 0, sizeof(s_r_opt)); @@ -1158,8 +1116,6 @@ if (!use_stdout) output_directory = set_outdir(prefix, output_directory); - else - setup_pager(); if (output_directory) { if (use_stdout) @@ -1228,6 +1184,10 @@ continue; } + /* ignore merges */ + if (commit->parents && commit->parents->next) + continue; + if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids)) continue; @@ -1245,7 +1205,7 @@ rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); if (in_reply_to) { const char *msgid = clean_message_id(in_reply_to); - string_list_append(rev.ref_message_ids, msgid); + string_list_append(msgid, rev.ref_message_ids); } rev.numbered_files = numbered_files; rev.patch_suffix = fmt_patch_suffix; @@ -1292,8 +1252,8 @@ && (!cover_letter || rev.nr > 1)) free(rev.message_id); else - string_list_append(rev.ref_message_ids, - rev.message_id); + string_list_append(rev.message_id, + rev.ref_message_ids); } gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); } @@ -1319,7 +1279,7 @@ mime_boundary_leader, rev.mime_boundary); else - print_signature(); + printf("-- \n%s\n\n", git_version_string); } if (!use_stdout) fclose(stdout); @@ -1366,7 +1326,7 @@ struct option options[] = { OPT__ABBREV(&abbrev), - OPT__VERBOSE(&verbose, "be verbose"), + OPT__VERBOSE(&verbose), OPT_END() }; diff -Nru git-1.7.4.1/builtin/ls-files.c git-1.7.1/builtin/ls-files.c --- git-1.7.4.1/builtin/ls-files.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/ls-files.c 2010-04-24 02:38:35.000000000 +0000 @@ -25,11 +25,9 @@ static int show_killed; static int show_valid_bit; static int line_terminator = '\n'; -static int debug_mode; -static const char *prefix; -static int max_prefix_len; static int prefix_len; +static int prefix_offset; static const char **pathspec; static int error_unmatch; static char *ps_matched; @@ -45,15 +43,10 @@ static const char *tag_skip_worktree = ""; static const char *tag_resolve_undo = ""; -static void write_name(const char* name, size_t len) -{ - write_name_quoted_relative(name, len, prefix, prefix_len, stdout, - line_terminator); -} - static void show_dir_entry(const char *tag, struct dir_entry *ent) { - int len = max_prefix_len; + int len = prefix_len; + int offset = prefix_offset; if (len >= ent->len) die("git ls-files: internal error - directory entry not superset of prefix"); @@ -62,7 +55,7 @@ return; fputs(tag, stdout); - write_name(ent->name, ent->len); + write_name_quoted(ent->name + offset, stdout, line_terminator); } static void show_other_files(struct dir_struct *dir) @@ -128,7 +121,8 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) { - int len = max_prefix_len; + int len = prefix_len; + int offset = prefix_offset; if (len >= ce_namelen(ce)) die("git ls-files: internal error - cache entry not superset of prefix"); @@ -162,45 +156,40 @@ find_unique_abbrev(ce->sha1,abbrev), ce_stage(ce)); } - write_name(ce->name, ce_namelen(ce)); - if (debug_mode) { - printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec); - printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec); - printf(" dev: %d\tino: %d\n", ce->ce_dev, ce->ce_ino); - printf(" uid: %d\tgid: %d\n", ce->ce_uid, ce->ce_gid); - printf(" size: %d\tflags: %x\n", ce->ce_size, ce->ce_flags); - } + write_name_quoted(ce->name + offset, stdout, line_terminator); } -static void show_ru_info(void) +static int show_one_ru(struct string_list_item *item, void *cbdata) { - struct string_list_item *item; + int offset = prefix_offset; + const char *path = item->string; + struct resolve_undo_info *ui = item->util; + int i, len; + + len = strlen(path); + if (len < prefix_len) + return 0; /* outside of the prefix */ + if (!match_pathspec(pathspec, path, len, prefix_len, ps_matched)) + return 0; /* uninterested */ + for (i = 0; i < 3; i++) { + if (!ui->mode[i]) + continue; + printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], + find_unique_abbrev(ui->sha1[i], abbrev), + i + 1); + write_name_quoted(path + offset, stdout, line_terminator); + } + return 0; +} +static void show_ru_info(const char *prefix) +{ if (!the_index.resolve_undo) return; - - for_each_string_list_item(item, the_index.resolve_undo) { - const char *path = item->string; - struct resolve_undo_info *ui = item->util; - int i, len; - - len = strlen(path); - if (len < max_prefix_len) - continue; /* outside of the prefix */ - if (!match_pathspec(pathspec, path, len, max_prefix_len, ps_matched)) - continue; /* uninterested */ - for (i = 0; i < 3; i++) { - if (!ui->mode[i]) - continue; - printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], - find_unique_abbrev(ui->sha1[i], abbrev), - i + 1); - write_name(path, len); - } - } + for_each_string_list(show_one_ru, the_index.resolve_undo, NULL); } -static void show_files(struct dir_struct *dir) +static void show_files(struct dir_struct *dir, const char *prefix) { int i; @@ -254,7 +243,7 @@ */ static void prune_cache(const char *prefix) { - int pos = cache_name_pos(prefix, max_prefix_len); + int pos = cache_name_pos(prefix, prefix_len); unsigned int first, last; if (pos < 0) @@ -267,7 +256,7 @@ while (last > first) { int next = (last + first) >> 1; struct cache_entry *ce = active_cache[next]; - if (!strncmp(ce->name, prefix, max_prefix_len)) { + if (!strncmp(ce->name, prefix, prefix_len)) { first = next+1; continue; } @@ -276,16 +265,11 @@ active_nr = last; } -static const char *pathspec_prefix(const char *prefix) +static const char *verify_pathspec(const char *prefix) { const char **p, *n, *prev; unsigned long max; - if (!pathspec) { - max_prefix_len = prefix ? strlen(prefix) : 0; - return prefix; - } - prev = NULL; max = PATH_MAX; for (p = pathspec; (n = *p) != NULL; p++) { @@ -307,7 +291,10 @@ } } - max_prefix_len = max; + if (prefix_offset > max || memcmp(prev, prefix, prefix_offset)) + die("git ls-files: cannot generate relative filenames containing '..'"); + + prefix_len = max; return max ? xmemdupz(prev, max) : NULL; } @@ -387,7 +374,7 @@ } } -int report_path_error(const char *ps_matched, const char **pathspec, int prefix_len) +int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset) { /* * Make sure all pathspec matched; otherwise it is an error. @@ -417,14 +404,14 @@ continue; error("pathspec '%s' did not match any file(s) known to git.", - pathspec[num] + prefix_len); + pathspec[num] + prefix_offset); errors++; } return errors; } static const char * const ls_files_usage[] = { - "git ls-files [options] [...]", + "git ls-files [options] []*", NULL }; @@ -469,10 +456,9 @@ return 0; } -int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) +int cmd_ls_files(int argc, const char **argv, const char *prefix) { int require_work_tree = 0, show_tag = 0; - const char *max_prefix; struct dir_struct dir; struct option builtin_ls_files_options[] = { { OPTION_CALLBACK, 'z', NULL, NULL, NULL, @@ -518,7 +504,7 @@ { OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL, "add the standard git exclusions", PARSE_OPT_NOARG, option_parse_exclude_standard }, - { OPTION_SET_INT, 0, "full-name", &prefix_len, NULL, + { OPTION_SET_INT, 0, "full-name", &prefix_offset, NULL, "make the output relative to the project top directory", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL }, OPT_BOOLEAN(0, "error-unmatch", &error_unmatch, @@ -526,17 +512,12 @@ OPT_STRING(0, "with-tree", &with_tree, "tree-ish", "pretend that paths removed since are still present"), OPT__ABBREV(&abbrev), - OPT_BOOLEAN(0, "debug", &debug_mode, "show debugging data"), OPT_END() }; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(ls_files_usage, builtin_ls_files_options); - memset(&dir, 0, sizeof(dir)); - prefix = cmd_prefix; if (prefix) - prefix_len = strlen(prefix); + prefix_offset = strlen(prefix); git_config(git_default_config, NULL); if (read_cache() < 0) @@ -574,8 +555,9 @@ if (pathspec) strip_trailing_slash_from_submodules(); - /* Find common prefix for all pathspec's */ - max_prefix = pathspec_prefix(prefix); + /* Verify that the pathspec matches the prefix */ + if (pathspec) + prefix = verify_pathspec(prefix); /* Treat unmatching pathspec elements as errors */ if (pathspec && error_unmatch) { @@ -593,8 +575,8 @@ show_killed | show_modified | show_resolve_undo)) show_cached = 1; - if (max_prefix) - prune_cache(max_prefix); + if (prefix) + prune_cache(prefix); if (with_tree) { /* * Basic sanity check; show-stages and show-unmerged @@ -602,15 +584,15 @@ */ if (show_stage || show_unmerged) die("ls-files --with-tree is incompatible with -s or -u"); - overlay_tree_on_cache(with_tree, max_prefix); + overlay_tree_on_cache(with_tree, prefix); } - show_files(&dir); + show_files(&dir, prefix); if (show_resolve_undo) - show_ru_info(); + show_ru_info(prefix); if (ps_matched) { int bad; - bad = report_path_error(ps_matched, pathspec, prefix_len); + bad = report_path_error(ps_matched, pathspec, prefix_offset); if (bad) fprintf(stderr, "Did you forget to 'git add'?\n"); diff -Nru git-1.7.4.1/builtin/ls-remote.c git-1.7.1/builtin/ls-remote.c --- git-1.7.4.1/builtin/ls-remote.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/ls-remote.c 2010-04-24 02:38:35.000000000 +0000 @@ -4,8 +4,7 @@ #include "remote.h" static const char ls_remote_usage[] = -"git ls-remote [--heads] [--tags] [-u | --upload-pack ]\n" -" [-q|--quiet] [ [...]]"; +"git ls-remote [--heads] [--tags] [-u | --upload-pack ] ..."; /* * Is there one among the list of patterns that match the tail part @@ -32,8 +31,8 @@ { int i; const char *dest = NULL; + int nongit; unsigned flags = 0; - int quiet = 0; const char *uploadpack = NULL; const char **pattern = NULL; @@ -41,6 +40,8 @@ struct transport *transport; const struct ref *ref; + setup_git_directory_gently(&nongit); + for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -65,10 +66,6 @@ flags |= REF_NORMAL; continue; } - if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { - quiet = 1; - continue; - } usage(ls_remote_usage); } dest = arg; @@ -76,6 +73,9 @@ break; } + if (!dest) + usage(ls_remote_usage); + if (argv[i]) { int j; pattern = xcalloc(sizeof(const char *), argc - i + 1); @@ -87,11 +87,6 @@ } } remote = remote_get(dest); - if (!remote) { - if (dest) - die("bad repository '%s'", dest); - die("No remote configured to list refs from."); - } if (!remote->url_nr) die("remote %s has no configured URL", dest); transport = transport_get(remote, NULL); @@ -101,9 +96,6 @@ ref = transport_get_remote_refs(transport); if (transport_disconnect(transport)) return 1; - - if (!dest && !quiet) - fprintf(stderr, "From %s\n", *remote->url); for ( ; ref; ref = ref->next) { if (!check_ref_type(ref, flags)) continue; diff -Nru git-1.7.4.1/builtin/ls-tree.c git-1.7.1/builtin/ls-tree.c --- git-1.7.4.1/builtin/ls-tree.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/ls-tree.c 2010-04-24 02:38:35.000000000 +0000 @@ -24,7 +24,7 @@ static const char *ls_tree_prefix; static const char * const ls_tree_usage[] = { - "git ls-tree [] [...]", + "git ls-tree [] [path...]", NULL }; @@ -52,8 +52,6 @@ speclen = strlen(spec); if (speclen <= len) continue; - if (spec[len] && spec[len] != '/') - continue; if (memcmp(pathname, spec, len)) continue; return 1; diff -Nru git-1.7.4.1/builtin/mailinfo.c git-1.7.1/builtin/mailinfo.c --- git-1.7.4.1/builtin/mailinfo.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/mailinfo.c 2010-04-24 02:38:35.000000000 +0000 @@ -17,10 +17,10 @@ static struct strbuf email = STRBUF_INIT; static enum { - TE_DONTCARE, TE_QP, TE_BASE64 + TE_DONTCARE, TE_QP, TE_BASE64, } transfer_encoding; static enum { - TYPE_TEXT, TYPE_OTHER + TYPE_TEXT, TYPE_OTHER, } message_type; static struct strbuf charset = STRBUF_INIT; @@ -1032,7 +1032,7 @@ */ git_config(git_mailinfo_config, NULL); - def_charset = get_commit_output_encoding(); + def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8"); metainfo_charset = def_charset; while (1 < argc && argv[1][0] == '-') { diff -Nru git-1.7.4.1/builtin/mailsplit.c git-1.7.1/builtin/mailsplit.c --- git-1.7.4.1/builtin/mailsplit.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/mailsplit.c 2010-04-24 02:38:35.000000000 +0000 @@ -10,7 +10,7 @@ #include "strbuf.h" static const char git_mailsplit_usage[] = -"git mailsplit [-d] [-f] [-b] [--keep-cr] -o [(|)...]"; +"git mailsplit [-d] [-f] [-b] [--keep-cr] -o [|...]"; static int is_from_line(const char *line, int len) { @@ -121,7 +121,7 @@ if (dent->d_name[0] == '.') continue; snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name); - string_list_insert(list, name); + string_list_insert(name, list); } closedir(dir); @@ -137,7 +137,7 @@ char name[PATH_MAX]; int ret = -1; int i; - struct string_list list = STRING_LIST_INIT_DUP; + struct string_list list = {NULL, 0, 0, 1}; if (populate_maildir_list(&list, maildir) < 0) goto out; diff -Nru git-1.7.4.1/builtin/merge-base.c git-1.7.1/builtin/merge-base.c --- git-1.7.4.1/builtin/merge-base.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/merge-base.c 2010-04-24 02:38:35.000000000 +0000 @@ -23,8 +23,7 @@ } static const char * const merge_base_usage[] = { - "git merge-base [-a|--all] [--octopus] ...", - "git merge-base --independent ...", + "git merge-base [-a|--all] ...", NULL }; @@ -42,58 +41,21 @@ return r; } -static int handle_octopus(int count, const char **args, int reduce, int show_all) -{ - struct commit_list *revs = NULL; - struct commit_list *result; - int i; - - if (reduce) - show_all = 1; - - for (i = count - 1; i >= 0; i--) - commit_list_insert(get_commit_reference(args[i]), &revs); - - result = reduce ? reduce_heads(revs) : get_octopus_merge_bases(revs); - - if (!result) - return 1; - - while (result) { - printf("%s\n", sha1_to_hex(result->item->object.sha1)); - if (!show_all) - return 0; - result = result->next; - } - - return 0; -} - int cmd_merge_base(int argc, const char **argv, const char *prefix) { struct commit **rev; int rev_nr = 0; int show_all = 0; - int octopus = 0; - int reduce = 0; struct option options[] = { - OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"), - OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"), - OPT_BOOLEAN(0, "independent", &reduce, "list revs not reachable from others"), + OPT_BOOLEAN('a', "all", &show_all, "outputs all common ancestors"), OPT_END() }; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0); - if (!octopus && !reduce && argc < 2) + if (argc < 2) usage_with_options(merge_base_usage, options); - if (reduce && (show_all || octopus)) - die("--independent cannot be used with other options"); - - if (octopus || reduce) - return handle_octopus(argc, argv, reduce, show_all); - rev = xmalloc(argc * sizeof(*rev)); while (argc-- > 0) rev[rev_nr++] = get_commit_reference(*argv++); diff -Nru git-1.7.4.1/builtin/merge.c git-1.7.1/builtin/merge.c --- git-1.7.4.1/builtin/merge.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/merge.c 2010-04-24 02:38:35.000000000 +0000 @@ -42,7 +42,7 @@ NULL }; -static int show_diffstat = 1, shortlog_len, squash; +static int show_diffstat = 1, option_log, squash; static int option_commit = 1, allow_fast_forward = 1; static int fast_forward_only; static int allow_trivial = 1, have_message; @@ -54,10 +54,8 @@ static const char **xopts; static size_t xopts_nr, xopts_alloc; static const char *branch; -static int option_renormalize; static int verbosity; static int allow_rerere_auto; -static int abort_current_merge; static struct strategy all_strategy[] = { { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, @@ -133,7 +131,6 @@ ret = xcalloc(1, sizeof(struct strategy)); ret->name = xstrdup(name); - ret->attr = NO_TRIVIAL; return ret; } @@ -178,9 +175,8 @@ OPT_BOOLEAN(0, "stat", &show_diffstat, "show a diffstat at the end of the merge"), OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"), - { OPTION_INTEGER, 0, "log", &shortlog_len, "n", - "add (at most ) entries from shortlog to merge commit message", - PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, + OPT_BOOLEAN(0, "log", &option_log, + "add list of one-line log to merge commit message"), OPT_BOOLEAN(0, "squash", &squash, "create a single commit instead of doing a merge"), OPT_BOOLEAN(0, "commit", &option_commit, @@ -198,8 +194,6 @@ "message to be used for the merge commit (if any)", option_parse_message), OPT__VERBOSITY(&verbosity), - OPT_BOOLEAN(0, "abort", &abort_current_merge, - "abort the current in-progress merge"), OPT_END() }; @@ -237,24 +231,6 @@ die("not a valid object: %s", buffer.buf); } -static void read_empty(unsigned const char *sha1, int verbose) -{ - int i = 0; - const char *args[7]; - - args[i++] = "read-tree"; - if (verbose) - args[i++] = "-v"; - args[i++] = "-m"; - args[i++] = "-u"; - args[i++] = EMPTY_TREE_SHA1_HEX; - args[i++] = sha1_to_hex(sha1); - args[i] = NULL; - - if (run_command_v_opt(args, RUN_GIT_CMD)) - die("read-tree failed"); -} - static void reset_hard(unsigned const char *sha1, int verbose) { int i = 0; @@ -424,7 +400,7 @@ goto cleanup; } if (!prefixcmp(found_ref, "refs/remotes/")) { - strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n", + strbuf_addf(msg, "%s\t\tremote branch '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; } @@ -461,7 +437,7 @@ strbuf_addstr(&truname, "refs/heads/"); strbuf_addstr(&truname, remote); strbuf_setlen(&truname, truname.len - len); - if (resolve_ref(truname.buf, buf_sha, 1, NULL)) { + if (resolve_ref(truname.buf, buf_sha, 0, NULL)) { strbuf_addf(msg, "%s\t\tbranch '%s'%s of .\n", sha1_to_hex(remote_head->sha1), @@ -510,8 +486,7 @@ buf = xstrdup(v); argc = split_cmdline(buf, &argv); if (argc < 0) - die("Bad branch.%s.mergeoptions string: %s", branch, - split_cmdline_strerror(argc)); + die("Bad branch.%s.mergeoptions string", branch); argv = xrealloc(argv, sizeof(*argv) * (argc + 2)); memmove(argv + 1, argv, sizeof(*argv) * (argc + 1)); argc++; @@ -526,17 +501,8 @@ return git_config_string(&pull_twohead, k, v); else if (!strcmp(k, "pull.octopus")) return git_config_string(&pull_octopus, k, v); - else if (!strcmp(k, "merge.renormalize")) - option_renormalize = git_config_bool(k, v); - else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) { - int is_bool; - shortlog_len = git_config_bool_or_int(k, v, &is_bool); - if (!is_bool && shortlog_len < 0) - return error("%s: negative length %s", k, v); - if (is_bool && shortlog_len) - shortlog_len = DEFAULT_MERGE_LOG_LEN; - return 0; - } + else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) + option_log = git_config_bool(k, v); return git_diff_ui_config(k, v, cb); } @@ -582,53 +548,13 @@ die("git write-tree failed to write a tree"); } -int try_merge_command(const char *strategy, struct commit_list *common, - const char *head_arg, struct commit_list *remotes) +static int try_merge_strategy(const char *strategy, struct commit_list *common, + const char *head_arg) { const char **args; int i = 0, x = 0, ret; struct commit_list *j; struct strbuf buf = STRBUF_INIT; - - args = xmalloc((4 + xopts_nr + commit_list_count(common) + - commit_list_count(remotes)) * sizeof(char *)); - strbuf_addf(&buf, "merge-%s", strategy); - args[i++] = buf.buf; - for (x = 0; x < xopts_nr; x++) { - char *s = xmalloc(strlen(xopts[x])+2+1); - strcpy(s, "--"); - strcpy(s+2, xopts[x]); - args[i++] = s; - } - for (j = common; j; j = j->next) - args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); - args[i++] = "--"; - args[i++] = head_arg; - for (j = remotes; j; j = j->next) - args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); - args[i] = NULL; - ret = run_command_v_opt(args, RUN_GIT_CMD); - strbuf_release(&buf); - i = 1; - for (x = 0; x < xopts_nr; x++) - free((void *)args[i++]); - for (j = common; j; j = j->next) - free((void *)args[i++]); - i += 2; - for (j = remotes; j; j = j->next) - free((void *)args[i++]); - free(args); - discard_cache(); - if (read_cache() < 0) - die("failed to read the cache"); - resolve_undo_clear(); - - return ret; -} - -static int try_merge_strategy(const char *strategy, struct commit_list *common, - const char *head_arg) -{ int index_fd; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); @@ -641,13 +567,12 @@ rollback_lock_file(lock); if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) { - int clean, x; + int clean; struct commit *result; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); int index_fd; struct commit_list *reversed = NULL; struct merge_options o; - struct commit_list *j; if (remoteheads->next) { error("Not handling anything other than two heads merge."); @@ -658,11 +583,18 @@ if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; - o.renormalize = option_renormalize; - - for (x = 0; x < xopts_nr; x++) - if (parse_merge_opt(&o, xopts[x])) + for (x = 0; x < xopts_nr; x++) { + if (!strcmp(xopts[x], "ours")) + o.recursive_variant = MERGE_RECURSIVE_OURS; + else if (!strcmp(xopts[x], "theirs")) + o.recursive_variant = MERGE_RECURSIVE_THEIRS; + else if (!strcmp(xopts[x], "subtree")) + o.subtree_shift = ""; + else if (!prefixcmp(xopts[x], "subtree=")) + o.subtree_shift = xopts[x]+8; + else die("Unknown option for merge-recursive: -X%s", xopts[x]); + } o.branch1 = head_arg; o.branch2 = remoteheads->item->util; @@ -680,7 +612,39 @@ rollback_lock_file(lock); return clean ? 0 : 1; } else { - return try_merge_command(strategy, common, head_arg, remoteheads); + args = xmalloc((4 + xopts_nr + commit_list_count(common) + + commit_list_count(remoteheads)) * sizeof(char *)); + strbuf_addf(&buf, "merge-%s", strategy); + args[i++] = buf.buf; + for (x = 0; x < xopts_nr; x++) { + char *s = xmalloc(strlen(xopts[x])+2+1); + strcpy(s, "--"); + strcpy(s+2, xopts[x]); + args[i++] = s; + } + for (j = common; j; j = j->next) + args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); + args[i++] = "--"; + args[i++] = head_arg; + for (j = remoteheads; j; j = j->next) + args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1)); + args[i] = NULL; + ret = run_command_v_opt(args, RUN_GIT_CMD); + strbuf_release(&buf); + i = 1; + for (x = 0; x < xopts_nr; x++) + free((void *)args[i++]); + for (j = common; j; j = j->next) + free((void *)args[i++]); + i += 2; + for (j = remoteheads; j; j = j->next) + free((void *)args[i++]); + free(args); + discard_cache(); + if (read_cache() < 0) + die("failed to read the cache"); + resolve_undo_clear(); + return ret; } } @@ -731,7 +695,7 @@ opts.verbose_update = 1; opts.merge = 1; opts.fn = twoway_merge; - setup_unpack_trees_porcelain(&opts, "merge"); + opts.msgs = get_porcelain_error_msgs(); trees[nr_trees] = parse_tree_indirect(head); if (!trees[nr_trees++]) @@ -843,7 +807,7 @@ return 0; } -static int suggest_conflicts(int renormalizing) +static int suggest_conflicts(void) { FILE *fp; int pos; @@ -922,9 +886,22 @@ const char *best_strategy = NULL, *wt_strategy = NULL; struct commit_list **remotes = &remoteheads; - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_merge_usage, builtin_merge_options); + if (read_cache_unmerged()) { + die_resolve_conflict("merge"); + } + if (file_exists(git_path("MERGE_HEAD"))) { + /* + * There is no unmerged entry, don't advise 'git + * add/rm ', just 'git commit'. + */ + if (advice_resolve_conflict) + die("You have not concluded your merge (MERGE_HEAD exists).\n" + "Please, commit your changes before you can merge."); + else + die("You have not concluded your merge (MERGE_HEAD exists)."); + } + resolve_undo_clear(); /* * Check if we are _not_ on a detached HEAD, i.e. if there is a * current branch. @@ -943,34 +920,6 @@ argc = parse_options(argc, argv, prefix, builtin_merge_options, builtin_merge_usage, 0); - - if (abort_current_merge) { - int nargc = 2; - const char *nargv[] = {"reset", "--merge", NULL}; - - if (!file_exists(git_path("MERGE_HEAD"))) - die("There is no merge to abort (MERGE_HEAD missing)."); - - /* Invoke 'git reset --merge' */ - return cmd_reset(nargc, nargv, prefix); - } - - if (read_cache_unmerged()) - die_resolve_conflict("merge"); - - if (file_exists(git_path("MERGE_HEAD"))) { - /* - * There is no unmerged entry, don't advise 'git - * add/rm ', just 'git commit'. - */ - if (advice_resolve_conflict) - die("You have not concluded your merge (MERGE_HEAD exists).\n" - "Please, commit your changes before you can merge."); - else - die("You have not concluded your merge (MERGE_HEAD exists)."); - } - resolve_undo_clear(); - if (verbosity < 0) show_diffstat = 0; @@ -1021,10 +970,10 @@ die("%s - not something we can merge", argv[0]); update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, DIE_ON_ERR); - read_empty(remote_head->sha1, 0); + reset_hard(remote_head->sha1, 0); return 0; } else { - struct strbuf merge_names = STRBUF_INIT; + struct strbuf msg = STRBUF_INIT; /* We are invoked directly as the first-class UI. */ head_arg = "HEAD"; @@ -1037,14 +986,12 @@ * codepath so we discard the error in this * loop. */ - for (i = 0; i < argc; i++) - merge_name(argv[i], &merge_names); - - if (!have_message || shortlog_len) { - fmt_merge_msg(&merge_names, &merge_msg, !have_message, - shortlog_len); + if (!have_message) { + for (i = 0; i < argc; i++) + merge_name(argv[i], &msg); + fmt_merge_msg(option_log, &msg, &merge_msg); if (merge_msg.len) - strbuf_setlen(&merge_msg, merge_msg.len - 1); + strbuf_setlen(&merge_msg, merge_msg.len-1); } } @@ -1341,5 +1288,5 @@ "stopped before committing as requested\n"); return 0; } else - return suggest_conflicts(option_renormalize); + return suggest_conflicts(); } diff -Nru git-1.7.4.1/builtin/merge-file.c git-1.7.1/builtin/merge-file.c --- git-1.7.4.1/builtin/merge-file.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/merge-file.c 2010-04-24 02:38:35.000000000 +0000 @@ -25,10 +25,10 @@ const char *names[3] = { NULL, NULL, NULL }; mmfile_t mmfs[3]; mmbuffer_t result = {NULL, 0}; - xmparam_t xmp = {{0}}; + xmparam_t xmp = {{XDF_NEED_MINIMAL}}; int ret = 0, i = 0, to_stdout = 0; int quiet = 0; - int prefixlen = 0; + int nongit; struct option options[] = { OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"), OPT_SET_INT(0, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3), @@ -40,7 +40,7 @@ XDL_MERGE_FAVOR_UNION), OPT_INTEGER(0, "marker-size", &xmp.marker_size, "for conflicts, use this marker size"), - OPT__QUIET(&quiet, "do not warn about conflicts"), + OPT__QUIET(&quiet), OPT_CALLBACK('L', NULL, names, "name", "set labels for file1/orig_file/file2", &label_cb), OPT_END(), @@ -50,7 +50,8 @@ xmp.style = 0; xmp.favor = 0; - if (startup_info->have_repository) { + prefix = setup_git_directory_gently(&nongit); + if (!nongit) { /* Read the configuration file */ git_config(git_xmerge_config, NULL); if (0 <= git_xmerge_style) @@ -66,14 +67,10 @@ "%s\n", strerror(errno)); } - if (prefix) - prefixlen = strlen(prefix); - for (i = 0; i < 3; i++) { - const char *fname = prefix_filename(prefix, prefixlen, argv[i]); if (!names[i]) names[i] = argv[i]; - if (read_mmfile(mmfs + i, fname)) + if (read_mmfile(mmfs + i, argv[i])) return -1; if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) return error("Cannot merge binary files: %s\n", diff -Nru git-1.7.4.1/builtin/merge-recursive.c git-1.7.1/builtin/merge-recursive.c --- git-1.7.4.1/builtin/merge-recursive.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/merge-recursive.c 2010-04-24 02:38:35.000000000 +0000 @@ -2,10 +2,6 @@ #include "commit.h" #include "tag.h" #include "merge-recursive.h" -#include "xdiff-interface.h" - -static const char builtin_merge_recursive_usage[] = - "git %s ... -- ..."; static const char *better_branch_name(const char *branch) { @@ -33,7 +29,7 @@ o.subtree_shift = ""; if (argc < 4) - usagef(builtin_merge_recursive_usage, argv[0]); + usagef("%s ... -- ...", argv[0]); for (i = 1; i < argc; ++i) { const char *arg = argv[i]; @@ -41,7 +37,15 @@ if (!prefixcmp(arg, "--")) { if (!arg[2]) break; - if (parse_merge_opt(&o, arg + 2)) + if (!strcmp(arg+2, "ours")) + o.recursive_variant = MERGE_RECURSIVE_OURS; + else if (!strcmp(arg+2, "theirs")) + o.recursive_variant = MERGE_RECURSIVE_THEIRS; + else if (!strcmp(arg+2, "subtree")) + o.subtree_shift = ""; + else if (!prefixcmp(arg+2, "subtree=")) + o.subtree_shift = arg + 10; + else die("Unknown option %s", arg); continue; } diff -Nru git-1.7.4.1/builtin/merge-tree.c git-1.7.1/builtin/merge-tree.c --- git-1.7.4.1/builtin/merge-tree.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/merge-tree.c 2010-04-24 02:38:35.000000000 +0000 @@ -60,7 +60,6 @@ { enum object_type type; struct blob *base, *our, *their; - const char *path = entry->path; if (!entry->stage) return read_sha1_file(entry->blob->object.sha1, &type, size); @@ -77,7 +76,7 @@ their = NULL; if (entry) their = entry->blob; - return merge_file(path, base, our, their, size); + return merge_file(entry->path, base, our, their, size); } static void *origin(struct merge_list *entry, unsigned long *size) @@ -107,7 +106,7 @@ xdemitconf_t xecfg; xdemitcb_t ecb; - xpp.flags = 0; + xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; ecb.outf = show_outf; diff -Nru git-1.7.4.1/builtin/mv.c git-1.7.1/builtin/mv.c --- git-1.7.4.1/builtin/mv.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/mv.c 2010-04-24 02:38:35.000000000 +0000 @@ -55,15 +55,15 @@ int i, newfd; int verbose = 0, show_only = 0, force = 0, ignore_errors = 0; struct option builtin_mv_options[] = { - OPT__DRY_RUN(&show_only, "dry run"), - OPT__FORCE(&force, "force move/rename even if target exists"), + OPT__DRY_RUN(&show_only), + OPT_BOOLEAN('f', "force", &force, "force move/rename even if target exists"), OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"), OPT_END(), }; const char **source, **destination, **dest_path; enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes; struct stat st; - struct string_list src_for_dst = STRING_LIST_INIT_NODUP; + struct string_list src_for_dst = {NULL, 0, 0, 0}; git_config(git_default_config, NULL); @@ -180,7 +180,7 @@ } else if (string_list_has_string(&src_for_dst, dst)) bad = "multiple sources for the same target"; else - string_list_insert(&src_for_dst, dst); + string_list_insert(dst, &src_for_dst); if (bad) { if (ignore_errors) { diff -Nru git-1.7.4.1/builtin/name-rev.c git-1.7.1/builtin/name-rev.c --- git-1.7.4.1/builtin/name-rev.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/name-rev.c 2010-04-24 02:38:35.000000000 +0000 @@ -220,7 +220,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) { - struct object_array revs = OBJECT_ARRAY_INIT; + struct object_array revs = { 0, 0, NULL }; int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0; struct name_ref_data data = { 0, 0, NULL }; struct option opts[] = { diff -Nru git-1.7.4.1/builtin/notes.c git-1.7.1/builtin/notes.c --- git-1.7.4.1/builtin/notes.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/notes.c 2010-04-24 02:38:35.000000000 +0000 @@ -17,7 +17,6 @@ #include "run-command.h" #include "parse-options.h" #include "string-list.h" -#include "notes-merge.h" static const char * const git_notes_usage[] = { "git notes [--ref ] [list []]", @@ -26,12 +25,8 @@ "git notes [--ref ] append [-m | -F | (-c | -C) ] []", "git notes [--ref ] edit []", "git notes [--ref ] show []", - "git notes [--ref ] merge [-v | -q] [-s ] ", - "git notes merge --commit [-v | -q]", - "git notes merge --abort [-v | -q]", "git notes [--ref ] remove []", - "git notes [--ref ] prune [-n | -v]", - "git notes [--ref ] get-ref", + "git notes [--ref ] prune", NULL }; @@ -66,25 +61,13 @@ NULL }; -static const char * const git_notes_merge_usage[] = { - "git notes merge [] ", - "git notes merge --commit []", - "git notes merge --abort []", - NULL -}; - static const char * const git_notes_remove_usage[] = { "git notes remove []", NULL }; static const char * const git_notes_prune_usage[] = { - "git notes prune []", - NULL -}; - -static const char * const git_notes_get_ref_usage[] = { - "git notes get-ref", + "git notes prune", NULL }; @@ -100,16 +83,6 @@ struct strbuf buf; }; -static void expand_notes_ref(struct strbuf *sb) -{ - if (!prefixcmp(sb->buf, "refs/notes/")) - return; /* we're happy */ - else if (!prefixcmp(sb->buf, "notes/")) - strbuf_insert(sb, 0, "refs/", 5); - else - strbuf_insert(sb, 0, "refs/notes/", 11); -} - static int list_each_note(const unsigned char *object_sha1, const unsigned char *note_sha1, char *note_path, void *cb_data) @@ -298,17 +271,18 @@ return parse_reuse_arg(opt, arg, unset); } -void commit_notes(struct notes_tree *t, const char *msg) +int commit_notes(struct notes_tree *t, const char *msg) { + struct commit_list *parent; + unsigned char tree_sha1[20], prev_commit[20], new_commit[20]; struct strbuf buf = STRBUF_INIT; - unsigned char commit_sha1[20]; if (!t) t = &default_notes_tree; if (!t->initialized || !t->ref || !*t->ref) die("Cannot commit uninitialized/unreferenced notes tree"); if (!t->dirty) - return; /* don't have to commit an unchanged tree */ + return 0; /* don't have to commit an unchanged tree */ /* Prepare commit message and reflog message */ strbuf_addstr(&buf, "notes: "); /* commit message starts at index 7 */ @@ -316,13 +290,30 @@ if (buf.buf[buf.len - 1] != '\n') strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */ - create_notes_commit(t, NULL, buf.buf + 7, commit_sha1); - update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, DIE_ON_ERR); + /* Convert notes tree to tree object */ + if (write_notes_tree(t, tree_sha1)) + die("Failed to write current notes tree to database"); + + /* Create new commit for the tree object */ + if (!read_ref(t->ref, prev_commit)) { /* retrieve parent commit */ + parent = xmalloc(sizeof(*parent)); + parent->item = lookup_commit(prev_commit); + parent->next = NULL; + } else { + hashclr(prev_commit); + parent = NULL; + } + if (commit_tree(buf.buf + 7, tree_sha1, parent, new_commit, NULL)) + die("Failed to commit notes tree to database"); + + /* Update notes ref with new commit */ + update_ref(buf.buf, t->ref, new_commit, prev_commit, 0, DIE_ON_ERR); strbuf_release(&buf); + return 0; } -combine_notes_fn parse_combine_notes_fn(const char *v) +combine_notes_fn *parse_combine_notes_fn(const char *v) { if (!strcasecmp(v, "overwrite")) return combine_notes_overwrite; @@ -330,8 +321,6 @@ return combine_notes_ignore; else if (!strcasecmp(v, "concatenate")) return combine_notes_concatenate; - else if (!strcasecmp(v, "cat_sort_uniq")) - return combine_notes_cat_sort_uniq; else return NULL; } @@ -427,7 +416,7 @@ { struct strbuf buf = STRBUF_INIT; struct notes_rewrite_cfg *c = NULL; - struct notes_tree *t = NULL; + struct notes_tree *t; int ret = 0; if (rewrite_cmd) { @@ -549,7 +538,7 @@ { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT", "reuse specified note object", PARSE_OPT_NONEG, parse_reuse_arg}, - OPT__FORCE(&force, "replace existing notes"), + OPT_BOOLEAN('f', "force", &force, "replace existing notes"), OPT_END() }; @@ -584,8 +573,8 @@ if (is_null_sha1(new_note)) remove_note(t, object); - else if (add_note(t, object, new_note, combine_notes_overwrite)) - die("BUG: combine_notes_overwrite failed"); + else + add_note(t, object, new_note, combine_notes_overwrite); snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'", is_null_sha1(new_note) ? "removed" : "added", "add"); @@ -605,7 +594,7 @@ struct notes_tree *t; const char *rewrite_cmd = NULL; struct option options[] = { - OPT__FORCE(&force, "replace existing notes"), + OPT_BOOLEAN('f', "force", &force, "replace existing notes"), OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"), OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command", "load rewriting config for (implies " @@ -625,10 +614,6 @@ } } - if (argc < 2) { - error("too few parameters"); - usage_with_options(git_notes_copy_usage, options); - } if (2 < argc) { error("too many parameters"); usage_with_options(git_notes_copy_usage, options); @@ -664,8 +649,7 @@ goto out; } - if (add_note(t, object, from_note, combine_notes_overwrite)) - die("BUG: combine_notes_overwrite failed"); + add_note(t, object, from_note, combine_notes_overwrite); commit_notes(t, "Notes added by 'git notes copy'"); out: free_notes(t); @@ -724,8 +708,8 @@ if (is_null_sha1(new_note)) remove_note(t, object); - else if (add_note(t, object, new_note, combine_notes_overwrite)) - die("BUG: combine_notes_overwrite failed"); + else + add_note(t, object, new_note, combine_notes_overwrite); snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'", is_null_sha1(new_note) ? "removed" : "added", argv[0]); @@ -773,180 +757,6 @@ return retval; } -static int merge_abort(struct notes_merge_options *o) -{ - int ret = 0; - - /* - * Remove .git/NOTES_MERGE_PARTIAL and .git/NOTES_MERGE_REF, and call - * notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE. - */ - - if (delete_ref("NOTES_MERGE_PARTIAL", NULL, 0)) - ret += error("Failed to delete ref NOTES_MERGE_PARTIAL"); - if (delete_ref("NOTES_MERGE_REF", NULL, REF_NODEREF)) - ret += error("Failed to delete ref NOTES_MERGE_REF"); - if (notes_merge_abort(o)) - ret += error("Failed to remove 'git notes merge' worktree"); - return ret; -} - -static int merge_commit(struct notes_merge_options *o) -{ - struct strbuf msg = STRBUF_INIT; - unsigned char sha1[20], parent_sha1[20]; - struct notes_tree *t; - struct commit *partial; - struct pretty_print_context pretty_ctx; - - /* - * Read partial merge result from .git/NOTES_MERGE_PARTIAL, - * and target notes ref from .git/NOTES_MERGE_REF. - */ - - if (get_sha1("NOTES_MERGE_PARTIAL", sha1)) - die("Failed to read ref NOTES_MERGE_PARTIAL"); - else if (!(partial = lookup_commit_reference(sha1))) - die("Could not find commit from NOTES_MERGE_PARTIAL."); - else if (parse_commit(partial)) - die("Could not parse commit from NOTES_MERGE_PARTIAL."); - - if (partial->parents) - hashcpy(parent_sha1, partial->parents->item->object.sha1); - else - hashclr(parent_sha1); - - t = xcalloc(1, sizeof(struct notes_tree)); - init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); - - o->local_ref = resolve_ref("NOTES_MERGE_REF", sha1, 0, 0); - if (!o->local_ref) - die("Failed to resolve NOTES_MERGE_REF"); - - if (notes_merge_commit(o, t, partial, sha1)) - die("Failed to finalize notes merge"); - - /* Reuse existing commit message in reflog message */ - memset(&pretty_ctx, 0, sizeof(pretty_ctx)); - format_commit_message(partial, "%s", &msg, &pretty_ctx); - strbuf_trim(&msg); - strbuf_insert(&msg, 0, "notes: ", 7); - update_ref(msg.buf, o->local_ref, sha1, - is_null_sha1(parent_sha1) ? NULL : parent_sha1, - 0, DIE_ON_ERR); - - free_notes(t); - strbuf_release(&msg); - return merge_abort(o); -} - -static int merge(int argc, const char **argv, const char *prefix) -{ - struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; - unsigned char result_sha1[20]; - struct notes_tree *t; - struct notes_merge_options o; - int do_merge = 0, do_commit = 0, do_abort = 0; - int verbosity = 0, result; - const char *strategy = NULL; - struct option options[] = { - OPT_GROUP("General options"), - OPT__VERBOSITY(&verbosity), - OPT_GROUP("Merge options"), - OPT_STRING('s', "strategy", &strategy, "strategy", - "resolve notes conflicts using the given strategy " - "(manual/ours/theirs/union/cat_sort_uniq)"), - OPT_GROUP("Committing unmerged notes"), - { OPTION_BOOLEAN, 0, "commit", &do_commit, NULL, - "finalize notes merge by committing unmerged notes", - PARSE_OPT_NOARG | PARSE_OPT_NONEG }, - OPT_GROUP("Aborting notes merge resolution"), - { OPTION_BOOLEAN, 0, "abort", &do_abort, NULL, - "abort notes merge", - PARSE_OPT_NOARG | PARSE_OPT_NONEG }, - OPT_END() - }; - - argc = parse_options(argc, argv, prefix, options, - git_notes_merge_usage, 0); - - if (strategy || do_commit + do_abort == 0) - do_merge = 1; - if (do_merge + do_commit + do_abort != 1) { - error("cannot mix --commit, --abort or -s/--strategy"); - usage_with_options(git_notes_merge_usage, options); - } - - if (do_merge && argc != 1) { - error("Must specify a notes ref to merge"); - usage_with_options(git_notes_merge_usage, options); - } else if (!do_merge && argc) { - error("too many parameters"); - usage_with_options(git_notes_merge_usage, options); - } - - init_notes_merge_options(&o); - o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT; - - if (do_abort) - return merge_abort(&o); - if (do_commit) - return merge_commit(&o); - - o.local_ref = default_notes_ref(); - strbuf_addstr(&remote_ref, argv[0]); - expand_notes_ref(&remote_ref); - o.remote_ref = remote_ref.buf; - - if (strategy) { - if (!strcmp(strategy, "manual")) - o.strategy = NOTES_MERGE_RESOLVE_MANUAL; - else if (!strcmp(strategy, "ours")) - o.strategy = NOTES_MERGE_RESOLVE_OURS; - else if (!strcmp(strategy, "theirs")) - o.strategy = NOTES_MERGE_RESOLVE_THEIRS; - else if (!strcmp(strategy, "union")) - o.strategy = NOTES_MERGE_RESOLVE_UNION; - else if (!strcmp(strategy, "cat_sort_uniq")) - o.strategy = NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ; - else { - error("Unknown -s/--strategy: %s", strategy); - usage_with_options(git_notes_merge_usage, options); - } - } - - t = init_notes_check("merge"); - - strbuf_addf(&msg, "notes: Merged notes from %s into %s", - remote_ref.buf, default_notes_ref()); - strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ - - result = notes_merge(&o, t, result_sha1); - - if (result >= 0) /* Merge resulted (trivially) in result_sha1 */ - /* Update default notes ref with new commit */ - update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, - 0, DIE_ON_ERR); - else { /* Merge has unresolved conflicts */ - /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ - update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, - 0, DIE_ON_ERR); - /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ - if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) - die("Failed to store link to current notes ref (%s)", - default_notes_ref()); - printf("Automatic notes merge failed. Fix conflicts in %s and " - "commit the result with 'git notes merge --commit', or " - "abort the merge with 'git notes merge --abort'.\n", - git_path(NOTES_MERGE_WORKTREE)); - } - - free_notes(t); - strbuf_release(&remote_ref); - strbuf_release(&msg); - return result < 0; /* return non-zero on conflicts */ -} - static int remove_cmd(int argc, const char **argv, const char *prefix) { struct option options[] = { @@ -955,7 +765,6 @@ const char *object_ref; struct notes_tree *t; unsigned char object[20]; - int retval; argc = parse_options(argc, argv, prefix, options, git_notes_remove_usage, 0); @@ -972,26 +781,18 @@ t = init_notes_check("remove"); - retval = remove_note(t, object); - if (retval) - fprintf(stderr, "Object %s has no note\n", sha1_to_hex(object)); - else { - fprintf(stderr, "Removing note for object %s\n", - sha1_to_hex(object)); + fprintf(stderr, "Removing note for object %s\n", sha1_to_hex(object)); + remove_note(t, object); - commit_notes(t, "Notes removed by 'git notes remove'"); - } + commit_notes(t, "Notes removed by 'git notes remove'"); free_notes(t); - return retval; + return 0; } static int prune(int argc, const char **argv, const char *prefix) { struct notes_tree *t; - int show_only = 0, verbose = 0; struct option options[] = { - OPT__DRY_RUN(&show_only, "do not remove, show only"), - OPT__VERBOSE(&verbose, "report pruned notes"), OPT_END() }; @@ -1005,29 +806,12 @@ t = init_notes_check("prune"); - prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) | - (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) ); - if (!show_only) - commit_notes(t, "Notes removed by 'git notes prune'"); + prune_notes(t); + commit_notes(t, "Notes removed by 'git notes prune'"); free_notes(t); return 0; } -static int get_ref(int argc, const char **argv, const char *prefix) -{ - struct option options[] = { OPT_END() }; - argc = parse_options(argc, argv, prefix, options, - git_notes_get_ref_usage, 0); - - if (argc) { - error("too many parameters"); - usage_with_options(git_notes_get_ref_usage, options); - } - - puts(default_notes_ref()); - return 0; -} - int cmd_notes(int argc, const char **argv, const char *prefix) { int result; @@ -1044,8 +828,13 @@ if (override_notes_ref) { struct strbuf sb = STRBUF_INIT; + if (!prefixcmp(override_notes_ref, "refs/notes/")) + /* we're happy */; + else if (!prefixcmp(override_notes_ref, "notes/")) + strbuf_addstr(&sb, "refs/"); + else + strbuf_addstr(&sb, "refs/notes/"); strbuf_addstr(&sb, override_notes_ref); - expand_notes_ref(&sb); setenv("GIT_NOTES_REF", sb.buf, 1); strbuf_release(&sb); } @@ -1060,14 +849,10 @@ result = append_edit(argc, argv, prefix); else if (!strcmp(argv[0], "show")) result = show(argc, argv, prefix); - else if (!strcmp(argv[0], "merge")) - result = merge(argc, argv, prefix); else if (!strcmp(argv[0], "remove")) result = remove_cmd(argc, argv, prefix); else if (!strcmp(argv[0], "prune")) result = prune(argc, argv, prefix); - else if (!strcmp(argv[0], "get-ref")) - result = get_ref(argc, argv, prefix); else { result = error("Unknown subcommand: %s", argv[0]); usage_with_options(git_notes_usage, options); diff -Nru git-1.7.4.1/builtin/pack-objects.c git-1.7.1/builtin/pack-objects.c --- git-1.7.4.1/builtin/pack-objects.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/pack-objects.c 2010-04-24 02:38:35.000000000 +0000 @@ -16,18 +16,22 @@ #include "list-objects.h" #include "progress.h" #include "refs.h" + +#ifndef NO_PTHREADS #include "thread-utils.h" +#include +#endif static const char pack_usage[] = - "git pack-objects [ -q | --progress | --all-progress ]\n" + "git pack-objects [{ -q | --progress | --all-progress }]\n" " [--all-progress-implied]\n" - " [--max-pack-size=] [--local] [--incremental]\n" - " [--window=] [--window-memory=] [--depth=]\n" + " [--max-pack-size=N] [--local] [--incremental]\n" + " [--window=N] [--window-memory=N] [--depth=N]\n" " [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset]\n" - " [--threads=] [--non-empty] [--revs [--unpacked | --all]]\n" + " [--threads=N] [--non-empty] [--revs [--unpacked | --all]*]\n" " [--reflog] [--stdout | base-name] [--include-tag]\n" - " [--keep-unreachable | --unpack-unreachable]\n" - " [< ref-list | < object-list]"; + " [--keep-unreachable | --unpack-unreachable \n" + " [idx; /* make sure off_t is sufficiently large not to wrap */ - if (signed_add_overflows(*offset, size)) + if (*offset > *offset + size) die("pack too large for current definition of off_t"); *offset += size; return 1; @@ -1294,23 +1298,9 @@ read_lock(); src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz); read_unlock(); - if (!src->data) { - if (src_entry->preferred_base) { - static int warned = 0; - if (!warned++) - warning("object %s cannot be read", - sha1_to_hex(src_entry->idx.sha1)); - /* - * Those objects are not included in the - * resulting pack. Be resilient and ignore - * them if they can't be read, in case the - * pack could be created nevertheless. - */ - return 0; - } + if (!src->data) die("object %s cannot be read", sha1_to_hex(src_entry->idx.sha1)); - } if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(src_entry->idx.sha1), sz, src_size); @@ -1532,15 +1522,6 @@ #ifndef NO_PTHREADS -static void try_to_free_from_threads(size_t size) -{ - read_lock(); - release_pack_memory(size, -1); - read_unlock(); -} - -static try_to_free_t old_try_to_free_routine; - /* * The main thread waits on the condition that (at least) one of the workers * has stopped working (which is indicated in the .working member of @@ -1571,16 +1552,14 @@ */ static void init_threaded_search(void) { - init_recursive_mutex(&read_mutex); + pthread_mutex_init(&read_mutex, NULL); pthread_mutex_init(&cache_mutex, NULL); pthread_mutex_init(&progress_mutex, NULL); pthread_cond_init(&progress_cond, NULL); - old_try_to_free_routine = set_try_to_free_routine(try_to_free_from_threads); } static void cleanup_threaded_search(void) { - set_try_to_free_routine(old_try_to_free_routine); pthread_cond_destroy(&progress_cond); pthread_mutex_destroy(&read_mutex); pthread_mutex_destroy(&cache_mutex); diff -Nru git-1.7.4.1/builtin/patch-id.c git-1.7.1/builtin/patch-id.c --- git-1.7.4.1/builtin/patch-id.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/patch-id.c 2010-04-24 02:38:35.000000000 +0000 @@ -28,42 +28,16 @@ return dst - line; } -static int scan_hunk_header(const char *p, int *p_before, int *p_after) -{ - static const char digits[] = "0123456789"; - const char *q, *r; - int n; - - q = p + 4; - n = strspn(q, digits); - if (q[n] == ',') { - q += n + 1; - n = strspn(q, digits); - } - if (n == 0 || q[n] != ' ' || q[n+1] != '+') - return 0; - - r = q + n + 2; - n = strspn(r, digits); - if (r[n] == ',') { - r += n + 1; - n = strspn(r, digits); - } - if (n == 0) - return 0; - - *p_before = atoi(q); - *p_after = atoi(r); - return 1; -} - -int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx) +static void generate_id_list(void) { + static unsigned char sha1[20]; static char line[1000]; - int patchlen = 0, found_next = 0; - int before = -1, after = -1; + git_SHA_CTX ctx; + int patchlen = 0; + git_SHA1_Init(&ctx); while (fgets(line, sizeof(line), stdin) != NULL) { + unsigned char n[20]; char *p = line; int len; @@ -71,75 +45,32 @@ p += 10; else if (!memcmp(line, "commit ", 7)) p += 7; - else if (!memcmp(line, "From ", 5)) - p += 5; - if (!get_sha1_hex(p, next_sha1)) { - found_next = 1; - break; + if (!get_sha1_hex(p, n)) { + flush_current_id(patchlen, sha1, &ctx); + hashcpy(sha1, n); + patchlen = 0; + continue; } /* Ignore commit comments */ if (!patchlen && memcmp(line, "diff ", 5)) continue; - /* Parsing diff header? */ - if (before == -1) { - if (!memcmp(line, "index ", 6)) - continue; - else if (!memcmp(line, "--- ", 4)) - before = after = 1; - else if (!isalpha(line[0])) - break; - } - - /* Looking for a valid hunk header? */ - if (before == 0 && after == 0) { - if (!memcmp(line, "@@ -", 4)) { - /* Parse next hunk, but ignore line numbers. */ - scan_hunk_header(line, &before, &after); - continue; - } - - /* Split at the end of the patch. */ - if (memcmp(line, "diff ", 5)) - break; - - /* Else we're parsing another header. */ - before = after = -1; - } + /* Ignore git-diff index header */ + if (!memcmp(line, "index ", 6)) + continue; - /* If we get here, we're inside a hunk. */ - if (line[0] == '-' || line[0] == ' ') - before--; - if (line[0] == '+' || line[0] == ' ') - after--; + /* Ignore line numbers when computing the SHA1 of the patch */ + if (!memcmp(line, "@@ -", 4)) + continue; /* Compute the sha without whitespace */ len = remove_space(line); patchlen += len; - git_SHA1_Update(ctx, line, len); - } - - if (!found_next) - hashclr(next_sha1); - - return patchlen; -} - -static void generate_id_list(void) -{ - unsigned char sha1[20], n[20]; - git_SHA_CTX ctx; - int patchlen; - - git_SHA1_Init(&ctx); - hashclr(sha1); - while (!feof(stdin)) { - patchlen = get_one_patchid(n, &ctx); - flush_current_id(patchlen, sha1, &ctx); - hashcpy(sha1, n); + git_SHA1_Update(&ctx, line, len); } + flush_current_id(patchlen, sha1, &ctx); } static const char patch_id_usage[] = "git patch-id < patch"; diff -Nru git-1.7.4.1/builtin/prune.c git-1.7.1/builtin/prune.c --- git-1.7.4.1/builtin/prune.c 2011-02-12 00:20:00.000000000 +0000 +++ git-1.7.1/builtin/prune.c 2010-04-24 02:38:35.000000000 +0000 @@ -125,8 +125,10 @@ { struct rev_info revs; const struct option options[] = { - OPT__DRY_RUN(&show_only, "do not remove, show only"), - OPT__VERBOSE(&verbose, "report pruned objects"), + OPT_BOOLEAN('n', NULL, &show_only, + "do not remove, show only"), + OPT_BOOLEAN('v', NULL, &verbose, + "report pruned objects"), OPT_DATE(0, "expire", &expire, "expire objects older than