static int do_pick_commit(struct commit *commit, struct replay_opts *opts) { unsigned char head[20]; struct commit *base, *next, *parent; const char *base_label, *next_label; struct commit_message msg = { NULL, NULL, NULL, NULL, NULL }; char *defmsg = NULL; struct strbuf msgbuf = STRBUF_INIT; int res, unborn = 0, allow; if (opts->no_commit) { /* * We do not intend to commit immediately. We just want to * merge the differences in, so let's compute the tree * that represents the "current" state for merge-recursive * to work on. */ if (write_cache_as_tree(head, 0, NULL)) die (_("Your index file is unmerged.")); } else { unborn = get_sha1("HEAD", head); if (unborn) hashcpy(head, EMPTY_TREE_SHA1_BIN); if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0)) return error_dirty_index(opts); } discard_cache(); if (!commit->parents) { parent = NULL; } else if (commit->parents->next) { /* Reverting or cherry-picking a merge commit */ int cnt; struct commit_list *p; if (!opts->mainline) return error(_("Commit %s is a merge but no -m option was given."), sha1_to_hex(commit->object.sha1)); for (cnt = 1, p = commit->parents; cnt != opts->mainline && p; cnt++) p = p->next; if (cnt != opts->mainline || !p) return error(_("Commit %s does not have parent %d"), sha1_to_hex(commit->object.sha1), opts->mainline); parent = p->item; } else if (0 < opts->mainline) return error(_("Mainline was specified but commit %s is not a merge."), sha1_to_hex(commit->object.sha1)); else parent = commit->parents->item; if (opts->allow_ff && ((parent && !hashcmp(parent->object.sha1, head)) || (!parent && unborn))) return fast_forward_to(commit->object.sha1, head, unborn, opts); if (parent && parse_commit(parent) < 0) /* TRANSLATORS: The first %s will be "revert" or "cherry-pick", the second %s a SHA1 */ return error(_("%s: cannot parse parent commit %s"), action_name(opts), sha1_to_hex(parent->object.sha1)); if (get_message(commit, &msg) != 0) return error(_("Cannot get commit message for %s"), sha1_to_hex(commit->object.sha1)); /* * "commit" is an existing commit. We would want to apply * the difference it introduces since its first parent "prev" * on top of the current HEAD if we are cherry-pick. Or the * reverse of it if we are revert. */ defmsg = git_pathdup("MERGE_MSG"); if (opts->action == REPLAY_REVERT) { base = commit; base_label = msg.label; next = parent; next_label = msg.parent_label; strbuf_addstr(&msgbuf, "Revert \""); strbuf_addstr(&msgbuf, msg.subject); strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit "); strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1)); if (commit->parents && commit->parents->next) { strbuf_addstr(&msgbuf, ", reversing\nchanges made to "); strbuf_addstr(&msgbuf, sha1_to_hex(parent->object.sha1)); } strbuf_addstr(&msgbuf, ".\n"); } else { const char *p; base = parent; base_label = msg.parent_label; next = commit; next_label = msg.label; /* * Append the commit log message to msgbuf; it starts * after the tree, parent, author, committer * information followed by "\n\n". */ p = strstr(msg.message, "\n\n"); if (p) { p += 2; strbuf_addstr(&msgbuf, p); } if (opts->record_origin) { if (!has_conforming_footer(&msgbuf, NULL, 0)) strbuf_addch(&msgbuf, '\n'); strbuf_addstr(&msgbuf, cherry_picked_prefix); strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1)); strbuf_addstr(&msgbuf, ")\n"); } } if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REPLAY_REVERT) { res = do_recursive_merge(base, next, base_label, next_label, head, &msgbuf, opts); write_message(&msgbuf, defmsg); } else { struct commit_list *common = NULL; struct commit_list *remotes = NULL; write_message(&msgbuf, defmsg); commit_list_insert(base, &common); commit_list_insert(next, &remotes); res = try_merge_command(opts->strategy, opts->xopts_nr, opts->xopts, common, sha1_to_hex(head), remotes); free_commit_list(common); free_commit_list(remotes); } /* * If the merge was clean or if it failed due to conflict, we write * CHERRY_PICK_HEAD for the subsequent invocation of commit to use. * However, if the merge did not even start, then we don't want to * write it at all. */ if (opts->action == REPLAY_PICK && !opts->no_commit && (res == 0 || res == 1)) write_cherry_pick_head(commit, "CHERRY_PICK_HEAD"); if (opts->action == REPLAY_REVERT && ((opts->no_commit && res == 0) || res == 1)) write_cherry_pick_head(commit, "REVERT_HEAD"); if (res) { error(opts->action == REPLAY_REVERT ? _("could not revert %s... %s") : _("could not apply %s... %s"), find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), msg.subject); print_advice(res == 1, opts); rerere(opts->allow_rerere_auto); goto leave; } allow = allow_empty(opts, commit); if (allow < 0) { res = allow; goto leave; } if (!opts->no_commit) res = run_git_commit(defmsg, opts, allow); leave: free_message(&msg); free(defmsg); return res; }
void replay_log_event (void) { int *start = rptr; in_replay_log = 1; assert (rptr < wptr); int op = *rptr; if (verbosity >= 2) { logprintf ("log_pos %lld, op 0x%08x\n", binlog_pos, op); } in_ptr = rptr; in_end = wptr; switch (op) { case LOG_START: rptr ++; break; case CODE_binlog_dc_option: in_ptr ++; { int id = fetch_int (); int l1 = prefetch_strlen (); char *name = fetch_str (l1); int l2 = prefetch_strlen (); char *ip = fetch_str (l2); int port = fetch_int (); if (verbosity) { logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port); } alloc_dc (id, strndup (ip, l2), port); } rptr = in_ptr; break; case LOG_AUTH_KEY: rptr ++; { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); assert (DC_list[num]); DC_list[num]->auth_key_id = *(long long *)rptr; rptr += 2; memcpy (DC_list[num]->auth_key, rptr, 256); rptr += 64; DC_list[num]->flags |= 1; }; break; case LOG_DEFAULT_DC: rptr ++; { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); DC_working = DC_list[num]; dc_working_num = num; } break; case LOG_OUR_ID: rptr ++; { our_id = *(rptr ++); } break; case LOG_DC_SIGNED: rptr ++; { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); assert (DC_list[num]); DC_list[num]->has_auth = 1; } break; case LOG_DC_SALT: rptr ++; { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); assert (DC_list[num]); DC_list[num]->server_salt = *(long long *)rptr; rptr += 2; }; break; /* case CODE_user_empty: case CODE_user_self: case CODE_user_contact: case CODE_user_request: case CODE_user_foreign: case CODE_user_deleted: fetch_alloc_user (); rptr = in_ptr; break;*/ case LOG_DH_CONFIG: get_dh_config_on_answer (0); rptr = in_ptr; break; case LOG_ENCR_CHAT_KEY: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); assert (U); U->key_fingerprint = *(long long *)rptr; rptr += 2; memcpy (U->key, rptr, 256); rptr += 64; }; break; case LOG_ENCR_CHAT_SEND_ACCEPT: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); assert (U); U->key_fingerprint = *(long long *)rptr; rptr += 2; memcpy (U->key, rptr, 256); rptr += 64; if (!U->g_key) { U->g_key = malloc (256); } memcpy (U->g_key, rptr, 256); rptr += 64; }; break; case LOG_ENCR_CHAT_SEND_CREATE: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); assert (!U || !(U->flags & FLAG_CREATED)); if (!U) { U = malloc (sizeof (peer_t)); memset (U, 0, sizeof (peer_t)); U->id = id; insert_encrypted_chat ((void *)U); } U->flags |= FLAG_CREATED; U->user_id = *(rptr ++); memcpy (U->key, rptr, 256); rptr += 64; if (!U->print_name) { peer_t *P = user_chat_get (MK_USER (U->user_id)); if (P) { U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0); } else { static char buf[100]; sprintf (buf, "user#%d", U->user_id); U->print_name = create_print_name (U->id, "!", buf, 0, 0); } } }; break; case LOG_ENCR_CHAT_DELETED: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); if (!U) { U = malloc (sizeof (peer_t)); memset (U, 0, sizeof (peer_t)); U->id = id; insert_encrypted_chat ((void *)U); } U->flags |= FLAG_CREATED; U->state = sc_deleted; }; break; case LOG_ENCR_CHAT_WAITING: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); assert (U); U->state = sc_waiting; U->date = *(rptr ++); U->admin_id = *(rptr ++); U->user_id = *(rptr ++); U->access_hash = *(long long *)rptr; rptr += 2; }; break; case LOG_ENCR_CHAT_REQUESTED: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); if (!U) { U = malloc (sizeof (peer_t)); memset (U, 0, sizeof (peer_t)); U->id = id; insert_encrypted_chat ((void *)U); } U->flags |= FLAG_CREATED; U->state = sc_request; U->date = *(rptr ++); U->admin_id = *(rptr ++); U->user_id = *(rptr ++); U->access_hash = *(long long *)rptr; if (!U->print_name) { peer_t *P = user_chat_get (MK_USER (U->user_id)); if (P) { U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0); } else { static char buf[100]; sprintf (buf, "user#%d", U->user_id); U->print_name = create_print_name (U->id, "!", buf, 0, 0); } } rptr += 2; }; break; case LOG_ENCR_CHAT_OK: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); struct secret_chat *U = (void *)user_chat_get (id); assert (U); U->state = sc_ok; } break; case CODE_binlog_new_user: in_ptr ++; { peer_id_t id = MK_USER (fetch_int ()); peer_t *_U = user_chat_get (id); if (!_U) { _U = malloc (sizeof (*_U)); memset (_U, 0, sizeof (*_U)); _U->id = id; insert_user (_U); } else { assert (!(_U->flags & FLAG_CREATED)); } struct user *U = (void *)_U; U->flags |= FLAG_CREATED; if (get_peer_id (id) == our_id) { U->flags |= FLAG_USER_SELF; } U->first_name = fetch_str_dup (); U->last_name = fetch_str_dup (); U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0); U->access_hash = fetch_long (); U->phone = fetch_str_dup (); if (fetch_int ()) { U->flags |= FLAG_USER_CONTACT; } } rptr = in_ptr; break; case CODE_binlog_user_delete: rptr ++; { peer_id_t id = MK_USER (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->flags |= FLAG_DELETED; } break; case CODE_binlog_set_user_access_token: rptr ++; { peer_id_t id = MK_USER (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->user.access_hash = *(long long *)rptr; rptr += 2; } break; case CODE_binlog_set_user_phone: in_ptr ++; { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); assert (U); if (U->user.phone) { free (U->user.phone); } U->user.phone = fetch_str_dup (); } rptr = in_ptr; break; case CODE_binlog_set_user_friend: rptr ++; { peer_id_t id = MK_USER (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); int friend = *(rptr ++); if (friend) { U->flags |= FLAG_USER_CONTACT; } else { U->flags &= ~FLAG_USER_CONTACT; } } break; case CODE_binlog_user_full_photo: in_ptr ++; { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); assert (U); if (U->flags & FLAG_HAS_PHOTO) { free_photo (&U->user.photo); } fetch_photo (&U->user.photo); } rptr = in_ptr; break; case CODE_binlog_user_blocked: rptr ++; { peer_id_t id = MK_USER (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->user.blocked = *(rptr ++); } break; case CODE_binlog_set_user_full_name: in_ptr ++; { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); assert (U); if (U->user.real_first_name) { free (U->user.real_first_name); } if (U->user.real_last_name) { free (U->user.real_last_name); } U->user.real_first_name = fetch_str_dup (); U->user.real_last_name = fetch_str_dup (); } rptr = in_ptr; break; case CODE_binlog_encr_chat_delete: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *_U = user_chat_get (id); assert (_U); struct secret_chat *U = &_U->encr_chat; memset (U->key, 0, sizeof (U->key)); U->flags |= FLAG_DELETED; U->state = sc_deleted; if (U->nonce) { memset (U->nonce, 0, 256); free (U->nonce); U->nonce = 0; } if (U->g_key) { memset (U->g_key, 0, 256); free (U->g_key); U->g_key = 0; } } break; case CODE_binlog_encr_chat_requested: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *_U = user_chat_get (id); if (!_U) { _U = malloc (sizeof (*_U)); memset (_U, 0, sizeof (*_U)); _U->id = id; insert_encrypted_chat (_U); } else { assert (!(_U->flags & FLAG_CREATED)); } struct secret_chat *U = (void *)_U; U->access_hash = *(long long *)rptr; rptr += 2; U->date = *(rptr ++); U->admin_id = *(rptr ++); U->user_id = *(rptr ++); peer_t *Us = user_chat_get (MK_USER (U->user_id)); if (Us) { U->print_name = create_print_name (id, "!", Us->user.first_name, Us->user.last_name, 0); } else { static char buf[20]; sprintf (buf, "user#%d", U->user_id); U->print_name = create_print_name (id, "!", buf, 0, 0); } U->g_key = malloc (256); U->nonce = malloc (256); memcpy (U->g_key, rptr, 256); rptr += 64; memcpy (U->nonce, rptr, 256); rptr += 64; U->flags |= FLAG_CREATED; U->state = sc_request; } break; case CODE_binlog_set_encr_chat_access_hash: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->encr_chat.access_hash = *(long long *)rptr; rptr += 2; } break; case CODE_binlog_set_encr_chat_date: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->encr_chat.date = *(rptr ++); } break; case CODE_binlog_set_encr_chat_state: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *U = user_chat_get (id); assert (U); U->encr_chat.state = *(rptr ++); } break; case CODE_binlog_encr_chat_accepted: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *_U = user_chat_get (id); assert (_U); struct secret_chat *U = &_U->encr_chat; if (!U->g_key) { U->g_key = malloc (256); } if (!U->nonce) { U->nonce = malloc (256); } memcpy (U->g_key, rptr, 256); rptr += 64; memcpy (U->nonce, rptr, 256); rptr += 64; U->key_fingerprint = *(long long *)rptr; rptr += 2; if (U->state == sc_waiting) { do_create_keys_end (U); } U->state = sc_ok; } break; case CODE_binlog_set_encr_chat_key: rptr ++; { peer_id_t id = MK_ENCR_CHAT (*(rptr ++)); peer_t *_U = user_chat_get (id); assert (_U); struct secret_chat *U = &_U->encr_chat; memcpy (U->key, rptr, 256); rptr += 64; U->key_fingerprint = *(long long *)rptr; rptr += 2; } break; case CODE_binlog_set_dh_params: rptr ++; { if (encr_prime) { free (encr_prime); } encr_root = *(rptr ++); encr_prime = malloc (256); memcpy (encr_prime, rptr, 256); rptr += 64; encr_param_version = *(rptr ++); } break; case CODE_binlog_encr_chat_init: rptr ++; { peer_t *P = malloc (sizeof (*P)); memset (P, 0, sizeof (*P)); P->id = MK_ENCR_CHAT (*(rptr ++)); assert (!user_chat_get (P->id)); P->encr_chat.user_id = *(rptr ++); P->encr_chat.admin_id = our_id; insert_encrypted_chat (P); peer_t *Us = user_chat_get (MK_USER (P->encr_chat.user_id)); assert (Us); P->print_name = create_print_name (P->id, "!", Us->user.first_name, Us->user.last_name, 0); memcpy (P->encr_chat.key, rptr, 256); rptr += 64; P->encr_chat.g_key = malloc (256); memcpy (P->encr_chat.g_key, rptr, 256); rptr += 64; P->flags |= FLAG_CREATED; } break; case CODE_binlog_set_pts: rptr ++; pts = *(rptr ++); break; case CODE_binlog_set_qts: rptr ++; qts = *(rptr ++); break; case CODE_binlog_set_date: rptr ++; last_date = *(rptr ++); break; case CODE_binlog_set_seq: rptr ++; seq = *(rptr ++); break; case CODE_binlog_chat_create: in_ptr ++; { peer_id_t id = MK_CHAT (fetch_int ()); peer_t *_C = user_chat_get (id); if (!_C) { _C = malloc (sizeof (*_C)); memset (_C, 0, sizeof (*_C)); _C->id = id; insert_chat (_C); } else { assert (!(_C->flags & FLAG_CREATED)); } struct chat *C = &_C->chat; C->flags = FLAG_CREATED | fetch_int (); C->title = fetch_str_dup (); C->print_title = create_print_name (id, C->title, 0, 0, 0); C->users_num = fetch_int (); C->date = fetch_int (); C->version = fetch_int (); fetch_data (&C->photo_big, sizeof (struct file_location)); fetch_data (&C->photo_small, sizeof (struct file_location)); }; rptr = in_ptr; break; case CODE_binlog_chat_change_flags: rptr ++; { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->flags |= *(rptr ++); C->flags &= ~*(rptr ++); }; break; case CODE_binlog_set_chat_title: in_ptr ++; { peer_t *_C = user_chat_get (MK_CHAT (fetch_int ())); assert (_C && (_C->flags & FLAG_CREATED)); struct chat *C = &_C->chat; if (C->title) { free (C->title); } C->title = fetch_str_dup (); C->print_title = create_print_name (C->id, C->title, 0, 0, 0); }; rptr = in_ptr; break; case CODE_binlog_set_chat_photo: in_ptr ++; { peer_t *C = user_chat_get (MK_CHAT (fetch_int ())); assert (C && (C->flags & FLAG_CREATED)); fetch_data (&C->photo_big, sizeof (struct file_location)); fetch_data (&C->photo_small, sizeof (struct file_location)); }; rptr = in_ptr; break; case CODE_binlog_set_chat_date: rptr ++; { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.date = *(rptr ++); }; break; case CODE_binlog_set_chat_version: rptr ++; { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.version = *(rptr ++); C->chat.users_num = *(rptr ++); }; break; case CODE_binlog_set_chat_admin: rptr ++; { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.admin_id = *(rptr ++); }; break; case CODE_binlog_set_chat_participants: rptr ++; { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.user_list_version = *(rptr ++); C->chat.user_list_size = *(rptr ++); if (C->chat.user_list) { free (C->chat.user_list); } C->chat.user_list = malloc (12 * C->chat.user_list_size); memcpy (C->chat.user_list, rptr, 12 * C->chat.user_list_size); rptr += 3 * C->chat.user_list_size; }; break; case CODE_binlog_chat_full_photo: in_ptr ++; { peer_id_t id = MK_CHAT (fetch_int ()); peer_t *U = user_chat_get (id); assert (U && (U->flags & FLAG_CREATED)); if (U->flags & FLAG_HAS_PHOTO) { free_photo (&U->chat.photo); } fetch_photo (&U->chat.photo); } rptr = in_ptr; break; case CODE_binlog_add_chat_participant: rptr ++; { peer_id_t id = MK_CHAT (*(rptr ++)); peer_t *_C = user_chat_get (id); assert (_C && (_C->flags & FLAG_CREATED)); struct chat *C = &_C->chat; int version = *(rptr ++); int user = *(rptr ++); int inviter = *(rptr ++); int date = *(rptr ++); assert (C->user_list_version < version); int i; for (i = 0; i < C->user_list_size; i++) { assert (C->user_list[i].user_id != user); } C->user_list_size ++; C->user_list = realloc (C->user_list, 12 * C->user_list_size); C->user_list[C->user_list_size - 1].user_id = user; C->user_list[C->user_list_size - 1].inviter_id = inviter; C->user_list[C->user_list_size - 1].date = date; C->user_list_version = version; } break; case CODE_binlog_del_chat_participant: rptr ++; { peer_id_t id = MK_CHAT (*(rptr ++)); peer_t *_C = user_chat_get (id); assert (_C && (_C->flags & FLAG_CREATED)); struct chat *C = &_C->chat; int version = *(rptr ++); int user = *(rptr ++); assert (C->user_list_version < version); int i; for (i = 0; i < C->user_list_size; i++) { if (C->user_list[i].user_id == user) { struct chat_user t; t = C->user_list[i]; C->user_list[i] = C->user_list[C->user_list_size - 1]; C->user_list[C->user_list_size - 1] = t; } } assert (C->user_list[C->user_list_size - 1].user_id == user); C->user_list_size --; C->user_list = realloc (C->user_list, 12 * C->user_list_size); C->user_list_version = version; } break; case CODE_binlog_create_message_text: case CODE_binlog_send_message_text: in_ptr ++; { long long id; if (op == CODE_binlog_create_message_text) { id = fetch_int (); } else { id = fetch_long (); } struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); if (t == PEER_ENCR_CHAT) { M->flags |= FLAG_ENCRYPTED; } M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); int l = prefetch_strlen (); M->message = malloc (l + 1); memcpy (M->message, fetch_str (l), l); M->message[l] = 0; M->message_len = l; if (t == PEER_ENCR_CHAT) { M->media.type = CODE_decrypted_message_media_empty; } else { M->media.type = CODE_message_media_empty; } M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; message_insert (M); if (op == CODE_binlog_send_message_text) { message_insert_unsent (M); M->flags |= FLAG_PENDING; } } rptr = in_ptr; break; case CODE_binlog_create_message_text_fwd: in_ptr ++; { int id = fetch_int (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); M->fwd_from_id = MK_USER (fetch_int ()); M->fwd_date = fetch_int (); int l = prefetch_strlen (); M->message = malloc (l + 1); memcpy (M->message, fetch_str (l), l); M->message[l] = 0; M->message_len = l; M->media.type = CODE_message_media_empty; M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_media: in_ptr ++; { int id = fetch_int (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); int l = prefetch_strlen (); M->message = malloc (l + 1); memcpy (M->message, fetch_str (l), l); M->message[l] = 0; M->message_len = l; fetch_message_media (&M->media); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_media_encr: in_ptr ++; { long long id = fetch_long (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED | FLAG_ENCRYPTED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); int l = prefetch_strlen (); M->message = malloc (l + 1); memcpy (M->message, fetch_str (l), l); M->message[l] = 0; M->message_len = l; fetch_message_media_encrypted (&M->media); fetch_encrypted_message_file (&M->media); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_media_fwd: in_ptr ++; { int id = fetch_int (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); M->fwd_from_id = MK_USER (fetch_int ()); M->fwd_date = fetch_int (); int l = prefetch_strlen (); M->message = malloc (l + 1); memcpy (M->message, fetch_str (l), l); M->message[l] = 0; M->message_len = l; fetch_message_media (&M->media); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_service: in_ptr ++; { int id = fetch_int (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); fetch_message_action (&M->action); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; M->service = 1; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_service_encr: in_ptr ++; { long long id = fetch_long (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED | FLAG_ENCRYPTED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); fetch_message_action_encrypted (&M->action); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; M->service = 1; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_create_message_service_fwd: in_ptr ++; { int id = fetch_int (); struct message *M = message_get (id); if (!M) { M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); M->id = id; message_insert_tree (M); messages_allocated ++; } else { assert (!(M->flags & FLAG_CREATED)); } M->flags |= FLAG_CREATED; M->from_id = MK_USER (fetch_int ()); int t = fetch_int (); M->to_id = set_peer_id (t, fetch_int ()); M->date = fetch_int (); M->fwd_from_id = MK_USER (fetch_int ()); M->fwd_date = fetch_int (); fetch_message_action (&M->action); M->unread = 1; M->out = get_peer_id (M->from_id) == our_id; M->service = 1; message_insert (M); } rptr = in_ptr; break; case CODE_binlog_set_unread: rptr ++; { struct message *M = message_get (*(rptr ++)); assert (M); M->unread = 0; } break; case CODE_binlog_set_message_sent: rptr ++; { struct message *M = message_get (*(long long *)rptr); rptr += 2; assert (M); message_remove_unsent (M); M->flags &= ~FLAG_PENDING; } break; case CODE_binlog_set_msg_id: rptr ++; { struct message *M = message_get (*(long long *)rptr); rptr += 2; assert (M); if (M->flags & FLAG_PENDING) { message_remove_unsent (M); M->flags &= ~FLAG_PENDING; } message_remove_tree (M); message_del_peer (M); M->id = *(rptr ++); if (message_get (M->id)) { free_message (M); free (M); } else { message_insert_tree (M); message_add_peer (M); } } break; case CODE_binlog_delete_msg: rptr ++; { struct message *M = message_get (*(long long *)rptr); rptr += 2; assert (M); if (M->flags & FLAG_PENDING) { message_remove_unsent (M); M->flags &= ~FLAG_PENDING; } message_remove_tree (M); message_del_peer (M); free_message (M); free (M); } break; case CODE_update_user_photo: case CODE_update_user_name: work_update_binlog (); rptr = in_ptr; break; default: logprintf ("Unknown logevent [0x%08x] 0x%08x [0x%08x] at %lld\n", *(rptr - 1), op, *(rptr + 1), binlog_pos); assert (0); }
int start_command(JNIEnv *env, jclass clazz __attribute__((unused)), jstring jhandler, jstring jcmd, jobjectArray jenv) { const char *utf; handler *h; int id; struct cmd_start_info *start_info; message *m; child_node *c; id = -1; m=NULL; c=NULL; utf=NULL; if(!authenticated()) { LOGE("%s: not authenticated", __func__); return -1; } if(!jhandler) { LOGE("%s: handler cannot be null", __func__); return -1; } utf = (*env)->GetStringUTFChars(env, jhandler, NULL); if(!utf) { LOGE("%s: cannot get handler name", __func__); goto jni_error; } h = get_handler_by_name(utf); if(!h) { LOGE("%s: handler \"%s\" not found", __func__, utf); goto exit; } (*env)->ReleaseStringUTFChars(env, jhandler, utf); utf=NULL; m = create_message(get_sequence(&ctrl_seq, &ctrl_seq_lock), sizeof(struct cmd_start_info), CTRL_ID); if(!m) { LOGE("%s: cannot create messages", __func__); goto exit; } start_info = (struct cmd_start_info *) m->data; start_info->cmd_action = CMD_START; start_info->hid = h->id; if(jcmd && parse_cmd(env, h, jcmd, m)) { LOGE("%s: cannot parse command", __func__); goto exit; } if(jenv && parse_env(env, jenv, m)) { LOGE("%s: cannot parse environment", __func__); goto exit; } // create child c = create_child(m->head.seq); if(!c) { LOGE("%s: cannot craete child", __func__); goto exit; } c->handler = h; // add child to list pthread_mutex_lock(&(children.control.mutex)); list_add(&(children.list), (node *) c); pthread_mutex_unlock(&(children.control.mutex)); // send message to cSploitd pthread_mutex_lock(&write_lock); // OPTIMIZATION: use id to store return value for later check id = send_message(sockfd, m); pthread_mutex_unlock(&write_lock); if(id) { LOGE("%s: cannot send messages", __func__); // mark it as failed c->id = CTRL_ID; c->seq = 0; } id=-1; // wait for CMD_STARTED or CMD_FAIL pthread_mutex_lock(&(children.control.mutex)); while(c->seq && children.control.active) pthread_cond_wait(&(children.control.cond), &(children.control.mutex)); if(c->id == CTRL_ID || c->seq) { // command failed list_del(&(children.list), (node *) c); } else { id = c->id; } c->pending = 0; pthread_mutex_unlock(&(children.control.mutex)); pthread_cond_broadcast(&(children.control.cond)); if(id != -1) { LOGI("%s: child #%d started", __func__, id); } else if(c->seq) { LOGW("%s: pending child cancelled", __func__); } else { LOGW("%s: cannot start command", __func__); } goto exit; jni_error: if((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } exit: if(m) free_message(m); if(utf) (*env)->ReleaseStringUTFChars(env, jhandler, utf); return id; }
static int do_pick_commit(void) { unsigned char head[20]; struct commit *base, *next, *parent; const char *base_label, *next_label; struct commit_message msg = { NULL, NULL, NULL, NULL, NULL }; char *defmsg = NULL; struct strbuf msgbuf = STRBUF_INIT; int res; if (no_commit) { /* * We do not intend to commit immediately. We just want to * merge the differences in, so let's compute the tree * that represents the "current" state for merge-recursive * to work on. */ if (write_cache_as_tree(head, 0, NULL)) die (_("Your index file is unmerged.")); } else { if (get_sha1("HEAD", head)) die (_("You do not have a valid HEAD")); if (index_differs_from("HEAD", 0)) die_dirty_index(me); } discard_cache(); if (!commit->parents) { parent = NULL; } else if (commit->parents->next) { /* Reverting or cherry-picking a merge commit */ int cnt; struct commit_list *p; if (!mainline) die(_("Commit %s is a merge but no -m option was given."), sha1_to_hex(commit->object.sha1)); for (cnt = 1, p = commit->parents; cnt != mainline && p; cnt++) p = p->next; if (cnt != mainline || !p) die(_("Commit %s does not have parent %d"), sha1_to_hex(commit->object.sha1), mainline); parent = p->item; } else if (0 < mainline) die(_("Mainline was specified but commit %s is not a merge."), sha1_to_hex(commit->object.sha1)); else parent = commit->parents->item; if (allow_ff && parent && !hashcmp(parent->object.sha1, head)) return fast_forward_to(commit->object.sha1, head); if (parent && parse_commit(parent) < 0) /* TRANSLATORS: The first %s will be "revert" or "cherry-pick", the second %s a SHA1 */ die(_("%s: cannot parse parent commit %s"), me, sha1_to_hex(parent->object.sha1)); if (get_message(commit->buffer, &msg) != 0) die(_("Cannot get commit message for %s"), sha1_to_hex(commit->object.sha1)); /* * "commit" is an existing commit. We would want to apply * the difference it introduces since its first parent "prev" * on top of the current HEAD if we are cherry-pick. Or the * reverse of it if we are revert. */ defmsg = git_pathdup("MERGE_MSG"); if (action == REVERT) { base = commit; base_label = msg.label; next = parent; next_label = msg.parent_label; strbuf_addstr(&msgbuf, "Revert \""); strbuf_addstr(&msgbuf, msg.subject); strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit "); strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1)); if (commit->parents && commit->parents->next) { strbuf_addstr(&msgbuf, ", reversing\nchanges made to "); strbuf_addstr(&msgbuf, sha1_to_hex(parent->object.sha1)); } strbuf_addstr(&msgbuf, ".\n"); } else { base = parent; base_label = msg.parent_label; next = commit; next_label = msg.label; add_message_to_msg(&msgbuf, msg.message); if (no_replay) { strbuf_addstr(&msgbuf, "(cherry picked from commit "); strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1)); strbuf_addstr(&msgbuf, ")\n"); } if (!no_commit) write_cherry_pick_head(); } if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) { res = do_recursive_merge(base, next, base_label, next_label, head, &msgbuf); write_message(&msgbuf, defmsg); } else { struct commit_list *common = NULL; struct commit_list *remotes = NULL; write_message(&msgbuf, defmsg); commit_list_insert(base, &common); commit_list_insert(next, &remotes); res = try_merge_command(strategy, xopts_nr, xopts, common, sha1_to_hex(head), remotes); free_commit_list(common); free_commit_list(remotes); } if (res) { error(action == REVERT ? _("could not revert %s... %s") : _("could not apply %s... %s"), find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), msg.subject); print_advice(); rerere(allow_rerere_auto); } else { if (!no_commit) res = run_git_commit(defmsg); } free_message(&msg); free(defmsg); return res; }