Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Sat, 16 Feb 2008 08:20:37 +0000 (00:20 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 16 Feb 2008 08:20:37 +0000 (00:20 -0800)
* maint:
commit: discard index after setting up partial commit
filter-branch: handle filenames that need quoting
diff: Fix miscounting of --check output
hg-to-git: fix parent analysis
mailinfo: feed only one line to handle_filter() for QP input
diff.c: add "const" qualifier to "char *cmd" member of "struct ll_diff_driver"
Add "const" qualifier to "char *excludes_file".
Add "const" qualifier to "char *editor_program".
Add "const" qualifier to "char *pager_program".
config: add 'git_config_string' to refactor string config variables.
diff.c: remove useless check for value != NULL
fast-import: check return value from unpack_entry()
Validate nicknames of remote branches to prohibit confusing ones
diff.c: replace a 'strdup' with 'xstrdup'.
diff.c: fixup garding of config parser from value=NULL

1  2 
builtin-commit.c
cache.h
config.c
diff.c
diff --combined builtin-commit.c
index 717eb18da0e0cbe901dd8a660649388ccc0a24e1,45232a11c408530e7ca011f7262532df236c2576..ff6ea0d85eebdd0b815f33b9b1ef0df8d1885988
@@@ -160,7 -160,7 +160,7 @@@ static int list_paths(struct path_list 
  
        for (i = 0; i < active_nr; i++) {
                struct cache_entry *ce = active_cache[i];
 -              if (ce->ce_flags & htons(CE_UPDATE))
 +              if (ce->ce_flags & CE_UPDATE)
                        continue;
                if (!pathspec_match(pattern, m, ce->name, 0))
                        continue;
@@@ -317,6 -317,10 +317,10 @@@ static char *prepare_index(int argc, co
        if (write_cache(fd, active_cache, active_nr) ||
            close_lock_file(&false_lock))
                die("unable to write temporary index file");
+       discard_cache();
+       read_cache_from(false_lock.filename);
        return false_lock.filename;
  }
  
diff --combined cache.h
index 3867ba7ff5c3946e0449c78b26880a71107730a0,43ba6a3ba568fb0b9e93c8aeb78782e12bfda416..cdcabe92b6e51fcda60ec68cd0ab21ae11cca66f
+++ b/cache.h
@@@ -3,7 -3,6 +3,7 @@@
  
  #include "git-compat-util.h"
  #include "strbuf.h"
 +#include "hash.h"
  
  #include SHA1_HEADER
  #include <zlib.h>
@@@ -95,84 -94,48 +95,84 @@@ struct cache_time 
   * We save the fields in big-endian order to allow using the
   * index file over NFS transparently.
   */
 +struct ondisk_cache_entry {
 +      struct cache_time ctime;
 +      struct cache_time mtime;
 +      unsigned int dev;
 +      unsigned int ino;
 +      unsigned int mode;
 +      unsigned int uid;
 +      unsigned int gid;
 +      unsigned int size;
 +      unsigned char sha1[20];
 +      unsigned short flags;
 +      char name[FLEX_ARRAY]; /* more */
 +};
 +
  struct cache_entry {
 -      struct cache_time ce_ctime;
 -      struct cache_time ce_mtime;
 +      struct cache_entry *next;
 +      unsigned int ce_ctime;
 +      unsigned int ce_mtime;
        unsigned int ce_dev;
        unsigned int ce_ino;
        unsigned int ce_mode;
        unsigned int ce_uid;
        unsigned int ce_gid;
        unsigned int ce_size;
 +      unsigned int ce_flags;
        unsigned char sha1[20];
 -      unsigned short ce_flags;
        char name[FLEX_ARRAY]; /* more */
  };
  
  #define CE_NAMEMASK  (0x0fff)
  #define CE_STAGEMASK (0x3000)
 -#define CE_UPDATE    (0x4000)
  #define CE_VALID     (0x8000)
  #define CE_STAGESHIFT 12
  
 -#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
 -#define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags))
 +/* In-memory only */
 +#define CE_UPDATE    (0x10000)
 +#define CE_REMOVE    (0x20000)
 +#define CE_UPTODATE  (0x40000)
 +#define CE_UNHASHED  (0x80000)
 +
 +static inline unsigned create_ce_flags(size_t len, unsigned stage)
 +{
 +      if (len >= CE_NAMEMASK)
 +              len = CE_NAMEMASK;
 +      return (len | (stage << CE_STAGESHIFT));
 +}
 +
 +static inline size_t ce_namelen(const struct cache_entry *ce)
 +{
 +      size_t len = ce->ce_flags & CE_NAMEMASK;
 +      if (len < CE_NAMEMASK)
 +              return len;
 +      return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK;
 +}
 +
  #define ce_size(ce) cache_entry_size(ce_namelen(ce))
 -#define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT)
 +#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
 +#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
 +#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
 +#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
  
  #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
  static inline unsigned int create_ce_mode(unsigned int mode)
  {
        if (S_ISLNK(mode))
 -              return htonl(S_IFLNK);
 +              return S_IFLNK;
        if (S_ISDIR(mode) || S_ISGITLINK(mode))
 -              return htonl(S_IFGITLINK);
 -      return htonl(S_IFREG | ce_permissions(mode));
 +              return S_IFGITLINK;
 +      return S_IFREG | ce_permissions(mode);
  }
  static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
  {
        extern int trust_executable_bit, has_symlinks;
        if (!has_symlinks && S_ISREG(mode) &&
 -          ce && S_ISLNK(ntohl(ce->ce_mode)))
 +          ce && S_ISLNK(ce->ce_mode))
                return ce->ce_mode;
        if (!trust_executable_bit && S_ISREG(mode)) {
 -              if (ce && S_ISREG(ntohl(ce->ce_mode)))
 +              if (ce && S_ISREG(ce->ce_mode))
                        return ce->ce_mode;
                return create_ce_mode(0666);
        }
        S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
  
  #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
 +#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7)
  
  struct index_state {
        struct cache_entry **cache;
        unsigned int cache_nr, cache_alloc, cache_changed;
        struct cache_tree *cache_tree;
        time_t timestamp;
 -      void *mmap;
 -      size_t mmap_size;
 +      void *alloc;
 +      unsigned name_hash_initialized : 1;
 +      struct hash_table name_hash;
  };
  
  extern struct index_state the_index;
  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)
  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
 +#define cache_name_exists(name, namelen) index_name_exists(&the_index, (name), (namelen))
  #endif
  
  enum object_type {
@@@ -303,7 -263,6 +303,7 @@@ extern int read_index_from(struct index
  extern int write_index(struct index_state *, int newfd);
  extern int discard_index(struct index_state *);
  extern int verify_path(const char *path);
 +extern int index_name_exists(struct index_state *istate, const char *name, int namelen);
  extern int index_name_pos(struct index_state *, const char *name, int namelen);
  #define ADD_CACHE_OK_TO_ADD 1         /* Ok to add */
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
@@@ -625,6 -584,7 +625,7 @@@ extern int git_parse_ulong(const char *
  extern int git_config_int(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
  extern int git_config_bool(const char *, const char *);
+ extern int git_config_string(const char **, const char *, const char *);
  extern int git_config_set(const char *, const char *);
  extern int git_config_set_multivar(const char *, const char *, const char *, int);
  extern int git_config_rename_section(const char *, const char *);
@@@ -650,12 -610,12 +651,12 @@@ extern int write_or_whine_pipe(int fd, 
  
  /* pager.c */
  extern void setup_pager(void);
- extern char *pager_program;
+ extern const char *pager_program;
  extern int pager_in_use(void);
  extern int pager_use_color;
  
- extern char *editor_program;
- extern char *excludes_file;
+ extern const char *editor_program;
+ extern const char *excludes_file;
  
  /* base85 */
  int decode_85(char *dst, const char *line, int linelen);
diff --combined config.c
index 3e72778e94267044780a180145eae0a6a229e3a3,b82907cb857c9f745a2afa7abe786ee0c7ae1ff8..ad47dc34f05c6cb7e8fb25a2975de487c2a484d3
+++ b/config.c
@@@ -309,6 -309,14 +309,14 @@@ int git_config_bool(const char *name, c
        return git_config_int(name, value) != 0;
  }
  
+ int git_config_string(const char **dest, const char *var, const char *value)
+ {
+       if (!value)
+               return config_error_nonbool(var);
+       *dest = xstrdup(value);
+       return 0;
+ }
  int git_default_config(const char *var, const char *value)
  {
        /* This needs a better name */
                return 0;
        }
  
-       if (!strcmp(var, "i18n.commitencoding")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               git_commit_encoding = xstrdup(value);
-               return 0;
-       }
-       if (!strcmp(var, "i18n.logoutputencoding")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               git_log_output_encoding = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp(var, "i18n.commitencoding"))
+               return git_config_string(&git_commit_encoding, var, value);
  
+       if (!strcmp(var, "i18n.logoutputencoding"))
+               return git_config_string(&git_log_output_encoding, var, value);
  
        if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
                pager_use_color = git_config_bool(var,value);
                return 0;
        }
  
-       if (!strcmp(var, "core.pager")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               pager_program = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp(var, "core.pager"))
+               return git_config_string(&pager_program, var, value);
  
-       if (!strcmp(var, "core.editor")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               editor_program = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp(var, "core.editor"))
+               return git_config_string(&editor_program, var, value);
  
-       if (!strcmp(var, "core.excludesfile")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               excludes_file = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp(var, "core.excludesfile"))
+               return git_config_string(&excludes_file, var, value);
  
        if (!strcmp(var, "core.whitespace")) {
                if (!value)
@@@ -498,9 -485,9 +485,9 @@@ const char *git_etc_gitconfig(void
                system_wide = ETC_GITCONFIG;
                if (!is_absolute_path(system_wide)) {
                        /* interpret path relative to exec-dir */
 -                      const char *exec_path = git_exec_path();
 -                      system_wide = prefix_path(exec_path, strlen(exec_path),
 -                                              system_wide);
 +                      struct strbuf d = STRBUF_INIT;
 +                      strbuf_addf(&d, "%s/%s", git_exec_path(), system_wide);
 +                      system_wide = strbuf_detach(&d, NULL);
                }
        }
        return system_wide;
diff --combined diff.c
index cd8bc4dcc32757dfed9374fa8769599a6a7857ad,39f6e21aa39db53b3d72cb221156b92267272033..41ec2ced78d7f0d8fe86eea0285b76f70843a3a8
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -57,7 -57,7 +57,7 @@@ static int parse_diff_color_slot(const 
  static struct ll_diff_driver {
        const char *name;
        struct ll_diff_driver *next;
-       char *cmd;
+       const char *cmd;
  } *user_diff, **user_diff_tail;
  
  /*
@@@ -86,10 -86,7 +86,7 @@@ static int parse_lldiff_command(const c
                user_diff_tail = &(drv->next);
        }
  
-       if (!value)
-               return error("%s: lacks value", var);
-       drv->cmd = strdup(value);
-       return 0;
+       return git_config_string(&(drv->cmd), var, value);
  }
  
  /*
@@@ -166,13 -163,8 +163,8 @@@ int git_diff_ui_config(const char *var
        if (!prefixcmp(var, "diff.")) {
                const char *ep = strrchr(var, '.');
  
-               if (ep != var + 4) {
-                       if (!strcmp(ep, ".command")) {
-                               if (!value)
-                                       return config_error_nonbool(var);
-                               return parse_lldiff_command(var, ep, value);
-                       }
-               }
+               if (ep != var + 4 && !strcmp(ep, ".command"))
+                       return parse_lldiff_command(var, ep, value);
        }
  
        return git_diff_basic_config(var, value);
@@@ -1021,6 -1013,7 +1013,7 @@@ static void checkdiff_consume(void *pri
        char *err;
  
        if (line[0] == '+') {
+               data->lineno++;
                data->status = check_and_emit_line(line + 1, len - 1,
                    data->ws_rule, NULL, NULL, NULL, NULL);
                if (!data->status)
                emit_line(set, reset, line, 1);
                (void)check_and_emit_line(line + 1, len - 1, data->ws_rule,
                    stdout, set, reset, ws);
-               data->lineno++;
        } else if (line[0] == ' ')
                data->lineno++;
        else if (line[0] == '@') {
                char *plus = strchr(line, '+');
                if (plus)
-                       data->lineno = strtol(plus, NULL, 10);
+                       data->lineno = strtol(plus, NULL, 10) - 1;
                else
                        die("invalid diff");
        }
@@@ -1520,22 -1512,17 +1512,22 @@@ static int reuse_worktree_file(const ch
        if (pos < 0)
                return 0;
        ce = active_cache[pos];
 -      if ((lstat(name, &st) < 0) ||
 -          !S_ISREG(st.st_mode) || /* careful! */
 -          ce_match_stat(ce, &st, 0) ||
 -          hashcmp(sha1, ce->sha1))
 +
 +      /*
 +       * This is not the sha1 we are looking for, or
 +       * unreusable because it is not a regular file.
 +       */
 +      if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
                return 0;
 -      /* we return 1 only when we can stat, it is a regular file,
 -       * stat information matches, and sha1 recorded in the cache
 -       * matches.  I.e. we know the file in the work tree really is
 -       * the same as the <name, sha1> pair.
 +
 +      /*
 +       * If ce matches the file in the work tree, we can reuse it.
         */
 -      return 1;
 +      if (ce_uptodate(ce) ||
 +          (!lstat(name, &st) && !ce_match_stat(ce, &st, 0)))
 +              return 1;
 +
 +      return 0;
  }
  
  static int populate_from_stdin(struct diff_filespec *s)