Merge branch 'jc/bare'
authorJunio C Hamano <junkio@cox.net>
Fri, 12 Jan 2007 00:50:36 +0000 (16:50 -0800)
committerJunio C Hamano <junkio@cox.net>
Fri, 12 Jan 2007 00:50:36 +0000 (16:50 -0800)
* jc/bare:
  Disallow working directory commands in a bare repository.
  git-fetch: allow updating the current branch in a bare repository.
  Introduce is_bare_repository() and core.bare configuration variable
  Move initialization of log_all_ref_updates

17 files changed:
builtin-init-db.c
cache.h
config.c
environment.c
git-am.sh
git-checkout.sh
git-clean.sh
git-commit.sh
git-fetch.sh
git-merge.sh
git-pull.sh
git-rebase.sh
git-reset.sh
git-revert.sh
git-sh-setup.sh
git.c
refs.c

index bbef820..22729f0 100644 (file)
@@ -252,9 +252,13 @@ static int create_default_files(const char *git_dir, const char *template_path)
        }
        git_config_set("core.filemode", filemode ? "true" : "false");
 
-       /* Enable logAllRefUpdates if a working tree is attached */
-       if (!is_bare_git_dir(git_dir))
+       if (is_bare_repository()) {
+               git_config_set("core.bare", "true");
+       }
+       else {
+               git_config_set("core.bare", "false");
                git_config_set("core.logallrefupdates", "true");
+       }
        return reinit;
 }
 
diff --git a/cache.h b/cache.h
index cbe398d..c482c32 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -127,7 +127,8 @@ extern int cache_errno;
 #define CONFIG_LOCAL_ENVIRONMENT "GIT_CONFIG_LOCAL"
 #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
 
-extern int is_bare_git_dir(const char *dir);
+extern int is_bare_repository_cfg;
+extern int is_bare_repository(void);
 extern const char *get_git_dir(void);
 extern char *get_object_directory(void);
 extern char *get_refs_directory(void);
index 733fb1a..b6082f5 100644 (file)
--- a/config.c
+++ b/config.c
@@ -269,6 +269,11 @@ int git_default_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.bare")) {
+               is_bare_repository_cfg = git_config_bool(var, value);
+               return 0;
+       }
+
        if (!strcmp(var, "core.ignorestat")) {
                assume_unchanged = git_config_bool(var, value);
                return 0;
index 09976c7..54c22f8 100644 (file)
@@ -15,7 +15,8 @@ int use_legacy_headers = 1;
 int trust_executable_bit = 1;
 int assume_unchanged;
 int prefer_symlink_refs;
-int log_all_ref_updates;
+int is_bare_repository_cfg = -1; /* unspecified */
+int log_all_ref_updates = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
 int repository_format_version;
 char *git_commit_encoding;
@@ -51,12 +52,15 @@ static void setup_git_env(void)
        git_graft_file = getenv(GRAFT_ENVIRONMENT);
        if (!git_graft_file)
                git_graft_file = xstrdup(git_path("info/grafts"));
-       log_all_ref_updates = !is_bare_git_dir(git_dir);
 }
 
-int is_bare_git_dir (const char *dir)
+int is_bare_repository(void)
 {
-       const char *s;
+       const char *dir, *s;
+       if (0 <= is_bare_repository_cfg)
+               return is_bare_repository_cfg;
+
+       dir = get_git_dir();
        if (!strcmp(dir, DEFAULT_GIT_DIR_ENVIRONMENT))
                return 0;
        s = strrchr(dir, '/');
index 59d663b..1252f26 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -7,6 +7,7 @@ USAGE='[--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
   or, when resuming [--skip | --resolved]'
 . git-sh-setup
 set_reflog_action am
+require_work_tree
 
 git var GIT_COMMITTER_IDENT >/dev/null || exit
 
index 8f4356d..a2b8e4f 100755 (executable)
@@ -3,6 +3,7 @@
 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)
index 071b974..db177a7 100755 (executable)
@@ -14,6 +14,7 @@ When optional <paths>... arguments are given, the paths
 affected are further limited to those that match them.'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
+require_work_tree
 
 ignored=
 ignoredonly=
index c2beb76..eddd863 100755 (executable)
@@ -6,6 +6,7 @@
 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
 
index 466fe59..c58704d 100755 (executable)
@@ -231,11 +231,12 @@ update_local_ref () {
     esac
 }
 
-case "$update_head_ok" in
-'')
+# updating the current HEAD with git-fetch in a bare
+# repository is always fine.
+if test -z "$update_head_ok" && test $(is_bare_repository) = false
+then
        orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
-       ;;
-esac
+fi
 
 # If --tags (and later --heads or --all) is specified, then we are
 # not talking about defaults stored in Pull: line of remotes or
index 4770029..3eef048 100755 (executable)
@@ -7,6 +7,7 @@ USAGE='[-n] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commi
 
 . 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."
index c184fb8..e9826fc 100755 (executable)
@@ -8,6 +8,7 @@ USAGE='[-n | --no-summary] [--no-commit] [-s strategy]... [<fetch-options>] <rep
 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."
index 828c59c..98f9558 100755 (executable)
@@ -29,6 +29,7 @@ Example:       git-rebase master~1 topic
 '
 . git-sh-setup
 set_reflog_action rebase
+require_work_tree
 
 RESOLVEMSG="
 When you have resolved this problem run \"git rebase --continue\".
index 76c8a81..b9045bc 100755 (executable)
@@ -6,6 +6,7 @@ USAGE='[--mixed | --soft | --hard]  [<commit-ish>] [ [--] <paths>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 set_reflog_action "reset $*"
+require_work_tree
 
 update= reset_type=--mixed
 unset rev
index 50cc47b..f9843c7 100755 (executable)
@@ -19,6 +19,7 @@ case "$0" in
        die "What are you talking about?" ;;
 esac
 . git-sh-setup
+require_work_tree
 
 no_commit=
 while case "$#" in 0) break ;; esac
index 87b939c..4a02b38 100755 (executable)
@@ -28,6 +28,19 @@ set_reflog_action() {
        fi
 }
 
+is_bare_repository () {
+       git-repo-config --bool --get core.bare ||
+       case "$GIT_DIR" in
+       .git | */.git) echo false ;;
+       *) echo true ;;
+       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"
diff --git a/git.c b/git.c
index 9ce545d..72a1486 100644 (file)
--- a/git.c
+++ b/git.c
@@ -199,6 +199,11 @@ const char git_version_string[] = GIT_VERSION;
 
 #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)
 {
@@ -208,7 +213,7 @@ 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 },
@@ -240,7 +245,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "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 },
@@ -253,8 +258,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "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 },
@@ -291,6 +296,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                        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));
diff --git a/refs.c b/refs.c
index d189d8a..689ac50 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -923,6 +923,9 @@ static int log_ref_write(struct ref_lock *lock,
        char *logrec;
        const char *committer;
 
+       if (log_all_ref_updates < 0)
+               log_all_ref_updates = !is_bare_repository();
+
        if (log_all_ref_updates &&
            (!strncmp(lock->ref_name, "refs/heads/", 11) ||
             !strncmp(lock->ref_name, "refs/remotes/", 13))) {