static void preload_index(struct index_state *index, const struct pathspec *pathspec) { int threads, i, work, offset; struct thread_data data[MAX_PARALLEL]; uint64_t start = getnanotime(); if (!core_preload_index) return; threads = index->cache_nr / THREAD_COST; if ((index->cache_nr > 1) && (threads < 2) && getenv("GIT_FORCE_PRELOAD_TEST")) threads = 2; if (threads < 2) return; if (threads > MAX_PARALLEL) threads = MAX_PARALLEL; offset = 0; work = DIV_ROUND_UP(index->cache_nr, threads); memset(&data, 0, sizeof(data)); for (i = 0; i < threads; i++) { struct thread_data *p = data+i; p->index = index; if (pathspec) copy_pathspec(&p->pathspec, pathspec); p->offset = offset; p->nr = work; offset += work; if (pthread_create(&p->pthread, NULL, preload_thread, p)) die("unable to create threaded lstat"); } for (i = 0; i < threads; i++) { struct thread_data *p = data+i; if (pthread_join(p->pthread, NULL)) die("unable to join threaded lstat"); } trace_performance_since(start, "preload index"); }
void refresh_fsmonitor(struct index_state *istate) { static int has_run_once = 0; struct strbuf query_result = STRBUF_INIT; int query_success = 0; size_t bol; /* beginning of line */ uint64_t last_update; char *buf; int i; if (!core_fsmonitor || has_run_once) return; has_run_once = 1; trace_printf_key(&trace_fsmonitor, "refresh fsmonitor"); /* * This could be racy so save the date/time now and query_fsmonitor * should be inclusive to ensure we don't miss potential changes. */ last_update = getnanotime(); /* * If we have a last update time, call query_fsmonitor for the set of * changes since that time, else assume everything is possibly dirty * and check it all. */ if (istate->fsmonitor_last_update) { query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION, istate->fsmonitor_last_update, &query_result); trace_performance_since(last_update, "fsmonitor process '%s'", core_fsmonitor); trace_printf_key(&trace_fsmonitor, "fsmonitor process '%s' returned %s", core_fsmonitor, query_success ? "success" : "failure"); } /* a fsmonitor process can return '/' to indicate all entries are invalid */ if (query_success && query_result.buf[0] != '/') { /* Mark all entries returned by the monitor as dirty */ buf = query_result.buf; bol = 0; for (i = 0; i < query_result.len; i++) { if (buf[i] != '\0') continue; fsmonitor_refresh_callback(istate, buf + bol); bol = i + 1; } if (bol < query_result.len) fsmonitor_refresh_callback(istate, buf + bol); } else { /* Mark all entries invalid */ for (i = 0; i < istate->cache_nr; i++) istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID; /* If we're going to check every file, ensure we save the results */ istate->cache_changed |= FSMONITOR_CHANGED; if (istate->untracked) istate->untracked->use_fsmonitor = 0; } strbuf_release(&query_result); /* Now that we've updated istate, save the last_update time */ istate->fsmonitor_last_update = last_update; }
int run_diff_files(struct rev_info *revs, unsigned int option) { int entries, i; int diff_unmerged_stage = revs->max_count; unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) ? CE_MATCH_RACY_IS_DIRTY : 0); uint64_t start = getnanotime(); struct index_state *istate = revs->diffopt.repo->index; diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/"); if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; entries = istate->cache_nr; for (i = 0; i < entries; i++) { unsigned int oldmode, newmode; struct cache_entry *ce = istate->cache[i]; int changed; unsigned dirty_submodule = 0; const struct object_id *old_oid, *new_oid; if (diff_can_quit_early(&revs->diffopt)) break; if (!ce_path_match(istate, ce, &revs->prune_data, NULL)) continue; if (ce_stage(ce)) { struct combine_diff_path *dpath; struct diff_filepair *pair; unsigned int wt_mode = 0; int num_compare_stages = 0; size_t path_len; struct stat st; path_len = ce_namelen(ce); dpath = xmalloc(combine_diff_path_size(5, path_len)); dpath->path = (char *) &(dpath->parent[5]); dpath->next = NULL; memcpy(dpath->path, ce->name, path_len); dpath->path[path_len] = '\0'; oidclr(&dpath->oid); memset(&(dpath->parent[0]), 0, sizeof(struct combine_diff_parent)*5); changed = check_removed(ce, &st); if (!changed) wt_mode = ce_mode_from_stat(ce, st.st_mode); else { if (changed < 0) { perror(ce->name); continue; } wt_mode = 0; } dpath->mode = wt_mode; while (i < entries) { struct cache_entry *nce = istate->cache[i]; int stage; if (strcmp(ce->name, nce->name)) break; /* Stage #2 (ours) is the first parent, * stage #3 (theirs) is the second. */ stage = ce_stage(nce); if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; oidcpy(&dpath->parent[stage - 2].oid, &nce->oid); dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode); dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; } /* diff against the proper unmerged stage */ if (stage == diff_unmerged_stage) ce = nce; i++; } /* * Compensate for loop update */ i--; if (revs->combine_merges && num_compare_stages == 2) { show_combined_diff(dpath, 2, revs->dense_combined_merges, revs); free(dpath); continue; } FREE_AND_NULL(dpath); /* * Show the diff for the 'ce' if we found the one * from the desired stage. */ pair = diff_unmerge(&revs->diffopt, ce->name); if (wt_mode) pair->two->mode = wt_mode; if (ce_stage(ce) != diff_unmerged_stage) continue; } if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; /* If CE_VALID is set, don't look at workdir for file removal */ if (ce->ce_flags & CE_VALID) { changed = 0; newmode = ce->ce_mode; } else { struct stat st; changed = check_removed(ce, &st); if (changed) { if (changed < 0) { perror(ce->name); continue; } diff_addremove(&revs->diffopt, '-', ce->ce_mode, &ce->oid, !is_null_oid(&ce->oid), ce->name, 0); continue; } else if (revs->diffopt.ita_invisible_in_index && ce_intent_to_add(ce)) { diff_addremove(&revs->diffopt, '+', ce->ce_mode, the_hash_algo->empty_tree, 0, ce->name, 0); continue; } changed = match_stat_with_submodule(&revs->diffopt, ce, &st, ce_option, &dirty_submodule); newmode = ce_mode_from_stat(ce, st.st_mode); } if (!changed && !dirty_submodule) { ce_mark_uptodate(ce); mark_fsmonitor_valid(ce); if (!revs->diffopt.flags.find_copies_harder) continue; } oldmode = ce->ce_mode; old_oid = &ce->oid; new_oid = changed ? &null_oid : &ce->oid; diff_change(&revs->diffopt, oldmode, newmode, old_oid, new_oid, !is_null_oid(old_oid), !is_null_oid(new_oid), ce->name, 0, dirty_submodule); } diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); trace_performance_since(start, "diff-files"); return 0; }