X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=read-cache.c;h=928e8fa1aee22a0a79c57ca675576d4998503ea9;hb=8391c60b6e08604e7023a8fff74350d6b35974af;hp=d9f46da5cc547d8cfaa34c901be50a13995b120e;hpb=cdd5b82ee8e6941eee9c7b09df63c44789fd5c4b;p=git.git diff --git a/read-cache.c b/read-cache.c index d9f46da5c..928e8fa1a 100644 --- a/read-cache.c +++ b/read-cache.c @@ -7,6 +7,7 @@ #include "cache.h" #include "cache-tree.h" #include "refs.h" +#include "dir.h" /* Index extensions. * @@ -92,7 +93,7 @@ static int ce_compare_gitlink(struct cache_entry *ce) /* * We don't actually require that the .git directory - * under DIRLNK directory be a valid git directory. It + * under GITLINK directory be a valid git directory. It * might even be missing (in case nobody populated that * sub-project). * @@ -115,7 +116,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st) return DATA_CHANGED; break; case S_IFDIR: - if (S_ISDIRLNK(ntohl(ce->ce_mode))) + if (S_ISGITLINK(ntohl(ce->ce_mode))) return 0; default: return TYPE_CHANGED; @@ -142,12 +143,14 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) (has_symlinks || !S_ISREG(st->st_mode))) changed |= TYPE_CHANGED; break; - case S_IFDIRLNK: + case S_IFGITLINK: if (!S_ISDIR(st->st_mode)) changed |= TYPE_CHANGED; else if (ce_compare_gitlink(ce)) changed |= DATA_CHANGED; return changed; + case 0: /* Special case: unmerged file in index */ + return MODE_CHANGED | DATA_CHANGED | TYPE_CHANGED; default: die("internal error: ce_mode is %o", ntohl(ce->ce_mode)); } @@ -166,7 +169,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) changed |= MTIME_CHANGED; if (ce->ce_ctime.nsec != htonl(st->st_ctim.tv_nsec)) changed |= CTIME_CHANGED; -#endif +#endif if (ce->ce_uid != htonl(st->st_uid) || ce->ce_gid != htonl(st->st_gid)) @@ -350,9 +353,37 @@ int remove_file_from_index(struct index_state *istate, const char *path) return 0; } +static int compare_name(struct cache_entry *ce, const char *path, int namelen) +{ + return namelen != ce_namelen(ce) || memcmp(path, ce->name, namelen); +} + +static int index_name_pos_also_unmerged(struct index_state *istate, + const char *path, int namelen) +{ + int pos = index_name_pos(istate, path, namelen); + struct cache_entry *ce; + + if (pos >= 0) + return pos; + + /* maybe unmerged? */ + pos = -1 - pos; + if (pos >= istate->cache_nr || + compare_name((ce = istate->cache[pos]), path, namelen)) + return -1; + + /* order of preference: stage 2, 1, 3 */ + if (ce_stage(ce) == 1 && pos + 1 < istate->cache_nr && + ce_stage((ce = istate->cache[pos + 1])) == 2 && + !compare_name(ce, path, namelen)) + pos++; + return pos; +} + int add_file_to_index(struct index_state *istate, const char *path, int verbose) { - int size, namelen; + int size, namelen, pos; struct stat st; struct cache_entry *ce; @@ -380,12 +411,21 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose) * from it, otherwise assume unexecutable regular file. */ struct cache_entry *ent; - int pos = index_name_pos(istate, path, namelen); + int pos = index_name_pos_also_unmerged(istate, path, namelen); ent = (0 <= pos) ? istate->cache[pos] : NULL; ce->ce_mode = ce_mode_from_stat(ent, st.st_mode); } + pos = index_name_pos(istate, ce->name, namelen); + if (0 <= pos && + !ce_stage(istate->cache[pos]) && + !ie_modified(istate, istate->cache[pos], &st, 1)) { + /* Nothing changed, really */ + free(ce); + return 0; + } + if (index_path(ce->sha1, path, &st, 1)) die("unable to index file %s", path); if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE)) @@ -396,6 +436,31 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose) return 0; } +struct cache_entry *make_cache_entry(unsigned int mode, + const unsigned char *sha1, const char *path, int stage, + int refresh) +{ + int size, len; + struct cache_entry *ce; + + if (!verify_path(path)) + return NULL; + + len = strlen(path); + size = cache_entry_size(len); + ce = xcalloc(1, size); + + hashcpy(ce->sha1, sha1); + memcpy(ce->name, path, len); + ce->ce_flags = create_ce_flags(len, stage); + ce->ce_mode = create_ce_mode(mode); + + if (refresh) + return refresh_cache_entry(ce, 0); + + return ce; +} + int ce_same_name(struct cache_entry *a, struct cache_entry *b) { int len = ce_namelen(a); @@ -597,7 +662,7 @@ static int has_dir_name(struct index_state *istate, * is being added, or we already have path and path/file is being * added. Either one would result in a nonsense tree that has path * twice when git-write-tree tries to write it out. Prevent it. - * + * * If ok-to-replace is specified, we remove the conflicting entries * from the cache so the caller should recompute the insert position. * When this happens, we return non-zero. @@ -628,7 +693,7 @@ static int check_file_directory_conflict(struct index_state *istate, return retval + has_dir_name(istate, ce, pos, ok_to_replace); } -int add_index_entry(struct index_state *istate, struct cache_entry *ce, int option) +static int add_index_entry_with_check(struct index_state *istate, struct cache_entry *ce, int option) { int pos; int ok_to_add = option & ADD_CACHE_OK_TO_ADD; @@ -670,6 +735,22 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti pos = index_name_pos(istate, ce->name, ntohs(ce->ce_flags)); pos = -pos-1; } + return pos + 1; +} + +int add_index_entry(struct index_state *istate, struct cache_entry *ce, int option) +{ + int pos; + + if (option & ADD_CACHE_JUST_APPEND) + pos = istate->cache_nr; + else { + int ret; + ret = add_index_entry_with_check(istate, ce, option); + if (ret <= 0) + return ret; + pos = ret - 1; + } /* Make sure the array is big enough .. */ if (istate->cache_nr == istate->cache_alloc) { @@ -680,7 +761,7 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti /* Add it in.. */ istate->cache_nr++; - if (istate->cache_nr > pos) + if (istate->cache_nr > pos + 1) memmove(istate->cache + pos + 1, istate->cache + pos, (istate->cache_nr - pos - 1) * sizeof(ce)); @@ -745,7 +826,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, return updated; } -int refresh_index(struct index_state *istate, unsigned int flags) +int refresh_index(struct index_state *istate, unsigned int flags, const char **pathspec, char *seen) { int i; int has_errors = 0; @@ -771,6 +852,9 @@ int refresh_index(struct index_state *istate, unsigned int flags) continue; } + if (pathspec && !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen)) + continue; + new = refresh_cache_ent(istate, ce, really, &cache_errno); if (new == ce) continue; @@ -970,8 +1054,8 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) write_buffer_len = buffered; len -= partial; data = (char *) data + partial; - } - return 0; + } + return 0; } static int write_index_ext_header(SHA_CTX *context, int fd, @@ -1037,7 +1121,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) * size to zero here, then the object name recorded * in index is the 6-byte file but the cached stat information * becomes zero --- which would then match what we would - * obtain from the filesystem next time we stat("frotz"). + * obtain from the filesystem next time we stat("frotz"). * * However, the second update-index, before calling * this function, notices that the cached size is 6