#include "cache.h"
#include "commit.h"
#include "pack.h"
-#include "fetch.h"
#include "tag.h"
#include "blob.h"
#include "http.h"
#include "diff.h"
#include "revision.h"
#include "exec_cmd.h"
+#include "remote.h"
#include <expat.h>
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5
-static int pushing = 0;
-static int aborted = 0;
+static int pushing;
+static int aborted;
static signed char remote_dir_exists[256];
static struct curl_slist *no_pragma_header;
static struct curl_slist *default_headers;
-static int push_verbosely = 0;
-static int push_all = 0;
-static int force_all = 0;
+static int push_verbosely;
+static int push_all;
+static int force_all;
-static struct object_list *objects = NULL;
+static struct object_list *objects;
struct repo
{
struct remote_lock *locks;
};
-static struct repo *remote = NULL;
+static struct repo *remote;
enum transfer_state {
NEED_FETCH,
struct transfer_request *next;
};
-static struct transfer_request *request_queue_head = NULL;
+static struct transfer_request *request_queue_head;
struct xml_ctx
{
int posn = 0;
struct transfer_request *request = (struct transfer_request *)data;
do {
- ssize_t retval = write(request->local_fileno,
+ ssize_t retval = xwrite(request->local_fileno,
(char *) ptr + posn, size - posn);
if (retval < 0)
return posn;
prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) {
do {
- prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
+ prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) {
if (fwrite_sha1_file(prev_buf,
1,
SHA1_Init(&request->c);
if (prev_posn>0) {
prev_posn = 0;
- lseek(request->local_fileno, SEEK_SET, 0);
+ lseek(request->local_fileno, 0, SEEK_SET);
ftruncate(request->local_fileno, 0);
}
}
char *hex = sha1_to_hex(request->obj->sha1);
struct active_request_slot *slot;
char *posn;
- char type[20];
+ enum object_type type;
char hdr[50];
void *unpacked;
unsigned long len;
ssize_t size;
z_stream stream;
- unpacked = read_sha1_file(request->obj->sha1, type, &len);
- hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
+ unpacked = read_sha1_file(request->obj->sha1, &type, &len);
+ hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
/* Set it up */
memset(&stream, 0, sizeof(stream));
request->buffer.size = stream.total_out;
request->buffer.posn = 0;
- request->url = xmalloc(strlen(remote->url) +
+ request->url = xmalloc(strlen(remote->url) +
strlen(request->lock->token) + 51);
strcpy(request->url, remote->url);
posn = request->url + strlen(remote->url);
request->dest = xmalloc(strlen(request->url) + 14);
sprintf(request->dest, "Destination: %s", request->url);
posn += 38;
- *(posn++) = '.';
+ *(posn++) = '_';
strcpy(posn, request->lock->token);
slot = get_active_slot();
SHA1_Final(request->real_sha1, &request->c);
if (request->zret != Z_STREAM_END) {
unlink(request->tmpfile);
- } else if (memcmp(request->obj->sha1, request->real_sha1, 20)) {
+ } else if (hashcmp(request->obj->sha1, request->real_sha1)) {
unlink(request->tmpfile);
} else {
request->rename =
request->url, curl_errorstr);
remote->can_update_info_refs = 0;
} else {
+ off_t pack_size = ftell(request->local_stream);
+
fclose(request->local_stream);
request->local_stream = NULL;
if (!move_temp_to_file(request->tmpfile,
request->filename)) {
target = (struct packed_git *)request->userData;
+ target->pack_size = pack_size;
lst = &remote->packs;
while (*lst != target)
lst = &((*lst)->next);
}
#ifdef USE_CURL_MULTI
-void fill_active_slots(void)
+static int fill_active_slot(void *unused)
{
struct transfer_request *request = request_queue_head;
- struct transfer_request *next;
- struct active_request_slot *slot = active_queue_head;
- int num_transfers;
if (aborted)
- return;
+ return 0;
- while (active_requests < max_requests && request != NULL) {
- next = request->next;
+ for (request = request_queue_head; request; request = request->next) {
if (request->state == NEED_FETCH) {
start_fetch_loose(request);
+ return 1;
} else if (pushing && request->state == NEED_PUSH) {
if (remote_dir_exists[request->obj->sha1[0]] == 1) {
start_put(request);
} else {
start_mkcol(request);
}
- curl_multi_perform(curlm, &num_transfers);
- }
- request = next;
- }
-
- while (slot != NULL) {
- if (!slot->in_use && slot->curl != NULL) {
- curl_easy_cleanup(slot->curl);
- slot->curl = NULL;
+ return 1;
}
- slot = slot->next;
}
+ return 0;
}
#endif
case 'P':
i++;
if (i + 52 < buffer.posn &&
- !strncmp(data + i, " pack-", 6) &&
- !strncmp(data + i + 46, ".pack\n", 6)) {
+ !prefixcmp(data + i, " pack-") &&
+ !prefixcmp(data + i + 46, ".pack\n")) {
get_sha1_hex(data + i + 6, sha1);
setup_index(sha1);
i += 51;
lock->owner = xmalloc(strlen(ctx->cdata) + 1);
strcpy(lock->owner, ctx->cdata);
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
- if (!strncmp(ctx->cdata, "Second-", 7))
+ if (!prefixcmp(ctx->cdata, "Second-"))
lock->timeout =
strtol(ctx->cdata + 7, NULL, 10);
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
- if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
+ if (!prefixcmp(ctx->cdata, "opaquelocktoken:")) {
lock->token = xmalloc(strlen(ctx->cdata) - 15);
strcpy(lock->token, ctx->cdata + 16);
}
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);
}
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);
+ /* NB: 's' is not null-terminated, can not use strlcpy here */
+ memcpy(ctx->cdata, s, len);
+ ctx->cdata[len] = '\0';
}
static struct remote_lock *lock_remote(const char *path, long timeout)
sprintf(url, "%s%s", remote->url, path);
/* Make sure leading directories exist for the remote ref */
- ep = strchr(url + strlen(remote->url) + 11, '/');
+ ep = strchr(url + strlen(remote->url) + 1, '/');
while (ep) {
*ep = 0;
slot = get_active_slot();
return;
path += 8;
obj_hex = xmalloc(strlen(path));
- strlcpy(obj_hex, path, 3);
+ /* NB: path is not null-terminated, can not use strlcpy here */
+ memcpy(obj_hex, path, 2);
strcpy(obj_hex + 2, path + 3);
one_remote_object(obj_hex);
free(obj_hex);
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;
}
struct remote_ls_ctx ls;
ls.flags = flags;
- ls.path = strdup(path);
+ ls.path = xstrdup(path);
ls.dentry_name = NULL;
ls.dentry_flags = 0;
ls.userData = userData;
return lock_flags;
}
-struct object_list **add_one_object(struct object *obj, struct object_list **p)
+static struct object_list **add_one_object(struct object *obj, struct object_list **p)
{
struct object_list *entry = xmalloc(sizeof(struct object_list));
entry->item = obj;
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
- name = strdup(name);
+ name = xstrdup(name);
p = add_one_object(obj, p);
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
- desc.buf = tree->buffer;
- desc.size = tree->size;
+ init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
if (obj->flags & (UNINTERESTING | SEEN))
continue;
- if (obj->type == TYPE_TAG) {
+ if (obj->type == OBJ_TAG) {
obj->flags |= SEEN;
p = add_one_object(obj, p);
continue;
}
- if (obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_TREE) {
p = process_tree((struct tree *)obj, p, NULL, name);
continue;
}
- if (obj->type == TYPE_BLOB) {
+ if (obj->type == OBJ_BLOB) {
p = process_blob((struct blob *)obj, p, NULL, name);
continue;
}
static struct ref *local_refs, **local_tail;
static struct ref *remote_refs, **remote_tail;
-static int one_local_ref(const char *refname, const unsigned char *sha1)
+static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
struct ref *ref;
int len = strlen(refname) + 1;
ref = xcalloc(1, sizeof(*ref) + len);
- memcpy(ref->new_sha1, sha1, 20);
+ hashcpy(ref->new_sha1, sha1);
memcpy(ref->name, refname, len);
*local_tail = ref;
local_tail = &ref->next;
}
ref = xcalloc(1, sizeof(*ref) + len);
- memcpy(ref->old_sha1, remote_sha1, 20);
+ hashcpy(ref->old_sha1, remote_sha1);
memcpy(ref->name, refname, len);
*remote_tail = ref;
remote_tail = &ref->next;
static void get_local_heads(void)
{
local_tail = &local_refs;
- for_each_ref(one_local_ref);
+ for_each_ref(one_local_ref, NULL);
}
static void get_dav_remote_heads(void)
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
o = deref_tag(parse_object(new_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
fwrite_buffer(ref_info, 1, len, buf);
free(ref_info);
- if (o->type == TYPE_TAG) {
+ if (o->type == OBJ_TAG) {
o = deref_tag(o, ls->dentry_name, 0);
if (o) {
len = strlen(ls->dentry_name) + 45;
if (*symref != NULL)
free(*symref);
*symref = NULL;
- memset(sha1, 0, 20);
+ hashclr(sha1);
if (buffer.posn == 0)
return;
/* If it's a symref, set the refname; otherwise try for a sha1 */
- if (!strncmp((char *)buffer.buffer, "ref: ", 5)) {
+ if (!prefixcmp((char *)buffer.buffer, "ref: ")) {
*symref = xmalloc(buffer.posn - 5);
- strlcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5);
+ memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6);
+ (*symref)[buffer.posn - 6] = '\0';
} else {
get_sha1_hex(buffer.buffer, sha1);
}
static int verify_merge_base(unsigned char *head_sha1, unsigned char *branch_sha1)
{
- int pipe_fd[2];
- pid_t merge_base_pid;
- char line[PATH_MAX + 20];
- unsigned char merge_sha1[20];
- int verified = 0;
-
- if (pipe(pipe_fd) < 0)
- die("Verify merge base: pipe failed");
-
- merge_base_pid = fork();
- if (!merge_base_pid) {
- static const char *args[] = {
- "merge-base",
- "-a",
- NULL,
- NULL,
- NULL
- };
- args[2] = strdup(sha1_to_hex(head_sha1));
- args[3] = sha1_to_hex(branch_sha1);
-
- dup2(pipe_fd[1], 1);
- close(pipe_fd[0]);
- close(pipe_fd[1]);
- execv_git_cmd(args);
- die("merge-base setup failed");
- }
- if (merge_base_pid < 0)
- die("merge-base fork failed");
-
- dup2(pipe_fd[0], 0);
- close(pipe_fd[0]);
- close(pipe_fd[1]);
- while (fgets(line, sizeof(line), stdin) != NULL) {
- if (get_sha1_hex(line, merge_sha1))
- die("expected sha1, got garbage:\n %s", line);
- if (!memcmp(branch_sha1, merge_sha1, 20)) {
- verified = 1;
- break;
- }
- }
+ struct commit *head = lookup_commit(head_sha1);
+ struct commit *branch = lookup_commit(branch_sha1);
+ struct commit_list *merge_bases = get_merge_bases(head, branch, 1);
- return verified;
+ return (merge_bases && !merge_bases->next && merge_bases->item == branch);
}
static int delete_remote_branch(char *pattern, int force)
struct ref *ref;
setup_git_directory();
- setup_ident();
remote = xcalloc(sizeof(*remote), 1);
if (!ref->peer_ref)
continue;
- if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
+ if (!hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
if (push_verbosely || 1)
fprintf(stderr, "'%s': up-to-date\n", ref->name);
continue;
continue;
}
}
- memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
if (is_zero_sha1(ref->new_sha1)) {
error("cannot happen anymore");
rc = -3;
/* Set up revision info for this refspec */
commit_argc = 3;
- new_sha1_hex = strdup(sha1_to_hex(ref->new_sha1));
+ new_sha1_hex = xstrdup(sha1_to_hex(ref->new_sha1));
old_sha1_hex = NULL;
commit_argv[1] = "--objects";
commit_argv[2] = new_sha1_hex;
commit_argv[3] = old_sha1_hex;
commit_argc++;
}
- init_revisions(&revs);
+ init_revisions(&revs, setup_git_directory());
setup_revisions(commit_argc, commit_argv, &revs, NULL);
free(new_sha1_hex);
if (old_sha1_hex) {
objects_to_send);
#ifdef USE_CURL_MULTI
fill_active_slots();
+ add_fill_function(NULL, fill_active_slot);
#endif
finish_all_active_slots();