expose a helper function peel_to_type().
[gitweb.git] / builtin-update-index.c
index 509369e9e7b1719e53ba2dd2d976066fb9513353..a8795d3d5fea9f340dfe21a71190f120c63856cd 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
-#include "strbuf.h"
 #include "quote.h"
 #include "cache-tree.h"
 #include "tree-walk.h"
@@ -48,10 +47,10 @@ static int mark_valid(const char *path)
        if (0 <= pos) {
                switch (mark_valid_only) {
                case MARK_VALID:
-                       active_cache[pos]->ce_flags |= htons(CE_VALID);
+                       active_cache[pos]->ce_flags |= CE_VALID;
                        break;
                case UNMARK_VALID:
-                       active_cache[pos]->ce_flags &= ~htons(CE_VALID);
+                       active_cache[pos]->ce_flags &= ~CE_VALID;
                        break;
                }
                cache_tree_invalidate_path(active_cache_tree, path);
@@ -86,11 +85,17 @@ static int process_lstat_error(const char *path, int err)
 
 static int add_one_path(struct cache_entry *old, const char *path, int len, struct stat *st)
 {
-       int option, size = cache_entry_size(len);
-       struct cache_entry *ce = xcalloc(1, size);
+       int option, size;
+       struct cache_entry *ce;
+
+       /* Was the old index entry already up-to-date? */
+       if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
+               return 0;
 
+       size = cache_entry_size(len);
+       ce = xcalloc(1, size);
        memcpy(ce->name, path, len);
-       ce->ce_flags = htons(len);
+       ce->ce_flags = len;
        fill_stat_cache_info(ce, st);
        ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
 
@@ -134,7 +139,7 @@ static int process_directory(const char *path, int len, struct stat *st)
        /* Exact match: file or existing gitlink */
        if (pos >= 0) {
                struct cache_entry *ce = active_cache[pos];
-               if (S_ISGITLINK(ntohl(ce->ce_mode))) {
+               if (S_ISGITLINK(ce->ce_mode)) {
 
                        /* Do nothing to the index if there is no HEAD! */
                        if (resolve_gitlink_ref(path, "HEAD", sha1) < 0)
@@ -178,7 +183,7 @@ static int process_file(const char *path, int len, struct stat *st)
        int pos = cache_name_pos(path, len);
        struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos];
 
-       if (ce && S_ISGITLINK(ntohl(ce->ce_mode)))
+       if (ce && S_ISGITLINK(ce->ce_mode))
                return error("%s is already a gitlink, not replacing", path);
 
        return add_one_path(ce, path, len, st);
@@ -189,11 +194,6 @@ static int process_path(const char *path)
        int len;
        struct stat st;
 
-       /* We probably want to do this in remove_file_from_cache() and
-        * add_cache_entry() instead...
-        */
-       cache_tree_invalidate_path(active_cache_tree, path);
-
        /*
         * First things first: get the stat information, to decide
         * what to do about the pathname!
@@ -226,14 +226,13 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
        ce->ce_flags = create_ce_flags(len, stage);
        ce->ce_mode = create_ce_mode(mode);
        if (assume_unchanged)
-               ce->ce_flags |= htons(CE_VALID);
+               ce->ce_flags |= CE_VALID;
        option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
        option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
        if (add_cache_entry(ce, option))
                return error("%s: cannot add to the index - missing --add option?",
                             path);
        report("add '%s'", path);
-       cache_tree_invalidate_path(active_cache_tree, path);
        return 0;
 }
 
@@ -247,14 +246,14 @@ static void chmod_path(int flip, const char *path)
        if (pos < 0)
                goto fail;
        ce = active_cache[pos];
-       mode = ntohl(ce->ce_mode);
+       mode = ce->ce_mode;
        if (!S_ISREG(mode))
                goto fail;
        switch (flip) {
        case '+':
-               ce->ce_mode |= htonl(0111); break;
+               ce->ce_mode |= 0111; break;
        case '-':
-               ce->ce_mode &= htonl(~0111); break;
+               ce->ce_mode &= ~0111; break;
        default:
                goto fail;
        }
@@ -278,7 +277,6 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
                        die("Unable to mark file %s", path);
                goto free_return;
        }
-       cache_tree_invalidate_path(active_cache_tree, path);
 
        if (force_remove) {
                if (remove_file_from_cache(p))
@@ -297,8 +295,11 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
 static void read_index_info(int line_termination)
 {
        struct strbuf buf;
-       strbuf_init(&buf);
-       while (1) {
+       struct strbuf uq;
+
+       strbuf_init(&buf, 0);
+       strbuf_init(&uq, 0);
+       while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
                char *ptr, *tab;
                char *path_name;
                unsigned char sha1[20];
@@ -322,10 +323,6 @@ static void read_index_info(int line_termination)
                 * This format is to put higher order stages into the
                 * index file and matches git-ls-files --stage output.
                 */
-               read_line(&buf, stdin, line_termination);
-               if (buf.eof)
-                       break;
-
                errno = 0;
                ul = strtoul(buf.buf, &ptr, 8);
                if (ptr == buf.buf || *ptr != ' '
@@ -350,18 +347,19 @@ static void read_index_info(int line_termination)
                if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
                        goto bad_line;
 
-               if (line_termination && ptr[0] == '"')
-                       path_name = unquote_c_style(ptr, NULL);
-               else
-                       path_name = ptr;
+               path_name = ptr;
+               if (line_termination && path_name[0] == '"') {
+                       strbuf_reset(&uq);
+                       if (unquote_c_style(&uq, path_name, NULL)) {
+                               die("git-update-index: bad quoting of path name");
+                       }
+                       path_name = uq.buf;
+               }
 
                if (!verify_path(path_name)) {
                        fprintf(stderr, "Ignoring path %s\n", path_name);
-                       if (path_name != ptr)
-                               free(path_name);
                        continue;
                }
-               cache_tree_invalidate_path(active_cache_tree, path_name);
 
                if (!mode) {
                        /* mode == 0 means there is no such path -- remove */
@@ -379,13 +377,13 @@ static void read_index_info(int line_termination)
                                die("git-update-index: unable to update %s",
                                    path_name);
                }
-               if (path_name != ptr)
-                       free(path_name);
                continue;
 
        bad_line:
                die("malformed index info %s", buf.buf);
        }
+       strbuf_release(&buf);
+       strbuf_release(&uq);
 }
 
 static const char update_index_usage[] =
@@ -468,7 +466,6 @@ static int unresolve_one(const char *path)
                goto free_return;
        }
 
-       cache_tree_invalidate_path(active_cache_tree, path);
        remove_file_from_cache(path);
        if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
                error("%s: cannot add our version to the index.", path);
@@ -709,27 +706,27 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                        free((char*)p);
        }
        if (read_from_stdin) {
-               struct strbuf buf;
-               strbuf_init(&buf);
-               while (1) {
-                       char *path_name;
+               struct strbuf buf, nbuf;
+
+               strbuf_init(&buf, 0);
+               strbuf_init(&nbuf, 0);
+               while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
                        const char *p;
-                       read_line(&buf, stdin, line_termination);
-                       if (buf.eof)
-                               break;
-                       if (line_termination && buf.buf[0] == '"')
-                               path_name = unquote_c_style(buf.buf, NULL);
-                       else
-                               path_name = buf.buf;
-                       p = prefix_path(prefix, prefix_length, path_name);
+                       if (line_termination && buf.buf[0] == '"') {
+                               strbuf_reset(&nbuf);
+                               if (unquote_c_style(&nbuf, buf.buf, NULL))
+                                       die("line is badly quoted");
+                               strbuf_swap(&buf, &nbuf);
+                       }
+                       p = prefix_path(prefix, prefix_length, buf.buf);
                        update_one(p, NULL, 0);
                        if (set_executable_bit)
                                chmod_path(set_executable_bit, p);
-                       if (p < path_name || p > path_name + strlen(path_name))
-                               free((char*) p);
-                       if (path_name != buf.buf)
-                               free(path_name);
+                       if (p < buf.buf || p > buf.buf + buf.len)
+                               free((char *)p);
                }
+               strbuf_release(&nbuf);
+               strbuf_release(&buf);
        }
 
  finish:
@@ -741,7 +738,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                            get_index_file(), strerror(lock_error));
                }
                if (write_cache(newfd, active_cache, active_nr) ||
-                   close(newfd) || commit_locked_index(lock_file))
+                   commit_locked_index(lock_file))
                        die("Unable to write new index file");
        }