# HG changeset patch # User Artem Tikhomirov # Date 1365528334 -7200 # Node ID 32453f30de07efe9d7b386c084ebd607dbeaba2b # Parent 78a9e26e670d5fbbf53fdf13bb82ffab6e4910be Annotate command with command-line example diff -r 78a9e26e670d -r 32453f30de07 cmdline/org/tmatesoft/hg/console/Annotate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmdline/org/tmatesoft/hg/console/Annotate.java Tue Apr 09 19:25:34 2013 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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.Collections; + +import org.tmatesoft.hg.core.HgAnnotateCommand; +import org.tmatesoft.hg.core.HgAnnotateCommand.LineInfo; +import org.tmatesoft.hg.core.HgRepoFacade; +import org.tmatesoft.hg.repo.HgDataFile; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class Annotate { + + public static void main(String[] args) throws Exception { + Options cmdLineOpts = Options.parse(args, Collections.emptySet()); + HgRepoFacade repo = new HgRepoFacade(); + if (!repo.init(cmdLineOpts.findRepository())) { + System.err.printf("Can't find repository in: %s\n", repo.getRepository().getLocation()); + return; + } + int rev = cmdLineOpts.getSingleInt(TIP, "-r", "--rev"); + HgAnnotateCommand cmd = repo.createAnnotateCommand(); + AnnotateDumpInspector insp = new AnnotateDumpInspector(cmdLineOpts.getBoolean(false, "-l", "--line-number")); + cmd.changeset(rev); + for (String fname : cmdLineOpts.getList("")) { + HgDataFile fn = repo.getRepository().getFileNode(fname); + cmd.file(fn); + cmd.execute(insp); + } + } + + private static class AnnotateDumpInspector implements HgAnnotateCommand.Inspector { + private final boolean lineNumbers; + + public AnnotateDumpInspector(boolean printLineNumbers) { + lineNumbers = printLineNumbers; + } + + public void next(LineInfo lineInfo) { + if (lineNumbers) { + System.out.printf("%3d:%3d:%s", lineInfo.getChangesetIndex(), lineInfo.getLineNumber(), new String(lineInfo.getContent())); + } else { + System.out.printf("%3d:%s", lineInfo.getChangesetIndex(), new String(lineInfo.getContent())); + } + } + } +} diff -r 78a9e26e670d -r 32453f30de07 src/org/tmatesoft/hg/core/HgAnnotateCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/core/HgAnnotateCommand.java Tue Apr 09 19:25:34 2013 +0200 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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.core; + +import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; + +import java.util.Arrays; + +import org.tmatesoft.hg.internal.Callback; +import org.tmatesoft.hg.internal.CsetParamKeeper; +import org.tmatesoft.hg.internal.Experimental; +import org.tmatesoft.hg.internal.FileAnnotation; +import org.tmatesoft.hg.internal.FileAnnotation.LineDescriptor; +import org.tmatesoft.hg.internal.FileAnnotation.LineInspector; +import org.tmatesoft.hg.repo.HgBlameFacility.BlockData; +import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.util.CancelledException; + +/** + * WORK IN PROGRESS. UNSTABLE API + * + * 'hg annotate' counterpart, report origin revision and file line-by-line + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +@Experimental(reason="Work in progress. Unstable API") +public class HgAnnotateCommand extends HgAbstractCommand { + + private final HgRepository repo; + private final CsetParamKeeper annotateRevision; + private HgDataFile file; + + public HgAnnotateCommand(HgRepository hgRepo) { + repo = hgRepo; + annotateRevision = new CsetParamKeeper(repo); + annotateRevision.doSet(HgRepository.TIP); + } + + public HgAnnotateCommand changeset(Nodeid nodeid) throws HgBadArgumentException { + annotateRevision.set(nodeid); + return this; + } + + public HgAnnotateCommand changeset(int changelogRevIndex) throws HgBadArgumentException { + annotateRevision.set(changelogRevIndex); + return this; + } + + public HgAnnotateCommand file(HgDataFile fileNode) { + file = fileNode; + return this; + } + + // TODO [1.1] set encoding and provide String line content from LineInfo + + // FIXME [1.1] follow and no-follow parameters + + public void execute(Inspector inspector) throws HgException, HgCallbackTargetException, CancelledException { + if (inspector == null) { + throw new IllegalArgumentException(); + } + if (file == null) { + throw new HgBadArgumentException("Command needs file argument", null); + } + Collector c = new Collector(); + FileAnnotation.annotate(file, annotateRevision.get(), c); + LineImpl li = new LineImpl(); + for (int i = 0; i < c.lineRevisions.length; i++) { + li.init(i+1, c.lineRevisions[i], c.line(i)); + inspector.next(li); + } + } + + /** + * Callback to receive annotated lines + */ + @Callback + public interface Inspector { + // start(FileDescriptor); + void next(LineInfo lineInfo); + // end(FileDescriptor); + } + + /** + * Describes a line reported through {@link Inspector#next(LineInfo)} + * + * Clients shall not implement this interface + */ + public interface LineInfo { + int getLineNumber(); + int getChangesetIndex(); + byte[] getContent(); + } + + // FIXME there's no need in FileAnnotation.LineInspector, merge it here + private static class Collector implements LineInspector { + private int[] lineRevisions; + private byte[][] lines; + + Collector() { + } + + public void line(int lineNumber, int changesetRevIndex, BlockData lineContent, LineDescriptor ld) { + if (lineRevisions == null) { + lineRevisions = new int [ld.totalLines()]; + Arrays.fill(lineRevisions, NO_REVISION); + lines = new byte[ld.totalLines()][]; + } + lineRevisions[lineNumber] = changesetRevIndex; + lines[lineNumber] = lineContent.asArray(); + } + + public byte[] line(int i) { + return lines[i]; + } + } + + + private static class LineImpl implements LineInfo { + private int ln; + private int rev; + private byte[] content; + + void init(int line, int csetRev, byte[] cnt) { + ln = line; + rev = csetRev; + content = cnt; + } + + public int getLineNumber() { + return ln; + } + + public int getChangesetIndex() { + return rev; + } + + public byte[] getContent() { + return content; + } + } +} diff -r 78a9e26e670d -r 32453f30de07 src/org/tmatesoft/hg/core/HgRepoFacade.java --- a/src/org/tmatesoft/hg/core/HgRepoFacade.java Tue Apr 09 17:15:30 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgRepoFacade.java Tue Apr 09 19:25:34 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -121,4 +121,10 @@ public HgIncomingCommand createIncomingCommand() { return new HgIncomingCommand(repo); } + + // TODO [1.1] add factory methods for all new commands + + public HgAnnotateCommand createAnnotateCommand() { + return new HgAnnotateCommand(repo); + } }