/* * Used to set up core.excludesfile and .git/info/exclude lists. */ void add_excludes_from_file(struct dir_struct *dir, const char *fname) { struct exclude_list *el; el = add_exclude_list(dir, EXC_FILE, fname); if (add_excludes_from_file_to_list(fname, "", 0, el, 0) < 0) die("cannot use %s as an exclude file", fname); }
static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) { struct exclude_list *el; struct exclude_stack *stk = NULL; int current; if ((!dir->exclude_per_dir) || (baselen + strlen(dir->exclude_per_dir) >= PATH_MAX)) return; /* too long a path -- ignore */ /* Pop the ones that are not the prefix of the path being checked. */ el = &dir->exclude_list[EXC_DIRS]; while ((stk = dir->exclude_stack) != NULL) { if (stk->baselen <= baselen && !strncmp(dir->basebuf, base, stk->baselen)) break; dir->exclude_stack = stk->prev; while (stk->exclude_ix < el->nr) free(el->excludes[--el->nr]); free(stk->filebuf); free(stk); } /* Read from the parent directories and push them down. */ current = stk ? stk->baselen : -1; while (current < baselen) { struct exclude_stack *stk = xcalloc(1, sizeof(*stk)); const char *cp; if (current < 0) { cp = base; current = 0; } else { cp = strchr(base + current + 1, '/'); if (!cp) die("oops in prep_exclude"); cp++; } stk->prev = dir->exclude_stack; stk->baselen = cp - base; stk->exclude_ix = el->nr; memcpy(dir->basebuf + current, base + current, stk->baselen - current); strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir); add_excludes_from_file_to_list(dir->basebuf, dir->basebuf, stk->baselen, &stk->filebuf, el, 1); dir->exclude_stack = stk; current = stk->baselen; } dir->basebuf[baselen] = '\0'; }
struct walker *get_http_walker(const char *url) { char *s; struct walker_data *data = xmalloc(sizeof(struct walker_data)); struct walker *walker = xmalloc(sizeof(struct walker)); data->alt = xmalloc(sizeof(*data->alt)); data->alt->base = xmalloc(strlen(url) + 1); strcpy(data->alt->base, url); for (s = data->alt->base + strlen(data->alt->base) - 1; *s == '/'; --s) *s = 0; data->alt->got_indices = 0; data->alt->packs = NULL; data->alt->next = NULL; data->got_alternates = -1; walker->corrupt_object_found = 0; walker->fetch = fetch; walker->fetch_ref = fetch_ref; walker->prefetch = prefetch; walker->cleanup = cleanup; walker->data = data; walker->skip_sparse_checkout = !core_apply_sparse_checkout; memset(&walker->exclude_list, 0, sizeof(walker->exclude_list)); if (!walker->skip_sparse_checkout) { if (add_excludes_from_file_to_list(git_path("info/sparse-checkout"), "", 0, &walker->exclude_list, 0) < 0) walker->skip_sparse_checkout = 1; } walker->sparse_checkout_list_count = 0; walker->sparse_checkout_list_size = 256; walker->sparse_checkout_list = !walker->skip_sparse_checkout ? xmalloc(walker->sparse_checkout_list_size * sizeof(unsigned char[20])) : NULL; #ifdef USE_CURL_MULTI add_fill_function(walker, (int (*)(void *)) fill_active_slot); #endif return walker; }
/* * N-way merge "len" trees. Returns 0 on success, -1 on failure to manipulate the * resulting index, -2 on failure to reflect the changes to the work tree. * * CE_ADDED, CE_UNPACKED and CE_NEW_SKIP_WORKTREE are used internally */ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) { int i, ret; static struct cache_entry *dfc; struct exclude_list el; if (len > MAX_UNPACK_TREES) die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES); memset(&state, 0, sizeof(state)); state.base_dir = ""; state.force = 1; state.quiet = 1; state.refresh_cache = 1; state.istate = &o->result; memset(&el, 0, sizeof(el)); if (!core_apply_sparse_checkout || !o->update) o->skip_sparse_checkout = 1; if (!o->skip_sparse_checkout) { char *sparse = git_pathdup("info/sparse-checkout"); if (add_excludes_from_file_to_list(sparse, "", 0, &el, 0) < 0) o->skip_sparse_checkout = 1; else o->el = ⪙ free(sparse); } memset(&o->result, 0, sizeof(o->result)); o->result.initialized = 1; o->result.timestamp.sec = o->src_index->timestamp.sec; o->result.timestamp.nsec = o->src_index->timestamp.nsec; o->result.version = o->src_index->version; o->result.split_index = o->src_index->split_index; if (o->result.split_index) o->result.split_index->refcount++; hashcpy(o->result.sha1, o->src_index->sha1); o->merge_size = len; mark_all_ce_unused(o->src_index); /* * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries */ if (!o->skip_sparse_checkout) mark_new_skip_worktree(o->el, o->src_index, 0, CE_NEW_SKIP_WORKTREE); if (!dfc) dfc = xcalloc(1, cache_entry_size(0)); o->df_conflict_entry = dfc; if (len) { const char *prefix = o->prefix ? o->prefix : ""; struct traverse_info info; setup_traverse_info(&info, prefix); info.fn = unpack_callback; info.data = o; info.show_all_errors = o->show_all_errors; info.pathspec = o->pathspec; if (o->prefix) { /* * Unpack existing index entries that sort before the * prefix the tree is spliced into. Note that o->merge * is always true in this case. */ while (1) { struct cache_entry *ce = next_cache_entry(o); if (!ce) break; if (ce_in_traverse_path(ce, &info)) break; if (unpack_index_entry(ce, o) < 0) goto return_failed; } } if (traverse_trees(len, t, &info) < 0) goto return_failed; } /* Any left-over entries in the index? */ if (o->merge) { while (1) { struct cache_entry *ce = next_cache_entry(o); if (!ce) break; if (unpack_index_entry(ce, o) < 0) goto return_failed; } } mark_all_ce_unused(o->src_index); if (o->trivial_merges_only && o->nontrivial_merge) { ret = unpack_failed(o, "Merge requires file-level merging"); goto done; } if (!o->skip_sparse_checkout) { int empty_worktree = 1; /* * Sparse checkout loop #2: set NEW_SKIP_WORKTREE on entries not in loop #1 * If the will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE * so apply_sparse_checkout() won't attempt to remove it from worktree */ mark_new_skip_worktree(o->el, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE); ret = 0; for (i = 0; i < o->result.cache_nr; i++) { struct cache_entry *ce = o->result.cache[i]; /* * Entries marked with CE_ADDED in merged_entry() do not have * verify_absent() check (the check is effectively disabled * because CE_NEW_SKIP_WORKTREE is set unconditionally). * * Do the real check now because we have had * correct CE_NEW_SKIP_WORKTREE */ if (ce->ce_flags & CE_ADDED && verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) { if (!o->show_all_errors) goto return_failed; ret = -1; } if (apply_sparse_checkout(&o->result, ce, o)) { if (!o->show_all_errors) goto return_failed; ret = -1; } if (!ce_skip_worktree(ce)) empty_worktree = 0; } if (ret < 0) goto return_failed; /* * Sparse checkout is meant to narrow down checkout area * but it does not make sense to narrow down to empty working * tree. This is usually a mistake in sparse checkout rules. * Do not allow users to do that. */ if (o->result.cache_nr && empty_worktree) { ret = unpack_failed(o, "Sparse checkout leaves no entry on working directory"); goto done; } } o->src_index = NULL; ret = check_updates(o) ? (-2) : 0; if (o->dst_index) { if (!ret) { if (!o->result.cache_tree) o->result.cache_tree = cache_tree(); if (!cache_tree_fully_valid(o->result.cache_tree)) cache_tree_update(&o->result, WRITE_TREE_SILENT | WRITE_TREE_REPAIR); } discard_index(o->dst_index); *o->dst_index = o->result; } else { discard_index(&o->result); } done: clear_exclude_list(&el); return ret; return_failed: if (o->show_all_errors) display_error_msgs(o); mark_all_ce_unused(o->src_index); ret = unpack_failed(o, NULL); if (o->exiting_early) ret = 0; goto done; }
void add_excludes_from_file(struct dir_struct *dir, const char *fname) { if (add_excludes_from_file_to_list(fname, "", 0, NULL, &dir->exclude_list[EXC_FILE], 0) < 0) die("cannot use %s as an exclude file", fname); }
/* * Loads the per-directory exclude list for the substring of base * which has a char length of baselen. */ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) { struct exclude_list_group *group; struct exclude_list *el; struct exclude_stack *stk = NULL; int current; group = &dir->exclude_list_group[EXC_DIRS]; /* Pop the exclude lists from the EXCL_DIRS exclude_list_group * which originate from directories not in the prefix of the * path being checked. */ while ((stk = dir->exclude_stack) != NULL) { if (stk->baselen <= baselen && !strncmp(dir->basebuf, base, stk->baselen)) break; el = &group->el[dir->exclude_stack->exclude_ix]; dir->exclude_stack = stk->prev; dir->exclude = NULL; free((char *)el->src); /* see strdup() below */ clear_exclude_list(el); free(stk); group->nr--; } /* Skip traversing into sub directories if the parent is excluded */ if (dir->exclude) return; /* Read from the parent directories and push them down. */ current = stk ? stk->baselen : -1; while (current < baselen) { struct exclude_stack *stk = xcalloc(1, sizeof(*stk)); const char *cp; if (current < 0) { cp = base; current = 0; } else { cp = strchr(base + current + 1, '/'); if (!cp) die("oops in prep_exclude"); cp++; } stk->prev = dir->exclude_stack; stk->baselen = cp - base; stk->exclude_ix = group->nr; el = add_exclude_list(dir, EXC_DIRS, NULL); memcpy(dir->basebuf + current, base + current, stk->baselen - current); /* Abort if the directory is excluded */ if (stk->baselen) { int dt = DT_DIR; dir->basebuf[stk->baselen - 1] = 0; dir->exclude = last_exclude_matching_from_lists(dir, dir->basebuf, stk->baselen - 1, dir->basebuf + current, &dt); dir->basebuf[stk->baselen - 1] = '/'; if (dir->exclude && dir->exclude->flags & EXC_FLAG_NEGATIVE) dir->exclude = NULL; if (dir->exclude) { dir->basebuf[stk->baselen] = 0; dir->exclude_stack = stk; return; } } /* Try to read per-directory file unless path is too long */ if (dir->exclude_per_dir && stk->baselen + strlen(dir->exclude_per_dir) < PATH_MAX) { strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir); /* * dir->basebuf gets reused by the traversal, but we * need fname to remain unchanged to ensure the src * member of each struct exclude correctly * back-references its source file. Other invocations * of add_exclude_list provide stable strings, so we * strdup() and free() here in the caller. */ el->src = strdup(dir->basebuf); add_excludes_from_file_to_list(dir->basebuf, dir->basebuf, stk->baselen, el, 1); } dir->exclude_stack = stk; current = stk->baselen; } dir->basebuf[baselen] = '\0'; }
/* * Loads the per-directory exclude list for the substring of base * which has a char length of baselen. */ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) { struct exclude_list_group *group; struct exclude_list *el; struct exclude_stack *stk = NULL; int current; group = &dir->exclude_list_group[EXC_DIRS]; /* * Pop the exclude lists from the EXCL_DIRS exclude_list_group * which originate from directories not in the prefix of the * path being checked. */ while ((stk = dir->exclude_stack) != NULL) { if (stk->baselen <= baselen && !strncmp(dir->basebuf.buf, base, stk->baselen)) break; el = &group->el[dir->exclude_stack->exclude_ix]; dir->exclude_stack = stk->prev; dir->exclude = NULL; free((char *)el->src); /* see strbuf_detach() below */ clear_exclude_list(el); free(stk); group->nr--; } /* Skip traversing into sub directories if the parent is excluded */ if (dir->exclude) return; /* * Lazy initialization. All call sites currently just * memset(dir, 0, sizeof(*dir)) before use. Changing all of * them seems lots of work for little benefit. */ if (!dir->basebuf.buf) strbuf_init(&dir->basebuf, PATH_MAX); /* Read from the parent directories and push them down. */ current = stk ? stk->baselen : -1; strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current); while (current < baselen) { const char *cp; stk = xcalloc(1, sizeof(*stk)); if (current < 0) { cp = base; current = 0; } else { cp = strchr(base + current + 1, '/'); if (!cp) die("oops in prep_exclude"); cp++; } stk->prev = dir->exclude_stack; stk->baselen = cp - base; stk->exclude_ix = group->nr; el = add_exclude_list(dir, EXC_DIRS, NULL); strbuf_add(&dir->basebuf, base + current, stk->baselen - current); assert(stk->baselen == dir->basebuf.len); /* Abort if the directory is excluded */ if (stk->baselen) { int dt = DT_DIR; dir->basebuf.buf[stk->baselen - 1] = 0; dir->exclude = last_exclude_matching_from_lists(dir, dir->basebuf.buf, stk->baselen - 1, dir->basebuf.buf + current, &dt); dir->basebuf.buf[stk->baselen - 1] = '/'; if (dir->exclude && dir->exclude->flags & EXC_FLAG_NEGATIVE) dir->exclude = NULL; if (dir->exclude) { dir->exclude_stack = stk; return; } } /* Try to read per-directory file */ if (dir->exclude_per_dir) { /* * dir->basebuf gets reused by the traversal, but we * need fname to remain unchanged to ensure the src * member of each struct exclude correctly * back-references its source file. Other invocations * of add_exclude_list provide stable strings, so we * strbuf_detach() and free() here in the caller. */ struct strbuf sb = STRBUF_INIT; strbuf_addbuf(&sb, &dir->basebuf); strbuf_addstr(&sb, dir->exclude_per_dir); el->src = strbuf_detach(&sb, NULL); add_excludes_from_file_to_list(el->src, el->src, stk->baselen, el, 1); } dir->exclude_stack = stk; current = stk->baselen; } strbuf_setlen(&dir->basebuf, baselen); }