зеркало из https://github.com/microsoft/git.git
Merge branch 'jc/alternate-push'
* jc/alternate-push: push: receiver end advertises refs from alternate repositories push: prepare sender to receive extended ref information from the receiver receive-pack: make it a builtin is_directory(): a generic helper function
This commit is contained in:
Коммит
1ad6d46235
2
Makefile
2
Makefile
|
@ -294,7 +294,6 @@ PROGRAMS += git-mktag$X
|
|||
PROGRAMS += git-mktree$X
|
||||
PROGRAMS += git-pack-redundant$X
|
||||
PROGRAMS += git-patch-id$X
|
||||
PROGRAMS += git-receive-pack$X
|
||||
PROGRAMS += git-send-pack$X
|
||||
PROGRAMS += git-shell$X
|
||||
PROGRAMS += git-show-index$X
|
||||
|
@ -546,6 +545,7 @@ BUILTIN_OBJS += builtin-prune-packed.o
|
|||
BUILTIN_OBJS += builtin-prune.o
|
||||
BUILTIN_OBJS += builtin-push.o
|
||||
BUILTIN_OBJS += builtin-read-tree.o
|
||||
BUILTIN_OBJS += builtin-receive-pack.o
|
||||
BUILTIN_OBJS += builtin-reflog.o
|
||||
BUILTIN_OBJS += builtin-remote.o
|
||||
BUILTIN_OBJS += builtin-rerere.o
|
||||
|
|
13
abspath.c
13
abspath.c
|
@ -1,5 +1,16 @@
|
|||
#include "cache.h"
|
||||
|
||||
/*
|
||||
* Do not use this for inspecting *tracked* content. When path is a
|
||||
* symlink to a directory, we do not want to say it is a directory when
|
||||
* dealing with tracked content in the working tree.
|
||||
*/
|
||||
int is_directory(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
return (!stat(path, &st) && S_ISDIR(st.st_mode));
|
||||
}
|
||||
|
||||
/* We allow "recursive" symbolic links. Only within reason, though. */
|
||||
#define MAXDEPTH 5
|
||||
|
||||
|
@ -17,7 +28,7 @@ const char *make_absolute_path(const char *path)
|
|||
die ("Too long path: %.*s", 60, path);
|
||||
|
||||
while (depth--) {
|
||||
if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
|
||||
if (!is_directory(buf)) {
|
||||
char *last_slash = strrchr(buf, '/');
|
||||
if (last_slash) {
|
||||
*last_slash = '\0';
|
||||
|
|
|
@ -77,7 +77,7 @@ static char *get_repo_path(const char *repo, int *is_bundle)
|
|||
for (i = 0; i < ARRAY_SIZE(suffix); i++) {
|
||||
const char *path;
|
||||
path = mkpath("%s%s", repo, suffix[i]);
|
||||
if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
|
||||
if (is_directory(path)) {
|
||||
*is_bundle = 0;
|
||||
return xstrdup(make_nonrelative_path(path));
|
||||
}
|
||||
|
@ -140,13 +140,6 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
|
|||
return xstrndup(start, end - start);
|
||||
}
|
||||
|
||||
static int is_directory(const char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
return !stat(path, &buf) && S_ISDIR(buf.st_mode);
|
||||
}
|
||||
|
||||
static void strip_trailing_slashes(char *dir)
|
||||
{
|
||||
char *end = dir + strlen(dir);
|
||||
|
|
|
@ -735,7 +735,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
|||
conn = git_connect(fd, (char *)dest, args.uploadpack,
|
||||
args.verbose ? CONNECT_VERBOSE : 0);
|
||||
if (conn) {
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0, NULL);
|
||||
|
||||
ref = fetch_pack(&args, fd, conn, ref, dest, nr_heads, heads, NULL);
|
||||
close(fd[0]);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "exec_cmd.h"
|
||||
#include "commit.h"
|
||||
#include "object.h"
|
||||
#include "remote.h"
|
||||
#include "transport.h"
|
||||
|
||||
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
|
||||
|
||||
|
@ -462,14 +464,48 @@ static int delete_only(struct command *cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
|
||||
{
|
||||
char *other = xstrdup(make_absolute_path(e->base));
|
||||
size_t len = strlen(other);
|
||||
struct remote *remote;
|
||||
struct transport *transport;
|
||||
const struct ref *extra;
|
||||
|
||||
while (other[len-1] == '/')
|
||||
other[--len] = '\0';
|
||||
if (len < 8 || memcmp(other + len - 8, "/objects", 8))
|
||||
return 0;
|
||||
/* Is this a git repository with refs? */
|
||||
memcpy(other + len - 8, "/refs", 6);
|
||||
if (!is_directory(other))
|
||||
return 0;
|
||||
other[len - 8] = '\0';
|
||||
remote = remote_get(other);
|
||||
transport = transport_get(remote, other);
|
||||
for (extra = transport_get_remote_refs(transport);
|
||||
extra;
|
||||
extra = extra->next) {
|
||||
add_extra_ref(".have", extra->old_sha1, 0);
|
||||
}
|
||||
transport_disconnect(transport);
|
||||
free(other);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_alternate_refs(void)
|
||||
{
|
||||
foreach_alt_odb(add_refs_from_alternate, NULL);
|
||||
}
|
||||
|
||||
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
char *dir = NULL;
|
||||
|
||||
argv++;
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = *argv++;
|
||||
const char *arg = *argv++;
|
||||
|
||||
if (*arg == '-') {
|
||||
/* Do flag handling here */
|
||||
|
@ -477,7 +513,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
if (dir)
|
||||
usage(receive_pack_usage);
|
||||
dir = arg;
|
||||
dir = xstrdup(arg);
|
||||
}
|
||||
if (!dir)
|
||||
usage(receive_pack_usage);
|
||||
|
@ -497,7 +533,9 @@ int main(int argc, char **argv)
|
|||
else if (0 <= receive_unpack_limit)
|
||||
unpack_limit = receive_unpack_limit;
|
||||
|
||||
add_alternate_refs();
|
||||
write_head_info();
|
||||
clear_extra_refs();
|
||||
|
||||
/* EOF */
|
||||
packet_flush(1);
|
|
@ -18,7 +18,7 @@ static struct send_pack_args args = {
|
|||
/*
|
||||
* Make a pack stream and spit it out into file descriptor fd
|
||||
*/
|
||||
static int pack_objects(int fd, struct ref *refs)
|
||||
static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
|
||||
{
|
||||
/*
|
||||
* The child becomes pack-objects --revs; we feed
|
||||
|
@ -34,6 +34,8 @@ static int pack_objects(int fd, struct ref *refs)
|
|||
NULL,
|
||||
};
|
||||
struct child_process po;
|
||||
int i;
|
||||
char buf[42];
|
||||
|
||||
if (args.use_thin_pack)
|
||||
argv[4] = "--thin";
|
||||
|
@ -49,9 +51,15 @@ static int pack_objects(int fd, struct ref *refs)
|
|||
* We feed the pack-objects we just spawned with revision
|
||||
* parameters by writing to the pipe.
|
||||
*/
|
||||
while (refs) {
|
||||
char buf[42];
|
||||
for (i = 0; i < extra->nr; i++) {
|
||||
memcpy(buf + 1, sha1_to_hex(&extra->array[i][0]), 40);
|
||||
buf[0] = '^';
|
||||
buf[41] = '\n';
|
||||
if (!write_or_whine(po.in, buf, 42, "send-pack: send refs"))
|
||||
break;
|
||||
}
|
||||
|
||||
while (refs) {
|
||||
if (!is_null_sha1(refs->old_sha1) &&
|
||||
has_sha1_file(refs->old_sha1)) {
|
||||
memcpy(buf + 1, sha1_to_hex(refs->old_sha1), 40);
|
||||
|
@ -381,14 +389,17 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
|||
int expect_status_report = 0;
|
||||
int flags = MATCH_REFS_NONE;
|
||||
int ret;
|
||||
struct extra_have_objects extra_have;
|
||||
|
||||
memset(&extra_have, 0, sizeof(extra_have));
|
||||
if (args.send_all)
|
||||
flags |= MATCH_REFS_ALL;
|
||||
if (args.send_mirror)
|
||||
flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
/* No funny business with the matcher */
|
||||
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);
|
||||
remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
|
||||
&extra_have);
|
||||
get_local_heads();
|
||||
|
||||
/* Does the other end support the reporting? */
|
||||
|
@ -496,7 +507,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
|||
|
||||
packet_flush(out);
|
||||
if (new_refs && !args.dry_run) {
|
||||
if (pack_objects(out, remote_refs) < 0)
|
||||
if (pack_objects(out, remote_refs, &extra_have) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -79,6 +79,7 @@ extern int cmd_prune(int argc, const char **argv, const char *prefix);
|
|||
extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_push(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_reflog(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_remote(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_config(int argc, const char **argv, const char *prefix);
|
||||
|
|
9
cache.h
9
cache.h
|
@ -533,6 +533,7 @@ static inline int is_absolute_path(const char *path)
|
|||
{
|
||||
return path[0] == '/' || has_dos_drive_prefix(path);
|
||||
}
|
||||
int is_directory(const char *);
|
||||
const char *make_absolute_path(const char *path);
|
||||
const char *make_nonrelative_path(const char *path);
|
||||
const char *make_relative_path(const char *abs, const char *base);
|
||||
|
@ -640,6 +641,8 @@ extern struct alternate_object_database {
|
|||
} *alt_odb_list;
|
||||
extern void prepare_alt_odb(void);
|
||||
extern void add_to_alternates_file(const char *reference);
|
||||
typedef int alt_odb_fn(struct alternate_object_database *, void *);
|
||||
extern void foreach_alt_odb(alt_odb_fn, void*);
|
||||
|
||||
struct pack_window {
|
||||
struct pack_window *next;
|
||||
|
@ -708,7 +711,11 @@ extern struct child_process *git_connect(int fd[2], const char *url, const char
|
|||
extern int finish_connect(struct child_process *conn);
|
||||
extern int path_match(const char *path, int nr, char **match);
|
||||
extern int get_ack(int fd, unsigned char *result_sha1);
|
||||
extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags);
|
||||
struct extra_have_objects {
|
||||
int nr, alloc;
|
||||
unsigned char (*array)[20];
|
||||
};
|
||||
extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *);
|
||||
extern int server_supports(const char *feature);
|
||||
|
||||
extern struct packed_git *parse_pack_index(unsigned char *sha1);
|
||||
|
|
16
connect.c
16
connect.c
|
@ -41,12 +41,20 @@ int check_ref_type(const struct ref *ref, int flags)
|
|||
return check_ref(ref->name, strlen(ref->name), flags);
|
||||
}
|
||||
|
||||
static void add_extra_have(struct extra_have_objects *extra, unsigned char *sha1)
|
||||
{
|
||||
ALLOC_GROW(extra->array, extra->nr + 1, extra->alloc);
|
||||
hashcpy(&(extra->array[extra->nr][0]), sha1);
|
||||
extra->nr++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read all the refs from the other end
|
||||
*/
|
||||
struct ref **get_remote_heads(int in, struct ref **list,
|
||||
int nr_match, char **match,
|
||||
unsigned int flags)
|
||||
unsigned int flags,
|
||||
struct extra_have_objects *extra_have)
|
||||
{
|
||||
*list = NULL;
|
||||
for (;;) {
|
||||
|
@ -72,6 +80,12 @@ struct ref **get_remote_heads(int in, struct ref **list,
|
|||
server_capabilities = xstrdup(name + name_len + 1);
|
||||
}
|
||||
|
||||
if (extra_have &&
|
||||
name_len == 5 && !memcmp(".have", name, 5)) {
|
||||
add_extra_have(extra_have, old_sha1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!check_ref(name, name_len, flags))
|
||||
continue;
|
||||
if (nr_match && !path_match(name, nr_match, match))
|
||||
|
|
10
daemon.c
10
daemon.c
|
@ -1116,13 +1116,9 @@ int main(int argc, char **argv)
|
|||
if (strict_paths && (!ok_paths || !*ok_paths))
|
||||
die("option --strict-paths requires a whitelist");
|
||||
|
||||
if (base_path) {
|
||||
struct stat st;
|
||||
|
||||
if (stat(base_path, &st) || !S_ISDIR(st.st_mode))
|
||||
die("base-path '%s' does not exist or "
|
||||
"is not a directory", base_path);
|
||||
}
|
||||
if (base_path && !is_directory(base_path))
|
||||
die("base-path '%s' does not exist or is not a directory",
|
||||
base_path);
|
||||
|
||||
if (inetd_mode) {
|
||||
struct sockaddr_storage ss;
|
||||
|
|
1
git.c
1
git.c
|
@ -330,6 +330,7 @@ static void handle_internal_command(int argc, const char **argv)
|
|||
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
|
||||
{ "push", cmd_push, RUN_SETUP },
|
||||
{ "read-tree", cmd_read_tree, RUN_SETUP },
|
||||
{ "receive-pack", cmd_receive_pack },
|
||||
{ "reflog", cmd_reflog, RUN_SETUP },
|
||||
{ "remote", cmd_remote, RUN_SETUP },
|
||||
{ "repo-config", cmd_config },
|
||||
|
|
3
rerere.c
3
rerere.c
|
@ -319,7 +319,6 @@ static int git_rerere_config(const char *var, const char *value, void *cb)
|
|||
|
||||
static int is_rerere_enabled(void)
|
||||
{
|
||||
struct stat st;
|
||||
const char *rr_cache;
|
||||
int rr_cache_exists;
|
||||
|
||||
|
@ -327,7 +326,7 @@ static int is_rerere_enabled(void)
|
|||
return 0;
|
||||
|
||||
rr_cache = git_path("rr-cache");
|
||||
rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
|
||||
rr_cache_exists = is_directory(rr_cache);
|
||||
if (rerere_enabled < 0)
|
||||
return rr_cache_exists;
|
||||
|
||||
|
|
13
sha1_file.c
13
sha1_file.c
|
@ -254,7 +254,6 @@ static void read_info_alternates(const char * alternates, int depth);
|
|||
*/
|
||||
static int link_alt_odb_entry(const char * entry, int len, const char * relative_base, int depth)
|
||||
{
|
||||
struct stat st;
|
||||
const char *objdir = get_object_directory();
|
||||
struct alternate_object_database *ent;
|
||||
struct alternate_object_database *alt;
|
||||
|
@ -285,7 +284,7 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
|
|||
ent->base[pfxlen] = ent->base[entlen-1] = 0;
|
||||
|
||||
/* Detect cases where alternate disappeared */
|
||||
if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {
|
||||
if (!is_directory(ent->base)) {
|
||||
error("object directory %s does not exist; "
|
||||
"check .git/objects/info/alternates.",
|
||||
ent->base);
|
||||
|
@ -398,6 +397,16 @@ void add_to_alternates_file(const char *reference)
|
|||
link_alt_odb_entries(alt, alt + strlen(alt), '\n', NULL, 0);
|
||||
}
|
||||
|
||||
void foreach_alt_odb(alt_odb_fn fn, void *cb)
|
||||
{
|
||||
struct alternate_object_database *ent;
|
||||
|
||||
prepare_alt_odb();
|
||||
for (ent = alt_odb_list; ent; ent = ent->next)
|
||||
if (fn(ent, cb))
|
||||
return;
|
||||
}
|
||||
|
||||
void prepare_alt_odb(void)
|
||||
{
|
||||
const char *alt;
|
||||
|
|
|
@ -619,7 +619,7 @@ static struct ref *get_refs_via_connect(struct transport *transport)
|
|||
struct ref *refs;
|
||||
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL, 0);
|
||||
get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
@ -652,7 +652,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
|||
|
||||
if (!data->conn) {
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
refs = fetch_pack(&args, data->fd, data->conn,
|
||||
|
|
Загрузка…
Ссылка в новой задаче