2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
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
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
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.
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
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.
44
using System.Collections.Generic;
54
/// <summary>Batch of reference updates to be applied to a repository.</summary>
56
/// Batch of reference updates to be applied to a repository.
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.
61
public class BatchRefUpdate
63
private readonly RefDatabase refdb;
65
/// <summary>Commands to apply during this batch.</summary>
66
/// <remarks>Commands to apply during this batch.</remarks>
67
private readonly IList<ReceiveCommand> commands;
69
/// <summary>Does the caller permit a forced update on a reference?</summary>
70
private bool allowNonFastForwards;
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;
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;
81
/// Should the result value be appended to
82
/// <see cref="refLogMessage">refLogMessage</see>
85
private bool refLogIncludeResult;
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)
93
this.commands = new AList<ReceiveCommand>();
97
/// true if the batch update will permit a non-fast-forward update to
98
/// an existing reference.
100
public virtual bool IsAllowNonFastForwards()
102
return allowNonFastForwards;
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>
110
/// <code>this</code>
113
public virtual NGit.BatchRefUpdate SetAllowNonFastForwards(bool allow)
115
allowNonFastForwards = allow;
119
/// <returns>identity of the user making the change in the reflog.</returns>
120
public virtual PersonIdent GetRefLogIdent()
125
/// <summary>Set the identity of the user appearing in the reflog.</summary>
127
/// Set the identity of the user appearing in the reflog.
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.
133
/// <param name="pi">
134
/// identity of the user. If null the identity will be
135
/// automatically determined based on the repository
140
/// <code>this</code>
143
public virtual NGit.BatchRefUpdate SetRefLogIdent(PersonIdent pi)
149
/// <summary>Get the message to include in the reflog.</summary>
150
/// <remarks>Get the message to include in the reflog.</remarks>
152
/// message the caller wants to include in the reflog; null if the
153
/// update should not be logged.
155
public virtual string GetRefLogMessage()
157
return refLogMessage;
162
/// <code>true</code>
163
/// if the ref log message should show the result.
165
public virtual bool IsRefLogIncludingResult()
167
return refLogIncludeResult;
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
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
183
/// <code>this</code>
186
public virtual NGit.BatchRefUpdate SetRefLogMessage(string msg, bool appendStatus
189
if (msg == null && !appendStatus)
195
if (msg == null && appendStatus)
197
refLogMessage = string.Empty;
198
refLogIncludeResult = true;
203
refLogIncludeResult = appendStatus;
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>
213
/// <code>this</code>
216
public virtual NGit.BatchRefUpdate DisableRefLog()
218
refLogMessage = null;
219
refLogIncludeResult = false;
224
/// true if log has been disabled by
225
/// <see cref="DisableRefLog()">DisableRefLog()</see>
228
public virtual bool IsRefLogDisabled()
230
return refLogMessage == null;
233
/// <returns>commands this update will process.</returns>
234
public virtual IList<ReceiveCommand> GetCommands()
236
return Sharpen.Collections.UnmodifiableList(commands);
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>
244
/// <code>this</code>
247
public virtual NGit.BatchRefUpdate AddCommand(ReceiveCommand cmd)
249
commands.AddItem(cmd);
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>
258
/// <code>this</code>
261
public virtual NGit.BatchRefUpdate AddCommand(params ReceiveCommand[] cmd)
263
return AddCommand(Arrays.AsList(cmd));
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>
271
/// <code>this</code>
274
public virtual NGit.BatchRefUpdate AddCommand(ICollection<ReceiveCommand> cmd)
276
Sharpen.Collections.AddAll(commands, cmd);
280
/// <summary>Execute this batch update.</summary>
282
/// Execute this batch update.
284
/// The default implementation of this method performs a sequential reference
285
/// update over each reference.
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.
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.
297
public virtual void Execute(RevWalk walk, ProgressMonitor update)
299
update.BeginTask(JGitText.Get().updatingReferences, commands.Count);
300
foreach (ReceiveCommand cmd in commands)
305
if (cmd.GetResult() == ReceiveCommand.Result.NOT_ATTEMPTED)
307
cmd.UpdateType(walk);
308
RefUpdate ru = NewUpdate(cmd);
309
switch (cmd.GetType())
311
case ReceiveCommand.Type.DELETE:
313
cmd.SetResult(ru.Delete(walk));
315
goto case ReceiveCommand.Type.CREATE;
318
case ReceiveCommand.Type.CREATE:
319
case ReceiveCommand.Type.UPDATE:
320
case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
322
cmd.SetResult(ru.Update(walk));
328
catch (IOException err)
330
cmd.SetResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, MessageFormat.Format(JGitText
331
.Get().lockError, err.Message));
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.
345
protected internal virtual RefUpdate NewUpdate(ReceiveCommand cmd)
347
RefUpdate ru = refdb.NewUpdate(cmd.GetRefName(), false);
348
if (IsRefLogDisabled())
354
ru.SetRefLogIdent(refLogIdent);
355
ru.SetRefLogMessage(refLogMessage, refLogIncludeResult);
357
switch (cmd.GetType())
359
case ReceiveCommand.Type.DELETE:
361
if (!ObjectId.ZeroId.Equals(cmd.GetOldId()))
363
ru.SetExpectedOldObjectId(cmd.GetOldId());
365
ru.SetForceUpdate(true);
369
case ReceiveCommand.Type.CREATE:
370
case ReceiveCommand.Type.UPDATE:
371
case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
374
ru.SetForceUpdate(IsAllowNonFastForwards());
375
ru.SetExpectedOldObjectId(cmd.GetOldId());
376
ru.SetNewObjectId(cmd.GetNewId());