Merge branch 'cb/common-prefix-unification'
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:17 +0000 (15:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:17 +0000 (15:56 -0700)
* cb/common-prefix-unification:
rename pathspec_prefix() to common_prefix() and move to dir.[ch]
consolidate pathspec_prefix and common_prefix
remove prefix argument from pathspec_prefix

1  2 
builtin/commit.c
builtin/ls-files.c
cache.h
setup.c
diff --combined builtin/commit.c
index cbc9613ec661bc2cef8274cd66efb06b9cab55b6,1e8e0acb534c142c0d91bd7f8560d2d5ddbfc3fa..b9ab5ef3146ff0536cb79dabf8c77605e4974c31
@@@ -62,6 -62,8 +62,6 @@@ N_("The previous cherry-pick is now emp
  "\n"
  "Otherwise, please use 'git reset'\n");
  
 -static unsigned char head_sha1[20];
 -
  static const char *use_message_buffer;
  static const char commit_editmsg[] = "COMMIT_EDITMSG";
  static struct lock_file index_lock; /* real index */
@@@ -100,7 -102,7 +100,7 @@@ static enum 
  static char *cleanup_arg;
  
  static enum commit_whence whence;
 -static int use_editor = 1, initial_commit, include_status = 1;
 +static int use_editor = 1, include_status = 1;
  static int show_ignored_in_status;
  static const char *only_include_assumed;
  static struct strbuf message;
@@@ -255,8 -257,9 +255,9 @@@ static int list_paths(struct string_lis
        m = xcalloc(1, i);
  
        if (with_tree) {
-               const char *max_prefix = pathspec_prefix(prefix, pattern);
-               overlay_tree_on_cache(with_tree, max_prefix);
+               char *max_prefix = common_prefix(pattern);
+               overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
+               free(max_prefix);
        }
  
        for (i = 0; i < active_nr; i++) {
                        item->util = item; /* better a valid pointer than a fake one */
        }
  
 -      return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
 +      return report_path_error(m, pattern, prefix);
  }
  
  static void add_remove_files(struct string_list *list)
        }
  }
  
 -static void create_base_index(void)
 +static void create_base_index(const struct commit *current_head)
  {
        struct tree *tree;
        struct unpack_trees_options opts;
        struct tree_desc t;
  
 -      if (initial_commit) {
 +      if (!current_head) {
                discard_cache();
                return;
        }
        opts.dst_index = &the_index;
  
        opts.fn = oneway_merge;
 -      tree = parse_tree_indirect(head_sha1);
 +      tree = parse_tree_indirect(current_head->object.sha1);
        if (!tree)
                die(_("failed to unpack HEAD tree object"));
        parse_tree(tree);
@@@ -332,8 -335,7 +333,8 @@@ static void refresh_cache_or_die(int re
                die_resolve_conflict("commit");
  }
  
 -static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
 +static char *prepare_index(int argc, const char **argv, const char *prefix,
 +                         const struct commit *current_head, int is_status)
  {
        int fd;
        struct string_list partial;
  
        memset(&partial, 0, sizeof(partial));
        partial.strdup_strings = 1;
 -      if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
 +      if (list_paths(&partial, !current_head ? NULL : "HEAD", prefix, pathspec))
                exit(1);
  
        discard_cache();
                                                (uintmax_t) getpid()),
                                       LOCK_DIE_ON_ERROR);
  
 -      create_base_index();
 +      create_base_index(current_head);
        add_remove_files(&partial);
        refresh_cache(REFRESH_QUIET);
  
@@@ -517,9 -519,12 +518,9 @@@ static int run_status(FILE *fp, const c
        return s->commitable;
  }
  
 -static int is_a_merge(const unsigned char *sha1)
 +static int is_a_merge(const struct commit *current_head)
  {
 -      struct commit *commit = lookup_commit(sha1);
 -      if (!commit || parse_commit(commit))
 -              die(_("could not parse HEAD commit"));
 -      return !!(commit->parents && commit->parents->next);
 +      return !!(current_head->parents && current_head->parents->next);
  }
  
  static const char sign_off_header[] = "Signed-off-by: ";
@@@ -623,7 -628,6 +624,7 @@@ static char *cut_ident_timestamp_part(c
  }
  
  static int prepare_to_commit(const char *index_file, const char *prefix,
 +                           struct commit *current_head,
                             struct wt_status *s,
                             struct strbuf *author_ident)
  {
         * empty due to conflict resolution, which the user should okay.
         */
        if (!commitable && whence != FROM_MERGE && !allow_empty &&
 -          !(amend && is_a_merge(head_sha1))) {
 +          !(amend && is_a_merge(current_head))) {
                run_status(stdout, index_file, prefix, 0, s);
                if (amend)
                        fputs(_(empty_amend_advice), stderr);
@@@ -1003,7 -1007,6 +1004,7 @@@ static const char *read_commit_message(
  static int parse_and_validate_options(int argc, const char *argv[],
                                      const char * const usage[],
                                      const char *prefix,
 +                                    struct commit *current_head,
                                      struct wt_status *s)
  {
        int f = 0;
        if (!use_editor)
                setenv("GIT_EDITOR", ":", 1);
  
 -      if (get_sha1("HEAD", head_sha1))
 -              initial_commit = 1;
 -
        /* Sanity check options */
 -      if (amend && initial_commit)
 +      if (amend && !current_head)
                die(_("You have nothing to amend."));
        if (amend && whence != FROM_COMMIT)
                die(_("You are in the middle of a %s -- cannot amend."), whence_s());
  }
  
  static int dry_run_commit(int argc, const char **argv, const char *prefix,
 -                        struct wt_status *s)
 +                        const struct commit *current_head, struct wt_status *s)
  {
        int commitable;
        const char *index_file;
  
 -      index_file = prepare_index(argc, argv, prefix, 1);
 +      index_file = prepare_index(argc, argv, prefix, current_head, 1);
        commitable = run_status(stdout, index_file, prefix, 0, s);
        rollback_index_files();
  
@@@ -1141,7 -1147,7 +1142,7 @@@ static int git_status_config(const cha
                return 0;
        }
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
 -              s->use_color = git_config_colorbool(k, v, -1);
 +              s->use_color = git_config_colorbool(k, v);
                return 0;
        }
        if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
@@@ -1234,6 -1240,10 +1235,6 @@@ int cmd_status(int argc, const char **a
  
        if (s.relative_paths)
                s.prefix = prefix;
 -      if (s.use_color == -1)
 -              s.use_color = git_use_color_default;
 -      if (diff_use_color_default == -1)
 -              diff_use_color_default = git_use_color_default;
  
        switch (status_format) {
        case STATUS_FORMAT_SHORT:
        return 0;
  }
  
 -static void print_summary(const char *prefix, const unsigned char *sha1)
 +static void print_summary(const char *prefix, const unsigned char *sha1,
 +                        int initial_commit)
  {
        struct rev_info rev;
        struct commit *commit;
@@@ -1374,13 -1383,12 +1375,13 @@@ int cmd_commit(int argc, const char **a
        struct strbuf author_ident = STRBUF_INIT;
        const char *index_file, *reflog_msg;
        char *nl, *p;
 -      unsigned char commit_sha1[20];
 +      unsigned char sha1[20];
        struct ref_lock *ref_lock;
        struct commit_list *parents = NULL, **pptr = &parents;
        struct stat statbuf;
        int allow_fast_forward = 1;
        struct wt_status s;
 +      struct commit *current_head = NULL;
  
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_commit_usage, builtin_commit_options);
        git_config(git_commit_config, &s);
        determine_whence(&s);
  
 -      if (s.use_color == -1)
 -              s.use_color = git_use_color_default;
 -      argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
 -                                        prefix, &s);
 -      if (dry_run) {
 -              if (diff_use_color_default == -1)
 -                      diff_use_color_default = git_use_color_default;
 -              return dry_run_commit(argc, argv, prefix, &s);
 +      if (get_sha1("HEAD", sha1))
 +              current_head = NULL;
 +      else {
 +              current_head = lookup_commit(sha1);
 +              if (!current_head || parse_commit(current_head))
 +                      die(_("could not parse HEAD commit"));
        }
 -      index_file = prepare_index(argc, argv, prefix, 0);
 +      argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
 +                                        prefix, current_head, &s);
 +      if (dry_run)
 +              return dry_run_commit(argc, argv, prefix, current_head, &s);
 +      index_file = prepare_index(argc, argv, prefix, current_head, 0);
  
        /* Set up everything for writing the commit object.  This includes
           running hooks, writing the trees, and interacting with the user.  */
 -      if (!prepare_to_commit(index_file, prefix, &s, &author_ident)) {
 +      if (!prepare_to_commit(index_file, prefix,
 +                             current_head, &s, &author_ident)) {
                rollback_index_files();
                return 1;
        }
  
        /* Determine parents */
        reflog_msg = getenv("GIT_REFLOG_ACTION");
 -      if (initial_commit) {
 +      if (!current_head) {
                if (!reflog_msg)
                        reflog_msg = "commit (initial)";
        } else if (amend) {
                struct commit_list *c;
 -              struct commit *commit;
  
                if (!reflog_msg)
                        reflog_msg = "commit (amend)";
 -              commit = lookup_commit(head_sha1);
 -              if (!commit || parse_commit(commit))
 -                      die(_("could not parse HEAD commit"));
 -
 -              for (c = commit->parents; c; c = c->next)
 +              for (c = current_head->parents; c; c = c->next)
                        pptr = &commit_list_insert(c->item, pptr)->next;
        } else if (whence == FROM_MERGE) {
                struct strbuf m = STRBUF_INIT;
  
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
 -              pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
 +              pptr = &commit_list_insert(current_head, pptr)->next;
                fp = fopen(git_path("MERGE_HEAD"), "r");
                if (fp == NULL)
                        die_errno(_("could not open '%s' for reading"),
                        reflog_msg = (whence == FROM_CHERRY_PICK)
                                        ? "commit (cherry-pick)"
                                        : "commit";
 -              pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
 +              pptr = &commit_list_insert(current_head, pptr)->next;
        }
  
        /* Finally, get the commit message */
                exit(1);
        }
  
 -      if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
 +      if (commit_tree(sb.buf, active_cache_tree->sha1, parents, sha1,
                        author_ident.buf)) {
                rollback_index_files();
                die(_("failed to write commit object"));
        strbuf_release(&author_ident);
  
        ref_lock = lock_any_ref_for_update("HEAD",
 -                                         initial_commit ? NULL : head_sha1,
 +                                         !current_head
 +                                         ? NULL
 +                                         : current_head->object.sha1,
                                           0);
  
        nl = strchr(sb.buf, '\n');
                rollback_index_files();
                die(_("cannot lock HEAD ref"));
        }
 -      if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) {
 +      if (write_ref_sha1(ref_lock, sha1, sb.buf) < 0) {
                rollback_index_files();
                die(_("cannot update HEAD ref"));
        }
                struct notes_rewrite_cfg *cfg;
                cfg = init_copy_notes_for_rewrite("amend");
                if (cfg) {
 -                      copy_note_for_rewrite(cfg, head_sha1, commit_sha1);
 +                      /* we are amending, so current_head is not NULL */
 +                      copy_note_for_rewrite(cfg, current_head->object.sha1, sha1);
                        finish_copy_notes_for_rewrite(cfg);
                }
 -              run_rewrite_hook(head_sha1, commit_sha1);
 +              run_rewrite_hook(current_head->object.sha1, sha1);
        }
        if (!quiet)
 -              print_summary(prefix, commit_sha1);
 +              print_summary(prefix, sha1, !current_head);
  
        return 0;
  }
diff --combined builtin/ls-files.c
index e8a800d3ac42bfce328bea786d8e1efa4ff695c7,0956bb51b95be497831979a7ed3dccc0c141bad2..7cff175745d680d9cde24280e569b4f513d28673
@@@ -353,13 -353,11 +353,13 @@@ void overlay_tree_on_cache(const char *
        }
  }
  
 -int report_path_error(const char *ps_matched, const char **pathspec, int prefix_len)
 +int report_path_error(const char *ps_matched, const char **pathspec, const char *prefix)
  {
        /*
         * Make sure all pathspec matched; otherwise it is an error.
         */
 +      struct strbuf sb = STRBUF_INIT;
 +      const char *name;
        int num, errors = 0;
        for (num = 0; pathspec[num]; num++) {
                int other, found_dup;
                if (found_dup)
                        continue;
  
 +              name = quote_path_relative(pathspec[num], -1, &sb, prefix);
                error("pathspec '%s' did not match any file(s) known to git.",
 -                    pathspec[num] + prefix_len);
 +                    name);
                errors++;
        }
 +      strbuf_release(&sb);
        return errors;
  }
  
@@@ -545,7 -541,7 +545,7 @@@ int cmd_ls_files(int argc, const char *
                strip_trailing_slash_from_submodules();
  
        /* Find common prefix for all pathspec's */
-       max_prefix = pathspec_prefix(prefix, pathspec);
+       max_prefix = common_prefix(pathspec);
        max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
  
        /* Treat unmatching pathspec elements as errors */
  
        if (ps_matched) {
                int bad;
 -              bad = report_path_error(ps_matched, pathspec, prefix_len);
 +              bad = report_path_error(ps_matched, pathspec, prefix);
                if (bad)
                        fprintf(stderr, "Did you forget to 'git add'?\n");
  
diff --combined cache.h
index c989f79835a332d879333ee8b927ede150784e54,e11cf6ab1c73ac97c94e76e8c8699d55af95b978..1aa682d83dfb678f43930a4fa7d816c516d8ee1d
+++ b/cache.h
@@@ -6,7 -6,6 +6,7 @@@
  #include "hash.h"
  #include "advice.h"
  #include "gettext.h"
 +#include "convert.h"
  
  #include SHA1_HEADER
  #ifndef git_SHA_CTX
  #endif
  
  #include <zlib.h>
 -#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
 -#define deflateBound(c,s)  ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
 -#endif
 -
 -void git_inflate_init(z_streamp strm);
 -void git_inflate_end(z_streamp strm);
 -int git_inflate(z_streamp strm, int flush);
 +typedef struct git_zstream {
 +      z_stream z;
 +      unsigned long avail_in;
 +      unsigned long avail_out;
 +      unsigned long total_in;
 +      unsigned long total_out;
 +      unsigned char *next_in;
 +      unsigned char *next_out;
 +} git_zstream;
 +
 +void git_inflate_init(git_zstream *);
 +void git_inflate_init_gzip_only(git_zstream *);
 +void git_inflate_end(git_zstream *);
 +int git_inflate(git_zstream *, int flush);
 +
 +void git_deflate_init(git_zstream *, int level);
 +void git_deflate_init_gzip(git_zstream *, int level);
 +void git_deflate_end(git_zstream *);
 +int git_deflate_end_gently(git_zstream *);
 +int git_deflate(git_zstream *, int flush);
 +unsigned long git_deflate_bound(git_zstream *, unsigned long);
  
  #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
  #define DTYPE(de)     ((de)->d_type)
@@@ -394,7 -379,6 +394,7 @@@ static inline enum object_type object_t
  }
  
  #define GIT_DIR_ENVIRONMENT "GIT_DIR"
 +#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
  #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
  #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
  #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
@@@ -435,17 -419,13 +435,16 @@@ extern char *get_object_directory(void)
  extern char *get_index_file(void);
  extern char *get_graft_file(void);
  extern int set_git_dir(const char *path);
 +extern const char *get_git_namespace(void);
 +extern const char *strip_namespace(const char *namespaced_ref);
  extern const char *get_git_work_tree(void);
 -extern const char *read_gitfile_gently(const char *path);
 +extern const char *read_gitfile(const char *path);
 +extern const char *resolve_gitdir(const char *suspect);
  extern void set_git_work_tree(const char *tree);
  
  #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
  
  extern const char **get_pathspec(const char *prefix, const char **pathspec);
- extern const char *pathspec_prefix(const char *prefix, const char **pathspec);
  extern void setup_work_tree(void);
  extern const char *setup_git_directory_gently(int *);
  extern const char *setup_git_directory(void);
@@@ -602,6 -582,35 +601,6 @@@ extern int fsync_object_files
  extern int core_preload_index;
  extern int core_apply_sparse_checkout;
  
 -enum safe_crlf {
 -      SAFE_CRLF_FALSE = 0,
 -      SAFE_CRLF_FAIL = 1,
 -      SAFE_CRLF_WARN = 2
 -};
 -
 -extern enum safe_crlf safe_crlf;
 -
 -enum auto_crlf {
 -      AUTO_CRLF_FALSE = 0,
 -      AUTO_CRLF_TRUE = 1,
 -      AUTO_CRLF_INPUT = -1
 -};
 -
 -extern enum auto_crlf auto_crlf;
 -
 -enum eol {
 -      EOL_UNSET,
 -      EOL_CRLF,
 -      EOL_LF,
 -#ifdef NATIVE_CRLF
 -      EOL_NATIVE = EOL_CRLF
 -#else
 -      EOL_NATIVE = EOL_LF
 -#endif
 -};
 -
 -extern enum eol core_eol;
 -
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -738,7 -747,7 +737,7 @@@ extern char *expand_user_path(const cha
  char *enter_repo(char *path, int strict);
  static inline int is_absolute_path(const char *path)
  {
 -      return path[0] == '/' || has_dos_drive_prefix(path);
 +      return is_dir_sep(path[0]) || has_dos_drive_prefix(path);
  }
  int is_directory(const char *);
  const char *real_path(const char *path);
@@@ -771,16 -780,10 +770,16 @@@ extern int hash_sha1_file(const void *b
  extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
  extern int force_object_loose(const unsigned char *sha1, time_t mtime);
 +extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
 +extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 +extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
  
  /* global flag to enable extra checks when accessing packed objects */
  extern int do_check_packed_object_crc;
  
 +/* for development: log offset of pack access */
 +extern const char *log_pack_access;
 +
  extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
  
  extern int move_temp_to_file(const char *tmpfile, const char *filename);
@@@ -1006,7 -1009,7 +1005,7 @@@ extern struct packed_git *find_sha1_pac
  extern void pack_report(void);
  extern int open_pack_index(struct packed_git *);
  extern void close_pack_index(struct packed_git *);
 -extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
 +extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
  extern void free_pack_by_name(const char *);
@@@ -1018,36 -1021,7 +1017,36 @@@ extern off_t find_pack_entry_one(const 
  extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
  extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
  extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
 -extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
 +extern int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, unsigned long *);
 +
 +struct object_info {
 +      /* Request */
 +      unsigned long *sizep;
 +
 +      /* Response */
 +      enum {
 +              OI_CACHED,
 +              OI_LOOSE,
 +              OI_PACKED,
 +              OI_DBCACHED
 +      } whence;
 +      union {
 +              /*
 +               * struct {
 +               *      ... Nothing to expose in this case
 +               * } cached;
 +               * struct {
 +               *      ... Nothing to expose in this case
 +               * } loose;
 +               */
 +              struct {
 +                      struct packed_git *pack;
 +                      off_t offset;
 +                      unsigned int is_delta;
 +              } packed;
 +      } u;
 +};
 +extern int sha1_object_info_extended(const unsigned char *, struct object_info *);
  
  /* Dumb servers support */
  extern int update_server_info(int);
@@@ -1077,11 -1051,9 +1076,11 @@@ extern int git_config_bool(const char *
  extern int git_config_maybe_bool(const char *, const char *);
  extern int git_config_string(const char **, const char *, const char *);
  extern int git_config_pathname(const char **, const char *, const char *);
 +extern int git_config_set_in_file(const char *, const char *, const char *);
  extern int git_config_set(const char *, const char *);
  extern int git_config_parse_key(const char *, char **, int *);
  extern int git_config_set_multivar(const char *, const char *, const char *, int);
 +extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
  extern int git_config_rename_section(const char *, const char *);
  extern const char *git_etc_gitconfig(void);
  extern int check_repository_format_version(const char *var, const char *value, void *cb);
@@@ -1091,8 -1063,6 +1090,8 @@@ extern int config_error_nonbool(const c
  extern const char *get_log_output_encoding(void);
  extern const char *get_commit_output_encoding(void);
  
 +extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 +
  extern const char *config_exclusive_filename;
  
  #define MAX_GITNAME (1000)
@@@ -1159,6 -1129,13 +1158,6 @@@ extern void trace_strbuf(const char *ke
  
  void packet_trace_identity(const char *prog);
  
 -/* convert.c */
 -/* returns 1 if *dst was used */
 -extern int convert_to_git(const char *path, const char *src, size_t len,
 -                          struct strbuf *dst, enum safe_crlf checksafe);
 -extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
 -extern int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst);
 -
  /* add */
  /*
   * return 0 if success, 1 - if addition of a file failed and
@@@ -1198,7 -1175,7 +1197,7 @@@ extern int ws_blank_line(const char *li
  #define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
  
  /* ls-files */
 -int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
 +int report_path_error(const char *ps_matched, const char **pathspec, const char *prefix);
  void overlay_tree_on_cache(const char *tree_name, const char *prefix);
  
  char *alias_lookup(const char *alias);
diff --combined setup.c
index b2b4872b700ab9776144f145dfb27d5d16dfc945,ce87900ce3c68ace0f231827bdda0e9a65ef15b3..61c22e6becc1e49f1e92c916a4b8badd30a9cb2f
+++ b/setup.c
@@@ -40,6 -40,34 +40,6 @@@ char *prefix_path(const char *prefix, i
        return sanitized;
  }
  
 -/*
 - * Unlike prefix_path, this should be used if the named file does
 - * not have to interact with index entry; i.e. name of a random file
 - * on the filesystem.
 - */
 -const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 -{
 -      static char path[PATH_MAX];
 -#ifndef WIN32
 -      if (!pfx_len || is_absolute_path(arg))
 -              return arg;
 -      memcpy(path, pfx, pfx_len);
 -      strcpy(path + pfx_len, arg);
 -#else
 -      char *p;
 -      /* don't add prefix to absolute paths, but still replace '\' by '/' */
 -      if (is_absolute_path(arg))
 -              pfx_len = 0;
 -      else if (pfx_len)
 -              memcpy(path, pfx, pfx_len);
 -      strcpy(path + pfx_len, arg);
 -      for (p = path + pfx_len; *p; p++)
 -              if (*p == '\\')
 -                      *p = '/';
 -#endif
 -      return path;
 -}
 -
  int check_filename(const char *prefix, const char *arg)
  {
        const char *name;
@@@ -236,38 -264,6 +236,6 @@@ const char **get_pathspec(const char *p
        return pathspec;
  }
  
- const char *pathspec_prefix(const char *prefix, const char **pathspec)
- {
-       const char **p, *n, *prev;
-       unsigned long max;
-       if (!pathspec)
-               return prefix ? xmemdupz(prefix, strlen(prefix)) : NULL;
-       prev = NULL;
-       max = PATH_MAX;
-       for (p = pathspec; (n = *p) != NULL; p++) {
-               int i, len = 0;
-               for (i = 0; i < max; i++) {
-                       char c = n[i];
-                       if (prev && prev[i] != c)
-                               break;
-                       if (!c || c == '*' || c == '?')
-                               break;
-                       if (c == '/')
-                               len = i+1;
-               }
-               prev = n;
-               if (len < max) {
-                       max = len;
-                       if (!max)
-                               break;
-               }
-       }
-       return max ? xmemdupz(prev, max) : NULL;
- }
  /*
   * Test if it looks like we're at a git directory.
   * We want to see:
@@@ -379,7 -375,7 +347,7 @@@ static int check_repository_format_gent
   * Try to read the location of the git directory from the .git file,
   * return path to git directory if found.
   */
 -const char *read_gitfile_gently(const char *path)
 +const char *read_gitfile(const char *path)
  {
        char *buf;
        char *dir;
@@@ -441,7 -437,7 +409,7 @@@ static const char *setup_explicit_git_d
        if (PATH_MAX - 40 < strlen(gitdirenv))
                die("'$%s' too big", GIT_DIR_ENVIRONMENT);
  
 -      gitfile = (char*)read_gitfile_gently(gitdirenv);
 +      gitfile = (char*)read_gitfile(gitdirenv);
        if (gitfile) {
                gitfile = xstrdup(gitfile);
                gitdirenv = gitfile;
@@@ -665,7 -661,7 +633,7 @@@ static const char *setup_git_directory_
        if (one_filesystem)
                current_device = get_device_or_die(".", NULL);
        for (;;) {
 -              gitfile = (char*)read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
 +              gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
                if (gitfile)
                        gitdirenv = gitfile = xstrdup(gitfile);
                else {
@@@ -714,11 -710,6 +682,11 @@@ const char *setup_git_directory_gently(
        const char *prefix;
  
        prefix = setup_git_directory_gently_1(nongit_ok);
 +      if (prefix)
 +              setenv("GIT_PREFIX", prefix, 1);
 +      else
 +              setenv("GIT_PREFIX", "", 1);
 +
        if (startup_info) {
                startup_info->have_repository = !nongit_ok || !*nongit_ok;
                startup_info->prefix = prefix;
@@@ -812,10 -803,3 +780,10 @@@ const char *setup_git_directory(void
  {
        return setup_git_directory_gently(NULL);
  }
 +
 +const char *resolve_gitdir(const char *suspect)
 +{
 +      if (is_git_directory(suspect))
 +              return suspect;
 +      return read_gitfile(suspect);
 +}