# HG changeset patch # User Artem Tikhomirov # Date 1303951664 -7200 # Node ID 63c9fed4369e6582e50b5757fb08436efa355ce8 # Parent ffc5f6d59f7e6bc211451224d301984dd914b199 Sample command line tools for incoming/outgoing to use commands diff -r ffc5f6d59f7e -r 63c9fed4369e cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java Thu Apr 28 02:47:44 2011 +0200 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2011 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.console; + +import java.util.Formatter; +import java.util.LinkedList; +import java.util.List; + +import org.tmatesoft.hg.core.HgChangeset; +import org.tmatesoft.hg.core.HgChangesetHandler; +import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.core.HgLogCommand.FileRevision; +import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.util.Path; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class ChangesetDumpHandler implements HgChangesetHandler { + // params + private boolean complete = false; // roughly --debug + private boolean reverseOrder = false; + private boolean verbose = true; // roughly -v + // own + private LinkedList l = new LinkedList(); + private final HgRepository repo; + private final int tip; + + public ChangesetDumpHandler(HgRepository hgRepo) { + repo = hgRepo; + tip = hgRepo.getChangelog().getLastRevision(); + } + + public ChangesetDumpHandler complete(boolean b) { + complete = b; + return this; + } + + public ChangesetDumpHandler reversed(boolean b) { + reverseOrder = b; + return this; + } + + public ChangesetDumpHandler verbose(boolean b) { + verbose = b; + return this; + } + + public void next(HgChangeset changeset) { + final String s = print(changeset); + if (reverseOrder) { + // XXX in fact, need to insert s into l according to changeset.getRevision() + // because when file history is being followed, revisions of the original file (with smaller revNumber) + // are reported *after* revisions of present file and with addFirst appear above them + l.addFirst(s); + } else { + System.out.print(s); + } + } + + public void done() { + if (!reverseOrder) { + return; + } + for (String s : l) { + System.out.print(s); + } + l.clear(); + } + + private String print(HgChangeset cset) { + StringBuilder sb = new StringBuilder(); + Formatter f = new Formatter(sb); + final Nodeid csetNodeid = cset.getNodeid(); + f.format("changeset: %d:%s\n", cset.getRevision(), complete ? csetNodeid : csetNodeid.shortNotation()); + if (cset.getRevision() == tip || repo.getTags().isTagged(csetNodeid)) { + + sb.append("tag: "); + for (String t : repo.getTags().tags(csetNodeid)) { + sb.append(t); + sb.append(' '); + } + if (cset.getRevision() == tip) { + sb.append("tip"); + } + sb.append('\n'); + } + if (complete) { + Nodeid p1 = cset.getFirstParentRevision(); + Nodeid p2 = cset.getSecondParentRevision(); + int p1x = p1 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p1); + int p2x = p2 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p2); + int mx = repo.getManifest().getLocalRevision(cset.getManifestRevision()); + f.format("parent: %d:%s\nparent: %d:%s\nmanifest: %d:%s\n", p1x, p1, p2x, p2, mx, cset.getManifestRevision()); + } + f.format("user: %s\ndate: %s\n", cset.getUser(), cset.getDate()); + if (!complete && verbose) { + final List files = cset.getAffectedFiles(); + sb.append("files: "); + for (Path s : files) { + sb.append(' '); + sb.append(s); + } + sb.append('\n'); + } + if (complete) { + if (!cset.getModifiedFiles().isEmpty()) { + sb.append("files: "); + for (FileRevision s : cset.getModifiedFiles()) { + sb.append(' '); + sb.append(s.getPath()); + } + sb.append('\n'); + } + if (!cset.getAddedFiles().isEmpty()) { + sb.append("files+: "); + for (FileRevision s : cset.getAddedFiles()) { + sb.append(' '); + sb.append(s.getPath()); + } + sb.append('\n'); + } + if (!cset.getRemovedFiles().isEmpty()) { + sb.append("files-: "); + for (Path s : cset.getRemovedFiles()) { + sb.append(' '); + sb.append(s); + } + sb.append('\n'); + } + // if (cset.extras() != null) { + // sb.append("extra: "); + // for (Map.Entry e : cset.extras().entrySet()) { + // sb.append(' '); + // sb.append(e.getKey()); + // sb.append('='); + // sb.append(e.getValue()); + // } + // sb.append('\n'); + // } + } + if (complete || verbose) { + f.format("description:\n%s\n\n", cset.getComment()); + } else { + f.format("summary: %s\n\n", cset.getComment()); + } + return sb.toString(); + } +} diff -r ffc5f6d59f7e -r 63c9fed4369e cmdline/org/tmatesoft/hg/console/Incoming.java --- a/cmdline/org/tmatesoft/hg/console/Incoming.java Thu Apr 28 02:00:42 2011 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Incoming.java Thu Apr 28 02:47:44 2011 +0200 @@ -22,27 +22,19 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; -import org.tmatesoft.hg.console.Outgoing.ChangesetFormatter; -import org.tmatesoft.hg.core.HgBadStateException; +import org.tmatesoft.hg.core.HgIncomingCommand; +import org.tmatesoft.hg.core.HgRepoFacade; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.internal.RepositoryComparator; -import org.tmatesoft.hg.internal.RepositoryComparator.BranchChain; -import org.tmatesoft.hg.repo.HgBundle; -import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRemoteRepository; -import org.tmatesoft.hg.repo.HgRepository; /** - * WORK IN PROGRESS, DO NOT USE - * hg incoming counterpart + * hg incoming counterpart * * @author Artem Tikhomirov * @author TMate Software Ltd. @@ -55,66 +47,35 @@ return; } Options cmdLineOpts = Options.parse(args); - final HgRepository hgRepo = cmdLineOpts.findRepository(); - if (hgRepo.isInvalid()) { - System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); + HgRepoFacade hgRepo = new HgRepoFacade(); + if (!hgRepo.init(cmdLineOpts.findRepository())) { + System.err.printf("Can't find repository in: %s\n", hgRepo.getRepository().getLocation()); return; } - HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo); + HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo.getRepository()); if (hgRemote.isInvalid()) { System.err.printf("Remote repository %s is not valid", hgRemote.getLocation()); return; } - // - // in fact, all we need from changelog is set of all nodeids. However, since ParentWalker reuses same Nodeids, it's not too expensive - // to reuse it here, XXX although later this may need to be refactored - final HgChangelog.ParentWalker pw = hgRepo.getChangelog().new ParentWalker(); - pw.init(); + HgIncomingCommand cmd = hgRepo.createIncomingCommand(); + cmd.against(hgRemote); // - RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote); - repoCompare.compare(null); - List missingBranches = repoCompare.calculateMissingBranches(); - final LinkedHashSet common = new LinkedHashSet(); - // XXX common can be obtained from repoCompare, but at the moment it would almost duplicate work of calculateMissingBranches - // once I refactor latter, common shall be taken from repoCompare. - for (BranchChain bc : missingBranches) { - bc.dump(); - common.add(bc.branchRoot); // common known node - List missing = repoCompare.visitBranches(bc); - assert bc.branchRoot.equals(missing.get(0)); - missing.remove(0); - Collections.reverse(missing); // useful to test output, from newer to older - System.out.println("Nodes to fetch in this branch:"); - for (Nodeid n : missing) { - if (pw.knownNode(n)) { - System.out.println("Erroneous to fetch:" + n); - } else { - System.out.println(n); - } - } - System.out.println("Branch done"); - } + List missing = cmd.executeLite(null); + Collections.reverse(missing); // useful to test output, from newer to older + Outgoing.dump("Nodes to fetch:", missing); // // Complete - HgBundle changegroup = hgRemote.getChanges(new LinkedList(common)); - changegroup.changes(hgRepo, new HgChangelog.Inspector() { - private int localIndex; - private final ChangesetFormatter formatter = new ChangesetFormatter(); - - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { - if (pw.knownNode(nodeid)) { - if (!common.contains(nodeid)) { - throw new HgBadStateException("Bundle shall not report known nodes other than roots we've supplied"); - } - localIndex = hgRepo.getChangelog().getLocalRevision(nodeid); - return; - } - System.out.println(formatter.simple(++localIndex, nodeid, cset)); - } - }); + final ChangesetDumpHandler h = new ChangesetDumpHandler(hgRepo.getRepository()); + h.complete(false); // this option looks up index of parent revision, done via repo.changelog (which doesn't have any of these new revisions) + // this can be fixed by tracking all nodeid->revision idx inside ChangesetDumpHandler, and refer to repo.changelog only when that mapping didn't work + h.verbose(cmdLineOpts.getBoolean("-v", "--verbose")); + cmd.executeFull(h); } + /* + * This is for investigation purposes only + */ private static class SequenceConstructor { private int[] between(int root, int head) { diff -r ffc5f6d59f7e -r 63c9fed4369e cmdline/org/tmatesoft/hg/console/Log.java --- a/cmdline/org/tmatesoft/hg/console/Log.java Thu Apr 28 02:00:42 2011 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Log.java Thu Apr 28 02:47:44 2011 +0200 @@ -16,17 +16,12 @@ */ package org.tmatesoft.hg.console; -import java.util.Formatter; -import java.util.LinkedList; import java.util.List; -import org.tmatesoft.hg.core.HgChangeset; import org.tmatesoft.hg.core.HgLogCommand; import org.tmatesoft.hg.core.HgLogCommand.FileRevision; -import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; -import org.tmatesoft.hg.util.Path; /** @@ -45,9 +40,10 @@ return; } final Dump dump = new Dump(hgRepo); - dump.complete = cmdLineOpts.getBoolean("--debug"); - dump.verbose = cmdLineOpts.getBoolean("-v", "--verbose"); - dump.reverseOrder = true; + dump.complete(cmdLineOpts.getBoolean("--debug")); + dump.verbose(cmdLineOpts.getBoolean("-v", "--verbose")); + final boolean reverseOrder = true; + dump.reversed(reverseOrder); HgLogCommand cmd = new HgLogCommand(hgRepo); for (String u : cmdLineOpts.getList("-u", "--user")) { cmd.user(u); @@ -69,13 +65,13 @@ // in fact, external (to dump inspector) --limit processing yelds incorrect results when other args // e.g. -u or -b are used (i.e. with -u shall give csets with user, not check last csets for user int[] r = new int[] { 0, hgRepo.getChangelog().getRevisionCount() }; - if (fixRange(r, dump.reverseOrder, limit) == 0) { + if (fixRange(r, reverseOrder, limit) == 0) { System.out.println("No changes"); return; } cmd.range(r[0], r[1]).execute(dump); } - dump.complete(); + dump.done(); } else { for (String fname : files) { HgDataFile f1 = hgRepo.getFileNode(fname); @@ -84,13 +80,13 @@ cmd.file(f1.getPath(), true).execute(dump); } else { int[] r = new int[] { 0, f1.getRevisionCount() }; - if (fixRange(r, dump.reverseOrder, limit) == 0) { + if (fixRange(r, reverseOrder, limit) == 0) { System.out.println("No changes"); continue; } cmd.range(r[0], r[1]).file(f1.getPath(), true).execute(dump); } - dump.complete(); + dump.done(); } } // cmd = null; @@ -113,132 +109,14 @@ return rv; } - private static final class Dump implements HgLogCommand.FileHistoryHandler { - // params - boolean complete = false; // roughly --debug - boolean reverseOrder = false; - boolean verbose = true; // roughly -v - // own - private LinkedList l = new LinkedList(); - private final HgRepository repo; -// private HgChangelog.ParentWalker changelogWalker; - private final int tip ; + private static final class Dump extends ChangesetDumpHandler implements HgLogCommand.FileHistoryHandler { public Dump(HgRepository hgRepo) { - repo = hgRepo; - tip = hgRepo.getChangelog().getLastRevision(); + super(hgRepo); } public void copy(FileRevision from, FileRevision to) { System.out.printf("Got notified that %s(%s) was originally known as %s(%s)\n", to.getPath(), to.getRevision(), from.getPath(), from.getRevision()); } - - public void next(HgChangeset changeset) { - final String s = print(changeset); - if (reverseOrder) { - // XXX in fact, need to insert s into l according to changeset.getRevision() - // because when file history is being followed, revisions of the original file (with smaller revNumber) - // are reported *after* revisions of present file and with addFirst appear above them - l.addFirst(s); - } else { - System.out.print(s); - } - } - - public void complete() { - if (!reverseOrder) { - return; - } - for (String s : l) { - System.out.print(s); - } - l.clear(); -// changelogWalker = null; - } - - private String print(HgChangeset cset) { - StringBuilder sb = new StringBuilder(); - Formatter f = new Formatter(sb); - final Nodeid csetNodeid = cset.getNodeid(); - f.format("changeset: %d:%s\n", cset.getRevision(), complete ? csetNodeid : csetNodeid.shortNotation()); - if (cset.getRevision() == tip || repo.getTags().isTagged(csetNodeid)) { - - sb.append("tag: "); - for (String t : repo.getTags().tags(csetNodeid)) { - sb.append(t); - sb.append(' '); - } - if (cset.getRevision() == tip) { - sb.append("tip"); - } - sb.append('\n'); - } - if (complete) { -// if (changelogWalker == null) { -// changelogWalker = repo.getChangelog().new ParentWalker(); -// changelogWalker.init(); -// } -// Nodeid p1 = changelogWalker.safeFirstParent(csetNodeid); -// Nodeid p2 = changelogWalker.safeSecondParent(csetNodeid); - Nodeid p1 = cset.getFirstParentRevision(); - Nodeid p2 = cset.getSecondParentRevision(); - int p1x = p1 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p1); - int p2x = p2 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p2); - int mx = repo.getManifest().getLocalRevision(cset.getManifestRevision()); - f.format("parent: %d:%s\nparent: %d:%s\nmanifest: %d:%s\n", p1x, p1, p2x, p2, mx, cset.getManifestRevision()); - } - f.format("user: %s\ndate: %s\n", cset.getUser(), cset.getDate()); - if (!complete && verbose) { - final List files = cset.getAffectedFiles(); - sb.append("files: "); - for (Path s : files) { - sb.append(' '); - sb.append(s); - } - sb.append('\n'); - } - if (complete) { - if (!cset.getModifiedFiles().isEmpty()) { - sb.append("files: "); - for (FileRevision s : cset.getModifiedFiles()) { - sb.append(' '); - sb.append(s.getPath()); - } - sb.append('\n'); - } - if (!cset.getAddedFiles().isEmpty()) { - sb.append("files+: "); - for (FileRevision s : cset.getAddedFiles()) { - sb.append(' '); - sb.append(s.getPath()); - } - sb.append('\n'); - } - if (!cset.getRemovedFiles().isEmpty()) { - sb.append("files-: "); - for (Path s : cset.getRemovedFiles()) { - sb.append(' '); - sb.append(s); - } - sb.append('\n'); - } -// if (cset.extras() != null) { -// sb.append("extra: "); -// for (Map.Entry e : cset.extras().entrySet()) { -// sb.append(' '); -// sb.append(e.getKey()); -// sb.append('='); -// sb.append(e.getValue()); -// } -// sb.append('\n'); -// } - } - if (complete || verbose) { - f.format("description:\n%s\n\n", cset.getComment()); - } else { - f.format("summary: %s\n\n", cset.getComment()); - } - return sb.toString(); - } } } diff -r ffc5f6d59f7e -r 63c9fed4369e cmdline/org/tmatesoft/hg/console/Outgoing.java --- a/cmdline/org/tmatesoft/hg/console/Outgoing.java Thu Apr 28 02:00:42 2011 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Outgoing.java Thu Apr 28 02:47:44 2011 +0200 @@ -19,18 +19,15 @@ import java.util.Collection; import java.util.List; +import org.tmatesoft.hg.core.HgOutgoingCommand; +import org.tmatesoft.hg.core.HgRepoFacade; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.internal.RepositoryComparator; -import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRemoteRepository; -import org.tmatesoft.hg.repo.HgRepository; /** - * WORK IN PROGRESS, DO NOT USE - * hg outgoing + * hg outgoing * * @author Artem Tikhomirov * @author TMate Software Ltd. @@ -38,60 +35,50 @@ public class Outgoing { public static void main(String[] args) throws Exception { - final boolean debug = true; // perhaps, use hg4j.remote.debug or own property? Options cmdLineOpts = Options.parse(args); - HgRepository hgRepo = cmdLineOpts.findRepository(); - if (hgRepo.isInvalid()) { - System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); + HgRepoFacade hgRepo = new HgRepoFacade(); + if (!hgRepo.init(cmdLineOpts.findRepository())) { + System.err.printf("Can't find repository in: %s\n", hgRepo.getRepository().getLocation()); return; } - HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo); + // XXX perhaps, HgRepoFacade shall get detectRemote() analog (to get remote server with respect of facade's repo) + HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo.getRepository()); if (hgRemote.isInvalid()) { System.err.printf("Remote repository %s is not valid", hgRemote.getLocation()); return; } - - HgChangelog changelog = hgRepo.getChangelog(); - HgChangelog.ParentWalker pw = changelog.new ParentWalker(); - pw.init(); + // + HgOutgoingCommand cmd = hgRepo.createOutgoingCommand(); + cmd.against(hgRemote); - RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote); - repoCompare.compare(null); - if (debug) { - List commonKnown = repoCompare.getCommon(); - dump("Nodes known to be both locally and at remote server", commonKnown); - } // find all local children of commonKnown - List result = repoCompare.getLocalOnlyRevisions(); + List result = cmd.executeLite(null); dump("Lite", result); // // System.out.println("Full"); // show all, starting from next to common - repoCompare.visitLocalOnlyRevisions(new HgChangelog.Inspector() { - private final ChangesetFormatter formatter = new ChangesetFormatter(); - - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { - System.out.println(formatter.simple(revisionNumber, nodeid, cset)); - } - }); + final ChangesetDumpHandler h = new ChangesetDumpHandler(hgRepo.getRepository()); + h.complete(cmdLineOpts.getBoolean("--debug")).verbose(cmdLineOpts.getBoolean("-v", "--verbose")); + cmd.executeFull(h); + h.done(); } - public static class ChangesetFormatter { - private final StringBuilder sb = new StringBuilder(1024); - - public CharSequence simple(int revisionNumber, Nodeid nodeid, RawChangeset cset) { - sb.setLength(0); - sb.append(String.format("changeset: %d:%s\n", revisionNumber, nodeid.toString())); - sb.append(String.format("user: %s\n", cset.user())); - sb.append(String.format("date: %s\n", cset.dateString())); - sb.append(String.format("comment: %s\n\n", cset.comment())); - return sb; - } - } +// public static class ChangesetFormatter { +// private final StringBuilder sb = new StringBuilder(1024); +// +// public CharSequence simple(int revisionNumber, Nodeid nodeid, RawChangeset cset) { +// sb.setLength(0); +// sb.append(String.format("changeset: %d:%s\n", revisionNumber, nodeid.toString())); +// sb.append(String.format("user: %s\n", cset.user())); +// sb.append(String.format("date: %s\n", cset.dateString())); +// sb.append(String.format("comment: %s\n\n", cset.comment())); +// return sb; +// } +// } - private static void dump(String s, Collection c) { + static void dump(String s, Collection c) { System.out.println(s); for (Nodeid n : c) { System.out.println(n); diff -r ffc5f6d59f7e -r 63c9fed4369e src/org/tmatesoft/hg/core/HgOutgoingCommand.java --- a/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Thu Apr 28 02:00:42 2011 +0200 +++ b/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Thu Apr 28 02:47:44 2011 +0200 @@ -36,6 +36,7 @@ private final HgRepository localRepo; private HgRemoteRepository remoteRepo; + @SuppressWarnings("unused") private boolean includeSubrepo; private RepositoryComparator comparator; private HgChangelog.ParentWalker parentHelper; diff -r ffc5f6d59f7e -r 63c9fed4369e src/org/tmatesoft/hg/internal/RepositoryComparator.java --- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java Thu Apr 28 02:00:42 2011 +0200 +++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java Thu Apr 28 02:47:44 2011 +0200 @@ -47,6 +47,7 @@ */ public class RepositoryComparator { + private final boolean debug = Boolean.parseBoolean(System.getProperty("hg4j.remote.debug")); private final HgChangelog.ParentWalker localRepo; private final HgRemoteRepository remoteRepo; private List common; @@ -305,6 +306,12 @@ throw new HgBadStateException(String.format("Can't narrow down branch [%s, %s]", rb.head.shortNotation(), rb.root.shortNotation())); } } + if (debug) { + for (BranchChain bc : branches2load) { + System.out.println("calculateMissingBranches:"); + bc.dump(); + } + } return branches2load; } @@ -343,7 +350,7 @@ return String.format("BranchChain [%s, %s]", branchRoot, branchHead); } - public void dump() { + void dump() { System.out.println(toString()); internalDump(" "); }