git-remote: match usage string with the manual pages
[gitweb.git] / read-cache.c
index 901064bf1ae72aacb583ff735058eec953475ae3..22a814311d2cfc032129b43f6da56706c7026b9c 100644 (file)
@@ -13,6 +13,7 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "revision.h"
+#include "blob.h"
 
 /* Index extensions.
  *
@@ -159,7 +160,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
        return 0;
 }
 
-static int is_empty_blob_sha1(const unsigned char *sha1)
+int is_empty_blob_sha1(const unsigned char *sha1)
 {
        static const unsigned char empty_blob_sha1[20] = {
                0xe6,0x9d,0xe2,0x9b,0xb2,0xd1,0xd6,0x43,0x4b,0x8b,
@@ -511,6 +512,14 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_
        return new;
 }
 
+static void record_intent_to_add(struct cache_entry *ce)
+{
+       unsigned char sha1[20];
+       if (write_sha1_file("", 0, blob_type, sha1))
+               die("cannot create an empty blob in the object database");
+       hashcpy(ce->sha1, sha1);
+}
+
 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
 {
        int size, namelen, was_same;
@@ -519,6 +528,9 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;
        int verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);
        int pretend = flags & ADD_CACHE_PRETEND;
+       int intent_only = flags & ADD_CACHE_INTENT;
+       int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
+                         (intent_only ? ADD_CACHE_NEW_ONLY : 0));
 
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
                return error("%s: can only add regular files, symbolic links or git-directories", path);
@@ -532,7 +544,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        ce = xcalloc(1, size);
        memcpy(ce->name, path, namelen);
        ce->ce_flags = namelen;
-       fill_stat_cache_info(ce, st);
+       if (!intent_only)
+               fill_stat_cache_info(ce, st);
 
        if (trust_executable_bit && has_symlinks)
                ce->ce_mode = create_ce_mode(st_mode);
@@ -555,8 +568,12 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                alias->ce_flags |= CE_ADDED;
                return 0;
        }
-       if (index_path(ce->sha1, path, st, 1))
-               return error("unable to index file %s", path);
+       if (!intent_only) {
+               if (index_path(ce->sha1, path, st, 1))
+                       return error("unable to index file %s", path);
+       } else
+               record_intent_to_add(ce);
+
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
        ce->ce_flags |= CE_ADDED;
@@ -569,7 +586,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 
        if (pretend)
                ;
-       else if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
+       else if (add_index_entry(istate, ce, add_option))
                return error("unable to add %s to index",path);
        if (verbose && !was_same)
                printf("add '%s'\n", path);
@@ -591,8 +608,10 @@ struct cache_entry *make_cache_entry(unsigned int mode,
        int size, len;
        struct cache_entry *ce;
 
-       if (!verify_path(path))
+       if (!verify_path(path)) {
+               error("Invalid path '%s'", path);
                return NULL;
+       }
 
        len = strlen(path);
        size = cache_entry_size(len);
@@ -848,13 +867,15 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
        int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
        int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
        int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
+       int new_only = option & ADD_CACHE_NEW_ONLY;
 
        cache_tree_invalidate_path(istate->cache_tree, ce->name);
        pos = index_name_pos(istate, ce->name, ce->ce_flags);
 
        /* existing match? Just replace it. */
        if (pos >= 0) {
-               replace_index_entry(istate, pos, ce);
+               if (!new_only)
+                       replace_index_entry(istate, pos, ce);
                return 0;
        }
        pos = -pos-1;
@@ -874,7 +895,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
        if (!ok_to_add)
                return -1;
        if (!verify_path(ce->name))
-               return -1;
+               return error("Invalid path '%s'", ce->name);
 
        if (!skip_df_check &&
            check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {
@@ -1248,6 +1269,11 @@ int read_index_from(struct index_state *istate, const char *path)
        die("index file corrupt");
 }
 
+int is_index_unborn(struct index_state *istate)
+{
+       return (!istate->cache_nr && !istate->alloc && !istate->timestamp);
+}
+
 int discard_index(struct index_state *istate)
 {
        istate->cache_nr = 0;
@@ -1446,9 +1472,8 @@ int write_index(const struct index_state *istate, int newfd)
 
        /* Write extension data here */
        if (istate->cache_tree) {
-               struct strbuf sb;
+               struct strbuf sb = STRBUF_INIT;
 
-               strbuf_init(&sb, 0);
                cache_tree_write(&sb, istate->cache_tree);
                err = write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sb.len) < 0
                        || ce_write(&c, newfd, sb.buf, sb.len) < 0;
@@ -1469,25 +1494,30 @@ int write_index(const struct index_state *istate, int newfd)
 int read_index_unmerged(struct index_state *istate)
 {
        int i;
-       struct cache_entry **dst;
-       struct cache_entry *last = NULL;
+       int unmerged = 0;
 
        read_index(istate);
-       dst = istate->cache;
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce = istate->cache[i];
-               if (ce_stage(ce)) {
-                       remove_name_hash(ce);
-                       if (last && !strcmp(ce->name, last->name))
-                               continue;
-                       cache_tree_invalidate_path(istate->cache_tree, ce->name);
-                       last = ce;
+               struct cache_entry *new_ce;
+               int size, len;
+
+               if (!ce_stage(ce))
                        continue;
-               }
-               *dst++ = ce;
+               unmerged = 1;
+               len = strlen(ce->name);
+               size = cache_entry_size(len);
+               new_ce = xcalloc(1, size);
+               hashcpy(new_ce->sha1, ce->sha1);
+               memcpy(new_ce->name, ce->name, len);
+               new_ce->ce_flags = create_ce_flags(len, 0);
+               new_ce->ce_mode = ce->ce_mode;
+               if (add_index_entry(istate, new_ce, 0))
+                       return error("%s: cannot drop to stage #0",
+                                    ce->name);
+               i = index_name_pos(istate, new_ce->name, len);
        }
-       istate->cache_nr = dst - istate->cache;
-       return !!last;
+       return unmerged;
 }
 
 struct update_callback_data
@@ -1545,3 +1575,30 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
        return !!data.add_errors;
 }
 
+/*
+ * Returns 1 if the path is an "other" path with respect to
+ * the index; that is, the path is not mentioned in the index at all,
+ * either as a file, a directory with some files in the index,
+ * or as an unmerged entry.
+ *
+ * We helpfully remove a trailing "/" from directories so that
+ * the output of read_directory can be used as-is.
+ */
+int index_name_is_other(const struct index_state *istate, const char *name,
+               int namelen)
+{
+       int pos;
+       if (namelen && name[namelen - 1] == '/')
+               namelen--;
+       pos = index_name_pos(istate, name, namelen);
+       if (0 <= pos)
+               return 0;       /* exact match */
+       pos = -pos - 1;
+       if (pos < istate->cache_nr) {
+               struct cache_entry *ce = istate->cache[pos];
+               if (ce_namelen(ce) == namelen &&
+                   !memcmp(ce->name, name, namelen))
+                       return 0; /* Yup, this one exists unmerged */
+       }
+       return 1;
+}