return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
}
+int ce_path_match(const struct cache_entry *ce, const char **pathspec)
+{
+ const char *match, *name;
+ int len;
+
+ if (!pathspec)
+ return 1;
+
+ len = ce_namelen(ce);
+ name = ce->name;
+ while ((match = *pathspec++) != NULL) {
+ int matchlen = strlen(match);
+ if (matchlen > len)
+ continue;
+ if (memcmp(name, match, matchlen))
+ continue;
+ if (matchlen && name[matchlen-1] == '/')
+ return 1;
+ if (name[matchlen] == '/' || !name[matchlen])
+ return 1;
+ if (!matchlen)
+ return 1;
+ }
+ return 0;
+}
+
/*
* Do we have another file that has the beginning components being a
* proper superset of the name we're trying to add?
{
int retval = 0;
int len = ce_namelen(ce);
+ int stage = ce_stage(ce);
const char *name = ce->name;
while (pos < active_nr) {
break;
if (memcmp(name, p->name, len))
break;
+ if (ce_stage(p) != stage)
+ continue;
if (p->name[len] != '/')
continue;
-fprintf(stderr, "conflict: %s %s\n", ce->name, p->name);
retval = -1;
if (!ok_to_replace)
break;
static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace)
{
int retval = 0;
+ int stage = ce_stage(ce);
const char *name = ce->name;
const char *slash = name + ce_namelen(ce);
}
len = slash - name;
- pos = cache_name_pos(name, len);
+ pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage)));
if (pos >= 0) {
retval = -1;
if (ok_to_replace)
/*
* Trivial optimization: if we find an entry that
* already matches the sub-directory, then we know
- * we're ok, and we can exit
+ * we're ok, and we can exit.
*/
pos = -pos-1;
- if (pos < active_nr) {
+ while (pos < active_nr) {
struct cache_entry *p = active_cache[pos];
- if (ce_namelen(p) <= len)
- continue;
- if (p->name[len] != '/')
- continue;
- if (memcmp(p->name, name, len))
- continue;
- break;
+ if ((ce_namelen(p) <= len) ||
+ (p->name[len] != '/') ||
+ memcmp(p->name, name, len))
+ break; /* not our subdirectory */
+ if (ce_stage(p) == stage)
+ /* p is at the same stage as our entry, and
+ * is a subdirectory of what we are looking
+ * at, so we cannot have conflicts at our
+ * level or anything shorter.
+ */
+ return retval;
+ pos++;
}
}
return retval;
int pos;
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;
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
/* existing match? Just replace it */
if (!ok_to_add)
return -1;
- if (!ce_stage(ce) && check_file_directory_conflict(ce, pos, ok_to_replace)) {
+ if (!skip_df_check && check_file_directory_conflict(ce, pos, ok_to_replace)) {
if (!ok_to_replace)
return -1;
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
return (errno == ENOENT) ? 0 : error("open failed");
size = 0; // avoid gcc warning
- map = (void *)-1;
+ map = MAP_FAILED;
if (!fstat(fd, &st)) {
size = st.st_size;
errno = EINVAL;
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
close(fd);
- if (-1 == (int)(long)map)
+ if (map == MAP_FAILED)
return error("mmap failed");
hdr = map;
SHA1_Update(context, write_buffer, left);
}
+ /* Flush first if not enough space for SHA1 signature */
+ if (left + 20 > WRITE_BUFFER_SIZE) {
+ if (write(fd, write_buffer, left) != left)
+ return -1;
+ left = 0;
+ }
+
/* Append the SHA1 signature at the end */
SHA1_Final(write_buffer + left, context);
left += 20;