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

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Api/CommitCommand.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.Collections.Generic;
 
45
using System.IO;
 
46
using NGit;
 
47
using NGit.Api;
 
48
using NGit.Api.Errors;
 
49
using NGit.Dircache;
 
50
using NGit.Errors;
 
51
using NGit.Revwalk;
 
52
using NGit.Treewalk;
 
53
using NGit.Util;
 
54
using Sharpen;
 
55
 
 
56
namespace NGit.Api
 
57
{
 
58
        /// <summary>
 
59
        /// A class used to execute a
 
60
        /// <code>Commit</code>
 
61
        /// command. It has setters for all
 
62
        /// supported options and arguments of this command and a
 
63
        /// <see cref="Call()">Call()</see>
 
64
        /// method
 
65
        /// to finally execute the command.
 
66
        /// </summary>
 
67
        /// <seealso><a
 
68
        /// *      href="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html"
 
69
        /// *      >Git documentation about Commit</a></seealso>
 
70
        public class CommitCommand : GitCommand<RevCommit>
 
71
        {
 
72
                private PersonIdent author;
 
73
 
 
74
                private PersonIdent committer;
 
75
 
 
76
                private string message;
 
77
 
 
78
                private bool all;
 
79
 
 
80
                private IList<string> only = new AList<string>();
 
81
 
 
82
                private bool[] onlyProcessed;
 
83
 
 
84
                private bool amend;
 
85
 
 
86
                private bool insertChangeId;
 
87
 
 
88
                /// <summary>parents this commit should have.</summary>
 
89
                /// <remarks>
 
90
                /// parents this commit should have. The current HEAD will be in this list
 
91
                /// and also all commits mentioned in .git/MERGE_HEAD
 
92
                /// </remarks>
 
93
                private IList<ObjectId> parents = new List<ObjectId>();
 
94
 
 
95
                /// <param name="repo"></param>
 
96
                protected internal CommitCommand(Repository repo) : base(repo)
 
97
                {
 
98
                }
 
99
 
 
100
                /// <summary>
 
101
                /// Executes the
 
102
                /// <code>commit</code>
 
103
                /// command with all the options and parameters
 
104
                /// collected by the setter methods of this class. Each instance of this
 
105
                /// class should only be used for one invocation of the command (means: one
 
106
                /// call to
 
107
                /// <see cref="Call()">Call()</see>
 
108
                /// )
 
109
                /// </summary>
 
110
                /// <returns>
 
111
                /// a
 
112
                /// <see cref="NGit.Revwalk.RevCommit">NGit.Revwalk.RevCommit</see>
 
113
                /// object representing the successful commit.
 
114
                /// </returns>
 
115
                /// <exception cref="NGit.Api.Errors.NoHeadException">when called on a git repo without a HEAD reference
 
116
                ///     </exception>
 
117
                /// <exception cref="NGit.Api.Errors.NoMessageException">when called without specifying a commit message
 
118
                ///     </exception>
 
119
                /// <exception cref="NGit.Errors.UnmergedPathException">when the current index contained unmerged paths (conflicts)
 
120
                ///     </exception>
 
121
                /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">when repository is not in the right state for committing
 
122
                ///     </exception>
 
123
                /// <exception cref="NGit.Api.Errors.JGitInternalException">
 
124
                /// a low-level exception of JGit has occurred. The original
 
125
                /// exception can be retrieved by calling
 
126
                /// <see cref="System.Exception.InnerException()">System.Exception.InnerException()</see>
 
127
                /// . Expect only
 
128
                /// <code>IOException's</code>
 
129
                /// to be wrapped. Subclasses of
 
130
                /// <see cref="System.IO.IOException">System.IO.IOException</see>
 
131
                /// (e.g.
 
132
                /// <see cref="NGit.Errors.UnmergedPathException">NGit.Errors.UnmergedPathException</see>
 
133
                /// ) are
 
134
                /// typically not wrapped here but thrown as original exception
 
135
                /// </exception>
 
136
                /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException"></exception>
 
137
                public override RevCommit Call()
 
138
                {
 
139
                        CheckCallable();
 
140
                        RepositoryState state = repo.GetRepositoryState();
 
141
                        if (!state.CanCommit())
 
142
                        {
 
143
                                throw new WrongRepositoryStateException(MessageFormat.Format(JGitText.Get().cannotCommitOnARepoWithState
 
144
                                        , state.Name()));
 
145
                        }
 
146
                        ProcessOptions(state);
 
147
                        try
 
148
                        {
 
149
                                if (all && !repo.IsBare && repo.WorkTree != null)
 
150
                                {
 
151
                                        Git git = new Git(repo);
 
152
                                        try
 
153
                                        {
 
154
                                                git.Add().AddFilepattern(".").SetUpdate(true).Call();
 
155
                                        }
 
156
                                        catch (NoFilepatternException e)
 
157
                                        {
 
158
                                                // should really not happen
 
159
                                                throw new JGitInternalException(e.Message, e);
 
160
                                        }
 
161
                                }
 
162
                                Ref head = repo.GetRef(Constants.HEAD);
 
163
                                if (head == null)
 
164
                                {
 
165
                                        throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported
 
166
                                                );
 
167
                                }
 
168
                                // determine the current HEAD and the commit it is referring to
 
169
                                ObjectId headId = repo.Resolve(Constants.HEAD + "^{commit}");
 
170
                                if (headId != null)
 
171
                                {
 
172
                                        if (amend)
 
173
                                        {
 
174
                                                RevCommit previousCommit = new RevWalk(repo).ParseCommit(headId);
 
175
                                                RevCommit[] p = previousCommit.Parents;
 
176
                                                for (int i = 0; i < p.Length; i++)
 
177
                                                {
 
178
                                                        parents.Add(0, p[i].Id);
 
179
                                                }
 
180
                                        }
 
181
                                        else
 
182
                                        {
 
183
                                                parents.Add(0, headId);
 
184
                                        }
 
185
                                }
 
186
                                // lock the index
 
187
                                DirCache index = repo.LockDirCache();
 
188
                                try
 
189
                                {
 
190
                                        if (!only.IsEmpty())
 
191
                                        {
 
192
                                                index = CreateTemporaryIndex(headId, index);
 
193
                                        }
 
194
                                        ObjectInserter odi = repo.NewObjectInserter();
 
195
                                        try
 
196
                                        {
 
197
                                                // Write the index as tree to the object database. This may
 
198
                                                // fail for example when the index contains unmerged paths
 
199
                                                // (unresolved conflicts)
 
200
                                                ObjectId indexTreeId = index.WriteTree(odi);
 
201
                                                if (insertChangeId)
 
202
                                                {
 
203
                                                        InsertChangeId(indexTreeId);
 
204
                                                }
 
205
                                                // Create a Commit object, populate it and write it
 
206
                                                NGit.CommitBuilder commit = new NGit.CommitBuilder();
 
207
                                                commit.Committer = committer;
 
208
                                                commit.Author = author;
 
209
                                                commit.Message = message;
 
210
                                                commit.SetParentIds(parents);
 
211
                                                commit.TreeId = indexTreeId;
 
212
                                                ObjectId commitId = odi.Insert(commit);
 
213
                                                odi.Flush();
 
214
                                                RevWalk revWalk = new RevWalk(repo);
 
215
                                                try
 
216
                                                {
 
217
                                                        RevCommit revCommit = revWalk.ParseCommit(commitId);
 
218
                                                        RefUpdate ru = repo.UpdateRef(Constants.HEAD);
 
219
                                                        ru.SetNewObjectId(commitId);
 
220
                                                        string prefix = amend ? "commit (amend): " : "commit: ";
 
221
                                                        ru.SetRefLogMessage(prefix + revCommit.GetShortMessage(), false);
 
222
                                                        ru.SetExpectedOldObjectId(headId);
 
223
                                                        RefUpdate.Result rc = ru.ForceUpdate();
 
224
                                                        switch (rc)
 
225
                                                        {
 
226
                                                                case RefUpdate.Result.NEW:
 
227
                                                                case RefUpdate.Result.FORCED:
 
228
                                                                case RefUpdate.Result.FAST_FORWARD:
 
229
                                                                {
 
230
                                                                        SetCallable(false);
 
231
                                                                        if (state == RepositoryState.MERGING_RESOLVED)
 
232
                                                                        {
 
233
                                                                                // Commit was successful. Now delete the files
 
234
                                                                                // used for merge commits
 
235
                                                                                repo.WriteMergeCommitMsg(null);
 
236
                                                                                repo.WriteMergeHeads(null);
 
237
                                                                        }
 
238
                                                                        return revCommit;
 
239
                                                                }
 
240
 
 
241
                                                                case RefUpdate.Result.REJECTED:
 
242
                                                                case RefUpdate.Result.LOCK_FAILURE:
 
243
                                                                {
 
244
                                                                        throw new ConcurrentRefUpdateException(JGitText.Get().couldNotLockHEAD, ru.GetRef
 
245
                                                                                (), rc);
 
246
                                                                }
 
247
 
 
248
                                                                default:
 
249
                                                                {
 
250
                                                                        throw new JGitInternalException(MessageFormat.Format(JGitText.Get().updatingRefFailed
 
251
                                                                                , Constants.HEAD, commitId.ToString(), rc));
 
252
                                                                }
 
253
                                                        }
 
254
                                                }
 
255
                                                finally
 
256
                                                {
 
257
                                                        revWalk.Release();
 
258
                                                }
 
259
                                        }
 
260
                                        finally
 
261
                                        {
 
262
                                                odi.Release();
 
263
                                        }
 
264
                                }
 
265
                                finally
 
266
                                {
 
267
                                        index.Unlock();
 
268
                                }
 
269
                        }
 
270
                        catch (UnmergedPathException e)
 
271
                        {
 
272
                                // since UnmergedPathException is a subclass of IOException
 
273
                                // which should not be wrapped by a JGitInternalException we
 
274
                                // have to catch and re-throw it here
 
275
                                throw;
 
276
                        }
 
277
                        catch (IOException e)
 
278
                        {
 
279
                                throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfCommitCommand
 
280
                                        , e);
 
281
                        }
 
282
                }
 
283
 
 
284
                /// <exception cref="System.IO.IOException"></exception>
 
285
                private void InsertChangeId(ObjectId treeId)
 
286
                {
 
287
                        ObjectId firstParentId = null;
 
288
                        if (!parents.IsEmpty())
 
289
                        {
 
290
                                firstParentId = parents[0];
 
291
                        }
 
292
                        ObjectId changeId = ChangeIdUtil.ComputeChangeId(treeId, firstParentId, author, committer
 
293
                                , message);
 
294
                        message = ChangeIdUtil.InsertId(message, changeId);
 
295
                        if (changeId != null)
 
296
                        {
 
297
                                message = message.ReplaceAll("\nChange-Id: I" + ObjectId.ZeroId.GetName() + "\n", 
 
298
                                        "\nChange-Id: I" + changeId.GetName() + "\n");
 
299
                        }
 
300
                }
 
301
 
 
302
                /// <exception cref="System.IO.IOException"></exception>
 
303
                private DirCache CreateTemporaryIndex(ObjectId headId, DirCache index)
 
304
                {
 
305
                        ObjectInserter inserter = null;
 
306
                        // get DirCacheEditor to modify the index if required
 
307
                        DirCacheEditor dcEditor = index.Editor();
 
308
                        // get DirCacheBuilder for newly created in-core index to build a
 
309
                        // temporary index for this commit
 
310
                        DirCache inCoreIndex = DirCache.NewInCore();
 
311
                        DirCacheBuilder dcBuilder = inCoreIndex.Builder();
 
312
                        onlyProcessed = new bool[only.Count];
 
313
                        bool emptyCommit = true;
 
314
                        TreeWalk treeWalk = new TreeWalk(repo);
 
315
                        int dcIdx = treeWalk.AddTree(new DirCacheIterator(index));
 
316
                        int fIdx = treeWalk.AddTree(new FileTreeIterator(repo));
 
317
                        int hIdx = -1;
 
318
                        if (headId != null)
 
319
                        {
 
320
                                hIdx = treeWalk.AddTree(new RevWalk(repo).ParseTree(headId));
 
321
                        }
 
322
                        treeWalk.Recursive = true;
 
323
                        while (treeWalk.Next())
 
324
                        {
 
325
                                string path = treeWalk.PathString;
 
326
                                // check if current entry's path matches a specified path
 
327
                                int pos = LookupOnly(path);
 
328
                                CanonicalTreeParser hTree = null;
 
329
                                if (hIdx != -1)
 
330
                                {
 
331
                                        hTree = treeWalk.GetTree<CanonicalTreeParser>(hIdx);
 
332
                                }
 
333
                                if (pos >= 0)
 
334
                                {
 
335
                                        // include entry in commit
 
336
                                        DirCacheIterator dcTree = treeWalk.GetTree<DirCacheIterator>(dcIdx);
 
337
                                        FileTreeIterator fTree = treeWalk.GetTree<FileTreeIterator>(fIdx);
 
338
                                        // check if entry refers to a tracked file
 
339
                                        bool tracked = dcTree != null || hTree != null;
 
340
                                        if (!tracked)
 
341
                                        {
 
342
                                                break;
 
343
                                        }
 
344
                                        if (fTree != null)
 
345
                                        {
 
346
                                                // create a new DirCacheEntry with data retrieved from disk
 
347
                                                DirCacheEntry dcEntry = new DirCacheEntry(path);
 
348
                                                long entryLength = fTree.GetEntryLength();
 
349
                                                dcEntry.SetLength(entryLength);
 
350
                                                dcEntry.LastModified = fTree.GetEntryLastModified();
 
351
                                                dcEntry.FileMode = fTree.EntryFileMode;
 
352
                                                bool objectExists = (dcTree != null && fTree.IdEqual(dcTree)) || (hTree != null &&
 
353
                                                         fTree.IdEqual(hTree));
 
354
                                                if (objectExists)
 
355
                                                {
 
356
                                                        dcEntry.SetObjectId(fTree.EntryObjectId);
 
357
                                                }
 
358
                                                else
 
359
                                                {
 
360
                                                        // insert object
 
361
                                                        if (inserter == null)
 
362
                                                        {
 
363
                                                                inserter = repo.NewObjectInserter();
 
364
                                                        }
 
365
                                                        InputStream inputStream = fTree.OpenEntryStream();
 
366
                                                        try
 
367
                                                        {
 
368
                                                                dcEntry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, entryLength, inputStream)
 
369
                                                                        );
 
370
                                                        }
 
371
                                                        finally
 
372
                                                        {
 
373
                                                                inputStream.Close();
 
374
                                                        }
 
375
                                                }
 
376
                                                // update index
 
377
                                                dcEditor.Add(new _PathEdit_356(dcEntry, path));
 
378
                                                // add to temporary in-core index
 
379
                                                dcBuilder.Add(dcEntry);
 
380
                                                if (emptyCommit && (hTree == null || !hTree.IdEqual(fTree)))
 
381
                                                {
 
382
                                                        // this is a change
 
383
                                                        emptyCommit = false;
 
384
                                                }
 
385
                                        }
 
386
                                        else
 
387
                                        {
 
388
                                                // if no file exists on disk, remove entry from index and
 
389
                                                // don't add it to temporary in-core index
 
390
                                                dcEditor.Add(new DirCacheEditor.DeletePath(path));
 
391
                                                if (emptyCommit && hTree != null)
 
392
                                                {
 
393
                                                        // this is a change
 
394
                                                        emptyCommit = false;
 
395
                                                }
 
396
                                        }
 
397
                                        // keep track of processed path
 
398
                                        onlyProcessed[pos] = true;
 
399
                                }
 
400
                                else
 
401
                                {
 
402
                                        // add entries from HEAD for all other paths
 
403
                                        if (hTree != null)
 
404
                                        {
 
405
                                                // create a new DirCacheEntry with data retrieved from HEAD
 
406
                                                DirCacheEntry dcEntry = new DirCacheEntry(path);
 
407
                                                dcEntry.SetObjectId(hTree.EntryObjectId);
 
408
                                                dcEntry.FileMode = hTree.EntryFileMode;
 
409
                                                // add to temporary in-core index
 
410
                                                dcBuilder.Add(dcEntry);
 
411
                                        }
 
412
                                }
 
413
                        }
 
414
                        // there must be no unprocessed paths left at this point; otherwise an
 
415
                        // untracked or unknown path has been specified
 
416
                        for (int i = 0; i < onlyProcessed.Length; i++)
 
417
                        {
 
418
                                if (!onlyProcessed[i])
 
419
                                {
 
420
                                        throw new JGitInternalException(MessageFormat.Format(JGitText.Get().entryNotFoundByPath
 
421
                                                , only[i]));
 
422
                                }
 
423
                        }
 
424
                        // there must be at least one change
 
425
                        if (emptyCommit)
 
426
                        {
 
427
                                throw new JGitInternalException(JGitText.Get().emptyCommit);
 
428
                        }
 
429
                        // update index
 
430
                        dcEditor.Commit();
 
431
                        // finish temporary in-core index used for this commit
 
432
                        dcBuilder.Finish();
 
433
                        return inCoreIndex;
 
434
                }
 
435
 
 
436
                private sealed class _PathEdit_356 : DirCacheEditor.PathEdit
 
437
                {
 
438
                        public _PathEdit_356(DirCacheEntry dcEntry, string baseArg1) : base(baseArg1)
 
439
                        {
 
440
                                this.dcEntry = dcEntry;
 
441
                        }
 
442
 
 
443
                        public override void Apply(DirCacheEntry ent)
 
444
                        {
 
445
                                ent.CopyMetaData(dcEntry);
 
446
                        }
 
447
 
 
448
                        private readonly DirCacheEntry dcEntry;
 
449
                }
 
450
 
 
451
                /// <summary>
 
452
                /// Look an entry's path up in the list of paths specified by the --only/ -o
 
453
                /// option
 
454
                /// In case the complete (file) path (e.g.
 
455
                /// </summary>
 
456
                /// <remarks>
 
457
                /// Look an entry's path up in the list of paths specified by the --only/ -o
 
458
                /// option
 
459
                /// In case the complete (file) path (e.g. "d1/d2/f1") cannot be found in
 
460
                /// <code>only</code>, lookup is also tried with (parent) directory paths
 
461
                /// (e.g. "d1/d2" and "d1").
 
462
                /// </remarks>
 
463
                /// <param name="pathString">entry's path</param>
 
464
                /// <returns>the item's index in <code>only</code>; -1 if no item matches</returns>
 
465
                private int LookupOnly(string pathString)
 
466
                {
 
467
                        int i = 0;
 
468
                        foreach (string o in only)
 
469
                        {
 
470
                                string p = pathString;
 
471
                                while (true)
 
472
                                {
 
473
                                        if (p.Equals(o))
 
474
                                        {
 
475
                                                return i;
 
476
                                        }
 
477
                                        int l = p.LastIndexOf("/");
 
478
                                        if (l < 1)
 
479
                                        {
 
480
                                                break;
 
481
                                        }
 
482
                                        p = Sharpen.Runtime.Substring(p, 0, l);
 
483
                                }
 
484
                                i++;
 
485
                        }
 
486
                        return -1;
 
487
                }
 
488
 
 
489
                /// <summary>Sets default values for not explicitly specified options.</summary>
 
490
                /// <remarks>
 
491
                /// Sets default values for not explicitly specified options. Then validates
 
492
                /// that all required data has been provided.
 
493
                /// </remarks>
 
494
                /// <param name="state">the state of the repository we are working on</param>
 
495
                /// <exception cref="NGit.Api.Errors.NoMessageException">if the commit message has not been specified
 
496
                ///     </exception>
 
497
                private void ProcessOptions(RepositoryState state)
 
498
                {
 
499
                        if (committer == null)
 
500
                        {
 
501
                                committer = new PersonIdent(repo);
 
502
                        }
 
503
                        if (author == null)
 
504
                        {
 
505
                                author = committer;
 
506
                        }
 
507
                        // when doing a merge commit parse MERGE_HEAD and MERGE_MSG files
 
508
                        if (state == RepositoryState.MERGING_RESOLVED)
 
509
                        {
 
510
                                try
 
511
                                {
 
512
                                        parents = repo.ReadMergeHeads();
 
513
                                }
 
514
                                catch (IOException e)
 
515
                                {
 
516
                                        throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionOccurredDuringReadingOfGIT_DIR
 
517
                                                , Constants.MERGE_HEAD, e), e);
 
518
                                }
 
519
                                if (message == null)
 
520
                                {
 
521
                                        try
 
522
                                        {
 
523
                                                message = repo.ReadMergeCommitMsg();
 
524
                                        }
 
525
                                        catch (IOException e)
 
526
                                        {
 
527
                                                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionOccurredDuringReadingOfGIT_DIR
 
528
                                                        , Constants.MERGE_MSG, e), e);
 
529
                                        }
 
530
                                }
 
531
                        }
 
532
                        if (message == null)
 
533
                        {
 
534
                                // as long as we don't suppport -C option we have to have
 
535
                                // an explicit message
 
536
                                throw new NoMessageException(JGitText.Get().commitMessageNotSpecified);
 
537
                        }
 
538
                }
 
539
 
 
540
                /// <param name="message">
 
541
                /// the commit message used for the
 
542
                /// <code>commit</code>
 
543
                /// </param>
 
544
                /// <returns>
 
545
                /// 
 
546
                /// <code>this</code>
 
547
                /// </returns>
 
548
                public virtual NGit.Api.CommitCommand SetMessage(string message)
 
549
                {
 
550
                        CheckCallable();
 
551
                        this.message = message;
 
552
                        return this;
 
553
                }
 
554
 
 
555
                /// <returns>the commit message used for the <code>commit</code></returns>
 
556
                public virtual string GetMessage()
 
557
                {
 
558
                        return message;
 
559
                }
 
560
 
 
561
                /// <summary>
 
562
                /// Sets the committer for this
 
563
                /// <code>commit</code>
 
564
                /// . If no committer is explicitly
 
565
                /// specified because this method is never called or called with
 
566
                /// <code>null</code>
 
567
                /// value then the committer will be deduced from config info in repository,
 
568
                /// with current time.
 
569
                /// </summary>
 
570
                /// <param name="committer">
 
571
                /// the committer used for the
 
572
                /// <code>commit</code>
 
573
                /// </param>
 
574
                /// <returns>
 
575
                /// 
 
576
                /// <code>this</code>
 
577
                /// </returns>
 
578
                public virtual NGit.Api.CommitCommand SetCommitter(PersonIdent committer)
 
579
                {
 
580
                        CheckCallable();
 
581
                        this.committer = committer;
 
582
                        return this;
 
583
                }
 
584
 
 
585
                /// <summary>
 
586
                /// Sets the committer for this
 
587
                /// <code>commit</code>
 
588
                /// . If no committer is explicitly
 
589
                /// specified because this method is never called or called with
 
590
                /// <code>null</code>
 
591
                /// value then the committer will be deduced from config info in repository,
 
592
                /// with current time.
 
593
                /// </summary>
 
594
                /// <param name="name">
 
595
                /// the name of the committer used for the
 
596
                /// <code>commit</code>
 
597
                /// </param>
 
598
                /// <param name="email">
 
599
                /// the email of the committer used for the
 
600
                /// <code>commit</code>
 
601
                /// </param>
 
602
                /// <returns>
 
603
                /// 
 
604
                /// <code>this</code>
 
605
                /// </returns>
 
606
                public virtual NGit.Api.CommitCommand SetCommitter(string name, string email)
 
607
                {
 
608
                        CheckCallable();
 
609
                        return SetCommitter(new PersonIdent(name, email));
 
610
                }
 
611
 
 
612
                /// <returns>
 
613
                /// the committer used for the
 
614
                /// <code>commit</code>
 
615
                /// . If no committer was
 
616
                /// specified
 
617
                /// <code>null</code>
 
618
                /// is returned and the default
 
619
                /// <see cref="NGit.PersonIdent">NGit.PersonIdent</see>
 
620
                /// of this repo is used during execution of the
 
621
                /// command
 
622
                /// </returns>
 
623
                public virtual PersonIdent GetCommitter()
 
624
                {
 
625
                        return committer;
 
626
                }
 
627
 
 
628
                /// <summary>
 
629
                /// Sets the author for this
 
630
                /// <code>commit</code>
 
631
                /// . If no author is explicitly
 
632
                /// specified because this method is never called or called with
 
633
                /// <code>null</code>
 
634
                /// value then the author will be set to the committer.
 
635
                /// </summary>
 
636
                /// <param name="author">
 
637
                /// the author used for the
 
638
                /// <code>commit</code>
 
639
                /// </param>
 
640
                /// <returns>
 
641
                /// 
 
642
                /// <code>this</code>
 
643
                /// </returns>
 
644
                public virtual NGit.Api.CommitCommand SetAuthor(PersonIdent author)
 
645
                {
 
646
                        CheckCallable();
 
647
                        this.author = author;
 
648
                        return this;
 
649
                }
 
650
 
 
651
                /// <summary>
 
652
                /// Sets the author for this
 
653
                /// <code>commit</code>
 
654
                /// . If no author is explicitly
 
655
                /// specified because this method is never called or called with
 
656
                /// <code>null</code>
 
657
                /// value then the author will be set to the committer.
 
658
                /// </summary>
 
659
                /// <param name="name">
 
660
                /// the name of the author used for the
 
661
                /// <code>commit</code>
 
662
                /// </param>
 
663
                /// <param name="email">
 
664
                /// the email of the author used for the
 
665
                /// <code>commit</code>
 
666
                /// </param>
 
667
                /// <returns>
 
668
                /// 
 
669
                /// <code>this</code>
 
670
                /// </returns>
 
671
                public virtual NGit.Api.CommitCommand SetAuthor(string name, string email)
 
672
                {
 
673
                        CheckCallable();
 
674
                        return SetAuthor(new PersonIdent(name, email));
 
675
                }
 
676
 
 
677
                /// <returns>
 
678
                /// the author used for the
 
679
                /// <code>commit</code>
 
680
                /// . If no author was
 
681
                /// specified
 
682
                /// <code>null</code>
 
683
                /// is returned and the default
 
684
                /// <see cref="NGit.PersonIdent">NGit.PersonIdent</see>
 
685
                /// of this repo is used during execution of the
 
686
                /// command
 
687
                /// </returns>
 
688
                public virtual PersonIdent GetAuthor()
 
689
                {
 
690
                        return author;
 
691
                }
 
692
 
 
693
                /// <summary>
 
694
                /// If set to true the Commit command automatically stages files that have
 
695
                /// been modified and deleted, but new files not known by the repository are
 
696
                /// not affected.
 
697
                /// </summary>
 
698
                /// <remarks>
 
699
                /// If set to true the Commit command automatically stages files that have
 
700
                /// been modified and deleted, but new files not known by the repository are
 
701
                /// not affected. This corresponds to the parameter -a on the command line.
 
702
                /// </remarks>
 
703
                /// <param name="all"></param>
 
704
                /// <returns>
 
705
                /// 
 
706
                /// <code>this</code>
 
707
                /// </returns>
 
708
                /// <exception cref="NGit.Api.Errors.JGitInternalException">in case of an illegal combination of arguments/ options
 
709
                ///     </exception>
 
710
                public virtual NGit.Api.CommitCommand SetAll(bool all)
 
711
                {
 
712
                        CheckCallable();
 
713
                        if (!only.IsEmpty())
 
714
                        {
 
715
                                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().illegalCombinationOfArguments
 
716
                                        , "--all", "--only"));
 
717
                        }
 
718
                        this.all = all;
 
719
                        return this;
 
720
                }
 
721
 
 
722
                /// <summary>Used to amend the tip of the current branch.</summary>
 
723
                /// <remarks>
 
724
                /// Used to amend the tip of the current branch. If set to true, the previous
 
725
                /// commit will be amended. This is equivalent to --amend on the command
 
726
                /// line.
 
727
                /// </remarks>
 
728
                /// <param name="amend"></param>
 
729
                /// <returns>
 
730
                /// 
 
731
                /// <code>this</code>
 
732
                /// </returns>
 
733
                public virtual NGit.Api.CommitCommand SetAmend(bool amend)
 
734
                {
 
735
                        CheckCallable();
 
736
                        this.amend = amend;
 
737
                        return this;
 
738
                }
 
739
 
 
740
                /// <summary>
 
741
                /// Commit dedicated path only
 
742
                /// This method can be called several times to add multiple paths.
 
743
                /// </summary>
 
744
                /// <remarks>
 
745
                /// Commit dedicated path only
 
746
                /// This method can be called several times to add multiple paths. Full file
 
747
                /// paths are supported as well as directory paths; in the latter case this
 
748
                /// commits all files/ directories below the specified path.
 
749
                /// </remarks>
 
750
                /// <param name="only">path to commit</param>
 
751
                /// <returns>
 
752
                /// 
 
753
                /// <code>this</code>
 
754
                /// </returns>
 
755
                public virtual NGit.Api.CommitCommand SetOnly(string only)
 
756
                {
 
757
                        CheckCallable();
 
758
                        if (all)
 
759
                        {
 
760
                                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().illegalCombinationOfArguments
 
761
                                        , "--only", "--all"));
 
762
                        }
 
763
                        string o = only.EndsWith("/") ? Sharpen.Runtime.Substring(only, 0, only.Length - 
 
764
                                1) : only;
 
765
                        // ignore duplicates
 
766
                        if (!this.only.Contains(o))
 
767
                        {
 
768
                                this.only.AddItem(o);
 
769
                        }
 
770
                        return this;
 
771
                }
 
772
 
 
773
                /// <summary>
 
774
                /// If set to true a change id will be inserted into the commit message
 
775
                /// An existing change id is not replaced.
 
776
                /// </summary>
 
777
                /// <remarks>
 
778
                /// If set to true a change id will be inserted into the commit message
 
779
                /// An existing change id is not replaced. An initial change id (I000...)
 
780
                /// will be replaced by the change id.
 
781
                /// </remarks>
 
782
                /// <param name="insertChangeId"></param>
 
783
                /// <returns>
 
784
                /// 
 
785
                /// <code>this</code>
 
786
                /// </returns>
 
787
                public virtual NGit.Api.CommitCommand SetInsertChangeId(bool insertChangeId)
 
788
                {
 
789
                        CheckCallable();
 
790
                        this.insertChangeId = insertChangeId;
 
791
                        return this;
 
792
                }
 
793
        }
 
794
}