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

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Transport/RemoteRefUpdate.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;
 
45
using System.IO;
 
46
using NGit;
 
47
using NGit.Revwalk;
 
48
using NGit.Transport;
 
49
using Sharpen;
 
50
 
 
51
namespace NGit.Transport
 
52
{
 
53
        /// <summary>Represent request and status of a remote ref update.</summary>
 
54
        /// <remarks>
 
55
        /// Represent request and status of a remote ref update. Specification is
 
56
        /// provided by client, while status is handled by
 
57
        /// <see cref="PushProcess">PushProcess</see>
 
58
        /// class,
 
59
        /// being read-only for client.
 
60
        /// <p>
 
61
        /// Client can create instances of this class directly, basing on user
 
62
        /// specification and advertised refs (
 
63
        /// <see cref="Connection">Connection</see>
 
64
        /// or through
 
65
        /// <see cref="Transport">Transport</see>
 
66
        /// helper methods. Apply this specification on remote
 
67
        /// repository using
 
68
        /// <see cref="Transport.Push(NGit.ProgressMonitor, System.Collections.Generic.ICollection{E})
 
69
        ///     ">Transport.Push(NGit.ProgressMonitor, System.Collections.Generic.ICollection&lt;E&gt;)
 
70
        ///     </see>
 
71
        /// method.
 
72
        /// </p>
 
73
        /// </remarks>
 
74
        public class RemoteRefUpdate
 
75
        {
 
76
                /// <summary>Represent current status of a remote ref update.</summary>
 
77
                /// <remarks>Represent current status of a remote ref update.</remarks>
 
78
                public enum Status
 
79
                {
 
80
                        NOT_ATTEMPTED,
 
81
                        UP_TO_DATE,
 
82
                        REJECTED_NONFASTFORWARD,
 
83
                        REJECTED_NODELETE,
 
84
                        REJECTED_REMOTE_CHANGED,
 
85
                        REJECTED_OTHER_REASON,
 
86
                        NON_EXISTING,
 
87
                        AWAITING_REPORT,
 
88
                        OK
 
89
                }
 
90
 
 
91
                private readonly ObjectId expectedOldObjectId;
 
92
 
 
93
                private readonly ObjectId newObjectId;
 
94
 
 
95
                private readonly string remoteName;
 
96
 
 
97
                private readonly TrackingRefUpdate trackingRefUpdate;
 
98
 
 
99
                private readonly string srcRef;
 
100
 
 
101
                private readonly bool forceUpdate;
 
102
 
 
103
                private RemoteRefUpdate.Status status;
 
104
 
 
105
                private bool fastForward;
 
106
 
 
107
                private string message;
 
108
 
 
109
                private readonly Repository localDb;
 
110
 
 
111
                /// <summary>Construct remote ref update request by providing an update specification.
 
112
                ///     </summary>
 
113
                /// <remarks>
 
114
                /// Construct remote ref update request by providing an update specification.
 
115
                /// Object is created with default
 
116
                /// <see cref="Status.NOT_ATTEMPTED">Status.NOT_ATTEMPTED</see>
 
117
                /// status and no
 
118
                /// message.
 
119
                /// </remarks>
 
120
                /// <param name="localDb">local repository to push from.</param>
 
121
                /// <param name="srcRef">
 
122
                /// source revision - any string resolvable by
 
123
                /// <see cref="NGit.Repository.Resolve(string)">NGit.Repository.Resolve(string)</see>
 
124
                /// . This resolves to the new
 
125
                /// object that the caller want remote ref to be after update. Use
 
126
                /// null or
 
127
                /// <see cref="NGit.ObjectId.ZeroId()">NGit.ObjectId.ZeroId()</see>
 
128
                /// string for delete request.
 
129
                /// </param>
 
130
                /// <param name="remoteName">
 
131
                /// full name of a remote ref to update, e.g. "refs/heads/master"
 
132
                /// (no wildcard, no short name).
 
133
                /// </param>
 
134
                /// <param name="forceUpdate">
 
135
                /// true when caller want remote ref to be updated regardless
 
136
                /// whether it is fast-forward update (old object is ancestor of
 
137
                /// new object).
 
138
                /// </param>
 
139
                /// <param name="localName">
 
140
                /// optional full name of a local stored tracking branch, to
 
141
                /// update after push, e.g. "refs/remotes/zawir/dirty" (no
 
142
                /// wildcard, no short name); null if no local tracking branch
 
143
                /// should be updated.
 
144
                /// </param>
 
145
                /// <param name="expectedOldObjectId">
 
146
                /// optional object id that caller is expecting, requiring to be
 
147
                /// advertised by remote side before update; update will take
 
148
                /// place ONLY if remote side advertise exactly this expected id;
 
149
                /// null if caller doesn't care what object id remote side
 
150
                /// advertise. Use
 
151
                /// <see cref="NGit.ObjectId.ZeroId()">NGit.ObjectId.ZeroId()</see>
 
152
                /// when expecting no
 
153
                /// remote ref with this name.
 
154
                /// </param>
 
155
                /// <exception cref="System.IO.IOException">
 
156
                /// when I/O error occurred during creating
 
157
                /// <see cref="TrackingRefUpdate">TrackingRefUpdate</see>
 
158
                /// for local tracking branch or srcRef
 
159
                /// can't be resolved to any object.
 
160
                /// </exception>
 
161
                /// <exception cref="System.ArgumentException">if some required parameter was null</exception>
 
162
                public RemoteRefUpdate(Repository localDb, string srcRef, string remoteName, bool
 
163
                         forceUpdate, string localName, ObjectId expectedOldObjectId) : this(localDb, srcRef
 
164
                        , srcRef != null ? localDb.Resolve(srcRef) : ObjectId.ZeroId, remoteName, forceUpdate
 
165
                        , localName, expectedOldObjectId)
 
166
                {
 
167
                }
 
168
 
 
169
                /// <summary>Construct remote ref update request by providing an update specification.
 
170
                ///     </summary>
 
171
                /// <remarks>
 
172
                /// Construct remote ref update request by providing an update specification.
 
173
                /// Object is created with default
 
174
                /// <see cref="Status.NOT_ATTEMPTED">Status.NOT_ATTEMPTED</see>
 
175
                /// status and no
 
176
                /// message.
 
177
                /// </remarks>
 
178
                /// <param name="localDb">local repository to push from.</param>
 
179
                /// <param name="srcRef">source revision. Use null to delete.</param>
 
180
                /// <param name="remoteName">
 
181
                /// full name of a remote ref to update, e.g. "refs/heads/master"
 
182
                /// (no wildcard, no short name).
 
183
                /// </param>
 
184
                /// <param name="forceUpdate">
 
185
                /// true when caller want remote ref to be updated regardless
 
186
                /// whether it is fast-forward update (old object is ancestor of
 
187
                /// new object).
 
188
                /// </param>
 
189
                /// <param name="localName">
 
190
                /// optional full name of a local stored tracking branch, to
 
191
                /// update after push, e.g. "refs/remotes/zawir/dirty" (no
 
192
                /// wildcard, no short name); null if no local tracking branch
 
193
                /// should be updated.
 
194
                /// </param>
 
195
                /// <param name="expectedOldObjectId">
 
196
                /// optional object id that caller is expecting, requiring to be
 
197
                /// advertised by remote side before update; update will take
 
198
                /// place ONLY if remote side advertise exactly this expected id;
 
199
                /// null if caller doesn't care what object id remote side
 
200
                /// advertise. Use
 
201
                /// <see cref="NGit.ObjectId.ZeroId()">NGit.ObjectId.ZeroId()</see>
 
202
                /// when expecting no
 
203
                /// remote ref with this name.
 
204
                /// </param>
 
205
                /// <exception cref="System.IO.IOException">
 
206
                /// when I/O error occurred during creating
 
207
                /// <see cref="TrackingRefUpdate">TrackingRefUpdate</see>
 
208
                /// for local tracking branch or srcRef
 
209
                /// can't be resolved to any object.
 
210
                /// </exception>
 
211
                /// <exception cref="System.ArgumentException">if some required parameter was null</exception>
 
212
                public RemoteRefUpdate(Repository localDb, Ref srcRef, string remoteName, bool forceUpdate
 
213
                        , string localName, ObjectId expectedOldObjectId) : this(localDb, srcRef != null
 
214
                         ? srcRef.GetName() : null, srcRef != null ? srcRef.GetObjectId() : null, remoteName
 
215
                        , forceUpdate, localName, expectedOldObjectId)
 
216
                {
 
217
                }
 
218
 
 
219
                /// <summary>Construct remote ref update request by providing an update specification.
 
220
                ///     </summary>
 
221
                /// <remarks>
 
222
                /// Construct remote ref update request by providing an update specification.
 
223
                /// Object is created with default
 
224
                /// <see cref="Status.NOT_ATTEMPTED">Status.NOT_ATTEMPTED</see>
 
225
                /// status and no
 
226
                /// message.
 
227
                /// </remarks>
 
228
                /// <param name="localDb">local repository to push from.</param>
 
229
                /// <param name="srcRef">
 
230
                /// source revision to label srcId with. If null srcId.name() will
 
231
                /// be used instead.
 
232
                /// </param>
 
233
                /// <param name="srcId">
 
234
                /// The new object that the caller wants remote ref to be after
 
235
                /// update. Use null or
 
236
                /// <see cref="NGit.ObjectId.ZeroId()">NGit.ObjectId.ZeroId()</see>
 
237
                /// for delete
 
238
                /// request.
 
239
                /// </param>
 
240
                /// <param name="remoteName">
 
241
                /// full name of a remote ref to update, e.g. "refs/heads/master"
 
242
                /// (no wildcard, no short name).
 
243
                /// </param>
 
244
                /// <param name="forceUpdate">
 
245
                /// true when caller want remote ref to be updated regardless
 
246
                /// whether it is fast-forward update (old object is ancestor of
 
247
                /// new object).
 
248
                /// </param>
 
249
                /// <param name="localName">
 
250
                /// optional full name of a local stored tracking branch, to
 
251
                /// update after push, e.g. "refs/remotes/zawir/dirty" (no
 
252
                /// wildcard, no short name); null if no local tracking branch
 
253
                /// should be updated.
 
254
                /// </param>
 
255
                /// <param name="expectedOldObjectId">
 
256
                /// optional object id that caller is expecting, requiring to be
 
257
                /// advertised by remote side before update; update will take
 
258
                /// place ONLY if remote side advertise exactly this expected id;
 
259
                /// null if caller doesn't care what object id remote side
 
260
                /// advertise. Use
 
261
                /// <see cref="NGit.ObjectId.ZeroId()">NGit.ObjectId.ZeroId()</see>
 
262
                /// when expecting no
 
263
                /// remote ref with this name.
 
264
                /// </param>
 
265
                /// <exception cref="System.IO.IOException">
 
266
                /// when I/O error occurred during creating
 
267
                /// <see cref="TrackingRefUpdate">TrackingRefUpdate</see>
 
268
                /// for local tracking branch or srcRef
 
269
                /// can't be resolved to any object.
 
270
                /// </exception>
 
271
                /// <exception cref="System.ArgumentException">if some required parameter was null</exception>
 
272
                public RemoteRefUpdate(Repository localDb, string srcRef, ObjectId srcId, string 
 
273
                        remoteName, bool forceUpdate, string localName, ObjectId expectedOldObjectId)
 
274
                {
 
275
                        if (remoteName == null)
 
276
                        {
 
277
                                throw new ArgumentException(JGitText.Get().remoteNameCantBeNull);
 
278
                        }
 
279
                        if (srcId == null && srcRef != null)
 
280
                        {
 
281
                                throw new IOException(MessageFormat.Format(JGitText.Get().sourceRefDoesntResolveToAnyObject
 
282
                                        , srcRef));
 
283
                        }
 
284
                        if (srcRef != null)
 
285
                        {
 
286
                                this.srcRef = srcRef;
 
287
                        }
 
288
                        else
 
289
                        {
 
290
                                if (srcId != null && !srcId.Equals(ObjectId.ZeroId))
 
291
                                {
 
292
                                        this.srcRef = srcId.Name;
 
293
                                }
 
294
                                else
 
295
                                {
 
296
                                        this.srcRef = null;
 
297
                                }
 
298
                        }
 
299
                        if (srcId != null)
 
300
                        {
 
301
                                this.newObjectId = srcId;
 
302
                        }
 
303
                        else
 
304
                        {
 
305
                                this.newObjectId = ObjectId.ZeroId;
 
306
                        }
 
307
                        this.remoteName = remoteName;
 
308
                        this.forceUpdate = forceUpdate;
 
309
                        if (localName != null && localDb != null)
 
310
                        {
 
311
                                trackingRefUpdate = new TrackingRefUpdate(localDb, localName, remoteName, true, newObjectId
 
312
                                        , "push");
 
313
                        }
 
314
                        else
 
315
                        {
 
316
                                trackingRefUpdate = null;
 
317
                        }
 
318
                        this.localDb = localDb;
 
319
                        this.expectedOldObjectId = expectedOldObjectId;
 
320
                        this.status = RemoteRefUpdate.Status.NOT_ATTEMPTED;
 
321
                }
 
322
 
 
323
                /// <summary>
 
324
                /// Create a new instance of this object basing on existing instance for
 
325
                /// configuration.
 
326
                /// </summary>
 
327
                /// <remarks>
 
328
                /// Create a new instance of this object basing on existing instance for
 
329
                /// configuration. State (like
 
330
                /// <see cref="GetMessage()">GetMessage()</see>
 
331
                /// ,
 
332
                /// <see cref="GetStatus()">GetStatus()</see>
 
333
                /// )
 
334
                /// of base object is not shared. Expected old object id is set up from
 
335
                /// scratch, as this constructor may be used for 2-stage push: first one
 
336
                /// being dry run, second one being actual push.
 
337
                /// </remarks>
 
338
                /// <param name="base">configuration base.</param>
 
339
                /// <param name="newExpectedOldObjectId">new expected object id value.</param>
 
340
                /// <exception cref="System.IO.IOException">
 
341
                /// when I/O error occurred during creating
 
342
                /// <see cref="TrackingRefUpdate">TrackingRefUpdate</see>
 
343
                /// for local tracking branch or srcRef
 
344
                /// of base object no longer can be resolved to any object.
 
345
                /// </exception>
 
346
                public RemoteRefUpdate(NGit.Transport.RemoteRefUpdate @base, ObjectId newExpectedOldObjectId
 
347
                        ) : this(@base.localDb, @base.srcRef, @base.remoteName, @base.forceUpdate, (@base
 
348
                        .trackingRefUpdate == null ? null : @base.trackingRefUpdate.GetLocalName()), newExpectedOldObjectId
 
349
                        )
 
350
                {
 
351
                }
 
352
 
 
353
                /// <returns>
 
354
                /// expectedOldObjectId required to be advertised by remote side, as
 
355
                /// set in constructor; may be null.
 
356
                /// </returns>
 
357
                public virtual ObjectId GetExpectedOldObjectId()
 
358
                {
 
359
                        return expectedOldObjectId;
 
360
                }
 
361
 
 
362
                /// <returns>
 
363
                /// true if some object is required to be advertised by remote side,
 
364
                /// as set in constructor; false otherwise.
 
365
                /// </returns>
 
366
                public virtual bool IsExpectingOldObjectId()
 
367
                {
 
368
                        return expectedOldObjectId != null;
 
369
                }
 
370
 
 
371
                /// <returns>newObjectId for remote ref, as set in constructor.</returns>
 
372
                public virtual ObjectId GetNewObjectId()
 
373
                {
 
374
                        return newObjectId;
 
375
                }
 
376
 
 
377
                /// <returns>true if this update is deleting update; false otherwise.</returns>
 
378
                public virtual bool IsDelete()
 
379
                {
 
380
                        return ObjectId.ZeroId.Equals(newObjectId);
 
381
                }
 
382
 
 
383
                /// <returns>name of remote ref to update, as set in constructor.</returns>
 
384
                public virtual string GetRemoteName()
 
385
                {
 
386
                        return remoteName;
 
387
                }
 
388
 
 
389
                /// <returns>local tracking branch update if localName was set in constructor.</returns>
 
390
                public virtual TrackingRefUpdate GetTrackingRefUpdate()
 
391
                {
 
392
                        return trackingRefUpdate;
 
393
                }
 
394
 
 
395
                /// <returns>
 
396
                /// source revision as specified by user (in constructor), could be
 
397
                /// any string parseable by
 
398
                /// <see cref="NGit.Repository.Resolve(string)">NGit.Repository.Resolve(string)</see>
 
399
                /// ; can
 
400
                /// be null if specified that way in constructor - this stands for
 
401
                /// delete request.
 
402
                /// </returns>
 
403
                public virtual string GetSrcRef()
 
404
                {
 
405
                        return srcRef;
 
406
                }
 
407
 
 
408
                /// <returns>
 
409
                /// true if user specified a local tracking branch for remote update;
 
410
                /// false otherwise.
 
411
                /// </returns>
 
412
                public virtual bool HasTrackingRefUpdate()
 
413
                {
 
414
                        return trackingRefUpdate != null;
 
415
                }
 
416
 
 
417
                /// <returns>
 
418
                /// true if this update is forced regardless of old remote ref
 
419
                /// object; false otherwise.
 
420
                /// </returns>
 
421
                public virtual bool IsForceUpdate()
 
422
                {
 
423
                        return forceUpdate;
 
424
                }
 
425
 
 
426
                /// <returns>status of remote ref update operation.</returns>
 
427
                public virtual RemoteRefUpdate.Status GetStatus()
 
428
                {
 
429
                        return status;
 
430
                }
 
431
 
 
432
                /// <summary>Check whether update was fast-forward.</summary>
 
433
                /// <remarks>
 
434
                /// Check whether update was fast-forward. Note that this result is
 
435
                /// meaningful only after successful update (when status is
 
436
                /// <see cref="Status.OK">Status.OK</see>
 
437
                /// ).
 
438
                /// </remarks>
 
439
                /// <returns>true if update was fast-forward; false otherwise.</returns>
 
440
                public virtual bool IsFastForward()
 
441
                {
 
442
                        return fastForward;
 
443
                }
 
444
 
 
445
                /// <returns>
 
446
                /// message describing reasons of status when needed/possible; may be
 
447
                /// null.
 
448
                /// </returns>
 
449
                public virtual string GetMessage()
 
450
                {
 
451
                        return message;
 
452
                }
 
453
 
 
454
                internal virtual void SetStatus(RemoteRefUpdate.Status status)
 
455
                {
 
456
                        this.status = status;
 
457
                }
 
458
 
 
459
                internal virtual void SetFastForward(bool fastForward)
 
460
                {
 
461
                        this.fastForward = fastForward;
 
462
                }
 
463
 
 
464
                internal virtual void SetMessage(string message)
 
465
                {
 
466
                        this.message = message;
 
467
                }
 
468
 
 
469
                /// <summary>Update locally stored tracking branch with the new object.</summary>
 
470
                /// <remarks>Update locally stored tracking branch with the new object.</remarks>
 
471
                /// <param name="walk">walker used for checking update properties.</param>
 
472
                /// <exception cref="System.IO.IOException">when I/O error occurred during update</exception>
 
473
                protected internal virtual void UpdateTrackingRef(RevWalk walk)
 
474
                {
 
475
                        if (IsDelete())
 
476
                        {
 
477
                                trackingRefUpdate.Delete(walk);
 
478
                        }
 
479
                        else
 
480
                        {
 
481
                                trackingRefUpdate.Update(walk);
 
482
                        }
 
483
                }
 
484
 
 
485
                public override string ToString()
 
486
                {
 
487
                        return "RemoteRefUpdate[remoteName=" + remoteName + ", " + status + ", " + (expectedOldObjectId
 
488
                                 != null ? expectedOldObjectId.Name : "(null)") + "..." + (newObjectId != null ? 
 
489
                                newObjectId.Name : "(null)") + (fastForward ? ", fastForward" : string.Empty) + 
 
490
                                ", srcRef=" + srcRef + (forceUpdate ? ", forceUpdate" : string.Empty) + ", message="
 
491
                                 + (message != null ? "\"" + message + "\"" : "null") + "]";
 
492
                }
 
493
        }
 
494
}