1package git
2
3import (
4 "errors"
5 "fmt"
6 "regexp"
7 "strings"
8 "time"
9
10 "github.com/ProtonMail/go-crypto/openpgp"
11 "github.com/go-git/go-git/v5/config"
12 "github.com/go-git/go-git/v5/plumbing"
13 formatcfg "github.com/go-git/go-git/v5/plumbing/format/config"
14 "github.com/go-git/go-git/v5/plumbing/object"
15 "github.com/go-git/go-git/v5/plumbing/protocol/packp"
16 "github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
17 "github.com/go-git/go-git/v5/plumbing/transport"
18)
19
20// SubmoduleRecursivity defines how depth will affect any submodule recursive
21// operation.
22type SubmoduleRecursivity uint
23
24const (
25 // DefaultRemoteName name of the default Remote, just like git command.
26 DefaultRemoteName = "origin"
27
28 // NoRecurseSubmodules disables the recursion for a submodule operation.
29 NoRecurseSubmodules SubmoduleRecursivity = 0
30 // DefaultSubmoduleRecursionDepth allow recursion in a submodule operation.
31 DefaultSubmoduleRecursionDepth SubmoduleRecursivity = 10
32)
33
34var ErrMissingURL = errors.New("URL field is required")
35
36// CloneOptions describes how a clone should be performed.
37type CloneOptions struct {
38 // The (possibly remote) repository URL to clone from.
39 URL string
40 // Auth credentials, if required, to use with the remote repository.
41 Auth transport.AuthMethod
42 // Name of the remote to be added, by default `origin`.
43 RemoteName string
44 // Remote branch to clone.
45 ReferenceName plumbing.ReferenceName
46 // Fetch only ReferenceName if true.
47 SingleBranch bool
48 // Mirror clones the repository as a mirror.
49 //
50 // Compared to a bare clone, mirror not only maps local branches of the
51 // source to local branches of the target, it maps all refs (including
52 // remote-tracking branches, notes etc.) and sets up a refspec configuration
53 // such that all these refs are overwritten by a git remote update in the
54 // target repository.
55 Mirror bool
56 // No checkout of HEAD after clone if true.
57 NoCheckout bool
58 // Limit fetching to the specified number of commits.
59 Depth int
60 // RecurseSubmodules after the clone is created, initialize all submodules
61 // within, using their default settings. This option is ignored if the
62 // cloned repository does not have a worktree.
63 RecurseSubmodules SubmoduleRecursivity
64 // ShallowSubmodules limit cloning submodules to the 1 level of depth.
65 // It matches the git command --shallow-submodules.
66 ShallowSubmodules bool
67 // Progress is where the human readable information sent by the server is
68 // stored, if nil nothing is stored and the capability (if supported)
69 // no-progress, is sent to the server to avoid send this information.
70 Progress sideband.Progress
71 // Tags describe how the tags will be fetched from the remote repository,
72 // by default is AllTags.
73 Tags plumbing.TagMode
74 // InsecureSkipTLS skips ssl verify if protocol is https
75 InsecureSkipTLS bool
76 // CABundle specify additional ca bundle with system cert pool
77 CABundle []byte
78 // ProxyOptions provides info required for connecting to a proxy.
79 ProxyOptions transport.ProxyOptions
80 // When the repository to clone is on the local machine, instead of
81 // using hard links, automatically setup .git/objects/info/alternates
82 // to share the objects with the source repository.
83 // The resulting repository starts out without any object of its own.
84 // NOTE: this is a possibly dangerous operation; do not use it unless
85 // you understand what it does.
86 //
87 // [Reference]: https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---shared
88 Shared bool
89 // Filter requests that the server to send only a subset of the objects.
90 // See https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--filterltfilter-specgtcode
91 Filter packp.Filter
92}
93
94// MergeOptions describes how a merge should be performed.
95type MergeOptions struct {
96 // Strategy defines the merge strategy to be used.
97 Strategy MergeStrategy
98}
99
100// MergeStrategy represents the different types of merge strategies.
101type MergeStrategy int8
102
103const (
104 // FastForwardMerge represents a Git merge strategy where the current
105 // branch can be simply updated to point to the HEAD of the branch being
106 // merged. This is only possible if the history of the branch being merged
107 // is a linear descendant of the current branch, with no conflicting commits.
108 //
109 // This is the default option.
110 FastForwardMerge MergeStrategy = iota
111)
112
113// Validate validates the fields and sets the default values.
114func (o *CloneOptions) Validate() error {
115 if o.URL == "" {
116 return ErrMissingURL
117 }
118
119 if o.RemoteName == "" {
120 o.RemoteName = DefaultRemoteName
121 }
122
123 if o.ReferenceName == "" {
124 o.ReferenceName = plumbing.HEAD
125 }
126
127 if o.Tags == plumbing.InvalidTagMode {
128 o.Tags = plumbing.AllTags
129 }
130
131 return nil
132}
133
134// PullOptions describes how a pull should be performed.
135type PullOptions struct {
136 // Name of the remote to be pulled. If empty, uses the default.
137 RemoteName string
138 // RemoteURL overrides the remote repo address with a custom URL
139 RemoteURL string
140 // Remote branch to clone. If empty, uses HEAD.
141 ReferenceName plumbing.ReferenceName
142 // Fetch only ReferenceName if true.
143 SingleBranch bool
144 // Limit fetching to the specified number of commits.
145 Depth int
146 // Auth credentials, if required, to use with the remote repository.
147 Auth transport.AuthMethod
148 // RecurseSubmodules controls if new commits of all populated submodules
149 // should be fetched too.
150 RecurseSubmodules SubmoduleRecursivity
151 // Progress is where the human readable information sent by the server is
152 // stored, if nil nothing is stored and the capability (if supported)
153 // no-progress, is sent to the server to avoid send this information.
154 Progress sideband.Progress
155 // Force allows the pull to update a local branch even when the remote
156 // branch does not descend from it.
157 Force bool
158 // InsecureSkipTLS skips ssl verify if protocol is https
159 InsecureSkipTLS bool
160 // CABundle specify additional ca bundle with system cert pool
161 CABundle []byte
162 // ProxyOptions provides info required for connecting to a proxy.
163 ProxyOptions transport.ProxyOptions
164}
165
166// Validate validates the fields and sets the default values.
167func (o *PullOptions) Validate() error {
168 if o.RemoteName == "" {
169 o.RemoteName = DefaultRemoteName
170 }
171
172 if o.ReferenceName == "" {
173 o.ReferenceName = plumbing.HEAD
174 }
175
176 return nil
177}
178
179// TagMode defines how the tags will be fetched from the remote repository.
180// TODO: delete for V6
181type TagMode = plumbing.TagMode
182
183const (
184 InvalidTagMode = plumbing.InvalidTagMode
185 // TagFollowing any tag that points into the histories being fetched is also
186 // fetched. TagFollowing requires a server with `include-tag` capability
187 // in order to fetch the annotated tags objects.
188 TagFollowing = plumbing.TagFollowing
189 // AllTags fetch all tags from the remote (i.e., fetch remote tags
190 // refs/tags/* into local tags with the same name)
191 AllTags = plumbing.AllTags
192 // NoTags fetch no tags from the remote at all
193 NoTags = plumbing.NoTags
194)
195
196// FetchOptions describes how a fetch should be performed
197type FetchOptions struct {
198 // Name of the remote to fetch from. Defaults to origin.
199 RemoteName string
200 // RemoteURL overrides the remote repo address with a custom URL
201 RemoteURL string
202 RefSpecs []config.RefSpec
203 // Depth limit fetching to the specified number of commits from the tip of
204 // each remote branch history.
205 Depth int
206 // Auth credentials, if required, to use with the remote repository.
207 Auth transport.AuthMethod
208 // Progress is where the human readable information sent by the server is
209 // stored, if nil nothing is stored and the capability (if supported)
210 // no-progress, is sent to the server to avoid send this information.
211 Progress sideband.Progress
212 // Tags describe how the tags will be fetched from the remote repository,
213 // by default is TagFollowing.
214 Tags plumbing.TagMode
215 // Force allows the fetch to update a local branch even when the remote
216 // branch does not descend from it.
217 Force bool
218 // InsecureSkipTLS skips ssl verify if protocol is https
219 InsecureSkipTLS bool
220 // CABundle specify additional ca bundle with system cert pool
221 CABundle []byte
222 // ProxyOptions provides info required for connecting to a proxy.
223 ProxyOptions transport.ProxyOptions
224 // Prune specify that local refs that match given RefSpecs and that do
225 // not exist remotely will be removed.
226 Prune bool
227 // Filter requests that the server to send only a subset of the objects.
228 // See https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--filterltfilter-specgtcode
229 Filter packp.Filter
230}
231
232// Validate validates the fields and sets the default values.
233func (o *FetchOptions) Validate() error {
234 if o.RemoteName == "" {
235 o.RemoteName = DefaultRemoteName
236 }
237
238 if o.Tags == plumbing.InvalidTagMode {
239 o.Tags = plumbing.TagFollowing
240 }
241
242 for _, r := range o.RefSpecs {
243 if err := r.Validate(); err != nil {
244 return err
245 }
246 }
247
248 return nil
249}
250
251// PushOptions describes how a push should be performed.
252type PushOptions struct {
253 // RemoteName is the name of the remote to be pushed to.
254 RemoteName string
255 // RemoteURL overrides the remote repo address with a custom URL
256 RemoteURL string
257 // RefSpecs specify what destination ref to update with what source object.
258 //
259 // The format of a <refspec> parameter is an optional plus +, followed by
260 // the source object <src>, followed by a colon :, followed by the destination ref <dst>.
261 // The <src> is often the name of the branch you would want to push, but it can be a SHA-1.
262 // The <dst> tells which ref on the remote side is updated with this push.
263 //
264 // A refspec with empty src can be used to delete a reference.
265 RefSpecs []config.RefSpec
266 // Auth credentials, if required, to use with the remote repository.
267 Auth transport.AuthMethod
268 // Progress is where the human readable information sent by the server is
269 // stored, if nil nothing is stored.
270 Progress sideband.Progress
271 // Prune specify that remote refs that match given RefSpecs and that do
272 // not exist locally will be removed.
273 Prune bool
274 // Force allows the push to update a remote branch even when the local
275 // branch does not descend from it.
276 Force bool
277 // InsecureSkipTLS skips ssl verify if protocol is https
278 InsecureSkipTLS bool
279 // CABundle specify additional ca bundle with system cert pool
280 CABundle []byte
281 // RequireRemoteRefs only allows a remote ref to be updated if its current
282 // value is the one specified here.
283 RequireRemoteRefs []config.RefSpec
284 // FollowTags will send any annotated tags with a commit target reachable from
285 // the refs already being pushed
286 FollowTags bool
287 // ForceWithLease allows a force push as long as the remote ref adheres to a "lease"
288 ForceWithLease *ForceWithLease
289 // PushOptions sets options to be transferred to the server during push.
290 Options map[string]string
291 // Atomic sets option to be an atomic push
292 Atomic bool
293 // ProxyOptions provides info required for connecting to a proxy.
294 ProxyOptions transport.ProxyOptions
295}
296
297// ForceWithLease sets fields on the lease
298// If neither RefName nor Hash are set, ForceWithLease protects
299// all refs in the refspec by ensuring the ref of the remote in the local repsitory
300// matches the one in the ref advertisement.
301type ForceWithLease struct {
302 // RefName, when set will protect the ref by ensuring it matches the
303 // hash in the ref advertisement.
304 RefName plumbing.ReferenceName
305 // Hash is the expected object id of RefName. The push will be rejected unless this
306 // matches the corresponding object id of RefName in the refs advertisement.
307 Hash plumbing.Hash
308}
309
310// Validate validates the fields and sets the default values.
311func (o *PushOptions) Validate() error {
312 if o.RemoteName == "" {
313 o.RemoteName = DefaultRemoteName
314 }
315
316 if len(o.RefSpecs) == 0 {
317 o.RefSpecs = []config.RefSpec{
318 config.RefSpec(config.DefaultPushRefSpec),
319 }
320 }
321
322 for _, r := range o.RefSpecs {
323 if err := r.Validate(); err != nil {
324 return err
325 }
326 }
327
328 return nil
329}
330
331// SubmoduleUpdateOptions describes how a submodule update should be performed.
332type SubmoduleUpdateOptions struct {
333 // Init, if true initializes the submodules recorded in the index.
334 Init bool
335 // NoFetch tell to the update command to not fetch new objects from the
336 // remote site.
337 NoFetch bool
338 // RecurseSubmodules the update is performed not only in the submodules of
339 // the current repository but also in any nested submodules inside those
340 // submodules (and so on). Until the SubmoduleRecursivity is reached.
341 RecurseSubmodules SubmoduleRecursivity
342 // Auth credentials, if required, to use with the remote repository.
343 Auth transport.AuthMethod
344 // Depth limit fetching to the specified number of commits from the tip of
345 // each remote branch history.
346 Depth int
347}
348
349var (
350 ErrBranchHashExclusive = errors.New("Branch and Hash are mutually exclusive")
351 ErrCreateRequiresBranch = errors.New("Branch is mandatory when Create is used")
352)
353
354// CheckoutOptions describes how a checkout operation should be performed.
355type CheckoutOptions struct {
356 // Hash is the hash of a commit or tag to be checked out. If used, HEAD
357 // will be in detached mode. If Create is not used, Branch and Hash are
358 // mutually exclusive.
359 Hash plumbing.Hash
360 // Branch to be checked out, if Branch and Hash are empty is set to `master`.
361 Branch plumbing.ReferenceName
362 // Create a new branch named Branch and start it at Hash.
363 Create bool
364 // Force, if true when switching branches, proceed even if the index or the
365 // working tree differs from HEAD. This is used to throw away local changes
366 Force bool
367 // Keep, if true when switching branches, local changes (the index or the
368 // working tree changes) will be kept so that they can be committed to the
369 // target branch. Force and Keep are mutually exclusive, should not be both
370 // set to true.
371 Keep bool
372 // SparseCheckoutDirectories
373 SparseCheckoutDirectories []string
374}
375
376// Validate validates the fields and sets the default values.
377func (o *CheckoutOptions) Validate() error {
378 if !o.Create && !o.Hash.IsZero() && o.Branch != "" {
379 return ErrBranchHashExclusive
380 }
381
382 if o.Create && o.Branch == "" {
383 return ErrCreateRequiresBranch
384 }
385
386 if o.Branch == "" {
387 o.Branch = plumbing.Master
388 }
389
390 return nil
391}
392
393// ResetMode defines the mode of a reset operation.
394type ResetMode int8
395
396const (
397 // MixedReset resets the index but not the working tree (i.e., the changed
398 // files are preserved but not marked for commit) and reports what has not
399 // been updated. This is the default action.
400 MixedReset ResetMode = iota
401 // HardReset resets the index and working tree. Any changes to tracked files
402 // in the working tree are discarded.
403 HardReset
404 // MergeReset resets the index and updates the files in the working tree
405 // that are different between Commit and HEAD, but keeps those which are
406 // different between the index and working tree (i.e. which have changes
407 // which have not been added).
408 //
409 // If a file that is different between Commit and the index has unstaged
410 // changes, reset is aborted.
411 MergeReset
412 // SoftReset does not touch the index file or the working tree at all (but
413 // resets the head to <commit>, just like all modes do). This leaves all
414 // your changed files "Changes to be committed", as git status would put it.
415 SoftReset
416)
417
418// ResetOptions describes how a reset operation should be performed.
419type ResetOptions struct {
420 // Commit, if commit is present set the current branch head (HEAD) to it.
421 Commit plumbing.Hash
422 // Mode, form resets the current branch head to Commit and possibly updates
423 // the index (resetting it to the tree of Commit) and the working tree
424 // depending on Mode. If empty MixedReset is used.
425 Mode ResetMode
426 // Files, if not empty will constrain the reseting the index to only files
427 // specified in this list.
428 Files []string
429}
430
431// Validate validates the fields and sets the default values.
432func (o *ResetOptions) Validate(r *Repository) error {
433 if o.Commit == plumbing.ZeroHash {
434 ref, err := r.Head()
435 if err != nil {
436 return err
437 }
438
439 o.Commit = ref.Hash()
440 } else {
441 _, err := r.CommitObject(o.Commit)
442 if err != nil {
443 return fmt.Errorf("invalid reset option: %w", err)
444 }
445 }
446
447 return nil
448}
449
450type LogOrder int8
451
452const (
453 LogOrderDefault LogOrder = iota
454 LogOrderDFS
455 LogOrderDFSPost
456 LogOrderBSF
457 LogOrderCommitterTime
458)
459
460// LogOptions describes how a log action should be performed.
461type LogOptions struct {
462 // When the From option is set the log will only contain commits
463 // reachable from it. If this option is not set, HEAD will be used as
464 // the default From.
465 From plumbing.Hash
466
467 // When To is set the log will go down until it reaches to the commit with the
468 // specified hash. The default value for this field in nil
469 To plumbing.Hash
470
471 // The default traversal algorithm is Depth-first search
472 // set Order=LogOrderCommitterTime for ordering by committer time (more compatible with `git log`)
473 // set Order=LogOrderBSF for Breadth-first search
474 Order LogOrder
475
476 // Show only those commits in which the specified file was inserted/updated.
477 // It is equivalent to running `git log -- <file-name>`.
478 // this field is kept for compatibility, it can be replaced with PathFilter
479 FileName *string
480
481 // Filter commits based on the path of files that are updated
482 // takes file path as argument and should return true if the file is desired
483 // It can be used to implement `git log -- <path>`
484 // either <path> is a file path, or directory path, or a regexp of file/directory path
485 PathFilter func(string) bool
486
487 // Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as <commit>.
488 // It is equivalent to running `git log --all`.
489 // If set on true, the From option will be ignored.
490 All bool
491
492 // Show commits more recent than a specific date.
493 // It is equivalent to running `git log --since <date>` or `git log --after <date>`.
494 Since *time.Time
495
496 // Show commits older than a specific date.
497 // It is equivalent to running `git log --until <date>` or `git log --before <date>`.
498 Until *time.Time
499}
500
501var ErrMissingAuthor = errors.New("author field is required")
502
503// AddOptions describes how an `add` operation should be performed
504type AddOptions struct {
505 // All equivalent to `git add -A`, update the index not only where the
506 // working tree has a file matching `Path` but also where the index already
507 // has an entry. This adds, modifies, and removes index entries to match the
508 // working tree. If no `Path` nor `Glob` is given when `All` option is
509 // used, all files in the entire working tree are updated.
510 All bool
511 // Path is the exact filepath to the file or directory to be added.
512 Path string
513 // Glob adds all paths, matching pattern, to the index. If pattern matches a
514 // directory path, all directory contents are added to the index recursively.
515 Glob string
516 // SkipStatus adds the path with no status check. This option is relevant only
517 // when the `Path` option is specified and does not apply when the `All` option is used.
518 // Notice that when passing an ignored path it will be added anyway.
519 // When true it can speed up adding files to the worktree in very large repositories.
520 SkipStatus bool
521}
522
523// Validate validates the fields and sets the default values.
524func (o *AddOptions) Validate(r *Repository) error {
525 if o.Path != "" && o.Glob != "" {
526 return fmt.Errorf("fields Path and Glob are mutual exclusive")
527 }
528
529 return nil
530}
531
532// CommitOptions describes how a commit operation should be performed.
533type CommitOptions struct {
534 // All automatically stage files that have been modified and deleted, but
535 // new files you have not told Git about are not affected.
536 All bool
537 // AllowEmptyCommits enable empty commits to be created. An empty commit
538 // is when no changes to the tree were made, but a new commit message is
539 // provided. The default behavior is false, which results in ErrEmptyCommit.
540 AllowEmptyCommits bool
541 // Author is the author's signature of the commit. If Author is empty the
542 // Name and Email is read from the config, and time.Now it's used as When.
543 Author *object.Signature
544 // Committer is the committer's signature of the commit. If Committer is
545 // nil the Author signature is used.
546 Committer *object.Signature
547 // Parents are the parents commits for the new commit, by default when
548 // len(Parents) is zero, the hash of HEAD reference is used.
549 Parents []plumbing.Hash
550 // SignKey denotes a key to sign the commit with. A nil value here means the
551 // commit will not be signed. The private key must be present and already
552 // decrypted.
553 SignKey *openpgp.Entity
554 // Signer denotes a cryptographic signer to sign the commit with.
555 // A nil value here means the commit will not be signed.
556 // Takes precedence over SignKey.
557 Signer Signer
558 // Amend will create a new commit object and replace the commit that HEAD currently
559 // points to. Cannot be used with All nor Parents.
560 Amend bool
561}
562
563// Validate validates the fields and sets the default values.
564func (o *CommitOptions) Validate(r *Repository) error {
565 if o.All && o.Amend {
566 return errors.New("all and amend cannot be used together")
567 }
568
569 if o.Amend && len(o.Parents) > 0 {
570 return errors.New("parents cannot be used with amend")
571 }
572
573 if o.Author == nil {
574 if err := o.loadConfigAuthorAndCommitter(r); err != nil {
575 return err
576 }
577 }
578
579 if o.Committer == nil {
580 o.Committer = o.Author
581 }
582
583 if len(o.Parents) == 0 {
584 head, err := r.Head()
585 if err != nil && err != plumbing.ErrReferenceNotFound {
586 return err
587 }
588
589 if head != nil {
590 o.Parents = []plumbing.Hash{head.Hash()}
591 }
592 }
593
594 return nil
595}
596
597func (o *CommitOptions) loadConfigAuthorAndCommitter(r *Repository) error {
598 cfg, err := r.ConfigScoped(config.SystemScope)
599 if err != nil {
600 return err
601 }
602
603 if o.Author == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
604 o.Author = &object.Signature{
605 Name: cfg.Author.Name,
606 Email: cfg.Author.Email,
607 When: time.Now(),
608 }
609 }
610
611 if o.Committer == nil && cfg.Committer.Email != "" && cfg.Committer.Name != "" {
612 o.Committer = &object.Signature{
613 Name: cfg.Committer.Name,
614 Email: cfg.Committer.Email,
615 When: time.Now(),
616 }
617 }
618
619 if o.Author == nil && cfg.User.Email != "" && cfg.User.Name != "" {
620 o.Author = &object.Signature{
621 Name: cfg.User.Name,
622 Email: cfg.User.Email,
623 When: time.Now(),
624 }
625 }
626
627 if o.Author == nil {
628 return ErrMissingAuthor
629 }
630
631 return nil
632}
633
634var (
635 ErrMissingName = errors.New("name field is required")
636 ErrMissingTagger = errors.New("tagger field is required")
637 ErrMissingMessage = errors.New("message field is required")
638)
639
640// CreateTagOptions describes how a tag object should be created.
641type CreateTagOptions struct {
642 // Tagger defines the signature of the tag creator. If Tagger is empty the
643 // Name and Email is read from the config, and time.Now it's used as When.
644 Tagger *object.Signature
645 // Message defines the annotation of the tag. It is canonicalized during
646 // validation into the format expected by git - no leading whitespace and
647 // ending in a newline.
648 Message string
649 // SignKey denotes a key to sign the tag with. A nil value here means the tag
650 // will not be signed. The private key must be present and already decrypted.
651 SignKey *openpgp.Entity
652}
653
654// Validate validates the fields and sets the default values.
655func (o *CreateTagOptions) Validate(r *Repository, hash plumbing.Hash) error {
656 if o.Tagger == nil {
657 if err := o.loadConfigTagger(r); err != nil {
658 return err
659 }
660 }
661
662 if o.Message == "" {
663 return ErrMissingMessage
664 }
665
666 // Canonicalize the message into the expected message format.
667 o.Message = strings.TrimSpace(o.Message) + "\n"
668
669 return nil
670}
671
672func (o *CreateTagOptions) loadConfigTagger(r *Repository) error {
673 cfg, err := r.ConfigScoped(config.SystemScope)
674 if err != nil {
675 return err
676 }
677
678 if o.Tagger == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
679 o.Tagger = &object.Signature{
680 Name: cfg.Author.Name,
681 Email: cfg.Author.Email,
682 When: time.Now(),
683 }
684 }
685
686 if o.Tagger == nil && cfg.User.Email != "" && cfg.User.Name != "" {
687 o.Tagger = &object.Signature{
688 Name: cfg.User.Name,
689 Email: cfg.User.Email,
690 When: time.Now(),
691 }
692 }
693
694 if o.Tagger == nil {
695 return ErrMissingTagger
696 }
697
698 return nil
699}
700
701// ListOptions describes how a remote list should be performed.
702type ListOptions struct {
703 // Auth credentials, if required, to use with the remote repository.
704 Auth transport.AuthMethod
705 // InsecureSkipTLS skips ssl verify if protocol is https
706 InsecureSkipTLS bool
707 // CABundle specify additional ca bundle with system cert pool
708 CABundle []byte
709 // PeelingOption defines how peeled objects are handled during a
710 // remote list.
711 PeelingOption PeelingOption
712 // ProxyOptions provides info required for connecting to a proxy.
713 ProxyOptions transport.ProxyOptions
714 // Timeout specifies the timeout in seconds for list operations
715 Timeout int
716}
717
718// PeelingOption represents the different ways to handle peeled references.
719//
720// Peeled references represent the underlying object of an annotated
721// (or signed) tag. Refer to upstream documentation for more info:
722// https://github.com/git/git/blob/master/Documentation/technical/reftable.txt
723type PeelingOption uint8
724
725const (
726 // IgnorePeeled ignores all peeled reference names. This is the default behavior.
727 IgnorePeeled PeelingOption = 0
728 // OnlyPeeled returns only peeled reference names.
729 OnlyPeeled PeelingOption = 1
730 // AppendPeeled appends peeled reference names to the reference list.
731 AppendPeeled PeelingOption = 2
732)
733
734// CleanOptions describes how a clean should be performed.
735type CleanOptions struct {
736 Dir bool
737}
738
739// GrepOptions describes how a grep should be performed.
740type GrepOptions struct {
741 // Patterns are compiled Regexp objects to be matched.
742 Patterns []*regexp.Regexp
743 // InvertMatch selects non-matching lines.
744 InvertMatch bool
745 // CommitHash is the hash of the commit from which worktree should be derived.
746 CommitHash plumbing.Hash
747 // ReferenceName is the branch or tag name from which worktree should be derived.
748 ReferenceName plumbing.ReferenceName
749 // PathSpecs are compiled Regexp objects of pathspec to use in the matching.
750 PathSpecs []*regexp.Regexp
751}
752
753var ErrHashOrReference = errors.New("ambiguous options, only one of CommitHash or ReferenceName can be passed")
754
755// Validate validates the fields and sets the default values.
756//
757// TODO: deprecate in favor of Validate(r *Repository) in v6.
758func (o *GrepOptions) Validate(w *Worktree) error {
759 return o.validate(w.r)
760}
761
762func (o *GrepOptions) validate(r *Repository) error {
763 if !o.CommitHash.IsZero() && o.ReferenceName != "" {
764 return ErrHashOrReference
765 }
766
767 // If none of CommitHash and ReferenceName are provided, set commit hash of
768 // the repository's head.
769 if o.CommitHash.IsZero() && o.ReferenceName == "" {
770 ref, err := r.Head()
771 if err != nil {
772 return err
773 }
774 o.CommitHash = ref.Hash()
775 }
776
777 return nil
778}
779
780// PlainOpenOptions describes how opening a plain repository should be
781// performed.
782type PlainOpenOptions struct {
783 // DetectDotGit defines whether parent directories should be
784 // walked until a .git directory or file is found.
785 DetectDotGit bool
786 // Enable .git/commondir support (see https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt).
787 // NOTE: This option will only work with the filesystem storage.
788 EnableDotGitCommonDir bool
789}
790
791// Validate validates the fields and sets the default values.
792func (o *PlainOpenOptions) Validate() error { return nil }
793
794type PlainInitOptions struct {
795 InitOptions
796 // Determines if the repository will have a worktree (non-bare) or not (bare).
797 Bare bool
798 ObjectFormat formatcfg.ObjectFormat
799}
800
801// Validate validates the fields and sets the default values.
802func (o *PlainInitOptions) Validate() error { return nil }
803
804var ErrNoRestorePaths = errors.New("you must specify path(s) to restore")
805
806// RestoreOptions describes how a restore should be performed.
807type RestoreOptions struct {
808 // Marks to restore the content in the index
809 Staged bool
810 // Marks to restore the content of the working tree
811 Worktree bool
812 // List of file paths that will be restored
813 Files []string
814}
815
816// Validate validates the fields and sets the default values.
817func (o *RestoreOptions) Validate() error {
818 if len(o.Files) == 0 {
819 return ErrNoRestorePaths
820 }
821
822 return nil
823}