tikhomirov@615: /* tikhomirov@615: * Copyright (c) 2013 TMate Software Ltd tikhomirov@615: * tikhomirov@615: * This program is free software; you can redistribute it and/or modify tikhomirov@615: * it under the terms of the GNU General Public License as published by tikhomirov@615: * the Free Software Foundation; version 2 of the License. tikhomirov@615: * tikhomirov@615: * This program is distributed in the hope that it will be useful, tikhomirov@615: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@615: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@615: * GNU General Public License for more details. tikhomirov@615: * tikhomirov@615: * For information on how to redistribute this software under tikhomirov@615: * the terms of a license other than GNU General Public License tikhomirov@615: * contact TMate Software at support@hg4j.com tikhomirov@615: */ tikhomirov@615: package org.tmatesoft.hg.test; tikhomirov@615: tikhomirov@615: import java.io.File; tikhomirov@631: import java.util.HashMap; tikhomirov@631: import java.util.Map; tikhomirov@631: import java.util.concurrent.CountDownLatch; tikhomirov@615: tikhomirov@615: import org.junit.Assert; tikhomirov@615: import org.junit.Test; tikhomirov@631: import org.tmatesoft.hg.core.HgStatusCommand; tikhomirov@631: import org.tmatesoft.hg.internal.BasicSessionContext; tikhomirov@631: import org.tmatesoft.hg.internal.DataAccessProvider; tikhomirov@615: import org.tmatesoft.hg.repo.HgLookup; tikhomirov@615: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@615: import org.tmatesoft.hg.repo.HgRepositoryLock; tikhomirov@615: tikhomirov@615: /** tikhomirov@615: * tikhomirov@615: * @author Artem Tikhomirov tikhomirov@615: * @author TMate Software Ltd. tikhomirov@615: */ tikhomirov@615: public class TestRepositoryLock { tikhomirov@615: tikhomirov@615: @Test tikhomirov@615: public void testWorkingDirLock() throws Exception { tikhomirov@615: File repoLoc = RepoUtils.cloneRepoToTempLocation("log-1", "test-wc-lock", false); tikhomirov@615: // turn off lock timeout, to fail fast tikhomirov@615: File hgrc = new File(repoLoc, ".hg/hgrc"); tikhomirov@615: RepoUtils.createFile(hgrc, "[ui]\ntimeout=0\n"); // or 1 tikhomirov@616: final OutputParser.Stub p = new OutputParser.Stub(); tikhomirov@616: ExecHelper eh = new ExecHelper(p, repoLoc); tikhomirov@615: HgRepository hgRepo = new HgLookup().detect(repoLoc); tikhomirov@615: final HgRepositoryLock wdLock = hgRepo.getWorkingDirLock(); tikhomirov@615: try { tikhomirov@615: wdLock.acquire(); tikhomirov@615: eh.run("hg", "tag", "tag-aaa"); tikhomirov@615: Assert.assertNotSame(0 /*returns 0 on success*/, eh.getExitValue()); tikhomirov@616: Assert.assertTrue(p.result().toString().contains("abort")); tikhomirov@615: } finally { tikhomirov@615: wdLock.release(); tikhomirov@615: } tikhomirov@615: } tikhomirov@631: tikhomirov@631: public static void main(String[] args) throws Exception { tikhomirov@631: Map po = new HashMap(); tikhomirov@631: po.put(DataAccessProvider.CFG_PROPERTY_MAPIO_LIMIT, 0); tikhomirov@631: final HgLookup hgLookup = new HgLookup(new BasicSessionContext(po , null)); tikhomirov@631: final File rebaseFromRepoLoc = RepoUtils.cloneRepoToTempLocation(new File("/temp/hg/junit-test-repos/test-annotate"), "repo-lock-remote", false, true); tikhomirov@631: final File rebaseToRepoLoc = RepoUtils.cloneRepoToTempLocation(rebaseFromRepoLoc, "repo-lock-local", false, true); tikhomirov@631: final File remoteChanges = new File(rebaseFromRepoLoc, "file1"); tikhomirov@631: // tikhomirov@631: // create commit in the "local" repository that will be rebased on top of changes tikhomirov@631: // pulled from "remote repository" tikhomirov@631: File localChanges = new File(rebaseToRepoLoc, "file-new"); tikhomirov@631: if (localChanges.exists()) { tikhomirov@631: RepoUtils.modifyFileAppend(localChanges, "whatever"); tikhomirov@631: } else { tikhomirov@631: RepoUtils.createFile(localChanges, "whatever"); tikhomirov@631: } tikhomirov@631: commit(rebaseToRepoLoc, "local change"); tikhomirov@631: // tikhomirov@631: final int rebaseRevisionCount = 70; tikhomirov@631: final CountDownLatch latch = new CountDownLatch(2); tikhomirov@631: Runnable r1 = new Runnable() { tikhomirov@631: public void run() { tikhomirov@631: for (int i = 0; i < rebaseRevisionCount; i++) { tikhomirov@631: commitPullRebaseNative(rebaseFromRepoLoc, rebaseToRepoLoc, remoteChanges); tikhomirov@631: sleep(500, 1000); tikhomirov@631: } tikhomirov@631: latch.countDown(); tikhomirov@631: } tikhomirov@631: }; tikhomirov@631: Runnable r2 = new Runnable() { tikhomirov@631: public void run() { tikhomirov@631: for (int i = 0; i < 100; i++) { tikhomirov@631: readWithHg4J(hgLookup, rebaseToRepoLoc); tikhomirov@631: sleep(800, 400); tikhomirov@631: } tikhomirov@631: latch.countDown(); tikhomirov@631: } tikhomirov@631: }; tikhomirov@631: new Thread(r1, "pull-rebase-thread").start(); tikhomirov@631: new Thread(r2, "hg4j-read-thread").start(); tikhomirov@631: latch.await(); tikhomirov@631: System.out.println("DONE."); tikhomirov@631: // now `hg log` in rebaseToRepoLoc shall show tikhomirov@631: // all rebaseRevisionCount revisions from rebaseFromRepoLoc + 1 more, "local change", on top of them tikhomirov@631: } tikhomirov@631: tikhomirov@631: private static int count = 0; tikhomirov@631: tikhomirov@631: private static void commitPullRebaseNative(final File rebaseFromRepoLoc, final File rebaseToRepoLoc, final File rebaseFromChanges) { tikhomirov@631: try { tikhomirov@631: OutputParser.Stub p = new OutputParser.Stub(); tikhomirov@631: final ExecHelper eh = new ExecHelper(p, rebaseToRepoLoc); tikhomirov@631: RepoUtils.modifyFileAppend(rebaseFromChanges, "Change #" + count++); tikhomirov@631: commit(rebaseFromRepoLoc, "remote change"); tikhomirov@631: p.reset(); tikhomirov@631: eh.run("hg", "--traceback", "pull", rebaseFromRepoLoc.toString()); tikhomirov@631: if (eh.getExitValue() != 0) { tikhomirov@631: System.out.println(p.result()); tikhomirov@631: } tikhomirov@631: Assert.assertEquals(0, eh.getExitValue()); tikhomirov@631: p.reset(); tikhomirov@631: eh.run("hg", "--traceback", "--config", "extensions.hgext.rebase=", "rebase"); tikhomirov@631: if (eh.getExitValue() != 0) { tikhomirov@631: System.out.println(p.result()); tikhomirov@631: } tikhomirov@631: System.out.print("X"); tikhomirov@631: Assert.assertEquals(0, eh.getExitValue()); tikhomirov@631: } catch (RuntimeException ex) { tikhomirov@631: throw ex; tikhomirov@631: } catch (Exception ex) { tikhomirov@631: ex.printStackTrace(); tikhomirov@631: throw new RuntimeException(null, ex); tikhomirov@631: } tikhomirov@631: } tikhomirov@631: tikhomirov@631: private static void readWithHg4J(final HgLookup hgLookup, final File repoLoc) { tikhomirov@631: try { tikhomirov@631: System.out.print("("); tikhomirov@631: final long start = System.nanoTime(); tikhomirov@631: HgRepository hgRepo = hgLookup.detect(repoLoc); tikhomirov@631: final HgRepositoryLock wcLock = hgRepo.getWorkingDirLock(); tikhomirov@631: final HgRepositoryLock storeLock = hgRepo.getStoreLock(); tikhomirov@631: wcLock.acquire(); tikhomirov@631: System.out.print("."); tikhomirov@631: storeLock.acquire(); tikhomirov@631: System.out.print("."); tikhomirov@631: try { tikhomirov@631: new HgStatusCommand(hgRepo).execute(new TestStatus.StatusCollector()); tikhomirov@631: System.out.printf("%d ms)\n", (System.nanoTime() - start) / 1000000); tikhomirov@631: } finally { tikhomirov@631: storeLock.release(); tikhomirov@631: wcLock.release(); tikhomirov@631: } tikhomirov@631: } catch (RuntimeException ex) { tikhomirov@631: throw ex; tikhomirov@631: } catch (Exception ex) { tikhomirov@631: ex.printStackTrace(); tikhomirov@631: throw new RuntimeException(null, ex); tikhomirov@631: } tikhomirov@631: } tikhomirov@631: tikhomirov@631: private static void commit(File repoLoc, String message) throws Exception { tikhomirov@631: OutputParser.Stub p = new OutputParser.Stub(); tikhomirov@631: final ExecHelper eh = new ExecHelper(p, repoLoc); tikhomirov@631: eh.run("hg", "commit", "--addremove", "-m", "\"" + message + "\""); tikhomirov@631: if (eh.getExitValue() != 0) { tikhomirov@631: System.out.println(p.result()); tikhomirov@631: } tikhomirov@631: Assert.assertEquals(0, eh.getExitValue()); tikhomirov@631: } tikhomirov@631: tikhomirov@631: private static void sleep(int msBase, int msDelta) { tikhomirov@631: try { tikhomirov@631: Thread.sleep(msBase + Math.round(Math.random() * msDelta)); tikhomirov@631: } catch (InterruptedException ex) { tikhomirov@631: // IGNORE tikhomirov@631: } tikhomirov@631: } tikhomirov@615: }