git 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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