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

« back to all changes in this revision

Viewing changes to external/ngit/NGit/NGit/BatchRefUpdate.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:
 
1
/*
 
2
This code is derived from jgit (http://eclipse.org/jgit).
 
3
Copyright owners are documented in jgit's IP log.
 
4
 
 
5
This program and the accompanying materials are made available
 
6
under the terms of the Eclipse Distribution License v1.0 which
 
7
accompanies this distribution, is reproduced below, and is
 
8
available at http://www.eclipse.org/org/documents/edl-v10.php
 
9
 
 
10
All rights reserved.
 
11
 
 
12
Redistribution and use in source and binary forms, with or
 
13
without modification, are permitted provided that the following
 
14
conditions are met:
 
15
 
 
16
- Redistributions of source code must retain the above copyright
 
17
  notice, this list of conditions and the following disclaimer.
 
18
 
 
19
- Redistributions in binary form must reproduce the above
 
20
  copyright notice, this list of conditions and the following
 
21
  disclaimer in the documentation and/or other materials provided
 
22
  with the distribution.
 
23
 
 
24
- Neither the name of the Eclipse Foundation, Inc. nor the
 
25
  names of its contributors may be used to endorse or promote
 
26
  products derived from this software without specific prior
 
27
  written permission.
 
28
 
 
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
42
*/
 
43
 
 
44
using System.Collections.Generic;
 
45
using System.IO;
 
46
using NGit;
 
47
using NGit.Internal;
 
48
using NGit.Revwalk;
 
49
using NGit.Transport;
 
50
using Sharpen;
 
51
 
 
52
namespace NGit
 
53
{
 
54
        /// <summary>Batch of reference updates to be applied to a repository.</summary>
 
55
        /// <remarks>
 
56
        /// Batch of reference updates to be applied to a repository.
 
57
        /// <p>
 
58
        /// The batch update is primarily useful in the transport code, where a client or
 
59
        /// server is making changes to more than one reference at a time.
 
60
        /// </remarks>
 
61
        public class BatchRefUpdate
 
62
        {
 
63
                private readonly RefDatabase refdb;
 
64
 
 
65
                /// <summary>Commands to apply during this batch.</summary>
 
66
                /// <remarks>Commands to apply during this batch.</remarks>
 
67
                private readonly IList<ReceiveCommand> commands;
 
68
 
 
69
                /// <summary>Does the caller permit a forced update on a reference?</summary>
 
70
                private bool allowNonFastForwards;
 
71
 
 
72
                /// <summary>Identity to record action as within the reflog.</summary>
 
73
                /// <remarks>Identity to record action as within the reflog.</remarks>
 
74
                private PersonIdent refLogIdent;
 
75
 
 
76
                /// <summary>Message the caller wants included in the reflog.</summary>
 
77
                /// <remarks>Message the caller wants included in the reflog.</remarks>
 
78
                private string refLogMessage;
 
79
 
 
80
                /// <summary>
 
81
                /// Should the result value be appended to
 
82
                /// <see cref="refLogMessage">refLogMessage</see>
 
83
                /// .
 
84
                /// </summary>
 
85
                private bool refLogIncludeResult;
 
86
 
 
87
                /// <summary>Initialize a new batch update.</summary>
 
88
                /// <remarks>Initialize a new batch update.</remarks>
 
89
                /// <param name="refdb">the reference database of the repository to be updated.</param>
 
90
                protected internal BatchRefUpdate(RefDatabase refdb)
 
91
                {
 
92
                        this.refdb = refdb;
 
93
                        this.commands = new AList<ReceiveCommand>();
 
94
                }
 
95
 
 
96
                /// <returns>
 
97
                /// true if the batch update will permit a non-fast-forward update to
 
98
                /// an existing reference.
 
99
                /// </returns>
 
100
                public virtual bool IsAllowNonFastForwards()
 
101
                {
 
102
                        return allowNonFastForwards;
 
103
                }
 
104
 
 
105
                /// <summary>Set if this update wants to permit a forced update.</summary>
 
106
                /// <remarks>Set if this update wants to permit a forced update.</remarks>
 
107
                /// <param name="allow">true if this update batch should ignore merge tests.</param>
 
108
                /// <returns>
 
109
                /// 
 
110
                /// <code>this</code>
 
111
                /// .
 
112
                /// </returns>
 
113
                public virtual NGit.BatchRefUpdate SetAllowNonFastForwards(bool allow)
 
114
                {
 
115
                        allowNonFastForwards = allow;
 
116
                        return this;
 
117
                }
 
118
 
 
119
                /// <returns>identity of the user making the change in the reflog.</returns>
 
120
                public virtual PersonIdent GetRefLogIdent()
 
121
                {
 
122
                        return refLogIdent;
 
123
                }
 
124
 
 
125
                /// <summary>Set the identity of the user appearing in the reflog.</summary>
 
126
                /// <remarks>
 
127
                /// Set the identity of the user appearing in the reflog.
 
128
                /// <p>
 
129
                /// The timestamp portion of the identity is ignored. A new identity with the
 
130
                /// current timestamp will be created automatically when the update occurs
 
131
                /// and the log record is written.
 
132
                /// </remarks>
 
133
                /// <param name="pi">
 
134
                /// identity of the user. If null the identity will be
 
135
                /// automatically determined based on the repository
 
136
                /// configuration.
 
137
                /// </param>
 
138
                /// <returns>
 
139
                /// 
 
140
                /// <code>this</code>
 
141
                /// .
 
142
                /// </returns>
 
143
                public virtual NGit.BatchRefUpdate SetRefLogIdent(PersonIdent pi)
 
144
                {
 
145
                        refLogIdent = pi;
 
146
                        return this;
 
147
                }
 
148
 
 
149
                /// <summary>Get the message to include in the reflog.</summary>
 
150
                /// <remarks>Get the message to include in the reflog.</remarks>
 
151
                /// <returns>
 
152
                /// message the caller wants to include in the reflog; null if the
 
153
                /// update should not be logged.
 
154
                /// </returns>
 
155
                public virtual string GetRefLogMessage()
 
156
                {
 
157
                        return refLogMessage;
 
158
                }
 
159
 
 
160
                /// <returns>
 
161
                /// 
 
162
                /// <code>true</code>
 
163
                /// if the ref log message should show the result.
 
164
                /// </returns>
 
165
                public virtual bool IsRefLogIncludingResult()
 
166
                {
 
167
                        return refLogIncludeResult;
 
168
                }
 
169
 
 
170
                /// <summary>Set the message to include in the reflog.</summary>
 
171
                /// <remarks>Set the message to include in the reflog.</remarks>
 
172
                /// <param name="msg">
 
173
                /// the message to describe this change. It may be null if
 
174
                /// appendStatus is null in order not to append to the reflog
 
175
                /// </param>
 
176
                /// <param name="appendStatus">
 
177
                /// true if the status of the ref change (fast-forward or
 
178
                /// forced-update) should be appended to the user supplied
 
179
                /// message.
 
180
                /// </param>
 
181
                /// <returns>
 
182
                /// 
 
183
                /// <code>this</code>
 
184
                /// .
 
185
                /// </returns>
 
186
                public virtual NGit.BatchRefUpdate SetRefLogMessage(string msg, bool appendStatus
 
187
                        )
 
188
                {
 
189
                        if (msg == null && !appendStatus)
 
190
                        {
 
191
                                DisableRefLog();
 
192
                        }
 
193
                        else
 
194
                        {
 
195
                                if (msg == null && appendStatus)
 
196
                                {
 
197
                                        refLogMessage = string.Empty;
 
198
                                        refLogIncludeResult = true;
 
199
                                }
 
200
                                else
 
201
                                {
 
202
                                        refLogMessage = msg;
 
203
                                        refLogIncludeResult = appendStatus;
 
204
                                }
 
205
                        }
 
206
                        return this;
 
207
                }
 
208
 
 
209
                /// <summary>Don't record this update in the ref's associated reflog.</summary>
 
210
                /// <remarks>Don't record this update in the ref's associated reflog.</remarks>
 
211
                /// <returns>
 
212
                /// 
 
213
                /// <code>this</code>
 
214
                /// .
 
215
                /// </returns>
 
216
                public virtual NGit.BatchRefUpdate DisableRefLog()
 
217
                {
 
218
                        refLogMessage = null;
 
219
                        refLogIncludeResult = false;
 
220
                        return this;
 
221
                }
 
222
 
 
223
                /// <returns>
 
224
                /// true if log has been disabled by
 
225
                /// <see cref="DisableRefLog()">DisableRefLog()</see>
 
226
                /// .
 
227
                /// </returns>
 
228
                public virtual bool IsRefLogDisabled()
 
229
                {
 
230
                        return refLogMessage == null;
 
231
                }
 
232
 
 
233
                /// <returns>commands this update will process.</returns>
 
234
                public virtual IList<ReceiveCommand> GetCommands()
 
235
                {
 
236
                        return Sharpen.Collections.UnmodifiableList(commands);
 
237
                }
 
238
 
 
239
                /// <summary>Add a single command to this batch update.</summary>
 
240
                /// <remarks>Add a single command to this batch update.</remarks>
 
241
                /// <param name="cmd">the command to add, must not be null.</param>
 
242
                /// <returns>
 
243
                /// 
 
244
                /// <code>this</code>
 
245
                /// .
 
246
                /// </returns>
 
247
                public virtual NGit.BatchRefUpdate AddCommand(ReceiveCommand cmd)
 
248
                {
 
249
                        commands.AddItem(cmd);
 
250
                        return this;
 
251
                }
 
252
 
 
253
                /// <summary>Add commands to this batch update.</summary>
 
254
                /// <remarks>Add commands to this batch update.</remarks>
 
255
                /// <param name="cmd">the commands to add, must not be null.</param>
 
256
                /// <returns>
 
257
                /// 
 
258
                /// <code>this</code>
 
259
                /// .
 
260
                /// </returns>
 
261
                public virtual NGit.BatchRefUpdate AddCommand(params ReceiveCommand[] cmd)
 
262
                {
 
263
                        return AddCommand(Arrays.AsList(cmd));
 
264
                }
 
265
 
 
266
                /// <summary>Add commands to this batch update.</summary>
 
267
                /// <remarks>Add commands to this batch update.</remarks>
 
268
                /// <param name="cmd">the commands to add, must not be null.</param>
 
269
                /// <returns>
 
270
                /// 
 
271
                /// <code>this</code>
 
272
                /// .
 
273
                /// </returns>
 
274
                public virtual NGit.BatchRefUpdate AddCommand(ICollection<ReceiveCommand> cmd)
 
275
                {
 
276
                        Sharpen.Collections.AddAll(commands, cmd);
 
277
                        return this;
 
278
                }
 
279
 
 
280
                /// <summary>Execute this batch update.</summary>
 
281
                /// <remarks>
 
282
                /// Execute this batch update.
 
283
                /// <p>
 
284
                /// The default implementation of this method performs a sequential reference
 
285
                /// update over each reference.
 
286
                /// </remarks>
 
287
                /// <param name="walk">
 
288
                /// a RevWalk to parse tags in case the storage system wants to
 
289
                /// store them pre-peeled, a common performance optimization.
 
290
                /// </param>
 
291
                /// <param name="update">progress monitor to receive update status on.</param>
 
292
                /// <exception cref="System.IO.IOException">
 
293
                /// the database is unable to accept the update. Individual
 
294
                /// command status must be tested to determine if there is a
 
295
                /// partial failure, or a total failure.
 
296
                /// </exception>
 
297
                public virtual void Execute(RevWalk walk, ProgressMonitor update)
 
298
                {
 
299
                        update.BeginTask(JGitText.Get().updatingReferences, commands.Count);
 
300
                        foreach (ReceiveCommand cmd in commands)
 
301
                        {
 
302
                                try
 
303
                                {
 
304
                                        update.Update(1);
 
305
                                        if (cmd.GetResult() == ReceiveCommand.Result.NOT_ATTEMPTED)
 
306
                                        {
 
307
                                                cmd.UpdateType(walk);
 
308
                                                RefUpdate ru = NewUpdate(cmd);
 
309
                                                switch (cmd.GetType())
 
310
                                                {
 
311
                                                        case ReceiveCommand.Type.DELETE:
 
312
                                                        {
 
313
                                                                cmd.SetResult(ru.Delete(walk));
 
314
                                                                continue;
 
315
                                                                goto case ReceiveCommand.Type.CREATE;
 
316
                                                        }
 
317
 
 
318
                                                        case ReceiveCommand.Type.CREATE:
 
319
                                                        case ReceiveCommand.Type.UPDATE:
 
320
                                                        case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
 
321
                                                        {
 
322
                                                                cmd.SetResult(ru.Update(walk));
 
323
                                                                continue;
 
324
                                                        }
 
325
                                                }
 
326
                                        }
 
327
                                }
 
328
                                catch (IOException err)
 
329
                                {
 
330
                                        cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, MessageFormat.Format(JGitText
 
331
                                                .Get().lockError, err.Message));
 
332
                                }
 
333
                        }
 
334
                        update.EndTask();
 
335
                }
 
336
 
 
337
                /// <summary>Create a new RefUpdate copying the batch settings.</summary>
 
338
                /// <remarks>Create a new RefUpdate copying the batch settings.</remarks>
 
339
                /// <param name="cmd">specific command the update should be created to copy.</param>
 
340
                /// <returns>a single reference update command.</returns>
 
341
                /// <exception cref="System.IO.IOException">
 
342
                /// the reference database cannot make a new update object for
 
343
                /// the given reference.
 
344
                /// </exception>
 
345
                protected internal virtual RefUpdate NewUpdate(ReceiveCommand cmd)
 
346
                {
 
347
                        RefUpdate ru = refdb.NewUpdate(cmd.GetRefName(), false);
 
348
                        if (IsRefLogDisabled())
 
349
                        {
 
350
                                ru.DisableRefLog();
 
351
                        }
 
352
                        else
 
353
                        {
 
354
                                ru.SetRefLogIdent(refLogIdent);
 
355
                                ru.SetRefLogMessage(refLogMessage, refLogIncludeResult);
 
356
                        }
 
357
                        switch (cmd.GetType())
 
358
                        {
 
359
                                case ReceiveCommand.Type.DELETE:
 
360
                                {
 
361
                                        if (!ObjectId.ZeroId.Equals(cmd.GetOldId()))
 
362
                                        {
 
363
                                                ru.SetExpectedOldObjectId(cmd.GetOldId());
 
364
                                        }
 
365
                                        ru.SetForceUpdate(true);
 
366
                                        return ru;
 
367
                                }
 
368
 
 
369
                                case ReceiveCommand.Type.CREATE:
 
370
                                case ReceiveCommand.Type.UPDATE:
 
371
                                case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
 
372
                                default:
 
373
                                {
 
374
                                        ru.SetForceUpdate(IsAllowNonFastForwards());
 
375
                                        ru.SetExpectedOldObjectId(cmd.GetOldId());
 
376
                                        ru.SetNewObjectId(cmd.GetNewId());
 
377
                                        return ru;
 
378
                                        break;
 
379
                                }
 
380
                        }
 
381
                }
 
382
        }
 
383
}