public void testStatusDoesNotLockForWrite() throws Exception {
    final File ioFile = new File(myWorkingCopyRoot, filename);
    ioFile.getParentFile().mkdirs();

    /*SVNWCClient client11 = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
    client11.doAdd(ioFile.getParentFile(), true, false, true, true);*/

    ioFile.createNewFile();
    try {
      final SVNStatusClient readClient =
          new SVNStatusClient((ISVNRepositoryPool) null, new DefaultSVNOptions());
      final Semaphore semaphore = new Semaphore();
      final Semaphore semaphoreMain = new Semaphore();
      final Semaphore semaphoreWokeUp = new Semaphore();

      final AtomicReference<Boolean> wasUp = new AtomicReference<Boolean>(false);
      final ISVNStatusHandler handler =
          status -> {
            semaphore.waitFor();
            wasUp.set(true);
          };

      semaphore.down();
      semaphoreMain.down();
      semaphoreWokeUp.down();

      final SVNException[] exception = new SVNException[1];
      Thread thread =
          new Thread(
              () -> {
                try {
                  semaphoreMain.up();
                  readClient.doStatus(myWorkingCopyRoot, true, false, true, false, handler);
                  semaphoreWokeUp.up();
                } catch (SVNException e) {
                  exception[0] = e;
                }
              },
              "svn test");
      thread.start();

      semaphoreMain.waitFor();
      TimeoutUtil.sleep(5);
      SVNWCClient client = new SVNWCClient((ISVNRepositoryPool) null, new DefaultSVNOptions());
      client.doAdd(ioFile.getParentFile(), true, false, true, true);
      semaphore.up();
      semaphoreWokeUp.waitFor();

      Assert.assertEquals(true, wasUp.get().booleanValue());
      if (exception[0] != null) {
        throw exception[0];
      }
      thread.join();
    } finally {
      ioFile.delete();
    }
  }
  @Nullable
  public Script getScriptSync(@NotNull final String isolateId, @NotNull final String scriptId) {
    assertSyncRequestAllowed();

    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    final Ref<Script> resultRef = Ref.create();

    addRequest(
        () ->
            myVmService.getObject(
                isolateId,
                scriptId,
                new GetObjectConsumer() {
                  @Override
                  public void received(Obj script) {
                    resultRef.set((Script) script);
                    semaphore.up();
                  }

                  @Override
                  public void received(Sentinel response) {
                    semaphore.up();
                  }

                  @Override
                  public void onError(RPCError error) {
                    semaphore.up();
                  }
                }));

    semaphore.waitFor(RESPONSE_WAIT_TIMEOUT);
    return resultRef.get();
  }
  public static List<GitCommit> history(
      final Project project, @NotNull VirtualFile root, String... parameters) throws VcsException {
    final List<GitCommit> commits = new ArrayList<GitCommit>();
    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    historyWithLinks(
        project,
        new FilePathImpl(root),
        null,
        new AsynchConsumer<GitCommit>() {
          @Override
          public void finished() {
            semaphore.up();
          }

          @Override
          public void consume(GitCommit gitCommit) {
            commits.add(gitCommit);
          }
        },
        null,
        null,
        parameters);
    semaphore.waitFor();
    return commits;
  }
  private List<String> runCompiler(final Consumer<ErrorReportingCallback> runnable) {
    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    final ErrorReportingCallback callback = new ErrorReportingCallback(semaphore);
    UIUtil.invokeAndWaitIfNeeded(
        new Runnable() {
          @Override
          public void run() {
            try {
              if (useJps()) {
                getProject().save();
                CompilerTestUtil.saveSdkTable();
                File ioFile = VfsUtil.virtualToIoFile(myModule.getModuleFile());
                if (!ioFile.exists()) {
                  getProject().save();
                  assert ioFile.exists() : "File does not exist: " + ioFile.getPath();
                }
              }
              runnable.consume(callback);
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
          }
        });

    // tests run in awt
    while (!semaphore.waitFor(100)) {
      if (SwingUtilities.isEventDispatchThread()) {
        UIUtil.dispatchAllInvocationEvents();
      }
    }
    callback.throwException();
    return callback.getMessages();
  }
  static void invokeAndWait(
      @NotNull final Runnable runnable, @NotNull ModalityState modalityState) {
    LOG.assertTrue(!isDispatchThread());

    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    final Ref<Throwable> exception = Ref.create();
    Runnable runnable1 =
        new Runnable() {
          @Override
          public void run() {
            try {
              runnable.run();
            } catch (Throwable e) {
              exception.set(e);
            } finally {
              semaphore.up();
            }
          }

          @Override
          @NonNls
          public String toString() {
            return "InvokeAndWait[" + runnable + "]";
          }
        };
    invokeLater(runnable1, modalityState);
    semaphore.waitFor();
    if (!exception.isNull()) {
      throw new RuntimeException(exception.get());
    }
  }
Example #6
0
  public synchronized void stop() {
    if (myOriginal.isRunning()) {
      myOriginal.stop();
    } else {
      myStartupAlarm.cancelAllRequests();
    }

    // needed only for correct assertion of !progress.isRunning() in
    // ApplicationImpl.runProcessWithProgressSynchroniously
    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            semaphore.waitFor();
            if (myDialog != null) {
              // System.out.println("myDialog.destroyProcess()");
              myDialog.close(DialogWrapper.OK_EXIT_CODE);
              myDialog = null;
            }
          }
        });

    super.stop(); // should be last to not leaveModal before closing the dialog
    semaphore.up();
  }
Example #7
0
  private void openAndWait(VirtualFile file, @Nullable String relativePath)
      throws InterruptedException, IOException {
    semaphore.down();

    DesignerApplicationManager.getInstance()
        .renderDocument(myModule, Tests.virtualToPsi(myProject, file));
    await();
  }
Example #8
0
 public Waiter(
     @NotNull Project project, @NotNull Runnable runnable, String title, boolean cancellable) {
   super(
       project,
       VcsBundle.message("change.list.manager.wait.lists.synchronization", title),
       cancellable);
   myRunnable = runnable;
   mySemaphore.down();
   setCancelText("Skip");
 }
Example #9
0
  public static void invokeAndWaitInterruptedWhenClosing(
      final Project project, final Runnable runnable, final ModalityState modalityState) {
    final Ref<Boolean> start = new Ref<Boolean>(Boolean.TRUE);
    final Application application = ApplicationManager.getApplication();
    LOG.assertTrue(!application.isDispatchThread());

    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    Runnable runnable1 =
        new Runnable() {
          public void run() {
            try {
              runnable.run();
            } finally {
              semaphore.up();
            }
          }

          @NonNls
          public String toString() {
            return "PeriodicalTaskCloser's invoke and wait [" + runnable.toString() + "]";
          }
        };
    LaterInvocator.invokeLater(
        runnable1,
        modalityState,
        new Condition<Object>() {
          public boolean value(Object o) {
            synchronized (start) {
              return !start.get();
            }
          }
        });

    while (true) {
      if (semaphore.waitFor(1000)) {
        return;
      }
      final Ref<Boolean> fire = new Ref<Boolean>();
      synchronized (ourLock) {
        final Boolean state = myStates.get(project);
        if (!Boolean.TRUE.equals(state)) {
          fire.set(Boolean.TRUE);
        }
        if (Boolean.TRUE.equals(fire.get())) {
          synchronized (start) {
            start.set(Boolean.FALSE);
            return;
          }
        }
      }
    }
  }
 // blocks until all elements in the queue are processed
 public void waitFor() {
   final Semaphore semaphore = new Semaphore();
   semaphore.down();
   schedule(
       new Runnable() {
         @Override
         public void run() {
           semaphore.up();
         }
       });
   semaphore.waitFor();
 }
 private void waitForProcess(Application application) {
   myWaitSemaphore = new Semaphore();
   myWaitSemaphore.down();
   myWaitForThreadFuture =
       application.executeOnPooledThread(
           () -> {
             try {
               myProcess.waitFor();
             } catch (InterruptedException ignored) {
             } finally {
               myWaitSemaphore.up();
             }
           });
 }
Example #12
0
  private void insertString(VirtualFile file, int offset, @NotNull CharSequence s)
      throws InterruptedException {
    final Document document = FileDocumentManager.getInstance().getDocument(file);
    assertNotNull(document);
    AccessToken token = WriteAction.start();
    try {
      document.insertString(offset, s);
    } finally {
      token.finish();
    }

    semaphore.down();
    PsiDocumentManager.getInstance(myProject).commitAllDocuments();
    FileDocumentManager.getInstance().saveAllDocuments();
    await();
  }
Example #13
0
  private void renderAndWait(VirtualFile file) throws InterruptedException {
    semaphore.down();
    AsyncResult<DocumentInfo> result =
        DesignerApplicationManager.getInstance()
            .renderDocument(myModule, Tests.virtualToPsi(myProject, file));

    result.doWhenProcessed(
        new Runnable() {
          @Override
          public void run() {
            semaphore.up();
          }
        });

    await();
  }
  protected ProcessHandler runProcess(
      String className,
      Module module,
      final Class<? extends Executor> executorClass,
      final ProcessListener listener,
      final ProgramRunner runner)
      throws ExecutionException {
    final ApplicationConfiguration configuration =
        new ApplicationConfiguration(
            "app", getProject(), ApplicationConfigurationType.getInstance());
    configuration.setModule(module);
    configuration.setMainClassName(className);
    final Executor executor = Executor.EXECUTOR_EXTENSION_NAME.findExtension(executorClass);
    final ExecutionEnvironment environment =
        new ExecutionEnvironment(
            configuration,
            getProject(),
            new RunnerSettings<JDOMExternalizable>(null, null),
            null,
            null);
    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    final AtomicReference<ProcessHandler> processHandler = new AtomicReference<ProcessHandler>();
    runner.execute(
        executor,
        environment,
        new ProgramRunner.Callback() {
          @Override
          public void processStarted(final RunContentDescriptor descriptor) {
            disposeOnTearDown(
                new Disposable() {
                  @Override
                  public void dispose() {
                    Disposer.dispose(descriptor);
                  }
                });
            final ProcessHandler handler = descriptor.getProcessHandler();
            assert handler != null;
            handler.addProcessListener(listener);
            processHandler.set(handler);
            semaphore.up();
          }
        });
    semaphore.waitFor();
    return processHandler.get();
  }
Example #15
0
 private void callClientAssert(VirtualFile file) throws IOException, InterruptedException {
   semaphore.down();
   ActionCallback callback =
       client.test(
           null,
           DocumentFactoryManager.getInstance().getId(file),
           getTestName(false),
           APP_TEST_CLASS_ID);
   callback.doWhenProcessed(
       new Runnable() {
         @Override
         public void run() {
           semaphore.up();
         }
       });
   await();
 }
  protected void performRemoteGitTask(final GitLineHandler handler, String title)
      throws ServerRuntimeException {
    final GitTask task = new GitTask(myProject, handler, title);
    task.setProgressAnalyzer(new GitStandardProgressAnalyzer());

    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    final Ref<ServerRuntimeException> errorRef = new Ref<ServerRuntimeException>();

    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {

              @Override
              public void run() {
                task.execute(
                    false,
                    false,
                    new GitTaskResultHandlerAdapter() {

                      @Override
                      protected void run(GitTaskResult result) {
                        super.run(result);
                        semaphore.up();
                      }

                      @Override
                      protected void onFailure() {
                        for (VcsException error : handler.errors()) {
                          myLoggingHandler.println(error.toString());
                          if (errorRef.isNull()) {
                            errorRef.set(new ServerRuntimeException(error));
                          }
                        }
                      }
                    });
              }
            });

    semaphore.waitFor();
    if (!errorRef.isNull()) {
      throw errorRef.get();
    }
  }
  @Nullable
  private String evaluateExpression(
      final @NotNull String isolateId,
      final @Nullable Frame vmTopFrame,
      final @Nullable XExpression xExpression) {
    final String evalText = xExpression == null ? null : xExpression.getExpression();
    if (vmTopFrame == null || StringUtil.isEmptyOrSpaces(evalText)) return null;

    final Ref<String> evalResult = new Ref<>();
    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    myDebugProcess
        .getVmServiceWrapper()
        .evaluateInFrame(
            isolateId,
            vmTopFrame,
            evalText,
            new XDebuggerEvaluator.XEvaluationCallback() {
              @Override
              public void evaluated(@NotNull final XValue result) {
                if (result instanceof DartVmServiceValue) {
                  evalResult.set(
                      getSimpleStringPresentation(((DartVmServiceValue) result).getInstanceRef()));
                }
                semaphore.up();
              }

              @Override
              public void errorOccurred(@NotNull final String errorMessage) {
                evalResult.set(
                    "Failed to evaluate log expression [" + evalText + "]: " + errorMessage);
                semaphore.up();
              }
            },
            true);

    semaphore.waitFor(1000);
    return evalResult.get();
  }
  @Override
  public synchronized void stop() {
    if (myOriginal.isRunning()) {
      myOriginal.stop();
    } else {
      myStartupAlarm.cancelAllRequests();

      if (!myOriginalStarted && myOriginal instanceof Disposable) {
        // dispose original because start & stop were not called so original progress might not have
        // released its resources
        Disposer.dispose(((Disposable) myOriginal));
      }
    }

    // needed only for correct assertion of !progress.isRunning() in
    // ApplicationImpl.runProcessWithProgressSynchroniously
    final Semaphore semaphore = new Semaphore();
    semaphore.down();

    SwingUtilities.invokeLater(
        new Runnable() {
          @Override
          public void run() {
            semaphore.waitFor();
            if (myDialog != null) {
              // System.out.println("myDialog.destroyProcess()");
              myDialog.close(DialogWrapper.OK_EXIT_CODE);
              myDialog = null;
            }
          }
        });

    try {
      super.stop(); // should be last to not leaveModal before closing the dialog
    } finally {
      semaphore.up();
    }
  }
  @Override
  public void waitForSmartMode() {
    final Application application = ApplicationManager.getApplication();
    if (!application.isUnitTestMode()) {
      assert !application.isDispatchThread();
      assert !application.isReadAccessAllowed();
    }

    if (!isDumb()) {
      return;
    }

    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    runWhenSmart(
        new Runnable() {
          @Override
          public void run() {
            semaphore.up();
          }
        });
    semaphore.waitFor();
  }
  @CalledInAwt
  public void execute() {
    FileDocumentManager.getInstance().saveAllDocuments();

    mySemaphore.down();
    runInEdt(
        () -> {
          if (areInSameHierarchy(
              createUrl(myMergeContext.getSourceUrl()), myMergeContext.getWcInfo().getUrl())) {
            end("Cannot merge from self", true);
          } else if (!hasSwitchedRoots() || myInteraction.shouldContinueSwitchedRootFound()) {
            runInBackground(
                "Checking repository capabilities",
                indicator -> {
                  if (supportsMergeInfo()) {
                    runInEdt(this::selectMergeVariant);
                  } else {
                    mergeAll(false);
                  }
                });
          }
        });
  }
 private void execute(final MavenRunnerParameters params) {
   final Semaphore sema = new Semaphore();
   sema.down();
   UIUtil.invokeLaterIfNeeded(
       new Runnable() {
         @Override
         public void run() {
           MavenRunConfigurationType.runConfiguration(
               myProject,
               params,
               getMavenGeneralSettings(),
               new MavenRunnerSettings(),
               new ProgramRunner.Callback() {
                 @Override
                 public void processStarted(final RunContentDescriptor descriptor) {
                   descriptor
                       .getProcessHandler()
                       .addProcessListener(
                           new ProcessAdapter() {
                             @Override
                             public void processTerminated(ProcessEvent event) {
                               sema.up();
                               UIUtil.invokeLaterIfNeeded(
                                   new Runnable() {
                                     @Override
                                     public void run() {
                                       Disposer.dispose(descriptor);
                                     }
                                   });
                             }
                           });
                 }
               });
         }
       });
   sema.waitFor();
 }
  private static boolean checkPort(final InetSocketAddress remoteAddress) {
    final ClientBootstrap bootstrap =
        new ClientBootstrap(new OioClientSocketChannelFactory(new PooledThreadExecutor()));
    bootstrap.setOption("child.tcpNoDelay", true);

    final AtomicBoolean result = new AtomicBoolean(false);
    final Semaphore semaphore = new Semaphore();
    semaphore.down(); // must call to down() here to ensure that down was called _before_ up()
    bootstrap.setPipeline(
        pipeline(
            new HttpResponseDecoder(),
            new HttpRequestEncoder(),
            new SimpleChannelUpstreamHandler() {
              @Override
              public void messageReceived(ChannelHandlerContext context, MessageEvent e)
                  throws Exception {
                try {
                  if (e.getMessage() instanceof HttpResponse) {
                    HttpResponse response = (HttpResponse) e.getMessage();
                    if (response.getStatus().equals(OK)
                        && response
                            .getContent()
                            .toString(CharsetUtil.US_ASCII)
                            .equals(getApplicationStartTime())) {
                      LOG.info("port check: current OS must be marked as normal");
                      result.set(true);
                    }
                  }
                } finally {
                  semaphore.up();
                }
              }

              @Override
              public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                  throws Exception {
                try {
                  LOG.error(e.getCause());
                } finally {
                  semaphore.up();
                }
              }
            }));

    ChannelFuture connectFuture = null;
    try {
      connectFuture = bootstrap.connect(remoteAddress);
      if (!waitComplete(connectFuture, "connect")) {
        return false;
      }
      ChannelFuture writeFuture =
          connectFuture
              .getChannel()
              .write(new DefaultHttpRequest(HTTP_1_1, HttpMethod.GET, START_TIME_PATH));
      if (!waitComplete(writeFuture, "write")) {
        return false;
      }

      try {
        // yes, 30 seconds. I always get timeout in Linux in Parallels if I set to 2 seconds.
        // In any case all work is done in pooled thread (IDE init time isn't affected)
        if (!semaphore.waitForUnsafe(30000)) {
          LOG.info("port check: semaphore down timeout");
        }
      } catch (InterruptedException e) {
        LOG.info("port check: semaphore interrupted", e);
      }
    } finally {
      if (connectFuture != null) {
        connectFuture.getChannel().close().awaitUninterruptibly();
      }
      bootstrap.releaseExternalResources();
    }
    return result.get();
  }
  public void testCommitInBackground() {
    PsiFile file = getPsiManager().findFile(createFile());
    assertTrue(file.isPhysical());
    final Document document = getPsiDocumentManager().getDocument(file);

    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    getPsiDocumentManager()
        .performWhenAllCommitted(
            new Runnable() {
              @Override
              public void run() {
                assertTrue(getPsiDocumentManager().isCommitted(document));
                semaphore.up();
              }
            });
    waitAndPump(semaphore);
    assertTrue(getPsiDocumentManager().isCommitted(document));

    ApplicationManager.getApplication()
        .runWriteAction(
            new Runnable() {
              public void run() {
                document.insertString(0, "class X {}");
              }
            });

    semaphore.down();
    getPsiDocumentManager()
        .performWhenAllCommitted(
            new Runnable() {
              @Override
              public void run() {
                assertTrue(getPsiDocumentManager().isCommitted(document));
                semaphore.up();
              }
            });
    waitAndPump(semaphore);
    assertTrue(getPsiDocumentManager().isCommitted(document));

    final AtomicInteger count = new AtomicInteger();
    final Runnable action =
        new Runnable() {
          @Override
          public void run() {
            count.incrementAndGet();
          }
        };

    ApplicationManager.getApplication()
        .runWriteAction(
            new Runnable() {
              public void run() {
                document.insertString(0, "/**/");
                boolean executed =
                    getPsiDocumentManager().cancelAndRunWhenAllCommitted("xxx", action);
                assertFalse(executed);
                executed = getPsiDocumentManager().cancelAndRunWhenAllCommitted("xxx", action);
                assertFalse(executed);
                assertEquals(0, count.get());
              }
            });

    while (!getPsiDocumentManager().isCommitted(document)) {
      UIUtil.dispatchAllInvocationEvents();
    }
    assertTrue(getPsiDocumentManager().isCommitted(document));
    assertEquals(1, count.get());

    count.set(0);
    ApplicationManager.getApplication()
        .runWriteAction(
            new Runnable() {
              public void run() {
                document.insertString(0, "/**/");
                boolean executed = getPsiDocumentManager().performWhenAllCommitted(action);
                assertFalse(executed);
                executed = getPsiDocumentManager().performWhenAllCommitted(action);
                assertFalse(executed);
                assertEquals(0, count.get());
              }
            });

    while (!getPsiDocumentManager().isCommitted(document)) {
      UIUtil.dispatchAllInvocationEvents();
    }
    assertTrue(getPsiDocumentManager().isCommitted(document));
    assertEquals(2, count.get());
  }
 @Override
 public void launch() {
   mySemaphore.down();
   ((RefreshQueueImpl) RefreshQueue.getInstance()).execute(this);
 }
 public void begin() {
   done.down();
 }
  private void doComplete(
      CompletionInitializationContext initContext,
      boolean hasModifiers,
      int invocationCount,
      PsiFile hostCopy,
      OffsetMap hostMap,
      OffsetTranslator translator) {
    final Editor editor = initContext.getEditor();
    CompletionAssertions.checkEditorValid(editor);

    CompletionContext context =
        createCompletionContext(
            hostCopy,
            hostMap.getOffset(CompletionInitializationContext.START_OFFSET),
            hostMap,
            initContext.getFile());
    LookupImpl lookup = obtainLookup(editor);
    CompletionParameters parameters = createCompletionParameters(invocationCount, context, editor);

    CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
    if (phase instanceof CompletionPhase.CommittingDocuments) {
      if (phase.indicator != null) {
        phase.indicator.closeAndFinish(false);
      }
      ((CompletionPhase.CommittingDocuments) phase).replaced = true;
    } else {
      CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
    }

    final Semaphore freezeSemaphore = new Semaphore();
    freezeSemaphore.down();
    final CompletionProgressIndicator indicator =
        new CompletionProgressIndicator(
            editor,
            parameters,
            this,
            freezeSemaphore,
            initContext.getOffsetMap(),
            hasModifiers,
            lookup);
    Disposer.register(indicator, hostMap);
    Disposer.register(indicator, context.getOffsetMap());
    Disposer.register(indicator, translator);

    CompletionServiceImpl.setCompletionPhase(
        synchronous
            ? new CompletionPhase.Synchronous(indicator)
            : new CompletionPhase.BgCalculation(indicator));

    final AtomicReference<LookupElement[]> data = indicator.startCompletion(initContext);

    if (!synchronous) {
      return;
    }

    if (freezeSemaphore.waitFor(2000)) {
      final LookupElement[] allItems = data.get();
      if (allItems != null
          && !indicator.isRunning()
          && !indicator
              .isCanceled()) { // the completion is really finished, now we may auto-insert or show
        // lookup
        completionFinished(
            initContext.getStartOffset(),
            initContext.getSelectionEndOffset(),
            indicator,
            allItems,
            hasModifiers);
        checkNotSync(indicator, allItems);
        return;
      }
    }

    CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation(indicator));
    indicator.showLookup();
  }
  public static void historyWithLinks(
      final Project project,
      FilePath path,
      @Nullable final SymbolicRefsI refs,
      @NotNull final AsynchConsumer<GitCommit> gitCommitConsumer,
      @Nullable final Getter<Boolean> isCanceled,
      @Nullable Collection<VirtualFile> paths,
      final String... parameters)
      throws VcsException {
    // adjust path using change manager
    path = getLastCommitName(project, path);
    final VirtualFile root = GitUtil.getGitRoot(path);
    final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
    final GitLogParser parser =
        new GitLogParser(
            project,
            GitLogParser.NameStatus.STATUS,
            SHORT_HASH,
            HASH,
            COMMIT_TIME,
            AUTHOR_NAME,
            AUTHOR_TIME,
            AUTHOR_EMAIL,
            COMMITTER_NAME,
            COMMITTER_EMAIL,
            SHORT_PARENTS,
            REF_NAMES,
            SUBJECT,
            BODY,
            RAW_BODY);
    h.setNoSSH(true);
    h.setStdoutSuppressed(true);
    h.addParameters(parameters);
    h.addParameters("--name-status", parser.getPretty(), "--encoding=UTF-8", "--full-history");
    if (paths != null && !paths.isEmpty()) {
      h.endOptions();
      h.addRelativeFiles(paths);
    } else {
      h.addParameters("--sparse");
      h.endOptions();
      h.addRelativePaths(path);
    }

    final VcsException[] exc = new VcsException[1];
    final Semaphore semaphore = new Semaphore();
    final StringBuilder sb = new StringBuilder();
    final Ref<Boolean> skipFirst = new Ref<Boolean>(true);
    h.addLineListener(
        new GitLineHandlerAdapter() {
          @Override
          public void onLineAvailable(final String line, final Key outputType) {
            try {
              if (ProcessOutputTypes.STDOUT.equals(outputType)) {
                if (isCanceled != null && isCanceled.get()) {
                  h.cancel();
                  return;
                }
                // if (line.charAt(line.length() - 1) != '\u0003') {
                if ((!line.startsWith("\u0001")) || skipFirst.get()) {
                  if (sb.length() > 0) {
                    sb.append("\n");
                  }
                  sb.append(line);
                  skipFirst.set(false);
                  return;
                }
                takeLine(project, line, sb, parser, refs, root, exc, h, gitCommitConsumer);
              }
            } catch (ProcessCanceledException e) {
              h.cancel();
              semaphore.up();
            }
          }

          @Override
          public void processTerminated(int exitCode) {
            semaphore.up();
          }

          @Override
          public void startFailed(Throwable exception) {
            semaphore.up();
          }
        });
    semaphore.down();
    h.start();
    semaphore.waitFor();
    takeLine(project, "", sb, parser, refs, root, exc, h, gitCommitConsumer);
    gitCommitConsumer.finished();
    if (exc[0] != null) {
      throw exc[0];
    }
  }
  /**
   * Retrieves the history of the file, including renames.
   *
   * @param project
   * @param path FilePath which history is queried.
   * @param root Git root - optional: if this is null, then git root will be detected automatically.
   * @param consumer This consumer is notified ({@link Consumer#consume(Object)} when new history
   *     records are retrieved.
   * @param exceptionConsumer This consumer is notified in case of error while executing git
   *     command.
   * @param parameters Optional parameters which will be added to the git log command just before
   *     the path.
   * @throws VcsException In case of git native execution error.
   */
  public static void history(
      final Project project,
      FilePath path,
      @Nullable VirtualFile root,
      final Consumer<GitFileRevision> consumer,
      final Consumer<VcsException> exceptionConsumer,
      String... parameters)
      throws VcsException {
    // adjust path using change manager
    path = getLastCommitName(project, path);
    final VirtualFile finalRoot = (root == null ? GitUtil.getGitRoot(path) : root);
    final GitLogParser logParser =
        new GitLogParser(
            project,
            GitLogParser.NameStatus.STATUS,
            HASH,
            COMMIT_TIME,
            AUTHOR_NAME,
            AUTHOR_EMAIL,
            COMMITTER_NAME,
            COMMITTER_EMAIL,
            PARENTS,
            SUBJECT,
            BODY,
            RAW_BODY,
            AUTHOR_TIME);

    final AtomicReference<String> firstCommit = new AtomicReference<String>("HEAD");
    final AtomicReference<String> firstCommitParent = new AtomicReference<String>("HEAD");
    final AtomicReference<FilePath> currentPath = new AtomicReference<FilePath>(path);
    final AtomicReference<GitLineHandler> logHandler = new AtomicReference<GitLineHandler>();
    final AtomicBoolean skipFurtherOutput = new AtomicBoolean();

    final Consumer<GitLogRecord> resultAdapter =
        new Consumer<GitLogRecord>() {
          public void consume(GitLogRecord record) {
            if (skipFurtherOutput.get()) {
              return;
            }
            if (record == null) {
              exceptionConsumer.consume(new VcsException("revision details are null."));
              return;
            }
            record.setUsedHandler(logHandler.get());
            final GitRevisionNumber revision =
                new GitRevisionNumber(record.getHash(), record.getDate());
            firstCommit.set(record.getHash());
            final String[] parentHashes = record.getParentsHashes();
            if (parentHashes == null || parentHashes.length < 1) {
              firstCommitParent.set(null);
            } else {
              firstCommitParent.set(parentHashes[0]);
            }
            final String message = record.getFullMessage();

            FilePath revisionPath;
            try {
              final List<FilePath> paths = record.getFilePaths(finalRoot);
              if (paths.size() > 0) {
                revisionPath = paths.get(0);
              } else {
                // no paths are shown for merge commits, so we're using the saved path we're
                // inspecting now
                revisionPath = currentPath.get();
              }

              final Pair<String, String> authorPair =
                  Pair.create(record.getAuthorName(), record.getAuthorEmail());
              final Pair<String, String> committerPair =
                  record.getCommitterName() == null
                      ? null
                      : Pair.create(record.getCommitterName(), record.getCommitterEmail());
              Collection<String> parents =
                  parentHashes == null
                      ? Collections.<String>emptyList()
                      : Arrays.asList(parentHashes);
              consumer.consume(
                  new GitFileRevision(
                      project,
                      revisionPath,
                      revision,
                      Pair.create(authorPair, committerPair),
                      message,
                      null,
                      new Date(record.getAuthorTimeStamp() * 1000),
                      false,
                      parents));
              List<GitLogStatusInfo> statusInfos = record.getStatusInfos();
              if (statusInfos.isEmpty()) {
                // can safely be empty, for example, for simple merge commits that don't change
                // anything.
                return;
              }
              if (statusInfos.get(0).getType() == GitChangeType.ADDED) {
                skipFurtherOutput.set(true);
              }
            } catch (VcsException e) {
              exceptionConsumer.consume(e);
            }
          }
        };

    while (currentPath.get() != null && firstCommitParent.get() != null) {
      logHandler.set(
          getLogHandler(
              project,
              finalRoot,
              logParser,
              currentPath.get(),
              firstCommitParent.get(),
              parameters));
      final MyTokenAccumulator accumulator = new MyTokenAccumulator(logParser);
      final Semaphore semaphore = new Semaphore();

      logHandler
          .get()
          .addLineListener(
              new GitLineHandlerAdapter() {
                @Override
                public void onLineAvailable(String line, Key outputType) {
                  final GitLogRecord record = accumulator.acceptLine(line);
                  if (record != null) {
                    resultAdapter.consume(record);
                  }
                }

                @Override
                public void startFailed(Throwable exception) {
                  //noinspection ThrowableInstanceNeverThrown
                  try {
                    exceptionConsumer.consume(new VcsException(exception));
                  } finally {
                    semaphore.up();
                  }
                }

                @Override
                public void processTerminated(int exitCode) {
                  try {
                    super.processTerminated(exitCode);
                    final GitLogRecord record = accumulator.processLast();
                    if (record != null) {
                      resultAdapter.consume(record);
                    }
                  } finally {
                    semaphore.up();
                  }
                }
              });
      semaphore.down();
      logHandler.get().start();
      semaphore.waitFor();

      currentPath.set(
          getFirstCommitRenamePath(project, finalRoot, firstCommit.get(), currentPath.get()));
      skipFurtherOutput.set(false);
    }
  }
  public static void dumpFullHistory(
      final Project project, VirtualFile root, final String outFilePath) throws VcsException {
    if (!GitUtil.isGitRoot(new File(root.getPath())))
      throw new VcsException("Path " + root.getPath() + " is not git repository root");

    final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
    // GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
    GitLogParser parser =
        new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME);
    h.setNoSSH(true);
    h.setSilent(true);
    h.addParameters(
        "--all",
        "--pretty=format:%H%x20%ct%x0A",
        "--date-order",
        "--reverse",
        "--encoding=UTF-8",
        "--full-history",
        "--sparse");
    h.endOptions();

    // for file sort
    final Long[] minTs = new Long[1];
    minTs[0] = Long.MAX_VALUE;
    final Long[] maxTs = new Long[1];
    minTs[0] = 0L;

    final OutputStream[] stream = new OutputStream[1];
    try {
      stream[0] = new BufferedOutputStream(new FileOutputStream(outFilePath, false));
      final Semaphore semaphore = new Semaphore();
      final VcsException[] ioExceptions = new VcsException[1];
      h.addLineListener(
          new GitLineHandlerListener() {
            @Override
            public void onLineAvailable(String line, Key outputType) {
              if (line.length() == 0) return;
              try {
                GitCommitsSequentialIndex.parseRecord(line);
                stream[0].write((line + '\n').getBytes("UTF-8"));
              } catch (IOException e) {
                ioExceptions[0] = new VcsException(e);
                h.cancel();
                semaphore.up();
              } catch (ProcessCanceledException e) {
                h.cancel();
                semaphore.up();
              } catch (VcsException e) {
                ioExceptions[0] = e;
                h.cancel();
                semaphore.up();
              }
            }

            @Override
            public void processTerminated(int exitCode) {
              semaphore.up();
            }

            @Override
            public void startFailed(Throwable exception) {
              semaphore.up();
            }
          });
      semaphore.down();
      h.start();
      semaphore.waitFor();
      if (ioExceptions[0] != null) {
        throw ioExceptions[0];
      }
    } catch (FileNotFoundException e) {
      throw new VcsException(e);
    } finally {
      try {
        if (stream[0] != null) {
          stream[0].close();
        }
      } catch (IOException e) {
        throw new VcsException(e);
      }
    }
    /*String result = h.run();
    if (result.length() > 0) {
      throw new VcsException(result);
    }*/
    File file = new File(outFilePath);
    if (!file.exists() || file.length() == 0)
      throw new VcsException("Short repository history not loaded");
  }
  public static void hashesWithParents(
      Project project,
      FilePath path,
      final AsynchConsumer<CommitHashPlusParents> consumer,
      final Getter<Boolean> isCanceled,
      Collection<VirtualFile> paths,
      final String... parameters)
      throws VcsException {
    // adjust path using change manager
    path = getLastCommitName(project, path);
    final VirtualFile root = GitUtil.getGitRoot(path);
    final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
    final GitLogParser parser =
        new GitLogParser(
            project,
            GitLogParser.NameStatus.NAME,
            SHORT_HASH,
            COMMIT_TIME,
            SHORT_PARENTS,
            AUTHOR_NAME);
    h.setNoSSH(true);
    h.setStdoutSuppressed(true);
    h.addParameters(parameters);
    h.addParameters(parser.getPretty(), "--encoding=UTF-8", "--full-history");

    if (paths != null && !paths.isEmpty()) {
      h.endOptions();
      h.addRelativeFiles(paths);
    } else {
      h.addParameters("--sparse");
      h.endOptions();
      h.addRelativePaths(path);
    }

    final Semaphore semaphore = new Semaphore();
    h.addLineListener(
        new GitLineHandlerListener() {
          @Override
          public void onLineAvailable(final String line, final Key outputType) {
            try {
              if (ProcessOutputTypes.STDOUT.equals(outputType)) {
                if (isCanceled != null && isCanceled.get()) {
                  h.cancel();
                  return;
                }
                GitLogRecord record = parser.parseOneRecord(line);
                consumer.consume(
                    new CommitHashPlusParents(
                        record.getShortHash(),
                        record.getParentsShortHashes(),
                        record.getLongTimeStamp() * 1000,
                        record.getAuthorName()));
              }
            } catch (ProcessCanceledException e) {
              h.cancel();
              semaphore.up();
            }
          }

          @Override
          public void processTerminated(int exitCode) {
            semaphore.up();
          }

          @Override
          public void startFailed(Throwable exception) {
            semaphore.up();
          }
        });
    semaphore.down();
    h.start();
    semaphore.waitFor();
    consumer.finished();
  }