Mercurial > jhg
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); |
