while (low <= high) {
mid = (low + high) / 2;
- for (mid_up = mid; !flist->files[mid_up]->basename; mid_up++) {}
- if (mid_up <= high)
- ret = f_name_cmp(flist->files[mid_up], f);
- else
- ret = 1;
+ if (flist->files[mid]->basename)
+ mid_up = mid;
+ else {
+ /* Scan for the next non-empty entry using the cached
+ * distance values. If the value isn't fully up-to-
+ * date, update it. */
+ while (1) {
+ mid_up = mid + flist->files[mid]->dir.depth;
+ if (flist->files[mid_up]->basename)
+ break;
+ flist->files[mid]->dir.depth
+ += flist->files[mid_up]->dir.depth;
+ }
+ if (mid_up > high) {
+ /* If there's nothing left above us, set high to
+ * a non-empty entry below us and continue. */
+ while (1) {
+ high = mid - flist->files[mid]->length;
+ if (flist->files[high]->basename)
+ break;
+ flist->files[mid]->length
+ += flist->files[high]->length;
+ }
+ continue;
+ }
+ }
+ ret = f_name_cmp(flist->files[mid_up], f);
if (ret == 0) {
if (protocol_version < 29
&& S_ISDIR(flist->files[mid_up]->mode)
*/
void clear_file(int i, struct file_list *flist)
{
- if (flist->hlink_pool && flist->files[i]->link_u.idev)
- pool_free(flist->hlink_pool, 0, flist->files[i]->link_u.idev);
- memset(flist->files[i], 0, file_struct_len);
+ struct file_struct *file = flist->files[i];
+ if (flist->hlink_pool && file->link_u.idev)
+ pool_free(flist->hlink_pool, 0, file->link_u.idev);
+ memset(file, 0, file_struct_len);
+ /* In an empty entry, dir.depth is an offset to the next non-empty
+ * entry. Likewise for length in the opposite direction. We assume
+ * that we're alone for now since flist_find() will collate adjacent
+ * items for any entries that are encountered during the find. */
+ file->length = file->dir.depth = 1;
}
/*
if (!file->basename)
continue;
-
- if (strip_root && file->dirname) {
- /* We need to strip off the leading slashes for
- * relative paths, but this must be done _after_
- * the sorting phase (above). */
- if (*file->dirname == '/') {
- char *s = file->dirname + 1;
- while (*s == '/') s++;
- memmove(file->dirname, s, strlen(s) + 1);
- }
- if (!*file->dirname)
- file->dirname = NULL;
- }
-
if (f_name_cmp(file, flist->files[prev_i]) == 0)
j = prev_i;
else if (protocol_version >= 29 && S_ISDIR(file->mode)) {
file->mode = save_mode;
} else
j = -1;
-
if (j >= 0) {
struct file_struct *fp = flist->files[j];
int keep, drop;
}
flist->high = no_dups ? prev_i : flist->count - 1;
+ if (strip_root) {
+ /* We need to strip off the leading slashes for relative
+ * paths, but this must be done _after_ the sorting phase. */
+ for (i = flist->low; i <= flist->high; i++) {
+ struct file_struct *file = flist->files[i];
+
+ if (!file->dirname)
+ continue;
+ while (*file->dirname == '/')
+ file->dirname++;
+ if (!*file->dirname)
+ file->dirname = NULL;
+ }
+ }
+
if (skip_empty_dirs && no_dups && max_dir_depth) {
int j, cur_depth = 0;
int *maybe_dirs = new_array(int, max_dir_depth);