builtin-branch.c 11.6 KB
Newer Older
L
Lars Hjemli 已提交
1 2 3 4 5 6 7 8
/*
 * Builtin "git branch"
 *
 * Copyright (c) 2006 Kristian Hgsberg <krh@redhat.com>
 * Based on git-branch.sh by Junio C Hamano.
 */

#include "cache.h"
9
#include "color.h"
L
Lars Hjemli 已提交
10 11 12 13 14
#include "refs.h"
#include "commit.h"
#include "builtin.h"

static const char builtin_branch_usage[] =
15
  "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
L
Lars Hjemli 已提交
16

17 18 19 20
#define REF_UNKNOWN_TYPE    0x00
#define REF_LOCAL_BRANCH    0x01
#define REF_REMOTE_BRANCH   0x02
#define REF_TAG             0x04
L
Lars Hjemli 已提交
21 22 23 24

static const char *head;
static unsigned char head_sha1[20];

A
Andy Parkins 已提交
25 26 27 28 29
static int branch_use_color;
static char branch_colors[][COLOR_MAXLEN] = {
	"\033[m",	/* reset */
	"",		/* PLAIN (normal) */
	"\033[31m",	/* REMOTE (red) */
30 31
	"",		/* LOCAL (normal) */
	"\033[32m",	/* CURRENT (green) */
A
Andy Parkins 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
};
enum color_branch {
	COLOR_BRANCH_RESET = 0,
	COLOR_BRANCH_PLAIN = 1,
	COLOR_BRANCH_REMOTE = 2,
	COLOR_BRANCH_LOCAL = 3,
	COLOR_BRANCH_CURRENT = 4,
};

static int parse_branch_color_slot(const char *var, int ofs)
{
	if (!strcasecmp(var+ofs, "plain"))
		return COLOR_BRANCH_PLAIN;
	if (!strcasecmp(var+ofs, "reset"))
		return COLOR_BRANCH_RESET;
	if (!strcasecmp(var+ofs, "remote"))
		return COLOR_BRANCH_REMOTE;
	if (!strcasecmp(var+ofs, "local"))
		return COLOR_BRANCH_LOCAL;
	if (!strcasecmp(var+ofs, "current"))
		return COLOR_BRANCH_CURRENT;
	die("bad config variable '%s'", var);
}

int git_branch_config(const char *var, const char *value)
{
	if (!strcmp(var, "color.branch")) {
		branch_use_color = git_config_colorbool(var, value);
		return 0;
	}
	if (!strncmp(var, "color.branch.", 13)) {
		int slot = parse_branch_color_slot(var, 13);
		color_parse(value, var, branch_colors[slot]);
		return 0;
	}
	return git_default_config(var, value);
}

const char *branch_get_color(enum color_branch ix)
{
	if (branch_use_color)
		return branch_colors[ix];
	return "";
}

77
static int delete_branches(int argc, const char **argv, int force, int kinds)
L
Lars Hjemli 已提交
78
{
79
	struct commit *rev, *head_rev = head_rev;
L
Lars Hjemli 已提交
80
	unsigned char sha1[20];
81
	char *name = NULL;
82
	const char *fmt, *remote;
L
Lars Hjemli 已提交
83
	int i;
84
	int ret = 0;
L
Lars Hjemli 已提交
85

86 87 88 89 90 91 92 93 94 95 96 97 98
	switch (kinds) {
	case REF_REMOTE_BRANCH:
		fmt = "refs/remotes/%s";
		remote = "remote ";
		force = 1;
		break;
	case REF_LOCAL_BRANCH:
		fmt = "refs/heads/%s";
		remote = "";
		break;
	default:
		die("cannot use -a with -d");
	}
L
Lars Hjemli 已提交
99

100 101 102 103 104
	if (!force) {
		head_rev = lookup_commit_reference(head_sha1);
		if (!head_rev)
			die("Couldn't look up commit object for HEAD");
	}
L
Lars Hjemli 已提交
105
	for (i = 0; i < argc; i++) {
106 107 108 109 110 111 112 113 114
		if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) {
			error("Cannot delete the branch '%s' "
				"which you are currently on.", argv[i]);
			ret = 1;
			continue;
		}

		if (name)
			free(name);
L
Lars Hjemli 已提交
115

116
		name = xstrdup(mkpath(fmt, argv[i]));
117 118 119 120 121 122
		if (!resolve_ref(name, sha1, 1, NULL)) {
			error("%sbranch '%s' not found.",
					remote, argv[i]);
			ret = 1;
			continue;
		}
L
Lars Hjemli 已提交
123 124

		rev = lookup_commit_reference(sha1);
125 126 127 128 129
		if (!rev) {
			error("Couldn't look up commit object for '%s'", name);
			ret = 1;
			continue;
		}
L
Lars Hjemli 已提交
130 131 132 133 134 135 136

		/* This checks whether the merge bases of branch and
		 * HEAD contains branch -- which means that the HEAD
		 * contains everything in both.
		 */

		if (!force &&
J
Junio C Hamano 已提交
137
		    !in_merge_bases(rev, head_rev)) {
138 139 140 141 142 143
			error("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'.", argv[i], argv[i]);
			ret = 1;
			continue;
L
Lars Hjemli 已提交
144 145
		}

146 147
		if (delete_ref(name, sha1)) {
			error("Error deleting %sbranch '%s'", remote,
148
			       argv[i]);
149 150
			ret = 1;
		} else
151
			printf("Deleted %sbranch %s.\n", remote, argv[i]);
L
Lars Hjemli 已提交
152 153 154

	}

155 156 157 158
	if (name)
		free(name);

	return(ret);
L
Lars Hjemli 已提交
159 160
}

161 162 163
struct ref_item {
	char *name;
	unsigned int kind;
164
	unsigned char sha1[20];
165 166 167
};

struct ref_list {
168
	int index, alloc, maxwidth;
169 170 171 172 173
	struct ref_item *list;
	int kinds;
};

static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
L
Lars Hjemli 已提交
174
{
175 176 177
	struct ref_list *ref_list = (struct ref_list*)(cb_data);
	struct ref_item *newitem;
	int kind = REF_UNKNOWN_TYPE;
178
	int len;
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

	/* Detect kind */
	if (!strncmp(refname, "refs/heads/", 11)) {
		kind = REF_LOCAL_BRANCH;
		refname += 11;
	} else if (!strncmp(refname, "refs/remotes/", 13)) {
		kind = REF_REMOTE_BRANCH;
		refname += 13;
	} else if (!strncmp(refname, "refs/tags/", 10)) {
		kind = REF_TAG;
		refname += 10;
	}

	/* Don't add types the caller doesn't want */
	if ((kind & ref_list->kinds) == 0)
		return 0;

	/* Resize buffer */
	if (ref_list->index >= ref_list->alloc) {
		ref_list->alloc = alloc_nr(ref_list->alloc);
		ref_list->list = xrealloc(ref_list->list,
				ref_list->alloc * sizeof(struct ref_item));
L
Lars Hjemli 已提交
201 202
	}

203 204 205 206
	/* Record the new item */
	newitem = &(ref_list->list[ref_list->index++]);
	newitem->name = xstrdup(refname);
	newitem->kind = kind;
207 208 209 210
	hashcpy(newitem->sha1, sha1);
	len = strlen(newitem->name);
	if (len > ref_list->maxwidth)
		ref_list->maxwidth = len;
L
Lars Hjemli 已提交
211 212 213 214

	return 0;
}

215 216 217 218 219 220 221 222 223
static void free_ref_list(struct ref_list *ref_list)
{
	int i;

	for (i = 0; i < ref_list->index; i++)
		free(ref_list->list[i].name);
	free(ref_list->list);
}

L
Lars Hjemli 已提交
224 225
static int ref_cmp(const void *r1, const void *r2)
{
226 227 228 229 230 231
	struct ref_item *c1 = (struct ref_item *)(r1);
	struct ref_item *c2 = (struct ref_item *)(r2);

	if (c1->kind != c2->kind)
		return c1->kind - c2->kind;
	return strcmp(c1->name, c2->name);
L
Lars Hjemli 已提交
232 233
}

234 235
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
			   int abbrev, int current)
236
{
237 238
	char c;
	int color;
239 240 241
	struct commit *commit;
	char subject[256];

242 243 244 245 246 247 248 249 250 251 252
	switch (item->kind) {
	case REF_LOCAL_BRANCH:
		color = COLOR_BRANCH_LOCAL;
		break;
	case REF_REMOTE_BRANCH:
		color = COLOR_BRANCH_REMOTE;
		break;
	default:
		color = COLOR_BRANCH_PLAIN;
		break;
	}
253

254 255 256 257 258
	c = ' ';
	if (current) {
		c = '*';
		color = COLOR_BRANCH_CURRENT;
	}
259

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
	if (verbose) {
		commit = lookup_commit(item->sha1);
		if (commit && !parse_commit(commit))
			pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
					    subject, sizeof(subject), 0,
					    NULL, NULL, 0);
		else
			strcpy(subject, " **** invalid ref ****");
		printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
		       maxwidth, item->name,
		       branch_get_color(COLOR_BRANCH_RESET),
		       find_unique_abbrev(item->sha1, abbrev), subject);
	} else {
		printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
		       branch_get_color(COLOR_BRANCH_RESET));
	}
276 277
}

L
Lars Hjemli 已提交
278
static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
L
Lars Hjemli 已提交
279 280
{
	int i;
281
	struct ref_list ref_list;
L
Lars Hjemli 已提交
282

283 284 285
	memset(&ref_list, 0, sizeof(ref_list));
	ref_list.kinds = kinds;
	for_each_ref(append_ref, &ref_list);
L
Lars Hjemli 已提交
286

287
	qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
L
Lars Hjemli 已提交
288

L
Lars Hjemli 已提交
289 290 291 292 293 294 295 296 297 298 299
	detached = (detached && (kinds & REF_LOCAL_BRANCH));
	if (detached) {
		struct ref_item item;
		item.name = "(no branch)";
		item.kind = REF_LOCAL_BRANCH;
		hashcpy(item.sha1, head_sha1);
		if (strlen(item.name) > ref_list.maxwidth)
			      ref_list.maxwidth = strlen(item.name);
		print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
	}

300
	for (i = 0; i < ref_list.index; i++) {
L
Lars Hjemli 已提交
301 302
		int current = !detached &&
			(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
303 304 305
			!strcmp(ref_list.list[i].name, head);
		print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
			       abbrev, current);
L
Lars Hjemli 已提交
306
	}
307 308

	free_ref_list(&ref_list);
L
Lars Hjemli 已提交
309 310
}

J
Junio C Hamano 已提交
311 312
static void create_branch(const char *name, const char *start_name,
			  unsigned char *start_sha1,
L
Lars Hjemli 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326
			  int force, int reflog)
{
	struct ref_lock *lock;
	struct commit *commit;
	unsigned char sha1[20];
	char ref[PATH_MAX], msg[PATH_MAX + 20];

	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);
327
		else if (!is_bare_repository() && !strcmp(head, name))
L
Lars Hjemli 已提交
328 329 330
			die("Cannot force update the current branch.");
	}

J
Junio C Hamano 已提交
331 332 333 334 335 336 337 338
	if (start_sha1)
		/* detached HEAD */
		hashcpy(sha1, start_sha1);
	else if (get_sha1(start_name, sha1))
		die("Not a valid object name: '%s'.", start_name);

	if ((commit = lookup_commit_reference(sha1)) == NULL)
		die("Not a valid branch point: '%s'.", start_name);
L
Lars Hjemli 已提交
339 340 341 342 343 344 345 346
	hashcpy(sha1, commit->object.sha1);

	lock = lock_any_ref_for_update(ref, NULL);
	if (!lock)
		die("Failed to lock ref for update: %s.", strerror(errno));

	if (reflog) {
		log_all_ref_updates = 1;
J
Junio C Hamano 已提交
347 348
		snprintf(msg, sizeof msg, "branch: Created from %s",
			 start_name);
L
Lars Hjemli 已提交
349 350 351 352 353 354
	}

	if (write_ref_sha1(lock, sha1, msg) < 0)
		die("Failed to write ref: %s.", strerror(errno));
}

355 356
static void rename_branch(const char *oldname, const char *newname, int force)
{
357
	char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
358 359
	unsigned char sha1[20];

J
Junio C Hamano 已提交
360 361 362
	if (!oldname)
		die("cannot rename the curren branch while not on any.");

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
	if (snprintf(oldref, sizeof(oldref), "refs/heads/%s", oldname) > sizeof(oldref))
		die("Old branchname too long");

	if (check_ref_format(oldref))
		die("Invalid branch name: %s", oldref);

	if (snprintf(newref, sizeof(newref), "refs/heads/%s", newname) > sizeof(newref))
		die("New branchname too long");

	if (check_ref_format(newref))
		die("Invalid branch name: %s", newref);

	if (resolve_ref(newref, sha1, 1, NULL) && !force)
		die("A branch named '%s' already exists.", newname);

378 379 380 381
	snprintf(logmsg, sizeof(logmsg), "Branch: renamed %s to %s",
		 oldref, newref);

	if (rename_ref(oldref, newref, logmsg))
382 383 384 385 386 387
		die("Branch rename failed");

	if (!strcmp(oldname, head) && create_symref("HEAD", newref))
		die("Branch renamed to %s, but HEAD is not updated!", newname);
}

L
Lars Hjemli 已提交
388 389
int cmd_branch(int argc, const char **argv, const char *prefix)
{
390
	int delete = 0, force_delete = 0, force_create = 0;
391
	int rename = 0, force_rename = 0;
L
Lars Hjemli 已提交
392
	int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
L
Lars Hjemli 已提交
393
	int reflog = 0;
394
	int kinds = REF_LOCAL_BRANCH;
L
Lars Hjemli 已提交
395 396
	int i;

A
Andy Parkins 已提交
397
	git_config(git_branch_config);
L
Lars Hjemli 已提交
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420

	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;
		}
421 422 423 424 425 426 427 428 429
		if (!strcmp(arg, "-m")) {
			rename = 1;
			continue;
		}
		if (!strcmp(arg, "-M")) {
			rename = 1;
			force_rename = 1;
			continue;
		}
L
Lars Hjemli 已提交
430
		if (!strcmp(arg, "-r")) {
431 432 433 434 435
			kinds = REF_REMOTE_BRANCH;
			continue;
		}
		if (!strcmp(arg, "-a")) {
			kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
L
Lars Hjemli 已提交
436 437 438 439 440 441
			continue;
		}
		if (!strcmp(arg, "-l")) {
			reflog = 1;
			continue;
		}
442 443 444 445 446 447 448 449
		if (!strncmp(arg, "--abbrev=", 9)) {
			abbrev = atoi(arg+9);
			continue;
		}
		if (!strcmp(arg, "-v")) {
			verbose = 1;
			continue;
		}
A
Andy Parkins 已提交
450 451 452 453 454 455 456 457
		if (!strcmp(arg, "--color")) {
			branch_use_color = 1;
			continue;
		}
		if (!strcmp(arg, "--no-color")) {
			branch_use_color = 0;
			continue;
		}
L
Lars Hjemli 已提交
458 459 460
		usage(builtin_branch_usage);
	}

461 462 463 464
	if ((delete && rename) || (delete && force_create) ||
	    (rename && force_create))
		usage(builtin_branch_usage);

L
Lars Hjemli 已提交
465 466 467
	head = xstrdup(resolve_ref("HEAD", head_sha1, 0, NULL));
	if (!head)
		die("Failed to resolve HEAD as a valid ref.");
L
Lars Hjemli 已提交
468 469 470 471 472 473 474 475
	if (!strcmp(head, "HEAD")) {
		detached = 1;
	}
	else {
		if (strncmp(head, "refs/heads/", 11))
			die("HEAD not found below refs/heads!");
		head += 11;
	}
L
Lars Hjemli 已提交
476 477

	if (delete)
478
		return delete_branches(argc - i, argv + i, force_delete, kinds);
L
Lars Hjemli 已提交
479
	else if (i == argc)
L
Lars Hjemli 已提交
480
		print_ref_list(kinds, detached, verbose, abbrev);
481 482 483 484
	else if (rename && (i == argc - 1))
		rename_branch(head, argv[i], force_rename);
	else if (rename && (i == argc - 2))
		rename_branch(argv[i], argv[i + 1], force_rename);
L
Lars Hjemli 已提交
485
	else if (i == argc - 1)
J
Junio C Hamano 已提交
486
		create_branch(argv[i], head, head_sha1, force_create, reflog);
L
Lars Hjemli 已提交
487
	else if (i == argc - 2)
J
Junio C Hamano 已提交
488
		create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
L
Lars Hjemli 已提交
489 490 491 492 493
	else
		usage(builtin_branch_usage);

	return 0;
}