github.com/purpleclay/gitz@v0.8.2-0.20240515052600-43f80eea2fe1/fetch.go (about) 1 package git 2 3 import ( 4 "strconv" 5 "strings" 6 ) 7 8 // FetchOption provides a way for setting specific options while fetching changes 9 // from the remote. Each supported option can customize how changes are fetched 10 // from the remote 11 type FetchOption func(*fetchOptions) 12 13 type fetchOptions struct { 14 All bool 15 Config []string 16 Depth int 17 Force bool 18 NoTags bool 19 RefSpecs []string 20 Tags bool 21 } 22 23 func (o fetchOptions) String() string { 24 var buf strings.Builder 25 26 if o.All { 27 buf.WriteString(" --all") 28 } 29 30 if o.Depth > 0 { 31 buf.WriteString(" --depth ") 32 buf.WriteString(strconv.Itoa(o.Depth)) 33 } 34 35 if o.Tags { 36 buf.WriteString(" --tags") 37 } 38 39 if o.Force { 40 buf.WriteString(" --force") 41 } 42 43 if o.NoTags { 44 buf.WriteString(" --no-tags") 45 } 46 47 if len(o.RefSpecs) > 0 { 48 buf.WriteString(" origin ") 49 buf.WriteString(strings.Join(o.RefSpecs, " ")) 50 } 51 52 return buf.String() 53 } 54 55 // WithFetchConfig allows temporary git config to be set while fetching 56 // changes from the remote. Config set using this approach will override 57 // any config defined within existing git config files. Config must be 58 // provided as key value pairs, mismatched config will result in an 59 // [ErrMissingConfigValue] error. Any invalid paths will result in an 60 // [ErrInvalidConfigPath] error 61 func WithFetchConfig(kv ...string) FetchOption { 62 return func(opts *fetchOptions) { 63 opts.Config = trim(kv...) 64 } 65 } 66 67 // WithAll will fetch the latest changes from all tracked remotes 68 func WithAll() FetchOption { 69 return func(opts *fetchOptions) { 70 opts.All = true 71 } 72 } 73 74 // WithTags will fetch all tags from the remote into local tag 75 // references with the same name 76 func WithTags() FetchOption { 77 return func(opts *fetchOptions) { 78 opts.Tags = true 79 } 80 } 81 82 // WithDepthTo will limit the number of commits to be fetched from the 83 // remotes history to the specified depth. If fetching into a shallow 84 // clone of a repository, this can be used to shorten or deepen the 85 // existing history 86 func WithDepthTo(depth int) FetchOption { 87 return func(opts *fetchOptions) { 88 opts.Depth = depth 89 } 90 } 91 92 // WithForce will force the fetching of a remote branch into a local 93 // branch with a different name (or refspec). Default behavior within 94 // git prevents such an operation. Typically used in conjunction with 95 // the [WithFetchRefSpecs] option 96 func WithForce() FetchOption { 97 return func(opts *fetchOptions) { 98 opts.Force = true 99 } 100 } 101 102 // WithIgnoreTags disables local tracking of tags from the remote 103 func WithIgnoreTags() FetchOption { 104 return func(opts *fetchOptions) { 105 opts.NoTags = true 106 } 107 } 108 109 // WithFetchRefSpecs allows remote references to be cherry-picked and 110 // fetched into the current repository (working copy). A reference 111 // (or refspec) can be as simple as a name, where git will automatically 112 // resolve any ambiguity, or as explicit as providing a source and destination 113 // for reference within the remote. Check out the official git documentation 114 // on how to write a more complex [refspec] 115 // [refspec]: https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt 116 func WithFetchRefSpecs(refs ...string) FetchOption { 117 return func(opts *fetchOptions) { 118 opts.RefSpecs = trim(refs...) 119 } 120 } 121 122 // Fetch all remote changes from a remote repository without integrating (merging) 123 // them into the current repository (working directory). Ensures the current repository 124 // only tracks the latest remote changes 125 func (c *Client) Fetch(opts ...FetchOption) (string, error) { 126 options := &fetchOptions{} 127 for _, opt := range opts { 128 opt(options) 129 } 130 131 cfg, err := ToInlineConfig(options.Config...) 132 if err != nil { 133 return "", err 134 } 135 136 var buf strings.Builder 137 buf.WriteString("git") 138 139 if len(cfg) > 0 { 140 buf.WriteString(" ") 141 buf.WriteString(strings.Join(cfg, " ")) 142 } 143 144 buf.WriteString(" fetch") 145 buf.WriteString(options.String()) 146 return c.exec(buf.String()) 147 }