diff options
Diffstat (limited to 'builtin-branch.c')
-rw-r--r-- | builtin-branch.c | 136 |
1 files changed, 57 insertions, 79 deletions
diff --git a/builtin-branch.c b/builtin-branch.c index b1a2ad7a6b..504a981ad5 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -97,9 +97,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) unsigned char sha1[20]; char *name = NULL; const char *fmt, *remote; - char section[PATH_MAX]; int i; int ret = 0; + struct strbuf bname = STRBUF_INIT; switch (kinds) { case REF_REMOTE_BRANCH: @@ -120,20 +120,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) if (!head_rev) die("Couldn't look up commit object for HEAD"); } - for (i = 0; i < argc; i++) { - if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) { + for (i = 0; i < argc; i++, strbuf_release(&bname)) { + int len = strlen(argv[i]); + + if (interpret_nth_last_branch(argv[i], &bname) != len) + strbuf_add(&bname, argv[i], len); + + if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) { error("Cannot delete the branch '%s' " - "which you are currently on.", argv[i]); + "which you are currently on.", bname.buf); ret = 1; continue; } free(name); - name = xstrdup(mkpath(fmt, argv[i])); + name = xstrdup(mkpath(fmt, bname.buf)); if (!resolve_ref(name, sha1, 1, NULL)) { error("%sbranch '%s' not found.", - remote, argv[i]); + remote, bname.buf); ret = 1; continue; } @@ -153,23 +158,26 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) if (!force && !in_merge_bases(rev, &head_rev, 1)) { error("The branch '%s' is not an ancestor of " - "your current HEAD.\n" - "If you are sure you want to delete it, " - "run 'git branch -D %s'.", argv[i], argv[i]); + "your current HEAD.\n" + "If you are sure you want to delete it, " + "run 'git branch -D %s'.", bname.buf, bname.buf); ret = 1; continue; } - if (delete_ref(name, sha1)) { + if (delete_ref(name, sha1, 0)) { error("Error deleting %sbranch '%s'", remote, - argv[i]); + bname.buf); ret = 1; } else { - printf("Deleted %sbranch %s.\n", remote, argv[i]); - snprintf(section, sizeof(section), "branch.%s", - argv[i]); - if (git_config_rename_section(section, NULL) < 0) + struct strbuf buf = STRBUF_INIT; + printf("Deleted %sbranch %s (%s).\n", remote, + bname.buf, + find_unique_abbrev(sha1, DEFAULT_ABBREV)); + strbuf_addf(&buf, "branch.%s", bname.buf); + if (git_config_rename_section(buf.buf, NULL) < 0) warning("Update of config-file failed"); + strbuf_release(&buf); } } @@ -192,21 +200,6 @@ struct ref_list { int kinds; }; -static int has_commit(struct commit *commit, struct commit_list *with_commit) -{ - if (!with_commit) - return 1; - while (with_commit) { - struct commit *other; - - other = with_commit->item; - with_commit = with_commit->next; - if (in_merge_bases(other, &commit, 1)) - return 1; - } - return 0; -} - static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct ref_list *ref_list = (struct ref_list*)(cb_data); @@ -230,7 +223,7 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags, return error("branch '%s' does not point at a commit", refname); /* Filter with with_commit if specified */ - if (!has_commit(commit, ref_list->with_commit)) + if (!is_descendant_of(commit, ref_list->with_commit)) return 0; /* Don't add types the caller doesn't want */ @@ -279,7 +272,7 @@ static int ref_cmp(const void *r1, const void *r2) return strcmp(c1->name, c2->name); } -static void fill_tracking_info(char *stat, const char *branch_name) +static void fill_tracking_info(struct strbuf *stat, const char *branch_name) { int ours, theirs; struct branch *branch = branch_get(branch_name); @@ -287,11 +280,11 @@ static void fill_tracking_info(char *stat, const char *branch_name) if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs)) return; if (!ours) - sprintf(stat, "[behind %d] ", theirs); + strbuf_addf(stat, "[behind %d] ", theirs); else if (!theirs) - sprintf(stat, "[ahead %d] ", ours); + strbuf_addf(stat, "[ahead %d] ", ours); else - sprintf(stat, "[ahead %d, behind %d] ", ours, theirs); + strbuf_addf(stat, "[ahead %d, behind %d] ", ours, theirs); } static int matches_merge_filter(struct commit *commit) @@ -334,12 +327,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, } if (verbose) { - struct strbuf subject; + struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT; const char *sub = " **** invalid ref ****"; - char stat[128]; - - strbuf_init(&subject, 0); - stat[0] = '\0'; commit = item->commit; if (commit && !parse_commit(commit)) { @@ -349,13 +338,14 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, } if (item->kind == REF_LOCAL_BRANCH) - fill_tracking_info(stat, item->name); + fill_tracking_info(&stat, item->name); printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color), maxwidth, item->name, branch_get_color(COLOR_BRANCH_RESET), find_unique_abbrev(item->commit->object.sha1, abbrev), - stat, sub); + stat.buf, sub); + strbuf_release(&stat); strbuf_release(&subject); } else { printf("%c %s%s%s\n", c, branch_get_color(color), item->name, @@ -403,7 +393,8 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); - if (detached && head_commit && has_commit(head_commit, with_commit)) { + if (detached && head_commit && + is_descendant_of(head_commit, with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; @@ -427,58 +418,45 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str static void rename_branch(const char *oldname, const char *newname, int force) { - char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100]; + struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT; unsigned char sha1[20]; - char oldsection[PATH_MAX], newsection[PATH_MAX]; + struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT; if (!oldname) die("cannot rename the current branch while not on any."); - if (snprintf(oldref, sizeof(oldref), "refs/heads/%s", oldname) > sizeof(oldref)) - die("Old branchname too long"); + strbuf_addf(&oldref, "refs/heads/%s", oldname); - if (check_ref_format(oldref)) - die("Invalid branch name: %s", oldref); + if (check_ref_format(oldref.buf)) + die("Invalid branch name: %s", oldref.buf); - if (snprintf(newref, sizeof(newref), "refs/heads/%s", newname) > sizeof(newref)) - die("New branchname too long"); + strbuf_addf(&newref, "refs/heads/%s", newname); - if (check_ref_format(newref)) - die("Invalid branch name: %s", newref); + if (check_ref_format(newref.buf)) + die("Invalid branch name: %s", newref.buf); - if (resolve_ref(newref, sha1, 1, NULL) && !force) + if (resolve_ref(newref.buf, sha1, 1, NULL) && !force) die("A branch named '%s' already exists.", newname); - snprintf(logmsg, sizeof(logmsg), "Branch: renamed %s to %s", - oldref, newref); + strbuf_addf(&logmsg, "Branch: renamed %s to %s", + oldref.buf, newref.buf); - if (rename_ref(oldref, newref, logmsg)) + if (rename_ref(oldref.buf, newref.buf, logmsg.buf)) die("Branch rename failed"); + strbuf_release(&logmsg); /* no need to pass logmsg here as HEAD didn't really move */ - if (!strcmp(oldname, head) && create_symref("HEAD", newref, NULL)) + if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL)) die("Branch renamed to %s, but HEAD is not updated!", newname); - snprintf(oldsection, sizeof(oldsection), "branch.%s", oldref + 11); - snprintf(newsection, sizeof(newsection), "branch.%s", newref + 11); - if (git_config_rename_section(oldsection, newsection) < 0) + strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11); + strbuf_release(&oldref); + strbuf_addf(&newsection, "branch.%s", newref.buf + 11); + strbuf_release(&newref); + if (git_config_rename_section(oldsection.buf, newsection.buf) < 0) die("Branch is renamed, but update of config-file failed"); -} - -static int opt_parse_with_commit(const struct option *opt, const char *arg, int unset) -{ - unsigned char sha1[20]; - struct commit *commit; - - if (!arg) - return -1; - if (get_sha1(arg, sha1)) - die("malformed object name %s", arg); - commit = lookup_commit_reference(sha1); - if (!commit) - die("no such commit %s", arg); - commit_list_insert(commit, opt->value); - return 0; + strbuf_release(&oldsection); + strbuf_release(&newsection); } static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset) @@ -516,13 +494,13 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPTION_CALLBACK, 0, "contains", &with_commit, "commit", "print only branches that contain the commit", PARSE_OPT_LASTARG_DEFAULT, - opt_parse_with_commit, (intptr_t)"HEAD", + parse_opt_with_commit, (intptr_t)"HEAD", }, { OPTION_CALLBACK, 0, "with", &with_commit, "commit", "print only branches that contain the commit", PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT, - opt_parse_with_commit, (intptr_t) "HEAD", + parse_opt_with_commit, (intptr_t) "HEAD", }, OPT__ABBREV(&abbrev), |