git 2.0.0 → 2.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ebad290719cdefc27125cf9a2ebb0d3544334c2d49a079220c0714a701ce141
4
- data.tar.gz: 293499cbb61ca9b4d374e86d0bd4357ed3f3b1254a46aa57c095cf0816afd7f6
3
+ metadata.gz: cf601afe6ddef5cc504f0a350bd9595feb76cc95822bd65716d6b5cecf2d324d
4
+ data.tar.gz: 5f334a391220774ab0fea9c789a87fe3a45d9de55e0745d87f59c0bc9a52e5a9
5
5
  SHA512:
6
- metadata.gz: 8fc0929f6ff79eea57f5dbd5f05da813bb55f6c44f925ce45f4ad4f3a011c99e3cfa2d00c4a18824e1521ab975fa70057127b143d77e301f0d5d2382cd4d7480
7
- data.tar.gz: 5ef0e326223cc983605c8afc002e3fe77808d337a3a3dcfd1b25588adf58b5c697a3451fd8baae777f727a5f2ba3cb92f2c3e811c79bc9f5da836b24ad5a8a6b
6
+ metadata.gz: 20133b00f0f50ccc00dc1bd4bb88107911ff5f438e127b804270752c43029e2447b15a5212c701a24a49a6f98d7b12359cb3326924ea3dadf631408b316e626e
7
+ data.tar.gz: 11ca7ae94de18e0b3d4aad99d315c2b973a8e2521ee24a935e5236fdc91eace943074ad388889a09ef4d8e33e2a4b1355d2590fe16fe0a1eda05357e1a315290
data/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@
5
5
 
6
6
  # Change Log
7
7
 
8
+ ## v2.1.0 (2024-05-31)
9
+
10
+ [Full Changelog](https://github.com/ruby-git/ruby-git/compare/v2.0.1..v2.1.0)
11
+
12
+ Changes since v2.0.1:
13
+
14
+ * 93c8210 Add Git::Log#max_count
15
+ * d84097b Update YARDoc for a few a few method
16
+
17
+ ## v2.0.1 (2024-05-21)
18
+
19
+ [Full Changelog](https://github.com/ruby-git/ruby-git/compare/v2.0.0..v2.0.1)
20
+
21
+ Changes since v2.0.0:
22
+
23
+ * da435b1 Document and add tests for Git::Status
24
+ * c8a77db Fix Git::Base#status on an empty repo
25
+ * 712fdad Fix Git::Status#untracked when run from worktree subdir
26
+ * 6a59bc8 Remove the Git::Base::Factory module
27
+
8
28
  ## v2.0.0 (2024-05-10)
9
29
 
10
30
  [Full Changelog](https://github.com/ruby-git/ruby-git/compare/v2.0.0.pre4..v2.0.0)
data/README.md CHANGED
@@ -23,11 +23,8 @@
23
23
 
24
24
  ## Summary
25
25
 
26
- The [git gem](https://rubygems.org/gems/git) provides an API that can be used to
27
- create, read, and manipulate Git repositories by wrapping system calls to the `git`
28
- command line. The API can be used for working with Git in complex interactions
29
- including branching and merging, object inspection and manipulation, history, patch
30
- generation and more.
26
+ The [git gem](https://rubygems.org/gems/git) provides a Ruby interface to the `git`
27
+ command line.
31
28
 
32
29
  Get started by obtaining a repository object by:
33
30
 
@@ -41,8 +38,7 @@ Methods that can be called on a repository object are documented in [Git::Base](
41
38
 
42
39
  git 2.0.0 has recently been released. Please give it a try.
43
40
 
44
-
45
- **If you have problems with the 2.x release, open an issue and use the 1.9.1 version
41
+ **If you have problems with the 2.x release, open an issue and use the 1.x version
46
42
  instead.** We will do our best to fix your issues in a timely fashion.
47
43
 
48
44
  **JRuby on Windows is not yet supported by the 2.x release line. Users running JRuby
@@ -105,16 +101,28 @@ directory, in the index and in the repository. Similar to running 'git status'
105
101
 
106
102
  **Git::Remote**- A reference to a remote repository that is tracked by this repository.
107
103
 
108
- **Git::Log** - An Enumerable object that references all the `Git::Object::Commit` objects that encompass your log query, which can be constructed through methods on the `Git::Log object`,
109
- like:
104
+ **Git::Log** - An Enumerable object that references all the `Git::Object::Commit`
105
+ objects that encompass your log query, which can be constructed through methods on
106
+ the `Git::Log object`, like:
110
107
 
111
- `@git.log(20).object("some_file").since("2 weeks ago").between('v2.6', 'v2.7').each { |commit| [block] }`
108
+ ```ruby
109
+ git.log
110
+ .max_count(:all)
111
+ .object('README.md')
112
+ .since('10 years ago')
113
+ .between('v1.0.7', 'HEAD')
114
+ .map { |commit| commit.sha }
115
+ ```
112
116
 
113
- Pass the `--all` option to `git log` as follows:
117
+ A maximum of 30 commits are returned if `max_count` is not called. To get all commits
118
+ that match the log query, call `max_count(:all)`.
114
119
 
115
- `@git.log.all.each { |commit| [block] }`
120
+ Note that `git.log.all` adds the `--all` option to the underlying `git log` command.
121
+ This asks for the logs of all refs (basically all commits reachable by HEAD,
122
+ branches, and tags). This does not control the maximum number of commits returned. To
123
+ control how many commits are returned, you should call `max_count`.
116
124
 
117
- **Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`.
125
+ **Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`.
118
126
 
119
127
  ## Errors Raised By This Gem
120
128
 
data/lib/git/base.rb CHANGED
@@ -1,17 +1,16 @@
1
- require 'git/base/factory'
2
1
  require 'logger'
3
2
  require 'open3'
4
3
 
5
4
  module Git
6
- # Git::Base is the main public interface for interacting with Git commands.
5
+ # The main public interface for interacting with Git commands
7
6
  #
8
7
  # Instead of creating a Git::Base directly, obtain a Git::Base instance by
9
8
  # calling one of the follow {Git} class methods: {Git.open}, {Git.init},
10
9
  # {Git.clone}, or {Git.bare}.
11
10
  #
11
+ # @api public
12
+ #
12
13
  class Base
13
- include Git::Base::Factory
14
-
15
14
  # (see Git.bare)
16
15
  def self.bare(git_dir, options = {})
17
16
  normalize_paths(options, default_repository: git_dir, bare: true)
@@ -122,6 +121,62 @@ module Git
122
121
  @index = options[:index] ? Git::Index.new(options[:index], false) : nil
123
122
  end
124
123
 
124
+ # Update the index from the current worktree to prepare the for the next commit
125
+ #
126
+ # @example
127
+ # lib.add('path/to/file')
128
+ # lib.add(['path/to/file1','path/to/file2'])
129
+ # lib.add(all: true)
130
+ #
131
+ # @param [String, Array<String>] paths a file or files to be added to the repository (relative to the worktree root)
132
+ # @param [Hash] options
133
+ #
134
+ # @option options [Boolean] :all Add, modify, and remove index entries to match the worktree
135
+ # @option options [Boolean] :force Allow adding otherwise ignored files
136
+ #
137
+ def add(paths = '.', **options)
138
+ self.lib.add(paths, options)
139
+ end
140
+
141
+ # adds a new remote to this repository
142
+ # url can be a git url or a Git::Base object if it's a local reference
143
+ #
144
+ # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
145
+ # @git.fetch('scotts_git')
146
+ # @git.merge('scotts_git/master')
147
+ #
148
+ # Options:
149
+ # :fetch => true
150
+ # :track => <branch_name>
151
+ def add_remote(name, url, opts = {})
152
+ url = url.repo.path if url.is_a?(Git::Base)
153
+ self.lib.remote_add(name, url, opts)
154
+ Git::Remote.new(self, name)
155
+ end
156
+
157
+ # Create a new git tag
158
+ #
159
+ # @example
160
+ # repo.add_tag('tag_name', object_reference)
161
+ # repo.add_tag('tag_name', object_reference, {:options => 'here'})
162
+ # repo.add_tag('tag_name', {:options => 'here'})
163
+ #
164
+ # @param [String] name The name of the tag to add
165
+ # @param [Hash] options Opstions to pass to `git tag`.
166
+ # See [git-tag](https://git-scm.com/docs/git-tag) for more details.
167
+ # @option options [boolean] :annotate Make an unsigned, annotated tag object
168
+ # @option options [boolean] :a An alias for the `:annotate` option
169
+ # @option options [boolean] :d Delete existing tag with the given names.
170
+ # @option options [boolean] :f Replace an existing tag with the given name (instead of failing)
171
+ # @option options [String] :message Use the given tag message
172
+ # @option options [String] :m An alias for the `:message` option
173
+ # @option options [boolean] :s Make a GPG-signed tag.
174
+ #
175
+ def add_tag(name, *options)
176
+ self.lib.tag(name, *options)
177
+ self.tag(name)
178
+ end
179
+
125
180
  # changes current working directory for a block
126
181
  # to the git working directory
127
182
  #
@@ -254,29 +309,6 @@ module Git
254
309
  self.object('HEAD').grep(string, path_limiter, opts)
255
310
  end
256
311
 
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
312
  # removes file(s) from the git repository
281
313
  def rm(path = '.', opts = {})
282
314
  self.lib.rm(path, opts)
@@ -437,22 +469,6 @@ module Git
437
469
  self.lib.remotes.map { |r| Git::Remote.new(self, r) }
438
470
  end
439
471
 
440
- # adds a new remote to this repository
441
- # url can be a git url or a Git::Base object if it's a local reference
442
- #
443
- # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
444
- # @git.fetch('scotts_git')
445
- # @git.merge('scotts_git/master')
446
- #
447
- # Options:
448
- # :fetch => true
449
- # :track => <branch_name>
450
- def add_remote(name, url, opts = {})
451
- url = url.repo.path if url.is_a?(Git::Base)
452
- self.lib.remote_add(name, url, opts)
453
- Git::Remote.new(self, name)
454
- end
455
-
456
472
  # sets the url for a remote
457
473
  # url can be a git url or a Git::Base object if it's a local reference
458
474
  #
@@ -476,7 +492,7 @@ module Git
476
492
  self.lib.tags.map { |r| tag(r) }
477
493
  end
478
494
 
479
- # Creates a new git tag (Git::Tag)
495
+ # Create a new git tag
480
496
  #
481
497
  # @example
482
498
  # repo.add_tag('tag_name', object_reference)
@@ -632,6 +648,96 @@ module Git
632
648
  self.lib.branch_current
633
649
  end
634
650
 
651
+ # @return [Git::Branch] an object for branch_name
652
+ def branch(branch_name = self.current_branch)
653
+ Git::Branch.new(self, branch_name)
654
+ end
655
+
656
+ # @return [Git::Branches] a collection of all the branches in the repository.
657
+ # Each branch is represented as a {Git::Branch}.
658
+ def branches
659
+ Git::Branches.new(self)
660
+ end
661
+
662
+ # returns a Git::Worktree object for dir, commitish
663
+ def worktree(dir, commitish = nil)
664
+ Git::Worktree.new(self, dir, commitish)
665
+ end
666
+
667
+ # returns a Git::worktrees object of all the Git::Worktrees
668
+ # objects for this repo
669
+ def worktrees
670
+ Git::Worktrees.new(self)
671
+ end
672
+
673
+ # @return [Git::Object::Commit] a commit object
674
+ def commit_tree(tree = nil, opts = {})
675
+ Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
676
+ end
677
+
678
+ # @return [Git::Diff] a Git::Diff object
679
+ def diff(objectish = 'HEAD', obj2 = nil)
680
+ Git::Diff.new(self, objectish, obj2)
681
+ end
682
+
683
+ # @return [Git::Object] a Git object
684
+ def gblob(objectish)
685
+ Git::Object.new(self, objectish, 'blob')
686
+ end
687
+
688
+ # @return [Git::Object] a Git object
689
+ def gcommit(objectish)
690
+ Git::Object.new(self, objectish, 'commit')
691
+ end
692
+
693
+ # @return [Git::Object] a Git object
694
+ def gtree(objectish)
695
+ Git::Object.new(self, objectish, 'tree')
696
+ end
697
+
698
+ # @return [Git::Log] a log with the specified number of commits
699
+ def log(count = 30)
700
+ Git::Log.new(self, count)
701
+ end
702
+
703
+ # returns a Git::Object of the appropriate type
704
+ # you can also call @git.gtree('tree'), but that's
705
+ # just for readability. If you call @git.gtree('HEAD') it will
706
+ # still return a Git::Object::Commit object.
707
+ #
708
+ # object calls a method that will run a rev-parse
709
+ # on the objectish and determine the type of the object and return
710
+ # an appropriate object for that type
711
+ #
712
+ # @return [Git::Object] an instance of the appropriate type of Git::Object
713
+ def object(objectish)
714
+ Git::Object.new(self, objectish)
715
+ end
716
+
717
+ # @return [Git::Remote] a remote of the specified name
718
+ def remote(remote_name = 'origin')
719
+ Git::Remote.new(self, remote_name)
720
+ end
721
+
722
+ # @return [Git::Status] a status object
723
+ def status
724
+ Git::Status.new(self)
725
+ end
726
+
727
+ # @return [Git::Object::Tag] a tag object
728
+ def tag(tag_name)
729
+ Git::Object.new(self, tag_name, 'tag', true)
730
+ end
731
+
732
+ # Find as good common ancestors as possible for a merge
733
+ # example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)
734
+ #
735
+ # @return [Array<Git::Object::Commit>] a collection of common ancestors
736
+ def merge_base(*args)
737
+ shas = self.lib.merge_base(*args)
738
+ shas.map { |sha| gcommit(sha) }
739
+ end
740
+
635
741
  private
636
742
 
637
743
  # Normalize options before they are sent to Git::Base.new
data/lib/git/lib.rb CHANGED
@@ -38,14 +38,23 @@ module Git
38
38
 
39
39
  # Create a new Git::Lib object
40
40
  #
41
- # @param [Git::Base, Hash] base An object that passes in values for
42
- # @git_work_dir, @git_dir, and @git_index_file
41
+ # @overload initialize(base, logger)
43
42
  #
44
- # @param [Logger] logger
43
+ # @param base [Hash] the hash containing paths to the Git working copy,
44
+ # the Git repository directory, and the Git index file.
45
45
  #
46
- # @option base [Pathname] :working_directory
47
- # @option base [Pathname] :repository
48
- # @option base [Pathname] :index
46
+ # @option base [Pathname] :working_directory
47
+ # @option base [Pathname] :repository
48
+ # @option base [Pathname] :index
49
+ #
50
+ # @param [Logger] logger
51
+ #
52
+ # @overload initialize(base, logger)
53
+ #
54
+ # @param base [#dir, #repo, #index] an object with methods to get the Git worktree (#dir),
55
+ # the Git repository directory (#repo), and the Git index file (#index).
56
+ #
57
+ # @param [Logger] logger
49
58
  #
50
59
  def initialize(base = nil, logger = nil)
51
60
  @git_dir = nil
@@ -600,6 +609,9 @@ module Git
600
609
  command_lines('ls-files', '--others', '-i', '--exclude-standard')
601
610
  end
602
611
 
612
+ def untracked_files
613
+ command_lines('ls-files', '--others', '--exclude-standard', chdir: @git_work_dir)
614
+ end
603
615
 
604
616
  def config_remote(name)
605
617
  hsh = {}
@@ -667,18 +679,20 @@ module Git
667
679
  command('config', '--global', name, value)
668
680
  end
669
681
 
670
- # updates the repository index using the working directory content
671
- #
672
- # lib.add('path/to/file')
673
- # lib.add(['path/to/file1','path/to/file2'])
674
- # lib.add(:all => true)
682
+
683
+ # Update the index from the current worktree to prepare the for the next commit
675
684
  #
676
- # options:
677
- # :all => true
678
- # :force => true
685
+ # @example
686
+ # lib.add('path/to/file')
687
+ # lib.add(['path/to/file1','path/to/file2'])
688
+ # lib.add(:all => true)
679
689
  #
680
- # @param [String,Array] paths files paths to be added to the repository
690
+ # @param [String, Array<String>] paths files to be added to the repository (relative to the worktree root)
681
691
  # @param [Hash] options
692
+ #
693
+ # @option options [Boolean] :all Add, modify, and remove index entries to match the worktree
694
+ # @option options [Boolean] :force Allow adding otherwise ignored files
695
+ #
682
696
  def add(paths='.',options={})
683
697
  arr_opts = []
684
698
 
@@ -704,6 +718,19 @@ module Git
704
718
  command('rm', *arr_opts)
705
719
  end
706
720
 
721
+ # Returns true if the repository is empty (meaning it has no commits)
722
+ #
723
+ # @return [Boolean]
724
+ #
725
+ def empty?
726
+ command('rev-parse', '--verify', 'HEAD')
727
+ false
728
+ rescue Git::FailedError => e
729
+ raise unless e.result.status.exitstatus == 128 &&
730
+ e.result.stderr == 'fatal: Needed a single revision'
731
+ true
732
+ end
733
+
707
734
  # Takes the commit message with the options and executes the commit command
708
735
  #
709
736
  # accepts options:
data/lib/git/log.rb CHANGED
@@ -1,15 +1,76 @@
1
1
  module Git
2
2
 
3
- # object that holds the last X commits on given branch
3
+ # Return the last n commits that match the specified criteria
4
+ #
5
+ # @example The last (default number) of commits
6
+ # git = Git.open('.')
7
+ # Git::Log.new(git) #=> Enumerable of the last 30 commits
8
+ #
9
+ # @example The last n commits
10
+ # Git::Log.new(git).max_commits(50) #=> Enumerable of last 50 commits
11
+ #
12
+ # @example All commits returned by `git log`
13
+ # Git::Log.new(git).max_count(:all) #=> Enumerable of all commits
14
+ #
15
+ # @example All commits that match complex criteria
16
+ # Git::Log.new(git)
17
+ # .max_count(:all)
18
+ # .object('README.md')
19
+ # .since('10 years ago')
20
+ # .between('v1.0.7', 'HEAD')
21
+ #
22
+ # @api public
23
+ #
4
24
  class Log
5
25
  include Enumerable
6
26
 
7
- def initialize(base, count = 30)
27
+ # Create a new Git::Log object
28
+ #
29
+ # @example
30
+ # git = Git.open('.')
31
+ # Git::Log.new(git)
32
+ #
33
+ # @param base [Git::Base] the git repository object
34
+ # @param max_count [Integer, Symbol, nil] the number of commits to return, or
35
+ # `:all` or `nil` to return all
36
+ #
37
+ # Passing max_count to {#initialize} is equivalent to calling {#max_count} on the object.
38
+ #
39
+ def initialize(base, max_count = 30)
8
40
  dirty_log
9
41
  @base = base
10
- @count = count
42
+ max_count(max_count)
43
+ end
44
+
45
+ # The maximum number of commits to return
46
+ #
47
+ # @example All commits returned by `git log`
48
+ # git = Git.open('.')
49
+ # Git::Log.new(git).max_count(:all)
50
+ #
51
+ # @param num_or_all [Integer, Symbol, nil] the number of commits to return, or
52
+ # `:all` or `nil` to return all
53
+ #
54
+ # @return [self]
55
+ #
56
+ def max_count(num_or_all)
57
+ dirty_log
58
+ @max_count = (num_or_all == :all) ? nil : num_or_all
59
+ self
11
60
  end
12
61
 
62
+ # Adds the --all flag to the git log command
63
+ #
64
+ # This asks for the logs of all refs (basically all commits reachable by HEAD,
65
+ # branches, and tags). This does not control the maximum number of commits
66
+ # returned. To control how many commits are returned, call {#max_count}.
67
+ #
68
+ # @example Return the last 50 commits reachable by all refs
69
+ # git = Git.open('.')
70
+ # Git::Log.new(git).max_count(50).all
71
+ #
72
+ # @return [self]
73
+ #
13
74
  def all
14
75
  dirty_log
15
76
  @all = true
@@ -119,7 +180,7 @@ module Git
119
180
  # actually run the 'git log' command
120
181
  def run_log
121
182
  log = @base.lib.full_log_commits(
122
- count: @count, all: @all, object: @object, path_limiter: @path, since: @since,
183
+ count: @max_count, all: @all, object: @object, path_limiter: @path, since: @since,
123
184
  author: @author, grep: @grep, skip: @skip, until: @until, between: @between,
124
185
  cherry: @cherry
125
186
  )
data/lib/git/status.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  module Git
2
+ # The status class gets the status of a git repository
2
3
  #
3
- # A class for git status
4
+ # This identifies which files have been modified, added, or deleted from the
5
+ # worktree. Untracked files are also identified.
6
+ #
7
+ # The Status object is an Enumerable that contains StatusFile objects.
8
+ #
9
+ # @api public
4
10
  #
5
11
  class Status
6
12
  include Enumerable
@@ -31,7 +37,6 @@ module Git
31
37
  changed.member?(file)
32
38
  end
33
39
 
34
- #
35
40
  # Returns an Enumerable containing files that have been added.
36
41
  # File path starts at git base directory
37
42
  #
@@ -40,8 +45,8 @@ module Git
40
45
  @files.select { |_k, f| f.type == 'A' }
41
46
  end
42
47
 
43
- #
44
48
  # Determines whether the given file has been added to the repository
49
+ #
45
50
  # File path starts at git base directory
46
51
  #
47
52
  # @param file [String] The name of the file.
@@ -126,9 +131,63 @@ module Git
126
131
 
127
132
  # subclass that does heavy lifting
128
133
  class StatusFile
129
- attr_accessor :path, :type, :stage, :untracked
130
- attr_accessor :mode_index, :mode_repo
131
- attr_accessor :sha_index, :sha_repo
134
+ # @!attribute [r] path
135
+ # The path of the file relative to the project root directory
136
+ # @return [String]
137
+ attr_accessor :path
138
+
139
+ # @!attribute [r] type
140
+ # The type of change
141
+ #
142
+ # * 'M': modified
143
+ # * 'A': added
144
+ # * 'D': deleted
145
+ # * nil: ???
146
+ #
147
+ # @return [String]
148
+ attr_accessor :type
149
+
150
+ # @!attribute [r] mode_index
151
+ # The mode of the file in the index
152
+ # @return [String]
153
+ # @example 100644
154
+ #
155
+ attr_accessor :mode_index
156
+
157
+ # @!attribute [r] mode_repo
158
+ # The mode of the file in the repo
159
+ # @return [String]
160
+ # @example 100644
161
+ #
162
+ attr_accessor :mode_repo
163
+
164
+ # @!attribute [r] sha_index
165
+ # The sha of the file in the index
166
+ # @return [String]
167
+ # @example 123456
168
+ #
169
+ attr_accessor :sha_index
170
+
171
+ # @!attribute [r] sha_repo
172
+ # The sha of the file in the repo
173
+ # @return [String]
174
+ # @example 123456
175
+ attr_accessor :sha_repo
176
+
177
+ # @!attribute [r] untracked
178
+ # Whether the file is untracked
179
+ # @return [Boolean]
180
+ attr_accessor :untracked
181
+
182
+ # @!attribute [r] stage
183
+ # The stage of the file
184
+ #
185
+ # * '0': the unmerged state
186
+ # * '1': the common ancestor (or original) version
187
+ # * '2': "our version" from the current branch head
188
+ # * '3': "their version" from the other branch head
189
+ # @return [String]
190
+ attr_accessor :stage
132
191
 
133
192
  def initialize(base, hash)
134
193
  @base = base
@@ -158,10 +217,19 @@ module Git
158
217
  private
159
218
 
160
219
  def construct_status
220
+ # Lists all files in the index and the worktree
221
+ # git ls-files --stage
222
+ # { file => { path: file, mode_index: '100644', sha_index: 'dd4fc23', stage: '0' } }
161
223
  @files = @base.lib.ls_files
162
224
 
225
+ # Lists files in the worktree that are not in the index
226
+ # Add untracked files to @files
163
227
  fetch_untracked
228
+
229
+ # Lists files that are different between the index vs. the worktree
164
230
  fetch_modified
231
+
232
+ # Lists files that are different between the repo HEAD vs. the worktree
165
233
  fetch_added
166
234
 
167
235
  @files.each do |k, file_hash|
@@ -170,28 +238,30 @@ module Git
170
238
  end
171
239
 
172
240
  def fetch_untracked
173
- ignore = @base.lib.ignored_files
174
-
175
- root_dir = @base.dir.path
176
- Dir.glob('**/*', File::FNM_DOTMATCH, base: root_dir) do |file|
177
- next if @files[file] || File.directory?(File.join(root_dir, file)) ||
178
- ignore.include?(file) || file =~ %r{^.git\/.+}
179
-
241
+ # git ls-files --others --exclude-standard, chdir: @git_work_dir)
242
+ # { file => { path: file, untracked: true } }
243
+ @base.lib.untracked_files.each do |file|
180
244
  @files[file] = { path: file, untracked: true }
181
245
  end
182
246
  end
183
247
 
184
248
  def fetch_modified
185
- # find modified in tree
249
+ # Files changed between the index vs. the worktree
250
+ # git diff-files
251
+ # { file => { path: file, type: 'M', mode_index: '100644', mode_repo: '100644', sha_index: '0000000', :sha_repo: '52c6c4e' } }
186
252
  @base.lib.diff_files.each do |path, data|
187
253
  @files[path] ? @files[path].merge!(data) : @files[path] = data
188
254
  end
189
255
  end
190
256
 
191
257
  def fetch_added
192
- # find added but not committed - new files
258
+ unless @base.lib.empty?
259
+ # Files changed between the repo HEAD vs. the worktree
260
+ # git diff-index HEAD
261
+ # { file => { path: file, type: 'M', mode_index: '100644', mode_repo: '100644', sha_index: '0000000', :sha_repo: '52c6c4e' } }
193
262
  @base.lib.diff_index('HEAD').each do |path, data|
194
- @files[path] ? @files[path].merge!(data) : @files[path] = data
263
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
264
+ end
195
265
  end
196
266
  end
197
267
  end
data/lib/git/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Git
2
2
  # The current gem version
3
3
  # @return [String] the current gem version.
4
- VERSION='2.0.0'
4
+ VERSION='2.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon and others
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-11 00:00:00.000000000 Z
11
+ date: 2024-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -213,7 +213,6 @@ files:
213
213
  - lib/git.rb
214
214
  - lib/git/author.rb
215
215
  - lib/git/base.rb
216
- - lib/git/base/factory.rb
217
216
  - lib/git/branch.rb
218
217
  - lib/git/branches.rb
219
218
  - lib/git/command_line.rb
@@ -244,8 +243,8 @@ licenses:
244
243
  metadata:
245
244
  homepage_uri: http://github.com/ruby-git/ruby-git
246
245
  source_code_uri: http://github.com/ruby-git/ruby-git
247
- changelog_uri: https://rubydoc.info/gems/git/2.0.0/file/CHANGELOG.md
248
- documentation_uri: https://rubydoc.info/gems/git/2.0.0
246
+ changelog_uri: https://rubydoc.info/gems/git/2.1.0/file/CHANGELOG.md
247
+ documentation_uri: https://rubydoc.info/gems/git/2.1.0
249
248
  post_install_message:
250
249
  rdoc_options: []
251
250
  require_paths:
@@ -1,99 +0,0 @@
1
- module Git
2
-
3
- class Base
4
-
5
- module Factory
6
- # @return [Git::Branch] an object for branch_name
7
- def branch(branch_name = self.current_branch)
8
- Git::Branch.new(self, branch_name)
9
- end
10
-
11
- # @return [Git::Branches] a collection of all the branches in the repository.
12
- # Each branch is represented as a {Git::Branch}.
13
- def branches
14
- Git::Branches.new(self)
15
- end
16
-
17
- # returns a Git::Worktree object for dir, commitish
18
- def worktree(dir, commitish = nil)
19
- Git::Worktree.new(self, dir, commitish)
20
- end
21
-
22
- # returns a Git::worktrees object of all the Git::Worktrees
23
- # objects for this repo
24
- def worktrees
25
- Git::Worktrees.new(self)
26
- end
27
-
28
- # @return [Git::Object::Commit] a commit object
29
- def commit_tree(tree = nil, opts = {})
30
- Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
31
- end
32
-
33
- # @return [Git::Diff] a Git::Diff object
34
- def diff(objectish = 'HEAD', obj2 = nil)
35
- Git::Diff.new(self, objectish, obj2)
36
- end
37
-
38
- # @return [Git::Object] a Git object
39
- def gblob(objectish)
40
- Git::Object.new(self, objectish, 'blob')
41
- end
42
-
43
- # @return [Git::Object] a Git object
44
- def gcommit(objectish)
45
- Git::Object.new(self, objectish, 'commit')
46
- end
47
-
48
- # @return [Git::Object] a Git object
49
- def gtree(objectish)
50
- Git::Object.new(self, objectish, 'tree')
51
- end
52
-
53
- # @return [Git::Log] a log with the specified number of commits
54
- def log(count = 30)
55
- Git::Log.new(self, count)
56
- end
57
-
58
- # returns a Git::Object of the appropriate type
59
- # you can also call @git.gtree('tree'), but that's
60
- # just for readability. If you call @git.gtree('HEAD') it will
61
- # still return a Git::Object::Commit object.
62
- #
63
- # object calls a factory method that will run a rev-parse
64
- # on the objectish and determine the type of the object and return
65
- # an appropriate object for that type
66
- #
67
- # @return [Git::Object] an instance of the appropriate type of Git::Object
68
- def object(objectish)
69
- Git::Object.new(self, objectish)
70
- end
71
-
72
- # @return [Git::Remote] a remote of the specified name
73
- def remote(remote_name = 'origin')
74
- Git::Remote.new(self, remote_name)
75
- end
76
-
77
- # @return [Git::Status] a status object
78
- def status
79
- Git::Status.new(self)
80
- end
81
-
82
- # @return [Git::Object::Tag] a tag object
83
- def tag(tag_name)
84
- Git::Object.new(self, tag_name, 'tag', true)
85
- end
86
-
87
- # Find as good common ancestors as possible for a merge
88
- # example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)
89
- #
90
- # @return [Array<Git::Object::Commit>] a collection of common ancestors
91
- def merge_base(*args)
92
- shas = self.lib.merge_base(*args)
93
- shas.map { |sha| gcommit(sha) }
94
- end
95
- end
96
-
97
- end
98
-
99
- end