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.
47
using NGit.Api.Errors;
55
/// <summary>Checkout a branch to the working tree</summary>
57
/// * href="http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html"
58
/// * >Git documentation about Checkout</a></seealso>
59
public class CheckoutCommand : GitCommand<Ref>
63
private bool force = false;
65
private bool createBranch = false;
67
private CreateBranchCommand.SetupUpstreamMode upstreamMode;
69
private string startPoint = Constants.HEAD;
71
private RevCommit startCommit;
73
private CheckoutResult status;
75
/// <param name="repo"></param>
76
protected internal CheckoutCommand(Repository repo) : base(repo)
80
/// <exception cref="NGit.Api.Errors.RefAlreadyExistsException">
81
/// when trying to create (without force) a branch with a name
82
/// that already exists
84
/// <exception cref="NGit.Api.Errors.RefNotFoundException">if the start point or branch can not be found
86
/// <exception cref="NGit.Api.Errors.InvalidRefNameException">
87
/// if the provided name is <code>null</code> or otherwise
90
/// <returns>the newly created branch</returns>
91
/// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
92
public override Ref Call()
100
Git git = new Git(repo);
101
CreateBranchCommand command = git.BranchCreate();
102
command.SetName(name);
103
command.SetStartPoint(GetStartPoint().Name);
104
if (upstreamMode != null)
106
command.SetUpstreamMode(upstreamMode);
110
Ref headRef = repo.GetRef(Constants.HEAD);
111
string refLogMessage = "checkout: moving from " + headRef.GetTarget().GetName();
112
ObjectId branch = repo.Resolve(name);
115
throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
118
RevWalk revWalk = new RevWalk(repo);
119
AnyObjectId headId = headRef.GetObjectId();
120
RevCommit headCommit = headId == null ? null : revWalk.ParseCommit(headId);
121
RevCommit newCommit = revWalk.ParseCommit(branch);
122
RevTree headTree = headCommit == null ? null : headCommit.Tree;
123
DirCacheCheckout dco = new DirCacheCheckout(repo, headTree, repo.LockDirCache(),
125
dco.SetFailOnConflict(true);
130
catch (NGit.Errors.CheckoutConflictException e)
132
status = new CheckoutResult(CheckoutResult.Status.CONFLICTS, dco.GetConflicts());
135
Ref @ref = repo.GetRef(name);
136
if (@ref != null && !@ref.GetName().StartsWith(Constants.R_HEADS))
140
RefUpdate refUpdate = repo.UpdateRef(Constants.HEAD, @ref == null);
141
refUpdate.SetForceUpdate(force);
142
refUpdate.SetRefLogMessage(refLogMessage + " to " + newCommit.GetName(), false);
143
RefUpdate.Result updateResult;
146
updateResult = refUpdate.Link(@ref.GetName());
150
refUpdate.SetNewObjectId(newCommit);
151
updateResult = refUpdate.ForceUpdate();
155
switch (updateResult)
157
case RefUpdate.Result.NEW:
163
case RefUpdate.Result.NO_CHANGE:
164
case RefUpdate.Result.FAST_FORWARD:
165
case RefUpdate.Result.FORCED:
179
throw new JGitInternalException(MessageFormat.Format(JGitText.Get().checkoutUnexpectedResult
180
, updateResult.ToString()));
182
if (!dco.GetToBeDeleted().IsEmpty())
184
status = new CheckoutResult(CheckoutResult.Status.NONDELETED, dco.GetToBeDeleted(
189
status = CheckoutResult.OK_RESULT;
193
catch (IOException ioe)
195
throw new JGitInternalException(ioe.Message, ioe);
201
status = CheckoutResult.ERROR_RESULT;
206
/// <exception cref="NGit.Errors.AmbiguousObjectException"></exception>
207
/// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
208
/// <exception cref="System.IO.IOException"></exception>
209
private ObjectId GetStartPoint()
211
if (startCommit != null)
213
return startCommit.Id;
215
ObjectId result = null;
218
result = repo.Resolve((startPoint == null) ? Constants.HEAD : startPoint);
220
catch (AmbiguousObjectException e)
226
throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
227
, startPoint != null ? startPoint : Constants.HEAD));
232
/// <exception cref="NGit.Api.Errors.InvalidRefNameException"></exception>
233
private void ProcessOptions()
235
if (name == null || !Repository.IsValidRefName(Constants.R_HEADS + name))
237
throw new InvalidRefNameException(MessageFormat.Format(JGitText.Get().branchNameInvalid
238
, name == null ? "<null>" : name));
242
/// <param name="name">the name of the new branch</param>
243
/// <returns>this instance</returns>
244
public virtual NGit.Api.CheckoutCommand SetName(string name)
251
/// <param name="createBranch">
252
/// if <code>true</code> a branch will be created as part of the
253
/// checkout and set to the specified start point
255
/// <returns>this instance</returns>
256
public virtual NGit.Api.CheckoutCommand SetCreateBranch(bool createBranch)
259
this.createBranch = createBranch;
263
/// <param name="force">
264
/// if <code>true</code> and the branch with the given name
265
/// already exists, the start-point of an existing branch will be
266
/// set to a new start-point; if false, the existing branch will
269
/// <returns>this instance</returns>
270
public virtual NGit.Api.CheckoutCommand SetForce(bool force)
277
/// <param name="startPoint">
278
/// corresponds to the start-point option; if <code>null</code>,
279
/// the current HEAD will be used
281
/// <returns>this instance</returns>
282
public virtual NGit.Api.CheckoutCommand SetStartPoint(string startPoint)
285
this.startPoint = startPoint;
286
this.startCommit = null;
290
/// <param name="startCommit">
291
/// corresponds to the start-point option; if <code>null</code>,
292
/// the current HEAD will be used
294
/// <returns>this instance</returns>
295
public virtual NGit.Api.CheckoutCommand SetStartPoint(RevCommit startCommit)
298
this.startCommit = startCommit;
299
this.startPoint = null;
303
/// <param name="mode">
304
/// corresponds to the --track/--no-track options; may be
305
/// <code>null</code>
307
/// <returns>this instance</returns>
308
public virtual NGit.Api.CheckoutCommand SetUpstreamMode(CreateBranchCommand.SetupUpstreamMode
312
this.upstreamMode = mode;
316
/// <returns>the result</returns>
317
public virtual CheckoutResult GetResult()
321
return CheckoutResult.NOT_TRIED_RESULT;