static int check_updates(struct unpack_trees_options *o) { unsigned cnt = 0, total = 0; struct progress *progress = NULL; struct index_state *index = &o->result; int i; int errs = 0; if (o->update && o->verbose_update) { for (total = cnt = 0; cnt < index->cache_nr; cnt++) { const struct cache_entry *ce = index->cache[cnt]; if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE)) total++; } progress = start_progress_delay(_("Checking out files"), total, 50, 1); cnt = 0; } if (o->update) git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result); for (i = 0; i < index->cache_nr; i++) { const struct cache_entry *ce = index->cache[i]; if (ce->ce_flags & CE_WT_REMOVE) { display_progress(progress, ++cnt); if (o->update && !o->dry_run) unlink_entry(ce); continue; } } remove_marked_cache_entries(&o->result); remove_scheduled_dirs(); for (i = 0; i < index->cache_nr; i++) { struct cache_entry *ce = index->cache[i]; if (ce->ce_flags & CE_UPDATE) { if (ce->ce_flags & CE_WT_REMOVE) die("BUG: both update and delete flags are set on %s", ce->name); display_progress(progress, ++cnt); ce->ce_flags &= ~CE_UPDATE; if (o->update && !o->dry_run) { errs |= checkout_entry(ce, &state, NULL); } } } stop_progress(&progress); if (o->update) git_attr_set_direction(GIT_ATTR_CHECKIN, NULL); return errs != 0; }
int update_worktree (struct unpack_trees_options *o, gboolean recover_merge, const char *conflict_head_id, const char *default_conflict_suffix, int *finished_entries) { struct index_state *result = &o->result; int i; struct cache_entry *ce; char *conflict_suffix = NULL; int errs = 0; GHashTable *conflict_hash, *no_conflict_hash; for (i = 0; i < result->cache_nr; ++i) { ce = result->cache[i]; if (ce->ce_flags & CE_WT_REMOVE) errs |= unlink_entry (ce, o); } conflict_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); no_conflict_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (i = 0; i < result->cache_nr; ++i) { ce = result->cache[i]; if (ce->ce_flags & CE_UPDATE) { if (conflict_head_id) { conflict_suffix = get_last_changer_of_file (conflict_head_id, ce->name); if (!conflict_suffix) conflict_suffix = g_strdup(default_conflict_suffix); } errs |= checkout_entry (ce, o, recover_merge, conflict_suffix, conflict_hash, no_conflict_hash); g_free (conflict_suffix); } if (finished_entries) *finished_entries = *finished_entries + 1; } g_hash_table_destroy (conflict_hash); g_hash_table_destroy (no_conflict_hash); if (errs != 0) return -1; return 0; }
static int checkout_stage(int stage, const struct cache_entry *ce, int pos, const struct checkout *state, int *nr_checkouts, int overlay_mode) { while (pos < active_nr && !strcmp(active_cache[pos]->name, ce->name)) { if (ce_stage(active_cache[pos]) == stage) return checkout_entry(active_cache[pos], state, NULL, nr_checkouts); pos++; } if (!overlay_mode) { unlink_entry(ce); return 0; } if (stage == 2) return error(_("path '%s' does not have our version"), ce->name); else return error(_("path '%s' does not have their version"), ce->name); }
int update_worktree (struct unpack_trees_options *o, gboolean recover_merge, const char *conflict_head_id, const char *default_conflict_suffix, int *finished_entries) { struct index_state *result = &o->result; int i; struct cache_entry *ce; char *conflict_suffix = NULL; int errs = 0; for (i = 0; i < result->cache_nr; ++i) { ce = result->cache[i]; if (ce->ce_flags & CE_WT_REMOVE) errs |= unlink_entry (ce, o); } for (i = 0; i < result->cache_nr; ++i) { ce = result->cache[i]; if (ce->ce_flags & CE_UPDATE) { if (conflict_head_id) { conflict_suffix = get_last_changer_of_file (conflict_head_id, ce->name); if (!conflict_suffix) conflict_suffix = g_strdup(default_conflict_suffix); } errs |= checkout_entry (ce, o, recover_merge, conflict_suffix); g_free (conflict_suffix); } if (finished_entries) *finished_entries = *finished_entries + 1; } return errs != 0; }
int main(int ac, char **av) { GError *error = NULL; GOptionContext *context = g_option_context_new("PATH [PATH] ..."); g_option_context_add_main_entries(context, entries, NULL); if (!g_option_context_parse(context, &ac, &av, &error)) { g_printerr("option parsing failed: %s\n", error->message); exit(EXIT_FAILURE); } if (!paths) { g_printerr("Please provide at least one path.\n"); exit(EXIT_FAILURE); } /* Megabytize the argument */ if (chunk) chunk <<= 20; FTS *fts = fts_open(paths, onefs ? FTS_XDEV : 0, NULL); FTSENT *e; while ((e = fts_read(fts))) { switch (e->fts_info) { case FTS_D: /* Directories are easiest, * only dealwith them after we cleaned them * We bail though, if we encounter directory in non-recursive mode */ if (!recursive) { g_printerr("Directory (%s) encountered " "in non-recursive mode.\n", e->fts_path); if (force) { /* We skip the sub-tree and continue to next file */ fts_set(fts, e, FTS_SKIP); } else { exit(EXIT_FAILURE); } } break; case FTS_DP: if (rmdir(e->fts_accpath) < 0) { g_printerr("Could not remove (%s) directory: %s\n", e->fts_path, strerror(errno)); if (!force) exit(EXIT_FAILURE); } break; case FTS_F: /* Handling regular files. We sleep when we have * many smalls with large cumulative size. * * We also try to chunk large files and truncate * before dropping the fd * * If we're not running in force mode we * will bail pretty much all the time. * * Otherwise we will keep doing everything. */ if (e->fts_statp->st_size > chunk && e->fts_statp->st_nlink <= 1) { /* Large file case. * We only do this for files * that are not hardlinked anywhere else. */ int fd = open(e->fts_accpath, O_RDWR); if (fd < 0) { g_printerr("Could not open (%s) for truncation: %s", e->fts_path, strerror(errno)); if (!force) exit(EXIT_FAILURE); break; } if (!unlink_entry(e)) break; off_t boundary = e->fts_statp->st_size; /* We don't care about sparseness of the * file and approach this as logical trim */ while (boundary >= chunk) { boundary -= chunk; if (ftruncate(fd, boundary) < 0) { g_printerr("Could not truncate (%s): %s\n", e->fts_path, strerror(errno)); if (!force) exit(EXIT_FAILURE); break; } else if (!nofsync) { fsync(fd); } dream(); } if (fd > -1) close(fd); } else { /* Small file case */ if (unlink_entry(e)) the_counter += e->fts_statp->st_size; } break; default: /* Everything else */ unlink_entry(e); } if (the_counter > chunk) { if (!nofsync) { int fd = open(".", O_DIRECTORY); fsync(fd); if (fd > -1) close(fd); } dream(); } } if (fts) fts_close(fts); return EXIT_SUCCESS; }