Merge branch 'jn/paginate-fix'
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Aug 2010 23:23:31 +0000 (16:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Aug 2010 23:23:31 +0000 (16:23 -0700)
* jn/paginate-fix:
t7006 (pager): add missing TTY prerequisites
merge-file: run setup_git_directory_gently() sooner
var: run setup_git_directory_gently() sooner
ls-remote: run setup_git_directory_gently() sooner
index-pack: run setup_git_directory_gently() sooner
config: run setup_git_directory_gently() sooner
bundle: run setup_git_directory_gently() sooner
apply: run setup_git_directory_gently() sooner
grep: run setup_git_directory_gently() sooner
shortlog: run setup_git_directory_gently() sooner
git wrapper: allow setup_git_directory_gently() be called earlier
setup: remember whether repository was found
git wrapper: introduce startup_info struct

Conflicts:
builtin/index-pack.c

1  2 
builtin/apply.c
builtin/config.c
builtin/grep.c
builtin/index-pack.c
cache.h
git.c
setup.c
diff --combined builtin/apply.c
index f38c1f7b88fafa18550762685e3bb5b15bfa701f,f005ba1e8934d4383f6181737a53a388d8b03a61..470520bde7ceec8d01f401e7421927bd48fd69ee
@@@ -2979,7 -2979,8 +2979,7 @@@ static void build_fake_ancestor(struct 
                else if (get_sha1(patch->old_sha1_prefix, sha1))
                        /* git diff has no index line for mode/type changes */
                        if (!patch->lines_added && !patch->lines_deleted) {
 -                              if (get_current_sha1(patch->new_name, sha1) ||
 -                                  get_current_sha1(patch->old_name, sha1))
 +                              if (get_current_sha1(patch->old_name, sha1))
                                        die("mode change for %s, which is not "
                                                "in current HEAD", name);
                                sha1_ptr = sha1;
@@@ -3606,11 -3607,11 +3606,11 @@@ static int option_parse_directory(cons
        return 0;
  }
  
- int cmd_apply(int argc, const char **argv, const char *unused_prefix)
+ int cmd_apply(int argc, const char **argv, const char *prefix_)
  {
        int i;
        int errs = 0;
-       int is_not_gitdir;
+       int is_not_gitdir = !startup_info->have_repository;
        int binary;
        int force_apply = 0;
  
                OPT_END()
        };
  
-       prefix = setup_git_directory_gently(&is_not_gitdir);
+       prefix = prefix_;
        prefix_length = prefix ? strlen(prefix) : 0;
        git_config(git_apply_config, NULL);
        if (apply_default_whitespace)
diff --combined builtin/config.c
index 79fee767b88a2d826311afb7a3299d67dedd3b94,3f8ef91dfca3201a0f66fbc69bdcc4d39f9d1339..ca4a0db4a79241d7ded005483b4693967eea636f
@@@ -20,7 -20,7 +20,7 @@@ static char delim = '='
  static char key_delim = ' ';
  static char term = '\n';
  
 -static int use_global_config, use_system_config;
 +static int use_global_config, use_system_config, use_local_config;
  static const char *given_config_file;
  static int actions, types;
  static const char *get_color_slot, *get_colorbool_slot;
@@@ -51,7 -51,6 +51,7 @@@ static struct option builtin_config_opt
        OPT_GROUP("Config file location"),
        OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
        OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
 +      OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"),
        OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
        OPT_GROUP("Action"),
        OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
@@@ -331,11 -330,10 +331,10 @@@ static int get_colorbool(int print
                return get_colorbool_found ? 0 : 1;
  }
  
- int cmd_config(int argc, const char **argv, const char *unused_prefix)
+ int cmd_config(int argc, const char **argv, const char *prefix)
  {
-       int nongit;
+       int nongit = !startup_info->have_repository;
        char *value;
-       const char *prefix = setup_git_directory_gently(&nongit);
  
        config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
  
                             builtin_config_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
  
 -      if (use_global_config + use_system_config + !!given_config_file > 1) {
 +      if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) {
                error("only one config file at a time.");
                usage_with_options(builtin_config_usage, builtin_config_options);
        }
        }
        else if (use_system_config)
                config_exclusive_filename = git_etc_gitconfig();
 +      else if (use_local_config)
 +              config_exclusive_filename = git_pathdup("config");
        else if (given_config_file) {
                if (!is_absolute_path(given_config_file) && prefix)
                        config_exclusive_filename = prefix_filename(prefix,
diff --combined builtin/grep.c
index b725ede0f7270637759b9fef52ab5450fc1712e2,ca56c5b0099e19059b51440880d032c5e1d27f5e..da32f3df34da7af3cdcb0a9dd6aa66061bdfe927
@@@ -834,12 -834,12 +834,12 @@@ int cmd_grep(int argc, const char **arg
        int external_grep_allowed__ignored;
        const char *show_in_pager = NULL, *default_pager = "dummy";
        struct grep_opt opt;
 -      struct object_array list = { 0, 0, NULL };
 +      struct object_array list = OBJECT_ARRAY_INIT;
        const char **paths = NULL;
 -      struct string_list path_list = { NULL, 0, 0, 0 };
 +      struct string_list path_list = STRING_LIST_INIT_NODUP;
        int i;
        int dummy;
-       int nongit = 0, use_index = 1;
+       int use_index = 1;
        struct option options[] = {
                OPT_BOOLEAN(0, "cached", &cached,
                        "search in index instead of in the work tree"),
                OPT_END()
        };
  
-       prefix = setup_git_directory_gently(&nongit);
        /*
         * 'git grep -h', unlike 'git grep -h <pattern>', is a request
         * to show usage information and exit.
                             PARSE_OPT_STOP_AT_NON_OPTION |
                             PARSE_OPT_NO_INTERNAL_HELP);
  
-       if (use_index && nongit)
+       if (use_index && !startup_info->have_repository)
                /* die the same way as if we did it at the beginning */
                setup_git_directory();
  
diff --combined builtin/index-pack.c
index 96333d48cd49fcfba5707530440f6f6848a2acf5,e852890862e12c9ebeec087e6ada6fde59a75efc..2e680d7a7ac3495c9d6bd10e0fa6a6ae28bb8670
@@@ -880,14 -880,10 +880,12 @@@ int cmd_index_pack(int argc, const cha
        char *index_name_buf = NULL, *keep_name_buf = NULL;
        struct pack_idx_entry **idx_objects;
        unsigned char pack_sha1[20];
-       int nongit;
  
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage(index_pack_usage);
  
-       prefix = setup_git_directory_gently(&nongit);
 +      read_replace_refs = 0;
 +
        git_config(git_index_pack_config, NULL);
        if (prefix && chdir(prefix))
                die("Cannot come back to cwd");
diff --combined cache.h
index eb77e1df48814b92e76436ca3184319147192f7d,f9e82a8acea5a607e3c65e9d702de9117b42b520..733d4d1c81fe47bb2fa68aa3a76bade464de3051
+++ b/cache.h
@@@ -179,7 -179,8 +179,7 @@@ struct cache_entry 
  #define CE_UNHASHED  (0x200000)
  #define CE_CONFLICTED (0x800000)
  
 -/* Only remove in work directory, not index */
 -#define CE_WT_REMOVE (0x400000)
 +#define CE_WT_REMOVE (0x400000) /* remove in work directory */
  
  #define CE_UNPACKED  (0x1000000)
  
@@@ -448,7 -449,7 +448,7 @@@ extern int init_db(const char *template
                                alloc = alloc_nr(alloc); \
                        x = xrealloc((x), alloc * sizeof(*(x))); \
                } \
 -      } while(0)
 +      } while (0)
  
  /* Initialize and use the cache information */
  extern int read_index(struct index_state *);
@@@ -640,9 -641,6 +640,9 @@@ extern char *git_pathdup(const char *fm
  /* Return a statically allocated filename matching the sha1 signature */
  extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
  extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
 +extern char *git_path_submodule(const char *path, const char *fmt, ...)
 +      __attribute__((format (printf, 2, 3)));
 +
  extern char *sha1_file_name(const unsigned char *sha1);
  extern char *sha1_pack_name(const unsigned char *sha1);
  extern char *sha1_pack_index_name(const unsigned char *sha1);
@@@ -813,7 -811,6 +813,7 @@@ const char *show_date_relative(unsigne
                               char *timebuf,
                               size_t timebuf_size);
  int parse_date(const char *date, char *buf, int bufsize);
 +int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
  void datestamp(char *buf, int bufsize);
  #define approxidate(s) approxidate_careful((s), NULL)
  unsigned long approxidate_careful(const char *, int *);
@@@ -1099,9 -1096,13 +1099,15 @@@ void overlay_tree_on_cache(const char *
  
  char *alias_lookup(const char *alias);
  int split_cmdline(char *cmdline, const char ***argv);
 +/* Takes a negative value returned by split_cmdline */
 +const char *split_cmdline_strerror(int cmdline_errno);
  
+ /* git.c */
+ struct startup_info {
+       int have_repository;
+ };
+ extern struct startup_info *startup_info;
  /* builtin/merge.c */
  int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
  
diff --combined git.c
index 12d2952e079103c87b1f176f6928de4f342de9b5,286a3595a82d33b5c3d754cf422015c867617b63..8de48107e0dced316704c1ad78569ccb9eeebb08
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -14,6 -14,7 +14,7 @@@ const char git_usage_string[] 
  const char git_more_info_string[] =
        "See 'git help COMMAND' for more information on a specific command.";
  
+ static struct startup_info git_startup_info;
  static int use_pager = -1;
  struct pager_config {
        const char *cmd;
@@@ -188,8 -189,7 +189,8 @@@ static int handle_alias(int *argcp, con
                }
                count = split_cmdline(alias_string, &new_argv);
                if (count < 0)
 -                      die("Bad alias.%s string", alias_command);
 +                      die("Bad alias.%s string: %s", alias_command,
 +                          split_cmdline_strerror(count));
                option_count = handle_options(&new_argv, &count, &envchanged);
                if (envchanged)
                        die("alias '%s' changes environment variables\n"
  
  const char git_version_string[] = GIT_VERSION;
  
- #define RUN_SETUP     (1<<0)
- #define USE_PAGER     (1<<1)
+ #define RUN_SETUP             (1<<0)
+ #define RUN_SETUP_GENTLY      (1<<1)
+ #define USE_PAGER             (1<<2)
  /*
   * require working tree to be present -- anything uses this needs
   * RUN_SETUP for reading from the configuration file.
   */
- #define NEED_WORK_TREE        (1<<2)
+ #define NEED_WORK_TREE                (1<<3)
  
  struct cmd_struct {
        const char *cmd;
@@@ -255,8 -256,12 +257,12 @@@ static int run_builtin(struct cmd_struc
        if (!help) {
                if (p->option & RUN_SETUP)
                        prefix = setup_git_directory();
+               if (p->option & RUN_SETUP_GENTLY) {
+                       int nongit_ok;
+                       prefix = setup_git_directory_gently(&nongit_ok);
+               }
  
-               if (use_pager == -1 && p->option & RUN_SETUP)
+               if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))
                        use_pager = check_pager_config(p->cmd);
                if (use_pager == -1 && p->option & USE_PAGER)
                        use_pager = 1;
@@@ -296,12 -301,12 +302,12 @@@ static void handle_internal_command(in
                { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
                { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
                { "annotate", cmd_annotate, RUN_SETUP },
-               { "apply", cmd_apply },
+               { "apply", cmd_apply, RUN_SETUP_GENTLY },
                { "archive", cmd_archive },
                { "bisect--helper", cmd_bisect__helper, RUN_SETUP | NEED_WORK_TREE },
                { "blame", cmd_blame, RUN_SETUP },
                { "branch", cmd_branch, RUN_SETUP },
-               { "bundle", cmd_bundle },
+               { "bundle", cmd_bundle, RUN_SETUP_GENTLY },
                { "cat-file", cmd_cat_file, RUN_SETUP },
                { "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
                { "checkout-index", cmd_checkout_index,
                { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
                { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
                { "commit-tree", cmd_commit_tree, RUN_SETUP },
-               { "config", cmd_config },
+               { "config", cmd_config, RUN_SETUP_GENTLY },
                { "count-objects", cmd_count_objects, RUN_SETUP },
                { "describe", cmd_describe, RUN_SETUP },
                { "diff", cmd_diff },
                { "fsck-objects", cmd_fsck, RUN_SETUP },
                { "gc", cmd_gc, RUN_SETUP },
                { "get-tar-commit-id", cmd_get_tar_commit_id },
-               { "grep", cmd_grep },
+               { "grep", cmd_grep, RUN_SETUP_GENTLY },
                { "hash-object", cmd_hash_object },
                { "help", cmd_help },
-               { "index-pack", cmd_index_pack },
+               { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
                { "init", cmd_init_db },
                { "init-db", cmd_init_db },
 -              { "log", cmd_log, RUN_SETUP | USE_PAGER },
 +              { "log", cmd_log, RUN_SETUP },
                { "ls-files", cmd_ls_files, RUN_SETUP },
                { "ls-tree", cmd_ls_tree, RUN_SETUP },
-               { "ls-remote", cmd_ls_remote },
+               { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
                { "mailinfo", cmd_mailinfo },
                { "mailsplit", cmd_mailsplit },
                { "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
                { "merge-base", cmd_merge_base, RUN_SETUP },
-               { "merge-file", cmd_merge_file },
+               { "merge-file", cmd_merge_file, RUN_SETUP_GENTLY },
                { "merge-index", cmd_merge_index, RUN_SETUP },
                { "merge-ours", cmd_merge_ours, RUN_SETUP },
                { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
                { "pack-objects", cmd_pack_objects, RUN_SETUP },
                { "pack-redundant", cmd_pack_redundant, RUN_SETUP },
                { "patch-id", cmd_patch_id },
-               { "peek-remote", cmd_ls_remote },
+               { "peek-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
                { "pickaxe", cmd_blame, RUN_SETUP },
                { "prune", cmd_prune, RUN_SETUP },
                { "prune-packed", cmd_prune_packed, RUN_SETUP },
                { "reflog", cmd_reflog, RUN_SETUP },
                { "remote", cmd_remote, RUN_SETUP },
                { "replace", cmd_replace, RUN_SETUP },
-               { "repo-config", cmd_config },
+               { "repo-config", cmd_config, RUN_SETUP_GENTLY },
                { "rerere", cmd_rerere, RUN_SETUP },
                { "reset", cmd_reset, RUN_SETUP },
                { "rev-list", cmd_rev_list, RUN_SETUP },
                { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
                { "rm", cmd_rm, RUN_SETUP },
                { "send-pack", cmd_send_pack, RUN_SETUP },
-               { "shortlog", cmd_shortlog, USE_PAGER },
+               { "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
                { "show-branch", cmd_show_branch, RUN_SETUP },
 -              { "show", cmd_show, RUN_SETUP | USE_PAGER },
 +              { "show", cmd_show, RUN_SETUP },
                { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
                { "stripspace", cmd_stripspace },
                { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
                { "update-ref", cmd_update_ref, RUN_SETUP },
                { "update-server-info", cmd_update_server_info, RUN_SETUP },
                { "upload-archive", cmd_upload_archive },
-               { "var", cmd_var },
+               { "var", cmd_var, RUN_SETUP_GENTLY },
                { "verify-tag", cmd_verify_tag, RUN_SETUP },
                { "version", cmd_version },
 -              { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
 +              { "whatchanged", cmd_whatchanged, RUN_SETUP },
                { "write-tree", cmd_write_tree, RUN_SETUP },
                { "verify-pack", cmd_verify_pack },
                { "show-ref", cmd_show_ref, RUN_SETUP },
@@@ -490,6 -495,8 +496,8 @@@ int main(int argc, const char **argv
  {
        const char *cmd;
  
+       startup_info = &git_startup_info;
        cmd = git_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "git-help";
diff --combined setup.c
index d19aa7d7a9633eaf8bb7d65d31bad6b67bf85ead,6ee1e28bd8650332aade03b78a2660abbde5478a..a3b76de2bb1c18e2f3b8cdf5799c3c650b16d027
+++ b/setup.c
@@@ -360,28 -360,6 +360,28 @@@ static int cwd_contains_git_dir(const c
        return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);
  }
  
 +static const char *setup_discovered_git_dir(const char *work_tree_env,
 +              int offset, int len, char *cwd, int *nongit_ok)
 +{
 +      int root_len;
 +
 +      inside_git_dir = 0;
 +      if (!work_tree_env)
 +              inside_work_tree = 1;
 +      root_len = offset_1st_component(cwd);
 +      git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);
 +      if (check_repository_format_gently(nongit_ok))
 +              return NULL;
 +      if (offset == len)
 +              return NULL;
 +
 +      /* Make "offset" point to past the '/', and add a '/' at the end */
 +      offset++;
 +      cwd[len++] = '/';
 +      cwd[len] = 0;
 +      return cwd + offset;
 +}
 +
  static const char *setup_bare_git_dir(const char *work_tree_env,
                int offset, int len, char *cwd, int *nongit_ok)
  {
@@@ -426,14 -404,14 +426,14 @@@ static dev_t get_device_or_die(const ch
   * We cannot decide in this function whether we are in the work tree or
   * not, since the config can only be read _after_ this function was called.
   */
const char *setup_git_directory_gently(int *nongit_ok)
static const char *setup_git_directory_gently_1(int *nongit_ok)
  {
        const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
        const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
        static char cwd[PATH_MAX+1];
        const char *gitdirenv;
        const char *gitfile_dir;
 -      int len, offset, ceil_offset, root_len;
 +      int len, offset, ceil_offset;
        dev_t current_device = 0;
        int one_filesystem = 1;
  
                current_device = get_device_or_die(".", NULL);
        for (;;) {
                if (cwd_contains_git_dir(&gitfile_dir))
 -                      break;
 +                      return setup_discovered_git_dir(work_tree_env, offset,
 +                                                      len, cwd, nongit_ok);
                if (is_git_directory("."))
                        return setup_bare_git_dir(work_tree_env, offset,
                                                        len, cwd, nongit_ok);
                        die_errno("Cannot change to '%s/..'", cwd);
                }
        }
 -
 -      inside_git_dir = 0;
 -      if (!work_tree_env)
 -              inside_work_tree = 1;
 -      root_len = offset_1st_component(cwd);
 -      git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);
 -      if (check_repository_format_gently(nongit_ok))
 -              return NULL;
 -      if (offset == len)
 -              return NULL;
 -
 -      /* Make "offset" point to past the '/', and add a '/' at the end */
 -      offset++;
 -      cwd[len++] = '/';
 -      cwd[len] = 0;
 -      return cwd + offset;
  }
  
+ const char *setup_git_directory_gently(int *nongit_ok)
+ {
+       const char *prefix;
+       prefix = setup_git_directory_gently_1(nongit_ok);
+       if (startup_info)
+               startup_info->have_repository = !nongit_ok || !*nongit_ok;
+       return prefix;
+ }
  int git_config_perm(const char *var, const char *value)
  {
        int i;