aboutsummaryrefslogtreecommitdiff
path: root/builtin-branch.c
diff options
context:
space:
mode:
authorDaniel Barkalow <barkalow@iabervon.org>2008-02-07 11:40:08 -0500
committerJunio C Hamano <gitster@pobox.com>2008-02-09 23:16:51 -0800
commite496c00348140e73bdd202443df52192f6928541 (patch)
tree4c14c048a7cf56b8c5cc4a1ef5d51eb24cde04c8 /builtin-branch.c
parente1b3a2cad79a8138d18593c6eb3c46906ad2ee42 (diff)
downloadgit-e496c00348140e73bdd202443df52192f6928541.tar.gz
git-e496c00348140e73bdd202443df52192f6928541.tar.xz
Move create_branch into a library file
You can also create branches, in exactly the same way, with checkout -b. This introduces branch.{c,h} library files for doing porcelain-level operations on branches (such as creating them with their appropriate default configuration). Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Diffstat (limited to 'builtin-branch.c')
-rw-r--r--builtin-branch.c138
1 files changed, 2 insertions, 136 deletions
diff --git a/builtin-branch.c b/builtin-branch.c
index 089cae592..1e0c9dea3 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,6 +12,7 @@
#include "builtin.h"
#include "remote.h"
#include "parse-options.h"
+#include "branch.h"
static const char * const builtin_branch_usage[] = {
"git-branch [options] [-r | -a]",
@@ -356,141 +357,6 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
free_ref_list(&ref_list);
}
-struct tracking {
- struct refspec spec;
- char *src;
- const char *remote;
- int matches;
-};
-
-static int find_tracked_branch(struct remote *remote, void *priv)
-{
- struct tracking *tracking = priv;
-
- if (!remote_find_tracking(remote, &tracking->spec)) {
- if (++tracking->matches == 1) {
- tracking->src = tracking->spec.src;
- tracking->remote = remote->name;
- } else {
- free(tracking->spec.src);
- if (tracking->src) {
- free(tracking->src);
- tracking->src = NULL;
- }
- }
- tracking->spec.src = NULL;
- }
-
- return 0;
-}
-
-
-/*
- * This is called when new_ref is branched off of orig_ref, and tries
- * to infer the settings for branch.<new_ref>.{remote,merge} from the
- * config.
- */
-static int setup_tracking(const char *new_ref, const char *orig_ref)
-{
- char key[1024];
- struct tracking tracking;
-
- if (strlen(new_ref) > 1024 - 7 - 7 - 1)
- return error("Tracking not set up: name too long: %s",
- new_ref);
-
- memset(&tracking, 0, sizeof(tracking));
- tracking.spec.dst = (char *)orig_ref;
- if (for_each_remote(find_tracked_branch, &tracking) ||
- !tracking.matches)
- return 1;
-
- if (tracking.matches > 1)
- return error("Not tracking: ambiguous information for ref %s",
- orig_ref);
-
- if (tracking.matches == 1) {
- sprintf(key, "branch.%s.remote", new_ref);
- git_config_set(key, tracking.remote ? tracking.remote : ".");
- sprintf(key, "branch.%s.merge", new_ref);
- git_config_set(key, tracking.src);
- free(tracking.src);
- printf("Branch %s set up to track remote branch %s.\n",
- new_ref, orig_ref);
- }
-
- return 0;
-}
-
-static void create_branch(const char *name, const char *start_name,
- int force, int reflog, int track)
-{
- struct ref_lock *lock;
- struct commit *commit;
- unsigned char sha1[20];
- char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
- int forcing = 0;
-
- snprintf(ref, sizeof ref, "refs/heads/%s", name);
- if (check_ref_format(ref))
- die("'%s' is not a valid branch name.", name);
-
- if (resolve_ref(ref, sha1, 1, NULL)) {
- if (!force)
- die("A branch named '%s' already exists.", name);
- else if (!is_bare_repository() && !strcmp(head, name))
- die("Cannot force update the current branch.");
- forcing = 1;
- }
-
- real_ref = NULL;
- if (get_sha1(start_name, sha1))
- die("Not a valid object name: '%s'.", start_name);
-
- switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
- case 0:
- /* Not branching from any existing branch */
- real_ref = NULL;
- break;
- case 1:
- /* Unique completion -- good */
- break;
- default:
- die("Ambiguous object name: '%s'.", start_name);
- break;
- }
-
- if ((commit = lookup_commit_reference(sha1)) == NULL)
- die("Not a valid branch point: '%s'.", start_name);
- hashcpy(sha1, commit->object.sha1);
-
- lock = lock_any_ref_for_update(ref, NULL, 0);
- if (!lock)
- die("Failed to lock ref for update: %s.", strerror(errno));
-
- if (reflog)
- log_all_ref_updates = 1;
-
- if (forcing)
- snprintf(msg, sizeof msg, "branch: Reset from %s",
- start_name);
- else
- snprintf(msg, sizeof msg, "branch: Created from %s",
- start_name);
-
- /* When branching off a remote branch, set up so that git-pull
- automatically merges from there. So far, this is only done for
- remotes registered via .git/config. */
- if (real_ref && track)
- setup_tracking(name, real_ref);
-
- if (write_ref_sha1(lock, sha1, msg) < 0)
- die("Failed to write ref: %s.", strerror(errno));
-
- if (real_ref)
- free(real_ref);
-}
-
static void rename_branch(const char *oldname, const char *newname, int force)
{
char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
@@ -611,7 +477,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
else if (rename && (argc == 2))
rename_branch(argv[0], argv[1], rename > 1);
else if (argc <= 2)
- create_branch(argv[0], (argc == 2) ? argv[1] : head,
+ create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
force_create, reflog, track);
else
usage_with_options(builtin_branch_usage, options);