Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

KetchPreReceive.java 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (C) 2016, Google Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.internal.ketch;
  11. import static java.util.concurrent.TimeUnit.MILLISECONDS;
  12. import static java.util.concurrent.TimeUnit.SECONDS;
  13. import static org.eclipse.jgit.internal.ketch.Proposal.State.EXECUTED;
  14. import static org.eclipse.jgit.internal.ketch.Proposal.State.QUEUED;
  15. import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
  16. import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
  17. import java.io.IOException;
  18. import java.util.Collection;
  19. import org.eclipse.jgit.internal.JGitText;
  20. import org.eclipse.jgit.transport.PreReceiveHook;
  21. import org.eclipse.jgit.transport.ProgressSpinner;
  22. import org.eclipse.jgit.transport.ReceiveCommand;
  23. import org.eclipse.jgit.transport.ReceivePack;
  24. import org.slf4j.Logger;
  25. import org.slf4j.LoggerFactory;
  26. /**
  27. * PreReceiveHook for handling push traffic in a Ketch system.
  28. * <p>
  29. * Install an instance on {@link org.eclipse.jgit.transport.ReceivePack} to
  30. * capture the commands and other connection state and relay them through the
  31. * {@link org.eclipse.jgit.internal.ketch.KetchLeader}, allowing the leader to
  32. * gain consensus about the new reference state.
  33. */
  34. public class KetchPreReceive implements PreReceiveHook {
  35. private static final Logger log = LoggerFactory.getLogger(KetchPreReceive.class);
  36. private final KetchLeader leader;
  37. /**
  38. * Construct a hook executing updates through a
  39. * {@link org.eclipse.jgit.internal.ketch.KetchLeader}.
  40. *
  41. * @param leader
  42. * leader for this repository.
  43. */
  44. public KetchPreReceive(KetchLeader leader) {
  45. this.leader = leader;
  46. }
  47. /** {@inheritDoc} */
  48. @Override
  49. public void onPreReceive(ReceivePack rp, Collection<ReceiveCommand> cmds) {
  50. cmds = ReceiveCommand.filter(cmds, NOT_ATTEMPTED);
  51. if (cmds.isEmpty()) {
  52. return;
  53. }
  54. try {
  55. Proposal proposal = new Proposal(rp.getRevWalk(), cmds)
  56. .setPushCertificate(rp.getPushCertificate())
  57. .setAuthor(rp.getRefLogIdent())
  58. .setMessage("push"); //$NON-NLS-1$
  59. leader.queueProposal(proposal);
  60. if (proposal.isDone()) {
  61. // This failed fast, e.g. conflict or bad precondition.
  62. return;
  63. }
  64. ProgressSpinner spinner = new ProgressSpinner(
  65. rp.getMessageOutputStream());
  66. if (proposal.getState() == QUEUED) {
  67. waitForQueue(proposal, spinner);
  68. }
  69. if (!proposal.isDone()) {
  70. waitForPropose(proposal, spinner);
  71. }
  72. } catch (IOException | InterruptedException e) {
  73. String msg = JGitText.get().transactionAborted;
  74. for (ReceiveCommand cmd : cmds) {
  75. if (cmd.getResult() == NOT_ATTEMPTED) {
  76. cmd.setResult(REJECTED_OTHER_REASON, msg);
  77. }
  78. }
  79. log.error(msg, e);
  80. }
  81. }
  82. private void waitForQueue(Proposal proposal, ProgressSpinner spinner)
  83. throws InterruptedException {
  84. spinner.beginTask(KetchText.get().waitingForQueue, 1, SECONDS);
  85. while (!proposal.awaitStateChange(QUEUED, 250, MILLISECONDS)) {
  86. spinner.update();
  87. }
  88. switch (proposal.getState()) {
  89. case RUNNING:
  90. default:
  91. spinner.endTask(KetchText.get().starting);
  92. break;
  93. case EXECUTED:
  94. spinner.endTask(KetchText.get().accepted);
  95. break;
  96. case ABORTED:
  97. spinner.endTask(KetchText.get().failed);
  98. break;
  99. }
  100. }
  101. private void waitForPropose(Proposal proposal, ProgressSpinner spinner)
  102. throws InterruptedException {
  103. spinner.beginTask(KetchText.get().proposingUpdates, 2, SECONDS);
  104. while (!proposal.await(250, MILLISECONDS)) {
  105. spinner.update();
  106. }
  107. spinner.endTask(proposal.getState() == EXECUTED
  108. ? KetchText.get().accepted
  109. : KetchText.get().failed);
  110. }
  111. }