mirror of
https://github.com/git/git.git
synced 2026-03-13 10:23:30 +01:00
Merge branch 'jc/daemon' into next
* jc/daemon: multi-service daemon: documentation daemon: add upload-tar service. daemon: prepare for multiple services. Add git-zip-tree to .gitignore free(NULL) is perfectly valid. Use xcalloc instead of calloc Use fstat instead of fseek git-reset: remove unused variable git-cherry: remove unused variable
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -125,6 +125,7 @@ git-verify-pack
|
||||
git-verify-tag
|
||||
git-whatchanged
|
||||
git-write-tree
|
||||
git-zip-tree
|
||||
git-core-*/?*
|
||||
gitweb/gitweb.cgi
|
||||
test-date
|
||||
|
||||
@@ -11,17 +11,16 @@ SYNOPSIS
|
||||
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
||||
[--timeout=n] [--init-timeout=n] [--strict-paths]
|
||||
[--base-path=path] [--user-path | --user-path=path]
|
||||
[--reuseaddr] [--detach] [--pid-file=file]
|
||||
[--user=user [--group=group]] [directory...]
|
||||
[--enable=service] [--disable=service]
|
||||
[--allow-override=service] [--forbid-override=service]
|
||||
[--reuseaddr] [--detach] [--pid-file=file]
|
||||
[--user=user [--group=group]] [directory...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
A really simple TCP git daemon that normally listens on port "DEFAULT_GIT_PORT"
|
||||
aka 9418. It waits for a connection, and will just execute "git-upload-pack"
|
||||
when it gets one.
|
||||
|
||||
It's careful in that there's a magic request-line that gives the command and
|
||||
what directory to upload, and it verifies that the directory is OK.
|
||||
aka 9418. It waits for a connection asking for a service, and will serve
|
||||
that service if it is enabled.
|
||||
|
||||
It verifies that the directory has the magic file "git-daemon-export-ok", and
|
||||
it will refuse to export any git directory that hasn't explicitly been marked
|
||||
@@ -29,7 +28,12 @@ for export this way (unless the '--export-all' parameter is specified). If you
|
||||
pass some directory paths as 'git-daemon' arguments, you can further restrict
|
||||
the offers to a whitelist comprising of those.
|
||||
|
||||
This is ideally suited for read-only updates, i.e., pulling from git repositories.
|
||||
By default, only `upload-pack` service is enabled, which serves
|
||||
`git-fetch-pack` and `git-peek-remote` clients that are invoked
|
||||
from `git-fetch`, `git-ls-remote`, and `git-clone`.
|
||||
|
||||
This is ideally suited for read-only updates, i.e., pulling from
|
||||
git repositories.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
@@ -105,11 +109,38 @@ Giving these options is an error when used with `--inetd`; use
|
||||
the facility of inet daemon to achieve the same before spawning
|
||||
`git-daemon` if needed.
|
||||
|
||||
--enable-service, --disable-service::
|
||||
Enable/disable the service site-wide per default. Note
|
||||
that a service disabled site-wide can still be enabled
|
||||
per repository if it is marked overridable and the
|
||||
repository enables the service with an configuration
|
||||
item.
|
||||
|
||||
--allow-override, --forbid-override::
|
||||
Allow/forbid overriding the site-wide default with per
|
||||
repository configuration. By default, all the services
|
||||
are overridable.
|
||||
|
||||
<directory>::
|
||||
A directory to add to the whitelist of allowed directories. Unless
|
||||
--strict-paths is specified this will also include subdirectories
|
||||
of each named directory.
|
||||
|
||||
SERVICES
|
||||
--------
|
||||
|
||||
upload-pack::
|
||||
This serves `git-fetch-pack` and `git-peek-remote`
|
||||
clients. It is enabled by default, but a repository can
|
||||
disable it by setting `daemon.uploadpack` configuration
|
||||
item to `false`.
|
||||
|
||||
upload-tar::
|
||||
This serves `git-tar-tree --remote=repository` client.
|
||||
It is not enabled by default, but a repository can
|
||||
enable it by setting `daemon.uploadtar` configuration
|
||||
item to `true`.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
|
||||
|
||||
2
Makefile
2
Makefile
@@ -261,7 +261,7 @@ LIB_OBJS = \
|
||||
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
|
||||
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
|
||||
write_or_die.o \
|
||||
alloc.o merge-file.o path-list.o unpack-trees.o help.o $(DIFF_OBJS)
|
||||
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS)
|
||||
|
||||
BUILTIN_OBJS = \
|
||||
builtin-add.o \
|
||||
|
||||
14
TEST
14
TEST
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
cd t || exit
|
||||
GIT_USE_RECUR_FOR_RECURSIVE=LetsTryIt
|
||||
export GIT_USE_RECUR_FOR_RECURSIVE
|
||||
|
||||
./t3400-rebase.sh "$@" &&
|
||||
./t6020-merge-df.sh "$@" &&
|
||||
./t3401-rebase-partial.sh "$@" &&
|
||||
./t6021-merge-criss-cross.sh "$@" &&
|
||||
./t3402-rebase-merge.sh "$@" &&
|
||||
./t6022-merge-rename.sh "$@" &&
|
||||
./t6010-merge-base.sh "$@" &&
|
||||
:
|
||||
@@ -1131,8 +1131,7 @@ static struct fragment *parse_binary_hunk(char **buf_p,
|
||||
return frag;
|
||||
|
||||
corrupt:
|
||||
if (data)
|
||||
free(data);
|
||||
free(data);
|
||||
*status_p = -1;
|
||||
error("corrupt binary patch at line %d: %.*s",
|
||||
linenr-1, llen-1, buffer);
|
||||
@@ -1329,8 +1328,7 @@ static void show_stats(struct patch *patch)
|
||||
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
|
||||
len, name, patch->lines_added + patch->lines_deleted,
|
||||
add, pluses, del, minuses);
|
||||
if (qname)
|
||||
free(qname);
|
||||
free(qname);
|
||||
}
|
||||
|
||||
static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)
|
||||
|
||||
@@ -55,8 +55,7 @@ static void free_list(struct list *list)
|
||||
|
||||
for (i = 0; i < list->nr; i++) {
|
||||
free(list->list[i]);
|
||||
if (list->payload[i])
|
||||
free(list->payload[i]);
|
||||
free(list->payload[i]);
|
||||
}
|
||||
free(list->list);
|
||||
free(list->payload);
|
||||
|
||||
@@ -122,10 +122,8 @@ static int get_value(const char* key_, const char* regex_)
|
||||
ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
|
||||
|
||||
free_strings:
|
||||
if (repo_config)
|
||||
free(repo_config);
|
||||
if (global)
|
||||
free(global);
|
||||
free(repo_config);
|
||||
free(global);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,10 +93,8 @@ static void show_commit(struct commit *commit)
|
||||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
}
|
||||
if (commit->buffer) {
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
}
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
}
|
||||
|
||||
static void process_blob(struct blob *blob,
|
||||
|
||||
6
config.c
6
config.c
@@ -361,8 +361,7 @@ int git_config(config_fn_t fn)
|
||||
}
|
||||
|
||||
ret += git_config_from_file(fn, filename);
|
||||
if (repo_config)
|
||||
free(repo_config);
|
||||
free(repo_config);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -734,8 +733,7 @@ int git_config_set_multivar(const char* key, const char* value,
|
||||
out_free:
|
||||
if (0 <= fd)
|
||||
close(fd);
|
||||
if (config_filename)
|
||||
free(config_filename);
|
||||
free(config_filename);
|
||||
if (lock_file) {
|
||||
unlink(lock_file);
|
||||
free(lock_file);
|
||||
|
||||
124
daemon.c
124
daemon.c
@@ -232,13 +232,42 @@ static char *path_ok(char *dir)
|
||||
return NULL; /* Fallthrough. Deny by default */
|
||||
}
|
||||
|
||||
static int upload(char *dir)
|
||||
{
|
||||
/* Timeout as string */
|
||||
char timeout_buf[64];
|
||||
const char *path;
|
||||
typedef int (*daemon_service_fn)(void);
|
||||
struct daemon_service {
|
||||
const char *name;
|
||||
const char *config_name;
|
||||
daemon_service_fn fn;
|
||||
int enabled;
|
||||
int overridable;
|
||||
};
|
||||
|
||||
loginfo("Request for '%s'", dir);
|
||||
static struct daemon_service *service_looking_at;
|
||||
static int service_enabled;
|
||||
|
||||
static int git_daemon_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strncmp(var, "daemon.", 7) &&
|
||||
!strcmp(var + 7, service_looking_at->config_name)) {
|
||||
service_enabled = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we are not interested in parsing any other configuration here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_service(char *dir, struct daemon_service *service)
|
||||
{
|
||||
const char *path;
|
||||
int enabled = service->enabled;
|
||||
|
||||
loginfo("Request %s for '%s'", service->name, dir);
|
||||
|
||||
if (!enabled && !service->overridable) {
|
||||
logerror("'%s': service not enabled.", service->name);
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(path = path_ok(dir)))
|
||||
return -1;
|
||||
@@ -260,12 +289,34 @@ static int upload(char *dir)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (service->overridable) {
|
||||
service_looking_at = service;
|
||||
service_enabled = -1;
|
||||
git_config(git_daemon_config);
|
||||
if (0 <= service_enabled)
|
||||
enabled = service_enabled;
|
||||
}
|
||||
if (!enabled) {
|
||||
logerror("'%s': service not enabled for '%s'",
|
||||
service->name, path);
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We'll ignore SIGTERM from now on, we have a
|
||||
* good client.
|
||||
*/
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
return service->fn();
|
||||
}
|
||||
|
||||
static int upload_pack(void)
|
||||
{
|
||||
/* Timeout as string */
|
||||
char timeout_buf[64];
|
||||
|
||||
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
|
||||
|
||||
/* git-upload-pack only ever reads stuff, so this is safe */
|
||||
@@ -273,10 +324,43 @@ static int upload(char *dir)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int upload_tar(void)
|
||||
{
|
||||
execl_git_cmd("upload-tar", ".", NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct daemon_service daemon_service[] = {
|
||||
{ "upload-pack", "uploadpack", upload_pack, 1, 1 },
|
||||
{ "upload-tar", "uploadtar", upload_tar, 0, 1 },
|
||||
};
|
||||
|
||||
static void enable_service(const char *name, int ena) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||
if (!strcmp(daemon_service[i].name, name)) {
|
||||
daemon_service[i].enabled = ena;
|
||||
return;
|
||||
}
|
||||
}
|
||||
die("No such service %s", name);
|
||||
}
|
||||
|
||||
static void make_service_overridable(const char *name, int ena) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||
if (!strcmp(daemon_service[i].name, name)) {
|
||||
daemon_service[i].overridable = ena;
|
||||
return;
|
||||
}
|
||||
}
|
||||
die("No such service %s", name);
|
||||
}
|
||||
|
||||
static int execute(struct sockaddr *addr)
|
||||
{
|
||||
static char line[1000];
|
||||
int pktlen, len;
|
||||
int pktlen, len, i;
|
||||
|
||||
if (addr) {
|
||||
char addrbuf[256] = "";
|
||||
@@ -313,8 +397,14 @@ static int execute(struct sockaddr *addr)
|
||||
if (len && line[len-1] == '\n')
|
||||
line[--len] = 0;
|
||||
|
||||
if (!strncmp("git-upload-pack ", line, 16))
|
||||
return upload(line+16);
|
||||
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||
struct daemon_service *s = &(daemon_service[i]);
|
||||
int namelen = strlen(s->name);
|
||||
if (!strncmp("git-", line, 4) &&
|
||||
!strncmp(s->name, line + 4, namelen) &&
|
||||
line[namelen + 4] == ' ')
|
||||
return run_service(line + namelen + 5, s);
|
||||
}
|
||||
|
||||
logerror("Protocol error: '%s'", line);
|
||||
return -1;
|
||||
@@ -805,6 +895,22 @@ int main(int argc, char **argv)
|
||||
group_name = arg + 8;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--enable=", 9)) {
|
||||
enable_service(arg + 9, 1);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--disable=", 10)) {
|
||||
enable_service(arg + 10, 0);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--allow-override=", 17)) {
|
||||
make_service_overridable(arg + 17, 1);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--forbid-override=", 18)) {
|
||||
make_service_overridable(arg + 18, 0);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--")) {
|
||||
ok_paths = &argv[i+1];
|
||||
break;
|
||||
|
||||
8
dir.c
8
dir.c
@@ -112,17 +112,15 @@ static int add_excludes_from_file_1(const char *fname,
|
||||
int baselen,
|
||||
struct exclude_list *which)
|
||||
{
|
||||
struct stat st;
|
||||
int fd, i;
|
||||
long size;
|
||||
char *buf, *entry;
|
||||
|
||||
fd = open(fname, O_RDONLY);
|
||||
if (fd < 0)
|
||||
if (fd < 0 || fstat(fd, &st) < 0)
|
||||
goto err;
|
||||
size = lseek(fd, 0, SEEK_END);
|
||||
if (size < 0)
|
||||
goto err;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
size = st.st_size;
|
||||
if (size == 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
|
||||
3
fetch.c
3
fetch.c
@@ -302,8 +302,7 @@ int pull(int targets, char **target, const char **write_ref,
|
||||
if (ret)
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
if (msg)
|
||||
free(msg);
|
||||
free(msg);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -51,9 +51,6 @@ patch=$tmp-patch
|
||||
mkdir $patch
|
||||
trap "rm -rf $tmp-*" 0 1 2 3 15
|
||||
|
||||
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
|
||||
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
|
||||
|
||||
for c in $inup
|
||||
do
|
||||
git-diff-tree -p $c
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
USAGE='[--mixed | --soft | --hard] [<commit-ish>]'
|
||||
. git-sh-setup
|
||||
|
||||
tmp=${GIT_DIR}/reset.$$
|
||||
trap 'rm -f $tmp-*' 0 1 2 3 15
|
||||
|
||||
update=
|
||||
reset_type=--mixed
|
||||
case "$1" in
|
||||
|
||||
13
http-fetch.c
13
http-fetch.c
@@ -696,10 +696,8 @@ xml_start_tag(void *userData, const char *name, const char **atts)
|
||||
strcat(ctx->name, ".");
|
||||
strcat(ctx->name, c);
|
||||
|
||||
if (ctx->cdata) {
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = NULL;
|
||||
}
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = NULL;
|
||||
|
||||
ctx->userFunc(ctx, 0);
|
||||
}
|
||||
@@ -726,8 +724,7 @@ static void
|
||||
xml_cdata(void *userData, const XML_Char *s, int len)
|
||||
{
|
||||
struct xml_ctx *ctx = (struct xml_ctx *)userData;
|
||||
if (ctx->cdata)
|
||||
free(ctx->cdata);
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = xmalloc(len + 1);
|
||||
strlcpy(ctx->cdata, s, len + 1);
|
||||
}
|
||||
@@ -765,9 +762,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
ls->dentry_flags |= IS_DIR;
|
||||
}
|
||||
} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
|
||||
if (ls->dentry_name) {
|
||||
free(ls->dentry_name);
|
||||
}
|
||||
free(ls->dentry_name);
|
||||
ls->dentry_name = NULL;
|
||||
ls->dentry_flags = 0;
|
||||
}
|
||||
|
||||
13
http-push.c
13
http-push.c
@@ -1238,10 +1238,8 @@ xml_start_tag(void *userData, const char *name, const char **atts)
|
||||
strcat(ctx->name, ".");
|
||||
strcat(ctx->name, c);
|
||||
|
||||
if (ctx->cdata) {
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = NULL;
|
||||
}
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = NULL;
|
||||
|
||||
ctx->userFunc(ctx, 0);
|
||||
}
|
||||
@@ -1268,8 +1266,7 @@ static void
|
||||
xml_cdata(void *userData, const XML_Char *s, int len)
|
||||
{
|
||||
struct xml_ctx *ctx = (struct xml_ctx *)userData;
|
||||
if (ctx->cdata)
|
||||
free(ctx->cdata);
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = xmalloc(len + 1);
|
||||
strlcpy(ctx->cdata, s, len + 1);
|
||||
}
|
||||
@@ -1518,9 +1515,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
ls->dentry_flags |= IS_DIR;
|
||||
}
|
||||
} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
|
||||
if (ls->dentry_name) {
|
||||
free(ls->dentry_name);
|
||||
}
|
||||
free(ls->dentry_name);
|
||||
ls->dentry_name = NULL;
|
||||
ls->dentry_flags = 0;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static void grow_refs_hash(void)
|
||||
int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
|
||||
struct object_refs **new_hash;
|
||||
|
||||
new_hash = calloc(new_hash_size, sizeof(struct object_refs *));
|
||||
new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
|
||||
for (i = 0; i < refs_hash_size; i++) {
|
||||
struct object_refs *ref = refs_hash[i];
|
||||
if (!ref)
|
||||
|
||||
2
object.c
2
object.c
@@ -73,7 +73,7 @@ static void grow_object_hash(void)
|
||||
int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
|
||||
struct object **new_hash;
|
||||
|
||||
new_hash = calloc(new_hash_size, sizeof(struct object *));
|
||||
new_hash = xcalloc(new_hash_size, sizeof(struct object *));
|
||||
for (i = 0; i < obj_hash_size; i++) {
|
||||
struct object *obj = obj_hash[i];
|
||||
if (!obj)
|
||||
|
||||
@@ -85,8 +85,7 @@ void path_list_clear(struct path_list *list, int free_items)
|
||||
for (i = 0; i < list->nr; i++) {
|
||||
if (list->strdup_paths)
|
||||
free(list->items[i].path);
|
||||
if (list->items[i].util)
|
||||
free(list->items[i].util);
|
||||
free(list->items[i].util);
|
||||
}
|
||||
free(list->items);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user