diff options
| author | David Turner <dturner@twopensource.com> | 2015-08-10 13:52:44 -0400 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2015-08-11 13:48:15 -0700 | 
| commit | 41af65651d4333cd19ab4af3509fa2d08f3816ed (patch) | |
| tree | 19a55a6e2d48d20fc6bee7f6f2a99f3ae7ba8f0d /branch.c | |
| parent | 65f9b75dfe34a67cf4c6a8507f999c5710d36ba9 (diff) | |
| download | git-41af65651d4333cd19ab4af3509fa2d08f3816ed.tar.gz | |
worktrees: add find_shared_symref
Add a new function, find_shared_symref, which contains the heart of
die_if_checked_out, but works for any symref, not just HEAD.  Refactor
die_if_checked_out to use the same infrastructure as
find_shared_symref.
Soon, we will use find_shared_symref to protect notes merges in
worktrees.
Signed-off-by: David Turner <dturner@twopensource.com>
Reviewed-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'branch.c')
| -rw-r--r-- | branch.c | 46 | 
1 files changed, 34 insertions, 12 deletions
| @@ -310,21 +310,23 @@ void remove_branch_state(void)  	unlink(git_path("SQUASH_MSG"));  } -static void check_linked_checkout(const char *branch, const char *id) +static char *find_linked_symref(const char *symref, const char *branch, +				const char *id)  {  	struct strbuf sb = STRBUF_INIT;  	struct strbuf path = STRBUF_INIT;  	struct strbuf gitdir = STRBUF_INIT; +	char *existing = NULL;  	/* -	 * $GIT_COMMON_DIR/HEAD is practically outside -	 * $GIT_DIR so resolve_ref_unsafe() won't work (it -	 * uses git_path). Parse the ref ourselves. +	 * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside +	 * $GIT_DIR so resolve_ref_unsafe() won't work (it uses +	 * git_path). Parse the ref ourselves.  	 */  	if (id) -		strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); +		strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref);  	else -		strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); +		strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref);  	if (!strbuf_readlink(&sb, path.buf, 0)) {  		if (!starts_with(sb.buf, "refs/") || @@ -346,33 +348,53 @@ static void check_linked_checkout(const char *branch, const char *id)  		strbuf_rtrim(&gitdir);  	} else  		strbuf_addstr(&gitdir, get_git_common_dir()); -	skip_prefix(branch, "refs/heads/", &branch);  	strbuf_strip_suffix(&gitdir, ".git"); -	die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf); + +	existing = strbuf_detach(&gitdir, NULL);  done:  	strbuf_release(&path);  	strbuf_release(&sb);  	strbuf_release(&gitdir); + +	return existing;  } -void die_if_checked_out(const char *branch) +char *find_shared_symref(const char *symref, const char *target)  {  	struct strbuf path = STRBUF_INIT;  	DIR *dir;  	struct dirent *d; +	char *existing; -	check_linked_checkout(branch, NULL); +	if ((existing = find_linked_symref(symref, target, NULL))) +		return existing;  	strbuf_addf(&path, "%s/worktrees", get_git_common_dir());  	dir = opendir(path.buf);  	strbuf_release(&path);  	if (!dir) -		return; +		return NULL;  	while ((d = readdir(dir)) != NULL) {  		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))  			continue; -		check_linked_checkout(branch, d->d_name); +		existing = find_linked_symref(symref, target, d->d_name); +		if (existing) +			goto done;  	} +done:  	closedir(dir); + +	return existing; +} + +void die_if_checked_out(const char *branch) +{ +	char *existing; + +	existing = find_shared_symref("HEAD", branch); +	if (existing) { +		skip_prefix(branch, "refs/heads/", &branch); +		die(_("'%s' is already checked out at '%s'"), branch, existing); +	}  } | 
