comparison src/org/tmatesoft/hg/core/HgCatCommand.java @ 232:b7347daa50e3

Allow to cat a file with changeset revision
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 02 Jun 2011 05:13:39 +0200
parents 41a778e3fd31
children 6e1373b54e9b
comparison
equal deleted inserted replaced
231:1792b37650f2 232:b7347daa50e3
39 39
40 private final HgRepository repo; 40 private final HgRepository repo;
41 private Path file; 41 private Path file;
42 private int localRevision = TIP; 42 private int localRevision = TIP;
43 private Nodeid revision; 43 private Nodeid revision;
44 private Nodeid cset;
44 45
45 public HgCatCommand(HgRepository hgRepo) { 46 public HgCatCommand(HgRepository hgRepo) {
46 repo = hgRepo; 47 repo = hgRepo;
47 } 48 }
48 49
59 file = fname; 60 file = fname;
60 return this; 61 return this;
61 } 62 }
62 63
63 /** 64 /**
65 * Select specific local revision of the file to cat. Note, revision numbering is of particular file, not that of
66 * repository (i.e. revision 0 means initial content of the file, irrespective of changeset revision at the time of commit)
67 *
64 * Invocation of this method clears revision set with {@link #revision(Nodeid)} or {@link #revision(int)} earlier. 68 * Invocation of this method clears revision set with {@link #revision(Nodeid)} or {@link #revision(int)} earlier.
69 *
65 * XXX rev can't be WORKING_COPY (if allowed, need to implement in #execute()) 70 * XXX rev can't be WORKING_COPY (if allowed, need to implement in #execute())
66 * @param rev local revision number, non-negative, or one of predefined constants. Note, use of {@link HgRepository#BAD_REVISION}, 71 * @param rev local revision number, non-negative, or one of predefined constants. Note, use of {@link HgRepository#BAD_REVISION},
67 * although possible, makes little sense (command would fail if executed). 72 * although possible, makes little sense (command would fail if executed).
68 * @return <code>this</code> for convenience 73 * @return <code>this</code> for convenience
69 */ 74 */
71 if (wrongLocalRevision(rev)) { 76 if (wrongLocalRevision(rev)) {
72 throw new IllegalArgumentException(String.valueOf(rev)); 77 throw new IllegalArgumentException(String.valueOf(rev));
73 } 78 }
74 localRevision = rev; 79 localRevision = rev;
75 revision = null; 80 revision = null;
81 cset = null;
76 return this; 82 return this;
77 } 83 }
78 84
79 /** 85 /**
80 * Select revision to read. Invocation of this method clears revision set with {@link #revision(int)} or {@link #revision(Nodeid)} earlier. 86 * Select revision to read. Note, this revision is file revision (i.e. the one from manifest), not the changeset revision.
87 *
88 * Invocation of this method clears revision set with {@link #revision(int)} or {@link #revision(Nodeid)} earlier.
81 * 89 *
82 * @param nodeid - unique revision identifier, Note, use of <code>null</code> or {@link Nodeid#NULL} is senseless 90 * @param nodeid - unique file revision identifier, Note, use of <code>null</code> or {@link Nodeid#NULL} is senseless
83 * @return <code>this</code> for convenience 91 * @return <code>this</code> for convenience
84 */ 92 */
85 public HgCatCommand revision(Nodeid nodeid) { 93 public HgCatCommand revision(Nodeid nodeid) {
86 if (nodeid != null && nodeid.isNull()) { 94 if (nodeid != null && nodeid.isNull()) {
87 nodeid = null; 95 nodeid = null;
88 } 96 }
89 revision = nodeid; 97 revision = nodeid;
90 localRevision = BAD_REVISION; 98 localRevision = BAD_REVISION;
99 cset = null;
100 return this;
101 }
102
103 /**
104 * Select whatever revision of the file that was actual at the time of the specified changeset. Unlike {@link #revision(int)} or {@link #revision(Nodeid)}, this method
105 * operates in terms of repository global revisions (aka changesets).
106 *
107 * Invocation of this method clears local file revisions selection.
108 *
109 * @param nodeid changeset revision
110 * @return <code>this</code> for convenience
111 */
112 public HgCatCommand changeset(Nodeid nodeid) {
113 localRevision = BAD_REVISION;
114 revision = null;
115 cset = nodeid;
91 return this; 116 return this;
92 } 117 }
93 118
94 /** 119 /**
95 * Runs the command with current set of parameters and pipes data to provided sink. 120 * Runs the command with current set of parameters and pipes data to provided sink.
97 * @param sink output channel to write data to. 122 * @param sink output channel to write data to.
98 * @throws HgDataStreamException 123 * @throws HgDataStreamException
99 * @throws IllegalArgumentException when command arguments are incomplete or wrong 124 * @throws IllegalArgumentException when command arguments are incomplete or wrong
100 */ 125 */
101 public void execute(ByteChannel sink) throws HgDataStreamException, IOException, CancelledException { 126 public void execute(ByteChannel sink) throws HgDataStreamException, IOException, CancelledException {
102 if (localRevision == BAD_REVISION && revision == null) { 127 if (localRevision == BAD_REVISION && revision == null && cset == null) {
103 throw new IllegalArgumentException("Either local file revision number or nodeid shall be specified"); 128 throw new IllegalArgumentException("File revision, corresponing local number, or a changset nodeid shall be specified");
104 } 129 }
105 if (file == null) { 130 if (file == null) {
106 throw new IllegalArgumentException("Name of the file is missing"); 131 throw new IllegalArgumentException("Name of the file is missing");
107 } 132 }
108 if (sink == null) { 133 if (sink == null) {
111 HgDataFile dataFile = repo.getFileNode(file); 136 HgDataFile dataFile = repo.getFileNode(file);
112 if (!dataFile.exists()) { 137 if (!dataFile.exists()) {
113 throw new HgDataStreamException(file, new FileNotFoundException(file.toString())); 138 throw new HgDataStreamException(file, new FileNotFoundException(file.toString()));
114 } 139 }
115 int revToExtract; 140 int revToExtract;
116 if (revision != null) { 141 if (cset != null) {
142 int csetRev = repo.getChangelog().getLocalRevision(cset);
143 Nodeid toExtract = null;
144 do {
145 toExtract = repo.getManifest().getFileRevision(csetRev, file);
146 if (toExtract == null) {
147 if (dataFile.isCopy()) {
148 file = dataFile.getCopySourceName();
149 dataFile = repo.getFileNode(file);
150 } else {
151 break;
152 }
153 }
154 } while (toExtract == null);
155 if (toExtract == null) {
156 throw new HgBadStateException(String.format("File %s not its origins were not known at repository %s revision", file, cset.shortNotation()));
157 }
158 revToExtract = dataFile.getLocalRevision(toExtract);
159 } else if (revision != null) {
117 revToExtract = dataFile.getLocalRevision(revision); 160 revToExtract = dataFile.getLocalRevision(revision);
118 } else { 161 } else {
119 revToExtract = localRevision; 162 revToExtract = localRevision;
120 } 163 }
121 dataFile.contentWithFilters(revToExtract, sink); 164 dataFile.contentWithFilters(revToExtract, sink);