Пример #1
0
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;
}
Пример #2
0
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);
  }
Пример #3
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;
}
Пример #4
0
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;
}