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

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Api/CheckoutCommand.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.IO;
 
45
using NGit;
 
46
using NGit.Api;
 
47
using NGit.Api.Errors;
 
48
using NGit.Dircache;
 
49
using NGit.Errors;
 
50
using NGit.Revwalk;
 
51
using Sharpen;
 
52
 
 
53
namespace NGit.Api
 
54
{
 
55
        /// <summary>Checkout a branch to the working tree</summary>
 
56
        /// <seealso><a
 
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>
 
60
        {
 
61
                private string name;
 
62
 
 
63
                private bool force = false;
 
64
 
 
65
                private bool createBranch = false;
 
66
 
 
67
                private CreateBranchCommand.SetupUpstreamMode upstreamMode;
 
68
 
 
69
                private string startPoint = Constants.HEAD;
 
70
 
 
71
                private RevCommit startCommit;
 
72
 
 
73
                private CheckoutResult status;
 
74
 
 
75
                /// <param name="repo"></param>
 
76
                protected internal CheckoutCommand(Repository repo) : base(repo)
 
77
                {
 
78
                }
 
79
 
 
80
                /// <exception cref="NGit.Api.Errors.RefAlreadyExistsException">
 
81
                /// when trying to create (without force) a branch with a name
 
82
                /// that already exists
 
83
                /// </exception>
 
84
                /// <exception cref="NGit.Api.Errors.RefNotFoundException">if the start point or branch can not be found
 
85
                ///     </exception>
 
86
                /// <exception cref="NGit.Api.Errors.InvalidRefNameException">
 
87
                /// if the provided name is <code>null</code> or otherwise
 
88
                /// invalid
 
89
                /// </exception>
 
90
                /// <returns>the newly created branch</returns>
 
91
                /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
 
92
                public override Ref Call()
 
93
                {
 
94
                        CheckCallable();
 
95
                        ProcessOptions();
 
96
                        try
 
97
                        {
 
98
                                if (createBranch)
 
99
                                {
 
100
                                        Git git = new Git(repo);
 
101
                                        CreateBranchCommand command = git.BranchCreate();
 
102
                                        command.SetName(name);
 
103
                                        command.SetStartPoint(GetStartPoint().Name);
 
104
                                        if (upstreamMode != null)
 
105
                                        {
 
106
                                                command.SetUpstreamMode(upstreamMode);
 
107
                                        }
 
108
                                        command.Call();
 
109
                                }
 
110
                                Ref headRef = repo.GetRef(Constants.HEAD);
 
111
                                string refLogMessage = "checkout: moving from " + headRef.GetTarget().GetName();
 
112
                                ObjectId branch = repo.Resolve(name);
 
113
                                if (branch == null)
 
114
                                {
 
115
                                        throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
 
116
                                                , name));
 
117
                                }
 
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(), 
 
124
                                        newCommit.Tree);
 
125
                                dco.SetFailOnConflict(true);
 
126
                                try
 
127
                                {
 
128
                                        dco.Checkout();
 
129
                                }
 
130
                                catch (NGit.Errors.CheckoutConflictException e)
 
131
                                {
 
132
                                        status = new CheckoutResult(CheckoutResult.Status.CONFLICTS, dco.GetConflicts());
 
133
                                        throw;
 
134
                                }
 
135
                                Ref @ref = repo.GetRef(name);
 
136
                                if (@ref != null && !@ref.GetName().StartsWith(Constants.R_HEADS))
 
137
                                {
 
138
                                        @ref = null;
 
139
                                }
 
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;
 
144
                                if (@ref != null)
 
145
                                {
 
146
                                        updateResult = refUpdate.Link(@ref.GetName());
 
147
                                }
 
148
                                else
 
149
                                {
 
150
                                        refUpdate.SetNewObjectId(newCommit);
 
151
                                        updateResult = refUpdate.ForceUpdate();
 
152
                                }
 
153
                                SetCallable(false);
 
154
                                bool ok = false;
 
155
                                switch (updateResult)
 
156
                                {
 
157
                                        case RefUpdate.Result.NEW:
 
158
                                        {
 
159
                                                ok = true;
 
160
                                                break;
 
161
                                        }
 
162
 
 
163
                                        case RefUpdate.Result.NO_CHANGE:
 
164
                                        case RefUpdate.Result.FAST_FORWARD:
 
165
                                        case RefUpdate.Result.FORCED:
 
166
                                        {
 
167
                                                ok = true;
 
168
                                                break;
 
169
                                        }
 
170
 
 
171
                                        default:
 
172
                                        {
 
173
                                                break;
 
174
                                                break;
 
175
                                        }
 
176
                                }
 
177
                                if (!ok)
 
178
                                {
 
179
                                        throw new JGitInternalException(MessageFormat.Format(JGitText.Get().checkoutUnexpectedResult
 
180
                                                , updateResult.ToString()));
 
181
                                }
 
182
                                if (!dco.GetToBeDeleted().IsEmpty())
 
183
                                {
 
184
                                        status = new CheckoutResult(CheckoutResult.Status.NONDELETED, dco.GetToBeDeleted(
 
185
                                                ));
 
186
                                }
 
187
                                else
 
188
                                {
 
189
                                        status = CheckoutResult.OK_RESULT;
 
190
                                }
 
191
                                return @ref;
 
192
                        }
 
193
                        catch (IOException ioe)
 
194
                        {
 
195
                                throw new JGitInternalException(ioe.Message, ioe);
 
196
                        }
 
197
                        finally
 
198
                        {
 
199
                                if (status == null)
 
200
                                {
 
201
                                        status = CheckoutResult.ERROR_RESULT;
 
202
                                }
 
203
                        }
 
204
                }
 
205
 
 
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()
 
210
                {
 
211
                        if (startCommit != null)
 
212
                        {
 
213
                                return startCommit.Id;
 
214
                        }
 
215
                        ObjectId result = null;
 
216
                        try
 
217
                        {
 
218
                                result = repo.Resolve((startPoint == null) ? Constants.HEAD : startPoint);
 
219
                        }
 
220
                        catch (AmbiguousObjectException e)
 
221
                        {
 
222
                                throw;
 
223
                        }
 
224
                        if (result == null)
 
225
                        {
 
226
                                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
 
227
                                        , startPoint != null ? startPoint : Constants.HEAD));
 
228
                        }
 
229
                        return result;
 
230
                }
 
231
 
 
232
                /// <exception cref="NGit.Api.Errors.InvalidRefNameException"></exception>
 
233
                private void ProcessOptions()
 
234
                {
 
235
                        if (name == null || !Repository.IsValidRefName(Constants.R_HEADS + name))
 
236
                        {
 
237
                                throw new InvalidRefNameException(MessageFormat.Format(JGitText.Get().branchNameInvalid
 
238
                                        , name == null ? "<null>" : name));
 
239
                        }
 
240
                }
 
241
 
 
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)
 
245
                {
 
246
                        CheckCallable();
 
247
                        this.name = name;
 
248
                        return this;
 
249
                }
 
250
 
 
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
 
254
                /// </param>
 
255
                /// <returns>this instance</returns>
 
256
                public virtual NGit.Api.CheckoutCommand SetCreateBranch(bool createBranch)
 
257
                {
 
258
                        CheckCallable();
 
259
                        this.createBranch = createBranch;
 
260
                        return this;
 
261
                }
 
262
 
 
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
 
267
                /// not be changed
 
268
                /// </param>
 
269
                /// <returns>this instance</returns>
 
270
                public virtual NGit.Api.CheckoutCommand SetForce(bool force)
 
271
                {
 
272
                        CheckCallable();
 
273
                        this.force = force;
 
274
                        return this;
 
275
                }
 
276
 
 
277
                /// <param name="startPoint">
 
278
                /// corresponds to the start-point option; if <code>null</code>,
 
279
                /// the current HEAD will be used
 
280
                /// </param>
 
281
                /// <returns>this instance</returns>
 
282
                public virtual NGit.Api.CheckoutCommand SetStartPoint(string startPoint)
 
283
                {
 
284
                        CheckCallable();
 
285
                        this.startPoint = startPoint;
 
286
                        this.startCommit = null;
 
287
                        return this;
 
288
                }
 
289
 
 
290
                /// <param name="startCommit">
 
291
                /// corresponds to the start-point option; if <code>null</code>,
 
292
                /// the current HEAD will be used
 
293
                /// </param>
 
294
                /// <returns>this instance</returns>
 
295
                public virtual NGit.Api.CheckoutCommand SetStartPoint(RevCommit startCommit)
 
296
                {
 
297
                        CheckCallable();
 
298
                        this.startCommit = startCommit;
 
299
                        this.startPoint = null;
 
300
                        return this;
 
301
                }
 
302
 
 
303
                /// <param name="mode">
 
304
                /// corresponds to the --track/--no-track options; may be
 
305
                /// <code>null</code>
 
306
                /// </param>
 
307
                /// <returns>this instance</returns>
 
308
                public virtual NGit.Api.CheckoutCommand SetUpstreamMode(CreateBranchCommand.SetupUpstreamMode
 
309
                         mode)
 
310
                {
 
311
                        CheckCallable();
 
312
                        this.upstreamMode = mode;
 
313
                        return this;
 
314
                }
 
315
 
 
316
                /// <returns>the result</returns>
 
317
                public virtual CheckoutResult GetResult()
 
318
                {
 
319
                        if (status == null)
 
320
                        {
 
321
                                return CheckoutResult.NOT_TRIED_RESULT;
 
322
                        }
 
323
                        return status;
 
324
                }
 
325
        }
 
326
}