Fixes from other repo.
diff --git a/alien/src/wormarc/ExternalRefs.java b/alien/src/wormarc/ExternalRefs.java
--- a/alien/src/wormarc/ExternalRefs.java
+++ b/alien/src/wormarc/ExternalRefs.java
@@ -129,7 +129,8 @@ public final class ExternalRefs {
StringBuilder buffer = new StringBuilder();
buffer.append(String.format("--- %sExternalRefs ---\n", labelWithTrailingSpace));
for (Reference ref: mRefs) {
- buffer.append(String.format(" [%d]:%s\n", ref.mKind, ref.mExternalKey));
+ buffer.append(String.format(" [%d]:%s (%s)\n", ref.mKind, ref.mExternalKey,
+ IOUtil.getHexDigest(ref.mExternalKey, 8)));
}
buffer.append("---");
return buffer.toString();
diff --git a/alien/src/wormarc/IOUtil.java b/alien/src/wormarc/IOUtil.java
--- a/alien/src/wormarc/IOUtil.java
+++ b/alien/src/wormarc/IOUtil.java
@@ -122,6 +122,17 @@ public class IOUtil {
}
}
+ public static String getHexDigest(String value, int numBytes) {
+ try {
+ if (value == null) {
+ return "???";
+ }
+ return IOUtil.getFileDigest(IOUtil.toStreamAsUtf8(value)).hexDigest(numBytes);
+ } catch (IOException ioe) {
+ return "???";
+ }
+ }
+
public final static void copyAndClose(InputStream fromStream, String toFileName) throws IOException {
copyAndClose(fromStream, new FileOutputStream(toFileName));
}
diff --git a/alien/src/wormarc/io/BlobIO.java b/alien/src/wormarc/io/BlobIO.java
--- a/alien/src/wormarc/io/BlobIO.java
+++ b/alien/src/wormarc/io/BlobIO.java
@@ -55,7 +55,7 @@ public class BlobIO implements Archive.I
// REQUIRES: Length must not change.
protected final static String VERSION_1 = "BLOB0001";
- // Anything that you can read or write a BLOB to.
+ // Anything that you can read or write a BLOB from/to.
public interface StreamFactory {
InputStream getInputStream() throws IOException;
OutputStream getOutputStream() throws IOException;
diff --git a/doc/latest_release.txt b/doc/latest_release.txt
--- a/doc/latest_release.txt
+++ b/doc/latest_release.txt
@@ -1,18 +1,6 @@
-Fixed the "Discover" page to draw lines for rebased versions.
+Fixed bug on the "Discover" page that caused lines to be drawn incorrectly
+in some cases for graphs with rebased versions.
-Added preliminary support for file diffs on the "Edit" page.
-It needs layout / CSS cleanup but it works.
+Use .zip instead of .tgz for source release.
-Added <<<ArchiveVersion>>> macro to print the 16 digit hex version
-of the current archive.
-Added <<<ArchiveUri>>> macro to print a link to the archive SSK
-that the current wiki version was loaded from.
-
-These macros where added so that people viewing dumped wiki
-freesites can tell which version / uri the wiki was
-dumped from.
-
-Release notes for previous version:
-USK@kRM~jJVREwnN2qnA8R0Vt8HmpfRzBZ0j4rHC2cQ-0hw,2xcoQVdQLyqfTpF2DpkdUIbHFCeL4W~2X1phUYymnhM,AQACAAE/jfniki_releases/2/
-
diff --git a/readme.txt b/readme.txt
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
-20110605
+20110611
djk@isFiaD04zgAgnrEC5XJt1i4IE7AkNPqhBG5bONi6Yks
WARNING:
@@ -121,7 +121,9 @@ IDEA: Freetalk vs Freenet interop
Hmmm... not sure if people would use this feature because of the correlation of ids.
---
Fixed bugs:
-8cfb2f3e7c38 BUG: Default FCP port wrong for CLI client. [requested by a real user]
+238c7dcc5ae3: BUG: incorrect drawing of rebased changes on discover page (since b963650876a7).
+ [The plausable commit order code was just wrong. Fixed it I hope.]
+8cfb2f3e7c38: BUG: Default FCP port wrong for CLI client. [requested by a real user]
[The default port is set to 9481 now and can be set via Java System properties. See ./script/wa.sh]
710d700bc7a1: BUG: Header links to discussion pages. [requested by a real user]
2ce3a4499a2c: BUG: No way to create an empty wiki from the UI. [requested by a real user]
diff --git a/release/cut_release.py b/release/cut_release.py
--- a/release/cut_release.py
+++ b/release/cut_release.py
@@ -25,8 +25,8 @@
# It is brittle and not fully debugged.
# It assumes you have hg infocalypse installed and configured.
#
-# BUG: ANONYMITY ISSUE: This script currently leaks the *nix user id
-# into the inserted .tgz and .jar files.
+# POSSIBLE BUG: ANONYMITY ISSUE: This script may leak the *nix user id into the .jar file.
+# Need to audit.
# DO NOT RUN IT if this concerns you.
#
import os
@@ -43,6 +43,10 @@ from minimalfms import get_connection, s
############################################################
+# For testing this script.
+#JUST_STAGE = True
+JUST_STAGE = False
+
# CAUTION: This directory is recursively deleted!
STAGING_DIR = '/tmp/staging'
@@ -63,11 +67,11 @@ PUBLIC_SITE = "USK@kRM~jJVREwnN2qnA8R0Vt
SITE_NAME
############################################################
-# Indexes of refereneced USK sites
+# Indexes of referenced USK sites
-FREENET_DOC_WIKI_IDX = 34
+FREENET_DOC_WIKI_IDX = 40
FNIKI_IDX = 84
-REPO_IDX = 17
+REPO_IDX = 18
############################################################
@@ -82,6 +86,15 @@ FMS_MESSAGE_TEMPLATE = os.path.abspath(o
############################################################
+def zip_source(staging_dir, source_dir, zip_file_name):
+ subprocess.check_call(['/usr/bin/zip',
+ '-r',
+ '-9', # best compression
+ zip_file_name,
+ source_dir],
+ # LATER: Better way to supress full path in zip?
+ cwd=staging_dir)
+
def stage_release():
# LATER: check for uncommitted changes
ui_ = ui.ui()
@@ -93,10 +106,10 @@ def stage_release():
head = heads[0]
jar_name = "jfniki.%s.jar" % head
- tgz_name = "jfniki.%s.tgz" % head
+ zip_name = "jfniki.%s.zip" % head
export_dir_name = "jfniki.%s" % head
- tgz_file_name = "%s/%s" % (STAGING_DIR, tgz_name)
+ zip_file_name = "%s/%s" % (STAGING_DIR, zip_name)
jar_file_name = "%s/%s" % (STAGING_DIR, jar_name)
# scrub staging directory
@@ -120,17 +133,8 @@ def stage_release():
# remove origin tarballs to save space
shutil.rmtree("%s/alien/origins/" % dest)
- # tar up source
- tgz_file = tarfile.open(tgz_file_name, 'w:gz')
-
- #def reset(tarinfo):
- # tarinfo.uid = tarinfo.gid = 0
- # tarinfo.uname = tarinfo.gname = "root"
- # return tarinfo
- # LATER: Use line after upgrading python. Keeps uid, gid, uname out of tar.
- # tgz_file.add("%s/%s" % (STAGING_DIR, export_dir_name), arcname=export_dir_name, filter=reset) # python 2.7
- tgz_file.add("%s/%s" % (STAGING_DIR, export_dir_name), arcname=export_dir_name)
- tgz_file.close()
+ # zip up the source.
+ zip_source(STAGING_DIR, export_dir_name, zip_file_name)
# cp freenet.jar required for build
os.makedirs("%s/%s/%s" % (STAGING_DIR, export_dir_name, "alien/libs"))
@@ -148,9 +152,9 @@ def stage_release():
print
print "SUCCESSFULLY STAGED:"
print jar_file_name
- print tgz_file_name
+ print zip_file_name
print
- return (head, jar_file_name, tgz_file_name)
+ return (head, jar_file_name, zip_file_name)
def simple_templating(text, substitutions):
@@ -188,7 +192,7 @@ def html_escape(text):
############################################################
-def update_html(head, jar_chk, tgz_chk):
+def update_html(head, jar_chk, zip_chk):
ui_ = ui.ui()
repo = hg.repository(ui_, REPO_DIR)
site_usk = PUBLIC_SITE % (latest_site_index(repo) + 1)
@@ -196,7 +200,7 @@ def update_html(head, jar_chk, tgz_chk):
html = simple_templating(open(INDEX_HTML_TEMPLATE).read(),
{'__HEAD__':head,
'__JAR_CHK__': jar_chk,
- '__SRC_CHK__': tgz_chk,
+ '__SRC_CHK__': zip_chk,
'__RELEASE_NOTES__' : html_escape(open(RELEASE_NOTES).read()),
'__SITE_USK__': site_usk,
'__INDEX_FDW__': FREENET_DOC_WIKI_IDX,
@@ -240,14 +244,14 @@ def insert_freesite():
# LATER: Do better. Parse request URI from output.
return PUBLIC_SITE % target_index, target_index
-def send_fms_notification(site_uri, target_index, head, jar_chk, tgz_chk):
+def send_fms_notification(site_uri, target_index, head, jar_chk, zip_chk):
connection = get_connection(FMS_HOST, FMS_PORT, FMS_ID)
msg = simple_templating(open(FMS_MESSAGE_TEMPLATE).read(),
{'__HEAD__':head,
'__JAR_CHK__': jar_chk,
- '__SRC_CHK__': tgz_chk,
+ '__SRC_CHK__': zip_chk,
'__SITE_USK__' : site_uri,
'__RELEASE_NOTES__' : open(RELEASE_NOTES).read(),
})
@@ -270,11 +274,15 @@ def release():
print
print "------------------------------------------------------------"
- head, jar_file, tgz_file = stage_release()
- jar_chk, tgz_chk = insert_files(FCP_HOST, FCP_PORT, [jar_file, tgz_file])
- update_html(head, jar_chk, tgz_chk)
+ head, jar_file, zip_file = stage_release()
+
+ if JUST_STAGE:
+ return
+
+ jar_chk, zip_chk = insert_files(FCP_HOST, FCP_PORT, [jar_file, zip_file])
+ update_html(head, jar_chk, zip_chk)
site_uri, target_index = insert_freesite()
- send_fms_notification(site_uri, target_index, head, jar_chk, tgz_chk)
+ send_fms_notification(site_uri, target_index, head, jar_chk, zip_chk)
print
print "Success!"
diff --git a/script/graphtest.sh b/script/graphtest.sh
new file mode 100755
--- /dev/null
+++ b/script/graphtest.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+# Script to run GraphLog.java code from a text file for debugging.
+
+export set SCRIPT_DIR=`dirname $0`
+. "${SCRIPT_DIR}/setup_env.sh"
+
+${JAVA_CMD} -classpath ${JAR_FILE}:${FN_JAR_FILE} fniki.wiki.GraphLog "$@"
diff --git a/src/fniki/freenet/plugin/Fniki.java b/src/fniki/freenet/plugin/Fniki.java
--- a/src/fniki/freenet/plugin/Fniki.java
+++ b/src/fniki/freenet/plugin/Fniki.java
@@ -105,7 +105,7 @@ public class Fniki implements FredPlugin
continue;
}
mParamTable.put(name, mParent.getParam(name));
- System.err.println("Set Param: " + name + " : " + mParamTable.get(name));
+ //System.err.println("Set Param: " + name + " : " + mParamTable.get(name));
}
// Then read multipart params if there are any.
@@ -118,8 +118,8 @@ public class Fniki implements FredPlugin
String value = new String(mParent.getPartAsBytesFailsafe(part, 64 * 1024), "utf-8");
mParamTable.put(part, value);
- System.err.println("Set multipart Param: " + part + " : " +
- mParamTable.get(part));
+ // System.err.println("Set multipart Param: " + part + " : " +
+ // mParamTable.get(part));
}
} catch (UnsupportedEncodingException ue) {
// Shouldn't happen.
@@ -157,7 +157,7 @@ public class Fniki implements FredPlugin
throw new RuntimeException("Request doesn't start with: " + containerPrefix);
}
- System.err.println("Raw path: " + path);
+ //System.err.println("Raw path: " + path);
path = path.substring(containerPrefix.length());
while(path.startsWith("/")) {
diff --git a/src/fniki/standalone/FnikiContextHandler.java b/src/fniki/standalone/FnikiContextHandler.java
--- a/src/fniki/standalone/FnikiContextHandler.java
+++ b/src/fniki/standalone/FnikiContextHandler.java
@@ -63,7 +63,7 @@ public class FnikiContextHandler impleme
}
baos.write(oneByte);
}
- System.err.println("read part bytes: " + baos.toByteArray().length);
+ //System.err.println("read part bytes: " + baos.toByteArray().length);
return new String(baos.toByteArray(), "utf8");
}
@@ -76,7 +76,7 @@ public class FnikiContextHandler impleme
if (!parentParams.containsKey(name)) {
continue;
}
- System.err.println("Set Param: " + name + " : " + parentParams.get(name));
+ //System.err.println("Set Param: " + name + " : " + parentParams.get(name));
mParamTable.put(name, parentParams.get(name));
}
@@ -90,10 +90,10 @@ public class FnikiContextHandler impleme
continue;
}
mParamTable.put(part.name, readAsUtf8(part));
- System.err.println(String.format("Set multipart Param: %s[%d]:\n%s",
- part.name,
- mParamTable.get(part.name).length(),
- mParamTable.get(part.name)));
+ // System.err.println(String.format("Set multipart Param: %s[%d]:\n%s",
+ // part.name,
+ // mParamTable.get(part.name).length(),
+ // mParamTable.get(part.name)));
}
mParent.consumeBody();
}
@@ -127,7 +127,7 @@ public class FnikiContextHandler impleme
throw new RuntimeException("Request doesn't start with: " + containerPrefix);
}
- System.err.println("Raw path: " + path);
+ //System.err.println("Raw path: " + path);
path = path.substring(containerPrefix.length());
while(path.startsWith("/")) {
diff --git a/src/fniki/wiki/ArchiveManager.java b/src/fniki/wiki/ArchiveManager.java
--- a/src/fniki/wiki/ArchiveManager.java
+++ b/src/fniki/wiki/ArchiveManager.java
@@ -375,9 +375,12 @@ public class ArchiveManager {
}
public List<FMSUtil.BISSRecord> getRecentWikiVersions(PrintStream out) throws IOException {
+ out.println("Reading version announcements via NNTP...");
+
List<FMSUtil.BISSRecord> records =
FMSUtil.getBISSRecords(mFmsHost, mFmsPort, mFmsId, mFmsGroup, mBissName, MAX_VERSIONS);
+ out.println("Finished reading. Processing...");
// LATER: do better.
for (FMSUtil.BISSRecord record : records) {
String fields[] = record.mFmsId.split("@");
@@ -394,6 +397,7 @@ public class ArchiveManager {
mNymLut.put(fields[1].trim(), fields[0].trim());
}
+ out.println("Finished processing.");
return records;
}
diff --git a/src/fniki/wiki/GraphLog.java b/src/fniki/wiki/GraphLog.java
--- a/src/fniki/wiki/GraphLog.java
+++ b/src/fniki/wiki/GraphLog.java
@@ -374,7 +374,7 @@ public class GraphLog {
}
// A directed graph node.
- public static class DAGNode {
+ public static class DAGNode implements Comparable<DAGNode> {
public final String mTag;
public final int mId;
public final List<Integer> mParentIds;
@@ -383,6 +383,9 @@ public class GraphLog {
mId = id;
mParentIds = parentIds;
}
+ public int compareTo(DAGNode other) {
+ return other.mId - mId; // Descending order of integer id.
+ }
public String asString() {
return "{" + mTag + ", " + mId + ", " + GraphLog.prettyString_(mParentIds) + "}";
@@ -459,13 +462,10 @@ public class GraphLog {
static class ParentInfo {
public final Set<String> mAllParents;
- public final Set<String> mUnseenParents;
public final Set<String> mRootIds;
public ParentInfo(Set<String> allParents,
- Set<String> unseenParents,
Set<String> rootIds) {
mAllParents = allParents;
- mUnseenParents = unseenParents;
mRootIds = rootIds;
}
}
@@ -492,6 +492,19 @@ public class GraphLog {
}
}
+ static void remove_edges(List<GraphEdge> edges, String matchingFrom) {
+ while (true) {
+ top_of_while:
+ for (int index = 0; index < edges.size(); index++) {
+ if (edges.get(index).mFrom.equals(matchingFrom)) {
+ edges.remove(index);
+ continue top_of_while; // for
+ }
+ }
+ break; // while
+ }
+ }
+
static Set<String> allDescendants(Map<String, Set<String>> graph, String leaf_id) {
Set<String> seen = new HashSet<String>();
List<String> stack = new ArrayList<String>();
@@ -578,39 +591,6 @@ public class GraphLog {
return graph;
}
- // IMPORTANT: The "reversed" graph is what you need to traverse to build the DAG.
- // Take a graph which maps node ids -> set of parents and create a graph
- // which maps node ids -> set of children from it.
- static Map<String, Set<String>> get_reversed_graph(Map<String, Set<String>> graph,
- Set<String> root_ids,
- OrdinalMapper ordinals) {
- Map<String, Set<String>> reversed_graph = new HashMap<String, Set<String>>();
-
- for(Map.Entry<String, Set<String>> entry : graph.entrySet()) {
- String key = entry.getKey();
- Set<String> parents = entry.getValue();
-
- for (String parent : parents) {
- if (!graph.keySet().contains(parent)) {
- continue;
- }
-
- if (!reversed_graph.keySet().contains(parent)) {
- reversed_graph.put(parent, new HashSet<String>());
- }
-
- //# i.e. is a child of the parent
- reversed_graph.get(parent).add(key);
- }
-
- //# For leaf nodes.
- if (!reversed_graph.keySet().contains(key)) {
- reversed_graph.put(key, new HashSet<String>());
- }
- }
- return reversed_graph;
- }
-
// DCI: fix name
public static ParentInfo getParentInfo(Map<String, Set<String>> graph) {
Set<String> allParents = new HashSet<String>();
@@ -645,107 +625,96 @@ public class GraphLog {
}
}
- return new ParentInfo(allParents, unseenParents, rootIds);
+ return new ParentInfo(allParents, rootIds);
}
- // LATER: Grok harder. Possible to get rid of this?
- //# Breadth first traversal of the graph to force creation of ordinals
- //# in an order that won't freak out the drawing code.
- static void traverse_in_plausible_commit_order(Map<String, Set<String>> reversed_graph,
- Set<String> root_ids,
- OrdinalMapper ordinals) {
+ // Graph maps from child -> list of parents (i.e. like a commit DAG).
+ static void set_ordinals_in_plausible_commit_order(Map<String, Set<String>> graph,
+ OrdinalMapper ordinals) {
- LinkedList<String> queue = new LinkedList<String>();
- queue.addAll(root_ids);
- Collections.sort(queue);
+ // Make a list of all parent to child edges.
+ // Each edge represents the constraint "the ordinal of this parent is less
+ // than the ordinal of this child".
+ List<GraphEdge> edges = new ArrayList<GraphEdge>();
+ Set<String> leaf_nodes = new HashSet<String>();
+ for (Map.Entry<String, Set<String>> entry : graph.entrySet()) {
+ String child = entry.getKey();
+ Set<String> parents = entry.getValue();
+ if (parents.size() == 0) {
+ leaf_nodes.add(child);
+ continue;
+ }
- //# Force creation of ordinals for root nodes
- for (String id_value : queue) {
- ordinals.ordinal(id_value);
+ for (String parent : parents) {
+ edges.add(new GraphEdge(parent, child));
+ }
}
- Set<String> seen = new HashSet<String>();
- while (queue.size() > 0) {
- String id_value = queue.removeFirst();
- if (seen.contains(id_value)) {
- continue;
+ while (!edges.isEmpty()) {
+ // Find edges to vertices that no other edges reference.
+ Set<String> candidates = new HashSet<String>();
+ Set<String> referenced = new HashSet<String>();
+ for (GraphEdge edge : edges) {
+ candidates.add(edge.mFrom);
+ referenced.add(edge.mTo);
}
- seen.add(id_value);
+ // i.e. "the parents which no remaining children reference."
+ // Implies must have lower ordinals than all unprocessed children.
+ candidates.removeAll(referenced);
+ assert_(candidates.size() > 0);
- // Tricky: Sort to force creation of new ordinals in "natural order"
- // of child ids.
- List<String> child_ids = new ArrayList<String>();
- child_ids.addAll(reversed_graph.get(id_value));
- Collections.sort(child_ids);
+ List<String> sorted = new ArrayList<String>(candidates);
+ Collections.sort(sorted);
+ for (String candidate : sorted) {
+ // Set the ordinal.
+ ordinals.ordinal(candidate);
+ // Remove any unreferenced edges from the list.
+ // LATER: fix crappy code. do in one pass outside loop.
+ remove_edges(edges, candidate);
+ }
+ }
- for (String child_id : child_ids) {
- ordinals.ordinal(child_id);
- queue.add(child_id);
- }
+ // Set the ordinals for nodes which have no children.
+ List<String> sorted_leaf_nodes = new ArrayList<String>(leaf_nodes);
+ Collections.sort(sorted_leaf_nodes);
+ for (String leaf_node : sorted_leaf_nodes) {
+ ordinals.ordinal(leaf_node);
}
}
// Create a list of graph nodes in the correct order so that
// they can be used to draw the graph with the ascii() function.
static List<DAGNode> build_dag(Map<String, Set<String>> graph, String null_rev_name) {
- ParentInfo parentInfo = getParentInfo(graph);
- Set<String> all_parents = parentInfo.mAllParents;
- Set<String> unseen_parents = parentInfo.mUnseenParents;
- Set<String> root_ids = parentInfo.mRootIds;
+ assert_(!graph.keySet().contains(null_rev_name));
OrdinalMapper ordinals = new OrdinalMapper();
- Map<String, Set<String>> reversed_graph = get_reversed_graph(graph, root_ids, ordinals);
+ int null_rev_ordinal = ordinals.ordinal(null_rev_name);
//# Important: This sets the graph ordinals correctly.
- traverse_in_plausible_commit_order(reversed_graph, root_ids, ordinals);
-
- int null_rev_ordinal = ordinals.ordinal(null_rev_name);
-
- LinkedList<String> queue = new LinkedList<String>();
- queue.addAll(root_ids);
- Collections.sort(queue);
+ set_ordinals_in_plausible_commit_order(graph, ordinals);
List<DAGNode> dag = new ArrayList<DAGNode>();
- Set<String> seen = new HashSet<String>();
- while (queue.size() > 0) {
- String id_value = queue.removeFirst();
- if (seen.contains(id_value)) {
- continue;
- }
- seen.add(id_value);
+ for(Map.Entry<String, Set<String>> entry : graph.entrySet()) {
+ String child = entry.getKey();
- List<Integer> parents = new ArrayList<Integer>();
- for (String parent_id : graph.get(id_value)) {
- // This accesses ordinals in parent order, but the DAG requires them
- // to be in child order. That's why we need the call to
- // traverse_in_plausible_commit_order above.
- parents.add(ordinals.ordinal(parent_id));
- }
- Collections.sort(parents);
-
- if (parents.size() == 1 && parents.get(0) == null_rev_ordinal) {
- // Causes ascii() not to draw a line down from the 'o'.
- parents = new ArrayList<Integer>();
+ List<Integer> parent_ids = new ArrayList<Integer>();
+ for (String parent : entry.getValue()) {
+ parent_ids.add(ordinals.ordinal(parent));
}
- dag.add(new DAGNode(id_value, ordinals.ordinal(id_value), parents));
-
- if (!reversed_graph.keySet().contains(id_value)) {
- continue;
+ if (parent_ids.size() == 1 && parent_ids.get(0) == null_rev_ordinal) {
+ // Causes ascii() not to draw a line down from the 'o'.
+ parent_ids = new ArrayList<Integer>();
}
- // Tricky: Must traverse in order or the dag nodes won't be right.
- List<String> child_ids = new ArrayList<String>();
- child_ids.addAll(reversed_graph.get(id_value));
- Collections.sort(child_ids);
-
- for (String child_id : child_ids) {
- queue.add(child_id);
- }
+ dag.add(new DAGNode(child, ordinals.ordinal(child), parent_ids));
}
- Collections.reverse(dag);
+ //ordinals.dump();
+
+ // IMPORTANT: Sort in order of descending ordinal otherwise drawing code won't work.
+ Collections.sort(dag);
return dag;
}
diff --git a/src/fniki/wiki/WikiApp.java b/src/fniki/wiki/WikiApp.java
--- a/src/fniki/wiki/WikiApp.java
+++ b/src/fniki/wiki/WikiApp.java
@@ -160,9 +160,9 @@ public class WikiApp implements ChildCon
return mState;
}
- System.err.println(String.format("[%s] => [%s]",
- mState.getClass().getName(),
- container.getClass().getName()));
+ // System.err.println(String.format("[%s] => [%s]",
+ // mState.getClass().getName(),
+ // container.getClass().getName()));
if (mState != null && mState instanceof ModalContainer) {
((ModalContainer)mState).exited();
}
@@ -200,9 +200,9 @@ public class WikiApp implements ChildCon
// Handle transitions out of modal UI states.
ModalContainer state = (ModalContainer)mState;
if (action.equals("finished")) {
- System.err.println("finished");
+ //System.err.println("finished");
if (!state.isFinished()) {
- System.err.println("canceling");
+ //System.err.println("canceling");
state.cancel();
try {
Thread.sleep(250); // HACK
@@ -212,7 +212,7 @@ public class WikiApp implements ChildCon
}
// No "else" because it might have finished while sleeping.
if (state.isFinished()) {
- System.err.println("finished");
+ //System.err.println("finished");
setState(request, mWikiContainer);
return mGotoRedirect;
}
@@ -229,7 +229,7 @@ public class WikiApp implements ChildCon
}
// DCI: Fix. Use a hashmap of paths -> instances for static paths
- System.err.println("WikiApp.routeRequest: " + path);
+ //System.err.println("WikiApp.routeRequest: " + path);
if (path.equals("fniki/config")) {
return setState(request, mSettingConfig);
} else if (path.equals("fniki/submit")) {
@@ -257,7 +257,7 @@ public class WikiApp implements ChildCon
public synchronized String handle(WikiContext context) throws ChildContainerException {
try {
ChildContainer childContainer = routeRequest(context);
- System.err.println("Request routed to: " + childContainer.getClass().getName());
+ //System.err.println("Request routed to: " + childContainer.getClass().getName());
return mFilter.filter(childContainer.handle(context));
} catch (ChildContainerException cce) {
@@ -452,15 +452,15 @@ public class WikiApp implements ChildCon
// Hacks to find bugs
if (!containerRelativePath.startsWith("/")) {
containerRelativePath = "/" + containerRelativePath;
- System.err.println("WikiApp.makeLink -- added leading '/': " +
- containerRelativePath);
+ // System.err.println("WikiApp.makeLink -- added leading '/': " +
+ // containerRelativePath);
(new RuntimeException("find missing /")).printStackTrace();
}
String full = containerPrefix() + containerRelativePath;
while (full.indexOf("//") != -1) {
- System.err.println("WikiApp.makeLink -- fixing '//': " +
- full);
+ // System.err.println("WikiApp.makeLink -- fixing '//': " +
+ // full);
full = full.replace("//", "/");
(new RuntimeException("find extra /")).printStackTrace();
}
diff --git a/src/fniki/wiki/child/AsyncTaskContainer.java b/src/fniki/wiki/child/AsyncTaskContainer.java
--- a/src/fniki/wiki/child/AsyncTaskContainer.java
+++ b/src/fniki/wiki/child/AsyncTaskContainer.java
@@ -147,17 +147,17 @@ public abstract class AsyncTaskContainer
protected void invokeWorkerMethod() {
boolean failed = true;
try {
- System.err.println("Task started: " + mState);
+ //System.err.println("Task started: " + mState);
PrintStream log = new PrintStream(mBuffer, true);
mArchiveManager.setDebugOutput(log);
- failed = !doWork(new PrintStream(mBuffer, true));
+ failed = !doWork(new PrintStream(mBuffer, true));
} catch (Exception e) {
e.printStackTrace();
failed = true;
} finally {
synchronized (this) {
mState = failed ? STATE_FAILED : STATE_SUCCEEDED;
- System.err.println("Task finished: " + mState);
+ //System.err.println("Task finished: " + mState);
mThread = null;
}
}
diff --git a/src/fniki/wiki/child/LoadingVersionList.java b/src/fniki/wiki/child/LoadingVersionList.java
--- a/src/fniki/wiki/child/LoadingVersionList.java
+++ b/src/fniki/wiki/child/LoadingVersionList.java
@@ -1,4 +1,4 @@
-/* A UI subcomponent to load a list of other versions of this wiki via FMS.
+/* A UI subcomponent to load a list of other versions of this wiki via NNTP.
*
* Copyright (C) 2010, 2011 Darrell Karbott
*
@@ -97,19 +97,19 @@ public class LoadingVersionList extends
switch (getState()) {
case STATE_WORKING:
showBuffer = true;
- title = "Loading Wiki Version Info from FMS";
+ title = "Loading Wiki Version Info from Board";
cancelTitle = "Cancel";
break;
case STATE_WAITING:
// Shouldn't hit this state.
showBuffer = false;
- title = "Load Wiki Version Info from FMS";
+ title = "Load Wiki Version Info from Board";
confirmTitle = "Load";
cancelTitle = "Cancel";
break;
case STATE_SUCCEEDED:
showBuffer = true;
- title = "Loaded Wiki Version Info from FMS";
+ title = "Loaded Wiki Version Info from Board";
confirmTitle = null;
cancelTitle = "Done";
break;
@@ -132,7 +132,7 @@ public class LoadingVersionList extends
body.println("</head><body>\n");
body.println("<h3>" + escapeHTML(title) + "</h3>");
- body.println(String.format("wikiname:%s<br>FMS group:%s<p>",
+ body.println(String.format("wikiname: %s<br>board: %s<p>",
escapeHTML(context.getString("wikiname", "NOT_SET")),
escapeHTML(context.getString("fms_group", "NOT_SET"))));
@@ -267,9 +267,10 @@ public class LoadingVersionList extends
}
}
- public synchronized String getRevisionGraphHtml(List<FMSUtil.BISSRecord> records)
+ public synchronized String getRevisionGraphHtml(PrintStream textLog, List<FMSUtil.BISSRecord> records)
throws IOException {
+ textLog.println("Building graph...");
// Build a list of revision graph edges from the NNTP notification records.
List<GraphLog.GraphEdge> edges = new ArrayList<GraphLog.GraphEdge>();
Map<String, List<FMSUtil.BISSRecord>> lut = new HashMap<String, List<FMSUtil.BISSRecord>>();
@@ -347,8 +348,10 @@ public class LoadingVersionList extends
lines.add(String.format("date: %s", reference.mDate)); // Reliable?
}
String[] parentsAgain = getParentVersions(references.get(0));
+
+ lines.add(escapeHTML(String.format("parent: [%s]", parentsAgain[0])));
if (parentsAgain.length == 2) {
- lines.add(escapeHTML(String.format("rebased: %s (UNVERIFIED!)", parentsAgain[1])));
+ lines.add(escapeHTML(String.format("rebased: [%s] (UNVERIFIED!)", parentsAgain[1])));
}
lines.add("");
@@ -358,6 +361,8 @@ public class LoadingVersionList extends
}
out.write("</pre>\n");
out.flush();
+ textLog.println("Finished.");
+
return out.toString();
}
@@ -366,8 +371,7 @@ public class LoadingVersionList extends
mListHtml = new StringBuilder();
}
try {
- out.println("Reading versions from FMS...");
- String graphHtml = getRevisionGraphHtml(mArchiveManager.getRecentWikiVersions(out));
+ String graphHtml = getRevisionGraphHtml(out, mArchiveManager.getRecentWikiVersions(out));
synchronized (this) {
mListHtml.append(graphHtml);
}
diff --git a/test/graphs/branch0.txt b/test/graphs/branch0.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/branch0.txt
@@ -0,0 +1,12 @@
+c0 b0
+b0 a0
+a0 Z
+
+c1 b1
+b1 a1
+a1 Z
+
+d c0
+d c1
+
+
diff --git a/test/graphs/branch1.txt b/test/graphs/branch1.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/branch1.txt
@@ -0,0 +1,12 @@
+c0 b0
+b0 a0
+a0 Z0
+
+c1 b1
+b1 a1
+a1 Z1
+
+d c0
+d c1
+
+
diff --git a/test/graphs/empty.txt b/test/graphs/empty.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/empty.txt
@@ -0,0 +1,1 @@
+# empty on purpose
diff --git a/test/graphs/linear.txt b/test/graphs/linear.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/linear.txt
@@ -0,0 +1,4 @@
+c b
+b a
+a Z
+
diff --git a/test/graphs/one_edge.txt b/test/graphs/one_edge.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/one_edge.txt
@@ -0,0 +1,1 @@
+b a
diff --git a/test/graphs/sethcg.34194b24d92a.bug.txt b/test/graphs/sethcg.34194b24d92a.bug.txt
new file mode 100644
--- /dev/null
+++ b/test/graphs/sethcg.34194b24d92a.bug.txt
@@ -0,0 +1,40 @@
+# Used to diagnose a bug reported in the wild in version: 34194b24d92a.
+08c26c3ba8625fca 0b492241db429a63
+
+e76f3653fa8464c6 14d0b189ba3c9eb6
+
+0b492241db429a63 64d55b97a35bc07d
+
+14d0b189ba3c9eb6 26c56f1461beae7f
+
+64d55b97a35bc07d e76f3653fa8464c6
+
+64d55b97a35bc07d 7bbb7de37f88f49e
+
+26c56f1461beae7f 551458011a230904
+
+7bbb7de37f88f49e 0bd59cc84b2043ed
+
+551458011a230904 0bd59cc84b2043ed
+
+0bd59cc84b2043ed 0f5a714975290de4
+
+# --- dag ---
+# o id: 08c26c3ba8625fca (10)
+# |
+# o id: 0b492241db429a63 (9)
+# |
+# o id: 64d55b97a35bc07d (8)
+# |\
+# | o id: e76f3653fa8464c6 (7)
+# | |
+# | o id: 14d0b189ba3c9eb6 (6)
+# | |
+# | o id: 26c56f1461beae7f (5)
+# | |
+# o | id: 7bbb7de37f88f49e (4)
+# | |
+# | o id: 551458011a230904 (3)
+# |/
+# o id: 0bd59cc84b2043ed (2)
+# |