Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
e568e563ad | |||
c638f3e4d5 | |||
765428699a | |||
32c6dca8c4 | |||
2824e1841b | |||
dc06dc8800 | |||
f3badaed51 | |||
8eee9f9277 | |||
c6bd2a1dec | |||
d770187872 | |||
935de81289 | |||
24358560c3 | |||
11a458befc | |||
a2558fb8e1 | |||
6343e2f6f2 | |||
18b58f707f | |||
92cdfd2131 | |||
83c4d38017 | |||
dcd1742e56 | |||
3efb988098 | |||
f2df3104ce | |||
df37727a65 | |||
b258116462 | |||
f4113cac0c | |||
5088d3b387 | |||
33cfccbbf3 | |||
a5adaced2e | |||
ee6ad5f4d5 | |||
8833ccd7d0 | |||
d6579d9436 | |||
cfc3e0ee4a | |||
02dad2673b | |||
b9d66899a9 | |||
b80fa842ed | |||
486e1e1223 | |||
73f9145fbf | |||
2e5910f276 | |||
f178136e68 | |||
7687252f3f |
18
Documentation/RelNotes/2.3.10.txt
Normal file
18
Documentation/RelNotes/2.3.10.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Git v2.3.10 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v2.3.9
|
||||
------------------
|
||||
|
||||
* xdiff code we use to generate diffs is not prepared to handle
|
||||
extremely large files. It uses "int" in many places, which can
|
||||
overflow if we have a very large number of lines or even bytes in
|
||||
our input files, for example. Cap the input size to soemwhere
|
||||
around 1GB for now.
|
||||
|
||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||
found in the URL. The URLs that submodules use may come from
|
||||
arbitrary sources (e.g., .gitmodules files in a remote
|
||||
repository), and can hurt those who blindly enable recursive
|
||||
fetch. Restrict the allowed protocols to well known and safe
|
||||
ones.
|
18
Documentation/RelNotes/2.4.10.txt
Normal file
18
Documentation/RelNotes/2.4.10.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Git v2.4.10 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v2.4.9
|
||||
------------------
|
||||
|
||||
* xdiff code we use to generate diffs is not prepared to handle
|
||||
extremely large files. It uses "int" in many places, which can
|
||||
overflow if we have a very large number of lines or even bytes in
|
||||
our input files, for example. Cap the input size to soemwhere
|
||||
around 1GB for now.
|
||||
|
||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||
found in the URL. The URLs that submodules use may come from
|
||||
arbitrary sources (e.g., .gitmodules files in a remote
|
||||
repository), and can hurt those who blindly enable recursive
|
||||
fetch. Restrict the allowed protocols to well known and safe
|
||||
ones.
|
11
Documentation/RelNotes/2.4.11.txt
Normal file
11
Documentation/RelNotes/2.4.11.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Git v2.4.11 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v2.4.10
|
||||
-------------------
|
||||
|
||||
* Bugfix patches were backported from the 'master' front to plug heap
|
||||
corruption holes, to catch integer overflow in the computation of
|
||||
pathname lengths, and to get rid of the name_path API. Both of
|
||||
these would have resulted in writing over an under-allocated buffer
|
||||
when formulating pathnames while tree traversal.
|
17
Documentation/RelNotes/2.5.3.txt
Normal file
17
Documentation/RelNotes/2.5.3.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Git v2.5.3 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.5.2
|
||||
------------------
|
||||
|
||||
* The experimental untracked-cache feature were buggy when paths with
|
||||
a few levels of subdirectories are involved.
|
||||
|
||||
* Recent versions of scripted "git am" has a performance regression
|
||||
in "git am --skip" codepath, which no longer exists in the
|
||||
built-in version on the 'master' front. Fix the regression in
|
||||
the last scripted version that appear in 2.5.x maintenance track
|
||||
and older.
|
||||
|
||||
Also contains typofixes, documentation updates and trivial code
|
||||
clean-ups.
|
18
Documentation/RelNotes/2.5.4.txt
Normal file
18
Documentation/RelNotes/2.5.4.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Git v2.5.4 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.5.4
|
||||
------------------
|
||||
|
||||
* xdiff code we use to generate diffs is not prepared to handle
|
||||
extremely large files. It uses "int" in many places, which can
|
||||
overflow if we have a very large number of lines or even bytes in
|
||||
our input files, for example. Cap the input size to soemwhere
|
||||
around 1GB for now.
|
||||
|
||||
* Some protocols (like git-remote-ext) can execute arbitrary code
|
||||
found in the URL. The URLs that submodules use may come from
|
||||
arbitrary sources (e.g., .gitmodules files in a remote
|
||||
repository), and can hurt those who blindly enable recursive
|
||||
fetch. Restrict the allowed protocols to well known and safe
|
||||
ones.
|
11
Documentation/RelNotes/2.5.5.txt
Normal file
11
Documentation/RelNotes/2.5.5.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Git v2.5.5 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.5.4
|
||||
------------------
|
||||
|
||||
* Bugfix patches were backported from the 'master' front to plug heap
|
||||
corruption holes, to catch integer overflow in the computation of
|
||||
pathname lengths, and to get rid of the name_path API. Both of
|
||||
these would have resulted in writing over an under-allocated buffer
|
||||
when formulating pathnames while tree traversal.
|
@ -174,6 +174,9 @@ Skip "branches" and "tags" of first level directories;;
|
||||
(including automatic fetches due to 'clone', 'dcommit',
|
||||
'rebase', etc) on a given repository. '--ignore-paths' takes
|
||||
precedence over '--include-paths'.
|
||||
+
|
||||
[verse]
|
||||
config key: svn-remote.<name>.include-paths
|
||||
|
||||
--log-window-size=<n>;;
|
||||
Fetch <n> log entries per request when scanning Subversion history.
|
||||
|
@ -43,16 +43,21 @@ unreleased) version of Git, that is available from the 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v2.5.2/git.html[documentation for release 2.5.2]
|
||||
* link:v2.5.5/git.html[documentation for release 2.5.5]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.5.5.txt[2.5.5],
|
||||
link:RelNotes/2.5.4.txt[2.5.4],
|
||||
link:RelNotes/2.5.3.txt[2.5.3],
|
||||
link:RelNotes/2.5.2.txt[2.5.2],
|
||||
link:RelNotes/2.5.1.txt[2.5.1],
|
||||
link:RelNotes/2.5.0.txt[2.5].
|
||||
|
||||
* link:v2.4.9/git.html[documentation for release 2.4.9]
|
||||
* link:v2.4.11/git.html[documentation for release 2.4.11]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.4.11.txt[2.4.11],
|
||||
link:RelNotes/2.4.10.txt[2.4.10],
|
||||
link:RelNotes/2.4.9.txt[2.4.9],
|
||||
link:RelNotes/2.4.8.txt[2.4.8],
|
||||
link:RelNotes/2.4.7.txt[2.4.7],
|
||||
@ -64,9 +69,10 @@ Documentation for older releases are available here:
|
||||
link:RelNotes/2.4.1.txt[2.4.1],
|
||||
link:RelNotes/2.4.0.txt[2.4].
|
||||
|
||||
* link:v2.3.9/git.html[documentation for release 2.3.9]
|
||||
* link:v2.3.10/git.html[documentation for release 2.3.10]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.3.10.txt[2.3.10],
|
||||
link:RelNotes/2.3.9.txt[2.3.9],
|
||||
link:RelNotes/2.3.8.txt[2.3.8],
|
||||
link:RelNotes/2.3.7.txt[2.3.7],
|
||||
@ -1075,6 +1081,33 @@ GIT_ICASE_PATHSPECS::
|
||||
an operation has touched every ref (e.g., because you are
|
||||
cloning a repository to make a backup).
|
||||
|
||||
`GIT_ALLOW_PROTOCOL`::
|
||||
If set, provide a colon-separated list of protocols which are
|
||||
allowed to be used with fetch/push/clone. This is useful to
|
||||
restrict recursive submodule initialization from an untrusted
|
||||
repository. Any protocol not mentioned will be disallowed (i.e.,
|
||||
this is a whitelist, not a blacklist). If the variable is not
|
||||
set at all, all protocols are enabled. The protocol names
|
||||
currently used by git are:
|
||||
|
||||
- `file`: any local file-based path (including `file://` URLs,
|
||||
or local paths)
|
||||
|
||||
- `git`: the anonymous git protocol over a direct TCP
|
||||
connection (or proxy, if configured)
|
||||
|
||||
- `ssh`: git over ssh (including `host:path` syntax,
|
||||
`git+ssh://`, etc).
|
||||
|
||||
- `rsync`: git over rsync
|
||||
|
||||
- `http`: git over http, both "smart http" and "dumb http".
|
||||
Note that this does _not_ include `https`; if you want both,
|
||||
you should specify both as `http:https`.
|
||||
|
||||
- any external helpers are named by their protocol (e.g., use
|
||||
`hg` to allow the `git-remote-hg` helper)
|
||||
|
||||
|
||||
Discussion[[Discussion]]
|
||||
------------------------
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v2.5.2
|
||||
DEF_VER=v2.5.5
|
||||
|
||||
LF='
|
||||
'
|
||||
|
@ -973,7 +973,10 @@ static void pass_blame_to_parent(struct scoreboard *sb,
|
||||
fill_origin_blob(&sb->revs->diffopt, target, &file_o);
|
||||
num_get_patch++;
|
||||
|
||||
diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d);
|
||||
if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d))
|
||||
die("unable to generate diff (%s -> %s)",
|
||||
sha1_to_hex(parent->commit->object.sha1),
|
||||
sha1_to_hex(target->commit->object.sha1));
|
||||
/* The rest are the same as the parent */
|
||||
blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent);
|
||||
*d.dstq = NULL;
|
||||
@ -1119,7 +1122,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
|
||||
* file_p partially may match that image.
|
||||
*/
|
||||
memset(split, 0, sizeof(struct blame_entry [3]));
|
||||
diff_hunks(file_p, &file_o, 1, handle_split_cb, &d);
|
||||
if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d))
|
||||
die("unable to generate diff (%s)",
|
||||
sha1_to_hex(parent->commit->object.sha1));
|
||||
/* remainder, if any, all match the preimage */
|
||||
handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
names[i] = argv[i];
|
||||
if (read_mmfile(mmfs + i, fname))
|
||||
return -1;
|
||||
if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
|
||||
if (mmfs[i].size > MAX_XDIFF_SIZE ||
|
||||
buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
|
||||
return error("Cannot merge binary files: %s",
|
||||
argv[i]);
|
||||
}
|
||||
|
@ -118,7 +118,8 @@ static void show_diff(struct merge_list *entry)
|
||||
if (!dst.ptr)
|
||||
size = 0;
|
||||
dst.size = size;
|
||||
xdi_diff(&src, &dst, &xpp, &xecfg, &ecb);
|
||||
if (xdi_diff(&src, &dst, &xpp, &xecfg, &ecb))
|
||||
die("unable to generate diff");
|
||||
free(src.ptr);
|
||||
free(dst.ptr);
|
||||
}
|
||||
|
@ -2284,21 +2284,11 @@ static void show_commit(struct commit *commit, void *data)
|
||||
index_commit_for_bitmap(commit);
|
||||
}
|
||||
|
||||
static void show_object(struct object *obj,
|
||||
const struct name_path *path, const char *last,
|
||||
void *data)
|
||||
static void show_object(struct object *obj, const char *name, void *data)
|
||||
{
|
||||
char *name = path_name(path, last);
|
||||
|
||||
add_preferred_base_object(name);
|
||||
add_object_entry(obj->sha1, obj->type, name, 0);
|
||||
obj->flags |= OBJECT_ADDED;
|
||||
|
||||
/*
|
||||
* We will have generated the hash from the name,
|
||||
* but not saved a pointer to it - we can free it
|
||||
*/
|
||||
free((char *)name);
|
||||
}
|
||||
|
||||
static void show_edge(struct commit *commit)
|
||||
@ -2480,8 +2470,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
|
||||
}
|
||||
|
||||
static void record_recent_object(struct object *obj,
|
||||
const struct name_path *path,
|
||||
const char *last,
|
||||
const char *name,
|
||||
void *data)
|
||||
{
|
||||
sha1_array_append(&recent_objects, obj->sha1);
|
||||
|
@ -29,9 +29,10 @@ static int diff_two(const char *file1, const char *label1,
|
||||
xdemitconf_t xecfg;
|
||||
xdemitcb_t ecb;
|
||||
mmfile_t minus, plus;
|
||||
int ret;
|
||||
|
||||
if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2))
|
||||
return 1;
|
||||
return -1;
|
||||
|
||||
printf("--- a/%s\n+++ b/%s\n", label1, label2);
|
||||
fflush(stdout);
|
||||
@ -40,11 +41,11 @@ static int diff_two(const char *file1, const char *label1,
|
||||
memset(&xecfg, 0, sizeof(xecfg));
|
||||
xecfg.ctxlen = 3;
|
||||
ecb.outf = outf;
|
||||
xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
|
||||
ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
|
||||
|
||||
free(minus.ptr);
|
||||
free(plus.ptr);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cmd_rerere(int argc, const char **argv, const char *prefix)
|
||||
@ -104,7 +105,8 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
|
||||
for (i = 0; i < merge_rr.nr; i++) {
|
||||
const char *path = merge_rr.items[i].string;
|
||||
const char *name = (const char *)merge_rr.items[i].util;
|
||||
diff_two(rerere_path(name, "preimage"), path, path, path);
|
||||
if (diff_two(rerere_path(name, "preimage"), path, path, path))
|
||||
die("unable to generate diff for %s", name);
|
||||
}
|
||||
else
|
||||
usage_with_options(rerere_usage, options);
|
||||
|
@ -177,9 +177,7 @@ static void finish_commit(struct commit *commit, void *data)
|
||||
free_commit_buffer(commit);
|
||||
}
|
||||
|
||||
static void finish_object(struct object *obj,
|
||||
const struct name_path *path, const char *name,
|
||||
void *cb_data)
|
||||
static void finish_object(struct object *obj, const char *name, void *cb_data)
|
||||
{
|
||||
struct rev_list_info *info = cb_data;
|
||||
if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1))
|
||||
@ -188,15 +186,13 @@ static void finish_object(struct object *obj,
|
||||
parse_object(obj->sha1);
|
||||
}
|
||||
|
||||
static void show_object(struct object *obj,
|
||||
const struct name_path *path, const char *component,
|
||||
void *cb_data)
|
||||
static void show_object(struct object *obj, const char *name, void *cb_data)
|
||||
{
|
||||
struct rev_list_info *info = cb_data;
|
||||
finish_object(obj, path, component, cb_data);
|
||||
finish_object(obj, name, cb_data);
|
||||
if (info->flags & REV_LIST_QUIET)
|
||||
return;
|
||||
show_object_with_name(stdout, obj, path, component);
|
||||
show_object_with_name(stdout, obj, name);
|
||||
}
|
||||
|
||||
static void show_edge(struct commit *commit)
|
||||
|
@ -419,8 +419,10 @@ static void combine_diff(const struct object_id *parent, unsigned int mode,
|
||||
state.num_parent = num_parent;
|
||||
state.n = n;
|
||||
|
||||
xdi_diff_outf(&parent_file, result_file, consume_line, &state,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&parent_file, result_file, consume_line, &state,
|
||||
&xpp, &xecfg))
|
||||
die("unable to generate combined diff for %s",
|
||||
oid_to_hex(parent));
|
||||
free(parent_file.ptr);
|
||||
|
||||
/* Assign line numbers for this parent.
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "url.h"
|
||||
#include "string-list.h"
|
||||
#include "sha1-array.h"
|
||||
#include "transport.h"
|
||||
|
||||
static char *server_capabilities;
|
||||
static const char *parse_feature_value(const char *, const char *, int *);
|
||||
@ -694,6 +695,8 @@ struct child_process *git_connect(int fd[2], const char *url,
|
||||
else
|
||||
target_host = xstrdup(hostandport);
|
||||
|
||||
transport_check_allowed("git");
|
||||
|
||||
/* These underlying connection commands die() if they
|
||||
* cannot connect.
|
||||
*/
|
||||
@ -727,6 +730,7 @@ struct child_process *git_connect(int fd[2], const char *url,
|
||||
int putty, tortoiseplink = 0;
|
||||
char *ssh_host = hostandport;
|
||||
const char *port = NULL;
|
||||
transport_check_allowed("ssh");
|
||||
get_host_and_port(&ssh_host, &port);
|
||||
|
||||
if (!port)
|
||||
@ -781,6 +785,7 @@ struct child_process *git_connect(int fd[2], const char *url,
|
||||
/* remove repo-local variables from the environment */
|
||||
conn->env = local_repo_env;
|
||||
conn->use_shell = 1;
|
||||
transport_check_allowed("file");
|
||||
}
|
||||
argv_array_push(&conn->args, cmd.buf);
|
||||
|
||||
|
26
diff.c
26
diff.c
@ -1033,8 +1033,9 @@ static void diff_words_show(struct diff_words_data *diff_words)
|
||||
xpp.flags = 0;
|
||||
/* as only the hunk header will be parsed, we need a 0-context */
|
||||
xecfg.ctxlen = 0;
|
||||
xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
|
||||
&xpp, &xecfg))
|
||||
die("unable to generate word diff");
|
||||
free(minus.ptr);
|
||||
free(plus.ptr);
|
||||
if (diff_words->current_plus != diff_words->plus.text.ptr +
|
||||
@ -2441,8 +2442,9 @@ static void builtin_diff(const char *name_a,
|
||||
xecfg.ctxlen = strtoul(v, NULL, 10);
|
||||
if (o->word_diff)
|
||||
init_diff_words_data(&ecbdata, o, one, two);
|
||||
xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
|
||||
&xpp, &xecfg))
|
||||
die("unable to generate diff for %s", one->path);
|
||||
if (o->word_diff)
|
||||
free_diff_words_data(&ecbdata);
|
||||
if (textconv_one)
|
||||
@ -2519,8 +2521,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
|
||||
xpp.flags = o->xdl_opts;
|
||||
xecfg.ctxlen = o->context;
|
||||
xecfg.interhunkctxlen = o->interhunkcontext;
|
||||
xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
|
||||
&xpp, &xecfg))
|
||||
die("unable to generate diffstat for %s", one->path);
|
||||
}
|
||||
|
||||
diff_free_filespec_data(one);
|
||||
@ -2566,8 +2569,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
|
||||
memset(&xecfg, 0, sizeof(xecfg));
|
||||
xecfg.ctxlen = 1; /* at least one context line */
|
||||
xpp.flags = 0;
|
||||
xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
|
||||
&xpp, &xecfg))
|
||||
die("unable to generate checkdiff for %s", one->path);
|
||||
|
||||
if (data.ws_rule & WS_BLANK_AT_EOF) {
|
||||
struct emit_callback ecbdata;
|
||||
@ -4508,8 +4512,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
|
||||
xpp.flags = 0;
|
||||
xecfg.ctxlen = 3;
|
||||
xecfg.flags = 0;
|
||||
xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
|
||||
&xpp, &xecfg))
|
||||
return error("unable to generate patch-id diff for %s",
|
||||
p->one->path);
|
||||
}
|
||||
|
||||
git_SHA1_Final(sha1, &ctx);
|
||||
|
4
diff.h
4
diff.h
@ -221,8 +221,8 @@ struct combine_diff_path {
|
||||
} parent[FLEX_ARRAY];
|
||||
};
|
||||
#define combine_diff_path_size(n, l) \
|
||||
(sizeof(struct combine_diff_path) + \
|
||||
sizeof(struct combine_diff_parent) * (n) + (l) + 1)
|
||||
st_add4(sizeof(struct combine_diff_path), (l), 1, \
|
||||
st_mult(sizeof(struct combine_diff_parent), (n)))
|
||||
|
||||
extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
|
||||
int dense, struct rev_info *);
|
||||
|
@ -62,8 +62,8 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
|
||||
ecbdata.hit = 0;
|
||||
xecfg.ctxlen = o->context;
|
||||
xecfg.interhunkctxlen = o->interhunkcontext;
|
||||
xdi_diff_outf(one, two, diffgrep_consume, &ecbdata,
|
||||
&xpp, &xecfg);
|
||||
if (xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, &xpp, &xecfg))
|
||||
return 0;
|
||||
return ecbdata.hit;
|
||||
}
|
||||
|
||||
|
99
dir.c
99
dir.c
@ -1078,10 +1078,9 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
|
||||
(!untracked || !untracked->valid ||
|
||||
/*
|
||||
* .. and .gitignore does not exist before
|
||||
* (i.e. null exclude_sha1 and skip_worktree is
|
||||
* not set). Then we can skip loading .gitignore,
|
||||
* which would result in ENOENT anyway.
|
||||
* skip_worktree is taken care in read_directory()
|
||||
* (i.e. null exclude_sha1). Then we can skip
|
||||
* loading .gitignore, which would result in
|
||||
* ENOENT anyway.
|
||||
*/
|
||||
!is_null_sha1(untracked->exclude_sha1))) {
|
||||
/*
|
||||
@ -1298,7 +1297,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
|
||||
*/
|
||||
static enum path_treatment treat_directory(struct dir_struct *dir,
|
||||
struct untracked_cache_dir *untracked,
|
||||
const char *dirname, int len, int exclude,
|
||||
const char *dirname, int len, int baselen, int exclude,
|
||||
const struct path_simplify *simplify)
|
||||
{
|
||||
/* The "len-1" is to strip the final '/' */
|
||||
@ -1325,7 +1324,8 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
|
||||
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
|
||||
return exclude ? path_excluded : path_untracked;
|
||||
|
||||
untracked = lookup_untracked(dir->untracked, untracked, dirname, len);
|
||||
untracked = lookup_untracked(dir->untracked, untracked,
|
||||
dirname + baselen, len - baselen);
|
||||
return read_directory_recursive(dir, dirname, len,
|
||||
untracked, 1, simplify);
|
||||
}
|
||||
@ -1445,6 +1445,7 @@ static int get_dtype(struct dirent *de, const char *path, int len)
|
||||
static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
struct untracked_cache_dir *untracked,
|
||||
struct strbuf *path,
|
||||
int baselen,
|
||||
const struct path_simplify *simplify,
|
||||
int dtype, struct dirent *de)
|
||||
{
|
||||
@ -1496,8 +1497,8 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
return path_none;
|
||||
case DT_DIR:
|
||||
strbuf_addch(path, '/');
|
||||
return treat_directory(dir, untracked, path->buf, path->len, exclude,
|
||||
simplify);
|
||||
return treat_directory(dir, untracked, path->buf, path->len,
|
||||
baselen, exclude, simplify);
|
||||
case DT_REG:
|
||||
case DT_LNK:
|
||||
return exclude ? path_excluded : path_untracked;
|
||||
@ -1558,7 +1559,7 @@ static enum path_treatment treat_path(struct dir_struct *dir,
|
||||
return path_none;
|
||||
|
||||
dtype = DTYPE(de);
|
||||
return treat_one_path(dir, untracked, path, simplify, dtype, de);
|
||||
return treat_one_path(dir, untracked, path, baselen, simplify, dtype, de);
|
||||
}
|
||||
|
||||
static void add_untracked(struct untracked_cache_dir *dir, const char *name)
|
||||
@ -1828,7 +1829,7 @@ static int treat_leading_path(struct dir_struct *dir,
|
||||
break;
|
||||
if (simplify_away(sb.buf, sb.len, simplify))
|
||||
break;
|
||||
if (treat_one_path(dir, NULL, &sb, simplify,
|
||||
if (treat_one_path(dir, NULL, &sb, baselen, simplify,
|
||||
DT_DIR, NULL) == path_none)
|
||||
break; /* do not recurse into it */
|
||||
if (len <= baselen) {
|
||||
@ -1880,7 +1881,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
|
||||
const struct pathspec *pathspec)
|
||||
{
|
||||
struct untracked_cache_dir *root;
|
||||
int i;
|
||||
|
||||
if (!dir->untracked || getenv("GIT_DISABLE_UNTRACKED_CACHE"))
|
||||
return NULL;
|
||||
@ -1932,15 +1932,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
|
||||
if (dir->exclude_list_group[EXC_CMDL].nr)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* An optimization in prep_exclude() does not play well with
|
||||
* CE_SKIP_WORKTREE. It's a rare case anyway, if a single
|
||||
* entry has that bit set, disable the whole untracked cache.
|
||||
*/
|
||||
for (i = 0; i < active_nr; i++)
|
||||
if (ce_skip_worktree(active_cache[i]))
|
||||
return NULL;
|
||||
|
||||
if (!ident_in_untracked(dir->untracked)) {
|
||||
warning(_("Untracked cache is disabled on this system."));
|
||||
return NULL;
|
||||
@ -2625,23 +2616,67 @@ done2:
|
||||
return uc;
|
||||
}
|
||||
|
||||
static void invalidate_one_directory(struct untracked_cache *uc,
|
||||
struct untracked_cache_dir *ucd)
|
||||
{
|
||||
uc->dir_invalidated++;
|
||||
ucd->valid = 0;
|
||||
ucd->untracked_nr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally when an entry is added or removed from a directory,
|
||||
* invalidating that directory is enough. No need to touch its
|
||||
* ancestors. When a directory is shown as "foo/bar/" in git-status
|
||||
* however, deleting or adding an entry may have cascading effect.
|
||||
*
|
||||
* Say the "foo/bar/file" has become untracked, we need to tell the
|
||||
* untracked_cache_dir of "foo" that "bar/" is not an untracked
|
||||
* directory any more (because "bar" is managed by foo as an untracked
|
||||
* "file").
|
||||
*
|
||||
* Similarly, if "foo/bar/file" moves from untracked to tracked and it
|
||||
* was the last untracked entry in the entire "foo", we should show
|
||||
* "foo/" instead. Which means we have to invalidate past "bar" up to
|
||||
* "foo".
|
||||
*
|
||||
* This function traverses all directories from root to leaf. If there
|
||||
* is a chance of one of the above cases happening, we invalidate back
|
||||
* to root. Otherwise we just invalidate the leaf. There may be a more
|
||||
* sophisticated way than checking for SHOW_OTHER_DIRECTORIES to
|
||||
* detect these cases and avoid unnecessary invalidation, for example,
|
||||
* checking for the untracked entry named "bar/" in "foo", but for now
|
||||
* stick to something safe and simple.
|
||||
*/
|
||||
static int invalidate_one_component(struct untracked_cache *uc,
|
||||
struct untracked_cache_dir *dir,
|
||||
const char *path, int len)
|
||||
{
|
||||
const char *rest = strchr(path, '/');
|
||||
|
||||
if (rest) {
|
||||
int component_len = rest - path;
|
||||
struct untracked_cache_dir *d =
|
||||
lookup_untracked(uc, dir, path, component_len);
|
||||
int ret =
|
||||
invalidate_one_component(uc, d, rest + 1,
|
||||
len - (component_len + 1));
|
||||
if (ret)
|
||||
invalidate_one_directory(uc, dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
invalidate_one_directory(uc, dir);
|
||||
return uc->dir_flags & DIR_SHOW_OTHER_DIRECTORIES;
|
||||
}
|
||||
|
||||
void untracked_cache_invalidate_path(struct index_state *istate,
|
||||
const char *path)
|
||||
{
|
||||
const char *sep;
|
||||
struct untracked_cache_dir *d;
|
||||
if (!istate->untracked || !istate->untracked->root)
|
||||
return;
|
||||
sep = strrchr(path, '/');
|
||||
if (sep)
|
||||
d = lookup_untracked(istate->untracked,
|
||||
istate->untracked->root,
|
||||
path, sep - path);
|
||||
else
|
||||
d = istate->untracked->root;
|
||||
istate->untracked->dir_invalidated++;
|
||||
d->valid = 0;
|
||||
d->untracked_nr = 0;
|
||||
invalidate_one_component(istate->untracked, istate->untracked->root,
|
||||
path, strlen(path));
|
||||
}
|
||||
|
||||
void untracked_cache_remove_from_index(struct index_state *istate,
|
||||
|
@ -510,7 +510,7 @@ then
|
||||
git read-tree --reset -u $head_tree $head_tree &&
|
||||
index_tree=$(git write-tree) &&
|
||||
git read-tree -m -u $index_tree $head_tree
|
||||
git read-tree $head_tree
|
||||
git read-tree -m $head_tree
|
||||
;;
|
||||
,t)
|
||||
if test -f "$dotest/rebasing"
|
||||
|
@ -96,6 +96,14 @@
|
||||
#define unsigned_add_overflows(a, b) \
|
||||
((b) > maximum_unsigned_value_of_type(a) - (a))
|
||||
|
||||
/*
|
||||
* Returns true if the multiplication of "a" and "b" will
|
||||
* overflow. The types of "a" and "b" must match and must be unsigned.
|
||||
* Note that this macro evaluates "a" twice!
|
||||
*/
|
||||
#define unsigned_mult_overflows(a, b) \
|
||||
((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define TYPEOF(x) (__typeof__(x))
|
||||
#else
|
||||
@ -699,6 +707,32 @@ extern void release_pack_memory(size_t);
|
||||
typedef void (*try_to_free_t)(size_t);
|
||||
extern try_to_free_t set_try_to_free_routine(try_to_free_t);
|
||||
|
||||
static inline size_t st_add(size_t a, size_t b)
|
||||
{
|
||||
if (unsigned_add_overflows(a, b))
|
||||
die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
|
||||
(uintmax_t)a, (uintmax_t)b);
|
||||
return a + b;
|
||||
}
|
||||
#define st_add3(a,b,c) st_add((a),st_add((b),(c)))
|
||||
#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
|
||||
|
||||
static inline size_t st_mult(size_t a, size_t b)
|
||||
{
|
||||
if (unsigned_mult_overflows(a, b))
|
||||
die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
|
||||
(uintmax_t)a, (uintmax_t)b);
|
||||
return a * b;
|
||||
}
|
||||
|
||||
static inline size_t st_sub(size_t a, size_t b)
|
||||
{
|
||||
if (a < b)
|
||||
die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
|
||||
(uintmax_t)a, (uintmax_t)b);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# define xalloca(size) (alloca(size))
|
||||
|
@ -22,6 +22,15 @@ require_work_tree
|
||||
wt_prefix=$(git rev-parse --show-prefix)
|
||||
cd_to_toplevel
|
||||
|
||||
# Restrict ourselves to a vanilla subset of protocols; the URLs
|
||||
# we get are under control of a remote repository, and we do not
|
||||
# want them kicking off arbitrary git-remote-* programs.
|
||||
#
|
||||
# If the user has already specified a set of allowed protocols,
|
||||
# we assume they know what they're doing and use that instead.
|
||||
: ${GIT_ALLOW_PROTOCOL=file:git:http:https:ssh}
|
||||
export GIT_ALLOW_PROTOCOL
|
||||
|
||||
command=
|
||||
branch=
|
||||
force=
|
||||
@ -904,7 +913,7 @@ Maybe you want to use 'update --init'?")"
|
||||
;;
|
||||
!*)
|
||||
command="${update_module#!}"
|
||||
die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
|
||||
die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
|
||||
say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
|
||||
must_die_on_failure=yes
|
||||
;;
|
||||
|
23
http-push.c
23
http-push.c
@ -1276,9 +1276,7 @@ static struct object_list **add_one_object(struct object *obj, struct object_lis
|
||||
}
|
||||
|
||||
static struct object_list **process_blob(struct blob *blob,
|
||||
struct object_list **p,
|
||||
struct name_path *path,
|
||||
const char *name)
|
||||
struct object_list **p)
|
||||
{
|
||||
struct object *obj = &blob->object;
|
||||
|
||||
@ -1292,14 +1290,11 @@ static struct object_list **process_blob(struct blob *blob,
|
||||
}
|
||||
|
||||
static struct object_list **process_tree(struct tree *tree,
|
||||
struct object_list **p,
|
||||
struct name_path *path,
|
||||
const char *name)
|
||||
struct object_list **p)
|
||||
{
|
||||
struct object *obj = &tree->object;
|
||||
struct tree_desc desc;
|
||||
struct name_entry entry;
|
||||
struct name_path me;
|
||||
|
||||
obj->flags |= LOCAL;
|
||||
|
||||
@ -1309,21 +1304,17 @@ static struct object_list **process_tree(struct tree *tree,
|
||||
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
||||
|
||||
obj->flags |= SEEN;
|
||||
name = xstrdup(name);
|
||||
p = add_one_object(obj, p);
|
||||
me.up = path;
|
||||
me.elem = name;
|
||||
me.elem_len = strlen(name);
|
||||
|
||||
init_tree_desc(&desc, tree->buffer, tree->size);
|
||||
|
||||
while (tree_entry(&desc, &entry))
|
||||
switch (object_type(entry.mode)) {
|
||||
case OBJ_TREE:
|
||||
p = process_tree(lookup_tree(entry.sha1), p, &me, name);
|
||||
p = process_tree(lookup_tree(entry.sha1), p);
|
||||
break;
|
||||
case OBJ_BLOB:
|
||||
p = process_blob(lookup_blob(entry.sha1), p, &me, name);
|
||||
p = process_blob(lookup_blob(entry.sha1), p);
|
||||
break;
|
||||
default:
|
||||
/* Subproject commit - not in this repository */
|
||||
@ -1342,7 +1333,7 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
|
||||
int count = 0;
|
||||
|
||||
while ((commit = get_revision(revs)) != NULL) {
|
||||
p = process_tree(commit->tree, p, NULL, "");
|
||||
p = process_tree(commit->tree, p);
|
||||
commit->object.flags |= LOCAL;
|
||||
if (!(commit->object.flags & UNINTERESTING))
|
||||
count += add_send_request(&commit->object, lock);
|
||||
@ -1361,11 +1352,11 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
|
||||
continue;
|
||||
}
|
||||
if (obj->type == OBJ_TREE) {
|
||||
p = process_tree((struct tree *)obj, p, NULL, name);
|
||||
p = process_tree((struct tree *)obj, p);
|
||||
continue;
|
||||
}
|
||||
if (obj->type == OBJ_BLOB) {
|
||||
p = process_blob((struct blob *)obj, p, NULL, name);
|
||||
p = process_blob((struct blob *)obj, p);
|
||||
continue;
|
||||
}
|
||||
die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
|
||||
|
18
http.c
18
http.c
@ -9,6 +9,7 @@
|
||||
#include "version.h"
|
||||
#include "pkt-line.h"
|
||||
#include "gettext.h"
|
||||
#include "transport.h"
|
||||
|
||||
int active_requests;
|
||||
int http_is_verbose;
|
||||
@ -340,6 +341,7 @@ static void set_curl_keepalive(CURL *c)
|
||||
static CURL *get_curl_handle(void)
|
||||
{
|
||||
CURL *result = curl_easy_init();
|
||||
long allowed_protocols = 0;
|
||||
|
||||
if (!result)
|
||||
die("curl_easy_init failed");
|
||||
@ -394,11 +396,27 @@ static CURL *get_curl_handle(void)
|
||||
}
|
||||
|
||||
curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
|
||||
#if LIBCURL_VERSION_NUM >= 0x071301
|
||||
curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
|
||||
#elif LIBCURL_VERSION_NUM >= 0x071101
|
||||
curl_easy_setopt(result, CURLOPT_POST301, 1);
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x071304
|
||||
if (is_transport_allowed("http"))
|
||||
allowed_protocols |= CURLPROTO_HTTP;
|
||||
if (is_transport_allowed("https"))
|
||||
allowed_protocols |= CURLPROTO_HTTPS;
|
||||
if (is_transport_allowed("ftp"))
|
||||
allowed_protocols |= CURLPROTO_FTP;
|
||||
if (is_transport_allowed("ftps"))
|
||||
allowed_protocols |= CURLPROTO_FTPS;
|
||||
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
|
||||
#else
|
||||
if (transport_restrict_protocols())
|
||||
warning("protocol restrictions not applied to curl redirects because\n"
|
||||
"your curl version is too old (>= 7.19.4)");
|
||||
#endif
|
||||
|
||||
if (getenv("GIT_CURL_VERBOSE"))
|
||||
curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
|
||||
|
@ -325,7 +325,7 @@ static int collect_diff_cb(long start_a, long count_a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
|
||||
static int collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
|
||||
{
|
||||
struct collect_diff_cbdata cbdata = {NULL};
|
||||
xpparam_t xpp;
|
||||
@ -340,7 +340,7 @@ static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges
|
||||
xecfg.hunk_func = collect_diff_cb;
|
||||
memset(&ecb, 0, sizeof(ecb));
|
||||
ecb.priv = &cbdata;
|
||||
xdi_diff(parent, target, &xpp, &xecfg, &ecb);
|
||||
return xdi_diff(parent, target, &xpp, &xecfg, &ecb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1030,7 +1030,8 @@ static int process_diff_filepair(struct rev_info *rev,
|
||||
}
|
||||
|
||||
diff_ranges_init(&diff);
|
||||
collect_diff(&file_parent, &file_target, &diff);
|
||||
if (collect_diff(&file_parent, &file_target, &diff))
|
||||
die("unable to generate diff for %s", pair->one->path);
|
||||
|
||||
/* NEEDSWORK should apply some heuristics to prevent mismatches */
|
||||
free(rg->path);
|
||||
|
@ -11,11 +11,12 @@
|
||||
static void process_blob(struct rev_info *revs,
|
||||
struct blob *blob,
|
||||
show_object_fn show,
|
||||
struct name_path *path,
|
||||
struct strbuf *path,
|
||||
const char *name,
|
||||
void *cb_data)
|
||||
{
|
||||
struct object *obj = &blob->object;
|
||||
size_t pathlen;
|
||||
|
||||
if (!revs->blob_objects)
|
||||
return;
|
||||
@ -24,7 +25,11 @@ static void process_blob(struct rev_info *revs,
|
||||
if (obj->flags & (UNINTERESTING | SEEN))
|
||||
return;
|
||||
obj->flags |= SEEN;
|
||||
show(obj, path, name, cb_data);
|
||||
|
||||
pathlen = path->len;
|
||||
strbuf_addstr(path, name);
|
||||
show(obj, path->buf, cb_data);
|
||||
strbuf_setlen(path, pathlen);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -52,7 +57,7 @@ static void process_blob(struct rev_info *revs,
|
||||
static void process_gitlink(struct rev_info *revs,
|
||||
const unsigned char *sha1,
|
||||
show_object_fn show,
|
||||
struct name_path *path,
|
||||
struct strbuf *path,
|
||||
const char *name,
|
||||
void *cb_data)
|
||||
{
|
||||
@ -62,7 +67,6 @@ static void process_gitlink(struct rev_info *revs,
|
||||
static void process_tree(struct rev_info *revs,
|
||||
struct tree *tree,
|
||||
show_object_fn show,
|
||||
struct name_path *path,
|
||||
struct strbuf *base,
|
||||
const char *name,
|
||||
void *cb_data)
|
||||
@ -70,7 +74,6 @@ static void process_tree(struct rev_info *revs,
|
||||
struct object *obj = &tree->object;
|
||||
struct tree_desc desc;
|
||||
struct name_entry entry;
|
||||
struct name_path me;
|
||||
enum interesting match = revs->diffopt.pathspec.nr == 0 ?
|
||||
all_entries_interesting: entry_not_interesting;
|
||||
int baselen = base->len;
|
||||
@ -86,17 +89,12 @@ static void process_tree(struct rev_info *revs,
|
||||
return;
|
||||
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
||||
}
|
||||
obj->flags |= SEEN;
|
||||
show(obj, path, name, cb_data);
|
||||
me.up = path;
|
||||
me.elem = name;
|
||||
me.elem_len = strlen(name);
|
||||
|
||||
if (!match) {
|
||||
strbuf_addstr(base, name);
|
||||
if (base->len)
|
||||
strbuf_addch(base, '/');
|
||||
}
|
||||
obj->flags |= SEEN;
|
||||
strbuf_addstr(base, name);
|
||||
show(obj, base->buf, cb_data);
|
||||
if (base->len)
|
||||
strbuf_addch(base, '/');
|
||||
|
||||
init_tree_desc(&desc, tree->buffer, tree->size);
|
||||
|
||||
@ -113,16 +111,16 @@ static void process_tree(struct rev_info *revs,
|
||||
if (S_ISDIR(entry.mode))
|
||||
process_tree(revs,
|
||||
lookup_tree(entry.sha1),
|
||||
show, &me, base, entry.path,
|
||||
show, base, entry.path,
|
||||
cb_data);
|
||||
else if (S_ISGITLINK(entry.mode))
|
||||
process_gitlink(revs, entry.sha1,
|
||||
show, &me, entry.path,
|
||||
show, base, entry.path,
|
||||
cb_data);
|
||||
else
|
||||
process_blob(revs,
|
||||
lookup_blob(entry.sha1),
|
||||
show, &me, entry.path,
|
||||
show, base, entry.path,
|
||||
cb_data);
|
||||
}
|
||||
strbuf_setlen(base, baselen);
|
||||
@ -213,19 +211,19 @@ void traverse_commit_list(struct rev_info *revs,
|
||||
continue;
|
||||
if (obj->type == OBJ_TAG) {
|
||||
obj->flags |= SEEN;
|
||||
show_object(obj, NULL, name, data);
|
||||
show_object(obj, name, data);
|
||||
continue;
|
||||
}
|
||||
if (!path)
|
||||
path = "";
|
||||
if (obj->type == OBJ_TREE) {
|
||||
process_tree(revs, (struct tree *)obj, show_object,
|
||||
NULL, &base, path, data);
|
||||
&base, path, data);
|
||||
continue;
|
||||
}
|
||||
if (obj->type == OBJ_BLOB) {
|
||||
process_blob(revs, (struct blob *)obj, show_object,
|
||||
NULL, path, data);
|
||||
&base, path, data);
|
||||
continue;
|
||||
}
|
||||
die("unknown pending object %s (%s)",
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define LIST_OBJECTS_H
|
||||
|
||||
typedef void (*show_commit_fn)(struct commit *, void *);
|
||||
typedef void (*show_object_fn)(struct object *, const struct name_path *, const char *, void *);
|
||||
typedef void (*show_object_fn)(struct object *, const char *, void *);
|
||||
void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *);
|
||||
|
||||
typedef void (*show_edge_fn)(struct commit *);
|
||||
|
@ -89,7 +89,10 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
|
||||
xmparam_t xmp;
|
||||
assert(opts);
|
||||
|
||||
if (buffer_is_binary(orig->ptr, orig->size) ||
|
||||
if (orig->size > MAX_XDIFF_SIZE ||
|
||||
src1->size > MAX_XDIFF_SIZE ||
|
||||
src2->size > MAX_XDIFF_SIZE ||
|
||||
buffer_is_binary(orig->ptr, orig->size) ||
|
||||
buffer_is_binary(src1->ptr, src1->size) ||
|
||||
buffer_is_binary(src2->ptr, src2->size)) {
|
||||
return ll_binary_merge(drv_unused, result,
|
||||
|
@ -148,8 +148,7 @@ static uint32_t find_object_pos(const unsigned char *sha1)
|
||||
return entry->in_pack_pos;
|
||||
}
|
||||
|
||||
static void show_object(struct object *object, const struct name_path *path,
|
||||
const char *last, void *data)
|
||||
static void show_object(struct object *object, const char *name, void *data)
|
||||
{
|
||||
struct bitmap *base = data;
|
||||
bitmap_set(base, find_object_pos(object->sha1));
|
||||
|
@ -422,19 +422,15 @@ static int ext_index_add_object(struct object *object, const char *name)
|
||||
return bitmap_pos + bitmap_git.pack->num_objects;
|
||||
}
|
||||
|
||||
static void show_object(struct object *object, const struct name_path *path,
|
||||
const char *last, void *data)
|
||||
static void show_object(struct object *object, const char *name, void *data)
|
||||
{
|
||||
struct bitmap *base = data;
|
||||
int bitmap_pos;
|
||||
|
||||
bitmap_pos = bitmap_position(object->sha1);
|
||||
|
||||
if (bitmap_pos < 0) {
|
||||
char *name = path_name(path, last);
|
||||
if (bitmap_pos < 0)
|
||||
bitmap_pos = ext_index_add_object(object, name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
bitmap_set(base, bitmap_pos);
|
||||
}
|
||||
@ -902,9 +898,8 @@ struct bitmap_test_data {
|
||||
size_t seen;
|
||||
};
|
||||
|
||||
static void test_show_object(struct object *object,
|
||||
const struct name_path *path,
|
||||
const char *last, void *data)
|
||||
static void test_show_object(struct object *object, const char *name,
|
||||
void *data)
|
||||
{
|
||||
struct bitmap_test_data *tdata = data;
|
||||
int bitmap_pos;
|
||||
|
@ -37,15 +37,14 @@ static int add_one_ref(const char *path, const struct object_id *oid,
|
||||
* The traversal will have already marked us as SEEN, so we
|
||||
* only need to handle any progress reporting here.
|
||||
*/
|
||||
static void mark_object(struct object *obj, const struct name_path *path,
|
||||
const char *name, void *data)
|
||||
static void mark_object(struct object *obj, const char *name, void *data)
|
||||
{
|
||||
update_progress(data);
|
||||
}
|
||||
|
||||
static void mark_commit(struct commit *c, void *data)
|
||||
{
|
||||
mark_object(&c->object, NULL, NULL, data);
|
||||
mark_object(&c->object, NULL, data);
|
||||
}
|
||||
|
||||
struct recent_data {
|
||||
|
64
revision.c
64
revision.c
@ -21,69 +21,13 @@
|
||||
|
||||
volatile show_early_output_fn_t show_early_output;
|
||||
|
||||
char *path_name(const struct name_path *path, const char *name)
|
||||
void show_object_with_name(FILE *out, struct object *obj, const char *name)
|
||||
{
|
||||
const struct name_path *p;
|
||||
char *n, *m;
|
||||
int nlen = strlen(name);
|
||||
int len = nlen + 1;
|
||||
|
||||
for (p = path; p; p = p->up) {
|
||||
if (p->elem_len)
|
||||
len += p->elem_len + 1;
|
||||
}
|
||||
n = xmalloc(len);
|
||||
m = n + len - (nlen + 1);
|
||||
strcpy(m, name);
|
||||
for (p = path; p; p = p->up) {
|
||||
if (p->elem_len) {
|
||||
m -= p->elem_len + 1;
|
||||
memcpy(m, p->elem, p->elem_len);
|
||||
m[p->elem_len] = '/';
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static int show_path_component_truncated(FILE *out, const char *name, int len)
|
||||
{
|
||||
int cnt;
|
||||
for (cnt = 0; cnt < len; cnt++) {
|
||||
int ch = name[cnt];
|
||||
if (!ch || ch == '\n')
|
||||
return -1;
|
||||
fputc(ch, out);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int show_path_truncated(FILE *out, const struct name_path *path)
|
||||
{
|
||||
int emitted, ours;
|
||||
|
||||
if (!path)
|
||||
return 0;
|
||||
emitted = show_path_truncated(out, path->up);
|
||||
if (emitted < 0)
|
||||
return emitted;
|
||||
if (emitted)
|
||||
fputc('/', out);
|
||||
ours = show_path_component_truncated(out, path->elem, path->elem_len);
|
||||
if (ours < 0)
|
||||
return ours;
|
||||
return ours || emitted;
|
||||
}
|
||||
|
||||
void show_object_with_name(FILE *out, struct object *obj,
|
||||
const struct name_path *path, const char *component)
|
||||
{
|
||||
struct name_path leaf;
|
||||
leaf.up = (struct name_path *)path;
|
||||
leaf.elem = component;
|
||||
leaf.elem_len = strlen(component);
|
||||
const char *p;
|
||||
|
||||
fprintf(out, "%s ", sha1_to_hex(obj->sha1));
|
||||
show_path_truncated(out, &leaf);
|
||||
for (p = name; *p && *p != '\n'; p++)
|
||||
fputc(*p, out);
|
||||
fputc('\n', out);
|
||||
}
|
||||
|
||||
|
11
revision.h
11
revision.h
@ -256,16 +256,9 @@ extern void put_revision_mark(const struct rev_info *revs,
|
||||
extern void mark_parents_uninteresting(struct commit *commit);
|
||||
extern void mark_tree_uninteresting(struct tree *tree);
|
||||
|
||||
struct name_path {
|
||||
struct name_path *up;
|
||||
int elem_len;
|
||||
const char *elem;
|
||||
};
|
||||
char *path_name(struct strbuf *path, const char *name);
|
||||
|
||||
char *path_name(const struct name_path *path, const char *name);
|
||||
|
||||
extern void show_object_with_name(FILE *, struct object *,
|
||||
const struct name_path *, const char *);
|
||||
extern void show_object_with_name(FILE *, struct object *, const char *);
|
||||
|
||||
extern void add_pending_object(struct rev_info *revs,
|
||||
struct object *obj, const char *name);
|
||||
|
@ -119,6 +119,10 @@ RewriteRule ^/smart-redir-perm/(.*)$ /smart/$1 [R=301]
|
||||
RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302]
|
||||
RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301]
|
||||
RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301]
|
||||
RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302]
|
||||
|
||||
RewriteRule ^/loop-redir/x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-(.*) /$1 [R=302]
|
||||
RewriteRule ^/loop-redir/(.*)$ /loop-redir/x-$1 [R=302]
|
||||
|
||||
<IfDefine SSL>
|
||||
LoadModule ssl_module modules/mod_ssl.so
|
||||
|
96
t/lib-proto-disable.sh
Normal file
96
t/lib-proto-disable.sh
Normal file
@ -0,0 +1,96 @@
|
||||
# Test routines for checking protocol disabling.
|
||||
|
||||
# test cloning a particular protocol
|
||||
# $1 - description of the protocol
|
||||
# $2 - machine-readable name of the protocol
|
||||
# $3 - the URL to try cloning
|
||||
test_proto () {
|
||||
desc=$1
|
||||
proto=$2
|
||||
url=$3
|
||||
|
||||
test_expect_success "clone $1 (enabled)" '
|
||||
rm -rf tmp.git &&
|
||||
(
|
||||
GIT_ALLOW_PROTOCOL=$proto &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
git clone --bare "$url" tmp.git
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success "fetch $1 (enabled)" '
|
||||
(
|
||||
cd tmp.git &&
|
||||
GIT_ALLOW_PROTOCOL=$proto &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
git fetch
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success "push $1 (enabled)" '
|
||||
(
|
||||
cd tmp.git &&
|
||||
GIT_ALLOW_PROTOCOL=$proto &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
git push origin HEAD:pushed
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success "push $1 (disabled)" '
|
||||
(
|
||||
cd tmp.git &&
|
||||
GIT_ALLOW_PROTOCOL=none &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
test_must_fail git push origin HEAD:pushed
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success "fetch $1 (disabled)" '
|
||||
(
|
||||
cd tmp.git &&
|
||||
GIT_ALLOW_PROTOCOL=none &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
test_must_fail git fetch
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success "clone $1 (disabled)" '
|
||||
rm -rf tmp.git &&
|
||||
(
|
||||
GIT_ALLOW_PROTOCOL=none &&
|
||||
export GIT_ALLOW_PROTOCOL &&
|
||||
test_must_fail git clone --bare "$url" tmp.git
|
||||
)
|
||||
'
|
||||
}
|
||||
|
||||
# set up an ssh wrapper that will access $host/$repo in the
|
||||
# trash directory, and enable it for subsequent tests.
|
||||
setup_ssh_wrapper () {
|
||||
test_expect_success 'setup ssh wrapper' '
|
||||
write_script ssh-wrapper <<-\EOF &&
|
||||
echo >&2 "ssh: $*"
|
||||
host=$1; shift
|
||||
cd "$TRASH_DIRECTORY/$host" &&
|
||||
eval "$*"
|
||||
EOF
|
||||
GIT_SSH="$PWD/ssh-wrapper" &&
|
||||
export GIT_SSH &&
|
||||
export TRASH_DIRECTORY
|
||||
'
|
||||
}
|
||||
|
||||
# set up a wrapper that can be used with remote-ext to
|
||||
# access repositories in the "remote" directory of trash-dir,
|
||||
# like "ext::fake-remote %S repo.git"
|
||||
setup_ext_wrapper () {
|
||||
test_expect_success 'setup ext wrapper' '
|
||||
write_script fake-remote <<-\EOF &&
|
||||
echo >&2 "fake-remote: $*"
|
||||
cd "$TRASH_DIRECTORY/remote" &&
|
||||
eval "$*"
|
||||
EOF
|
||||
PATH=$TRASH_DIRECTORY:$PATH &&
|
||||
export TRASH_DIRECTORY
|
||||
'
|
||||
}
|
14
t/t5810-proto-disable-local.sh
Executable file
14
t/t5810-proto-disable-local.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test disabling of local paths in clone/fetch'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-proto-disable.sh"
|
||||
|
||||
test_expect_success 'setup repository to clone' '
|
||||
test_commit one
|
||||
'
|
||||
|
||||
test_proto "file://" file "file://$PWD"
|
||||
test_proto "path" file .
|
||||
|
||||
test_done
|
20
t/t5811-proto-disable-git.sh
Executable file
20
t/t5811-proto-disable-git.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test disabling of git-over-tcp in clone/fetch'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-proto-disable.sh"
|
||||
. "$TEST_DIRECTORY/lib-git-daemon.sh"
|
||||
start_git_daemon
|
||||
|
||||
test_expect_success 'create git-accessible repo' '
|
||||
bare="$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" &&
|
||||
test_commit one &&
|
||||
git --bare init "$bare" &&
|
||||
git push "$bare" HEAD &&
|
||||
>"$bare/git-daemon-export-ok" &&
|
||||
git -C "$bare" config daemon.receivepack true
|
||||
'
|
||||
|
||||
test_proto "git://" git "$GIT_DAEMON_URL/repo.git"
|
||||
|
||||
test_done
|
33
t/t5812-proto-disable-http.sh
Executable file
33
t/t5812-proto-disable-http.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test disabling of git-over-http in clone/fetch'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-proto-disable.sh"
|
||||
. "$TEST_DIRECTORY/lib-httpd.sh"
|
||||
start_httpd
|
||||
|
||||
test_expect_success 'create git-accessible repo' '
|
||||
bare="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
|
||||
test_commit one &&
|
||||
git --bare init "$bare" &&
|
||||
git push "$bare" HEAD &&
|
||||
git -C "$bare" config http.receivepack true
|
||||
'
|
||||
|
||||
test_proto "smart http" http "$HTTPD_URL/smart/repo.git"
|
||||
|
||||
test_expect_success 'curl redirects respect whitelist' '
|
||||
test_must_fail env GIT_ALLOW_PROTOCOL=http:https \
|
||||
git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr &&
|
||||
{
|
||||
test_i18ngrep "ftp.*disabled" stderr ||
|
||||
test_i18ngrep "your curl version is too old"
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'curl limits redirects' '
|
||||
test_must_fail git clone "$HTTPD_URL/loop-redir/smart/repo.git"
|
||||
'
|
||||
|
||||
stop_httpd
|
||||
test_done
|
20
t/t5813-proto-disable-ssh.sh
Executable file
20
t/t5813-proto-disable-ssh.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test disabling of git-over-ssh in clone/fetch'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-proto-disable.sh"
|
||||
|
||||
setup_ssh_wrapper
|
||||
|
||||
test_expect_success 'setup repository to clone' '
|
||||
test_commit one &&
|
||||
mkdir remote &&
|
||||
git init --bare remote/repo.git &&
|
||||
git push remote/repo.git HEAD
|
||||
'
|
||||
|
||||
test_proto "host:path" ssh "remote:repo.git"
|
||||
test_proto "ssh://" ssh "ssh://remote/$PWD/remote/repo.git"
|
||||
test_proto "git+ssh://" ssh "git+ssh://remote/$PWD/remote/repo.git"
|
||||
|
||||
test_done
|
18
t/t5814-proto-disable-ext.sh
Executable file
18
t/t5814-proto-disable-ext.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test disabling of remote-helper paths in clone/fetch'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-proto-disable.sh"
|
||||
|
||||
setup_ext_wrapper
|
||||
|
||||
test_expect_success 'setup repository to clone' '
|
||||
test_commit one &&
|
||||
mkdir remote &&
|
||||
git init --bare remote/repo.git &&
|
||||
git push remote/repo.git HEAD
|
||||
'
|
||||
|
||||
test_proto "remote-helper" ext "ext::fake-remote %S repo.git"
|
||||
|
||||
test_done
|
43
t/t5815-submodule-protos.sh
Executable file
43
t/t5815-submodule-protos.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test protocol whitelisting with submodules'
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY"/lib-proto-disable.sh
|
||||
|
||||
setup_ext_wrapper
|
||||
setup_ssh_wrapper
|
||||
|
||||
test_expect_success 'setup repository with submodules' '
|
||||
mkdir remote &&
|
||||
git init remote/repo.git &&
|
||||
(cd remote/repo.git && test_commit one) &&
|
||||
# submodule-add should probably trust what we feed it on the cmdline,
|
||||
# but its implementation is overly conservative.
|
||||
GIT_ALLOW_PROTOCOL=ssh git submodule add remote:repo.git ssh-module &&
|
||||
GIT_ALLOW_PROTOCOL=ext git submodule add "ext::fake-remote %S repo.git" ext-module &&
|
||||
git commit -m "add submodules"
|
||||
'
|
||||
|
||||
test_expect_success 'clone with recurse-submodules fails' '
|
||||
test_must_fail git clone --recurse-submodules . dst
|
||||
'
|
||||
|
||||
test_expect_success 'setup individual updates' '
|
||||
rm -rf dst &&
|
||||
git clone . dst &&
|
||||
git -C dst submodule init
|
||||
'
|
||||
|
||||
test_expect_success 'update of ssh allowed' '
|
||||
git -C dst submodule update ssh-module
|
||||
'
|
||||
|
||||
test_expect_success 'update of ext not allowed' '
|
||||
test_must_fail git -C dst submodule update ext-module
|
||||
'
|
||||
|
||||
test_expect_success 'user can override whitelist' '
|
||||
GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module
|
||||
'
|
||||
|
||||
test_done
|
@ -354,4 +354,219 @@ EOF
|
||||
test_cmp ../expect ../actual
|
||||
'
|
||||
|
||||
test_expect_success 'set up for sparse checkout testing' '
|
||||
echo two >done/.gitignore &&
|
||||
echo three >>done/.gitignore &&
|
||||
echo two >done/two &&
|
||||
git add -f done/two done/.gitignore &&
|
||||
git commit -m "first commit"
|
||||
'
|
||||
|
||||
test_expect_success 'status after commit' '
|
||||
: >../trace &&
|
||||
GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
|
||||
git status --porcelain >../actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
?? .gitignore
|
||||
?? dtwo/
|
||||
EOF
|
||||
test_cmp ../status.expect ../actual &&
|
||||
cat >../trace.expect <<EOF &&
|
||||
node creation: 0
|
||||
gitignore invalidation: 0
|
||||
directory invalidation: 0
|
||||
opendir: 2
|
||||
EOF
|
||||
test_cmp ../trace.expect ../trace
|
||||
'
|
||||
|
||||
test_expect_success 'untracked cache correct after commit' '
|
||||
test-dump-untracked-cache >../actual &&
|
||||
cat >../expect <<EOF &&
|
||||
info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
|
||||
core.excludesfile 0000000000000000000000000000000000000000
|
||||
exclude_per_dir .gitignore
|
||||
flags 00000006
|
||||
/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
|
||||
.gitignore
|
||||
dtwo/
|
||||
/done/ 0000000000000000000000000000000000000000 recurse valid
|
||||
/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
two
|
||||
EOF
|
||||
test_cmp ../expect ../actual
|
||||
'
|
||||
|
||||
test_expect_success 'set up sparse checkout' '
|
||||
echo "done/[a-z]*" >.git/info/sparse-checkout &&
|
||||
test_config core.sparsecheckout true &&
|
||||
git checkout master &&
|
||||
git update-index --force-untracked-cache &&
|
||||
git status --porcelain >/dev/null && # prime the cache
|
||||
test_path_is_missing done/.gitignore &&
|
||||
test_path_is_file done/one
|
||||
'
|
||||
|
||||
test_expect_success 'create/modify files, some of which are gitignored' '
|
||||
echo two bis >done/two &&
|
||||
echo three >done/three && # three is gitignored
|
||||
echo four >done/four && # four is gitignored at a higher level
|
||||
echo five >done/five # five is not gitignored
|
||||
'
|
||||
|
||||
test_expect_success 'test sparse status with untracked cache' '
|
||||
: >../trace &&
|
||||
avoid_racy &&
|
||||
GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
|
||||
git status --porcelain >../status.actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
M done/two
|
||||
?? .gitignore
|
||||
?? done/five
|
||||
?? dtwo/
|
||||
EOF
|
||||
test_cmp ../status.expect ../status.actual &&
|
||||
cat >../trace.expect <<EOF &&
|
||||
node creation: 0
|
||||
gitignore invalidation: 1
|
||||
directory invalidation: 2
|
||||
opendir: 2
|
||||
EOF
|
||||
test_cmp ../trace.expect ../trace
|
||||
'
|
||||
|
||||
test_expect_success 'untracked cache correct after status' '
|
||||
test-dump-untracked-cache >../actual &&
|
||||
cat >../expect <<EOF &&
|
||||
info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
|
||||
core.excludesfile 0000000000000000000000000000000000000000
|
||||
exclude_per_dir .gitignore
|
||||
flags 00000006
|
||||
/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
|
||||
.gitignore
|
||||
dtwo/
|
||||
/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
|
||||
five
|
||||
/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
two
|
||||
EOF
|
||||
test_cmp ../expect ../actual
|
||||
'
|
||||
|
||||
test_expect_success 'test sparse status again with untracked cache' '
|
||||
avoid_racy &&
|
||||
: >../trace &&
|
||||
GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
|
||||
git status --porcelain >../status.actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
M done/two
|
||||
?? .gitignore
|
||||
?? done/five
|
||||
?? dtwo/
|
||||
EOF
|
||||
test_cmp ../status.expect ../status.actual &&
|
||||
cat >../trace.expect <<EOF &&
|
||||
node creation: 0
|
||||
gitignore invalidation: 0
|
||||
directory invalidation: 0
|
||||
opendir: 0
|
||||
EOF
|
||||
test_cmp ../trace.expect ../trace
|
||||
'
|
||||
|
||||
test_expect_success 'set up for test of subdir and sparse checkouts' '
|
||||
mkdir done/sub &&
|
||||
mkdir done/sub/sub &&
|
||||
echo "sub" > done/sub/sub/file
|
||||
'
|
||||
|
||||
test_expect_success 'test sparse status with untracked cache and subdir' '
|
||||
avoid_racy &&
|
||||
: >../trace &&
|
||||
GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
|
||||
git status --porcelain >../status.actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
M done/two
|
||||
?? .gitignore
|
||||
?? done/five
|
||||
?? done/sub/
|
||||
?? dtwo/
|
||||
EOF
|
||||
test_cmp ../status.expect ../status.actual &&
|
||||
cat >../trace.expect <<EOF &&
|
||||
node creation: 2
|
||||
gitignore invalidation: 0
|
||||
directory invalidation: 1
|
||||
opendir: 3
|
||||
EOF
|
||||
test_cmp ../trace.expect ../trace
|
||||
'
|
||||
|
||||
test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
|
||||
test-dump-untracked-cache >../actual &&
|
||||
cat >../expect <<EOF &&
|
||||
info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
|
||||
core.excludesfile 0000000000000000000000000000000000000000
|
||||
exclude_per_dir .gitignore
|
||||
flags 00000006
|
||||
/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
|
||||
.gitignore
|
||||
dtwo/
|
||||
/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
|
||||
five
|
||||
sub/
|
||||
/done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
sub/
|
||||
/done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
file
|
||||
/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
|
||||
two
|
||||
EOF
|
||||
test_cmp ../expect ../actual
|
||||
'
|
||||
|
||||
test_expect_success 'test sparse status again with untracked cache and subdir' '
|
||||
avoid_racy &&
|
||||
: >../trace &&
|
||||
GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
|
||||
git status --porcelain >../status.actual &&
|
||||
test_cmp ../status.expect ../status.actual &&
|
||||
cat >../trace.expect <<EOF &&
|
||||
node creation: 0
|
||||
gitignore invalidation: 0
|
||||
directory invalidation: 0
|
||||
opendir: 0
|
||||
EOF
|
||||
test_cmp ../trace.expect ../trace
|
||||
'
|
||||
|
||||
test_expect_success 'move entry in subdir from untracked to cached' '
|
||||
git add dtwo/two &&
|
||||
git status --porcelain >../status.actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
M done/two
|
||||
A dtwo/two
|
||||
?? .gitignore
|
||||
?? done/five
|
||||
?? done/sub/
|
||||
EOF
|
||||
test_cmp ../status.expect ../status.actual
|
||||
'
|
||||
|
||||
test_expect_success 'move entry in subdir from cached to untracked' '
|
||||
git rm --cached dtwo/two &&
|
||||
git status --porcelain >../status.actual &&
|
||||
cat >../status.expect <<EOF &&
|
||||
M done/two
|
||||
?? .gitignore
|
||||
?? done/five
|
||||
?? done/sub/
|
||||
?? dtwo/
|
||||
EOF
|
||||
test_cmp ../status.expect ../status.actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -1043,6 +1043,8 @@ int transport_helper_init(struct transport *transport, const char *name)
|
||||
struct helper_data *data = xcalloc(1, sizeof(*data));
|
||||
data->name = name;
|
||||
|
||||
transport_check_allowed(name);
|
||||
|
||||
if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
|
||||
debug = 1;
|
||||
|
||||
|
43
transport.c
43
transport.c
@ -912,6 +912,42 @@ static int external_specification_len(const char *url)
|
||||
return strchr(url, ':') - url;
|
||||
}
|
||||
|
||||
static const struct string_list *protocol_whitelist(void)
|
||||
{
|
||||
static int enabled = -1;
|
||||
static struct string_list allowed = STRING_LIST_INIT_DUP;
|
||||
|
||||
if (enabled < 0) {
|
||||
const char *v = getenv("GIT_ALLOW_PROTOCOL");
|
||||
if (v) {
|
||||
string_list_split(&allowed, v, ':', -1);
|
||||
string_list_sort(&allowed);
|
||||
enabled = 1;
|
||||
} else {
|
||||
enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return enabled ? &allowed : NULL;
|
||||
}
|
||||
|
||||
int is_transport_allowed(const char *type)
|
||||
{
|
||||
const struct string_list *allowed = protocol_whitelist();
|
||||
return !allowed || string_list_has_string(allowed, type);
|
||||
}
|
||||
|
||||
void transport_check_allowed(const char *type)
|
||||
{
|
||||
if (!is_transport_allowed(type))
|
||||
die("transport '%s' not allowed", type);
|
||||
}
|
||||
|
||||
int transport_restrict_protocols(void)
|
||||
{
|
||||
return !!protocol_whitelist();
|
||||
}
|
||||
|
||||
struct transport *transport_get(struct remote *remote, const char *url)
|
||||
{
|
||||
const char *helper;
|
||||
@ -943,12 +979,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
||||
if (helper) {
|
||||
transport_helper_init(ret, helper);
|
||||
} else if (starts_with(url, "rsync:")) {
|
||||
transport_check_allowed("rsync");
|
||||
ret->get_refs_list = get_refs_via_rsync;
|
||||
ret->fetch = fetch_objs_via_rsync;
|
||||
ret->push = rsync_transport_push;
|
||||
ret->smart_options = NULL;
|
||||
} else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
|
||||
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
|
||||
transport_check_allowed("file");
|
||||
ret->data = data;
|
||||
ret->get_refs_list = get_refs_from_bundle;
|
||||
ret->fetch = fetch_refs_from_bundle;
|
||||
@ -960,7 +998,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
||||
|| starts_with(url, "ssh://")
|
||||
|| starts_with(url, "git+ssh://")
|
||||
|| starts_with(url, "ssh+git://")) {
|
||||
/* These are builtin smart transports. */
|
||||
/*
|
||||
* These are builtin smart transports; "allowed" transports
|
||||
* will be checked individually in git_connect.
|
||||
*/
|
||||
struct git_transport_data *data = xcalloc(1, sizeof(*data));
|
||||
ret->data = data;
|
||||
ret->set_option = NULL;
|
||||
|
18
transport.h
18
transport.h
@ -133,6 +133,24 @@ struct transport {
|
||||
/* Returns a transport suitable for the url */
|
||||
struct transport *transport_get(struct remote *, const char *);
|
||||
|
||||
/*
|
||||
* Check whether a transport is allowed by the environment. Type should
|
||||
* generally be the URL scheme, as described in Documentation/git.txt
|
||||
*/
|
||||
int is_transport_allowed(const char *type);
|
||||
|
||||
/*
|
||||
* Check whether a transport is allowed by the environment,
|
||||
* and die otherwise.
|
||||
*/
|
||||
void transport_check_allowed(const char *type);
|
||||
|
||||
/*
|
||||
* Returns true if the user has attempted to turn on protocol
|
||||
* restrictions at all.
|
||||
*/
|
||||
int transport_restrict_protocols(void);
|
||||
|
||||
/* Transport options which apply to git:// and scp-style URLs */
|
||||
|
||||
/* The program to use on the remote side to send a pack */
|
||||
|
@ -124,8 +124,8 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
|
||||
unsigned mode, const unsigned char *sha1)
|
||||
{
|
||||
struct combine_diff_path *p;
|
||||
int len = base->len + pathlen;
|
||||
int alloclen = combine_diff_path_size(nparent, len);
|
||||
size_t len = st_add(base->len, pathlen);
|
||||
size_t alloclen = combine_diff_path_size(nparent, len);
|
||||
|
||||
/* if last->next is !NULL - it is a pre-allocated memory, we can reuse */
|
||||
p = last->next;
|
||||
|
@ -131,6 +131,9 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co
|
||||
mmfile_t a = *mf1;
|
||||
mmfile_t b = *mf2;
|
||||
|
||||
if (mf1->size > MAX_XDIFF_SIZE || mf2->size > MAX_XDIFF_SIZE)
|
||||
return -1;
|
||||
|
||||
trim_common_tail(&a, &b, xecfg->ctxlen);
|
||||
|
||||
return xdl_diff(&a, &b, xpp, xecfg, xecb);
|
||||
|
@ -3,6 +3,13 @@
|
||||
|
||||
#include "xdiff/xdiff.h"
|
||||
|
||||
/*
|
||||
* xdiff isn't equipped to handle content over a gigabyte;
|
||||
* we make the cutoff 1GB - 1MB to give some breathing
|
||||
* room for constant-sized additions (e.g., merge markers)
|
||||
*/
|
||||
#define MAX_XDIFF_SIZE (1024UL * 1024 * 1023)
|
||||
|
||||
typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
|
||||
|
||||
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
|
||||
|
Reference in New Issue
Block a user