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))
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;
* 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))
* 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.
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;
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) {
/* 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));
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,
* 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