+static int check_local_mod(unsigned char *head)
+{
+ /* items in list are already sorted in the cache order,
+ * so we could do this a lot more efficiently by using
+ * tree_desc based traversal if we wanted to, but I am
+ * lazy, and who cares if removal of files is a tad
+ * slower than the theoretical maximum speed?
+ */
+ int i, no_head;
+ int errs = 0;
+
+ no_head = is_null_sha1(head);
+ for (i = 0; i < list.nr; i++) {
+ struct stat st;
+ int pos;
+ struct cache_entry *ce;
+ const char *name = list.name[i];
+ unsigned char sha1[20];
+ unsigned mode;
+
+ pos = cache_name_pos(name, strlen(name));
+ if (pos < 0)
+ continue; /* removing unmerged entry */
+ ce = active_cache[pos];
+
+ if (lstat(ce->name, &st) < 0) {
+ if (errno != ENOENT)
+ fprintf(stderr, "warning: '%s': %s",
+ ce->name, strerror(errno));
+ /* It already vanished from the working tree */
+ continue;
+ }
+ else if (S_ISDIR(st.st_mode)) {
+ /* if a file was removed and it is now a
+ * directory, that is the same as ENOENT as
+ * far as git is concerned; we do not track
+ * directories.
+ */
+ continue;
+ }
+ if (ce_match_stat(ce, &st, 0))
+ errs = error("'%s' has local modifications "
+ "(hint: try -f)", ce->name);
+ if (no_head)
+ continue;
+ /*
+ * It is Ok to remove a newly added path, as long as
+ * it is cache-clean.
+ */
+ if (get_tree_entry(head, name, sha1, &mode))
+ continue;
+ /*
+ * Otherwise make sure the version from the HEAD
+ * matches the index.
+ */
+ if (ce->ce_mode != create_ce_mode(mode) ||
+ hashcmp(ce->sha1, sha1))
+ errs = error("'%s' has changes staged in the index "
+ "(hint: try -f)", name);
+ }
+ return errs;
+}
+