Mercurial > hg4j
changeset 605:c56edf42be64
Commit: update active bookmark with new revision
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 06 May 2013 20:28:21 +0200 |
parents | c3505001a42a |
children | 5daa42067e7c |
files | src/org/tmatesoft/hg/internal/CommitFacility.java src/org/tmatesoft/hg/repo/HgBookmarks.java src/org/tmatesoft/hg/repo/HgRepositoryLock.java test/org/tmatesoft/hg/test/TestCommit.java |
diffstat | 4 files changed, 106 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/CommitFacility.java Mon May 06 18:53:04 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/CommitFacility.java Mon May 06 20:28:21 2013 +0200 @@ -180,7 +180,7 @@ byte[] clogContent = changelogBuilder.build(manifestRev, message); RevlogStreamWriter changelogWriter = new RevlogStreamWriter(repo, repo.getImplAccess().getChangelogStream()); Nodeid changesetRev = changelogWriter.addRevision(clogContent, clogRevisionIndex, p1Commit, p2Commit); - // FIXME move fncache update to an external facility, along with dirstate update + // FIXME move fncache update to an external facility, along with dirstate and bookmark update if (!newlyAddedFiles.isEmpty() && repo.fncacheInUse()) { FNCacheFile fncache = new FNCacheFile(repo); for (Path p : newlyAddedFiles) { @@ -204,6 +204,12 @@ } dirstateBuilder.parents(changesetRev, Nodeid.NULL); dirstateBuilder.serialize(); + // update bookmarks + Nodeid p1Cset = p1Commit == NO_REVISION ? null : clog.getRevision(p1Commit); + Nodeid p2Cset = p2Commit == NO_REVISION ? null : clog.getRevision(p2Commit); + if (p1Commit != NO_REVISION || p2Commit != NO_REVISION) { + repo.getRepo().getBookmarks().updateActive(p1Cset, p2Cset, changesetRev); + } return changesetRev; } /*
--- a/src/org/tmatesoft/hg/repo/HgBookmarks.java Mon May 06 18:53:04 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgBookmarks.java Mon May 06 20:28:21 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,20 +16,28 @@ */ package org.tmatesoft.hg.repo; +import static org.tmatesoft.hg.util.LogFacility.Severity.Error; + import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import org.tmatesoft.hg.core.HgIOException; +import org.tmatesoft.hg.core.HgRepositoryLockException; import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.internal.Experimental; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.LineReader; import org.tmatesoft.hg.util.LogFacility; /** * + * @see http://mercurial.selenic.com/wiki/Bookmarks * @author Artem Tikhomirov * @author TMate Software Ltd. */ @@ -114,4 +122,61 @@ // hence can use view (not a synchronized copy) here return Collections.unmodifiableSet(bookmarks.keySet()); } + + /** + * Update currently bookmark with new commit. + * Note, child has to be descendant of a p1 or p2 + * + * @param p1 first parent, or <code>null</code> + * @param p2 second parent, or <code>null</code> + * @param child new commit, descendant of one of the parents, not <code>null</code> + * @throws HgIOException if failed to write updated bookmark information + * @throws HgRepositoryLockException if failed to lock repository for modifications + */ + @Experimental(reason="Provisional API") + public void updateActive(Nodeid p1, Nodeid p2, Nodeid child) throws HgIOException, HgRepositoryLockException { + if (activeBookmark == null) { + return; + } + Nodeid activeRev = getRevision(activeBookmark); + if (!activeRev.equals(p1) && !activeRev.equals(p2)) { + // from the wiki: + // "active bookmarks are automatically updated when committing to the changeset they are pointing to" + // FIXME: test ci 1, hg bookmark active, ci 2, hg bookmark -f -r 0 active, ci 3, check active still points to r0 + return; + } + if (child.equals(activeRev)) { + return; + } + LinkedHashMap<String, Nodeid> copy = new LinkedHashMap<String, Nodeid>(bookmarks); + copy.put(activeBookmark, child); + bookmarks = copy; + write(); + } + + private void write() throws HgIOException, HgRepositoryLockException { + File bookmarksFile = internalRepo.getRepositoryFile(HgRepositoryFiles.Bookmarks); + HgRepositoryLock workingDirLock = internalRepo.getRepo().getWorkingDirLock(); + FileWriter fileWriter = null; + workingDirLock.acquire(); + try { + fileWriter = new FileWriter(bookmarksFile); + for (String bm : bookmarks.keySet()) { + Nodeid nid = bookmarks.get(bm); + fileWriter.write(String.format("%s %s\n", nid.toString(), bm)); + } + fileWriter.flush(); + } catch (IOException ex) { + throw new HgIOException("Failed to serialize bookmarks", ex, bookmarksFile); + } finally { + try { + if (fileWriter != null) { + fileWriter.close(); + } + } catch (IOException ex) { + internalRepo.getSessionContext().getLog().dump(getClass(), Error, ex, null); + } + workingDirLock.release(); + } + } }
--- a/src/org/tmatesoft/hg/repo/HgRepositoryLock.java Mon May 06 18:53:04 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRepositoryLock.java Mon May 06 20:28:21 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -99,7 +99,7 @@ /** * Perform actual locking. Waits for timeout (if specified at construction time) - * before throwing {@link HgInvalidStateException} in case lock is not available + * before throwing {@link HgRepositoryLockException} in case lock is not available * immediately. * * <p>Multiple calls are possible, but corresponding number of {@link #release()}
--- a/test/org/tmatesoft/hg/test/TestCommit.java Mon May 06 18:53:04 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestCommit.java Mon May 06 20:28:21 2013 +0200 @@ -277,6 +277,37 @@ assertHgVerifyOk(repoLoc); } + @Test + public void testUpdateActiveBookmark() throws Exception { + File repoLoc = RepoUtils.cloneRepoToTempLocation("log-1", "test-commit-cmd", false); + ExecHelper eh = new ExecHelper(new OutputParser.Stub(), repoLoc); + String activeBookmark = "bm1"; + eh.run("hg", "bookmarks", activeBookmark); + + HgRepository hgRepo = new HgLookup().detect(repoLoc); + assertEquals("[sanity]", activeBookmark, hgRepo.getBookmarks().getActiveBookmarkName()); + Nodeid activeBookmarkRevision = hgRepo.getBookmarks().getRevision(activeBookmark); + assertEquals("[sanity]", activeBookmarkRevision, hgRepo.getWorkingCopyParents().first()); + + HgDataFile dfD = hgRepo.getFileNode("d"); + File fileD = new File(repoLoc, "d"); + assertTrue("[sanity]", dfD.exists()); + assertTrue("[sanity]", fileD.canRead()); + + RepoUtils.modifyFileAppend(fileD, " 1 \n"); + HgCommitCommand cmd = new HgCommitCommand(hgRepo).message("FIRST"); + Outcome r = cmd.execute(); + errorCollector.assertTrue(r.isOk()); + Nodeid c = cmd.getCommittedRevision(); + + errorCollector.assertEquals(activeBookmark, hgRepo.getBookmarks().getActiveBookmarkName()); + errorCollector.assertEquals(c, hgRepo.getBookmarks().getRevision(activeBookmark)); + // reload repo, and repeat the check + hgRepo = new HgLookup().detect(repoLoc); + errorCollector.assertEquals(activeBookmark, hgRepo.getBookmarks().getActiveBookmarkName()); + errorCollector.assertEquals(c, hgRepo.getBookmarks().getRevision(activeBookmark)); + } + private void assertHgVerifyOk(File repoLoc) throws InterruptedException, IOException { ExecHelper verifyRun = new ExecHelper(new OutputParser.Stub(), repoLoc); verifyRun.run("hg", "verify");