git symbolic-ref --delete $symref
Teach symbolic-ref to delete symrefs by adding the -d/--delete option to git-symbolic-ref. Both proper and dangling symrefs are deleted by this option, but other refs - or anything else that is not a symref - is not. The symref deletion is performed by first verifying that we are given a proper symref, and then invoking delete_ref() on it with the REF_NODEREF flag. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									87a5461fa7
								
							
						
					
					
						commit
						9ab55daa55
					
				|  | @ -3,13 +3,14 @@ git-symbolic-ref(1) | ||||||
|  |  | ||||||
| NAME | NAME | ||||||
| ---- | ---- | ||||||
| git-symbolic-ref - Read and modify symbolic refs | git-symbolic-ref - Read, modify and delete symbolic refs | ||||||
|  |  | ||||||
| SYNOPSIS | SYNOPSIS | ||||||
| -------- | -------- | ||||||
| [verse] | [verse] | ||||||
| 'git symbolic-ref' [-m <reason>] <name> <ref> | 'git symbolic-ref' [-m <reason>] <name> <ref> | ||||||
| 'git symbolic-ref' [-q] [--short] <name> | 'git symbolic-ref' [-q] [--short] <name> | ||||||
|  | 'git symbolic-ref' --delete [-q] <name> | ||||||
|  |  | ||||||
| DESCRIPTION | DESCRIPTION | ||||||
| ----------- | ----------- | ||||||
|  | @ -21,6 +22,9 @@ argument to see which branch your working tree is on. | ||||||
| Given two arguments, creates or updates a symbolic ref <name> to | Given two arguments, creates or updates a symbolic ref <name> to | ||||||
| point at the given branch <ref>. | point at the given branch <ref>. | ||||||
|  |  | ||||||
|  | Given `--delete` and an additional argument, deletes the given | ||||||
|  | symbolic ref. | ||||||
|  |  | ||||||
| A symbolic ref is a regular file that stores a string that | A symbolic ref is a regular file that stores a string that | ||||||
| begins with `ref: refs/`.  For example, your `.git/HEAD` is | begins with `ref: refs/`.  For example, your `.git/HEAD` is | ||||||
| a regular file whose contents is `ref: refs/heads/master`. | a regular file whose contents is `ref: refs/heads/master`. | ||||||
|  | @ -28,6 +32,10 @@ a regular file whose contents is `ref: refs/heads/master`. | ||||||
| OPTIONS | OPTIONS | ||||||
| ------- | ------- | ||||||
|  |  | ||||||
|  | -d:: | ||||||
|  | --delete:: | ||||||
|  | 	Delete the symbolic ref <name>. | ||||||
|  |  | ||||||
| -q:: | -q:: | ||||||
| --quiet:: | --quiet:: | ||||||
| 	Do not issue an error message if the <name> is not a | 	Do not issue an error message if the <name> is not a | ||||||
|  |  | ||||||
|  | @ -5,12 +5,11 @@ | ||||||
|  |  | ||||||
| static const char * const git_symbolic_ref_usage[] = { | static const char * const git_symbolic_ref_usage[] = { | ||||||
| 	N_("git symbolic-ref [options] name [ref]"), | 	N_("git symbolic-ref [options] name [ref]"), | ||||||
|  | 	N_("git symbolic-ref -d [-q] name"), | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int shorten; | static int check_symref(const char *HEAD, int quiet, int shorten, int print) | ||||||
|  |  | ||||||
| static void check_symref(const char *HEAD, int quiet) |  | ||||||
| { | { | ||||||
| 	unsigned char sha1[20]; | 	unsigned char sha1[20]; | ||||||
| 	int flag; | 	int flag; | ||||||
|  | @ -22,20 +21,24 @@ static void check_symref(const char *HEAD, int quiet) | ||||||
| 		if (!quiet) | 		if (!quiet) | ||||||
| 			die("ref %s is not a symbolic ref", HEAD); | 			die("ref %s is not a symbolic ref", HEAD); | ||||||
| 		else | 		else | ||||||
| 			exit(1); | 			return 1; | ||||||
| 	} | 	} | ||||||
| 	if (shorten) | 	if (print) { | ||||||
| 		refname = shorten_unambiguous_ref(refname, 0); | 		if (shorten) | ||||||
| 	puts(refname); | 			refname = shorten_unambiguous_ref(refname, 0); | ||||||
|  | 		puts(refname); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) | int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) | ||||||
| { | { | ||||||
| 	int quiet = 0; | 	int quiet = 0, delete = 0, shorten = 0, ret = 0; | ||||||
| 	const char *msg = NULL; | 	const char *msg = NULL; | ||||||
| 	struct option options[] = { | 	struct option options[] = { | ||||||
| 		OPT__QUIET(&quiet, | 		OPT__QUIET(&quiet, | ||||||
| 			N_("suppress error message for non-symbolic (detached) refs")), | 			N_("suppress error message for non-symbolic (detached) refs")), | ||||||
|  | 		OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")), | ||||||
| 		OPT_BOOL(0, "short", &shorten, N_("shorten ref output")), | 		OPT_BOOL(0, "short", &shorten, N_("shorten ref output")), | ||||||
| 		OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")), | 		OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")), | ||||||
| 		OPT_END(), | 		OPT_END(), | ||||||
|  | @ -46,9 +49,19 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) | ||||||
| 			     git_symbolic_ref_usage, 0); | 			     git_symbolic_ref_usage, 0); | ||||||
| 	if (msg &&!*msg) | 	if (msg &&!*msg) | ||||||
| 		die("Refusing to perform update with empty message"); | 		die("Refusing to perform update with empty message"); | ||||||
|  |  | ||||||
|  | 	if (delete) { | ||||||
|  | 		if (argc != 1) | ||||||
|  | 			usage_with_options(git_symbolic_ref_usage, options); | ||||||
|  | 		ret = check_symref(argv[0], 1, 0, 0); | ||||||
|  | 		if (ret) | ||||||
|  | 			die("Cannot delete %s, not a symbolic ref", argv[0]); | ||||||
|  | 		return delete_ref(argv[0], NULL, REF_NODEREF); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	switch (argc) { | 	switch (argc) { | ||||||
| 	case 1: | 	case 1: | ||||||
| 		check_symref(argv[0], quiet); | 		ret = check_symref(argv[0], quiet, shorten, 1); | ||||||
| 		break; | 		break; | ||||||
| 	case 2: | 	case 2: | ||||||
| 		if (!strcmp(argv[0], "HEAD") && | 		if (!strcmp(argv[0], "HEAD") && | ||||||
|  | @ -59,5 +72,5 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) | ||||||
| 	default: | 	default: | ||||||
| 		usage_with_options(git_symbolic_ref_usage, options); | 		usage_with_options(git_symbolic_ref_usage, options); | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,4 +33,34 @@ test_expect_success 'symbolic-ref refuses bare sha1' ' | ||||||
| ' | ' | ||||||
| reset_to_sane | reset_to_sane | ||||||
|  |  | ||||||
|  | test_expect_success 'symbolic-ref deletes HEAD' ' | ||||||
|  | 	git symbolic-ref -d HEAD && | ||||||
|  | 	test_path_is_file .git/refs/heads/foo && | ||||||
|  | 	test_path_is_missing .git/HEAD | ||||||
|  | ' | ||||||
|  | reset_to_sane | ||||||
|  |  | ||||||
|  | test_expect_success 'symbolic-ref deletes dangling HEAD' ' | ||||||
|  | 	git symbolic-ref HEAD refs/heads/missing && | ||||||
|  | 	git symbolic-ref -d HEAD && | ||||||
|  | 	test_path_is_missing .git/refs/heads/missing && | ||||||
|  | 	test_path_is_missing .git/HEAD | ||||||
|  | ' | ||||||
|  | reset_to_sane | ||||||
|  |  | ||||||
|  | test_expect_success 'symbolic-ref fails to delete missing FOO' ' | ||||||
|  | 	echo "fatal: Cannot delete FOO, not a symbolic ref" >expect && | ||||||
|  | 	test_must_fail git symbolic-ref -d FOO >actual 2>&1 && | ||||||
|  | 	test_cmp expect actual | ||||||
|  | ' | ||||||
|  | reset_to_sane | ||||||
|  |  | ||||||
|  | test_expect_success 'symbolic-ref fails to delete real ref' ' | ||||||
|  | 	echo "fatal: Cannot delete refs/heads/foo, not a symbolic ref" >expect && | ||||||
|  | 	test_must_fail git symbolic-ref -d refs/heads/foo >actual 2>&1 && | ||||||
|  | 	test_path_is_file .git/refs/heads/foo && | ||||||
|  | 	test_cmp expect actual | ||||||
|  | ' | ||||||
|  | reset_to_sane | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Johan Herland
						Johan Herland