static const struct archiver **archivers;
static int nr_archivers;
static int alloc_archivers;
+static int remote_allow_unreachable;
void register_archiver(struct archiver *ar)
{
unsigned char sha1[20];
/* Remotes are only allowed to fetch actual refs */
- if (remote) {
+ if (remote && !remote_allow_unreachable) {
char *ref = NULL;
- const char *colon = strchr(name, ':');
- int refnamelen = colon ? colon - name : strlen(name);
+ const char *colon = strchrnul(name, ':');
+ int refnamelen = colon - name;
if (!dwim_ref(name, refnamelen, sha1, &ref))
die("no such ref: %.*s", refnamelen, name);
return argc;
}
+static int git_default_archive_config(const char *var, const char *value,
+ void *cb)
+{
+ if (!strcmp(var, "uploadarchive.allowunreachable"))
+ remote_allow_unreachable = git_config_bool(var, value);
+ return git_default_config(var, value, cb);
+}
+
int write_archive(int argc, const char **argv, const char *prefix,
int setup_prefix, const char *name_hint, int remote)
{
if (setup_prefix && prefix == NULL)
prefix = setup_git_directory_gently(&nongit);
- git_config(git_default_config, NULL);
+ git_config(git_default_archive_config, NULL);
init_tar_archiver();
init_zip_archiver();
return NULL;
pos = -pos-1;
- if (it->subtree_alloc <= it->subtree_nr) {
- it->subtree_alloc = alloc_nr(it->subtree_alloc);
- it->down = xrealloc(it->down, it->subtree_alloc *
- sizeof(*it->down));
- }
+ ALLOC_GROW(it->down, it->subtree_nr + 1, it->subtree_alloc);
it->subtree_nr++;
down = xmalloc(sizeof(*down) + pathlen + 1);
if (!it)
return;
- slash = strchr(path, '/');
+ slash = strchrnul(path, '/');
+ namelen = slash - path;
it->entry_count = -1;
- if (!slash) {
+ if (!*slash) {
int pos;
- namelen = strlen(path);
pos = subtree_pos(it, path, namelen);
if (0 <= pos) {
cache_tree_free(&it->down[pos]->cache_tree);
}
return;
}
- namelen = slash - path;
down = find_subtree(it, path, namelen, 0);
if (down)
cache_tree_invalidate_path(down->cache_tree, slash + 1);
struct cache_tree_sub *sub;
slash = strchrnul(path, '/');
- /* between path and slash is the name of the
- * subtree to look for.
+ /*
+ * Between path and slash is the name of the subtree
+ * to look for.
*/
sub = find_subtree(it, path, slash - path, 0);
if (!sub)
return NULL;
it = sub->cache_tree;
- if (*slash)
- while (*slash && *slash == '/')
- slash++;
- if (!*slash)
- return it; /* prefix ended with slashes */
+
path = slash;
+ while (*path == '/')
+ path++;
}
return it;
}
{
struct diffstat_file *x;
x = xcalloc(sizeof (*x), 1);
- if (diffstat->nr == diffstat->alloc) {
- diffstat->alloc = alloc_nr(diffstat->alloc);
- diffstat->files = xrealloc(diffstat->files,
- diffstat->alloc * sizeof(x));
- }
+ ALLOC_GROW(diffstat->files, diffstat->nr + 1, diffstat->alloc);
diffstat->files[diffstat->nr++] = x;
if (name_b) {
x->from_name = xstrdup(name_a);
remove_tempfile_installed = 1;
}
- if (!one->sha1_valid ||
- reuse_worktree_file(name, one->sha1, 1)) {
+ if (!S_ISGITLINK(one->mode) &&
+ (!one->sha1_valid ||
+ reuse_worktree_file(name, one->sha1, 1))) {
struct stat st;
if (lstat(name, &st) < 0) {
if (errno == ENOENT)
if (c != '-')
return 0;
arg++;
- eq = strchr(arg, '=');
- if (eq)
- len = eq - arg;
- else
- len = strlen(arg);
+ eq = strchrnul(arg, '=');
+ len = eq - arg;
if (!len || strncmp(arg, arg_long, len))
return 0;
- if (eq) {
+ if (*eq) {
int n;
char *end;
if (!isdigit(*++eq))
return 0;
}
-/* Used only by "diff-files" and "diff --no-index" */
-void handle_deprecated_show_diff_q(struct diff_options *opt)
-{
- warning("'diff -q' and 'diff-files -q' are deprecated.");
- warning("Use 'diff --diff-filter=d' instead to ignore deleted filepairs.");
- parse_diff_filter_opt("d", opt);
-}
-
static void enable_patch_output(int *fmt) {
*fmt &= ~DIFF_FORMAT_NO_OUTPUT;
*fmt |= DIFF_FORMAT_PATCH;
void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
{
- if (queue->alloc <= queue->nr) {
- queue->alloc = alloc_nr(queue->alloc);
- queue->queue = xrealloc(queue->queue,
- sizeof(dp) * queue->alloc);
- }
+ ALLOC_GROW(queue->queue, queue->nr + 1, queue->alloc);
queue->queue[queue->nr++] = dp;
}
return !memcmp(one->data, two->data, one->size);
}
+static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
+{
+ if (p->done_skip_stat_unmatch)
+ return p->skip_stat_unmatch_result;
+
+ p->done_skip_stat_unmatch = 1;
+ p->skip_stat_unmatch_result = 0;
+ /*
+ * 1. Entries that come from stat info dirtiness
+ * always have both sides (iow, not create/delete),
+ * one side of the object name is unknown, with
+ * the same mode and size. Keep the ones that
+ * do not match these criteria. They have real
+ * differences.
+ *
+ * 2. At this point, the file is known to be modified,
+ * with the same mode and size, and the object
+ * name of one side is unknown. Need to inspect
+ * the identical contents.
+ */
+ if (!DIFF_FILE_VALID(p->one) || /* (1) */
+ !DIFF_FILE_VALID(p->two) ||
+ (p->one->sha1_valid && p->two->sha1_valid) ||
+ (p->one->mode != p->two->mode) ||
+ diff_populate_filespec(p->one, 1) ||
+ diff_populate_filespec(p->two, 1) ||
+ (p->one->size != p->two->size) ||
+ !diff_filespec_is_identical(p->one, p->two)) /* (2) */
+ p->skip_stat_unmatch_result = 1;
+ return p->skip_stat_unmatch_result;
+}
+
static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
{
int i;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
- /*
- * 1. Entries that come from stat info dirtiness
- * always have both sides (iow, not create/delete),
- * one side of the object name is unknown, with
- * the same mode and size. Keep the ones that
- * do not match these criteria. They have real
- * differences.
- *
- * 2. At this point, the file is known to be modified,
- * with the same mode and size, and the object
- * name of one side is unknown. Need to inspect
- * the identical contents.
- */
- if (!DIFF_FILE_VALID(p->one) || /* (1) */
- !DIFF_FILE_VALID(p->two) ||
- (p->one->sha1_valid && p->two->sha1_valid) ||
- (p->one->mode != p->two->mode) ||
- diff_populate_filespec(p->one, 1) ||
- diff_populate_filespec(p->two, 1) ||
- (p->one->size != p->two->size) ||
- !diff_filespec_is_identical(p->one, p->two)) /* (2) */
+ if (diff_filespec_check_stat_unmatch(p))
diff_q(&outq, p);
else {
/*
unsigned old_dirty_submodule, unsigned new_dirty_submodule)
{
struct diff_filespec *one, *two;
+ struct diff_filepair *p;
if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
is_submodule_ignored(concatpath, options))
fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
one->dirty_submodule = old_dirty_submodule;
two->dirty_submodule = new_dirty_submodule;
+ p = diff_queue(&diff_queued_diff, one, two);
- diff_queue(&diff_queued_diff, one, two);
- if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
- DIFF_OPT_SET(options, HAS_CHANGES);
+ if (DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
+ return;
+
+ if (DIFF_OPT_TST(options, QUICK) && options->skip_stat_unmatch &&
+ !diff_filespec_check_stat_unmatch(p))
+ return;
+
+ DIFF_OPT_SET(options, HAS_CHANGES);
}
struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)