+static int verify_clean_subdirectory(const char *path, const char *action,
+ struct unpack_trees_options *o)
+{
+ /*
+ * we are about to extract "path"; we would not want to lose
+ * anything in the existing directory there.
+ */
+ int namelen;
+ int pos, i;
+ struct dir_struct d;
+ char *pathbuf;
+ int cnt = 0;
+
+ /*
+ * First let's make sure we do not have a local modification
+ * in that directory.
+ */
+ namelen = strlen(path);
+ pos = cache_name_pos(path, namelen);
+ if (0 <= pos)
+ return cnt; /* we have it as nondirectory */
+ pos = -pos - 1;
+ for (i = pos; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ int len = ce_namelen(ce);
+ if (len < namelen ||
+ strncmp(path, ce->name, namelen) ||
+ ce->name[namelen] != '/')
+ break;
+ /*
+ * ce->name is an entry in the subdirectory.
+ */
+ if (!ce_stage(ce)) {
+ verify_uptodate(ce, o);
+ ce->ce_mode = 0;
+ }
+ cnt++;
+ }
+
+ /*
+ * Then we need to make sure that we do not lose a locally
+ * present file that is not ignored.
+ */
+ pathbuf = xmalloc(namelen + 2);
+ memcpy(pathbuf, path, namelen);
+ strcpy(pathbuf+namelen, "/");
+
+ memset(&d, 0, sizeof(d));
+ if (o->dir)
+ d.exclude_per_dir = o->dir->exclude_per_dir;
+ i = read_directory(&d, path, pathbuf, namelen+1, NULL);
+ if (i)
+ die("Updating '%s' would lose untracked files in it",
+ path);
+ free(pathbuf);
+ return cnt;
+}
+