Merge branch 'maint-1.6.3' into maint-1.6.4
authorJunio C Hamano <gitster@pobox.com>
Tue, 19 Jan 2010 05:37:06 +0000 (21:37 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 19 Jan 2010 05:37:06 +0000 (21:37 -0800)
* maint-1.6.3:
base85: Make the code more obvious instead of explaining the non-obvious
base85: encode_85() does not use the decode table
base85 debug code: Fix length byte calculation
checkout -m: do not try to fall back to --merge from an unborn branch
branch: die explicitly why when calling "git branch [-a|-r] branchname".
textconv: stop leaking file descriptors
commit: --cleanup is a message option
git count-objects: handle packs bigger than 4G
t7102: make the test fail if one of its check fails

Conflicts:
builtin-commit.c

1  2 
builtin-branch.c
builtin-checkout.c
builtin-commit.c
builtin-count-objects.c
diff.c
diff --combined builtin-branch.c
index 1a03d5f356009de12364c320577e24853bec7959,73101a183eda3d33412fc7951b006425d5d1a10a..316a8336c6f4ca11c2b9ce1a6fade4f65ec279d0
@@@ -559,7 -559,7 +559,7 @@@ int cmd_branch(int argc, const char **a
        struct option options[] = {
                OPT_GROUP("Generic options"),
                OPT__VERBOSE(&verbose),
 -              OPT_SET_INT( 0 , "track",  &track, "set up tracking mode (see git-pull(1))",
 +              OPT_SET_INT('t', "track",  &track, "set up tracking mode (see git-pull(1))",
                        BRANCH_TRACK_EXPLICIT),
                OPT_BOOLEAN( 0 , "color",  &branch_use_color, "use colored output"),
                OPT_SET_INT('r', NULL,     &kinds, "act on remote-tracking branches",
        }
        hashcpy(merge_filter_ref, head_sha1);
  
 -      argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
 +      argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 +                           0);
        if (!!delete + !!rename + !!force_create > 1)
                usage_with_options(builtin_branch_usage, options);
  
                rename_branch(head, argv[0], rename > 1);
        else if (rename && (argc == 2))
                rename_branch(argv[0], argv[1], rename > 1);
-       else if (argc <= 2)
+       else if (argc <= 2) {
+               if (kinds != REF_LOCAL_BRANCH)
+                       die("-a and -r options to 'git branch' do not make sense with a branch name");
                create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
                              force_create, reflog, track);
-       else
+       else
                usage_with_options(builtin_branch_usage, options);
  
        return 0;
diff --combined builtin-checkout.c
index c6d6ac99f63459094d3e1a110fed228a74f7927b,edefb703fa8a62d96ba7c3d64966ee9ddafda16b..e2dd0cd0c05f13e4e07e1eff1e31e88731e1ee5a
@@@ -396,15 -396,13 +396,15 @@@ static int merge_working_tree(struct ch
                topts.initial_checkout = is_cache_unborn();
                topts.update = 1;
                topts.merge = 1;
-               topts.gently = opts->merge;
+               topts.gently = opts->merge && old->commit;
                topts.verbose_update = !opts->quiet;
                topts.fn = twoway_merge;
                topts.dir = xcalloc(1, sizeof(*topts.dir));
                topts.dir->flags |= DIR_SHOW_IGNORED;
                topts.dir->exclude_per_dir = ".gitignore";
 -              tree = parse_tree_indirect(old->commit->object.sha1);
 +              tree = parse_tree_indirect(old->commit ?
 +                                         old->commit->object.sha1 :
 +                                         (unsigned char *)EMPTY_TREE_SHA1_BIN);
                init_tree_desc(&trees[0], tree->buffer, tree->size);
                tree = parse_tree_indirect(new->commit->object.sha1);
                init_tree_desc(&trees[1], tree->buffer, tree->size);
                        struct merge_options o;
                        if (!opts->merge)
                                return 1;
-                       parse_commit(old->commit);
+                       /*
+                        * Without old->commit, the below is the same as
+                        * the two-tree unpack we already tried and failed.
+                        */
+                       if (!old->commit)
+                               return 1;
  
                        /* Do more real merge */
  
@@@ -543,6 -547,14 +549,6 @@@ static int switch_branches(struct check
                parse_commit(new->commit);
        }
  
 -      if (!old.commit && !opts->force) {
 -              if (!opts->quiet) {
 -                      warning("You appear to be on a branch yet to be born.");
 -                      warning("Forcing checkout of %s.", new->name);
 -              }
 -              opts->force = 1;
 -      }
 -
        ret = merge_working_tree(opts, &old, new);
        if (ret)
                return ret;
@@@ -599,7 -611,7 +605,7 @@@ int cmd_checkout(int argc, const char *
  
        opts.track = BRANCH_TRACK_UNSPECIFIED;
  
 -      argc = parse_options(argc, argv, options, checkout_usage,
 +      argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
  
        /* --track without -b should DWIM */
diff --combined builtin-commit.c
index 4bcce06fbffdf10ec701dfbc0b6b90a11513f89e,0e72a5657a52d3e3be2aae10993a30784607a896..26c3cc4e570274c88fa02194c9e9aced9f29b38f
@@@ -86,16 -86,18 +86,18 @@@ static int opt_parse_m(const struct opt
  static struct option builtin_commit_options[] = {
        OPT__QUIET(&quiet),
        OPT__VERBOSE(&verbose),
-       OPT_GROUP("Commit message options"),
  
 -      OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
+       OPT_GROUP("Commit message options"),
 +      OPT_FILENAME('F', "file", &logfile, "read log from file"),
        OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
        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_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
 -      OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
 +      OPT_FILENAME('t', "template", &template_file, "use specified template file"),
        OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
+       OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
+       /* end commit message options */
  
        OPT_GROUP("Commit contents options"),
        OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
        { 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"),
-       OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
+       /* end commit contents options */
  
        OPT_END()
  };
@@@ -434,12 -436,12 +436,12 @@@ static int prepare_to_commit(const cha
                if (isatty(0))
                        fprintf(stderr, "(reading log message from standard input)\n");
                if (strbuf_read(&sb, 0, 0) < 0)
 -                      die("could not read log from standard input");
 +                      die_errno("could not read log from standard input");
                hook_arg1 = "message";
        } else if (logfile) {
                if (strbuf_read_file(&sb, logfile, 0) < 0)
 -                      die("could not read log file '%s': %s",
 -                          logfile, strerror(errno));
 +                      die_errno("could not read log file '%s'",
 +                                logfile);
                hook_arg1 = "message";
        } else if (use_message) {
                buffer = strstr(use_message_buffer, "\n\n");
                hook_arg2 = use_message;
        } else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
                if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
 -                      die("could not read MERGE_MSG: %s", strerror(errno));
 +                      die_errno("could not read MERGE_MSG");
                hook_arg1 = "merge";
        } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
                if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
 -                      die("could not read SQUASH_MSG: %s", strerror(errno));
 +                      die_errno("could not read SQUASH_MSG");
                hook_arg1 = "squash";
        } else if (template_file && !stat(template_file, &statbuf)) {
                if (strbuf_read_file(&sb, template_file, 0) < 0)
 -                      die("could not read %s: %s",
 -                          template_file, strerror(errno));
 +                      die_errno("could not read '%s'", template_file);
                hook_arg1 = "template";
        }
  
  
        fp = fopen(git_path(commit_editmsg), "w");
        if (fp == NULL)
 -              die("could not open %s: %s",
 -                  git_path(commit_editmsg), strerror(errno));
 +              die_errno("could not open '%s'", git_path(commit_editmsg));
  
        if (cleanup_mode != CLEANUP_NONE)
                stripspace(&sb, 0);
        }
  
        if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
 -              die("could not write commit template: %s", strerror(errno));
 +              die_errno("could not write commit template");
  
        strbuf_release(&sb);
  
@@@ -695,8 -699,13 +697,8 @@@ static int parse_and_validate_options(i
  {
        int f = 0;
  
 -      argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
 -      logfile = parse_options_fix_filename(prefix, logfile);
 -      if (logfile)
 -              logfile = xstrdup(logfile);
 -      template_file = parse_options_fix_filename(prefix, template_file);
 -      if (template_file)
 -              template_file = xstrdup(template_file);
 +      argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
 +                           0);
  
        if (force_author && !strchr(force_author, '>'))
                force_author = find_author_by_nickname(force_author);
@@@ -938,8 -947,8 +940,8 @@@ int cmd_commit(int argc, const char **a
                pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
                fp = fopen(git_path("MERGE_HEAD"), "r");
                if (fp == NULL)
 -                      die("could not open %s for reading: %s",
 -                          git_path("MERGE_HEAD"), strerror(errno));
 +                      die_errno("could not open '%s' for reading",
 +                                git_path("MERGE_HEAD"));
                while (strbuf_getline(&m, fp, '\n') != EOF) {
                        unsigned char sha1[20];
                        if (get_sha1_hex(m.buf, sha1) < 0)
                strbuf_release(&m);
                if (!stat(git_path("MERGE_MODE"), &statbuf)) {
                        if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
 -                              die("could not read MERGE_MODE: %s",
 -                                              strerror(errno));
 +                              die_errno("could not read MERGE_MODE");
                        if (!strcmp(sb.buf, "no-ff"))
                                allow_fast_forward = 0;
                }
        /* Finally, get the commit message */
        strbuf_reset(&sb);
        if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
 +              int saved_errno = errno;
                rollback_index_files();
 -              die("could not read commit message");
 +              die("could not read commit message: %s", strerror(saved_errno));
        }
  
        /* Truncate the message just before the diff, if any. */
diff --combined builtin-count-objects.c
index 1b0b6c84ea4279df56b82c5a406adbea59e58513,433afd85770dde2ac22689f42ec806485016ffaa..2bdd8ebde1002e852055385396ef053f26c91ae8
@@@ -11,7 -11,7 +11,7 @@@
  
  static void count_objects(DIR *d, char *path, int len, int verbose,
                          unsigned long *loose,
-                         unsigned long *loose_size,
+                         off_t *loose_size,
                          unsigned long *packed_loose,
                          unsigned long *garbage)
  {
@@@ -77,13 -77,13 +77,13 @@@ int cmd_count_objects(int argc, const c
        int len = strlen(objdir);
        char *path = xmalloc(len + 50);
        unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
-       unsigned long loose_size = 0;
+       off_t loose_size = 0;
        struct option opts[] = {
                OPT__VERBOSE(&verbose),
                OPT_END(),
        };
  
 -      argc = parse_options(argc, argv, opts, count_objects_usage, 0);
 +      argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
        /* we do not take arguments other than flags for now */
        if (argc)
                usage_with_options(count_objects_usage, opts);
        if (verbose) {
                struct packed_git *p;
                unsigned long num_pack = 0;
-               unsigned long size_pack = 0;
+               off_t size_pack = 0;
                if (!packed_git)
                        prepare_packed_git();
                for (p = packed_git; p; p = p->next) {
                        num_pack++;
                }
                printf("count: %lu\n", loose);
-               printf("size: %lu\n", loose_size / 1024);
+               printf("size: %lu\n", (unsigned long) (loose_size / 1024));
                printf("in-pack: %lu\n", packed);
                printf("packs: %lu\n", num_pack);
-               printf("size-pack: %lu\n", size_pack / 1024);
+               printf("size-pack: %lu\n", (unsigned long) (size_pack / 1024));
                printf("prune-packable: %lu\n", packed_loose);
                printf("garbage: %lu\n", garbage);
        }
        else
                printf("%lu objects, %lu kilobytes\n",
-                      loose, loose_size / 1024);
+                      loose, (unsigned long) (loose_size / 1024));
        return 0;
  }
diff --combined diff.c
index cd35e0c2d7e29012e24cc8f5f49d9d351420b56e,ad5c0a20ee013a7f13ec9b0da1525bd5fdeafa70..6f3bd859799ff4c93b079f4073632ca815f5325d
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -839,9 -839,10 +839,9 @@@ static int scale_linear(int it, int wid
  }
  
  static void show_name(FILE *file,
 -                    const char *prefix, const char *name, int len,
 -                    const char *reset, const char *set)
 +                    const char *prefix, const char *name, int len)
  {
 -      fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset);
 +      fprintf(file, " %s%-*s |", prefix, len, name);
  }
  
  static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
@@@ -955,7 -956,7 +955,7 @@@ static void show_stats(struct diffstat_
                }
  
                if (data->files[i]->is_binary) {
 -                      show_name(options->file, prefix, name, len, reset, set);
 +                      show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Bin ");
                        fprintf(options->file, "%s%d%s", del_c, deleted, reset);
                        fprintf(options->file, " -> ");
                        continue;
                }
                else if (data->files[i]->is_unmerged) {
 -                      show_name(options->file, prefix, name, len, reset, set);
 +                      show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Unmerged\n");
                        continue;
                }
                        add = scale_linear(add, width, max_change);
                        del = scale_linear(del, width, max_change);
                }
 -              show_name(options->file, prefix, name, len, reset, set);
 +              show_name(options->file, prefix, name, len);
                fprintf(options->file, "%5d%s", added + deleted,
                                added + deleted ? " " : "");
                show_graph(options->file, '+', add, add_c, reset);
                fprintf(options->file, "\n");
        }
        fprintf(options->file,
 -             "%s %d files changed, %d insertions(+), %d deletions(-)%s\n",
 -             set, total_files, adds, dels, reset);
 +             " %d files changed, %d insertions(+), %d deletions(-)\n",
 +             total_files, adds, dels);
  }
  
  static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
@@@ -1603,7 -1604,6 +1603,7 @@@ static void builtin_diff(const char *na
                        free(mf1.ptr);
                if (textconv_two)
                        free(mf2.ptr);
 +              xdiff_clear_find_func(&xecfg);
        }
  
   free_ab_and_return:
@@@ -1965,33 -1965,23 +1965,33 @@@ static void prep_temp_blob(const char *
  {
        int fd;
        struct strbuf buf = STRBUF_INIT;
 +      struct strbuf template = STRBUF_INIT;
 +      char *path_dup = xstrdup(path);
 +      const char *base = basename(path_dup);
 +
 +      /* Generate "XXXXXX_basename.ext" */
 +      strbuf_addstr(&template, "XXXXXX_");
 +      strbuf_addstr(&template, base);
  
 -      fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
 +      fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
 +                      strlen(base) + 1);
        if (fd < 0)
 -              die("unable to create temp-file: %s", strerror(errno));
 +              die_errno("unable to create temp-file");
        if (convert_to_working_tree(path,
                        (const char *)blob, (size_t)size, &buf)) {
                blob = buf.buf;
                size = buf.len;
        }
        if (write_in_full(fd, blob, size) != size)
 -              die("unable to write temp-file");
 +              die_errno("unable to write temp-file");
        close(fd);
        temp->name = temp->tmp_path;
        strcpy(temp->hex, sha1_to_hex(sha1));
        temp->hex[40] = 0;
        sprintf(temp->mode, "%06o", mode);
        strbuf_release(&buf);
 +      strbuf_release(&template);
 +      free(path_dup);
  }
  
  static struct diff_tempfile *prepare_temp_file(const char *name,
                if (lstat(name, &st) < 0) {
                        if (errno == ENOENT)
                                goto not_a_valid_file;
 -                      die("stat(%s): %s", name, strerror(errno));
 +                      die_errno("stat(%s)", name);
                }
                if (S_ISLNK(st.st_mode)) {
 -                      int ret;
 -                      char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
 -                      ret = readlink(name, buf, sizeof(buf));
 -                      if (ret < 0)
 -                              die("readlink(%s)", name);
 -                      if (ret == sizeof(buf))
 -                              die("symlink too long: %s", name);
 -                      prep_temp_blob(name, temp, buf, ret,
 +                      struct strbuf sb = STRBUF_INIT;
 +                      if (strbuf_readlink(&sb, name, st.st_size) < 0)
 +                              die_errno("readlink(%s)", name);
 +                      prep_temp_blob(name, temp, sb.buf, sb.len,
                                       (one->sha1_valid ?
                                        one->sha1 : null_sha1),
                                       (one->sha1_valid ?
                                        one->mode : S_IFLNK));
 +                      strbuf_release(&sb);
                }
                else {
                        /* we can borrow from the file in the work tree */
@@@ -2220,7 -2213,7 +2220,7 @@@ static void diff_fill_sha1_info(struct 
                                return;
                        }
                        if (lstat(one->path, &st) < 0)
 -                              die("stat %s", one->path);
 +                              die_errno("stat '%s'", one->path);
                        if (index_path(one->sha1, one->path, &st, 0))
                                die("cannot hash %s", one->path);
                }
@@@ -3597,11 -3590,13 +3597,13 @@@ static char *run_textconv(const char *p
        if (start_command(&child) != 0 ||
            strbuf_read(&buf, child.out, 0) < 0 ||
            finish_command(&child) != 0) {
+               close(child.out);
                strbuf_release(&buf);
                remove_tempfile();
                error("error running textconv command '%s'", pgm);
                return NULL;
        }
+       close(child.out);
        remove_tempfile();
  
        return strbuf_detach(&buf, outsize);