~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ngit/NGit/NGit.Transport/ReceivePack.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
*/
43
43
 
44
44
using System;
45
 
using System.Collections.Generic;
46
45
using System.IO;
47
 
using System.Text;
48
46
using NGit;
49
47
using NGit.Errors;
50
 
using NGit.Internal;
51
 
using NGit.Revwalk;
52
 
using NGit.Storage.File;
53
48
using NGit.Transport;
54
 
using NGit.Util.IO;
55
49
using Sharpen;
56
50
 
57
51
namespace NGit.Transport
58
52
{
59
53
        /// <summary>Implements the server side of a push connection, receiving objects.</summary>
60
54
        /// <remarks>Implements the server side of a push connection, receiving objects.</remarks>
61
 
        public class ReceivePack
 
55
        public class ReceivePack : BaseReceivePack
62
56
        {
63
 
                /// <summary>Data in the first line of a request, the line itself plus capabilities.</summary>
64
 
                /// <remarks>Data in the first line of a request, the line itself plus capabilities.</remarks>
65
 
                public class FirstLine
66
 
                {
67
 
                        private readonly string line;
68
 
 
69
 
                        private readonly ICollection<string> capabilities;
70
 
 
71
 
                        /// <summary>Parse the first line of a receive-pack request.</summary>
72
 
                        /// <remarks>Parse the first line of a receive-pack request.</remarks>
73
 
                        /// <param name="line">line from the client.</param>
74
 
                        public FirstLine(string line)
75
 
                        {
76
 
                                HashSet<string> caps = new HashSet<string>();
77
 
                                int nul = line.IndexOf('\0');
78
 
                                if (nul >= 0)
79
 
                                {
80
 
                                        foreach (string c in Sharpen.Runtime.Substring(line, nul + 1).Split(" "))
81
 
                                        {
82
 
                                                caps.AddItem(c);
83
 
                                        }
84
 
                                        this.line = Sharpen.Runtime.Substring(line, 0, nul);
85
 
                                }
86
 
                                else
87
 
                                {
88
 
                                        this.line = line;
89
 
                                }
90
 
                                this.capabilities = Sharpen.Collections.UnmodifiableSet(caps);
91
 
                        }
92
 
 
93
 
                        /// <returns>non-capabilities part of the line.</returns>
94
 
                        public virtual string GetLine()
95
 
                        {
96
 
                                return line;
97
 
                        }
98
 
 
99
 
                        /// <returns>capabilities parsed from the line.</returns>
100
 
                        public virtual ICollection<string> GetCapabilities()
101
 
                        {
102
 
                                return capabilities;
103
 
                        }
104
 
                }
105
 
 
106
 
                /// <summary>Database we write the stored objects into.</summary>
107
 
                /// <remarks>Database we write the stored objects into.</remarks>
108
 
                private readonly Repository db;
109
 
 
110
 
                /// <summary>
111
 
                /// Revision traversal support over
112
 
                /// <see cref="db">db</see>
113
 
                /// .
114
 
                /// </summary>
115
 
                private readonly RevWalk walk;
116
 
 
117
 
                /// <summary>
118
 
                /// Is the client connection a bi-directional socket or pipe?
119
 
                /// <p>
120
 
                /// If true, this class assumes it can perform multiple read and write cycles
121
 
                /// with the client over the input and output streams.
122
 
                /// </summary>
123
 
                /// <remarks>
124
 
                /// Is the client connection a bi-directional socket or pipe?
125
 
                /// <p>
126
 
                /// If true, this class assumes it can perform multiple read and write cycles
127
 
                /// with the client over the input and output streams. This matches the
128
 
                /// functionality available with a standard TCP/IP connection, or a local
129
 
                /// operating system or in-memory pipe.
130
 
                /// <p>
131
 
                /// If false, this class runs in a read everything then output results mode,
132
 
                /// making it suitable for single round-trip systems RPCs such as HTTP.
133
 
                /// </remarks>
134
 
                private bool biDirectionalPipe = true;
135
 
 
136
 
                /// <summary>Should an incoming transfer validate objects?</summary>
137
 
                private bool checkReceivedObjects;
138
 
 
139
 
                /// <summary>Should an incoming transfer permit create requests?</summary>
140
 
                private bool allowCreates;
141
 
 
142
 
                /// <summary>Should an incoming transfer permit delete requests?</summary>
143
 
                private bool allowDeletes;
144
 
 
145
 
                /// <summary>Should an incoming transfer permit non-fast-forward requests?</summary>
146
 
                private bool allowNonFastForwards;
147
 
 
148
 
                private bool allowOfsDelta;
149
 
 
150
 
                /// <summary>Identity to record action as within the reflog.</summary>
151
 
                /// <remarks>Identity to record action as within the reflog.</remarks>
152
 
                private PersonIdent refLogIdent;
153
 
 
154
 
                /// <summary>Hook used while advertising the refs to the client.</summary>
155
 
                /// <remarks>Hook used while advertising the refs to the client.</remarks>
156
 
                private AdvertiseRefsHook advertiseRefsHook;
157
 
 
158
 
                /// <summary>Filter used while advertising the refs to the client.</summary>
159
 
                /// <remarks>Filter used while advertising the refs to the client.</remarks>
160
 
                private RefFilter refFilter;
161
 
 
162
57
                /// <summary>Hook to validate the update commands before execution.</summary>
163
58
                /// <remarks>Hook to validate the update commands before execution.</remarks>
164
59
                private PreReceiveHook preReceive;
167
62
                /// <remarks>Hook to report on the commands after execution.</remarks>
168
63
                private PostReceiveHook postReceive;
169
64
 
170
 
                /// <summary>Timeout in seconds to wait for client interaction.</summary>
171
 
                /// <remarks>Timeout in seconds to wait for client interaction.</remarks>
172
 
                private int timeout;
173
 
 
174
 
                /// <summary>
175
 
                /// Timer to manage
176
 
                /// <see cref="timeout">timeout</see>
177
 
                /// .
178
 
                /// </summary>
179
 
                private InterruptTimer timer;
180
 
 
181
 
                private TimeoutInputStream timeoutIn;
182
 
 
183
 
                private InputStream rawIn;
184
 
 
185
 
                private OutputStream rawOut;
186
 
 
187
 
                private OutputStream msgOut;
188
 
 
189
 
                private readonly ReceivePack.MessageOutputWrapper msgOutWrapper;
190
 
 
191
 
                private PacketLineIn pckIn;
192
 
 
193
 
                private PacketLineOut pckOut;
194
 
 
195
 
                private PackParser parser;
196
 
 
197
 
                /// <summary>The refs we advertised as existing at the start of the connection.</summary>
198
 
                /// <remarks>The refs we advertised as existing at the start of the connection.</remarks>
199
 
                private IDictionary<string, Ref> refs;
200
 
 
201
 
                /// <summary>All SHA-1s shown to the client, which can be possible edges.</summary>
202
 
                /// <remarks>All SHA-1s shown to the client, which can be possible edges.</remarks>
203
 
                private ICollection<ObjectId> advertisedHaves;
204
 
 
205
 
                /// <summary>Capabilities requested by the client.</summary>
206
 
                /// <remarks>Capabilities requested by the client.</remarks>
207
 
                private ICollection<string> enabledCapabilities;
208
 
 
209
 
                /// <summary>Commands to execute, as received by the client.</summary>
210
 
                /// <remarks>Commands to execute, as received by the client.</remarks>
211
 
                private IList<ReceiveCommand> commands;
212
 
 
213
 
                /// <summary>Error to display instead of advertising the references.</summary>
214
 
                /// <remarks>Error to display instead of advertising the references.</remarks>
215
 
                private StringBuilder advertiseError;
216
 
 
217
 
                /// <summary>An exception caught while unpacking and fsck'ing the objects.</summary>
218
 
                /// <remarks>An exception caught while unpacking and fsck'ing the objects.</remarks>
219
 
                private Exception unpackError;
220
 
 
221
65
                /// <summary>
222
66
                /// If
223
67
                /// <see cref="BasePackPushConnection.CAPABILITY_REPORT_STATUS">BasePackPushConnection.CAPABILITY_REPORT_STATUS
226
70
                /// </summary>
227
71
                private bool reportStatus;
228
72
 
229
 
                /// <summary>
230
 
                /// If
231
 
                /// <see cref="BasePackPushConnection.CAPABILITY_SIDE_BAND_64K">BasePackPushConnection.CAPABILITY_SIDE_BAND_64K
232
 
                ///     </see>
233
 
                /// is enabled.
234
 
                /// </summary>
235
 
                private bool sideBand;
236
 
 
237
 
                /// <summary>Lock around the received pack file, while updating refs.</summary>
238
 
                /// <remarks>Lock around the received pack file, while updating refs.</remarks>
239
 
                private PackLock packLock;
240
 
 
241
 
                private bool checkReferencedIsReachable;
242
 
 
243
 
                /// <summary>Git object size limit</summary>
244
 
                private long maxObjectSizeLimit;
 
73
                private bool echoCommandFailures;
245
74
 
246
75
                /// <summary>Create a new pack receive for an open repository.</summary>
247
76
                /// <remarks>Create a new pack receive for an open repository.</remarks>
248
77
                /// <param name="into">the destination repository.</param>
249
 
                public ReceivePack(Repository into)
 
78
                protected internal ReceivePack(Repository into) : base(into)
250
79
                {
251
 
                        msgOutWrapper = new ReceivePack.MessageOutputWrapper(this);
252
 
                        db = into;
253
 
                        walk = new RevWalk(db);
254
 
                        ReceivePack.ReceiveConfig cfg = db.GetConfig().Get(ReceivePack.ReceiveConfig.KEY);
255
 
                        checkReceivedObjects = cfg.checkReceivedObjects;
256
 
                        allowCreates = cfg.allowCreates;
257
 
                        allowDeletes = cfg.allowDeletes;
258
 
                        allowNonFastForwards = cfg.allowNonFastForwards;
259
 
                        allowOfsDelta = cfg.allowOfsDelta;
260
 
                        advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
261
 
                        refFilter = RefFilter.DEFAULT;
262
80
                        preReceive = PreReceiveHook.NULL;
263
81
                        postReceive = PostReceiveHook.NULL;
264
 
                        advertisedHaves = new HashSet<ObjectId>();
265
 
                }
266
 
 
267
 
                private class ReceiveConfig
268
 
                {
269
 
                        private sealed class _SectionParser_261 : Config.SectionParser<ReceivePack.ReceiveConfig
270
 
                                >
271
 
                        {
272
 
                                public _SectionParser_261()
273
 
                                {
274
 
                                }
275
 
 
276
 
                                public ReceivePack.ReceiveConfig Parse(Config cfg)
277
 
                                {
278
 
                                        return new ReceivePack.ReceiveConfig(cfg);
279
 
                                }
280
 
                        }
281
 
 
282
 
                        internal static readonly Config.SectionParser<ReceivePack.ReceiveConfig> KEY = new 
283
 
                                _SectionParser_261();
284
 
 
285
 
                        internal readonly bool checkReceivedObjects;
286
 
 
287
 
                        internal readonly bool allowCreates;
288
 
 
289
 
                        internal readonly bool allowDeletes;
290
 
 
291
 
                        internal readonly bool allowNonFastForwards;
292
 
 
293
 
                        internal readonly bool allowOfsDelta;
294
 
 
295
 
                        internal ReceiveConfig(Config config)
296
 
                        {
297
 
                                checkReceivedObjects = config.GetBoolean("receive", "fsckobjects", false);
298
 
                                allowCreates = true;
299
 
                                allowDeletes = !config.GetBoolean("receive", "denydeletes", false);
300
 
                                allowNonFastForwards = !config.GetBoolean("receive", "denynonfastforwards", false
301
 
                                        );
302
 
                                allowOfsDelta = config.GetBoolean("repack", "usedeltabaseoffset", true);
303
 
                        }
304
 
                }
305
 
 
306
 
                /// <summary>
307
 
                /// Output stream that wraps the current
308
 
                /// <see cref="ReceivePack.msgOut">ReceivePack.msgOut</see>
309
 
                /// .
310
 
                /// <p>
311
 
                /// We don't want to expose
312
 
                /// <see cref="ReceivePack.msgOut">ReceivePack.msgOut</see>
313
 
                /// directly because it can change
314
 
                /// several times over the course of a session.
315
 
                /// </summary>
316
 
                private class MessageOutputWrapper : OutputStream
317
 
                {
318
 
                        public override void Write(int ch)
319
 
                        {
320
 
                                if (this._enclosing.msgOut != null)
321
 
                                {
322
 
                                        try
323
 
                                        {
324
 
                                                this._enclosing.msgOut.Write(ch);
325
 
                                        }
326
 
                                        catch (IOException)
327
 
                                        {
328
 
                                        }
329
 
                                }
330
 
                        }
331
 
 
332
 
                        // Ignore write failures.
333
 
                        public override void Write(byte[] b, int off, int len)
334
 
                        {
335
 
                                if (this._enclosing.msgOut != null)
336
 
                                {
337
 
                                        try
338
 
                                        {
339
 
                                                this._enclosing.msgOut.Write(b, off, len);
340
 
                                        }
341
 
                                        catch (IOException)
342
 
                                        {
343
 
                                        }
344
 
                                }
345
 
                        }
346
 
 
347
 
                        // Ignore write failures.
348
 
                        public override void Write(byte[] b)
349
 
                        {
350
 
                                this.Write(b, 0, b.Length);
351
 
                        }
352
 
 
353
 
                        public override void Flush()
354
 
                        {
355
 
                                if (this._enclosing.msgOut != null)
356
 
                                {
357
 
                                        try
358
 
                                        {
359
 
                                                this._enclosing.msgOut.Flush();
360
 
                                        }
361
 
                                        catch (IOException)
362
 
                                        {
363
 
                                        }
364
 
                                }
365
 
                        }
366
 
 
367
 
                        internal MessageOutputWrapper(ReceivePack _enclosing)
368
 
                        {
369
 
                                this._enclosing = _enclosing;
370
 
                        }
371
 
 
372
 
                        private readonly ReceivePack _enclosing;
373
 
                        // Ignore write failures.
374
 
                }
375
 
 
376
 
                /// <returns>the repository this receive completes into.</returns>
377
 
                public Repository GetRepository()
378
 
                {
379
 
                        return db;
380
 
                }
381
 
 
382
 
                /// <returns>the RevWalk instance used by this connection.</returns>
383
 
                public RevWalk GetRevWalk()
384
 
                {
385
 
                        return walk;
386
 
                }
387
 
 
388
 
                /// <summary>Get refs which were advertised to the client.</summary>
389
 
                /// <remarks>Get refs which were advertised to the client.</remarks>
390
 
                /// <returns>
391
 
                /// all refs which were advertised to the client, or null if
392
 
                /// <see cref="SetAdvertisedRefs(System.Collections.Generic.IDictionary{K, V}, System.Collections.Generic.ICollection{E})
393
 
                ///     ">SetAdvertisedRefs(System.Collections.Generic.IDictionary&lt;K, V&gt;, System.Collections.Generic.ICollection&lt;E&gt;)
394
 
                ///     </see>
395
 
                /// has not been called yet.
396
 
                /// </returns>
397
 
                public IDictionary<string, Ref> GetAdvertisedRefs()
398
 
                {
399
 
                        return refs;
400
 
                }
401
 
 
402
 
                /// <summary>Set the refs advertised by this ReceivePack.</summary>
403
 
                /// <remarks>
404
 
                /// Set the refs advertised by this ReceivePack.
405
 
                /// <p>
406
 
                /// Intended to be called from a
407
 
                /// <see cref="PreReceiveHook">PreReceiveHook</see>
408
 
                /// .
409
 
                /// </remarks>
410
 
                /// <param name="allRefs">
411
 
                /// explicit set of references to claim as advertised by this
412
 
                /// ReceivePack instance. This overrides any references that
413
 
                /// may exist in the source repository. The map is passed
414
 
                /// to the configured
415
 
                /// <see cref="GetRefFilter()">GetRefFilter()</see>
416
 
                /// . If null, assumes
417
 
                /// all refs were advertised.
418
 
                /// </param>
419
 
                /// <param name="additionalHaves">
420
 
                /// explicit set of additional haves to claim as advertised. If
421
 
                /// null, assumes the default set of additional haves from the
422
 
                /// repository.
423
 
                /// </param>
424
 
                public virtual void SetAdvertisedRefs(IDictionary<string, Ref> allRefs, ICollection
425
 
                        <ObjectId> additionalHaves)
426
 
                {
427
 
                        refs = allRefs != null ? allRefs : db.GetAllRefs();
428
 
                        refs = refFilter.Filter(refs);
429
 
                        Ref head = refs.Get(Constants.HEAD);
430
 
                        if (head != null && head.IsSymbolic())
431
 
                        {
432
 
                                Sharpen.Collections.Remove(refs, Constants.HEAD);
433
 
                        }
434
 
                        foreach (Ref @ref in refs.Values)
435
 
                        {
436
 
                                if (@ref.GetObjectId() != null)
437
 
                                {
438
 
                                        advertisedHaves.AddItem(@ref.GetObjectId());
439
 
                                }
440
 
                        }
441
 
                        if (additionalHaves != null)
442
 
                        {
443
 
                                Sharpen.Collections.AddAll(advertisedHaves, additionalHaves);
444
 
                        }
445
 
                        else
446
 
                        {
447
 
                                Sharpen.Collections.AddAll(advertisedHaves, db.GetAdditionalHaves());
448
 
                        }
449
 
                }
450
 
 
451
 
                /// <summary>Get objects advertised to the client.</summary>
452
 
                /// <remarks>Get objects advertised to the client.</remarks>
453
 
                /// <returns>
454
 
                /// the set of objects advertised to the as present in this repository,
455
 
                /// or null if
456
 
                /// <see cref="SetAdvertisedRefs(System.Collections.Generic.IDictionary{K, V}, System.Collections.Generic.ICollection{E})
457
 
                ///     ">SetAdvertisedRefs(System.Collections.Generic.IDictionary&lt;K, V&gt;, System.Collections.Generic.ICollection&lt;E&gt;)
458
 
                ///     </see>
459
 
                /// has not been called
460
 
                /// yet.
461
 
                /// </returns>
462
 
                public ICollection<ObjectId> GetAdvertisedObjects()
463
 
                {
464
 
                        return advertisedHaves;
465
 
                }
466
 
 
467
 
                /// <returns>
468
 
                /// true if this instance will validate all referenced, but not
469
 
                /// supplied by the client, objects are reachable from another
470
 
                /// reference.
471
 
                /// </returns>
472
 
                public virtual bool IsCheckReferencedObjectsAreReachable()
473
 
                {
474
 
                        return checkReferencedIsReachable;
475
 
                }
476
 
 
477
 
                /// <summary>Validate all referenced but not supplied objects are reachable.</summary>
478
 
                /// <remarks>
479
 
                /// Validate all referenced but not supplied objects are reachable.
480
 
                /// <p>
481
 
                /// If enabled, this instance will verify that references to objects not
482
 
                /// contained within the received pack are already reachable through at least
483
 
                /// one other reference displayed as part of
484
 
                /// <see cref="GetAdvertisedRefs()">GetAdvertisedRefs()</see>
485
 
                /// .
486
 
                /// <p>
487
 
                /// This feature is useful when the application doesn't trust the client to
488
 
                /// not provide a forged SHA-1 reference to an object, in an attempt to
489
 
                /// access parts of the DAG that they aren't allowed to see and which have
490
 
                /// been hidden from them via the configured
491
 
                /// <see cref="AdvertiseRefsHook">AdvertiseRefsHook</see>
492
 
                /// or
493
 
                /// <see cref="RefFilter">RefFilter</see>
494
 
                /// .
495
 
                /// <p>
496
 
                /// Enabling this feature may imply at least some, if not all, of the same
497
 
                /// functionality performed by
498
 
                /// <see cref="SetCheckReceivedObjects(bool)">SetCheckReceivedObjects(bool)</see>
499
 
                /// .
500
 
                /// Applications are encouraged to enable both features, if desired.
501
 
                /// </remarks>
502
 
                /// <param name="b">
503
 
                /// <code>true</code>
504
 
                /// to enable the additional check.
505
 
                /// </param>
506
 
                public virtual void SetCheckReferencedObjectsAreReachable(bool b)
507
 
                {
508
 
                        this.checkReferencedIsReachable = b;
509
 
                }
510
 
 
511
 
                /// <returns>
512
 
                /// true if this class expects a bi-directional pipe opened between
513
 
                /// the client and itself. The default is true.
514
 
                /// </returns>
515
 
                public virtual bool IsBiDirectionalPipe()
516
 
                {
517
 
                        return biDirectionalPipe;
518
 
                }
519
 
 
520
 
                /// <param name="twoWay">
521
 
                /// if true, this class will assume the socket is a fully
522
 
                /// bidirectional pipe between the two peers and takes advantage
523
 
                /// of that by first transmitting the known refs, then waiting to
524
 
                /// read commands. If false, this class assumes it must read the
525
 
                /// commands before writing output and does not perform the
526
 
                /// initial advertising.
527
 
                /// </param>
528
 
                public virtual void SetBiDirectionalPipe(bool twoWay)
529
 
                {
530
 
                        biDirectionalPipe = twoWay;
531
 
                }
532
 
 
533
 
                /// <returns>
534
 
                /// true if this instance will verify received objects are formatted
535
 
                /// correctly. Validating objects requires more CPU time on this side
536
 
                /// of the connection.
537
 
                /// </returns>
538
 
                public virtual bool IsCheckReceivedObjects()
539
 
                {
540
 
                        return checkReceivedObjects;
541
 
                }
542
 
 
543
 
                /// <param name="check">
544
 
                /// true to enable checking received objects; false to assume all
545
 
                /// received objects are valid.
546
 
                /// </param>
547
 
                public virtual void SetCheckReceivedObjects(bool check)
548
 
                {
549
 
                        checkReceivedObjects = check;
550
 
                }
551
 
 
552
 
                /// <returns>true if the client can request refs to be created.</returns>
553
 
                public virtual bool IsAllowCreates()
554
 
                {
555
 
                        return allowCreates;
556
 
                }
557
 
 
558
 
                /// <param name="canCreate">true to permit create ref commands to be processed.</param>
559
 
                public virtual void SetAllowCreates(bool canCreate)
560
 
                {
561
 
                        allowCreates = canCreate;
562
 
                }
563
 
 
564
 
                /// <returns>true if the client can request refs to be deleted.</returns>
565
 
                public virtual bool IsAllowDeletes()
566
 
                {
567
 
                        return allowDeletes;
568
 
                }
569
 
 
570
 
                /// <param name="canDelete">true to permit delete ref commands to be processed.</param>
571
 
                public virtual void SetAllowDeletes(bool canDelete)
572
 
                {
573
 
                        allowDeletes = canDelete;
574
 
                }
575
 
 
576
 
                /// <returns>
577
 
                /// true if the client can request non-fast-forward updates of a ref,
578
 
                /// possibly making objects unreachable.
579
 
                /// </returns>
580
 
                public virtual bool IsAllowNonFastForwards()
581
 
                {
582
 
                        return allowNonFastForwards;
583
 
                }
584
 
 
585
 
                /// <param name="canRewind">
586
 
                /// true to permit the client to ask for non-fast-forward updates
587
 
                /// of an existing ref.
588
 
                /// </param>
589
 
                public virtual void SetAllowNonFastForwards(bool canRewind)
590
 
                {
591
 
                        allowNonFastForwards = canRewind;
592
 
                }
593
 
 
594
 
                /// <returns>identity of the user making the changes in the reflog.</returns>
595
 
                public virtual PersonIdent GetRefLogIdent()
596
 
                {
597
 
                        return refLogIdent;
598
 
                }
599
 
 
600
 
                /// <summary>Set the identity of the user appearing in the affected reflogs.</summary>
601
 
                /// <remarks>
602
 
                /// Set the identity of the user appearing in the affected reflogs.
603
 
                /// <p>
604
 
                /// The timestamp portion of the identity is ignored. A new identity with the
605
 
                /// current timestamp will be created automatically when the updates occur
606
 
                /// and the log records are written.
607
 
                /// </remarks>
608
 
                /// <param name="pi">
609
 
                /// identity of the user. If null the identity will be
610
 
                /// automatically determined based on the repository
611
 
                /// configuration.
612
 
                /// </param>
613
 
                public virtual void SetRefLogIdent(PersonIdent pi)
614
 
                {
615
 
                        refLogIdent = pi;
616
 
                }
617
 
 
618
 
                /// <returns>the hook used while advertising the refs to the client</returns>
619
 
                public virtual AdvertiseRefsHook GetAdvertiseRefsHook()
620
 
                {
621
 
                        return advertiseRefsHook;
622
 
                }
623
 
 
624
 
                /// <returns>the filter used while advertising the refs to the client</returns>
625
 
                public virtual RefFilter GetRefFilter()
626
 
                {
627
 
                        return refFilter;
628
 
                }
629
 
 
630
 
                /// <summary>Set the hook used while advertising the refs to the client.</summary>
631
 
                /// <remarks>
632
 
                /// Set the hook used while advertising the refs to the client.
633
 
                /// <p>
634
 
                /// If the
635
 
                /// <see cref="AdvertiseRefsHook">AdvertiseRefsHook</see>
636
 
                /// chooses to call
637
 
                /// <see cref="SetAdvertisedRefs(System.Collections.Generic.IDictionary{K, V}, System.Collections.Generic.ICollection{E})
638
 
                ///     ">SetAdvertisedRefs(System.Collections.Generic.IDictionary&lt;K, V&gt;, System.Collections.Generic.ICollection&lt;E&gt;)
639
 
                ///     </see>
640
 
                /// , only refs set by this hook
641
 
                /// <em>and</em> selected by the
642
 
                /// <see cref="RefFilter">RefFilter</see>
643
 
                /// will be shown to the client.
644
 
                /// Clients may still attempt to create or update a reference not advertised by
645
 
                /// the configured
646
 
                /// <see cref="AdvertiseRefsHook">AdvertiseRefsHook</see>
647
 
                /// . These attempts should be rejected
648
 
                /// by a matching
649
 
                /// <see cref="PreReceiveHook">PreReceiveHook</see>
650
 
                /// .
651
 
                /// </remarks>
652
 
                /// <param name="advertiseRefsHook">the hook; may be null to show all refs.</param>
653
 
                public virtual void SetAdvertiseRefsHook(AdvertiseRefsHook advertiseRefsHook)
654
 
                {
655
 
                        if (advertiseRefsHook != null)
656
 
                        {
657
 
                                this.advertiseRefsHook = advertiseRefsHook;
658
 
                        }
659
 
                        else
660
 
                        {
661
 
                                this.advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
662
 
                        }
663
 
                }
664
 
 
665
 
                /// <summary>Set the filter used while advertising the refs to the client.</summary>
666
 
                /// <remarks>
667
 
                /// Set the filter used while advertising the refs to the client.
668
 
                /// <p>
669
 
                /// Only refs allowed by this filter will be shown to the client.
670
 
                /// The filter is run against the refs specified by the
671
 
                /// <see cref="AdvertiseRefsHook">AdvertiseRefsHook</see>
672
 
                /// (if applicable).
673
 
                /// </remarks>
674
 
                /// <param name="refFilter">the filter; may be null to show all refs.</param>
675
 
                public virtual void SetRefFilter(RefFilter refFilter)
676
 
                {
677
 
                        this.refFilter = refFilter != null ? refFilter : RefFilter.DEFAULT;
678
82
                }
679
83
 
680
84
                /// <returns>the hook invoked before updates occur.</returns>
724
128
                        postReceive = h != null ? h : PostReceiveHook.NULL;
725
129
                }
726
130
 
727
 
                /// <returns>timeout (in seconds) before aborting an IO operation.</returns>
728
 
                public virtual int GetTimeout()
729
 
                {
730
 
                        return timeout;
731
 
                }
732
 
 
733
 
                /// <summary>Set the timeout before willing to abort an IO call.</summary>
734
 
                /// <remarks>Set the timeout before willing to abort an IO call.</remarks>
735
 
                /// <param name="seconds">
736
 
                /// number of seconds to wait (with no data transfer occurring)
737
 
                /// before aborting an IO read or write operation with the
738
 
                /// connected client.
739
 
                /// </param>
740
 
                public virtual void SetTimeout(int seconds)
741
 
                {
742
 
                        timeout = seconds;
743
 
                }
744
 
 
745
 
                /// <summary>Set the maximum allowed Git object size.</summary>
746
 
                /// <remarks>
747
 
                /// Set the maximum allowed Git object size.
748
 
                /// <p>
749
 
                /// If an object is larger than the given size the pack-parsing will throw an
750
 
                /// exception aborting the receive-pack operation.
751
 
                /// </remarks>
752
 
                /// <param name="limit">the Git object size limit. If zero then there is not limit.</param>
753
 
                public virtual void SetMaxObjectSizeLimit(long limit)
754
 
                {
755
 
                        maxObjectSizeLimit = limit;
756
 
                }
757
 
 
758
 
                /// <summary>Check whether the client expects a side-band stream.</summary>
759
 
                /// <remarks>Check whether the client expects a side-band stream.</remarks>
760
 
                /// <returns>
761
 
                /// true if the client has advertised a side-band capability, false
762
 
                /// otherwise.
763
 
                /// </returns>
764
 
                /// <exception cref="RequestNotYetReadException">
765
 
                /// if the client's request has not yet been read from the wire, so
766
 
                /// we do not know if they expect side-band. Note that the client
767
 
                /// may have already written the request, it just has not been
768
 
                /// read.
769
 
                /// </exception>
770
 
                /// <exception cref="NGit.Transport.RequestNotYetReadException"></exception>
771
 
                public virtual bool IsSideBand()
772
 
                {
773
 
                        if (enabledCapabilities == null)
774
 
                        {
775
 
                                throw new RequestNotYetReadException();
776
 
                        }
777
 
                        return enabledCapabilities.Contains(BasePackPushConnection.CAPABILITY_SIDE_BAND_64K
778
 
                                );
779
 
                }
780
 
 
781
 
                /// <returns>all of the command received by the current request.</returns>
782
 
                public virtual IList<ReceiveCommand> GetAllCommands()
783
 
                {
784
 
                        return Sharpen.Collections.UnmodifiableList(commands);
785
 
                }
786
 
 
787
 
                /// <summary>Send an error message to the client.</summary>
788
 
                /// <remarks>
789
 
                /// Send an error message to the client.
790
 
                /// <p>
791
 
                /// If any error messages are sent before the references are advertised to
792
 
                /// the client, the errors will be sent instead of the advertisement and the
793
 
                /// receive operation will be aborted. All clients should receive and display
794
 
                /// such early stage errors.
795
 
                /// <p>
796
 
                /// If the reference advertisements have already been sent, messages are sent
797
 
                /// in a side channel. If the client doesn't support receiving messages, the
798
 
                /// message will be discarded, with no other indication to the caller or to
799
 
                /// the client.
800
 
                /// <p>
801
 
                /// <see cref="PreReceiveHook">PreReceiveHook</see>
802
 
                /// s should always try to use
803
 
                /// <see cref="ReceiveCommand.SetResult(Result, string)">ReceiveCommand.SetResult(Result, string)
804
 
                ///     </see>
805
 
                /// with a result status of
806
 
                /// <see cref="Result.REJECTED_OTHER_REASON">Result.REJECTED_OTHER_REASON</see>
807
 
                /// to indicate any reasons for
808
 
                /// rejecting an update. Messages attached to a command are much more likely
809
 
                /// to be returned to the client.
810
 
                /// </remarks>
811
 
                /// <param name="what">
812
 
                /// string describing the problem identified by the hook. The
813
 
                /// string must not end with an LF, and must not contain an LF.
814
 
                /// </param>
815
 
                public virtual void SendError(string what)
816
 
                {
817
 
                        if (refs == null)
818
 
                        {
819
 
                                if (advertiseError == null)
820
 
                                {
821
 
                                        advertiseError = new StringBuilder();
822
 
                                }
823
 
                                advertiseError.Append(what).Append('\n');
824
 
                        }
825
 
                        else
826
 
                        {
827
 
                                msgOutWrapper.Write(Constants.Encode("error: " + what + "\n"));
828
 
                        }
829
 
                }
830
 
 
831
 
                /// <summary>Send a message to the client, if it supports receiving them.</summary>
832
 
                /// <remarks>
833
 
                /// Send a message to the client, if it supports receiving them.
834
 
                /// <p>
835
 
                /// If the client doesn't support receiving messages, the message will be
836
 
                /// discarded, with no other indication to the caller or to the client.
837
 
                /// </remarks>
838
 
                /// <param name="what">
839
 
                /// string describing the problem identified by the hook. The
840
 
                /// string must not end with an LF, and must not contain an LF.
841
 
                /// </param>
842
 
                public virtual void SendMessage(string what)
843
 
                {
844
 
                        msgOutWrapper.Write(Constants.Encode(what + "\n"));
845
 
                }
846
 
 
847
 
                /// <returns>an underlying stream for sending messages to the client.</returns>
848
 
                public virtual OutputStream GetMessageOutputStream()
849
 
                {
850
 
                        return msgOutWrapper;
 
131
                /// <param name="echo">
 
132
                /// if true this class will report command failures as warning
 
133
                /// messages before sending the command results. This is usually
 
134
                /// not necessary, but may help buggy Git clients that discard the
 
135
                /// errors when all branches fail.
 
136
                /// </param>
 
137
                public virtual void SetEchoCommandFailures(bool echo)
 
138
                {
 
139
                        echoCommandFailures = echo;
851
140
                }
852
141
 
853
142
                /// <summary>Execute the receive task on the socket.</summary>
872
161
                public virtual void Receive(InputStream input, OutputStream output, OutputStream 
873
162
                        messages)
874
163
                {
 
164
                        Init(input, output, messages);
875
165
                        try
876
166
                        {
877
 
                                rawIn = input;
878
 
                                rawOut = output;
879
 
                                msgOut = messages;
880
 
                                if (timeout > 0)
881
 
                                {
882
 
                                        Sharpen.Thread caller = Sharpen.Thread.CurrentThread();
883
 
                                        timer = new InterruptTimer(caller.GetName() + "-Timer");
884
 
                                        timeoutIn = new TimeoutInputStream(rawIn, timer);
885
 
                                        TimeoutOutputStream o = new TimeoutOutputStream(rawOut, timer);
886
 
                                        timeoutIn.SetTimeout(timeout * 1000);
887
 
                                        o.SetTimeout(timeout * 1000);
888
 
                                        rawIn = timeoutIn;
889
 
                                        rawOut = o;
890
 
                                }
891
 
                                pckIn = new PacketLineIn(rawIn);
892
 
                                pckOut = new PacketLineOut(rawOut);
893
 
                                pckOut.SetFlushOnEnd(false);
894
 
                                commands = new AList<ReceiveCommand>();
895
167
                                Service();
896
168
                        }
897
169
                        finally
898
170
                        {
899
 
                                walk.Release();
900
171
                                try
901
172
                                {
902
 
                                        if (sideBand)
903
 
                                        {
904
 
                                                // If we are using side band, we need to send a final
905
 
                                                // flush-pkt to tell the remote peer the side band is
906
 
                                                // complete and it should stop decoding. We need to
907
 
                                                // use the original output stream as rawOut is now the
908
 
                                                // side band data channel.
909
 
                                                //
910
 
                                                ((SideBandOutputStream)msgOut).FlushBuffer();
911
 
                                                ((SideBandOutputStream)rawOut).FlushBuffer();
912
 
                                                PacketLineOut plo = new PacketLineOut(output);
913
 
                                                plo.SetFlushOnEnd(false);
914
 
                                                plo.End();
915
 
                                        }
916
 
                                        if (biDirectionalPipe)
917
 
                                        {
918
 
                                                // If this was a native git connection, flush the pipe for
919
 
                                                // the caller. For smart HTTP we don't do this flush and
920
 
                                                // instead let the higher level HTTP servlet code do it.
921
 
                                                //
922
 
                                                if (!sideBand && msgOut != null)
923
 
                                                {
924
 
                                                        msgOut.Flush();
925
 
                                                }
926
 
                                                rawOut.Flush();
927
 
                                        }
 
173
                                        Close();
928
174
                                }
929
175
                                finally
930
176
                                {
931
 
                                        UnlockPack();
932
 
                                        timeoutIn = null;
933
 
                                        rawIn = null;
934
 
                                        rawOut = null;
935
 
                                        msgOut = null;
936
 
                                        pckIn = null;
937
 
                                        pckOut = null;
938
 
                                        refs = null;
939
 
                                        enabledCapabilities = null;
940
 
                                        commands = null;
941
 
                                        if (timer != null)
942
 
                                        {
943
 
                                                try
944
 
                                                {
945
 
                                                        timer.Terminate();
946
 
                                                }
947
 
                                                finally
948
 
                                                {
949
 
                                                        timer = null;
950
 
                                                }
951
 
                                        }
 
177
                                        Release();
952
178
                                }
953
179
                        }
954
180
                }
955
181
 
956
 
                private IDictionary<string, Ref> GetAdvertisedOrDefaultRefs()
 
182
                protected internal override void EnableCapabilities()
957
183
                {
958
 
                        if (refs == null)
959
 
                        {
960
 
                                SetAdvertisedRefs(null, null);
961
 
                        }
962
 
                        return refs;
 
184
                        reportStatus = IsCapabilityEnabled(BasePackPushConnection.CAPABILITY_REPORT_STATUS
 
185
                                );
 
186
                        base.EnableCapabilities();
963
187
                }
964
188
 
965
189
                /// <exception cref="System.IO.IOException"></exception>
966
190
                private void Service()
967
191
                {
968
 
                        if (biDirectionalPipe)
 
192
                        if (IsBiDirectionalPipe())
969
193
                        {
970
194
                                SendAdvertisedRefs(new RefAdvertiser.PacketLineOutRefAdvertiser(pckOut));
971
195
                                pckOut.Flush();
974
198
                        {
975
199
                                GetAdvertisedOrDefaultRefs();
976
200
                        }
977
 
                        if (advertiseError != null)
 
201
                        if (HasError())
978
202
                        {
979
203
                                return;
980
204
                        }
981
205
                        RecvCommands();
982
 
                        if (!commands.IsEmpty())
 
206
                        if (HasCommands())
983
207
                        {
984
208
                                EnableCapabilities();
 
209
                                Exception unpackError = null;
985
210
                                if (NeedPack())
986
211
                                {
987
212
                                        try
988
213
                                        {
989
 
                                                DoReceivePack();
990
 
                                                if (NeedCheckConnectivity())
991
 
                                                {
992
 
                                                        CheckConnectivity();
993
 
                                                }
994
 
                                                parser = null;
995
 
                                                unpackError = null;
 
214
                                                ReceivePackAndCheckConnectivity();
996
215
                                        }
997
216
                                        catch (IOException err)
998
217
                                        {
1010
229
                                if (unpackError == null)
1011
230
                                {
1012
231
                                        ValidateCommands();
 
232
                                        preReceive.OnPreReceive(this, FilterCommands(ReceiveCommand.Result.NOT_ATTEMPTED)
 
233
                                                );
1013
234
                                        ExecuteCommands();
1014
235
                                }
1015
236
                                UnlockPack();
1016
237
                                if (reportStatus)
1017
238
                                {
1018
 
                                        SendStatusReport(true, new _Reporter_860(this));
 
239
                                        if (echoCommandFailures && msgOut != null)
 
240
                                        {
 
241
                                                SendStatusReport(false, unpackError, new _Reporter_210(this));
 
242
                                                msgOut.Flush();
 
243
                                                try
 
244
                                                {
 
245
                                                        Sharpen.Thread.Sleep(500);
 
246
                                                }
 
247
                                                catch (Exception)
 
248
                                                {
 
249
                                                }
 
250
                                        }
 
251
                                        // Ignore an early wake up.
 
252
                                        SendStatusReport(true, unpackError, new _Reporter_222(this));
1019
253
                                        pckOut.End();
1020
254
                                }
1021
255
                                else
1022
256
                                {
1023
257
                                        if (msgOut != null)
1024
258
                                        {
1025
 
                                                SendStatusReport(false, new _Reporter_867(this));
 
259
                                                SendStatusReport(false, unpackError, new _Reporter_229(this));
1026
260
                                        }
1027
261
                                }
1028
 
                                postReceive.OnPostReceive(this, ReceiveCommand.Filter(commands, ReceiveCommand.Result
1029
 
                                        .OK));
 
262
                                postReceive.OnPostReceive(this, FilterCommands(ReceiveCommand.Result.OK));
1030
263
                                if (unpackError != null)
1031
264
                                {
1032
265
                                        throw new UnpackException(unpackError);
1034
267
                        }
1035
268
                }
1036
269
 
1037
 
                private sealed class _Reporter_860 : ReceivePack.Reporter
1038
 
                {
1039
 
                        public _Reporter_860(ReceivePack _enclosing)
 
270
                private sealed class _Reporter_210 : BaseReceivePack.Reporter
 
271
                {
 
272
                        public _Reporter_210(ReceivePack _enclosing)
 
273
                        {
 
274
                                this._enclosing = _enclosing;
 
275
                        }
 
276
 
 
277
                        /// <exception cref="System.IO.IOException"></exception>
 
278
                        internal override void SendString(string s)
 
279
                        {
 
280
                                this._enclosing.msgOut.Write(Constants.Encode(s + "\n"));
 
281
                        }
 
282
 
 
283
                        private readonly ReceivePack _enclosing;
 
284
                }
 
285
 
 
286
                private sealed class _Reporter_222 : BaseReceivePack.Reporter
 
287
                {
 
288
                        public _Reporter_222(ReceivePack _enclosing)
1040
289
                        {
1041
290
                                this._enclosing = _enclosing;
1042
291
                        }
1050
299
                        private readonly ReceivePack _enclosing;
1051
300
                }
1052
301
 
1053
 
                private sealed class _Reporter_867 : ReceivePack.Reporter
 
302
                private sealed class _Reporter_229 : BaseReceivePack.Reporter
1054
303
                {
1055
 
                        public _Reporter_867(ReceivePack _enclosing)
 
304
                        public _Reporter_229(ReceivePack _enclosing)
1056
305
                        {
1057
306
                                this._enclosing = _enclosing;
1058
307
                        }
1066
315
                        private readonly ReceivePack _enclosing;
1067
316
                }
1068
317
 
1069
 
                /// <exception cref="System.IO.IOException"></exception>
1070
 
                private void UnlockPack()
1071
 
                {
1072
 
                        if (packLock != null)
1073
 
                        {
1074
 
                                packLock.Unlock();
1075
 
                                packLock = null;
1076
 
                        }
1077
 
                }
1078
 
 
1079
 
                /// <summary>Generate an advertisement of available refs and capabilities.</summary>
1080
 
                /// <remarks>Generate an advertisement of available refs and capabilities.</remarks>
1081
 
                /// <param name="adv">the advertisement formatter.</param>
1082
 
                /// <exception cref="System.IO.IOException">the formatter failed to write an advertisement.
1083
 
                ///     </exception>
1084
 
                /// <exception cref="ServiceMayNotContinueException">the hook denied advertisement.</exception>
1085
 
                /// <exception cref="NGit.Transport.ServiceMayNotContinueException"></exception>
1086
 
                public virtual void SendAdvertisedRefs(RefAdvertiser adv)
1087
 
                {
1088
 
                        if (advertiseError != null)
1089
 
                        {
1090
 
                                adv.WriteOne("ERR " + advertiseError);
1091
 
                                return;
1092
 
                        }
1093
 
                        try
1094
 
                        {
1095
 
                                advertiseRefsHook.AdvertiseRefs(this);
1096
 
                        }
1097
 
                        catch (ServiceMayNotContinueException fail)
1098
 
                        {
1099
 
                                if (fail.Message != null)
1100
 
                                {
1101
 
                                        adv.WriteOne("ERR " + fail.Message);
1102
 
                                        fail.SetOutput();
1103
 
                                }
1104
 
                                throw;
1105
 
                        }
1106
 
                        adv.Init(db);
1107
 
                        adv.AdvertiseCapability(BasePackPushConnection.CAPABILITY_SIDE_BAND_64K);
1108
 
                        adv.AdvertiseCapability(BasePackPushConnection.CAPABILITY_DELETE_REFS);
1109
 
                        adv.AdvertiseCapability(BasePackPushConnection.CAPABILITY_REPORT_STATUS);
1110
 
                        if (allowOfsDelta)
1111
 
                        {
1112
 
                                adv.AdvertiseCapability(BasePackPushConnection.CAPABILITY_OFS_DELTA);
1113
 
                        }
1114
 
                        adv.Send(GetAdvertisedOrDefaultRefs());
1115
 
                        foreach (ObjectId obj in advertisedHaves)
1116
 
                        {
1117
 
                                adv.AdvertiseHave(obj);
1118
 
                        }
1119
 
                        if (adv.IsEmpty())
1120
 
                        {
1121
 
                                adv.AdvertiseId(ObjectId.ZeroId, "capabilities^{}");
1122
 
                        }
1123
 
                        adv.End();
1124
 
                }
1125
 
 
1126
 
                /// <exception cref="System.IO.IOException"></exception>
1127
 
                private void RecvCommands()
1128
 
                {
1129
 
                        for (; ; )
1130
 
                        {
1131
 
                                string line;
1132
 
                                try
1133
 
                                {
1134
 
                                        line = pckIn.ReadStringRaw();
1135
 
                                }
1136
 
                                catch (EOFException eof)
1137
 
                                {
1138
 
                                        if (commands.IsEmpty())
1139
 
                                        {
1140
 
                                                return;
1141
 
                                        }
1142
 
                                        throw;
1143
 
                                }
1144
 
                                if (line == PacketLineIn.END)
1145
 
                                {
1146
 
                                        break;
1147
 
                                }
1148
 
                                if (commands.IsEmpty())
1149
 
                                {
1150
 
                                        ReceivePack.FirstLine firstLine = new ReceivePack.FirstLine(line);
1151
 
                                        enabledCapabilities = firstLine.GetCapabilities();
1152
 
                                        line = firstLine.GetLine();
1153
 
                                }
1154
 
                                if (line.Length < 83)
1155
 
                                {
1156
 
                                        string m = JGitText.Get().errorInvalidProtocolWantedOldNewRef;
1157
 
                                        SendError(m);
1158
 
                                        throw new PackProtocolException(m);
1159
 
                                }
1160
 
                                ObjectId oldId = ObjectId.FromString(Sharpen.Runtime.Substring(line, 0, 40));
1161
 
                                ObjectId newId = ObjectId.FromString(Sharpen.Runtime.Substring(line, 41, 81));
1162
 
                                string name = Sharpen.Runtime.Substring(line, 82);
1163
 
                                ReceiveCommand cmd = new ReceiveCommand(oldId, newId, name);
1164
 
                                if (name.Equals(Constants.HEAD))
1165
 
                                {
1166
 
                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_CURRENT_BRANCH);
1167
 
                                }
1168
 
                                else
1169
 
                                {
1170
 
                                        cmd.SetRef(refs.Get(cmd.GetRefName()));
1171
 
                                }
1172
 
                                commands.AddItem(cmd);
1173
 
                        }
1174
 
                }
1175
 
 
1176
 
                private void EnableCapabilities()
1177
 
                {
1178
 
                        reportStatus = enabledCapabilities.Contains(BasePackPushConnection.CAPABILITY_REPORT_STATUS
1179
 
                                );
1180
 
                        sideBand = enabledCapabilities.Contains(BasePackPushConnection.CAPABILITY_SIDE_BAND_64K
1181
 
                                );
1182
 
                        if (sideBand)
1183
 
                        {
1184
 
                                OutputStream @out = rawOut;
1185
 
                                rawOut = new SideBandOutputStream(SideBandOutputStream.CH_DATA, SideBandOutputStream
1186
 
                                        .MAX_BUF, @out);
1187
 
                                msgOut = new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, SideBandOutputStream
1188
 
                                        .MAX_BUF, @out);
1189
 
                                pckOut = new PacketLineOut(rawOut);
1190
 
                                pckOut.SetFlushOnEnd(false);
1191
 
                        }
1192
 
                }
1193
 
 
1194
 
                private bool NeedPack()
1195
 
                {
1196
 
                        foreach (ReceiveCommand cmd in commands)
1197
 
                        {
1198
 
                                if (cmd.GetType() != ReceiveCommand.Type.DELETE)
1199
 
                                {
1200
 
                                        return true;
1201
 
                                }
1202
 
                        }
1203
 
                        return false;
1204
 
                }
1205
 
 
1206
 
                /// <exception cref="System.IO.IOException"></exception>
1207
 
                private void DoReceivePack()
1208
 
                {
1209
 
                        // It might take the client a while to pack the objects it needs
1210
 
                        // to send to us.  We should increase our timeout so we don't
1211
 
                        // abort while the client is computing.
1212
 
                        //
1213
 
                        if (timeoutIn != null)
1214
 
                        {
1215
 
                                timeoutIn.SetTimeout(10 * timeout * 1000);
1216
 
                        }
1217
 
                        ProgressMonitor receiving = NullProgressMonitor.INSTANCE;
1218
 
                        ProgressMonitor resolving = NullProgressMonitor.INSTANCE;
1219
 
                        if (sideBand)
1220
 
                        {
1221
 
                                resolving = new SideBandProgressMonitor(msgOut);
1222
 
                        }
1223
 
                        ObjectInserter ins = db.NewObjectInserter();
1224
 
                        try
1225
 
                        {
1226
 
                                string lockMsg = "jgit receive-pack";
1227
 
                                if (GetRefLogIdent() != null)
1228
 
                                {
1229
 
                                        lockMsg += " from " + GetRefLogIdent().ToExternalString();
1230
 
                                }
1231
 
                                parser = ins.NewPackParser(rawIn);
1232
 
                                parser.SetAllowThin(true);
1233
 
                                parser.SetNeedNewObjectIds(checkReferencedIsReachable);
1234
 
                                parser.SetNeedBaseObjectIds(checkReferencedIsReachable);
1235
 
                                parser.SetCheckEofAfterPackFooter(!biDirectionalPipe);
1236
 
                                parser.SetObjectChecking(IsCheckReceivedObjects());
1237
 
                                parser.SetLockMessage(lockMsg);
1238
 
                                parser.SetMaxObjectSizeLimit(maxObjectSizeLimit);
1239
 
                                packLock = parser.Parse(receiving, resolving);
1240
 
                                ins.Flush();
1241
 
                        }
1242
 
                        finally
1243
 
                        {
1244
 
                                ins.Release();
1245
 
                        }
1246
 
                        if (timeoutIn != null)
1247
 
                        {
1248
 
                                timeoutIn.SetTimeout(timeout * 1000);
1249
 
                        }
1250
 
                }
1251
 
 
1252
 
                private bool NeedCheckConnectivity()
1253
 
                {
1254
 
                        return IsCheckReceivedObjects() || IsCheckReferencedObjectsAreReachable();
1255
 
                }
1256
 
 
1257
 
                /// <exception cref="System.IO.IOException"></exception>
1258
 
                private void CheckConnectivity()
1259
 
                {
1260
 
                        ObjectIdSubclassMap<ObjectId> baseObjects = null;
1261
 
                        ObjectIdSubclassMap<ObjectId> providedObjects = null;
1262
 
                        if (checkReferencedIsReachable)
1263
 
                        {
1264
 
                                baseObjects = parser.GetBaseObjectIds();
1265
 
                                providedObjects = parser.GetNewObjectIds();
1266
 
                        }
1267
 
                        parser = null;
1268
 
                        ObjectWalk ow = new ObjectWalk(db);
1269
 
                        ow.SetRetainBody(false);
1270
 
                        if (checkReferencedIsReachable)
1271
 
                        {
1272
 
                                ow.Sort(RevSort.TOPO);
1273
 
                                if (!baseObjects.IsEmpty())
1274
 
                                {
1275
 
                                        ow.Sort(RevSort.BOUNDARY, true);
1276
 
                                }
1277
 
                        }
1278
 
                        foreach (ReceiveCommand cmd in commands)
1279
 
                        {
1280
 
                                if (cmd.GetResult() != ReceiveCommand.Result.NOT_ATTEMPTED)
1281
 
                                {
1282
 
                                        continue;
1283
 
                                }
1284
 
                                if (cmd.GetType() == ReceiveCommand.Type.DELETE)
1285
 
                                {
1286
 
                                        continue;
1287
 
                                }
1288
 
                                ow.MarkStart(ow.ParseAny(cmd.GetNewId()));
1289
 
                        }
1290
 
                        foreach (ObjectId have in advertisedHaves)
1291
 
                        {
1292
 
                                RevObject o = ow.ParseAny(have);
1293
 
                                ow.MarkUninteresting(o);
1294
 
                                if (checkReferencedIsReachable && !baseObjects.IsEmpty())
1295
 
                                {
1296
 
                                        o = ow.Peel(o);
1297
 
                                        if (o is RevCommit)
1298
 
                                        {
1299
 
                                                o = ((RevCommit)o).Tree;
1300
 
                                        }
1301
 
                                        if (o is RevTree)
1302
 
                                        {
1303
 
                                                ow.MarkUninteresting(o);
1304
 
                                        }
1305
 
                                }
1306
 
                        }
1307
 
                        RevCommit c;
1308
 
                        while ((c = ow.Next()) != null)
1309
 
                        {
1310
 
                                if (checkReferencedIsReachable && !c.Has(RevFlag.UNINTERESTING) && !providedObjects
1311
 
                                        .Contains(c))
1312
 
                                {
1313
 
                                        //
1314
 
                                        //
1315
 
                                        throw new MissingObjectException(c, Constants.TYPE_COMMIT);
1316
 
                                }
1317
 
                        }
1318
 
                        RevObject o_1;
1319
 
                        while ((o_1 = ow.NextObject()) != null)
1320
 
                        {
1321
 
                                if (o_1.Has(RevFlag.UNINTERESTING))
1322
 
                                {
1323
 
                                        continue;
1324
 
                                }
1325
 
                                if (checkReferencedIsReachable)
1326
 
                                {
1327
 
                                        if (providedObjects.Contains(o_1))
1328
 
                                        {
1329
 
                                                continue;
1330
 
                                        }
1331
 
                                        else
1332
 
                                        {
1333
 
                                                throw new MissingObjectException(o_1, o_1.Type);
1334
 
                                        }
1335
 
                                }
1336
 
                                if (o_1 is RevBlob && !db.HasObject(o_1))
1337
 
                                {
1338
 
                                        throw new MissingObjectException(o_1, Constants.TYPE_BLOB);
1339
 
                                }
1340
 
                        }
1341
 
                        if (checkReferencedIsReachable)
1342
 
                        {
1343
 
                                foreach (ObjectId id in baseObjects)
1344
 
                                {
1345
 
                                        o_1 = ow.ParseAny(id);
1346
 
                                        if (!o_1.Has(RevFlag.UNINTERESTING))
1347
 
                                        {
1348
 
                                                throw new MissingObjectException(o_1, o_1.Type);
1349
 
                                        }
1350
 
                                }
1351
 
                        }
1352
 
                }
1353
 
 
1354
 
                private void ValidateCommands()
1355
 
                {
1356
 
                        foreach (ReceiveCommand cmd in commands)
1357
 
                        {
1358
 
                                Ref @ref = cmd.GetRef();
1359
 
                                if (cmd.GetResult() != ReceiveCommand.Result.NOT_ATTEMPTED)
1360
 
                                {
1361
 
                                        continue;
1362
 
                                }
1363
 
                                if (cmd.GetType() == ReceiveCommand.Type.DELETE && !IsAllowDeletes())
1364
 
                                {
1365
 
                                        // Deletes are not supported on this repository.
1366
 
                                        //
1367
 
                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_NODELETE);
1368
 
                                        continue;
1369
 
                                }
1370
 
                                if (cmd.GetType() == ReceiveCommand.Type.CREATE)
1371
 
                                {
1372
 
                                        if (!IsAllowCreates())
1373
 
                                        {
1374
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_NOCREATE);
1375
 
                                                continue;
1376
 
                                        }
1377
 
                                        if (@ref != null && !IsAllowNonFastForwards())
1378
 
                                        {
1379
 
                                                // Creation over an existing ref is certainly not going
1380
 
                                                // to be a fast-forward update. We can reject it early.
1381
 
                                                //
1382
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_NONFASTFORWARD);
1383
 
                                                continue;
1384
 
                                        }
1385
 
                                        if (@ref != null)
1386
 
                                        {
1387
 
                                                // A well behaved client shouldn't have sent us a
1388
 
                                                // create command for a ref we advertised to it.
1389
 
                                                //
1390
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, MessageFormat.Format(JGitText
1391
 
                                                        .Get().refAlreadyExists, @ref));
1392
 
                                                continue;
1393
 
                                        }
1394
 
                                }
1395
 
                                if (cmd.GetType() == ReceiveCommand.Type.DELETE && @ref != null && !ObjectId.ZeroId
1396
 
                                        .Equals(cmd.GetOldId()) && !@ref.GetObjectId().Equals(cmd.GetOldId()))
1397
 
                                {
1398
 
                                        // Delete commands can be sent with the old id matching our
1399
 
                                        // advertised value, *OR* with the old id being 0{40}. Any
1400
 
                                        // other requested old id is invalid.
1401
 
                                        //
1402
 
                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, JGitText.Get().invalidOldIdSent
1403
 
                                                );
1404
 
                                        continue;
1405
 
                                }
1406
 
                                if (cmd.GetType() == ReceiveCommand.Type.UPDATE)
1407
 
                                {
1408
 
                                        if (@ref == null)
1409
 
                                        {
1410
 
                                                // The ref must have been advertised in order to be updated.
1411
 
                                                //
1412
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, JGitText.Get().noSuchRef
1413
 
                                                        );
1414
 
                                                continue;
1415
 
                                        }
1416
 
                                        if (!@ref.GetObjectId().Equals(cmd.GetOldId()))
1417
 
                                        {
1418
 
                                                // A properly functioning client will send the same
1419
 
                                                // object id we advertised.
1420
 
                                                //
1421
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, JGitText.Get().invalidOldIdSent
1422
 
                                                        );
1423
 
                                                continue;
1424
 
                                        }
1425
 
                                        // Is this possibly a non-fast-forward style update?
1426
 
                                        //
1427
 
                                        RevObject oldObj;
1428
 
                                        RevObject newObj;
1429
 
                                        try
1430
 
                                        {
1431
 
                                                oldObj = walk.ParseAny(cmd.GetOldId());
1432
 
                                        }
1433
 
                                        catch (IOException)
1434
 
                                        {
1435
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_MISSING_OBJECT, cmd.GetOldId().Name);
1436
 
                                                continue;
1437
 
                                        }
1438
 
                                        try
1439
 
                                        {
1440
 
                                                newObj = walk.ParseAny(cmd.GetNewId());
1441
 
                                        }
1442
 
                                        catch (IOException)
1443
 
                                        {
1444
 
                                                cmd.SetResult(ReceiveCommand.Result.REJECTED_MISSING_OBJECT, cmd.GetNewId().Name);
1445
 
                                                continue;
1446
 
                                        }
1447
 
                                        if (oldObj is RevCommit && newObj is RevCommit)
1448
 
                                        {
1449
 
                                                try
1450
 
                                                {
1451
 
                                                        if (!walk.IsMergedInto((RevCommit)oldObj, (RevCommit)newObj))
1452
 
                                                        {
1453
 
                                                                cmd.SetType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1454
 
                                                        }
1455
 
                                                }
1456
 
                                                catch (MissingObjectException e)
1457
 
                                                {
1458
 
                                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_MISSING_OBJECT, e.Message);
1459
 
                                                }
1460
 
                                                catch (IOException)
1461
 
                                                {
1462
 
                                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON);
1463
 
                                                }
1464
 
                                        }
1465
 
                                        else
1466
 
                                        {
1467
 
                                                cmd.SetType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1468
 
                                        }
1469
 
                                }
1470
 
                                if (!cmd.GetRefName().StartsWith(Constants.R_REFS) || !Repository.IsValidRefName(
1471
 
                                        cmd.GetRefName()))
1472
 
                                {
1473
 
                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, JGitText.Get().funnyRefname
1474
 
                                                );
1475
 
                                }
1476
 
                        }
1477
 
                }
1478
 
 
1479
 
                private void ExecuteCommands()
1480
 
                {
1481
 
                        preReceive.OnPreReceive(this, ReceiveCommand.Filter(commands, ReceiveCommand.Result
1482
 
                                .NOT_ATTEMPTED));
1483
 
                        IList<ReceiveCommand> toApply = ReceiveCommand.Filter(commands, ReceiveCommand.Result
1484
 
                                .NOT_ATTEMPTED);
1485
 
                        ProgressMonitor updating = NullProgressMonitor.INSTANCE;
1486
 
                        if (sideBand)
1487
 
                        {
1488
 
                                SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
1489
 
                                pm.SetDelayStart(250, TimeUnit.MILLISECONDS);
1490
 
                                updating = pm;
1491
 
                        }
1492
 
                        updating.BeginTask(JGitText.Get().updatingReferences, toApply.Count);
1493
 
                        foreach (ReceiveCommand cmd in toApply)
1494
 
                        {
1495
 
                                updating.Update(1);
1496
 
                                cmd.Execute(this);
1497
 
                        }
1498
 
                        updating.EndTask();
1499
 
                }
1500
 
 
1501
 
                /// <exception cref="System.IO.IOException"></exception>
1502
 
                private void SendStatusReport(bool forClient, ReceivePack.Reporter @out)
1503
 
                {
1504
 
                        if (unpackError != null)
1505
 
                        {
1506
 
                                @out.SendString("unpack error " + unpackError.Message);
1507
 
                                if (forClient)
1508
 
                                {
1509
 
                                        foreach (ReceiveCommand cmd in commands)
1510
 
                                        {
1511
 
                                                @out.SendString("ng " + cmd.GetRefName() + " n/a (unpacker error)");
1512
 
                                        }
1513
 
                                }
1514
 
                                return;
1515
 
                        }
1516
 
                        if (forClient)
1517
 
                        {
1518
 
                                @out.SendString("unpack ok");
1519
 
                        }
1520
 
                        foreach (ReceiveCommand cmd_1 in commands)
1521
 
                        {
1522
 
                                if (cmd_1.GetResult() == ReceiveCommand.Result.OK)
1523
 
                                {
1524
 
                                        if (forClient)
1525
 
                                        {
1526
 
                                                @out.SendString("ok " + cmd_1.GetRefName());
1527
 
                                        }
1528
 
                                        continue;
1529
 
                                }
1530
 
                                StringBuilder r = new StringBuilder();
1531
 
                                r.Append("ng ");
1532
 
                                r.Append(cmd_1.GetRefName());
1533
 
                                r.Append(" ");
1534
 
                                switch (cmd_1.GetResult())
1535
 
                                {
1536
 
                                        case ReceiveCommand.Result.NOT_ATTEMPTED:
1537
 
                                        {
1538
 
                                                r.Append("server bug; ref not processed");
1539
 
                                                break;
1540
 
                                        }
1541
 
 
1542
 
                                        case ReceiveCommand.Result.REJECTED_NOCREATE:
1543
 
                                        {
1544
 
                                                r.Append("creation prohibited");
1545
 
                                                break;
1546
 
                                        }
1547
 
 
1548
 
                                        case ReceiveCommand.Result.REJECTED_NODELETE:
1549
 
                                        {
1550
 
                                                r.Append("deletion prohibited");
1551
 
                                                break;
1552
 
                                        }
1553
 
 
1554
 
                                        case ReceiveCommand.Result.REJECTED_NONFASTFORWARD:
1555
 
                                        {
1556
 
                                                r.Append("non-fast forward");
1557
 
                                                break;
1558
 
                                        }
1559
 
 
1560
 
                                        case ReceiveCommand.Result.REJECTED_CURRENT_BRANCH:
1561
 
                                        {
1562
 
                                                r.Append("branch is currently checked out");
1563
 
                                                break;
1564
 
                                        }
1565
 
 
1566
 
                                        case ReceiveCommand.Result.REJECTED_MISSING_OBJECT:
1567
 
                                        {
1568
 
                                                if (cmd_1.GetMessage() == null)
1569
 
                                                {
1570
 
                                                        r.Append("missing object(s)");
1571
 
                                                }
1572
 
                                                else
1573
 
                                                {
1574
 
                                                        if (cmd_1.GetMessage().Length == Constants.OBJECT_ID_STRING_LENGTH)
1575
 
                                                        {
1576
 
                                                                r.Append("object " + cmd_1.GetMessage() + " missing");
1577
 
                                                        }
1578
 
                                                        else
1579
 
                                                        {
1580
 
                                                                r.Append(cmd_1.GetMessage());
1581
 
                                                        }
1582
 
                                                }
1583
 
                                                break;
1584
 
                                        }
1585
 
 
1586
 
                                        case ReceiveCommand.Result.REJECTED_OTHER_REASON:
1587
 
                                        {
1588
 
                                                if (cmd_1.GetMessage() == null)
1589
 
                                                {
1590
 
                                                        r.Append("unspecified reason");
1591
 
                                                }
1592
 
                                                else
1593
 
                                                {
1594
 
                                                        r.Append(cmd_1.GetMessage());
1595
 
                                                }
1596
 
                                                break;
1597
 
                                        }
1598
 
 
1599
 
                                        case ReceiveCommand.Result.LOCK_FAILURE:
1600
 
                                        {
1601
 
                                                r.Append("failed to lock");
1602
 
                                                break;
1603
 
                                        }
1604
 
 
1605
 
                                        case ReceiveCommand.Result.OK:
1606
 
                                        {
1607
 
                                                // We shouldn't have reached this case (see 'ok' case above).
1608
 
                                                continue;
1609
 
                                        }
1610
 
                                }
1611
 
                                @out.SendString(r.ToString());
1612
 
                        }
1613
 
                }
1614
 
 
1615
 
                internal abstract class Reporter
1616
 
                {
1617
 
                        /// <exception cref="System.IO.IOException"></exception>
1618
 
                        internal abstract void SendString(string s);
 
318
                protected internal override string GetLockMessageProcessName()
 
319
                {
 
320
                        return "jgit receive-pack";
1619
321
                }
1620
322
        }
1621
323
}