Merge branch 'jk/clone-cmdline-config'
authorJunio C Hamano <gitster@pobox.com>
Tue, 19 Jul 2011 16:45:24 +0000 (09:45 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 19 Jul 2011 16:45:24 +0000 (09:45 -0700)
* jk/clone-cmdline-config:
clone: accept config options on the command line
config: make git_config_parse_parameter a public function
remote: use new OPT_STRING_LIST
parse-options: add OPT_STRING_LIST helper

1  2 
builtin/remote.c
cache.h
config.c
diff --combined builtin/remote.c
index 9ff1cac69b9fd21c5f7dfc06b5859fedccc67644,82cd59e303b51a58440211511bc757dd1599765c..05b1f5b76de36b19ef4bebba32aff1b40cbc2030
@@@ -88,16 -88,6 +88,6 @@@ static inline int postfixcmp(const cha
        return strcmp(string + len1 - len2, postfix);
  }
  
- static int opt_parse_track(const struct option *opt, const char *arg, int not)
- {
-       struct string_list *list = opt->value;
-       if (not)
-               string_list_clear(list, 0);
-       else
-               string_list_append(list, arg);
-       return 0;
- }
  static int fetch_remote(const char *name)
  {
        const char *argv[] = { "fetch", name, NULL, NULL };
@@@ -176,8 -166,8 +166,8 @@@ static int add(int argc, const char **a
                            TAGS_SET),
                OPT_SET_INT(0, NULL, &fetch_tags,
                            "or do not fetch any tag at all (--no-tags)", TAGS_UNSET),
-               OPT_CALLBACK('t', "track", &track, "branch",
-                       "branch(es) to track", opt_parse_track),
+               OPT_STRING_LIST('t', "track", &track, "branch",
+                               "branch(es) to track"),
                OPT_STRING('m', "master", &master, "branch", "master branch"),
                { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
                        "set up remote as a mirror to push to or fetch from",
  
        if (mirror && master)
                die("specifying a master branch makes no sense with --mirror");
 -      if (mirror && track.nr)
 -              die("specifying branches to track makes no sense with --mirror");
 +      if (mirror && !(mirror & MIRROR_FETCH) && track.nr)
 +              die("specifying branches to track makes sense only with fetch mirrors");
  
        name = argv[0];
        url = argv[1];
diff --combined cache.h
index 30be900911fc3985211e80f79dbe86b739103718,fce9bc0503034d8d9c1820c3bb62d9719c47f0c8..5e80113ee93c5c44a7ada5982faaad9a3fcbdc2e
+++ 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)
@@@ -526,18 -511,15 +526,18 @@@ struct pathspec 
        struct pathspec_item {
                const char *match;
                int len;
 -              unsigned int has_wildcard:1;
 +              unsigned int use_wildcard:1;
        } *items;
  };
  
  extern int init_pathspec(struct pathspec *, const char **);
  extern void free_pathspec(struct pathspec *);
  extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
 -extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path, int format_check);
 -extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
 +
 +#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);
 +extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags);
  extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
  
  #define REFRESH_REALLY                0x0001  /* ignore_valid */
@@@ -597,6 -579,35 +597,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 eol;
 -
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -665,24 -676,14 +665,24 @@@ extern char *sha1_pack_name(const unsig
  extern char *sha1_pack_index_name(const unsigned char *sha1);
  extern const char *find_unique_abbrev(const unsigned char *sha1, int);
  extern const unsigned char null_sha1[20];
 -static inline int is_null_sha1(const unsigned char *sha1)
 +
 +static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
  {
 -      return !memcmp(sha1, null_sha1, 20);
 +      int i;
 +
 +      for (i = 0; i < 20; i++, sha1++, sha2++) {
 +              if (*sha1 != *sha2)
 +                      return *sha1 - *sha2;
 +      }
 +
 +      return 0;
  }
 -static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
 +
 +static inline int is_null_sha1(const unsigned char *sha1)
  {
 -      return memcmp(sha1, sha2, 20);
 +      return !hashcmp(sha1, null_sha1);
  }
 +
  static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src)
  {
        memcpy(sha_dst, sha_src, 20);
@@@ -733,7 -734,7 +733,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);
@@@ -745,30 -746,17 +745,30 @@@ char *strip_path_suffix(const char *pat
  int daemon_avoid_alias(const char *path);
  int offset_1st_component(const char *path);
  
 -/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 -extern int sha1_object_info(const unsigned char *, unsigned long *);
 -extern void *read_sha1_file_repl(const unsigned char *sha1, enum object_type *type, unsigned long *size, const unsigned char **replacement);
 +/* object replacement */
 +#define READ_SHA1_FILE_REPLACE 1
 +extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);
  static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
  {
 -      return read_sha1_file_repl(sha1, type, size, NULL);
 +      return read_sha1_file_extended(sha1, type, size, READ_SHA1_FILE_REPLACE);
 +}
 +extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
 +static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)
 +{
 +      if (!read_replace_refs)
 +              return sha1;
 +      return do_lookup_replace_object(sha1);
  }
 +
 +/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 +extern int sha1_object_info(const unsigned char *, unsigned long *);
  extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
  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;
@@@ -802,15 -790,15 +802,15 @@@ struct object_context 
  };
  
  extern int get_sha1(const char *str, unsigned char *sha1);
 -extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int gently, const char *prefix);
 +extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int only_to_die, const char *prefix);
  static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode)
  {
 -      return get_sha1_with_mode_1(str, sha1, mode, 1, NULL);
 +      return get_sha1_with_mode_1(str, sha1, mode, 0, NULL);
  }
 -extern int get_sha1_with_context_1(const char *name, unsigned char *sha1, struct object_context *orc, int gently, const char *prefix);
 +extern int get_sha1_with_context_1(const char *name, unsigned char *sha1, struct object_context *orc, int only_to_die, const char *prefix);
  static inline int get_sha1_with_context(const char *str, unsigned char *sha1, struct object_context *orc)
  {
 -      return get_sha1_with_context_1(str, sha1, orc, 1, NULL);
 +      return get_sha1_with_context_1(str, sha1, orc, 0, NULL);
  }
  extern int get_sha1_hex(const char *hex, unsigned char *sha1);
  extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
@@@ -998,7 -986,7 +998,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 *);
@@@ -1010,51 -998,11 +1010,51 @@@ 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 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);
  
 +/* git_config_parse_key() returns these negated: */
 +#define CONFIG_INVALID_KEY 1
 +#define CONFIG_NO_SECTION_OR_NAME 2
 +/* git_config_set(), git_config_set_multivar() return the above or these: */
 +#define CONFIG_NO_LOCK -1
 +#define CONFIG_INVALID_FILE 3
 +#define CONFIG_NO_WRITE 4
 +#define CONFIG_NOTHING_SET 5
 +#define CONFIG_INVALID_PATTERN 6
 +
  typedef int (*config_fn_t)(const char *, const char *, void *);
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
@@@ -1082,6 -1030,8 +1082,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)
@@@ -1148,6 -1098,13 +1150,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
diff --combined config.c
index 9340dfe5a831fb13c3a15a01976a22bb194eeb58,a1f3b59568bb6edacc161df65a6016974429c6fa..6b61a849d26c7a35f57d74c9d5f0adbb1f85c72d
+++ b/config.c
  
  #define MAXNAME (256)
  
 -static FILE *config_file;
 -static const char *config_file_name;
 -static int config_linenr;
 -static int config_file_eof;
 +typedef struct config_file {
 +      struct config_file *prev;
 +      FILE *f;
 +      const char *name;
 +      int linenr;
 +      int eof;
 +      struct strbuf value;
 +      char var[MAXNAME];
 +} config_file;
 +
 +static config_file *cf;
 +
  static int zlib_compression_seen;
  
  const char *config_exclusive_filename = NULL;
@@@ -47,8 -39,8 +47,8 @@@ void git_config_push_parameter(const ch
        strbuf_release(&env);
  }
  
static int git_config_parse_parameter(const char *text,
-                                     config_fn_t fn, void *data)
+ int git_config_parse_parameter(const char *text,
+                              config_fn_t fn, void *data)
  {
        struct strbuf **pair;
        pair = strbuf_split_str(text, '=', 2);
@@@ -107,7 -99,7 +107,7 @@@ static int get_next_char(void
        FILE *f;
  
        c = '\n';
 -      if ((f = config_file) != NULL) {
 +      if (cf && ((f = cf->f) != NULL)) {
                c = fgetc(f);
                if (c == '\r') {
                        /* DOS like systems */
                        }
                }
                if (c == '\n')
 -                      config_linenr++;
 +                      cf->linenr++;
                if (c == EOF) {
 -                      config_file_eof = 1;
 +                      cf->eof = 1;
                        c = '\n';
                }
        }
  
  static char *parse_value(void)
  {
 -      static char value[1024];
 -      int quote = 0, comment = 0, len = 0, space = 0;
 +      int quote = 0, comment = 0, space = 0;
  
 +      strbuf_reset(&cf->value);
        for (;;) {
                int c = get_next_char();
 -              if (len >= sizeof(value) - 1)
 -                      return NULL;
                if (c == '\n') {
                        if (quote)
                                return NULL;
 -                      value[len] = 0;
 -                      return value;
 +                      return cf->value.buf;
                }
                if (comment)
                        continue;
                if (isspace(c) && !quote) {
 -                      if (len)
 +                      if (cf->value.len)
                                space++;
                        continue;
                }
                        }
                }
                for (; space; space--)
 -                      value[len++] = ' ';
 +                      strbuf_addch(&cf->value, ' ');
                if (c == '\\') {
                        c = get_next_char();
                        switch (c) {
                        default:
                                return NULL;
                        }
 -                      value[len++] = c;
 +                      strbuf_addch(&cf->value, c);
                        continue;
                }
                if (c == '"') {
                        quote = 1-quote;
                        continue;
                }
 -              value[len++] = c;
 +              strbuf_addch(&cf->value, c);
        }
  }
  
@@@ -199,7 -194,7 +199,7 @@@ static int get_value(config_fn_t fn, vo
        /* Get the full name */
        for (;;) {
                c = get_next_char();
 -              if (config_file_eof)
 +              if (cf->eof)
                        break;
                if (!iskeychar(c))
                        break;
@@@ -263,7 -258,7 +263,7 @@@ static int get_base_var(char *name
  
        for (;;) {
                int c = get_next_char();
 -              if (config_file_eof)
 +              if (cf->eof)
                        return -1;
                if (c == ']')
                        return baselen;
@@@ -281,7 -276,7 +281,7 @@@ static int git_parse_file(config_fn_t f
  {
        int comment = 0;
        int baselen = 0;
 -      static char var[MAXNAME];
 +      char *var = cf->var;
  
        /* U+FEFF Byte Order Mark in UTF8 */
        static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf";
                        }
                }
                if (c == '\n') {
 -                      if (config_file_eof)
 +                      if (cf->eof)
                                return 0;
                        comment = 0;
                        continue;
                if (get_value(fn, data, var, baselen+1) < 0)
                        break;
        }
 -      die("bad config file line %d in %s", config_linenr, config_file_name);
 +      die("bad config file line %d in %s", cf->linenr, cf->name);
  }
  
  static int parse_unit_factor(const char *end, unsigned long *val)
@@@ -381,8 -376,8 +381,8 @@@ int git_parse_ulong(const char *value, 
  
  static void die_bad_config(const char *name)
  {
 -      if (config_file_name)
 -              die("bad config value for '%s' in %s", name, config_file_name);
 +      if (cf && cf->name)
 +              die("bad config value for '%s' in %s", name, cf->name);
        die("bad config value for '%s'", name);
  }
  
@@@ -578,7 -573,7 +578,7 @@@ static int git_default_core_config(cons
  
        if (!strcmp(var, "core.autocrlf")) {
                if (value && !strcasecmp(value, "input")) {
 -                      if (eol == EOL_CRLF)
 +                      if (core_eol == EOL_CRLF)
                                return error("core.autocrlf=input conflicts with core.eol=crlf");
                        auto_crlf = AUTO_CRLF_INPUT;
                        return 0;
  
        if (!strcmp(var, "core.eol")) {
                if (value && !strcasecmp(value, "lf"))
 -                      eol = EOL_LF;
 +                      core_eol = EOL_LF;
                else if (value && !strcasecmp(value, "crlf"))
 -                      eol = EOL_CRLF;
 +                      core_eol = EOL_CRLF;
                else if (value && !strcasecmp(value, "native"))
 -                      eol = EOL_NATIVE;
 +                      core_eol = EOL_NATIVE;
                else
 -                      eol = EOL_UNSET;
 -              if (eol == EOL_CRLF && auto_crlf == AUTO_CRLF_INPUT)
 +                      core_eol = EOL_UNSET;
 +              if (core_eol == EOL_CRLF && auto_crlf == AUTO_CRLF_INPUT)
                        return error("core.autocrlf=input conflicts with core.eol=crlf");
                return 0;
        }
@@@ -802,24 -797,13 +802,24 @@@ int git_config_from_file(config_fn_t fn
  
        ret = -1;
        if (f) {
 -              config_file = f;
 -              config_file_name = filename;
 -              config_linenr = 1;
 -              config_file_eof = 0;
 +              config_file top;
 +
 +              /* push config-file parsing state stack */
 +              top.prev = cf;
 +              top.f = f;
 +              top.name = filename;
 +              top.linenr = 1;
 +              top.eof = 0;
 +              strbuf_init(&top.value, 1024);
 +              cf = &top;
 +
                ret = git_parse_file(fn, data);
 +
 +              /* pop config-file parsing state stack */
 +              strbuf_release(&top.value);
 +              cf = top.prev;
 +
                fclose(f);
 -              config_file_name = NULL;
        }
        return ret;
  }
@@@ -927,7 -911,6 +927,7 @@@ static int store_aux(const char *key, c
  {
        const char *ep;
        size_t section_len;
 +      FILE *f = cf->f;
  
        switch (store.state) {
        case KEY_SEEN:
                                return 1;
                        }
  
 -                      store.offset[store.seen] = ftell(config_file);
 +                      store.offset[store.seen] = ftell(f);
                        store.seen++;
                }
                break;
                 * Do not increment matches: this is no match, but we
                 * just made sure we are in the desired section.
                 */
 -              store.offset[store.seen] = ftell(config_file);
 +              store.offset[store.seen] = ftell(f);
                /* fallthru */
        case SECTION_END_SEEN:
        case START:
                if (matches(key, value)) {
 -                      store.offset[store.seen] = ftell(config_file);
 +                      store.offset[store.seen] = ftell(f);
                        store.state = KEY_SEEN;
                        store.seen++;
                } else {
                        if (strrchr(key, '.') - key == store.baselen &&
                              !strncmp(key, store.key, store.baselen)) {
                                        store.state = SECTION_SEEN;
 -                                      store.offset[store.seen] = ftell(config_file);
 +                                      store.offset[store.seen] = ftell(f);
                        }
                }
        }
@@@ -1121,12 -1104,12 +1121,12 @@@ int git_config_parse_key(const char *ke
  
        if (last_dot == NULL || last_dot == key) {
                error("key does not contain a section: %s", key);
 -              return -2;
 +              return -CONFIG_NO_SECTION_OR_NAME;
        }
  
        if (!last_dot[1]) {
                error("key does not contain variable name: %s", key);
 -              return -2;
 +              return -CONFIG_NO_SECTION_OR_NAME;
        }
  
        baselen = last_dot - key;
  
  out_free_ret_1:
        free(*store_key);
 -      return -1;
 +      return -CONFIG_INVALID_KEY;
  }
  
  /*
@@@ -1219,7 -1202,7 +1219,7 @@@ int git_config_set_multivar(const char 
        if (fd < 0) {
                error("could not lock config file %s: %s", config_filename, strerror(errno));
                free(store.key);
 -              ret = -1;
 +              ret = CONFIG_NO_LOCK;
                goto out_free;
        }
  
                if ( ENOENT != errno ) {
                        error("opening %s: %s", config_filename,
                              strerror(errno));
 -                      ret = 3; /* same as "invalid config file" */
 +                      ret = CONFIG_INVALID_FILE; /* same as "invalid config file" */
                        goto out_free;
                }
                /* if nothing to unset, error out */
                if (value == NULL) {
 -                      ret = 5;
 +                      ret = CONFIG_NOTHING_SET;
                        goto out_free;
                }
  
                                        REG_EXTENDED)) {
                                error("invalid pattern: %s", value_regex);
                                free(store.value_regex);
 -                              ret = 6;
 +                              ret = CONFIG_INVALID_PATTERN;
                                goto out_free;
                        }
                }
                                regfree(store.value_regex);
                                free(store.value_regex);
                        }
 -                      ret = 3;
 +                      ret = CONFIG_INVALID_FILE;
                        goto out_free;
                }
  
                /* if nothing to unset, or too many matches, error out */
                if ((store.seen == 0 && value == NULL) ||
                                (store.seen > 1 && multi_replace == 0)) {
 -                      ret = 5;
 +                      ret = CONFIG_NOTHING_SET;
                        goto out_free;
                }
  
  
        if (commit_lock_file(lock) < 0) {
                error("could not commit config file %s", config_filename);
 -              ret = 4;
 +              ret = CONFIG_NO_WRITE;
                goto out_free;
        }
  
@@@ -1434,7 -1417,6 +1434,7 @@@ int git_config_rename_section(const cha
        struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);
        int out_fd;
        char buf[1024];
 +      FILE *config_file;
  
        if (config_exclusive_filename)
                config_filename = xstrdup(config_exclusive_filename);