Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
18b58f707f | |||
92cdfd2131 | |||
83c4d38017 | |||
dcd1742e56 | |||
3efb988098 | |||
f2df3104ce | |||
df37727a65 | |||
b258116462 | |||
f4113cac0c | |||
5088d3b387 | |||
33cfccbbf3 | |||
a5adaced2e | |||
ecad27cf98 | |||
8267cd11d6 | |||
441c4a4017 | |||
f54cb059b1 | |||
78f23bdf68 | |||
5015f01c12 | |||
c29edfefb6 | |||
f514ef9787 | |||
9a3d637541 | |||
811ce1b47c | |||
cd0120857b | |||
1add9aed85 | |||
13ec221d8c | |||
0269f968b7 | |||
d349e0ee60 | |||
7e11052442 | |||
f6e6362107 | |||
7fcec48da9 | |||
0615173998 | |||
c9e1f2c7f2 |
9
Documentation/RelNotes/2.2.3.txt
Normal file
9
Documentation/RelNotes/2.2.3.txt
Normal file
@ -0,0 +1,9 @@
|
||||
Git v2.2.3 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.2.2
|
||||
------------------
|
||||
|
||||
* A handful of codepaths that used to use fixed-sized arrays to hold
|
||||
pathnames have been corrected to use strbuf and other mechanisms to
|
||||
allow longer pathnames without fearing overflows.
|
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.
|
22
Documentation/RelNotes/2.3.8.txt
Normal file
22
Documentation/RelNotes/2.3.8.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Git v2.3.8 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.3.7
|
||||
------------------
|
||||
|
||||
* The usual "git diff" when seeing a file turning into a directory
|
||||
showed a patchset to remove the file and create all files in the
|
||||
directory, but "git diff --no-index" simply refused to work. Also,
|
||||
when asked to compare a file and a directory, imitate POSIX "diff"
|
||||
and compare the file with the file with the same name in the
|
||||
directory, instead of refusing to run.
|
||||
|
||||
* The default $HOME/.gitconfig file created upon "git config --global"
|
||||
that edits it had incorrectly spelled user.name and user.email
|
||||
entries in it.
|
||||
|
||||
* "git commit --date=now" or anything that relies on approxidate lost
|
||||
the daylight-saving-time offset.
|
||||
|
||||
Also contains typofixes, documentation updates and trivial code
|
||||
clean-ups.
|
9
Documentation/RelNotes/2.3.9.txt
Normal file
9
Documentation/RelNotes/2.3.9.txt
Normal file
@ -0,0 +1,9 @@
|
||||
Git v2.3.9 Release Notes
|
||||
========================
|
||||
|
||||
Fixes since v2.3.8
|
||||
------------------
|
||||
|
||||
* A handful of codepaths that used to use fixed-sized arrays to hold
|
||||
pathnames have been corrected to use strbuf and other mechanisms to
|
||||
allow longer pathnames without fearing overflows.
|
@ -10,7 +10,7 @@
|
||||
Include additional statistics at the end of blame output.
|
||||
|
||||
-L <start>,<end>::
|
||||
-L :<regex>::
|
||||
-L :<funcname>::
|
||||
Annotate only the given line range. May be specified multiple times.
|
||||
Overlapping ranges are allowed.
|
||||
+
|
||||
|
@ -62,9 +62,9 @@ produced by `--stat`, etc.
|
||||
output by allowing them to allocate space in advance.
|
||||
|
||||
-L <start>,<end>:<file>::
|
||||
-L :<regex>:<file>::
|
||||
-L :<funcname>:<file>::
|
||||
Trace the evolution of the line range given by "<start>,<end>"
|
||||
(or the funcname regex <regex>) within the <file>. You may
|
||||
(or the function name regex <funcname>) within the <file>. You may
|
||||
not give any pathspec limiters. This is currently limited to
|
||||
a walk starting from a single revision, i.e., you may only
|
||||
give zero or one positive revision arguments.
|
||||
|
@ -43,9 +43,12 @@ 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.3.7/git.html[documentation for release 2.3.7]
|
||||
* 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],
|
||||
link:RelNotes/2.3.6.txt[2.3.6],
|
||||
link:RelNotes/2.3.5.txt[2.3.5],
|
||||
@ -55,9 +58,10 @@ Documentation for older releases are available here:
|
||||
link:RelNotes/2.3.1.txt[2.3.1],
|
||||
link:RelNotes/2.3.0.txt[2.3].
|
||||
|
||||
* link:v2.2.2/git.html[documentation for release 2.2.2]
|
||||
* link:v2.2.3/git.html[documentation for release 2.2.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes/2.2.3.txt[2.2.3],
|
||||
link:RelNotes/2.2.2.txt[2.2.2],
|
||||
link:RelNotes/2.2.1.txt[2.2.1],
|
||||
link:RelNotes/2.2.0.txt[2.2].
|
||||
@ -1042,6 +1046,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]]
|
||||
------------------------
|
||||
|
@ -99,10 +99,10 @@ linkgit:git-rev-list[1] for a complete list.
|
||||
detailed explanation.)
|
||||
|
||||
-L<start>,<end>:<file>::
|
||||
-L:<regex>:<file>::
|
||||
-L:<funcname>:<file>::
|
||||
|
||||
Trace the evolution of the line range given by "<start>,<end>"
|
||||
(or the funcname regex <regex>) within the <file>. You may
|
||||
(or the function name regex <funcname>) within the <file>. You may
|
||||
not give any pathspec limiters. This is currently limited to
|
||||
a walk starting from a single revision, i.e., you may only
|
||||
give zero or one positive revision arguments.
|
||||
|
@ -22,8 +22,9 @@ This is only valid for <end> and will specify a number
|
||||
of lines before or after the line given by <start>.
|
||||
|
||||
+
|
||||
If ``:<regex>'' is given in place of <start> and <end>, it denotes the range
|
||||
from the first funcname line that matches <regex>, up to the next
|
||||
funcname line. ``:<regex>'' searches from the end of the previous `-L` range,
|
||||
if any, otherwise from the start of file.
|
||||
``^:<regex>'' searches from the start of file.
|
||||
If ``:<funcname>'' is given in place of <start> and <end>, it is a
|
||||
regular expression that denotes the range from the first funcname line
|
||||
that matches <funcname>, up to the next funcname line. ``:<funcname>''
|
||||
searches from the end of the previous `-L` range, if any, otherwise
|
||||
from the start of file. ``^:<funcname>'' searches from the start of
|
||||
file.
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v2.3.7
|
||||
DEF_VER=v2.3.10
|
||||
|
||||
LF='
|
||||
'
|
||||
|
@ -972,7 +972,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;
|
||||
@ -1118,7 +1121,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);
|
||||
}
|
||||
|
@ -455,9 +455,9 @@ static char *default_user_config(void)
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addf(&buf,
|
||||
_("# This is Git's per-user configuration file.\n"
|
||||
"[core]\n"
|
||||
"[user]\n"
|
||||
"# Please adapt and uncomment the following lines:\n"
|
||||
"# user = %s\n"
|
||||
"# name = %s\n"
|
||||
"# email = %s\n"),
|
||||
ident_default_name(),
|
||||
ident_default_email());
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -723,7 +723,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
|
||||
if (reflog) {
|
||||
unsigned char sha1[20];
|
||||
char nth_desc[256];
|
||||
char *ref;
|
||||
int base = 0;
|
||||
unsigned int flags = 0;
|
||||
@ -762,6 +761,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
|
||||
for (i = 0; i < reflog; i++) {
|
||||
char *logmsg;
|
||||
char *nth_desc;
|
||||
const char *msg;
|
||||
unsigned long timestamp;
|
||||
int tz;
|
||||
@ -780,8 +780,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
show_date(timestamp, tz, 1),
|
||||
msg);
|
||||
free(logmsg);
|
||||
sprintf(nth_desc, "%s@{%d}", *av, base+i);
|
||||
|
||||
nth_desc = xstrfmt("%s@{%d}", *av, base+i);
|
||||
append_ref(nth_desc, sha1, 1);
|
||||
free(nth_desc);
|
||||
}
|
||||
free(ref);
|
||||
}
|
||||
|
@ -419,8 +419,10 @@ static void combine_diff(const unsigned char *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",
|
||||
sha1_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;
|
||||
char *ssh_host = hostandport;
|
||||
const char *port = NULL;
|
||||
transport_check_allowed("ssh");
|
||||
get_host_and_port(&ssh_host, &port);
|
||||
|
||||
if (!port)
|
||||
@ -768,6 +772,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);
|
||||
|
||||
|
14
date.c
14
date.c
@ -704,10 +704,17 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
|
||||
date += match;
|
||||
}
|
||||
|
||||
/* mktime uses local timezone */
|
||||
/* do not use mktime(), which uses local timezone, here */
|
||||
*timestamp = tm_to_time_t(&tm);
|
||||
if (*timestamp == -1)
|
||||
return -1;
|
||||
|
||||
if (*offset == -1) {
|
||||
time_t temp_time = mktime(&tm);
|
||||
time_t temp_time;
|
||||
|
||||
/* gmtime_r() in match_digit() may have clobbered it */
|
||||
tm.tm_isdst = -1;
|
||||
temp_time = mktime(&tm);
|
||||
if ((time_t)*timestamp > temp_time) {
|
||||
*offset = ((time_t)*timestamp - temp_time) / 60;
|
||||
} else {
|
||||
@ -715,9 +722,6 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
|
||||
}
|
||||
}
|
||||
|
||||
if (*timestamp == -1)
|
||||
return -1;
|
||||
|
||||
if (!tm_gmt)
|
||||
*timestamp -= *offset * 60;
|
||||
return 0; /* success */
|
||||
|
@ -97,8 +97,27 @@ static int queue_diff(struct diff_options *o,
|
||||
if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
|
||||
return -1;
|
||||
|
||||
if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
|
||||
return error("file/directory conflict: %s, %s", name1, name2);
|
||||
if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) {
|
||||
struct diff_filespec *d1, *d2;
|
||||
|
||||
if (S_ISDIR(mode1)) {
|
||||
/* 2 is file that is created */
|
||||
d1 = noindex_filespec(NULL, 0);
|
||||
d2 = noindex_filespec(name2, mode2);
|
||||
name2 = NULL;
|
||||
mode2 = 0;
|
||||
} else {
|
||||
/* 1 is file that is deleted */
|
||||
d1 = noindex_filespec(name1, mode1);
|
||||
d2 = noindex_filespec(NULL, 0);
|
||||
name1 = NULL;
|
||||
mode1 = 0;
|
||||
}
|
||||
/* emit that file */
|
||||
diff_queue(&diff_queued_diff, d1, d2);
|
||||
|
||||
/* and then let the entire directory be created or deleted */
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
|
||||
struct strbuf buffer1 = STRBUF_INIT;
|
||||
@ -182,12 +201,50 @@ static int queue_diff(struct diff_options *o,
|
||||
}
|
||||
}
|
||||
|
||||
/* append basename of F to D */
|
||||
static void append_basename(struct strbuf *path, const char *dir, const char *file)
|
||||
{
|
||||
const char *tail = strrchr(file, '/');
|
||||
|
||||
strbuf_addstr(path, dir);
|
||||
while (path->len && path->buf[path->len - 1] == '/')
|
||||
path->len--;
|
||||
strbuf_addch(path, '/');
|
||||
strbuf_addstr(path, tail ? tail + 1 : file);
|
||||
}
|
||||
|
||||
/*
|
||||
* DWIM "diff D F" into "diff D/F F" and "diff F D" into "diff F D/F"
|
||||
* Note that we append the basename of F to D/, so "diff a/b/file D"
|
||||
* becomes "diff a/b/file D/file", not "diff a/b/file D/a/b/file".
|
||||
*/
|
||||
static void fixup_paths(const char **path, struct strbuf *replacement)
|
||||
{
|
||||
unsigned int isdir0, isdir1;
|
||||
|
||||
if (path[0] == file_from_standard_input ||
|
||||
path[1] == file_from_standard_input)
|
||||
return;
|
||||
isdir0 = is_directory(path[0]);
|
||||
isdir1 = is_directory(path[1]);
|
||||
if (isdir0 == isdir1)
|
||||
return;
|
||||
if (isdir0) {
|
||||
append_basename(replacement, path[0], path[1]);
|
||||
path[0] = replacement->buf;
|
||||
} else {
|
||||
append_basename(replacement, path[1], path[0]);
|
||||
path[1] = replacement->buf;
|
||||
}
|
||||
}
|
||||
|
||||
void diff_no_index(struct rev_info *revs,
|
||||
int argc, const char **argv,
|
||||
const char *prefix)
|
||||
{
|
||||
int i, prefixlen;
|
||||
const char *paths[2];
|
||||
struct strbuf replacement = STRBUF_INIT;
|
||||
|
||||
diff_setup(&revs->diffopt);
|
||||
for (i = 1; i < argc - 2; ) {
|
||||
@ -217,6 +274,9 @@ void diff_no_index(struct rev_info *revs,
|
||||
p = xstrdup(prefix_filename(prefix, prefixlen, p));
|
||||
paths[i] = p;
|
||||
}
|
||||
|
||||
fixup_paths(paths, &replacement);
|
||||
|
||||
revs->diffopt.skip_stat_unmatch = 1;
|
||||
if (!revs->diffopt.output_format)
|
||||
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
||||
@ -235,6 +295,8 @@ void diff_no_index(struct rev_info *revs,
|
||||
diffcore_std(&revs->diffopt);
|
||||
diff_flush(&revs->diffopt);
|
||||
|
||||
strbuf_release(&replacement);
|
||||
|
||||
/*
|
||||
* The return code for --no-index imitates diff(1):
|
||||
* 0 = no changes, 1 = changes, else error
|
||||
|
26
diff.c
26
diff.c
@ -1002,8 +1002,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 +
|
||||
@ -2400,8 +2401,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)
|
||||
@ -2478,8 +2480,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);
|
||||
@ -2525,8 +2528,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;
|
||||
@ -4425,8 +4429,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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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=
|
||||
|
18
http.c
18
http.c
@ -8,6 +8,7 @@
|
||||
#include "credential.h"
|
||||
#include "version.h"
|
||||
#include "pkt-line.h"
|
||||
#include "transport.h"
|
||||
|
||||
int active_requests;
|
||||
int http_is_verbose;
|
||||
@ -303,6 +304,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");
|
||||
@ -350,11 +352,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -575,7 +575,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
|
||||
|
||||
name_part = skip_range_arg(item->string);
|
||||
if (!name_part || *name_part != ':' || !name_part[1])
|
||||
die("-L argument '%s' not of the form start,end:file",
|
||||
die("-L argument not 'start,end:file' or ':funcname:file': %s",
|
||||
item->string);
|
||||
range_part = xstrndup(item->string, name_part - item->string);
|
||||
name_part++;
|
||||
@ -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);
|
||||
|
@ -88,7 +88,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,
|
||||
|
19
notes.c
19
notes.c
@ -362,13 +362,14 @@ static int non_note_cmp(const struct non_note *a, const struct non_note *b)
|
||||
return strcmp(a->path, b->path);
|
||||
}
|
||||
|
||||
static void add_non_note(struct notes_tree *t, const char *path,
|
||||
/* note: takes ownership of path string */
|
||||
static void add_non_note(struct notes_tree *t, char *path,
|
||||
unsigned int mode, const unsigned char *sha1)
|
||||
{
|
||||
struct non_note *p = t->prev_non_note, *n;
|
||||
n = (struct non_note *) xmalloc(sizeof(struct non_note));
|
||||
n->next = NULL;
|
||||
n->path = xstrdup(path);
|
||||
n->path = path;
|
||||
n->mode = mode;
|
||||
hashcpy(n->sha1, sha1);
|
||||
t->prev_non_note = n;
|
||||
@ -482,17 +483,17 @@ handle_non_note:
|
||||
* component.
|
||||
*/
|
||||
{
|
||||
char non_note_path[PATH_MAX];
|
||||
char *p = non_note_path;
|
||||
struct strbuf non_note_path = STRBUF_INIT;
|
||||
const char *q = sha1_to_hex(subtree->key_sha1);
|
||||
int i;
|
||||
for (i = 0; i < prefix_len; i++) {
|
||||
*p++ = *q++;
|
||||
*p++ = *q++;
|
||||
*p++ = '/';
|
||||
strbuf_addch(&non_note_path, *q++);
|
||||
strbuf_addch(&non_note_path, *q++);
|
||||
strbuf_addch(&non_note_path, '/');
|
||||
}
|
||||
strcpy(p, entry.path);
|
||||
add_non_note(t, non_note_path, entry.mode, entry.sha1);
|
||||
strbuf_addstr(&non_note_path, entry.path);
|
||||
add_non_note(t, strbuf_detach(&non_note_path, NULL),
|
||||
entry.mode, entry.sha1);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
|
@ -377,15 +377,12 @@ void read_info_alternates(const char * relative_base, int depth)
|
||||
char *map;
|
||||
size_t mapsz;
|
||||
struct stat st;
|
||||
const char alt_file_name[] = "info/alternates";
|
||||
/* Given that relative_base is no longer than PATH_MAX,
|
||||
ensure that "path" has enough space to append "/", the
|
||||
file name, "info/alternates", and a trailing NUL. */
|
||||
char path[PATH_MAX + 1 + sizeof alt_file_name];
|
||||
char *path;
|
||||
int fd;
|
||||
|
||||
sprintf(path, "%s/%s", relative_base, alt_file_name);
|
||||
path = xstrfmt("%s/info/alternates", relative_base);
|
||||
fd = git_open_noatime(path);
|
||||
free(path);
|
||||
if (fd < 0)
|
||||
return;
|
||||
if (fstat(fd, &st) || (st.st_size == 0)) {
|
||||
|
@ -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
|
||||
'
|
||||
}
|
@ -55,4 +55,38 @@ test_expect_success 'git diff --no-index executed outside repo gives correct err
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'diff D F and diff F D' '
|
||||
(
|
||||
cd repo &&
|
||||
echo in-repo >a &&
|
||||
echo non-repo >../non/git/a &&
|
||||
mkdir sub &&
|
||||
echo sub-repo >sub/a &&
|
||||
|
||||
test_must_fail git diff --no-index sub/a ../non/git/a >expect &&
|
||||
test_must_fail git diff --no-index sub/a ../non/git/ >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
test_must_fail git diff --no-index a ../non/git/a >expect &&
|
||||
test_must_fail git diff --no-index a ../non/git/ >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
test_must_fail git diff --no-index ../non/git/a a >expect &&
|
||||
test_must_fail git diff --no-index ../non/git a >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'turning a file into a directory' '
|
||||
(
|
||||
cd non/git &&
|
||||
mkdir d e e/sub &&
|
||||
echo 1 >d/sub &&
|
||||
echo 2 >e/sub/file &&
|
||||
printf "D\td/sub\nA\te/sub/file\n" >expect &&
|
||||
test_must_fail git diff --no-index --name-status d e >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -54,14 +54,14 @@ canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset
|
||||
canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset
|
||||
|
||||
test_bad_opts "-L" "switch.*requires a value"
|
||||
test_bad_opts "-L b.c" "argument.*not of the form"
|
||||
test_bad_opts "-L 1:" "argument.*not of the form"
|
||||
test_bad_opts "-L b.c" "argument not .start,end:file"
|
||||
test_bad_opts "-L 1:" "argument not .start,end:file"
|
||||
test_bad_opts "-L 1:nonexistent" "There is no path"
|
||||
test_bad_opts "-L 1:simple" "There is no path"
|
||||
test_bad_opts "-L '/foo:b.c'" "argument.*not of the form"
|
||||
test_bad_opts "-L '/foo:b.c'" "argument not .start,end:file"
|
||||
test_bad_opts "-L 1000:b.c" "has only.*lines"
|
||||
test_bad_opts "-L 1,1000:b.c" "has only.*lines"
|
||||
test_bad_opts "-L :b.c" "argument.*not of the form"
|
||||
test_bad_opts "-L :b.c" "argument not .start,end:file"
|
||||
test_bad_opts "-L :foo:b.c" "no match"
|
||||
|
||||
test_expect_success '-L X (X == nlines)' '
|
||||
|
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
|
@ -1038,6 +1038,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
@ -909,6 +909,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;
|
||||
@ -940,12 +976,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;
|
||||
@ -957,7 +995,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
@ -132,6 +132,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 */
|
||||
|
@ -1434,15 +1434,18 @@ static int verify_absent_1(const struct cache_entry *ce,
|
||||
if (!len)
|
||||
return 0;
|
||||
else if (len > 0) {
|
||||
char path[PATH_MAX + 1];
|
||||
memcpy(path, ce->name, len);
|
||||
path[len] = 0;
|
||||
if (lstat(path, &st))
|
||||
return error("cannot stat '%s': %s", path,
|
||||
strerror(errno));
|
||||
char *path;
|
||||
int ret;
|
||||
|
||||
return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
|
||||
error_type, o);
|
||||
path = xmemdupz(ce->name, len);
|
||||
if (lstat(path, &st))
|
||||
ret = error("cannot stat '%s': %s", path,
|
||||
strerror(errno));
|
||||
else
|
||||
ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
|
||||
&st, error_type, o);
|
||||
free(path);
|
||||
return ret;
|
||||
} else if (lstat(ce->name, &st)) {
|
||||
if (errno != ENOENT)
|
||||
return error("cannot stat '%s': %s", ce->name,
|
||||
|
@ -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