# HG changeset patch # User Artem Tikhomirov # Date 1297977385 -3600 # Node ID b9700740553a8f6b1a4f4f89e80069baf4be8e1a # Parent 37a34044e6bd56e6efb7ce3f1bdaa745dce9260b Command line tools parse and respect most of command-line arguments diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Cat.java --- a/cmdline/org/tmatesoft/hg/console/Cat.java Thu Feb 17 05:06:07 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Cat.java Thu Feb 17 22:16:25 2011 +0100 @@ -16,10 +16,14 @@ */ package org.tmatesoft.hg.console; -import org.tmatesoft.hg.internal.DigestHelper; +import static org.tmatesoft.hg.repo.HgRepository.TIP; + +import java.io.OutputStream; +import java.nio.ByteBuffer; + import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; -import org.tmatesoft.hg.repo.HgInternals; +import org.tmatesoft.hg.util.ByteChannel; /** @@ -35,32 +39,34 @@ System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); return; } - HgInternals debug = new HgInternals(hgRepo); - String[] toCheck = new String[] {"design.txt", "src/com/tmate/hgkit/ll/Changelog.java", "src/Extras.java", "bin/com/tmate/hgkit/ll/Changelog.class"}; - boolean[] checkResult = debug.checkIgnored(toCheck); - for (int i = 0; i < toCheck.length; i++) { - System.out.println("Ignored " + toCheck[i] + ": " + checkResult[i]); - } - DigestHelper dh = new DigestHelper(); - for (String fname : cmdLineOpts.files) { + int rev = cmdLineOpts.getSingleInt(TIP, "-r", "--rev"); + OutputStreamChannel out = new OutputStreamChannel(System.out); + for (String fname : cmdLineOpts.getList("")) { System.out.println(fname); HgDataFile fn = hgRepo.getFileNode(fname); if (fn.exists()) { - int total = fn.getRevisionCount(); - System.out.printf("Total revisions: %d\n", total); - for (int i = 0; i < total; i++) { - byte[] content = fn.content(i); - System.out.println("==========>"); - System.out.println(new String(content)); - int[] parentRevisions = new int[2]; - byte[] parent1 = new byte[20]; - byte[] parent2 = new byte[20]; - fn.parents(i, parentRevisions, parent1, parent2); - System.out.println(dh.sha1(parent1, parent2, content).asHexString()); - } + fn.content(rev, out, true); + System.out.println(); } else { - System.out.println(">>>Not found!"); + System.out.printf("%s not found!\n", fname); } } } + + private static class OutputStreamChannel implements ByteChannel { + + private final OutputStream stream; + + public OutputStreamChannel(OutputStream out) { + stream = out; + } + + public int write(ByteBuffer buffer) throws Exception { + int count = buffer.remaining(); + while(buffer.hasRemaining()) { + stream.write(buffer.get()); + } + return count; + } + } } diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Log.java --- a/cmdline/org/tmatesoft/hg/console/Log.java Thu Feb 17 05:06:07 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Log.java Thu Feb 17 22:16:25 2011 +0100 @@ -42,35 +42,31 @@ System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); return; } - System.out.println(hgRepo.getLocation()); final Dump dump = new Dump(hgRepo); - dump.complete = true; //cmdLineOpts; - dump.verbose = false; //cmdLineOpts; + dump.complete = cmdLineOpts.getBoolean("--debug"); + dump.verbose = cmdLineOpts.getBoolean("-v", "--verbose"); dump.reverseOrder = true; HgLogCommand cmd = new HgLogCommand(hgRepo); - if (cmdLineOpts.users != null) { - for (String u : cmdLineOpts.users) { - cmd.user(u); - } + for (String u : cmdLineOpts.getList("-u", "--user")) { + cmd.user(u); } - if (cmdLineOpts.branches != null) { - for (String b : cmdLineOpts.branches) { - cmd.branch(b); - } + for (String b : cmdLineOpts.getList("-b", "--branches")) { + cmd.branch(b); } - if (cmdLineOpts.limit != -1) { - cmd.limit(cmdLineOpts.limit); - + int limit = cmdLineOpts.getSingleInt(-1, "-l", "--limit"); + if (limit != -1) { + cmd.limit(limit); } - if (cmdLineOpts.files.isEmpty()) { - if (cmdLineOpts.limit == -1) { + List files = cmdLineOpts.getList(""); + if (files.isEmpty()) { + if (limit == -1) { // no revisions and no limit cmd.execute(dump); } else { // 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, cmdLineOpts.limit) == 0) { + if (fixRange(r, dump.reverseOrder, limit) == 0) { System.out.println("No changes"); return; } @@ -78,14 +74,14 @@ } dump.complete(); } else { - for (String fname : cmdLineOpts.files) { + for (String fname : files) { HgDataFile f1 = hgRepo.getFileNode(fname); System.out.println("History of the file: " + f1.getPath()); - if (cmdLineOpts.limit == -1) { + if (limit == -1) { cmd.file(f1.getPath(), true).execute(dump); } else { int[] r = new int[] { 0, f1.getRevisionCount() }; - if (fixRange(r, dump.reverseOrder, cmdLineOpts.limit) == 0) { + if (fixRange(r, dump.reverseOrder, limit) == 0) { System.out.println("No changes"); continue; } diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmdline/org/tmatesoft/hg/console/Main.java Thu Feb 17 22:16:25 2011 +0100 @@ -0,0 +1,265 @@ +/* + * 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 static org.tmatesoft.hg.repo.HgRepository.TIP; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.tmatesoft.hg.core.HgLogCommand.FileRevision; +import org.tmatesoft.hg.core.HgManifestCommand; +import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.internal.DigestHelper; +import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgInternals; +import org.tmatesoft.hg.repo.HgManifest; +import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgStatusCollector; +import org.tmatesoft.hg.repo.HgStatusInspector; +import org.tmatesoft.hg.repo.HgWorkingCopyStatusCollector; +import org.tmatesoft.hg.util.Path; + +/** + * Various debug dumps. + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class Main { + + private Options cmdLineOpts; + private HgRepository hgRepo; + + public Main(String[] args) throws Exception { + cmdLineOpts = Options.parse(args); + hgRepo = cmdLineOpts.findRepository(); + if (hgRepo.isInvalid()) { + System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); + return; + } + System.out.println("REPO:" + hgRepo.getLocation()); + } + + public static void main(String[] args) throws Exception { + Main m = new Main(args); + m.dumpIgnored(); + m.dumpDirstate(); + m.testStatusInternals(); + m.catCompleteHistory(); + m.dumpCompleteManifestLow(); + m.dumpCompleteManifestHigh(); + m.bunchOfTests(); + } + + private void dumpIgnored() { + HgInternals debug = new HgInternals(hgRepo); + String[] toCheck = new String[] {"design.txt", "src/com/tmate/hgkit/ll/Changelog.java", "src/Extras.java", "bin/com/tmate/hgkit/ll/Changelog.class"}; + boolean[] checkResult = debug.checkIgnored(toCheck); + for (int i = 0; i < toCheck.length; i++) { + System.out.println("Ignored " + toCheck[i] + ": " + checkResult[i]); + } + } + + private void dumpDirstate() { + new HgInternals(hgRepo).dumpDirstate(); + } + + + private void catCompleteHistory() { + DigestHelper dh = new DigestHelper(); + for (String fname : cmdLineOpts.getList("")) { + System.out.println(fname); + HgDataFile fn = hgRepo.getFileNode(fname); + if (fn.exists()) { + int total = fn.getRevisionCount(); + System.out.printf("Total revisions: %d\n", total); + for (int i = 0; i < total; i++) { + byte[] content = fn.content(i); + System.out.println("==========>"); + System.out.println(new String(content)); + int[] parentRevisions = new int[2]; + byte[] parent1 = new byte[20]; + byte[] parent2 = new byte[20]; + fn.parents(i, parentRevisions, parent1, parent2); + System.out.println(dh.sha1(parent1, parent2, content).asHexString()); + } + } else { + System.out.println(">>>Not found!"); + } + } + } + + private void dumpCompleteManifestLow() { + hgRepo.getManifest().walk(0, TIP, new ManifestDump()); + } + + public static final class ManifestDump implements HgManifest.Inspector { + public boolean begin(int revision, Nodeid nid) { + System.out.printf("%d : %s\n", revision, nid); + return true; + } + + public boolean next(Nodeid nid, String fname, String flags) { + System.out.println(nid + "\t" + fname + "\t\t" + flags); + return true; + } + + public boolean end(int revision) { + System.out.println(); + return true; + } + } + + private void dumpCompleteManifestHigh() { + new HgManifestCommand(hgRepo).dirs(true).execute(new HgManifestCommand.Handler() { + + public void begin(Nodeid manifestRevision) { + System.out.println(">> " + manifestRevision); + } + public void dir(Path p) { + System.out.println(p); + } + public void file(FileRevision fileRevision) { + System.out.print(fileRevision.getRevision());; + System.out.print(" "); + System.out.println(fileRevision.getPath()); + } + + public void end(Nodeid manifestRevision) { + System.out.println(); + } + }); + } + + private void bunchOfTests() throws Exception { + HgInternals debug = new HgInternals(hgRepo); + debug.dumpDirstate(); + final StatusDump dump = new StatusDump(); + dump.showIgnored = false; + dump.showClean = false; + HgStatusCollector sc = new HgStatusCollector(hgRepo); + final int r1 = 0, r2 = 3; + System.out.printf("Status for changes between revision %d and %d:\n", r1, r2); + sc.walk(r1, r2, dump); + // + System.out.println("\n\nSame, but sorted in the way hg status does:"); + HgStatusCollector.Record r = sc.status(r1, r2); + sortAndPrint('M', r.getModified(), null); + sortAndPrint('A', r.getAdded(), null); + sortAndPrint('R', r.getRemoved(), null); + // + System.out.println("\n\nTry hg status --change :"); + sc.change(0, dump); + System.out.println("\nStatus against working dir:"); + HgWorkingCopyStatusCollector wcc = new HgWorkingCopyStatusCollector(hgRepo); + wcc.walk(TIP, dump); + System.out.println(); + System.out.printf("Manifest of the revision %d:\n", r2); + hgRepo.getManifest().walk(r2, r2, new ManifestDump()); + System.out.println(); + System.out.printf("\nStatus of working dir against %d:\n", r2); + r = wcc.status(r2); + sortAndPrint('M', r.getModified(), null); + sortAndPrint('A', r.getAdded(), r.getCopied()); + sortAndPrint('R', r.getRemoved(), null); + sortAndPrint('?', r.getUnknown(), null); + sortAndPrint('I', r.getIgnored(), null); + sortAndPrint('C', r.getClean(), null); + sortAndPrint('!', r.getMissing(), null); + } + + private void sortAndPrint(char prefix, List ul, Map copies) { + ArrayList sortList = new ArrayList(ul); + Collections.sort(sortList); + for (Path s : sortList) { + System.out.print(prefix); + System.out.print(' '); + System.out.println(s); + if (copies != null && copies.containsKey(s)) { + System.out.println(" " + copies.get(s)); + } + } + } + + + private void testStatusInternals() { + HgDataFile n = hgRepo.getFileNode(Path.create("design.txt")); + for (String s : new String[] {"011dfd44417c72bd9e54cf89b82828f661b700ed", "e5529faa06d53e06a816e56d218115b42782f1ba", "c18e7111f1fc89a80a00f6a39d51288289a382fc"}) { + // expected: 359, 2123, 3079 + byte[] b = s.getBytes(); + final Nodeid nid = Nodeid.fromAscii(b, 0, b.length); + System.out.println(s + " : " + n.length(nid)); + } + } + + private static class StatusDump implements HgStatusInspector { + public boolean hideStatusPrefix = false; // hg status -n option + public boolean showCopied = true; // -C + public boolean showIgnored = true; // -i + public boolean showClean = true; // -c + + public void modified(Path fname) { + print('M', fname); + } + + public void added(Path fname) { + print('A', fname); + } + + public void copied(Path fnameOrigin, Path fnameAdded) { + added(fnameAdded); + if (showCopied) { + print(' ', fnameOrigin); + } + } + + public void removed(Path fname) { + print('R', fname); + } + + public void clean(Path fname) { + if (showClean) { + print('C', fname); + } + } + + public void missing(Path fname) { + print('!', fname); + } + + public void unknown(Path fname) { + print('?', fname); + } + + public void ignored(Path fname) { + if (showIgnored) { + print('I', fname); + } + } + + private void print(char status, Path fname) { + if (!hideStatusPrefix) { + System.out.print(status); + System.out.print(' '); + } + System.out.println(fname); + } + } +} diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Manifest.java --- a/cmdline/org/tmatesoft/hg/console/Manifest.java Thu Feb 17 05:06:07 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Manifest.java Thu Feb 17 22:16:25 2011 +0100 @@ -19,9 +19,8 @@ import static org.tmatesoft.hg.repo.HgRepository.TIP; import org.tmatesoft.hg.core.HgLogCommand.FileRevision; +import org.tmatesoft.hg.core.HgManifestCommand; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.core.HgManifestCommand; -import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.util.Path; @@ -40,43 +39,29 @@ System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); return; } - System.out.println(hgRepo.getLocation()); - hgRepo.getManifest().walk(0, TIP, new Dump()); - // - new HgManifestCommand(hgRepo).dirs(true).walk(new HgManifestCommand.Handler() { + final boolean debug = cmdLineOpts.getBoolean("--debug"); + final boolean verbose = cmdLineOpts.getBoolean("-v", "--verbose"); + HgManifestCommand.Handler h = new HgManifestCommand.Handler() { public void begin(Nodeid manifestRevision) { - System.out.println(">> " + manifestRevision); } public void dir(Path p) { - System.out.println(p); } public void file(FileRevision fileRevision) { - System.out.print(fileRevision.getRevision());; - System.out.print(" "); + if (debug) { + System.out.print(fileRevision.getRevision());; + } + if (debug || verbose) { + System.out.print(" 644"); // FIXME real flags! + System.out.print(" "); + } System.out.println(fileRevision.getPath()); } public void end(Nodeid manifestRevision) { - System.out.println(); } - }); - } - - public static final class Dump implements HgManifest.Inspector { - public boolean begin(int revision, Nodeid nid) { - System.out.printf("%d : %s\n", revision, nid); - return true; - } - - public boolean next(Nodeid nid, String fname, String flags) { - System.out.println(nid + "\t" + fname + "\t\t" + flags); - return true; - } - - public boolean end(int revision) { - System.out.println(); - return true; - } + }; + int rev = cmdLineOpts.getSingleInt(TIP, "-r", "--rev"); + new HgManifestCommand(hgRepo).dirs(false).revision(rev).execute(h); } } diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Options.java --- a/cmdline/org/tmatesoft/hg/console/Options.java Thu Feb 17 05:06:07 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Options.java Thu Feb 17 22:16:25 2011 +0100 @@ -16,33 +16,69 @@ */ package org.tmatesoft.hg.console; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Set; +import java.util.Map; +import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRepository; -import org.tmatesoft.hg.repo.HgLookup; /** - * Parse command-line options + * Parse command-line options. Primitive implementation that recognizes options with 0 or 1 argument. * * @author Artem Tikhomirov * @author TMate Software Ltd. */ class Options { - public String repoLocation; - public List files; - public int limit = -1; - public Set users; - public Set branches; + public final Map> opt2values = new HashMap>(); + + public boolean getBoolean(String... aliases) { + return getBoolean(false, aliases); + } + + public boolean getBoolean(boolean def, String... aliases) { + for (String s : aliases) { + if (opt2values.containsKey(s)) { + return true; + } + } + return def; + } + + public String getSingle(String... aliases) { + String rv = null; + for (String s : aliases) { + List values = opt2values.get(s); + if (values != null && values.size() > 0) { + rv = values.get(values.size() - 1); // take last one, most recent + } + } + return rv; + } + + public int getSingleInt(int def, String... aliases) { + String r = getSingle(aliases); + if (r == null) { + return def; + } + return Integer.parseInt(r); + } + + public List getList(String... aliases) { + LinkedList rv = new LinkedList(); + for (String s : aliases) { + List values = opt2values.get(s); + if (values != null) { + rv.addAll(values); + } + } + return rv; + } public HgRepository findRepository() throws Exception { + String repoLocation = getSingle("-R", "--repository"); if (repoLocation != null) { return new HgLookup().detect(repoLocation); } @@ -52,55 +88,24 @@ public static Options parse(String[] commandLineArgs) { Options rv = new Options(); - List args = Arrays.asList(commandLineArgs); - LinkedList files = new LinkedList(); - for (Iterator it = args.iterator(); it.hasNext(); ) { - String arg = it.next(); + List values = new LinkedList(); + rv.opt2values.put("", values); // values with no options + for (String arg : commandLineArgs) { if (arg.charAt(0) == '-') { // option if (arg.length() == 1) { throw new IllegalArgumentException("Bad option: -"); } - switch ((int) arg.charAt(1)) { - case (int) 'R' : { - if (! it.hasNext()) { - throw new IllegalArgumentException("Need repo location"); - } - rv.repoLocation = it.next(); - break; - } - case (int) 'l' : { - if (!it.hasNext()) { - throw new IllegalArgumentException(); - } - rv.limit = Integer.parseInt(it.next()); - break; - } - case (int) 'u' : { - if (rv.users == null) { - rv.users = new LinkedHashSet(); - } - rv.users.add(it.next()); - break; - } - case (int) 'b' : { - if (rv.branches == null) { - rv.branches = new LinkedHashSet(); - } - rv.branches.add(it.next()); - break; - } + values = rv.opt2values.get(arg); + if (values == null) { + rv.opt2values.put(arg, values = new LinkedList()); } + // next value, if any, gets into the values list for arg option. } else { - // filename - files.add(arg); + values.add(arg); + values = rv.opt2values.get(""); } } - if (!files.isEmpty()) { - rv.files = new ArrayList(files); - } else { - rv.files = Collections.emptyList(); - } return rv; } } \ No newline at end of file diff -r 37a34044e6bd -r b9700740553a cmdline/org/tmatesoft/hg/console/Status.java --- a/cmdline/org/tmatesoft/hg/console/Status.java Thu Feb 17 05:06:07 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Status.java Thu Feb 17 22:16:25 2011 +0100 @@ -16,21 +16,20 @@ */ package org.tmatesoft.hg.console; -import static org.tmatesoft.hg.repo.HgRepository.TIP; +import static org.tmatesoft.hg.repo.HgRepository.BAD_REVISION; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.TreeMap; -import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.repo.HgDataFile; -import org.tmatesoft.hg.repo.HgRepository; -import org.tmatesoft.hg.repo.HgStatusInspector; -import org.tmatesoft.hg.repo.HgInternals; -import org.tmatesoft.hg.repo.HgStatusCollector; -import org.tmatesoft.hg.repo.HgStatusCollector.Record; -import org.tmatesoft.hg.repo.HgWorkingCopyStatusCollector; +import org.tmatesoft.hg.core.HgRepoFacade; +import org.tmatesoft.hg.core.HgStatus; +import org.tmatesoft.hg.core.HgStatus.Kind; +import org.tmatesoft.hg.core.HgStatusCommand; import org.tmatesoft.hg.util.Path; /** @@ -42,159 +41,88 @@ public static void main(String[] args) throws Exception { 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; } - System.out.println(hgRepo.getLocation()); - // -// bunchOfTests(hgRepo); - // -// new Internals(hgRepo).dumpDirstate(); // - statusWorkingCopy(hgRepo); - //statusRevVsWorkingCopy(hgRepo); - } - - private static void statusWorkingCopy(HgRepository hgRepo) { - HgWorkingCopyStatusCollector wcc = new HgWorkingCopyStatusCollector(hgRepo); - HgStatusCollector.Record r = new HgStatusCollector.Record(); - wcc.walk(TIP, r); - mardu(r); - } - - private static void mardu(Record r) { - sortAndPrint('M', r.getModified()); - sortAndPrint('A', r.getAdded(), r.getCopied()); - sortAndPrint('R', r.getRemoved()); - sortAndPrint('?', r.getUnknown()); -// sortAndPrint('I', r.getIgnored()); -// sortAndPrint('C', r.getClean()); - sortAndPrint('!', r.getMissing()); - } - - private static void statusRevVsWorkingCopy(HgRepository hgRepo) { - HgWorkingCopyStatusCollector wcc = new HgWorkingCopyStatusCollector(hgRepo); - HgStatusCollector.Record r = new HgStatusCollector.Record(); - wcc.walk(3, r); - mardu(r); - } + HgStatusCommand cmd = hgRepo.createStatusCommand(); + if (cmdLineOpts.getBoolean("-A", "-all")) { + cmd.all(); + } else { + // default: mardu + cmd.modified(cmdLineOpts.getBoolean(true, "-m", "--modified")); + cmd.added(cmdLineOpts.getBoolean(true, "-a", "--added")); + cmd.removed(cmdLineOpts.getBoolean(true, "-r", "--removed")); + cmd.deleted(cmdLineOpts.getBoolean(true, "-d", "--deleted")); + cmd.unknown(cmdLineOpts.getBoolean(true, "-u", "--unknonwn")); + cmd.clean(cmdLineOpts.getBoolean("-c", "--clean")); + cmd.ignored(cmdLineOpts.getBoolean("-i", "--ignored")); + } +// cmd.subrepo(cmdLineOpts.getBoolean("-S", "--subrepos")) + final boolean noStatusPrefix = cmdLineOpts.getBoolean("-n", "--no-status"); + final boolean showCopies = cmdLineOpts.getBoolean("-C", "--copies"); + class StatusHandler implements HgStatusCommand.Handler { + + final Map> data = new TreeMap>(); + final Map copies = showCopies ? new HashMap() : null; + + public void handleStatus(HgStatus s) { + List l = data.get(s.getKind()); + if (l == null) { + l = new LinkedList(); + data.put(s.getKind(), l); + } + l.add(s.getPath()); + if (s.isCopy() && showCopies) { + copies.put(s.getPath(), s.getOriginalPath()); + } + } + + public void dump() { + sortAndPrint('M', data.get(Kind.Modified), null); + sortAndPrint('A', data.get(Kind.Added), copies); + sortAndPrint('R', data.get(Kind.Removed), null); + sortAndPrint('?', data.get(Kind.Unknown), null); + sortAndPrint('I', data.get(Kind.Ignored), null); + sortAndPrint('C', data.get(Kind.Clean), null); + sortAndPrint('!', data.get(Kind.Missing), null); + } - private static void bunchOfTests(HgRepository hgRepo) throws Exception { - HgInternals debug = new HgInternals(hgRepo); - debug.dumpDirstate(); - final StatusDump dump = new StatusDump(); - dump.showIgnored = false; - dump.showClean = false; - HgStatusCollector sc = new HgStatusCollector(hgRepo); - final int r1 = 0, r2 = 3; - System.out.printf("Status for changes between revision %d and %d:\n", r1, r2); - sc.walk(r1, r2, dump); - // - System.out.println("\n\nSame, but sorted in the way hg status does:"); - HgStatusCollector.Record r = sc.status(r1, r2); - sortAndPrint('M', r.getModified()); - sortAndPrint('A', r.getAdded()); - sortAndPrint('R', r.getRemoved()); - // - System.out.println("\n\nTry hg status --change :"); - sc.change(0, dump); - System.out.println("\nStatus against working dir:"); - HgWorkingCopyStatusCollector wcc = new HgWorkingCopyStatusCollector(hgRepo); - wcc.walk(TIP, dump); - System.out.println(); - System.out.printf("Manifest of the revision %d:\n", r2); - hgRepo.getManifest().walk(r2, r2, new Manifest.Dump()); - System.out.println(); - System.out.printf("\nStatus of working dir against %d:\n", r2); - r = wcc.status(r2); - sortAndPrint('M', r.getModified()); - sortAndPrint('A', r.getAdded(), r.getCopied()); - sortAndPrint('R', r.getRemoved()); - sortAndPrint('?', r.getUnknown()); - sortAndPrint('I', r.getIgnored()); - sortAndPrint('C', r.getClean()); - sortAndPrint('!', r.getMissing()); - } - - private static void sortAndPrint(char prefix, List ul) { - sortAndPrint(prefix, ul, null); - } - private static void sortAndPrint(char prefix, List ul, Map copies) { - ArrayList sortList = new ArrayList(ul); - Collections.sort(sortList); - for (Path s : sortList) { - System.out.print(prefix); - System.out.print(' '); - System.out.println(s); - if (copies != null && copies.containsKey(s)) { - System.out.println(" " + copies.get(s)); + private void sortAndPrint(char prefix, List ul, Map copies) { + if (ul == null) { + return; + } + ArrayList sortList = new ArrayList(ul); + Collections.sort(sortList); + for (Path s : sortList) { + if (!noStatusPrefix) { + System.out.print(prefix); + System.out.print(' '); + } + System.out.println(s); + if (copies != null && copies.containsKey(s)) { + System.out.println(" " + copies.get(s)); + } + } + } + }; + + StatusHandler statusHandler = new StatusHandler(); + int changeRev = cmdLineOpts.getSingleInt(BAD_REVISION, "--change"); + if (changeRev != BAD_REVISION) { + cmd.change(changeRev); + } else { + List revisions = cmdLineOpts.getList("--rev"); + int size = revisions.size(); + if (size > 1) { + cmd.base(Integer.parseInt(revisions.get(size - 2))).revision(Integer.parseInt(revisions.get(size - 1))); + } else if (size > 0) { + cmd.base(Integer.parseInt(revisions.get(0))); } } - } - - protected static void testStatusInternals(HgRepository hgRepo) { - HgDataFile n = hgRepo.getFileNode(Path.create("design.txt")); - for (String s : new String[] {"011dfd44417c72bd9e54cf89b82828f661b700ed", "e5529faa06d53e06a816e56d218115b42782f1ba", "c18e7111f1fc89a80a00f6a39d51288289a382fc"}) { - // expected: 359, 2123, 3079 - byte[] b = s.getBytes(); - final Nodeid nid = Nodeid.fromAscii(b, 0, b.length); - System.out.println(s + " : " + n.length(nid)); - } - } - - private static class StatusDump implements HgStatusInspector { - public boolean hideStatusPrefix = false; // hg status -n option - public boolean showCopied = true; // -C - public boolean showIgnored = true; // -i - public boolean showClean = true; // -c - - public void modified(Path fname) { - print('M', fname); - } - - public void added(Path fname) { - print('A', fname); - } - - public void copied(Path fnameOrigin, Path fnameAdded) { - added(fnameAdded); - if (showCopied) { - print(' ', fnameOrigin); - } - } - - public void removed(Path fname) { - print('R', fname); - } - - public void clean(Path fname) { - if (showClean) { - print('C', fname); - } - } - - public void missing(Path fname) { - print('!', fname); - } - - public void unknown(Path fname) { - print('?', fname); - } - - public void ignored(Path fname) { - if (showIgnored) { - print('I', fname); - } - } - - private void print(char status, Path fname) { - if (!hideStatusPrefix) { - System.out.print(status); - System.out.print(' '); - } - System.out.println(fname); - } + cmd.execute(statusHandler); + statusHandler.dump(); } } diff -r 37a34044e6bd -r b9700740553a src/org/tmatesoft/hg/core/HgManifestCommand.java --- a/src/org/tmatesoft/hg/core/HgManifestCommand.java Thu Feb 17 05:06:07 2011 +0100 +++ b/src/org/tmatesoft/hg/core/HgManifestCommand.java Thu Feb 17 22:16:25 2011 +0100 @@ -16,6 +16,8 @@ */ package org.tmatesoft.hg.core; +import static org.tmatesoft.hg.repo.HgRepository.*; +import static org.tmatesoft.hg.repo.HgRepository.BAD_REVISION; import static org.tmatesoft.hg.repo.HgRepository.TIP; import java.util.ConcurrentModificationException; @@ -52,8 +54,16 @@ } public HgManifestCommand range(int rev1, int rev2) { - // if manifest range is different from that of changelog, need conversion utils (external?) - throw HgRepository.notImplemented(); + // XXX if manifest range is different from that of changelog, need conversion utils (external?) + boolean badArgs = rev1 == BAD_REVISION || rev2 == BAD_REVISION || rev1 == WORKING_COPY || rev2 == WORKING_COPY; + badArgs |= rev2 != TIP && rev2 < rev1; // range(3, 1); + badArgs |= rev1 == TIP && rev2 != TIP; // range(TIP, 2), although this may be legitimate when TIP points to 2 + if (badArgs) { + throw new IllegalArgumentException(String.format("Bad range: [%d, %d]", rev1, rev2)); + } + startRev = rev1; + endRev = rev2; + return this; } public HgManifestCommand revision(int rev) { @@ -78,7 +88,7 @@ return this; } - public void walk(Handler handler) { + public void execute(Handler handler) { if (handler == null) { throw new IllegalArgumentException(); } diff -r 37a34044e6bd -r b9700740553a src/org/tmatesoft/hg/core/HgRepoFacade.java --- a/src/org/tmatesoft/hg/core/HgRepoFacade.java Thu Feb 17 05:06:07 2011 +0100 +++ b/src/org/tmatesoft/hg/core/HgRepoFacade.java Thu Feb 17 22:16:25 2011 +0100 @@ -32,6 +32,14 @@ public HgRepoFacade() { } + + public boolean init(HgRepository hgRepo) { + if (hgRepo == null) { + throw new IllegalArgumentException(); + } + repo = hgRepo; + return !repo.isInvalid(); + } public boolean init() throws Exception /*FIXME RepoInitException*/ { repo = new HgLookup().detectFromWorkingDir(); diff -r 37a34044e6bd -r b9700740553a src/org/tmatesoft/hg/core/HgStatus.java --- a/src/org/tmatesoft/hg/core/HgStatus.java Thu Feb 17 05:06:07 2011 +0100 +++ b/src/org/tmatesoft/hg/core/HgStatus.java Thu Feb 17 22:16:25 2011 +0100 @@ -31,7 +31,8 @@ public class HgStatus { public enum Kind { - Modified, Added, Removed, Unknown, Missing, Clean, Ignored + Modified, Added, Removed, Missing, Unknown, Clean, Ignored + // I'd refrain from changing order of these constants, just in case someone (erroneously, of course ;), uses .ordinal() }; private final HgStatus.Kind kind; diff -r 37a34044e6bd -r b9700740553a src/org/tmatesoft/hg/core/HgStatusCommand.java --- a/src/org/tmatesoft/hg/core/HgStatusCommand.java Thu Feb 17 05:06:07 2011 +0100 +++ b/src/org/tmatesoft/hg/core/HgStatusCommand.java Thu Feb 17 22:16:25 2011 +0100 @@ -120,11 +120,24 @@ if (revision == BAD_REVISION) { revision = WORKING_COPY; } - // XXX negative values, except for predefined constants, shall throw IAE. + if (revision != TIP && revision != WORKING_COPY && revision < 0) { + throw new IllegalArgumentException(String.valueOf(revision)); + } endRevision = revision; return this; } + /** + * Shorthand for {@link #base(int) cmd.base(BAD_REVISION)}{@link #change(int) .revision(revision)} + * + * @param revision compare given revision against its parent + * @return + */ + public HgStatusCommand change(int revision) { + base(BAD_REVISION); + return revision(revision); + } + // pass null to reset public HgStatusCommand match(Path.Matcher pathMatcher) { mediator.matcher = pathMatcher; diff -r 37a34044e6bd -r b9700740553a test/org/tmatesoft/hg/test/TestManifest.java --- a/test/org/tmatesoft/hg/test/TestManifest.java Thu Feb 17 05:06:07 2011 +0100 +++ b/test/org/tmatesoft/hg/test/TestManifest.java Thu Feb 17 22:16:25 2011 +0100 @@ -26,13 +26,11 @@ import java.util.LinkedList; import java.util.Map; -import org.junit.Assert; -import org.junit.Assume; import org.junit.Rule; import org.junit.Test; import org.tmatesoft.hg.core.HgLogCommand.FileRevision; +import org.tmatesoft.hg.core.HgManifestCommand; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.core.HgManifestCommand; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.util.Path; @@ -104,7 +102,7 @@ manifestParser.reset(); eh.run("hg", "manifest", "--debug", "--rev", String.valueOf(rev)); revisions.clear(); - new HgManifestCommand(repo).revision(rev).walk(handler); + new HgManifestCommand(repo).revision(rev).execute(handler); report("manifest " + (rev == TIP ? "TIP:" : "--rev " + rev)); }