changeset 484:ae4d6604debd

Bookmarks support added
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 08 Aug 2012 14:41:44 +0200
parents e31e85cf4d4c
children cdd53e5884ae
files cmdline/org/tmatesoft/hg/console/Main.java src/org/tmatesoft/hg/repo/HgBookmarks.java src/org/tmatesoft/hg/repo/HgRepository.java src/org/tmatesoft/hg/repo/HgRepositoryFiles.java
diffstat 4 files changed, 156 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/cmdline/org/tmatesoft/hg/console/Main.java	Tue Aug 07 19:14:53 2012 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Main.java	Wed Aug 08 14:41:44 2012 +0200
@@ -53,6 +53,7 @@
 import org.tmatesoft.hg.internal.RelativePathRewrite;
 import org.tmatesoft.hg.internal.RevisionDescendants;
 import org.tmatesoft.hg.internal.StreamLogFacility;
+import org.tmatesoft.hg.repo.HgBookmarks;
 import org.tmatesoft.hg.repo.HgBranches;
 import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
@@ -111,7 +112,8 @@
 
 	public static void main(String[] args) throws Exception {
 		Main m = new Main(args);
-		m.readConfigFile();
+		m.dumpBookmarks();
+//		m.readConfigFile();
 //		m.dumpCommitLastMessage();
 //		m.buildFileLog();
 //		m.testConsoleLog();
@@ -133,6 +135,22 @@
 //		m.dumpCompleteManifestHigh();
 //		m.bunchOfTests();
 	}
+	
+	// TODO as test
+	private void dumpBookmarks() throws Exception {
+		HgBookmarks bm = hgRepo.getBookmarks();
+		String active = bm.getActiveBookmarkName();
+		ArrayList<String> all = new ArrayList(bm.getAllBookmarks());
+		Collections.sort(all);
+		for (String bmname : all) {
+			if (bmname.equals(active)) {
+				System.out.print(" * ");
+			} else {
+				System.out.print("   ");
+			}
+			System.out.printf("%-26s (%s)\n", bmname, bm.getRevision(bmname).shortNotation());
+		}
+	}
 
 	// TODO as test
 	private void readConfigFile() throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tmatesoft/hg/repo/HgBookmarks.java	Wed Aug 08 14:41:44 2012 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 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
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * For information on how to redistribute this software under
+ * the terms of a license other than GNU General Public License
+ * contact TMate Software at support@hg4j.com
+ */
+package org.tmatesoft.hg.repo;
+
+import java.io.File;
+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.Nodeid;
+import org.tmatesoft.hg.internal.LineReader;
+import org.tmatesoft.hg.util.LogFacility;
+
+/**
+ * 
+ * @author Artem Tikhomirov
+ * @author TMate Software Ltd.
+ */
+public final class HgBookmarks {
+	private final HgRepository repo;
+	private Map<String, Nodeid> bookmarks = Collections.emptyMap();
+	private String activeBookmark; 
+
+	HgBookmarks(HgRepository hgRepo) {
+		repo = hgRepo;
+	}
+	
+	/*package-local*/ void read() throws HgInvalidControlFileException {
+		final LogFacility log = repo.getContext().getLog();
+		File all = new File (repo.getRepositoryRoot(), HgRepositoryFiles.Bookmarks.getName());
+		LinkedHashMap<String, Nodeid> bm = new LinkedHashMap<String, Nodeid>();
+		if (all.canRead()) {
+			LineReader lr1 = new LineReader(all, log);
+			ArrayList<String> c = new ArrayList<String>();
+			lr1.read(new LineReader.SimpleLineCollector(), c);
+			for (String s : c) {
+				int x = s.indexOf(' ');
+				try {
+					if (x > 0) {
+						Nodeid nid = Nodeid.fromAscii(s.substring(0, x));
+						String name = new String(s.substring(x+1));
+						if (repo.getChangelog().isKnown(nid)) {
+							// copy name part not to drag complete line
+							bm.put(name, nid);
+						} else {
+							log.dump(getClass(), LogFacility.Severity.Info, "Bookmark %s points to non-existent revision %s, ignored.", name, nid);
+						}
+					} else {
+						log.dump(getClass(), LogFacility.Severity.Warn, "Can't parse bookmark entry: %s", s);
+					}
+				} catch (IllegalArgumentException ex) {
+					log.dump(getClass(), LogFacility.Severity.Warn, ex, String.format("Can't parse bookmark entry: %s", s));
+				}
+			}
+			bookmarks = bm;
+		} else {
+			bookmarks = Collections.emptyMap();
+		}
+		
+		activeBookmark = null;
+		File active = new File(repo.getRepositoryRoot(), HgRepositoryFiles.BookmarksCurrent.getName());
+		if (active.canRead()) {
+			LineReader lr2 = new LineReader(active, repo.getContext().getLog());
+			ArrayList<String> c = new ArrayList<String>(2);
+			lr2.read(new LineReader.SimpleLineCollector(), c);
+			if (c.size() > 0) {
+				activeBookmark = c.get(0);
+			}
+		}
+	}
+
+	/**
+	 * Tell name of the active bookmark 
+	 * @return <code>null</code> if none active
+	 */
+	public String getActiveBookmarkName() {
+		return activeBookmark;
+	}
+
+	/**
+	 * Retrieve revision associated with the named bookmark.
+	 * 
+	 * @param bookmarkName name of the bookmark
+	 * @return revision or <code>null</code> if bookmark is not known
+	 */
+	public Nodeid getRevision(String bookmarkName) {
+		return bookmarks.get(bookmarkName);
+	}
+
+	/**
+	 * Retrieve all bookmarks known in the repository
+	 * @return collection with names, never <code>null</code>
+	 */
+	public Collection<String> getAllBookmarks() {
+		// bookmarks are initialized with atomic assignment,
+		// hence can use view (not a synchronized copy) here
+		return Collections.unmodifiableSet(bookmarks.keySet());
+	}
+}
--- a/src/org/tmatesoft/hg/repo/HgRepository.java	Tue Aug 07 19:14:53 2012 +0200
+++ b/src/org/tmatesoft/hg/repo/HgRepository.java	Wed Aug 08 14:41:44 2012 +0200
@@ -111,6 +111,7 @@
 	private HgBranches branches;
 	private HgMergeState mergeState;
 	private SubrepoManager subRepos;
+	private HgBookmarks bookmarks;
 
 	// XXX perhaps, shall enable caching explicitly
 	private final HashMap<Path, SoftReference<RevlogStream>> streamsCache = new HashMap<Path, SoftReference<RevlogStream>>();
@@ -233,6 +234,8 @@
 	}
 	
 	/**
+	 * Access branch information
+	 * @return branch manager instance, never <code>null</code>
 	 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
 	 */
 	public HgBranches getBranches() throws HgInvalidControlFileException {
@@ -243,6 +246,10 @@
 		return branches;
 	}
 
+	/**
+	 * Access state of the recent merge
+	 * @return merge state facility, never <code>null</code> 
+	 */
 	public HgMergeState getMergeState() {
 		if (mergeState == null) {
 			mergeState = new HgMergeState(this);
@@ -413,6 +420,19 @@
 			}
 		}
 	}
+	
+	/**
+	 * Access bookmarks-related functionality
+	 * @return facility to manage bookmarks, never <code>null</code>
+	 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
+	 */
+	public HgBookmarks getBookmarks() throws HgInvalidControlFileException {
+		if (bookmarks == null) {
+			bookmarks = new HgBookmarks(this);
+			bookmarks.read();
+		}
+		return bookmarks;
+	}
 
 	/*package-local*/ DataAccessProvider getDataAccess() {
 		return dataAccess;
--- a/src/org/tmatesoft/hg/repo/HgRepositoryFiles.java	Tue Aug 07 19:14:53 2012 +0200
+++ b/src/org/tmatesoft/hg/repo/HgRepositoryFiles.java	Wed Aug 08 14:41:44 2012 +0200
@@ -28,7 +28,8 @@
 	HgIgnore(".hgignore"), HgTags(".hgtags"), HgEol(".hgeol"), 
 	Dirstate(false, "dirstate"), HgLocalTags(false, "localtags"),
 	HgSub(".hgsub"), HgSubstate(".hgsubstate"),
-	LastMessage(false, "last-message.txt");
+	LastMessage(false, "last-message.txt"),
+	Bookmarks(false, "bookmarks"), BookmarksCurrent(false, "bookmarks.current");
 
 	private final String fname;
 	private final boolean livesInWC;