/* 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_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);
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;
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)
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)) {
*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;