fork of go-git with some jj specific features
at main 28 kB view raw
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}