Commits

Shawn O. Pearce  committed 7eff28a

Disallow working directory commands in a bare repository.

If the user tries to run a porcelainish command which requires
a working directory in a bare repository they may get unexpected
results which are difficult to predict and may differ from command
to command.

Instead we should detect that the current repository is a bare
repository and refuse to run the command there, as there is no
working directory associated with it.

[jc: updated Shawn's original somewhat -- bugs are mine.]

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>

  • Participants
  • Parent commits 4b441f4

Comments (0)

Files changed (11)

   or, when resuming [--skip | --resolved]'
 . git-sh-setup
 set_reflog_action am
+require_work_tree
 
 git var GIT_COMMITTER_IDENT >/dev/null || exit
 

File git-checkout.sh

 USAGE='[-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]'
 SUBDIRECTORY_OK=Sometimes
 . git-sh-setup
+require_work_tree
 
 old_name=HEAD
 old=$(git-rev-parse --verify $old_name 2>/dev/null)

File git-clean.sh

 affected are further limited to those that match them.'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
+require_work_tree
 
 ignored=
 ignoredonly=

File git-commit.sh

 USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [[-i | -o] <path>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
+require_work_tree
 
 git-rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
 

File git-merge.sh

 
 . git-sh-setup
 set_reflog_action "merge $*"
+require_work_tree
 
 test -z "$(git ls-files -u)" ||
 	die "You are in a middle of conflicted merge."
 LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
 . git-sh-setup
 set_reflog_action "pull $*"
+require_work_tree
 
 test -z "$(git ls-files -u)" ||
 	die "You are in a middle of conflicted merge."

File git-rebase.sh

 '
 . git-sh-setup
 set_reflog_action rebase
+require_work_tree
 
 RESOLVEMSG="
 When you have resolved this problem run \"git rebase --continue\".

File git-reset.sh

 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 set_reflog_action "reset $*"
+require_work_tree
 
 update= reset_type=--mixed
 unset rev

File git-revert.sh

 	die "What are you talking about?" ;;
 esac
 . git-sh-setup
+require_work_tree
 
 no_commit=
 while case "$#" in 0) break ;; esac

File git-sh-setup.sh

 	esac
 }
 
+require_work_tree () {
+	test $(is_bare_repository) = false ||
+	die "fatal: $0 cannot be used without a working tree."
+}
+
 if [ -z "$LONG_USAGE" ]
 then
 	LONG_USAGE="Usage: $0 $USAGE"
 
 #define RUN_SETUP	(1<<0)
 #define USE_PAGER	(1<<1)
+/*
+ * require working tree to be present -- anything uses this needs
+ * RUN_SETUP for reading from the configuration file.
+ */
+#define NOT_BARE 	(1<<2)
 
 static void handle_internal_command(int argc, const char **argv, char **envp)
 {
 		int (*fn)(int, const char **, const char *);
 		int option;
 	} commands[] = {
-		{ "add", cmd_add, RUN_SETUP },
+		{ "add", cmd_add, RUN_SETUP | NOT_BARE },
 		{ "annotate", cmd_annotate, },
 		{ "apply", cmd_apply },
 		{ "archive", cmd_archive },
 		{ "mailinfo", cmd_mailinfo },
 		{ "mailsplit", cmd_mailsplit },
 		{ "merge-file", cmd_merge_file },
-		{ "mv", cmd_mv, RUN_SETUP },
+		{ "mv", cmd_mv, RUN_SETUP | NOT_BARE },
 		{ "name-rev", cmd_name_rev, RUN_SETUP },
 		{ "pack-objects", cmd_pack_objects, RUN_SETUP },
 		{ "pickaxe", cmd_blame, RUN_SETUP | USE_PAGER },
 		{ "rerere", cmd_rerere, RUN_SETUP },
 		{ "rev-list", cmd_rev_list, RUN_SETUP },
 		{ "rev-parse", cmd_rev_parse, RUN_SETUP },
-		{ "rm", cmd_rm, RUN_SETUP },
-		{ "runstatus", cmd_runstatus, RUN_SETUP },
+		{ "rm", cmd_rm, RUN_SETUP | NOT_BARE },
+		{ "runstatus", cmd_runstatus, RUN_SETUP | NOT_BARE },
 		{ "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
 		{ "show-branch", cmd_show_branch, RUN_SETUP },
 		{ "show", cmd_show, RUN_SETUP | USE_PAGER },
 			prefix = setup_git_directory();
 		if (p->option & USE_PAGER)
 			setup_pager();
+		if ((p->option & NOT_BARE) && is_bare_repository())
+			die("%s cannot be used in a bare git directory", cmd);
 		trace_argv_printf(argv, argc, "trace: built-in: git");
 
 		exit(p->fn(argc, argv, prefix));