From: Jonas Fonseca <fonseca@diku.dk>
To: "Kristian Høgsberg" <hoegsberg@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] branch as a builtin (again)
Date: Mon, 21 Aug 2006 12:13:46 +0200 [thread overview]
Message-ID: <20060821101346.GA527@diku.dk> (raw)
In-Reply-To: <59ad55d30608201422h4a6d40f7y7782212637380438@mail.gmail.com>
Kristian Høgsberg <hoegsberg@gmail.com> wrote Sun, Aug 20, 2006:
> diff --git a/builtin-branch.c b/builtin-branch.c
> new file mode 100644
> index 0000000..25c6313
> --- /dev/null
> +++ b/builtin-branch.c
> @@ -0,0 +1,170 @@
> +/*
> + * Builtin "git branch"
> + *
> + * Copyright (c) 2006 Kristian Høgsberg <krh@redhat.com>
> + * Based on git-branch.sh by Junio C Hamano.
> + */
> +
> +#include "cache.h"
> +#include "refs.h"
> +#include "commit.h"
> +#include "builtin.h"
> +
> +static const char builtin_branch_usage[] =
> + "git-branch [(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]] | -r";
The norm seems to be that the usage string should not be indented.
> +
> +
> +static int remote_only = 0;
This could be local to cmd_branch.
> +static const char *head;
> +static unsigned char head_sha1[20];
> +
> +static int in_merge_bases(const unsigned char *sha1,
> + struct commit *rev1,
> + struct commit *rev2)
> +{
> + struct commit_list *bases, *b;
> +
> + bases = get_merge_bases(rev1, rev2, 1);
> + for (b = bases; b != NULL; b = b->next) {
> + if (!hashcmp(sha1, b->item->object.sha1)) {
> + free_commit_list(bases);
> + return 1;
> + }
> + }
> +
> + free_commit_list(bases);
> + return 0;
> +}
> +
> +static void delete_branches(int argc, const char **argv, int force)
> +{
> + struct commit *rev1, *rev2;
> + unsigned char sha1[20];
> + const char *p, *name;
> + int i;
> +
> + for (i = 0; i < argc; i++) {
> + if (!strcmp(head, argv[i]))
> + die("Cannot delete the branch you are currently on.");
> +
> + name = git_path("refs/heads/%s", argv[i]);
> + p = resolve_ref(name, sha1, 1);
> + if (p == NULL)
> + die("Branch '%s' not found.", argv[i]);
> +
> + rev1 = lookup_commit_reference(sha1);
> + rev2 = lookup_commit_reference(head_sha1);
> + if (!rev1 || !rev2)
> + die("Couldn't look up commit objects.");
> +
> + /* This checks wether the merge bases of branch and
whether
> + * HEAD contains branch -- which means that the HEAD
> + * contains everything in both.
> + */
> +
> + if (!force &&
> + !in_merge_bases(sha1, rev1, rev2)) {
> + fprintf(stderr,
> + "The branch '%s' is not a strict subset of your current HEAD.\n"
> + "If you are sure you want to delete it, run 'git branch -D %s'.\n",
> + argv[i], argv[i]);
> + exit(1);
> + }
> +
> + unlink(name);
> + printf("Deleted branch %s.\n", argv[i]);
> + }
> +}
> +
> +static int show_reference(const char *refname, const unsigned char *sha1)
> +{
> + int is_head = !strcmp(refname, head);
> +
> + printf("%c %s\n", (is_head ? '*' : ' '), refname);
> +
> + return 0;
> +}
> +
> +static void create_branch (const char *name, const char *start, int force)
> +{
> + struct ref_lock *lock;
> + unsigned char sha1[20];
> + char ref[PATH_MAX];
> +
> + snprintf(ref, sizeof ref, "refs/heads/%s", name);
> + if (check_ref_format(ref + 5))
> + die("'%s' is not a valid branch name.", name);
Why not simply check_ref_format(name)?
> +
> + if (resolve_ref(ref, sha1, 1)) {
All other places that call resolve_ref passes a ref created with
git_path. I don't know if this should too.
> + if (!force)
> + die("A branch named '%s' already exists.", name);
> + else if (!strcmp(head, name))
> + die("Cannot force update the current branch.");
> + }
> +
> + if (get_sha1(start, sha1))
> + die("Not a valid branch point: '%s'", start);
Missing punctuation at the end.
> +
> + lock = lock_any_ref_for_update(ref, NULL, 0);
> + if (!lock)
> + die("Failed to lock ref for update: %s.", strerror(errno));
> + if (write_ref_sha1(lock, sha1, NULL) < 0)
> + die("Failed to write ref: %s.", strerror(errno));
> +}
> +
> +int cmd_branch(int argc, const char **argv, const char *prefix)
> +{
> + int delete = 0, force_delete = 0, force_create = 0;
> + int i, prefix_length;
> + const char *p;
> +
> + git_config(git_default_config);
> +
> + for (i = 1; i < argc; i++) {
> + const char *arg = argv[i];
> +
> + if (arg[0] != '-')
> + break;
> + if (!strcmp(arg, "--")) {
> + i++;
> + break;
> + }
> + if (!strcmp(arg, "-d")) {
> + delete = 1;
> + continue;
> + }
> + if (!strcmp(arg, "-D")) {
> + delete = 1;
> + force_delete = 1;
> + continue;
> + }
> + if (!strcmp(arg, "-f")) {
> + force_create = 1;
> + continue;
> + }
> + if (!strcmp(arg, "-r")) {
> + remote_only = 1;
> + continue;
> + }
> + die(builtin_branch_usage);
Perhaps usage() would be more appropriate here.
> + }
> +
> + prefix_length = strlen(git_path("refs/heads/"));
> + p = resolve_ref(git_path("HEAD"), head_sha1, 0);
> + if (!p)
> + die("Failed to resolve HEAD as a valid ref");
Ending punctuation.
> + head = strdup(p + prefix_length);
> +
> + if (delete)
> + delete_branches(argc - i, argv + i, force_delete);
> + else if (i == argc && remote_only)
> + for_each_remote_ref(show_reference);
> + else if (i == argc)
> + for_each_branch_ref(show_reference);
> + else if (argc - i == 1)
> + create_branch (argv[i], head, force_create);
> + else
> + create_branch (argv[i], argv[i + 1], force_create);
It would be more consistent to leave out the space before the
paranthesis. Also goes for the implementation of create_branch as
already mentioned.
> +
> + return 0;
> +}
--
Jonas Fonseca
next prev parent reply other threads:[~2006-08-21 10:13 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-08-20 21:22 [PATCH] branch as a builtin (again) Kristian Høgsberg
2006-08-20 23:55 ` Johannes Schindelin
2006-08-21 7:49 ` David Rientjes
2006-08-21 8:03 ` Shawn Pearce
2006-08-21 10:13 ` Jonas Fonseca [this message]
2006-08-21 20:12 ` Kristian Høgsberg
2006-08-21 20:23 ` David Rientjes
2006-08-21 20:45 ` Kristian Høgsberg
2006-08-22 7:00 ` Junio C Hamano
2006-08-21 20:27 ` Johannes Schindelin
2006-08-21 21:07 ` Kristian Høgsberg
[not found] ` <59ad55d30608211337jabd515bra3566fbd0f7ba5a0@mail.gmail.com>
2006-08-21 21:25 ` Johannes Schindelin
2006-08-21 20:41 ` Shawn Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060821101346.GA527@diku.dk \
--to=fonseca@diku.dk \
--cc=git@vger.kernel.org \
--cc=hoegsberg@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.