git 1.19.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -1
  3. data/AI_POLICY.md +24 -0
  4. data/CHANGELOG.md +689 -0
  5. data/CODE_OF_CONDUCT.md +25 -0
  6. data/CONTRIBUTING.md +1175 -97
  7. data/GOVERNANCE.md +106 -0
  8. data/LICENSE +1 -1
  9. data/MAINTAINERS.md +17 -4
  10. data/README.md +476 -320
  11. data/UPGRADING.md +1138 -0
  12. data/git.gemspec +124 -36
  13. data/lib/git/author.rb +39 -7
  14. data/lib/git/author_info.rb +66 -0
  15. data/lib/git/branch.rb +615 -65
  16. data/lib/git/branch_delete_failure.rb +34 -0
  17. data/lib/git/branch_delete_result.rb +66 -0
  18. data/lib/git/branch_info.rb +237 -0
  19. data/lib/git/branches.rb +167 -44
  20. data/lib/git/command_line/base.rb +247 -0
  21. data/lib/git/command_line/capturing.rb +308 -0
  22. data/lib/git/command_line/result.rb +88 -0
  23. data/lib/git/command_line/streaming.rb +236 -0
  24. data/lib/git/command_line.rb +52 -0
  25. data/lib/git/commands/add.rb +139 -0
  26. data/lib/git/commands/am/abort.rb +43 -0
  27. data/lib/git/commands/am/apply.rb +263 -0
  28. data/lib/git/commands/am/continue.rb +43 -0
  29. data/lib/git/commands/am/quit.rb +43 -0
  30. data/lib/git/commands/am/retry.rb +49 -0
  31. data/lib/git/commands/am/show_current_patch.rb +64 -0
  32. data/lib/git/commands/am/skip.rb +42 -0
  33. data/lib/git/commands/am.rb +33 -0
  34. data/lib/git/commands/apply.rb +242 -0
  35. data/lib/git/commands/archive/list_formats.rb +46 -0
  36. data/lib/git/commands/archive.rb +145 -0
  37. data/lib/git/commands/arguments.rb +4521 -0
  38. data/lib/git/commands/base.rb +502 -0
  39. data/lib/git/commands/branch/copy.rb +102 -0
  40. data/lib/git/commands/branch/create.rb +177 -0
  41. data/lib/git/commands/branch/delete.rb +88 -0
  42. data/lib/git/commands/branch/list.rb +178 -0
  43. data/lib/git/commands/branch/move.rb +102 -0
  44. data/lib/git/commands/branch/set_upstream.rb +86 -0
  45. data/lib/git/commands/branch/show_current.rb +49 -0
  46. data/lib/git/commands/branch/unset_upstream.rb +53 -0
  47. data/lib/git/commands/branch.rb +34 -0
  48. data/lib/git/commands/cat_file/batch.rb +385 -0
  49. data/lib/git/commands/cat_file/filtered.rb +105 -0
  50. data/lib/git/commands/cat_file/raw.rb +271 -0
  51. data/lib/git/commands/cat_file.rb +49 -0
  52. data/lib/git/commands/checkout/branch.rb +153 -0
  53. data/lib/git/commands/checkout/files.rb +116 -0
  54. data/lib/git/commands/checkout.rb +38 -0
  55. data/lib/git/commands/checkout_index.rb +106 -0
  56. data/lib/git/commands/clean.rb +102 -0
  57. data/lib/git/commands/clone.rb +241 -0
  58. data/lib/git/commands/commit.rb +273 -0
  59. data/lib/git/commands/commit_tree.rb +101 -0
  60. data/lib/git/commands/config_option_syntax/add.rb +86 -0
  61. data/lib/git/commands/config_option_syntax/get.rb +121 -0
  62. data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
  63. data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
  64. data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
  65. data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
  66. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
  67. data/lib/git/commands/config_option_syntax/list.rb +111 -0
  68. data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
  69. data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
  70. data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
  71. data/lib/git/commands/config_option_syntax/set.rb +119 -0
  72. data/lib/git/commands/config_option_syntax/unset.rb +92 -0
  73. data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
  74. data/lib/git/commands/config_option_syntax.rb +56 -0
  75. data/lib/git/commands/describe.rb +156 -0
  76. data/lib/git/commands/diff.rb +657 -0
  77. data/lib/git/commands/diff_files.rb +519 -0
  78. data/lib/git/commands/diff_index.rb +499 -0
  79. data/lib/git/commands/fetch.rb +354 -0
  80. data/lib/git/commands/fsck.rb +138 -0
  81. data/lib/git/commands/gc.rb +134 -0
  82. data/lib/git/commands/grep.rb +339 -0
  83. data/lib/git/commands/init.rb +101 -0
  84. data/lib/git/commands/log.rb +634 -0
  85. data/lib/git/commands/ls_files.rb +195 -0
  86. data/lib/git/commands/ls_remote.rb +161 -0
  87. data/lib/git/commands/ls_tree.rb +135 -0
  88. data/lib/git/commands/maintenance/register.rb +77 -0
  89. data/lib/git/commands/maintenance/run.rb +109 -0
  90. data/lib/git/commands/maintenance/start.rb +71 -0
  91. data/lib/git/commands/maintenance/stop.rb +60 -0
  92. data/lib/git/commands/maintenance/unregister.rb +84 -0
  93. data/lib/git/commands/maintenance.rb +31 -0
  94. data/lib/git/commands/merge/abort.rb +44 -0
  95. data/lib/git/commands/merge/continue.rb +44 -0
  96. data/lib/git/commands/merge/quit.rb +46 -0
  97. data/lib/git/commands/merge/start.rb +250 -0
  98. data/lib/git/commands/merge.rb +28 -0
  99. data/lib/git/commands/merge_base.rb +91 -0
  100. data/lib/git/commands/mv.rb +82 -0
  101. data/lib/git/commands/name_rev.rb +119 -0
  102. data/lib/git/commands/pull.rb +382 -0
  103. data/lib/git/commands/push.rb +251 -0
  104. data/lib/git/commands/read_tree.rb +154 -0
  105. data/lib/git/commands/remote/add.rb +96 -0
  106. data/lib/git/commands/remote/get_url.rb +68 -0
  107. data/lib/git/commands/remote/list.rb +56 -0
  108. data/lib/git/commands/remote/prune.rb +63 -0
  109. data/lib/git/commands/remote/remove.rb +52 -0
  110. data/lib/git/commands/remote/rename.rb +76 -0
  111. data/lib/git/commands/remote/set_branches.rb +70 -0
  112. data/lib/git/commands/remote/set_head.rb +89 -0
  113. data/lib/git/commands/remote/set_url.rb +78 -0
  114. data/lib/git/commands/remote/set_url_add.rb +70 -0
  115. data/lib/git/commands/remote/set_url_delete.rb +71 -0
  116. data/lib/git/commands/remote/show.rb +77 -0
  117. data/lib/git/commands/remote/update.rb +79 -0
  118. data/lib/git/commands/remote.rb +42 -0
  119. data/lib/git/commands/repack.rb +281 -0
  120. data/lib/git/commands/reset.rb +154 -0
  121. data/lib/git/commands/rev_parse.rb +304 -0
  122. data/lib/git/commands/revert/abort.rb +45 -0
  123. data/lib/git/commands/revert/continue.rb +62 -0
  124. data/lib/git/commands/revert/quit.rb +47 -0
  125. data/lib/git/commands/revert/skip.rb +44 -0
  126. data/lib/git/commands/revert/start.rb +158 -0
  127. data/lib/git/commands/revert.rb +29 -0
  128. data/lib/git/commands/rm.rb +113 -0
  129. data/lib/git/commands/show.rb +632 -0
  130. data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
  131. data/lib/git/commands/show_ref/exists.rb +80 -0
  132. data/lib/git/commands/show_ref/list.rb +149 -0
  133. data/lib/git/commands/show_ref/verify.rb +122 -0
  134. data/lib/git/commands/show_ref.rb +42 -0
  135. data/lib/git/commands/stash/apply.rb +81 -0
  136. data/lib/git/commands/stash/branch.rb +67 -0
  137. data/lib/git/commands/stash/clear.rb +43 -0
  138. data/lib/git/commands/stash/create.rb +60 -0
  139. data/lib/git/commands/stash/drop.rb +73 -0
  140. data/lib/git/commands/stash/list.rb +43 -0
  141. data/lib/git/commands/stash/pop.rb +87 -0
  142. data/lib/git/commands/stash/push.rb +112 -0
  143. data/lib/git/commands/stash/show.rb +158 -0
  144. data/lib/git/commands/stash/store.rb +72 -0
  145. data/lib/git/commands/stash.rb +38 -0
  146. data/lib/git/commands/status.rb +174 -0
  147. data/lib/git/commands/symbolic_ref/delete.rb +72 -0
  148. data/lib/git/commands/symbolic_ref/read.rb +99 -0
  149. data/lib/git/commands/symbolic_ref/update.rb +79 -0
  150. data/lib/git/commands/symbolic_ref.rb +38 -0
  151. data/lib/git/commands/tag/create.rb +142 -0
  152. data/lib/git/commands/tag/delete.rb +57 -0
  153. data/lib/git/commands/tag/list.rb +146 -0
  154. data/lib/git/commands/tag/verify.rb +71 -0
  155. data/lib/git/commands/tag.rb +26 -0
  156. data/lib/git/commands/update_ref/batch.rb +145 -0
  157. data/lib/git/commands/update_ref/delete.rb +90 -0
  158. data/lib/git/commands/update_ref/update.rb +103 -0
  159. data/lib/git/commands/update_ref.rb +42 -0
  160. data/lib/git/commands/version.rb +60 -0
  161. data/lib/git/commands/worktree/add.rb +139 -0
  162. data/lib/git/commands/worktree/list.rb +64 -0
  163. data/lib/git/commands/worktree/lock.rb +58 -0
  164. data/lib/git/commands/worktree/management_base.rb +51 -0
  165. data/lib/git/commands/worktree/move.rb +66 -0
  166. data/lib/git/commands/worktree/prune.rb +67 -0
  167. data/lib/git/commands/worktree/remove.rb +63 -0
  168. data/lib/git/commands/worktree/repair.rb +76 -0
  169. data/lib/git/commands/worktree/unlock.rb +47 -0
  170. data/lib/git/commands/worktree.rb +43 -0
  171. data/lib/git/commands/write_tree.rb +68 -0
  172. data/lib/git/commands.rb +88 -0
  173. data/lib/git/config.rb +72 -5
  174. data/lib/git/config_entry_info.rb +106 -0
  175. data/lib/git/configuring.rb +795 -0
  176. data/lib/git/detached_head_info.rb +57 -0
  177. data/lib/git/diff.rb +437 -86
  178. data/lib/git/diff_file_numstat_info.rb +31 -0
  179. data/lib/git/diff_file_patch_info.rb +136 -0
  180. data/lib/git/diff_file_raw_info.rb +129 -0
  181. data/lib/git/diff_info.rb +162 -0
  182. data/lib/git/diff_path_status.rb +107 -0
  183. data/lib/git/diff_result.rb +34 -0
  184. data/lib/git/diff_stats.rb +111 -0
  185. data/lib/git/dirstat_info.rb +102 -0
  186. data/lib/git/encoding_utils.rb +32 -1
  187. data/lib/git/errors.rb +285 -0
  188. data/lib/git/escaped_path.rb +57 -5
  189. data/lib/git/execution_context/global.rb +31 -0
  190. data/lib/git/execution_context/repository.rb +151 -0
  191. data/lib/git/execution_context.rb +559 -0
  192. data/lib/git/factories.rb +813 -0
  193. data/lib/git/file_ref.rb +77 -0
  194. data/lib/git/fsck_object.rb +56 -0
  195. data/lib/git/fsck_result.rb +132 -0
  196. data/lib/git/log.rb +306 -90
  197. data/lib/git/object.rb +563 -141
  198. data/lib/git/parsers/branch.rb +240 -0
  199. data/lib/git/parsers/cat_file.rb +111 -0
  200. data/lib/git/parsers/config_entry.rb +110 -0
  201. data/lib/git/parsers/diff.rb +792 -0
  202. data/lib/git/parsers/fsck.rb +144 -0
  203. data/lib/git/parsers/grep.rb +42 -0
  204. data/lib/git/parsers/ls_remote.rb +79 -0
  205. data/lib/git/parsers/ls_tree.rb +58 -0
  206. data/lib/git/parsers/remote.rb +162 -0
  207. data/lib/git/parsers/stash.rb +292 -0
  208. data/lib/git/parsers/status.rb +251 -0
  209. data/lib/git/parsers/tag.rb +341 -0
  210. data/lib/git/parsers/worktree.rb +185 -0
  211. data/lib/git/path_resolver.rb +206 -0
  212. data/lib/git/remote.rb +165 -12
  213. data/lib/git/remote_info.rb +203 -0
  214. data/lib/git/repository/branching.rb +964 -0
  215. data/lib/git/repository/committing.rb +246 -0
  216. data/lib/git/repository/context_helpers.rb +293 -0
  217. data/lib/git/repository/diffing.rb +785 -0
  218. data/lib/git/repository/inspecting.rb +252 -0
  219. data/lib/git/repository/logging.rb +410 -0
  220. data/lib/git/repository/maintenance.rb +65 -0
  221. data/lib/git/repository/merging.rb +451 -0
  222. data/lib/git/repository/object_operations.rb +1551 -0
  223. data/lib/git/repository/remote_operations.rb +984 -0
  224. data/lib/git/repository/shared_private.rb +120 -0
  225. data/lib/git/repository/staging.rb +587 -0
  226. data/lib/git/repository/stashing.rb +623 -0
  227. data/lib/git/repository/status_operations.rb +249 -0
  228. data/lib/git/repository/worktree_operations.rb +339 -0
  229. data/lib/git/repository.rb +484 -2
  230. data/lib/git/stash.rb +109 -12
  231. data/lib/git/stash_info.rb +102 -0
  232. data/lib/git/stashes.rb +169 -26
  233. data/lib/git/status.rb +308 -122
  234. data/lib/git/status_file_info.rb +258 -0
  235. data/lib/git/status_info.rb +189 -0
  236. data/lib/git/tag_delete_failure.rb +34 -0
  237. data/lib/git/tag_delete_result.rb +66 -0
  238. data/lib/git/tag_info.rb +99 -0
  239. data/lib/git/url.rb +15 -8
  240. data/lib/git/version.rb +113 -2
  241. data/lib/git/version_constraint.rb +85 -0
  242. data/lib/git/worktree.rb +150 -8
  243. data/lib/git/worktree_info.rb +128 -0
  244. data/lib/git/worktrees.rb +118 -13
  245. data/lib/git.rb +632 -234
  246. metadata +369 -54
  247. data/.github/stale.yml +0 -25
  248. data/.github/workflows/continuous_integration.yml +0 -49
  249. data/.gitignore +0 -10
  250. data/Dockerfile.changelog-rs +0 -12
  251. data/Gemfile +0 -5
  252. data/ISSUE_TEMPLATE.md +0 -15
  253. data/PULL_REQUEST_TEMPLATE.md +0 -9
  254. data/RELEASING.md +0 -70
  255. data/Rakefile +0 -60
  256. data/lib/git/base/factory.rb +0 -99
  257. data/lib/git/base.rb +0 -711
  258. data/lib/git/command_line_result.rb +0 -86
  259. data/lib/git/failed_error.rb +0 -53
  260. data/lib/git/git_execute_error.rb +0 -7
  261. data/lib/git/index.rb +0 -5
  262. data/lib/git/lib.rb +0 -1328
  263. data/lib/git/path.rb +0 -31
  264. data/lib/git/signaled_error.rb +0 -50
  265. data/lib/git/working_directory.rb +0 -4
data/lib/git/base.rb DELETED
@@ -1,711 +0,0 @@
1
- require 'git/base/factory'
2
- require 'logger'
3
- require 'open3'
4
-
5
- module Git
6
- # Git::Base is the main public interface for interacting with Git commands.
7
- #
8
- # Instead of creating a Git::Base directly, obtain a Git::Base instance by
9
- # calling one of the follow {Git} class methods: {Git.open}, {Git.init},
10
- # {Git.clone}, or {Git.bare}.
11
- #
12
- class Base
13
- include Git::Base::Factory
14
-
15
- # (see Git.bare)
16
- def self.bare(git_dir, options = {})
17
- normalize_paths(options, default_repository: git_dir, bare: true)
18
- self.new(options)
19
- end
20
-
21
- # (see Git.clone)
22
- def self.clone(repository_url, directory, options = {})
23
- new_options = Git::Lib.new(nil, options[:log]).clone(repository_url, directory, options)
24
- normalize_paths(new_options, bare: options[:bare] || options[:mirror])
25
- new(new_options)
26
- end
27
-
28
- # (see Git.default_branch)
29
- def self.repository_default_branch(repository, options = {})
30
- Git::Lib.new(nil, options[:log]).repository_default_branch(repository)
31
- end
32
-
33
- # Returns (and initialize if needed) a Git::Config instance
34
- #
35
- # @return [Git::Config] the current config instance.
36
- def self.config
37
- @@config ||= Config.new
38
- end
39
-
40
- # (see Git.init)
41
- def self.init(directory = '.', options = {})
42
- normalize_paths(options, default_working_directory: directory, default_repository: directory, bare: options[:bare])
43
-
44
- init_options = {
45
- :bare => options[:bare],
46
- :initial_branch => options[:initial_branch]
47
- }
48
-
49
- directory = options[:bare] ? options[:repository] : options[:working_directory]
50
- FileUtils.mkdir_p(directory) unless File.exist?(directory)
51
-
52
- # TODO: this dance seems awkward: this creates a Git::Lib so we can call
53
- # init so we can create a new Git::Base which in turn (ultimately)
54
- # creates another/different Git::Lib.
55
- #
56
- # TODO: maybe refactor so this Git::Bare.init does this:
57
- # self.new(opts).init(init_opts) and move all/some of this code into
58
- # Git::Bare#init. This way the init method can be called on any
59
- # repository you have a Git::Base instance for. This would not
60
- # change the existing interface (other than adding to it).
61
- #
62
- Git::Lib.new(options).init(init_options)
63
-
64
- self.new(options)
65
- end
66
-
67
- def self.root_of_worktree(working_dir)
68
- result = working_dir
69
- status = nil
70
-
71
- git_cmd = "#{Git::Base.config.binary_path} -c core.quotePath=true -c color.ui=false rev-parse --show-toplevel 2>&1"
72
- result, status = Open3.capture2(git_cmd, chdir: File.expand_path(working_dir))
73
- result = result.chomp
74
-
75
- raise ArgumentError, "'#{working_dir}' is not in a git working tree" unless status.success?
76
- result
77
- end
78
-
79
- # (see Git.open)
80
- def self.open(working_dir, options = {})
81
- raise ArgumentError, "'#{working_dir}' is not a directory" unless Dir.exist?(working_dir)
82
-
83
- working_dir = root_of_worktree(working_dir) unless options[:repository]
84
-
85
- normalize_paths(options, default_working_directory: working_dir)
86
-
87
- self.new(options)
88
- end
89
-
90
- # Create an object that executes Git commands in the context of a working
91
- # copy or a bare repository.
92
- #
93
- # @param [Hash] options The options for this command (see list of valid
94
- # options below)
95
- #
96
- # @option options [Pathname] :working_dir the path to the root of the working
97
- # directory. Should be `nil` if executing commands on a bare repository.
98
- #
99
- # @option options [Pathname] :repository used to specify a non-standard path to
100
- # the repository directory. The default is `"#{working_dir}/.git"`.
101
- #
102
- # @option options [Pathname] :index used to specify a non-standard path to an
103
- # index file. The default is `"#{working_dir}/.git/index"`
104
- #
105
- # @option options [Logger] :log A logger to use for Git operations. Git
106
- # commands are logged at the `:info` level. Additional logging is done
107
- # at the `:debug` level.
108
- #
109
- # @return [Git::Base] an object that can execute git commands in the context
110
- # of the opened working copy or bare repository
111
- #
112
- def initialize(options = {})
113
- if working_dir = options[:working_directory]
114
- options[:repository] ||= File.join(working_dir, '.git')
115
- options[:index] ||= File.join(options[:repository], 'index')
116
- end
117
- @logger = (options[:log] || Logger.new(nil))
118
- @logger.info("Starting Git")
119
-
120
- @working_directory = options[:working_directory] ? Git::WorkingDirectory.new(options[:working_directory]) : nil
121
- @repository = options[:repository] ? Git::Repository.new(options[:repository]) : nil
122
- @index = options[:index] ? Git::Index.new(options[:index], false) : nil
123
- end
124
-
125
- # changes current working directory for a block
126
- # to the git working directory
127
- #
128
- # example
129
- # @git.chdir do
130
- # # write files
131
- # @git.add
132
- # @git.commit('message')
133
- # end
134
- def chdir # :yields: the Git::Path
135
- Dir.chdir(dir.path) do
136
- yield dir.path
137
- end
138
- end
139
-
140
- #g.config('user.name', 'Scott Chacon') # sets value
141
- #g.config('user.email', 'email@email.com') # sets value
142
- #g.config('user.email', 'email@email.com', file: 'path/to/custom/config) # sets value in file
143
- #g.config('user.name') # returns 'Scott Chacon'
144
- #g.config # returns whole config hash
145
- def config(name = nil, value = nil, options = {})
146
- if name && value
147
- # set value
148
- lib.config_set(name, value, options)
149
- elsif name
150
- # return value
151
- lib.config_get(name)
152
- else
153
- # return hash
154
- lib.config_list
155
- end
156
- end
157
-
158
- # returns a reference to the working directory
159
- # @git.dir.path
160
- # @git.dir.writeable?
161
- def dir
162
- @working_directory
163
- end
164
-
165
- # returns reference to the git index file
166
- def index
167
- @index
168
- end
169
-
170
- # returns reference to the git repository directory
171
- # @git.dir.path
172
- def repo
173
- @repository
174
- end
175
-
176
- # returns the repository size in bytes
177
- def repo_size
178
- Dir.glob(File.join(repo.path, '**', '*'), File::FNM_DOTMATCH).reject do |f|
179
- f.include?('..')
180
- end.map do |f|
181
- File.expand_path(f)
182
- end.uniq.map do |f|
183
- File.stat(f).size.to_i
184
- end.reduce(:+)
185
- end
186
-
187
- def set_index(index_file, check = true)
188
- @lib = nil
189
- @index = Git::Index.new(index_file.to_s, check)
190
- end
191
-
192
- def set_working(work_dir, check = true)
193
- @lib = nil
194
- @working_directory = Git::WorkingDirectory.new(work_dir.to_s, check)
195
- end
196
-
197
- # returns +true+ if the branch exists locally
198
- def is_local_branch?(branch)
199
- branch_names = self.branches.local.map {|b| b.name}
200
- branch_names.include?(branch)
201
- end
202
-
203
- # returns +true+ if the branch exists remotely
204
- def is_remote_branch?(branch)
205
- branch_names = self.branches.remote.map {|b| b.name}
206
- branch_names.include?(branch)
207
- end
208
-
209
- # returns +true+ if the branch exists
210
- def is_branch?(branch)
211
- branch_names = self.branches.map {|b| b.name}
212
- branch_names.include?(branch)
213
- end
214
-
215
- # this is a convenience method for accessing the class that wraps all the
216
- # actual 'git' forked system calls. At some point I hope to replace the Git::Lib
217
- # class with one that uses native methods or libgit C bindings
218
- def lib
219
- @lib ||= Git::Lib.new(self, @logger)
220
- end
221
-
222
- # Run a grep for 'string' on the HEAD of the git repository
223
- #
224
- # @example Limit grep's scope by calling grep() from a specific object:
225
- # git.object("v2.3").grep('TODO')
226
- #
227
- # @example Using grep results:
228
- # git.grep("TODO").each do |sha, arr|
229
- # puts "in blob #{sha}:"
230
- # arr.each do |line_no, match_string|
231
- # puts "\t line #{line_no}: '#{match_string}'"
232
- # end
233
- # end
234
- #
235
- # @param string [String] the string to search for
236
- # @param path_limiter [String, Array] a path or array of paths to limit the search to or nil for no limit
237
- # @param opts [Hash] options to pass to the underlying `git grep` command
238
- #
239
- # @option opts [Boolean] :ignore_case (false) ignore case when matching
240
- # @option opts [Boolean] :invert_match (false) select non-matching lines
241
- # @option opts [Boolean] :extended_regexp (false) use extended regular expressions
242
- # @option opts [String] :object (HEAD) the object to search from
243
- #
244
- # @return [Hash<String, Array>] a hash of arrays
245
- # ```Ruby
246
- # {
247
- # 'tree-ish1' => [[line_no1, match_string1], ...],
248
- # 'tree-ish2' => [[line_no1, match_string1], ...],
249
- # ...
250
- # }
251
- # ```
252
- #
253
- def grep(string, path_limiter = nil, opts = {})
254
- self.object('HEAD').grep(string, path_limiter, opts)
255
- end
256
-
257
- # updates the repository index using the working directory content
258
- #
259
- # @example
260
- # git.add
261
- # git.add('path/to/file')
262
- # git.add(['path/to/file1','path/to/file2'])
263
- # git.add(:all => true)
264
- #
265
- # options:
266
- # :all => true
267
- #
268
- # @param [String,Array] paths files paths to be added (optional, default='.')
269
- # @param [Hash] options
270
- # @option options [boolean] :all
271
- # Update the index not only where the working tree has a file matching
272
- # <pathspec> but also where the index already has an entry.
273
- # See [the --all option to git-add](https://git-scm.com/docs/git-add#Documentation/git-add.txt--A)
274
- # for more details.
275
- #
276
- def add(paths = '.', **options)
277
- self.lib.add(paths, options)
278
- end
279
-
280
- # removes file(s) from the git repository
281
- def rm(path = '.', opts = {})
282
- self.lib.rm(path, opts)
283
- end
284
-
285
- alias remove rm
286
-
287
- # resets the working directory to the provided commitish
288
- def reset(commitish = nil, opts = {})
289
- self.lib.reset(commitish, opts)
290
- end
291
-
292
- # resets the working directory to the commitish with '--hard'
293
- def reset_hard(commitish = nil, opts = {})
294
- opts = {:hard => true}.merge(opts)
295
- self.lib.reset(commitish, opts)
296
- end
297
-
298
- # cleans the working directory
299
- #
300
- # options:
301
- # :force
302
- # :d
303
- # :ff
304
- #
305
- def clean(opts = {})
306
- self.lib.clean(opts)
307
- end
308
-
309
- # returns the most recent tag that is reachable from a commit
310
- #
311
- # options:
312
- # :all
313
- # :tags
314
- # :contains
315
- # :debug
316
- # :exact_match
317
- # :dirty
318
- # :abbrev
319
- # :candidates
320
- # :long
321
- # :always
322
- # :match
323
- #
324
- def describe(committish=nil, opts={})
325
- self.lib.describe(committish, opts)
326
- end
327
-
328
- # reverts the working directory to the provided commitish.
329
- # Accepts a range, such as comittish..HEAD
330
- #
331
- # options:
332
- # :no_edit
333
- #
334
- def revert(commitish = nil, opts = {})
335
- self.lib.revert(commitish, opts)
336
- end
337
-
338
- # commits all pending changes in the index file to the git repository
339
- #
340
- # options:
341
- # :all
342
- # :allow_empty
343
- # :amend
344
- # :author
345
- #
346
- def commit(message, opts = {})
347
- self.lib.commit(message, opts)
348
- end
349
-
350
- # commits all pending changes in the index file to the git repository,
351
- # but automatically adds all modified files without having to explicitly
352
- # calling @git.add() on them.
353
- def commit_all(message, opts = {})
354
- opts = {:add_all => true}.merge(opts)
355
- self.lib.commit(message, opts)
356
- end
357
-
358
- # checks out a branch as the new git working directory
359
- def checkout(*args, **options)
360
- self.lib.checkout(*args, **options)
361
- end
362
-
363
- # checks out an old version of a file
364
- def checkout_file(version, file)
365
- self.lib.checkout_file(version,file)
366
- end
367
-
368
- # fetches changes from a remote branch - this does not modify the working directory,
369
- # it just gets the changes from the remote if there are any
370
- def fetch(remote = 'origin', opts = {})
371
- if remote.is_a?(Hash)
372
- opts = remote
373
- remote = nil
374
- end
375
- self.lib.fetch(remote, opts)
376
- end
377
-
378
- # Push changes to a remote repository
379
- #
380
- # @overload push(remote = nil, branch = nil, options = {})
381
- # @param remote [String] the remote repository to push to
382
- # @param branch [String] the branch to push
383
- # @param options [Hash] options to pass to the push command
384
- #
385
- # @option opts [Boolean] :mirror (false) Push all refs under refs/heads/, refs/tags/ and refs/remotes/
386
- # @option opts [Boolean] :delete (false) Delete refs that don't exist on the remote
387
- # @option opts [Boolean] :force (false) Force updates
388
- # @option opts [Boolean] :tags (false) Push all refs under refs/tags/
389
- # @option opts [Array, String] :push_options (nil) Push options to transmit
390
- #
391
- # @return [Void]
392
- #
393
- # @raise [Git::FailedError] if the push fails
394
- # @raise [ArgumentError] if a branch is given without a remote
395
- #
396
- def push(*args, **options)
397
- self.lib.push(*args, **options)
398
- end
399
-
400
- # merges one or more branches into the current working branch
401
- #
402
- # you can specify more than one branch to merge by passing an array of branches
403
- def merge(branch, message = 'merge', opts = {})
404
- self.lib.merge(branch, message, opts)
405
- end
406
-
407
- # iterates over the files which are unmerged
408
- def each_conflict(&block) # :yields: file, your_version, their_version
409
- self.lib.conflicts(&block)
410
- end
411
-
412
- # pulls the given branch from the given remote into the current branch
413
- #
414
- # @git.pull # pulls from origin/master
415
- # @git.pull('upstream') # pulls from upstream/master
416
- # @git.pull('upstream', 'develope') # pulls from upstream/develop
417
- #
418
- def pull(remote = nil, branch = nil)
419
- self.lib.pull(remote, branch)
420
- end
421
-
422
- # returns an array of Git:Remote objects
423
- def remotes
424
- self.lib.remotes.map { |r| Git::Remote.new(self, r) }
425
- end
426
-
427
- # adds a new remote to this repository
428
- # url can be a git url or a Git::Base object if it's a local reference
429
- #
430
- # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
431
- # @git.fetch('scotts_git')
432
- # @git.merge('scotts_git/master')
433
- #
434
- # Options:
435
- # :fetch => true
436
- # :track => <branch_name>
437
- def add_remote(name, url, opts = {})
438
- url = url.repo.path if url.is_a?(Git::Base)
439
- self.lib.remote_add(name, url, opts)
440
- Git::Remote.new(self, name)
441
- end
442
-
443
- # sets the url for a remote
444
- # url can be a git url or a Git::Base object if it's a local reference
445
- #
446
- # @git.set_remote_url('scotts_git', 'git://repo.or.cz/rubygit.git')
447
- #
448
- def set_remote_url(name, url)
449
- url = url.repo.path if url.is_a?(Git::Base)
450
- self.lib.remote_set_url(name, url)
451
- Git::Remote.new(self, name)
452
- end
453
-
454
- # removes a remote from this repository
455
- #
456
- # @git.remove_remote('scott_git')
457
- def remove_remote(name)
458
- self.lib.remote_remove(name)
459
- end
460
-
461
- # returns an array of all Git::Tag objects for this repository
462
- def tags
463
- self.lib.tags.map { |r| tag(r) }
464
- end
465
-
466
- # Creates a new git tag (Git::Tag)
467
- #
468
- # @example
469
- # repo.add_tag('tag_name', object_reference)
470
- # repo.add_tag('tag_name', object_reference, {:options => 'here'})
471
- # repo.add_tag('tag_name', {:options => 'here'})
472
- #
473
- # @param [String] name The name of the tag to add
474
- # @param [Hash] options Opstions to pass to `git tag`.
475
- # See [git-tag](https://git-scm.com/docs/git-tag) for more details.
476
- # @option options [boolean] :annotate Make an unsigned, annotated tag object
477
- # @option options [boolean] :a An alias for the `:annotate` option
478
- # @option options [boolean] :d Delete existing tag with the given names.
479
- # @option options [boolean] :f Replace an existing tag with the given name (instead of failing)
480
- # @option options [String] :message Use the given tag message
481
- # @option options [String] :m An alias for the `:message` option
482
- # @option options [boolean] :s Make a GPG-signed tag.
483
- #
484
- def add_tag(name, *options)
485
- self.lib.tag(name, *options)
486
- self.tag(name)
487
- end
488
-
489
- # deletes a tag
490
- def delete_tag(name)
491
- self.lib.tag(name, {:d => true})
492
- end
493
-
494
- # creates an archive file of the given tree-ish
495
- def archive(treeish, file = nil, opts = {})
496
- self.object(treeish).archive(file, opts)
497
- end
498
-
499
- # repacks the repository
500
- def repack
501
- self.lib.repack
502
- end
503
-
504
- def gc
505
- self.lib.gc
506
- end
507
-
508
- def apply(file)
509
- if File.exist?(file)
510
- self.lib.apply(file)
511
- end
512
- end
513
-
514
- def apply_mail(file)
515
- self.lib.apply_mail(file) if File.exist?(file)
516
- end
517
-
518
- # Shows objects
519
- #
520
- # @param [String|NilClass] objectish the target object reference (nil == HEAD)
521
- # @param [String|NilClass] path the path of the file to be shown
522
- # @return [String] the object information
523
- def show(objectish=nil, path=nil)
524
- self.lib.show(objectish, path)
525
- end
526
-
527
- ## LOWER LEVEL INDEX OPERATIONS ##
528
-
529
- def with_index(new_index) # :yields: new_index
530
- old_index = @index
531
- set_index(new_index, false)
532
- return_value = yield @index
533
- set_index(old_index)
534
- return_value
535
- end
536
-
537
- def with_temp_index &blk
538
- # Workaround for JRUBY, since they handle the TempFile path different.
539
- # MUST be improved to be safer and OS independent.
540
- if RUBY_PLATFORM == 'java'
541
- temp_path = "/tmp/temp-index-#{(0...15).map{ ('a'..'z').to_a[rand(26)] }.join}"
542
- else
543
- tempfile = Tempfile.new('temp-index')
544
- temp_path = tempfile.path
545
- tempfile.close
546
- tempfile.unlink
547
- end
548
-
549
- with_index(temp_path, &blk)
550
- end
551
-
552
- def checkout_index(opts = {})
553
- self.lib.checkout_index(opts)
554
- end
555
-
556
- def read_tree(treeish, opts = {})
557
- self.lib.read_tree(treeish, opts)
558
- end
559
-
560
- def write_tree
561
- self.lib.write_tree
562
- end
563
-
564
- def write_and_commit_tree(opts = {})
565
- tree = write_tree
566
- commit_tree(tree, opts)
567
- end
568
-
569
- def update_ref(branch, commit)
570
- branch(branch).update_ref(commit)
571
- end
572
-
573
-
574
- def ls_files(location=nil)
575
- self.lib.ls_files(location)
576
- end
577
-
578
- def with_working(work_dir) # :yields: the Git::WorkingDirectory
579
- return_value = false
580
- old_working = @working_directory
581
- set_working(work_dir)
582
- Dir.chdir work_dir do
583
- return_value = yield @working_directory
584
- end
585
- set_working(old_working)
586
- return_value
587
- end
588
-
589
- def with_temp_working &blk
590
- tempfile = Tempfile.new("temp-workdir")
591
- temp_dir = tempfile.path
592
- tempfile.close
593
- tempfile.unlink
594
- Dir.mkdir(temp_dir, 0700)
595
- with_working(temp_dir, &blk)
596
- end
597
-
598
- # runs git rev-parse to convert the objectish to a full sha
599
- #
600
- # @example
601
- # git.revparse("HEAD^^")
602
- # git.revparse('v2.4^{tree}')
603
- # git.revparse('v2.4:/doc/index.html')
604
- #
605
- def revparse(objectish)
606
- self.lib.revparse(objectish)
607
- end
608
-
609
- def ls_tree(objectish)
610
- self.lib.ls_tree(objectish)
611
- end
612
-
613
- def cat_file(objectish)
614
- self.lib.object_contents(objectish)
615
- end
616
-
617
- # returns the name of the branch the working directory is currently on
618
- def current_branch
619
- self.lib.branch_current
620
- end
621
-
622
- private
623
-
624
- # Normalize options before they are sent to Git::Base.new
625
- #
626
- # Updates the options parameter by setting appropriate values for the following keys:
627
- # * options[:working_directory]
628
- # * options[:repository]
629
- # * options[:index]
630
- #
631
- # All three values will be set to absolute paths. An exception is that
632
- # :working_directory will be set to nil if bare is true.
633
- #
634
- private_class_method def self.normalize_paths(
635
- options, default_working_directory: nil, default_repository: nil, bare: false
636
- )
637
- normalize_working_directory(options, default: default_working_directory, bare: bare)
638
- normalize_repository(options, default: default_repository, bare: bare)
639
- normalize_index(options)
640
- end
641
-
642
- # Normalize options[:working_directory]
643
- #
644
- # If working with a bare repository, set to `nil`.
645
- # Otherwise, set to the first non-nil value of:
646
- # 1. `options[:working_directory]`,
647
- # 2. the `default` parameter, or
648
- # 3. the current working directory
649
- #
650
- # Finally, if options[:working_directory] is a relative path, convert it to an absoluite
651
- # path relative to the current directory.
652
- #
653
- private_class_method def self.normalize_working_directory(options, default:, bare: false)
654
- working_directory =
655
- if bare
656
- nil
657
- else
658
- File.expand_path(options[:working_directory] || default || Dir.pwd)
659
- end
660
-
661
- options[:working_directory] = working_directory
662
- end
663
-
664
- # Normalize options[:repository]
665
- #
666
- # If working with a bare repository, set to the first non-nil value out of:
667
- # 1. `options[:repository]`
668
- # 2. the `default` parameter
669
- # 3. the current working directory
670
- #
671
- # Otherwise, set to the first non-nil value of:
672
- # 1. `options[:repository]`
673
- # 2. `.git`
674
- #
675
- # Next, if options[:repository] refers to a *file* and not a *directory*, set
676
- # options[:repository] to the contents of that file. This is the case when
677
- # working with a submodule or a secondary working tree (created with git worktree
678
- # add). In these cases the repository is actually contained/nested within the
679
- # parent's repository directory.
680
- #
681
- # Finally, if options[:repository] is a relative path, convert it to an absolute
682
- # path relative to:
683
- # 1. the current directory if working with a bare repository or
684
- # 2. the working directory if NOT working with a bare repository
685
- #
686
- private_class_method def self.normalize_repository(options, default:, bare: false)
687
- repository =
688
- if bare
689
- File.expand_path(options[:repository] || default || Dir.pwd)
690
- else
691
- File.expand_path(options[:repository] || '.git', options[:working_directory])
692
- end
693
-
694
- if File.file?(repository)
695
- repository = File.expand_path(File.open(repository).read[8..-1].strip, options[:working_directory])
696
- end
697
-
698
- options[:repository] = repository
699
- end
700
-
701
- # Normalize options[:index]
702
- #
703
- # If options[:index] is a relative directory, convert it to an absolute
704
- # directory relative to the repository directory
705
- #
706
- private_class_method def self.normalize_index(options)
707
- index = File.expand_path(options[:index] || 'index', options[:repository])
708
- options[:index] = index
709
- end
710
- end
711
- end