void wt_status_collect_changes_worktree(struct index_state *index, GList **results, const char *worktree) { DiffEntry *de; int entries, i; GList *ignore_list = seaf_repo_load_ignore_files (worktree); entries = index->cache_nr; for (i = 0; i < entries; i++) { char *realpath; SeafStat st; struct cache_entry *ce = index->cache[i]; int changed = 0; if (ce_stage(ce)) { int mask = 0; mask |= 1 << ce_stage(ce); while (i < entries) { struct cache_entry *nce = index->cache[i]; if (strcmp(ce->name, nce->name)) break; mask |= 1 << ce_stage(nce); i++; } /* * Compensate for loop update */ i--; de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_UNMERGED, ce->sha1, ce->name); de->unmerge_state = diff_unmerged_state (mask); *results = g_list_prepend (*results, de); continue; } if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; realpath = g_build_path (PATH_SEPERATOR, worktree, ce->name, NULL); if (seaf_stat(realpath, &st) < 0) { if (errno != ENOENT && errno != ENOTDIR) changed = -1; else changed = 1; } if (changed) { if (changed < 0) { g_warning ("Faile to stat %s: %s\n", ce->name, strerror(errno)); g_free (realpath); continue; } if (ce->ce_ctime.sec == 0) { g_free (realpath); continue; } de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DELETED, ce->sha1, ce->name); *results = g_list_prepend (*results, de); g_free (realpath); continue; } if (S_ISDIR (ce->ce_mode)) { g_free (realpath); continue; } /* Don't check changes to ignored files. * This can happen when a file is committed and then added to * ignore.txt. After that changes to this file will not committed, * and it should be ignored here. */ if (seaf_repo_check_ignore_file (ignore_list, realpath)) { g_free (realpath); continue; } g_free (realpath); changed = ie_match_stat (index, ce, &st, 0); if (!changed) { ce_mark_uptodate (ce); continue; } de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_MODIFIED, ce->sha1, ce->name); *results = g_list_prepend (*results, de); } seaf_repo_free_ignore_files (ignore_list); }
void wt_status_collect_changes_worktree(struct index_state *index, GList **results, const char *worktree, IgnoreFunc ignore_func) { DiffEntry *de; int entries, i; entries = index->cache_nr; for (i = 0; i < entries; i++) { char *realpath; struct stat st; struct cache_entry *ce = index->cache[i]; int changed = 0; if (ce_stage(ce)) { int mask = 0; mask |= 1 << ce_stage(ce); while (i < entries) { struct cache_entry *nce = index->cache[i]; if (strcmp(ce->name, nce->name)) break; mask |= 1 << ce_stage(nce); i++; } /* * Compensate for loop update */ i--; de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_UNMERGED, ce->sha1, ce->name); de->unmerge_state = diff_unmerged_state (mask); *results = g_list_prepend (*results, de); continue; } if (ce_uptodate(ce) || ce_skip_worktree(ce)) continue; realpath = g_build_path (PATH_SEPERATOR, worktree, ce->name, NULL); if (g_lstat(realpath, &st) < 0) { if (errno != ENOENT && errno != ENOTDIR) changed = -1; changed = 1; } if (changed) { if (changed < 0) { g_warning ("Faile to stat %s: %s\n", ce->name, strerror(errno)); g_free (realpath); continue; } de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DELETED, ce->sha1, ce->name); *results = g_list_prepend (*results, de); g_free (realpath); continue; } if (S_ISDIR (ce->ce_mode)) { if (!S_ISDIR (st.st_mode) || !is_empty_dir (realpath, ignore_func)) { de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_DIR_DELETED, ce->sha1, ce->name); *results = g_list_prepend (*results, de); } g_free (realpath); continue; } g_free (realpath); changed = ie_match_stat (index, ce, &st, 0); if (!changed) { ce_mark_uptodate (ce); continue; } de = diff_entry_new (DIFF_TYPE_WORKTREE, DIFF_STATUS_MODIFIED, ce->sha1, ce->name); *results = g_list_prepend (*results, de); } }