git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 21/25] worktree: add "lock" command

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Apr 13, 2016, 13:15 UTC
Message-ID
<1460553346-12985-22-git-send-email-pclouds@gmail.com>
In-Reply-To
<1460553346-12985-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-worktree.txt         | 12 ++++++++--
 builtin/worktree.c                     | 41 ++++++++++++++++++++++++++++++++++
 contrib/completion/git-completion.bash |  5 ++++-
 t/t2028-worktree-move.sh (new +x)      | 34 ++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 3 deletions(-)
 create mode 100755 t/t2028-worktree-move.sh
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 1c9d7c1..9f0c9f0 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]
 'git worktree list' [--porcelain]
+'git worktree lock' [--reason <string>] <path>
 'git worktree prune' [-n] [-v] [--expire <expire>]
 
 DESCRIPTION
@@ -61,6 +62,12 @@ each of the linked worktrees.  The output details include if the worktree is
 bare, the revision currently checked out, and the branch currently checked out
 (or 'detached HEAD' if none).
 
+lock::
+
+When a worktree is locked, it cannot be pruned, moved or deleted. For
+example, if the worktree is on portable device that is not available
+when "git worktree <command>" is executed.
+
 prune::
 
 Prune working tree information in $GIT_DIR/worktrees.
@@ -104,6 +111,9 @@ OPTIONS
 --expire <time>::
 	With `prune`, only expire unused working trees older than <time>.
 
+--reason <string>:
+	An explanation why the worktree is locked.
+
 DETAILS
 -------
 Each linked working tree has a private sub-directory in the repository's
@@ -220,8 +230,6 @@ performed manually, such as:
 - `remove` to remove a linked working tree and its administrative files (and
   warn if the working tree is dirty)
 - `mv` to move or rename a working tree and update its administrative files
-- `lock` to prevent automatic pruning of administrative files (for instance,
-  for a working tree on a portable device)
 
 GIT
 ---
diff --git a/builtin/worktree.c b/builtin/worktree.c
index a9e91ab..736caff 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -14,6 +14,7 @@
 static const char * const worktree_usage[] = {
 	N_("git worktree add [<options>] <path> [<branch>]"),
 	N_("git worktree list [<options>]"),
+	N_("git worktree lock [<options>] <path>"),
 	N_("git worktree prune [<options>]"),
 	NULL
 };
@@ -452,6 +453,44 @@ static int list(int ac, const char **av, const char *prefix)
 	return 0;
 }
 
+static int lock_worktree(int ac, const char **av, const char *prefix)
+{
+	const char *reason = "", *old_reason;
+	struct option options[] = {
+		OPT_STRING(0, "reason", &reason, N_("string"),
+			   N_("reason for locking")),
+		OPT_END()
+	};
+	struct worktree **worktrees, *wt;
+	struct strbuf dst = STRBUF_INIT;
+
+	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
+	if (ac != 1)
+		usage_with_options(worktree_usage, options);
+
+	strbuf_addstr(&dst, prefix_filename(prefix,
+					    strlen(prefix),
+					    av[0]));
+
+	worktrees = get_worktrees();
+	wt = find_worktree_by_path(worktrees, dst.buf);
+	if (!wt)
+		die(_("'%s' is not a working directory"), av[0]);
+	if (is_main_worktree(wt))
+		die(_("'%s' is a main working directory"), av[0]);
+
+	old_reason = is_worktree_locked(wt);
+	if (old_reason) {
+		if (*old_reason)
+			die(_("already locked, reason: %s"), old_reason);
+		die(_("already locked, no reason"));
+	}
+
+	write_file(git_common_path("worktrees/%s/locked", wt->id),
+		   "%s", reason);
+	return 0;
+}
+
 int cmd_worktree(int ac, const char **av, const char *prefix)
 {
 	struct option options[] = {
@@ -468,5 +507,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
 		return prune(ac - 1, av + 1, prefix);
 	if (!strcmp(av[1], "list"))
 		return list(ac - 1, av + 1, prefix);
+	if (!strcmp(av[1], "lock"))
+		return lock_worktree(ac - 1, av + 1, prefix);
 	usage_with_options(worktree_usage, options);
 }
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index f66db2d..cdae408 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2596,7 +2596,7 @@ _git_whatchanged ()
 
 _git_worktree ()
 {
-	local subcommands="add list prune"
+	local subcommands="add list lock prune"
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
@@ -2608,6 +2608,9 @@ _git_worktree ()
 		list,--*)
 			__gitcomp "--porcelain"
 			;;
+		lock,--*)
+			__gitcomp "--reason"
+			;;
 		prune,--*)
 			__gitcomp "--dry-run --expire --verbose"
 			;;
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
new file mode 100755
index 0000000..97434be
--- /dev/null
+++ b/t/t2028-worktree-move.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='test git worktree move, remove, lock and unlock'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit init &&
+	git worktree add source &&
+	git worktree list --porcelain | grep "^worktree" >actual &&
+	cat <<-EOF >expected &&
+	worktree $TRASH_DIRECTORY
+	worktree $TRASH_DIRECTORY/source
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'lock main worktree' '
+	test_must_fail git worktree lock .
+'
+
+test_expect_success 'lock linked worktree' '
+	git worktree lock --reason hahaha source &&
+	echo hahaha >expected &&
+	test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'lock worktree twice' '
+	test_must_fail git worktree lock source &&
+	echo hahaha >expected &&
+	test_cmp expected .git/worktrees/source/locked
+'
+
+test_done
-- 
2.8.0.rc0.210.gd302cd2
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 22 of 35 in “worktree lock, move, remove and unlock”
  1. 00/25 worktree lock, move, remove and unlockNguyễn Thái Ngọc Duy, Apr 13, 2016
  2. 01/25 usage.c: move format processing out of die_errno()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  3. 02/25 usage.c: add sys_error() that prints strerror() automaticallyNguyễn Thái Ngọc Duy, Apr 13, 2016
  4. 03/25 copy.c: import copy_file() from busyboxNguyễn Thái Ngọc Duy, Apr 13, 2016
  5. 04/25 copy.c: delete unused code in copy_file()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  6. 05/25 copy.c: convert bb_(p)error_msg to (sys_)errorNguyễn Thái Ngọc Duy, Apr 13, 2016
  7. 06/25 copy.c: style fixNguyễn Thái Ngọc Duy, Apr 13, 2016
  8. 07/25 copy.c: convert copy_file() to copy_dir_recursively()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  9. 08/25 completion: support git-worktreeNguyễn Thái Ngọc Duy, Apr 13, 2016
  10. 09/25 git-worktree.txt: keep subcommand listing in alphabetical orderNguyễn Thái Ngọc Duy, Apr 13, 2016
  11. 10/25 path.c: add git_common_path() and strbuf_git_common_path()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  12. 11/25 worktree.c: use is_dot_or_dotdot()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  13. 12/25 worktree.c: store "id" instead of "git_dir"Nguyễn Thái Ngọc Duy, Apr 13, 2016
  14. 13/25 worktree.c: add clear_worktree()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  15. 14/25 worktree.c: add find_worktree_by_path()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  16. 15/25 worktree.c: add is_main_worktree()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  17. 16/25 worktree.c: add validate_worktree()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  18. 17/25 worktree.c: add update_worktree_location()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  19. 18/25 worktree.c: add is_worktree_locked()Nguyễn Thái Ngọc Duy, Apr 13, 2016
  20. 19/25 worktree: avoid 0{40}, too many zeroes, hard to readNguyễn Thái Ngọc Duy, Apr 13, 2016
  21. 20/25 worktree: simplify prefixing pathsNguyễn Thái Ngọc Duy, Apr 13, 2016
  22. 21/25 worktree: add "lock" commandNguyễn Thái Ngọc Duy, Apr 13, 2016
  23. 22/25 worktree: add "unlock" commandNguyễn Thái Ngọc Duy, Apr 13, 2016
  24. 23/25 worktree: add "move" commmandNguyễn Thái Ngọc Duy, Apr 13, 2016
  25. 24/25 worktree move: accept destination as directoryNguyễn Thái Ngọc Duy, Apr 13, 2016
  26. Eric SunshineMay 11, 2016
  27. Duy NguyenMay 11, 2016
  28. Eric SunshineMay 11, 2016
  29. Johannes SixtMay 11, 2016
  30. Junio C HamanoMay 11, 2016
  31. Johannes SixtMay 12, 2016
  32. 25/25 worktree: add "remove" commandNguyễn Thái Ngọc Duy, Apr 13, 2016
  33. Junio C HamanoApr 14, 2016
  34. Duy NguyenApr 15, 2016
  35. Junio C HamanoApr 15, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.