~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Transport/BundleFetchConnection.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
This code is derived from jgit (http://eclipse.org/jgit).
 
3
Copyright owners are documented in jgit's IP log.
 
4
 
 
5
This program and the accompanying materials are made available
 
6
under the terms of the Eclipse Distribution License v1.0 which
 
7
accompanies this distribution, is reproduced below, and is
 
8
available at http://www.eclipse.org/org/documents/edl-v10.php
 
9
 
 
10
All rights reserved.
 
11
 
 
12
Redistribution and use in source and binary forms, with or
 
13
without modification, are permitted provided that the following
 
14
conditions are met:
 
15
 
 
16
- Redistributions of source code must retain the above copyright
 
17
  notice, this list of conditions and the following disclaimer.
 
18
 
 
19
- Redistributions in binary form must reproduce the above
 
20
  copyright notice, this list of conditions and the following
 
21
  disclaimer in the documentation and/or other materials provided
 
22
  with the distribution.
 
23
 
 
24
- Neither the name of the Eclipse Foundation, Inc. nor the
 
25
  names of its contributors may be used to endorse or promote
 
26
  products derived from this software without specific prior
 
27
  written permission.
 
28
 
 
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
42
*/
 
43
 
 
44
using System.Collections.Generic;
 
45
using System.IO;
 
46
using NGit;
 
47
using NGit.Errors;
 
48
using NGit.Revwalk;
 
49
using NGit.Storage.File;
 
50
using NGit.Transport;
 
51
using NGit.Util;
 
52
using Sharpen;
 
53
 
 
54
namespace NGit.Transport
 
55
{
 
56
        /// <summary>Fetch connection for bundle based classes.</summary>
 
57
        /// <remarks>
 
58
        /// Fetch connection for bundle based classes. It used by
 
59
        /// instances of
 
60
        /// <see cref="TransportBundle">TransportBundle</see>
 
61
        /// </remarks>
 
62
        internal class BundleFetchConnection : BaseFetchConnection
 
63
        {
 
64
                private readonly NGit.Transport.Transport transport;
 
65
 
 
66
                internal InputStream bin;
 
67
 
 
68
                internal readonly IDictionary<ObjectId, string> prereqs = new Dictionary<ObjectId
 
69
                        , string>();
 
70
 
 
71
                private string lockMessage;
 
72
 
 
73
                private PackLock packLock;
 
74
 
 
75
                /// <exception cref="NGit.Errors.TransportException"></exception>
 
76
                internal BundleFetchConnection(NGit.Transport.Transport transportBundle, InputStream
 
77
                         src)
 
78
                {
 
79
                        transport = transportBundle;
 
80
                        bin = new BufferedInputStream(src);
 
81
                        try
 
82
                        {
 
83
                                switch (ReadSignature())
 
84
                                {
 
85
                                        case 2:
 
86
                                        {
 
87
                                                ReadBundleV2();
 
88
                                                break;
 
89
                                        }
 
90
 
 
91
                                        default:
 
92
                                        {
 
93
                                                throw new TransportException(transport.uri, JGitText.Get().notABundle);
 
94
                                        }
 
95
                                }
 
96
                        }
 
97
                        catch (TransportException err)
 
98
                        {
 
99
                                Close();
 
100
                                throw;
 
101
                        }
 
102
                        catch (IOException err)
 
103
                        {
 
104
                                Close();
 
105
                                throw new TransportException(transport.uri, err.Message, err);
 
106
                        }
 
107
                        catch (RuntimeException err)
 
108
                        {
 
109
                                Close();
 
110
                                throw new TransportException(transport.uri, err.Message, err);
 
111
                        }
 
112
                }
 
113
 
 
114
                /// <exception cref="System.IO.IOException"></exception>
 
115
                private int ReadSignature()
 
116
                {
 
117
                        string rev = ReadLine(new byte[1024]);
 
118
                        if (NGit.Transport.TransportBundleConstants.V2_BUNDLE_SIGNATURE.Equals(rev))
 
119
                        {
 
120
                                return 2;
 
121
                        }
 
122
                        throw new TransportException(transport.uri, JGitText.Get().notABundle);
 
123
                }
 
124
 
 
125
                /// <exception cref="System.IO.IOException"></exception>
 
126
                private void ReadBundleV2()
 
127
                {
 
128
                        byte[] hdrbuf = new byte[1024];
 
129
                        LinkedHashMap<string, Ref> avail = new LinkedHashMap<string, Ref>();
 
130
                        for (; ; )
 
131
                        {
 
132
                                string line = ReadLine(hdrbuf);
 
133
                                if (line.Length == 0)
 
134
                                {
 
135
                                        break;
 
136
                                }
 
137
                                if (line[0] == '-')
 
138
                                {
 
139
                                        ObjectId id = ObjectId.FromString(Sharpen.Runtime.Substring(line, 1, 41));
 
140
                                        string shortDesc = null;
 
141
                                        if (line.Length > 42)
 
142
                                        {
 
143
                                                shortDesc = Sharpen.Runtime.Substring(line, 42);
 
144
                                        }
 
145
                                        prereqs.Put(id, shortDesc);
 
146
                                        continue;
 
147
                                }
 
148
                                string name = Sharpen.Runtime.Substring(line, 41, line.Length);
 
149
                                ObjectId id_1 = ObjectId.FromString(Sharpen.Runtime.Substring(line, 0, 40));
 
150
                                Ref prior = avail.Put(name, new ObjectIdRef.Unpeeled(RefStorage.NETWORK, name, id_1
 
151
                                        ));
 
152
                                if (prior != null)
 
153
                                {
 
154
                                        throw DuplicateAdvertisement(name);
 
155
                                }
 
156
                        }
 
157
                        Available(avail);
 
158
                }
 
159
 
 
160
                private PackProtocolException DuplicateAdvertisement(string name)
 
161
                {
 
162
                        return new PackProtocolException(transport.uri, MessageFormat.Format(JGitText.Get
 
163
                                ().duplicateAdvertisementsOf, name));
 
164
                }
 
165
 
 
166
                /// <exception cref="System.IO.IOException"></exception>
 
167
                private string ReadLine(byte[] hdrbuf)
 
168
                {
 
169
                        bin.Mark(hdrbuf.Length);
 
170
                        int cnt = bin.Read(hdrbuf);
 
171
                        int lf = 0;
 
172
                        while (lf < cnt && hdrbuf[lf] != '\n')
 
173
                        {
 
174
                                lf++;
 
175
                        }
 
176
                        bin.Reset();
 
177
                        IOUtil.SkipFully(bin, lf);
 
178
                        if (lf < cnt && hdrbuf[lf] == '\n')
 
179
                        {
 
180
                                IOUtil.SkipFully(bin, 1);
 
181
                        }
 
182
                        return RawParseUtils.Decode(Constants.CHARSET, hdrbuf, 0, lf);
 
183
                }
 
184
 
 
185
                public override bool DidFetchTestConnectivity()
 
186
                {
 
187
                        return false;
 
188
                }
 
189
 
 
190
                /// <exception cref="NGit.Errors.TransportException"></exception>
 
191
                protected internal override void DoFetch(ProgressMonitor monitor, ICollection<Ref
 
192
                        > want, ICollection<ObjectId> have)
 
193
                {
 
194
                        VerifyPrerequisites();
 
195
                        try
 
196
                        {
 
197
                                ObjectInserter ins = transport.local.NewObjectInserter();
 
198
                                try
 
199
                                {
 
200
                                        PackParser parser = ins.NewPackParser(bin);
 
201
                                        parser.SetAllowThin(true);
 
202
                                        parser.SetObjectChecking(transport.IsCheckFetchedObjects());
 
203
                                        parser.SetLockMessage(lockMessage);
 
204
                                        packLock = parser.Parse(NullProgressMonitor.INSTANCE);
 
205
                                        ins.Flush();
 
206
                                }
 
207
                                finally
 
208
                                {
 
209
                                        ins.Release();
 
210
                                }
 
211
                        }
 
212
                        catch (IOException err)
 
213
                        {
 
214
                                Close();
 
215
                                throw new TransportException(transport.uri, err.Message, err);
 
216
                        }
 
217
                        catch (RuntimeException err)
 
218
                        {
 
219
                                Close();
 
220
                                throw new TransportException(transport.uri, err.Message, err);
 
221
                        }
 
222
                }
 
223
 
 
224
                public override void SetPackLockMessage(string message)
 
225
                {
 
226
                        lockMessage = message;
 
227
                }
 
228
 
 
229
                public override ICollection<PackLock> GetPackLocks()
 
230
                {
 
231
                        if (packLock != null)
 
232
                        {
 
233
                                return Sharpen.Collections.Singleton(packLock);
 
234
                        }
 
235
                        return Sharpen.Collections.EmptyList<PackLock>();
 
236
                }
 
237
 
 
238
                /// <exception cref="NGit.Errors.TransportException"></exception>
 
239
                private void VerifyPrerequisites()
 
240
                {
 
241
                        if (prereqs.IsEmpty())
 
242
                        {
 
243
                                return;
 
244
                        }
 
245
                        RevWalk rw = new RevWalk(transport.local);
 
246
                        try
 
247
                        {
 
248
                                RevFlag PREREQ = rw.NewFlag("PREREQ");
 
249
                                RevFlag SEEN = rw.NewFlag("SEEN");
 
250
                                IDictionary<ObjectId, string> missing = new Dictionary<ObjectId, string>();
 
251
                                IList<RevObject> commits = new AList<RevObject>();
 
252
                                foreach (KeyValuePair<ObjectId, string> e in prereqs.EntrySet())
 
253
                                {
 
254
                                        ObjectId p = e.Key;
 
255
                                        try
 
256
                                        {
 
257
                                                RevCommit c = rw.ParseCommit(p);
 
258
                                                if (!c.Has(PREREQ))
 
259
                                                {
 
260
                                                        c.Add(PREREQ);
 
261
                                                        commits.AddItem(c);
 
262
                                                }
 
263
                                        }
 
264
                                        catch (MissingObjectException)
 
265
                                        {
 
266
                                                missing.Put(p, e.Value);
 
267
                                        }
 
268
                                        catch (IOException err)
 
269
                                        {
 
270
                                                throw new TransportException(transport.uri, MessageFormat.Format(JGitText.Get().cannotReadCommit
 
271
                                                        , p.Name), err);
 
272
                                        }
 
273
                                }
 
274
                                if (!missing.IsEmpty())
 
275
                                {
 
276
                                        throw new MissingBundlePrerequisiteException(transport.uri, missing);
 
277
                                }
 
278
                                foreach (Ref r in transport.local.GetAllRefs().Values)
 
279
                                {
 
280
                                        try
 
281
                                        {
 
282
                                                rw.MarkStart(rw.ParseCommit(r.GetObjectId()));
 
283
                                        }
 
284
                                        catch (IOException)
 
285
                                        {
 
286
                                        }
 
287
                                }
 
288
                                // If we cannot read the value of the ref skip it.
 
289
                                int remaining = commits.Count;
 
290
                                try
 
291
                                {
 
292
                                        RevCommit c;
 
293
                                        while ((c = rw.Next()) != null)
 
294
                                        {
 
295
                                                if (c.Has(PREREQ))
 
296
                                                {
 
297
                                                        c.Add(SEEN);
 
298
                                                        if (--remaining == 0)
 
299
                                                        {
 
300
                                                                break;
 
301
                                                        }
 
302
                                                }
 
303
                                        }
 
304
                                }
 
305
                                catch (IOException err)
 
306
                                {
 
307
                                        throw new TransportException(transport.uri, JGitText.Get().cannotReadObject, err);
 
308
                                }
 
309
                                if (remaining > 0)
 
310
                                {
 
311
                                        foreach (RevObject o in commits)
 
312
                                        {
 
313
                                                if (!o.Has(SEEN))
 
314
                                                {
 
315
                                                        missing.Put(o, prereqs.Get(o));
 
316
                                                }
 
317
                                        }
 
318
                                        throw new MissingBundlePrerequisiteException(transport.uri, missing);
 
319
                                }
 
320
                        }
 
321
                        finally
 
322
                        {
 
323
                                rw.Release();
 
324
                        }
 
325
                }
 
326
 
 
327
                public override void Close()
 
328
                {
 
329
                        if (bin != null)
 
330
                        {
 
331
                                try
 
332
                                {
 
333
                                        bin.Close();
 
334
                                }
 
335
                                catch (IOException)
 
336
                                {
 
337
                                }
 
338
                                finally
 
339
                                {
 
340
                                        // Ignore close failures.
 
341
                                        bin = null;
 
342
                                }
 
343
                        }
 
344
                }
 
345
        }
 
346
}