Code

Merge branch 'cn/maint-branch-with-bad'
authorJunio C Hamano <gitster@pobox.com>
Thu, 1 Mar 2012 22:44:17 +0000 (14:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 1 Mar 2012 22:44:17 +0000 (14:44 -0800)
* cn/maint-branch-with-bad:
  branch: don't assume the merge filter ref exists

Conflicts:
t/t3200-branch.sh

1  2 
builtin/branch.c
t/t3200-branch.sh

diff --combined builtin/branch.c
index cb17bc367571a88b6e6bcac5020c1746c4385480,d6691af0a57f3ced2fc943e8a036ac1e03cb0566..d8cccf725d3fab24ad585a26629373fc987bb3f8
@@@ -104,7 -104,6 +104,7 @@@ static int branch_merged(int kind, cons
         */
        struct commit *reference_rev = NULL;
        const char *reference_name = NULL;
 +      void *reference_name_to_free = NULL;
        int merged;
  
        if (kind == REF_LOCAL_BRANCH) {
                    branch->merge &&
                    branch->merge[0] &&
                    branch->merge[0]->dst &&
 -                  (reference_name =
 -                   resolve_ref(branch->merge[0]->dst, sha1, 1, NULL)) != NULL)
 +                  (reference_name = reference_name_to_free =
 +                   resolve_refdup(branch->merge[0]->dst, sha1, 1, NULL)) != NULL)
                        reference_rev = lookup_commit_reference(sha1);
        }
        if (!reference_rev)
                                "         '%s', even though it is merged to HEAD."),
                                name, reference_name);
        }
 +      free(reference_name_to_free);
        return merged;
  }
  
@@@ -188,7 -186,7 +188,7 @@@ static int delete_branches(int argc, co
                free(name);
  
                name = xstrdup(mkpath(fmt, bname.buf));
 -              if (!resolve_ref(name, sha1, 1, NULL)) {
 +              if (read_ref(name, sha1)) {
                        error(_("%sbranch '%s' not found."),
                                        remote, bname.buf);
                        ret = 1;
@@@ -252,7 -250,7 +252,7 @@@ static char *resolve_symref(const char 
        int flag;
        const char *dst, *cp;
  
 -      dst = resolve_ref(src, sha1, 0, &flag);
 +      dst = resolve_ref_unsafe(src, sha1, 0, &flag);
        if (!(dst && (flag & REF_ISSYMREF)))
                return NULL;
        if (prefix && (cp = skip_prefix(dst, prefix)))
@@@ -530,6 -528,10 +530,10 @@@ static int print_ref_list(int kinds, in
        if (merge_filter != NO_FILTER) {
                struct commit *filter;
                filter = lookup_commit_reference_gently(merge_filter_ref, 0);
+               if (!filter)
+                       die("object '%s' does not point to a commit",
+                           sha1_to_hex(merge_filter_ref));
                filter->object.flags |= UNINTERESTING;
                add_pending_object(&ref_list.revs,
                                   (struct object *) filter, "");
  static void rename_branch(const char *oldname, const char *newname, int force)
  {
        struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
 -      unsigned char sha1[20];
        struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
        int recovery = 0;
        int clobber_head_ok;
                 * Bad name --- this could be an attempt to rename a
                 * ref that we used to allow to be created by accident.
                 */
 -              if (resolve_ref(oldref.buf, sha1, 1, NULL))
 +              if (ref_exists(oldref.buf))
                        recovery = 1;
                else
                        die(_("Invalid branch name: '%s'"), oldname);
@@@ -631,49 -634,11 +635,49 @@@ static int opt_parse_merge_filter(cons
        return 0;
  }
  
 +static const char edit_description[] = "BRANCH_DESCRIPTION";
 +
 +static int edit_branch_description(const char *branch_name)
 +{
 +      FILE *fp;
 +      int status;
 +      struct strbuf buf = STRBUF_INIT;
 +      struct strbuf name = STRBUF_INIT;
 +
 +      read_branch_desc(&buf, branch_name);
 +      if (!buf.len || buf.buf[buf.len-1] != '\n')
 +              strbuf_addch(&buf, '\n');
 +      strbuf_addf(&buf,
 +                  "# Please edit the description for the branch\n"
 +                  "#   %s\n"
 +                  "# Lines starting with '#' will be stripped.\n",
 +                  branch_name);
 +      fp = fopen(git_path(edit_description), "w");
 +      if ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {
 +              strbuf_release(&buf);
 +              return error(_("could not write branch description template: %s\n"),
 +                           strerror(errno));
 +      }
 +      strbuf_reset(&buf);
 +      if (launch_editor(git_path(edit_description), &buf, NULL)) {
 +              strbuf_release(&buf);
 +              return -1;
 +      }
 +      stripspace(&buf, 1);
 +
 +      strbuf_addf(&name, "branch.%s.description", branch_name);
 +      status = git_config_set(name.buf, buf.buf);
 +      strbuf_release(&name);
 +      strbuf_release(&buf);
 +
 +      return status;
 +}
 +
  int cmd_branch(int argc, const char **argv, const char *prefix)
  {
        int delete = 0, rename = 0, force_create = 0, list = 0;
        int verbose = 0, abbrev = -1, detached = 0;
 -      int reflog = 0;
 +      int reflog = 0, edit_description = 0;
        enum branch_track track;
        int kinds = REF_LOCAL_BRANCH;
        struct commit_list *with_commit = NULL;
                OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
                OPT_BOOLEAN(0, "list", &list, "list branch names"),
                OPT_BOOLEAN('l', "create-reflog", &reflog, "create the branch's reflog"),
 +              OPT_BOOLEAN(0, "edit-description", &edit_description,
 +                          "edit the description for the branch"),
                OPT__FORCE(&force_create, "force creation (when already exists)"),
                {
                        OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
  
        track = git_branch_track;
  
 -      head = resolve_ref("HEAD", head_sha1, 0, NULL);
 +      head = resolve_refdup("HEAD", head_sha1, 0, NULL);
        if (!head)
                die(_("Failed to resolve HEAD as a valid ref."));
 -      head = xstrdup(head);
        if (!strcmp(head, "HEAD")) {
                detached = 1;
        } else {
        argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
                             0);
  
 -      if (!delete && !rename && argc == 0)
 +      if (!delete && !rename && !edit_description && argc == 0)
                list = 1;
  
        if (!!delete + !!rename + !!force_create + !!list > 1)
        else if (list)
                return print_ref_list(kinds, detached, verbose, abbrev,
                                      with_commit, argv);
 -      else if (rename) {
 +      else if (edit_description) {
 +              const char *branch_name;
 +              struct strbuf branch_ref = STRBUF_INIT;
 +
 +              if (detached)
 +                      die("Cannot give description to detached HEAD");
 +              if (!argc)
 +                      branch_name = head;
 +              else if (argc == 1)
 +                      branch_name = argv[0];
 +              else
 +                      usage_with_options(builtin_branch_usage, options);
 +
 +              strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
 +              if (!ref_exists(branch_ref.buf)) {
 +                      strbuf_release(&branch_ref);
 +
 +                      if (!argc)
 +                              return error("No commit on branch '%s' yet.",
 +                                           branch_name);
 +                      else
 +                              return error("No such branch '%s'.", branch_name);
 +              }
 +              strbuf_release(&branch_ref);
 +
 +              if (edit_branch_description(branch_name))
 +                      return 1;
 +      } else if (rename) {
                if (argc == 1)
                        rename_branch(head, argv[0], rename > 1);
                else if (argc == 2)
diff --combined t/t3200-branch.sh
index dd1acebd88070b75bbbfd07048b5a255aa00e0f3,6ad1763fda28cb86daf7e6baa901814d1a343517..9fe1d8feab419e1a8065b2ea5881f991edc68855
@@@ -3,8 -3,11 +3,8 @@@
  # Copyright (c) 2005 Amos Waterland
  #
  
 -test_description='git branch --foo should not create bogus branch
 +test_description='git branch assorted tests'
  
 -This test runs git branch --help and checks that the argument is properly
 -handled.  Specifically, that a bogus branch is not created.
 -'
  . ./test-lib.sh
  
  test_expect_success \
@@@ -19,7 -22,7 +19,7 @@@
  
  test_expect_success \
      'git branch --help should not have created a bogus branch' '
 -     git branch --help </dev/null >/dev/null 2>/dev/null;
 +     test_might_fail git branch --help </dev/null >/dev/null 2>/dev/null &&
       test_path_is_missing .git/refs/heads/--help
  '
  
@@@ -85,7 -88,7 +85,7 @@@ test_expect_success 
  test_expect_success \
      'git branch -m n/n n should work' \
         'git branch -l n/n &&
 -        git branch -m n/n n
 +      git branch -m n/n n &&
        test_path_is_file .git/logs/refs/heads/n'
  
  test_expect_success 'git branch -m o/o o should fail when o/p exists' '
@@@ -617,40 -620,8 +617,44 @@@ test_expect_success 'use set-upstream o
  
  '
  
 +test_expect_success 'use --edit-description' '
 +      write_script editor <<-\EOF &&
 +              echo "New contents" >"$1"
 +      EOF
 +      EDITOR=./editor git branch --edit-description &&
 +              write_script editor <<-\EOF &&
 +              git stripspace -s <"$1" >"EDITOR_OUTPUT"
 +      EOF
 +      EDITOR=./editor git branch --edit-description &&
 +      echo "New contents" >expect &&
 +      test_cmp EDITOR_OUTPUT expect
 +'
 +
 +test_expect_success 'detect typo in branch name when using --edit-description' '
 +      write_script editor <<-\EOF &&
 +              echo "New contents" >"$1"
 +      EOF
 +      (
 +              EDITOR=./editor &&
 +              export EDITOR &&
 +              test_must_fail git branch --edit-description no-such-branch
 +      )
 +'
 +
 +test_expect_success 'refuse --edit-description on unborn branch for now' '
 +      write_script editor <<-\EOF &&
 +              echo "New contents" >"$1"
 +      EOF
 +      git checkout --orphan unborn &&
 +      (
 +              EDITOR=./editor &&
 +              export EDITOR &&
 +              test_must_fail git branch --edit-description
 +      )
 +'
 +
+ test_expect_success '--merged catches invalid object names' '
+       test_must_fail git branch --merged 0000000000000000000000000000000000000000
+ '
  test_done