Merge branch 'lf/read-blob-data-from-index'
authorJunio C Hamano <gitster@pobox.com>
Mon, 22 Apr 2013 01:39:45 +0000 (18:39 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Apr 2013 01:39:45 +0000 (18:39 -0700)
Reduce duplicated code between convert.c and attr.c.

* lf/read-blob-data-from-index:
convert.c: remove duplicate code
read_blob_data_from_index(): optionally return the size of blob data
attr.c: extract read_index_data() as read_blob_data_from_index()

1  2 
attr.c
cache.h
convert.c
read-cache.c
diff --combined attr.c
index 689bc2a8961fac72a01e615764af53f49d01c3ec,09e7e50d3e4e3548187e230ea9bf20398e0959a0..0e774c6f22f9fd6c7e27490e5bed5be1f9f10de5
--- 1/attr.c
--- 2/attr.c
+++ b/attr.c
@@@ -286,7 -286,7 +286,7 @@@ static struct match_attr *parse_attr_li
   * (reading the file from top to bottom), .gitattribute of the root
   * directory (again, reading the file from top to bottom) down to the
   * current directory, and then scan the list backwards to find the first match.
 - * This is exactly the same as what excluded() does in dir.c to deal with
 + * This is exactly the same as what is_excluded() does in dir.c to deal with
   * .gitignore
   */
  
@@@ -381,46 -381,13 +381,13 @@@ static struct attr_stack *read_attr_fro
        return res;
  }
  
- static void *read_index_data(const char *path)
- {
-       int pos, len;
-       unsigned long sz;
-       enum object_type type;
-       void *data;
-       struct index_state *istate = use_index ? use_index : &the_index;
-       len = strlen(path);
-       pos = index_name_pos(istate, path, len);
-       if (pos < 0) {
-               /*
-                * We might be in the middle of a merge, in which
-                * case we would read stage #2 (ours).
-                */
-               int i;
-               for (i = -pos - 1;
-                    (pos < 0 && i < istate->cache_nr &&
-                     !strcmp(istate->cache[i]->name, path));
-                    i++)
-                       if (ce_stage(istate->cache[i]) == 2)
-                               pos = i;
-       }
-       if (pos < 0)
-               return NULL;
-       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
-       if (!data || type != OBJ_BLOB) {
-               free(data);
-               return NULL;
-       }
-       return data;
- }
  static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
  {
        struct attr_stack *res;
        char *buf, *sp;
        int lineno = 0;
  
-       buf = read_index_data(path);
+       buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL);
        if (!buf)
                return NULL;
  
diff --combined cache.h
index ba5a47c480c4f6a69aaf8ffc5f302af9ee3ab5a0,627776b5e6b6fbd74c44935033c36c8811ba3601..94ca1acf704bd2dfdc561b6b2d3d64740b975f61
+++ b/cache.h
@@@ -34,7 -34,6 +34,7 @@@ int git_inflate(git_zstream *, int flus
  
  void git_deflate_init(git_zstream *, int level);
  void git_deflate_init_gzip(git_zstream *, int level);
 +void git_deflate_init_raw(git_zstream *, int level);
  void git_deflate_end(git_zstream *);
  int git_deflate_abort(git_zstream *);
  int git_deflate_end_gently(git_zstream *);
@@@ -162,9 -161,6 +162,9 @@@ struct cache_entry 
  #define CE_UNPACKED          (1 << 24)
  #define CE_NEW_SKIP_WORKTREE (1 << 25)
  
 +/* used to temporarily mark paths matched by pathspecs */
 +#define CE_MATCHED           (1 << 26)
 +
  /*
   * Extended on-disk flags
   */
@@@ -311,6 -307,7 +311,7 @@@ extern void free_name_hash(struct index
  #define resolve_undo_clear() resolve_undo_clear_index(&the_index)
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
  #define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)
+ #define read_blob_data_from_cache(path, sz) read_blob_data_from_index(&the_index, (path), (sz))
  #endif
  
  enum object_type {
@@@ -334,11 -331,9 +335,11 @@@ static inline enum object_type object_t
                OBJ_BLOB;
  }
  
 +/* Double-check local_repo_env below if you add to this list. */
  #define GIT_DIR_ENVIRONMENT "GIT_DIR"
  #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
  #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
 +#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
  #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
  #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
  #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
  #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
  #define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
  #define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
 +#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
  
  /*
 - * Repository-local GIT_* environment variables
 - * The array is NULL-terminated to simplify its usage in contexts such
 - * environment creation or simple walk of the list.
 - * The number of non-NULL entries is available as a macro.
 + * This environment variable is expected to contain a boolean indicating
 + * whether we should or should not treat:
 + *
 + *   GIT_DIR=foo.git git ...
 + *
 + * as if GIT_WORK_TREE=. was given. It's not expected that users will make use
 + * of this, but we use it internally to communicate to sub-processes that we
 + * are in a bare repo. If not set, defaults to true.
   */
 -#define LOCAL_REPO_ENV_SIZE 9
 -extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1];
 +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
 +
 +/*
 + * Repository-local GIT_* environment variables; these will be cleared
 + * when git spawns a sub-process that runs inside another repository.
 + * The array is NULL-terminated, which makes it easy to pass in the "env"
 + * parameter of a run-command invocation, or to do a simple walk.
 + */
 +extern const char * const local_repo_env[];
  
  extern int is_bare_repository_cfg;
  extern int is_bare_repository(void);
@@@ -465,12 -448,12 +466,13 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_IGNORE_ERRORS       4
  #define ADD_CACHE_IGNORE_REMOVAL 8
  #define ADD_CACHE_INTENT 16
 +#define ADD_CACHE_IMPLICIT_DOT 32     /* internal to "git add -u/-A" */
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
  extern int index_name_is_other(const struct index_state *, const char *, int);
+ extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
  
  /* do stat comparison even if CE_VALID is true */
  #define CE_MATCH_IGNORE_VALID         01
  extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
  extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
  
 +#define PATHSPEC_ONESTAR 1    /* the pathspec pattern sastisfies GFNM_ONESTAR */
 +
  struct pathspec {
        const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
        int nr;
        struct pathspec_item {
                const char *match;
                int len;
 -              unsigned int use_wildcard:1;
 +              int nowildcard_len;
 +              int flags;
        } *items;
  };
  
@@@ -501,8 -481,6 +503,8 @@@ extern int init_pathspec(struct pathspe
  extern void free_pathspec(struct pathspec *);
  extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
  
 +extern int limit_pathspec_to_literal(void);
 +
  #define HASH_WRITE_OBJECT 1
  #define HASH_FORMAT_CHECK 2
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@@ -543,7 -521,6 +545,7 @@@ extern int delete_ref(const char *, con
  /* Environment bits from configuration mechanism */
  extern int trust_executable_bit;
  extern int trust_ctime;
 +extern int check_stat;
  extern int quote_path_fully;
  extern int has_symlinks;
  extern int minimum_abbrev, default_abbrev;
@@@ -570,12 -547,6 +572,12 @@@ extern int core_preload_index
  extern int core_apply_sparse_checkout;
  extern int precomposed_unicode;
  
 +/*
 + * The character that begins a commented line in user-editable file
 + * that is subject to stripspace.
 + */
 +extern char comment_line_char;
 +
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -720,7 -691,8 +722,7 @@@ enum sharedrepo 
        PERM_EVERYBODY      = 0664
  };
  int git_config_perm(const char *var, const char *value);
 -int set_shared_perm(const char *path, int mode);
 -#define adjust_shared_perm(path) set_shared_perm((path), 0)
 +int adjust_shared_perm(const char *path);
  int safe_create_leading_directories(char *path);
  int safe_create_leading_directories_const(const char *path);
  int mkdir_in_gitdir(const char *path);
@@@ -1019,20 -991,15 +1021,20 @@@ struct ref 
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
        char *symref;
 -      unsigned int force:1,
 +      unsigned int
 +              force:1,
 +              forced_update:1,
                merge:1,
 -              nonfastforward:1,
 -              deletion:1;
 +              deletion:1,
 +              matched:1;
        enum {
                REF_STATUS_NONE = 0,
                REF_STATUS_OK,
                REF_STATUS_REJECT_NONFASTFORWARD,
 +              REF_STATUS_REJECT_ALREADY_EXISTS,
                REF_STATUS_REJECT_NODELETE,
 +              REF_STATUS_REJECT_FETCH_FIRST,
 +              REF_STATUS_REJECT_NEEDS_FORCE,
                REF_STATUS_UPTODATE,
                REF_STATUS_REMOTE_REJECT,
                REF_STATUS_EXPECTING_REPORT
@@@ -1056,9 -1023,7 +1058,9 @@@ struct extra_have_objects 
        int nr, alloc;
        unsigned char (*array)[20];
  };
 -extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
 +extern struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
 +                                   struct ref **list, unsigned int flags,
 +                                   struct extra_have_objects *);
  extern int server_supports(const char *feature);
  extern int parse_feature_request(const char *features, const char *feature);
  extern const char *server_feature_value(const char *feature, int *len_ret);
@@@ -1066,9 -1031,6 +1068,9 @@@ extern const char *parse_feature_value(
  
  extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
  
 +/* A hook for count-objects to report invalid files in pack directory */
 +extern void (*report_garbage)(const char *desc, const char *path);
 +
  extern void prepare_packed_git(void);
  extern void reprepare_packed_git(void);
  extern void install_packed_git(struct packed_git *pack);
@@@ -1166,9 -1128,6 +1168,9 @@@ extern int check_repository_format_vers
  extern int git_env_bool(const char *, int);
  extern int git_config_system(void);
  extern int config_error_nonbool(const char *);
 +#if defined(__GNUC__) && ! defined(__clang__)
 +#define config_error_nonbool(s) (config_error_nonbool(s), -1)
 +#endif
  extern const char *get_log_output_encoding(void);
  extern const char *get_commit_output_encoding(void);
  
@@@ -1182,28 -1141,12 +1184,28 @@@ struct config_include_data 
  #define CONFIG_INCLUDE_INIT { 0 }
  extern int git_config_include(const char *name, const char *value, void *data);
  
 +/*
 + * Match and parse a config key of the form:
 + *
 + *   section.(subsection.)?key
 + *
 + * (i.e., what gets handed to a config_fn_t). The caller provides the section;
 + * we return -1 if it does not match, 0 otherwise. The subsection and key
 + * out-parameters are filled by the function (and subsection is NULL if it is
 + * missing).
 + */
 +extern int parse_config_key(const char *var,
 +                          const char *section,
 +                          const char **subsection, int *subsection_len,
 +                          const char **key);
 +
  extern int committer_ident_sufficiently_given(void);
  extern int author_ident_sufficiently_given(void);
  
  extern const char *git_commit_encoding;
  extern const char *git_log_output_encoding;
  extern const char *git_mailmap_file;
 +extern const char *git_mailmap_blob;
  
  /* IO helper functions */
  extern void maybe_flush_or_die(FILE *, const char *);
diff --combined convert.c
index 3520252d3abaf49d4b7682ad083da8b7ae6be4c6,5b164baf241f022bd21133159c8a05a21dd91b97..2a2e46c2012de3af673b9d8d8647ec894f07b65a
+++ b/convert.c
@@@ -153,36 -153,13 +153,13 @@@ static void check_safe_crlf(const char 
  
  static int has_cr_in_index(const char *path)
  {
-       int pos, len;
        unsigned long sz;
-       enum object_type type;
        void *data;
        int has_cr;
-       struct index_state *istate = &the_index;
  
-       len = strlen(path);
-       pos = index_name_pos(istate, path, len);
-       if (pos < 0) {
-               /*
-                * We might be in the middle of a merge, in which
-                * case we would read stage #2 (ours).
-                */
-               int i;
-               for (i = -pos - 1;
-                    (pos < 0 && i < istate->cache_nr &&
-                     !strcmp(istate->cache[i]->name, path));
-                    i++)
-                       if (ce_stage(istate->cache[i]) == 2)
-                               pos = i;
-       }
-       if (pos < 0)
+       data = read_blob_data_from_cache(path, &sz);
+       if (!data)
                return 0;
-       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
-       if (!data || type != OBJ_BLOB) {
-               free(data);
-               return 0;
-       }
        has_cr = memchr(data, '\r', sz) != NULL;
        free(data);
        return has_cr;
@@@ -457,7 -434,7 +434,7 @@@ static struct convert_driver 
  
  static int read_convert_config(const char *var, const char *value, void *cb)
  {
 -      const char *ep, *name;
 +      const char *key, *name;
        int namelen;
        struct convert_driver *drv;
  
         * External conversion drivers are configured using
         * "filter.<name>.variable".
         */
 -      if (prefixcmp(var, "filter.") || (ep = strrchr(var, '.')) == var + 6)
 +      if (parse_config_key(var, "filter", &name, &namelen, &key) < 0 || !name)
                return 0;
 -      name = var + 7;
 -      namelen = ep - name;
        for (drv = user_convert; drv; drv = drv->next)
                if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
                        break;
                user_convert_tail = &(drv->next);
        }
  
 -      ep++;
 -
        /*
         * filter.<name>.smudge and filter.<name>.clean specifies
         * the command line:
         * The command-line will not be interpolated in any way.
         */
  
 -      if (!strcmp("smudge", ep))
 +      if (!strcmp("smudge", key))
                return git_config_string(&drv->smudge, var, value);
  
 -      if (!strcmp("clean", ep))
 +      if (!strcmp("clean", key))
                return git_config_string(&drv->clean, var, value);
  
 -      if (!strcmp("required", ep)) {
 +      if (!strcmp("required", key)) {
                drv->required = git_config_bool(var, value);
                return 0;
        }
diff --combined read-cache.c
index 5a9704f4e5b974a46bc5486373a26816c5b3b4bd,8c27ed2c66345c0a1538932f57c554fcfe5339a5..04ed561bfe7dd8fbf1988190f95eb1cc3530ff58
@@@ -197,25 -197,21 +197,25 @@@ static int ce_match_stat_basic(struct c
        }
        if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
                changed |= MTIME_CHANGED;
 -      if (trust_ctime && ce->ce_ctime.sec != (unsigned int)st->st_ctime)
 +      if (trust_ctime && check_stat &&
 +          ce->ce_ctime.sec != (unsigned int)st->st_ctime)
                changed |= CTIME_CHANGED;
  
  #ifdef USE_NSEC
 -      if (ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
 +      if (check_stat && ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
                changed |= MTIME_CHANGED;
 -      if (trust_ctime && ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
 +      if (trust_ctime && check_stat &&
 +          ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
                changed |= CTIME_CHANGED;
  #endif
  
 -      if (ce->ce_uid != (unsigned int) st->st_uid ||
 -          ce->ce_gid != (unsigned int) st->st_gid)
 -              changed |= OWNER_CHANGED;
 -      if (ce->ce_ino != (unsigned int) st->st_ino)
 -              changed |= INODE_CHANGED;
 +      if (check_stat) {
 +              if (ce->ce_uid != (unsigned int) st->st_uid ||
 +                      ce->ce_gid != (unsigned int) st->st_gid)
 +                      changed |= OWNER_CHANGED;
 +              if (ce->ce_ino != (unsigned int) st->st_ino)
 +                      changed |= INODE_CHANGED;
 +      }
  
  #ifdef USE_STDEV
        /*
         * clients will have different views of what "device"
         * the filesystem is on
         */
 -      if (ce->ce_dev != (unsigned int) st->st_dev)
 -              changed |= INODE_CHANGED;
 +      if (check_stat && ce->ce_dev != (unsigned int) st->st_dev)
 +                      changed |= INODE_CHANGED;
  #endif
  
        if (ce->ce_size != (unsigned int) st->st_size)
@@@ -1899,3 -1895,37 +1899,37 @@@ int index_name_is_other(const struct in
        }
        return 1;
  }
+ void *read_blob_data_from_index(struct index_state *istate, const char *path, unsigned long *size)
+ {
+       int pos, len;
+       unsigned long sz;
+       enum object_type type;
+       void *data;
+       len = strlen(path);
+       pos = index_name_pos(istate, path, len);
+       if (pos < 0) {
+               /*
+                * We might be in the middle of a merge, in which
+                * case we would read stage #2 (ours).
+                */
+               int i;
+               for (i = -pos - 1;
+                    (pos < 0 && i < istate->cache_nr &&
+                     !strcmp(istate->cache[i]->name, path));
+                    i++)
+                       if (ce_stage(istate->cache[i]) == 2)
+                               pos = i;
+       }
+       if (pos < 0)
+               return NULL;
+       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
+       if (!data || type != OBJ_BLOB) {
+               free(data);
+               return NULL;
+       }
+       if (size)
+               *size = sz;
+       return data;
+ }