Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 237:6e1373b54e9b
Allow access to working copy content through HgDataFile. Give access to repository's working dir
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 10 Jun 2011 04:35:21 +0200 |
parents | 1d389c0cb0a5 |
children | 29231022fec8 |
comparison
equal
deleted
inserted
replaced
236:883300108179 | 237:6e1373b54e9b |
---|---|
18 | 18 |
19 import static org.tmatesoft.hg.repo.HgInternals.wrongLocalRevision; | 19 import static org.tmatesoft.hg.repo.HgInternals.wrongLocalRevision; |
20 import static org.tmatesoft.hg.repo.HgRepository.*; | 20 import static org.tmatesoft.hg.repo.HgRepository.*; |
21 | 21 |
22 import java.io.ByteArrayOutputStream; | 22 import java.io.ByteArrayOutputStream; |
23 import java.io.File; | |
24 import java.io.FileInputStream; | |
23 import java.io.IOException; | 25 import java.io.IOException; |
24 import java.nio.ByteBuffer; | 26 import java.nio.ByteBuffer; |
27 import java.nio.channels.FileChannel; | |
25 import java.util.ArrayList; | 28 import java.util.ArrayList; |
26 import java.util.Collection; | 29 import java.util.Collection; |
27 import java.util.TreeMap; | 30 import java.util.TreeMap; |
28 | 31 |
29 import org.tmatesoft.hg.core.HgDataStreamException; | 32 import org.tmatesoft.hg.core.HgDataStreamException; |
31 import org.tmatesoft.hg.core.Nodeid; | 34 import org.tmatesoft.hg.core.Nodeid; |
32 import org.tmatesoft.hg.internal.DataAccess; | 35 import org.tmatesoft.hg.internal.DataAccess; |
33 import org.tmatesoft.hg.internal.FilterByteChannel; | 36 import org.tmatesoft.hg.internal.FilterByteChannel; |
34 import org.tmatesoft.hg.internal.RevlogStream; | 37 import org.tmatesoft.hg.internal.RevlogStream; |
35 import org.tmatesoft.hg.util.ByteChannel; | 38 import org.tmatesoft.hg.util.ByteChannel; |
39 import org.tmatesoft.hg.util.CancelSupport; | |
36 import org.tmatesoft.hg.util.CancelledException; | 40 import org.tmatesoft.hg.util.CancelledException; |
37 import org.tmatesoft.hg.util.Path; | 41 import org.tmatesoft.hg.util.Path; |
42 import org.tmatesoft.hg.util.ProgressSupport; | |
38 | 43 |
39 | 44 |
40 | 45 |
41 /** | 46 /** |
42 * ? name:HgFileNode? | 47 * ? name:HgFileNode? |
75 | 80 |
76 public int length(Nodeid nodeid) { | 81 public int length(Nodeid nodeid) { |
77 return content.dataLength(getLocalRevision(nodeid)); | 82 return content.dataLength(getLocalRevision(nodeid)); |
78 } | 83 } |
79 | 84 |
80 public void workingCopy(ByteChannel sink) throws IOException, CancelledException { | 85 /** |
81 throw HgRepository.notImplemented(); | 86 * Reads content of the file from working directory. If file present in the working directory, its actual content without |
87 * any filters is supplied through the sink. If file does not exist in the working dir, this method provides content of a file | |
88 * as if it would be refreshed in the working copy, i.e. its corresponding revision | |
89 * (XXX according to dirstate? file tip?) is read from the repository, and filters repo -> working copy get applied. | |
90 * | |
91 * @param sink where to pipe content to | |
92 * @throws HgDataStreamException to indicate troubles reading repository file | |
93 * @throws CancelledException if operation was cancelled | |
94 */ | |
95 public void workingCopy(ByteChannel sink) throws HgDataStreamException, CancelledException { | |
96 File f = getRepo().getFile(this); | |
97 if (f.exists()) { | |
98 final CancelSupport cs = CancelSupport.Factory.get(sink); | |
99 final ProgressSupport progress = ProgressSupport.Factory.get(sink); | |
100 final long flength = f.length(); | |
101 final int bsize = (int) Math.min(flength, 32*1024); | |
102 progress.start((int) (flength > Integer.MAX_VALUE ? flength >>> 15 /*32 kb buf size*/ : flength)); | |
103 ByteBuffer buf = ByteBuffer.allocate(bsize); | |
104 FileChannel fc = null; | |
105 try { | |
106 fc = new FileInputStream(f).getChannel(); | |
107 while (fc.read(buf) != -1) { | |
108 cs.checkCancelled(); | |
109 buf.flip(); | |
110 int consumed = sink.write(buf); | |
111 progress.worked(flength > Integer.MAX_VALUE ? 1 : consumed); | |
112 buf.compact(); | |
113 } | |
114 } catch (IOException ex) { | |
115 throw new HgDataStreamException(getPath(), ex); | |
116 } finally { | |
117 progress.done(); | |
118 if (fc != null) { | |
119 try { | |
120 fc.close(); | |
121 } catch (IOException ex) { | |
122 ex.printStackTrace(); | |
123 } | |
124 } | |
125 } | |
126 } else { | |
127 contentWithFilters(TIP, sink); | |
128 } | |
82 } | 129 } |
83 | 130 |
84 // public void content(int revision, ByteChannel sink, boolean applyFilters) throws HgDataStreamException, IOException, CancelledException { | 131 // public void content(int revision, ByteChannel sink, boolean applyFilters) throws HgDataStreamException, IOException, CancelledException { |
85 // byte[] content = content(revision); | 132 // byte[] content = content(revision); |
86 // final CancelSupport cancelSupport = CancelSupport.Factory.get(sink); | 133 // final CancelSupport cancelSupport = CancelSupport.Factory.get(sink); |
104 // } while (left > 0); | 151 // } while (left > 0); |
105 // progressSupport.done(); // XXX shall specify whether #done() is invoked always or only if completed successfully. | 152 // progressSupport.done(); // XXX shall specify whether #done() is invoked always or only if completed successfully. |
106 // } | 153 // } |
107 | 154 |
108 /*XXX not sure distinct method contentWithFilters() is the best way to do, perhaps, callers shall add filters themselves?*/ | 155 /*XXX not sure distinct method contentWithFilters() is the best way to do, perhaps, callers shall add filters themselves?*/ |
109 public void contentWithFilters(int revision, ByteChannel sink) throws HgDataStreamException, IOException, CancelledException { | 156 public void contentWithFilters(int revision, ByteChannel sink) throws HgDataStreamException, CancelledException { |
110 content(revision, new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath()))); | 157 if (revision == WORKING_COPY) { |
158 workingCopy(sink); // pass un-mangled sink | |
159 } else { | |
160 content(revision, new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath()))); | |
161 } | |
111 } | 162 } |
112 | 163 |
113 // for data files need to check heading of the file content for possible metadata | 164 // for data files need to check heading of the file content for possible metadata |
114 // @see http://mercurial.selenic.com/wiki/FileFormats#data.2BAC8- | 165 // @see http://mercurial.selenic.com/wiki/FileFormats#data.2BAC8- |
115 public void content(int revision, ByteChannel sink) throws HgDataStreamException, IOException, CancelledException { | 166 public void content(int revision, ByteChannel sink) throws HgDataStreamException, CancelledException { |
116 if (revision == TIP) { | 167 if (revision == TIP) { |
117 revision = getLastRevision(); | 168 revision = getLastRevision(); |
118 } | 169 } |
119 if (revision == WORKING_COPY) { | 170 if (revision == WORKING_COPY) { |
171 // sink is supposed to come into workingCopy without filters | |
172 // thus we shall not get here (into #content) from #contentWithFilters(WC) | |
120 workingCopy(sink); | 173 workingCopy(sink); |
121 return; | 174 return; |
122 } | 175 } |
123 if (wrongLocalRevision(revision) || revision == BAD_REVISION) { | 176 if (wrongLocalRevision(revision) || revision == BAD_REVISION) { |
124 throw new IllegalArgumentException(String.valueOf(revision)); | 177 throw new IllegalArgumentException(String.valueOf(revision)); |
139 insp = new MetadataContentPipe(sink, metadata, getPath()); | 192 insp = new MetadataContentPipe(sink, metadata, getPath()); |
140 } | 193 } |
141 insp.checkCancelled(); | 194 insp.checkCancelled(); |
142 super.content.iterate(revision, revision, true, insp); | 195 super.content.iterate(revision, revision, true, insp); |
143 try { | 196 try { |
144 insp.checkFailed(); | 197 insp.checkFailed(); // XXX is there real need to throw IOException from ContentPipe? |
145 } catch (HgDataStreamException ex) { | 198 } catch (HgDataStreamException ex) { |
146 throw ex; | 199 throw ex; |
200 } catch (IOException ex) { | |
201 throw new HgDataStreamException(getPath(), ex); | |
147 } catch (HgException ex) { | 202 } catch (HgException ex) { |
148 // shall not happen, unless we changed ContentPipe or its subclass | 203 // shall not happen, unless we changed ContentPipe or its subclass |
149 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex); | 204 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex); |
150 } | 205 } |
151 } | 206 } |