git 5.2.0 → 5.4.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 +4 -4
- data/CHANGELOG.md +49 -0
- data/CONTRIBUTING.md +17 -4
- data/README.md +49 -8
- data/UPGRADING.md +587 -3
- data/lib/git/author.rb +11 -0
- data/lib/git/author_info.rb +66 -0
- data/lib/git/branch.rb +216 -17
- data/lib/git/branch_info.rb +1 -1
- data/lib/git/branches.rb +35 -7
- data/lib/git/commands/cat_file/raw.rb +60 -6
- data/lib/git/object.rb +69 -15
- data/lib/git/parsers/stash.rb +50 -17
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/tag.rb +54 -8
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/remote.rb +37 -7
- data/lib/git/remote_info.rb +67 -10
- data/lib/git/repository/branching.rb +111 -1
- data/lib/git/repository/merging.rb +96 -2
- data/lib/git/repository/object_operations.rb +257 -20
- data/lib/git/repository/remote_operations.rb +57 -0
- data/lib/git/repository/shared_private.rb +67 -0
- data/lib/git/repository/stashing.rb +532 -52
- data/lib/git/repository/status_operations.rb +56 -8
- data/lib/git/repository/worktree_operations.rb +198 -18
- data/lib/git/stash.rb +31 -2
- data/lib/git/stash_info.rb +32 -34
- data/lib/git/stashes.rb +47 -11
- data/lib/git/status.rb +14 -0
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_info.rb +23 -30
- data/lib/git/version.rb +1 -1
- data/lib/git/worktree.rb +39 -0
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +19 -1
- data/lib/git.rb +5 -0
- metadata +9 -3
|
@@ -721,8 +721,28 @@ module Git
|
|
|
721
721
|
# @raise [Git::FailedError] if the underlying `git show-ref` invocation
|
|
722
722
|
# exits with an unexpected status (i.e., outside the allowed 0..1 range)
|
|
723
723
|
#
|
|
724
|
+
# @deprecated Use `tag_list(name).first` instead
|
|
725
|
+
#
|
|
726
|
+
# {#tag_list} returns immutable {Git::TagInfo} value objects rather
|
|
727
|
+
# than {Git::Object::Tag}. `tag_list(name).first` is `nil` when the tag
|
|
728
|
+
# does not exist, where this method raises
|
|
729
|
+
# {Git::UnexpectedResultError}. Call the corresponding
|
|
730
|
+
# {Git::Repository} method (e.g. {#archive}, {#log}, {#diff},
|
|
731
|
+
# {#cat_file_contents}) with `info.oid || info.target_oid` for
|
|
732
|
+
# operations on a tag; that is the object this method's return value
|
|
733
|
+
# pins at construction, so a later move of the tag does not redirect
|
|
734
|
+
# it, whereas the tag name would. The
|
|
735
|
+
# {Git::Object::Tag} constructor is deprecated too; this method
|
|
736
|
+
# silences it so one call emits one warning.
|
|
737
|
+
#
|
|
738
|
+
# @see #tag_list
|
|
739
|
+
#
|
|
724
740
|
def tag(tag_name)
|
|
725
|
-
Git::
|
|
741
|
+
Git::Deprecation.warn(
|
|
742
|
+
'Git::Repository#tag is deprecated and will be removed in v6.0.0. ' \
|
|
743
|
+
'Use Git::Repository#tag_list(name).first instead.'
|
|
744
|
+
)
|
|
745
|
+
Git::Deprecation.silence { Git::Object::Tag.new(self, tag_name) }
|
|
726
746
|
end
|
|
727
747
|
|
|
728
748
|
# Returns the appropriate git object for the given object reference
|
|
@@ -753,6 +773,47 @@ module Git
|
|
|
753
773
|
Git::Object.new(self, objectish)
|
|
754
774
|
end
|
|
755
775
|
|
|
776
|
+
# Returns the tags in the repository as structured objects
|
|
777
|
+
#
|
|
778
|
+
# @example List all tags
|
|
779
|
+
# repo.tag_list
|
|
780
|
+
# # => [#<data Git::TagInfo name="v1.0.0", oid=nil, target_oid="abc123...", ...>,
|
|
781
|
+
# # #<data Git::TagInfo name="v2.0.0", oid="def456...", target_oid="789abc...", ...>]
|
|
782
|
+
#
|
|
783
|
+
# @example Look up a single tag by name
|
|
784
|
+
# repo.tag_list('v1.0.0').first
|
|
785
|
+
# # => #<data Git::TagInfo name="v1.0.0", ...>
|
|
786
|
+
#
|
|
787
|
+
# @example Look up a tag that does not exist
|
|
788
|
+
# repo.tag_list('nonexistent').first #=> nil
|
|
789
|
+
#
|
|
790
|
+
# @example Filter using glob patterns
|
|
791
|
+
# repo.tag_list('v1.*', 'v2.*')
|
|
792
|
+
#
|
|
793
|
+
# @example List only annotated tags
|
|
794
|
+
# repo.tag_list.select(&:annotated?)
|
|
795
|
+
#
|
|
796
|
+
# @param patterns [Array<String>] optional shell wildcard patterns passed
|
|
797
|
+
# directly to `git tag --list`; when empty (the default) all tags are
|
|
798
|
+
# returned
|
|
799
|
+
#
|
|
800
|
+
# @return [Array<Git::TagInfo>] parsed tag information for every tag
|
|
801
|
+
# matching the patterns, in the order `git tag --list` reports them
|
|
802
|
+
#
|
|
803
|
+
# Returns an empty array when the repository has no tags or no tag
|
|
804
|
+
# matches the given patterns.
|
|
805
|
+
#
|
|
806
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
807
|
+
#
|
|
808
|
+
# @see https://git-scm.com/docs/git-tag git-tag
|
|
809
|
+
#
|
|
810
|
+
def tag_list(*patterns)
|
|
811
|
+
result = Git::Commands::Tag::List.new(@execution_context).call(
|
|
812
|
+
*patterns, format: Git::Parsers::Tag::FORMAT_STRING
|
|
813
|
+
)
|
|
814
|
+
Git::Parsers::Tag.parse_list(result.stdout)
|
|
815
|
+
end
|
|
816
|
+
|
|
756
817
|
# Returns all tags in the repository as tag objects
|
|
757
818
|
#
|
|
758
819
|
# Runs `git tag --list` with a machine-readable format, parses the output,
|
|
@@ -769,30 +830,50 @@ module Git
|
|
|
769
830
|
#
|
|
770
831
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
771
832
|
#
|
|
833
|
+
# @deprecated Use {#tag_list} instead
|
|
834
|
+
#
|
|
835
|
+
# {#tag_list} returns `Array<Git::TagInfo>` (immutable value objects)
|
|
836
|
+
# rather than `Array<Git::Object::Tag>`. Look a tag up by name with
|
|
837
|
+
# `tag_list(name).first`, and call the corresponding {Git::Repository}
|
|
838
|
+
# method (e.g. {#archive}, {#log}, {#diff}, {#cat_file_contents}) with
|
|
839
|
+
# `info.oid || info.target_oid` for operations on a tag; that is the
|
|
840
|
+
# object each returned {Git::Object::Tag} pins at construction, so a
|
|
841
|
+
# later move of the tag does not redirect it, whereas the tag name
|
|
842
|
+
# would. The {Git::Object::Tag}
|
|
843
|
+
# constructor is deprecated too; this method silences it so one call
|
|
844
|
+
# emits one warning.
|
|
845
|
+
#
|
|
846
|
+
# @see #tag_list
|
|
847
|
+
#
|
|
772
848
|
def tags
|
|
773
|
-
|
|
774
|
-
|
|
849
|
+
Git::Deprecation.warn(
|
|
850
|
+
'Git::Repository#tags is deprecated and will be removed in v6.0.0. ' \
|
|
851
|
+
'Use Git::Repository#tag_list instead.'
|
|
852
|
+
)
|
|
853
|
+
Git::Deprecation.silence { tag_list.map { |info| Git::Object::Tag.new(self, info.name) } }
|
|
775
854
|
end
|
|
776
855
|
|
|
777
|
-
# Option keys accepted by {#tag_add}
|
|
778
|
-
|
|
856
|
+
# Option keys accepted by {#tag_create} and {#tag_add}
|
|
857
|
+
TAG_CREATE_ALLOWED_OPTS = %i[
|
|
779
858
|
annotate a sign s no_sign local_user u force f message m file F
|
|
780
859
|
edit e no_edit trailer cleanup create_reflog
|
|
781
860
|
].freeze
|
|
782
|
-
private_constant :
|
|
861
|
+
private_constant :TAG_CREATE_ALLOWED_OPTS
|
|
783
862
|
|
|
784
|
-
# Create a new tag
|
|
863
|
+
# Create a new tag and return its metadata
|
|
785
864
|
#
|
|
786
|
-
# @overload
|
|
865
|
+
# @overload tag_create(name, options = {})
|
|
787
866
|
#
|
|
788
867
|
# @example Create a lightweight tag on HEAD
|
|
789
|
-
# repo.
|
|
868
|
+
# repo.tag_create('v1.0.0')
|
|
869
|
+
# # => #<data Git::TagInfo name="v1.0.0", oid=nil, target_oid="abc123...", ...>
|
|
790
870
|
#
|
|
791
871
|
# @example Create an annotated tag on HEAD
|
|
792
|
-
# repo.
|
|
872
|
+
# repo.tag_create('v1.0.0', annotate: true, message: 'Release 1.0.0')
|
|
873
|
+
# # => #<data Git::TagInfo name="v1.0.0", oid="def456...", message="Release 1.0.0", ...>
|
|
793
874
|
#
|
|
794
875
|
# @example Replace an existing tag on HEAD
|
|
795
|
-
# repo.
|
|
876
|
+
# repo.tag_create('v1.0.0', force: true)
|
|
796
877
|
#
|
|
797
878
|
# @param name [String] the name of the tag to create
|
|
798
879
|
#
|
|
@@ -847,6 +928,65 @@ module Git
|
|
|
847
928
|
# @option options [Boolean, nil] :create_reflog (nil) create a reflog for
|
|
848
929
|
# the tag
|
|
849
930
|
#
|
|
931
|
+
# @return [Git::TagInfo] the newly created tag
|
|
932
|
+
#
|
|
933
|
+
# @overload tag_create(name, target, options = {})
|
|
934
|
+
#
|
|
935
|
+
# @example Create a lightweight tag on a specific commit
|
|
936
|
+
# repo.tag_create('v1.0.0', 'abc123')
|
|
937
|
+
#
|
|
938
|
+
# @example Create an annotated tag on a specific commit
|
|
939
|
+
# repo.tag_create('v1.0.0', 'abc123', annotate: true, message: 'Release 1.0.0')
|
|
940
|
+
#
|
|
941
|
+
# @param name [String] the name of the tag to create
|
|
942
|
+
#
|
|
943
|
+
# @param target [String] the object to tag (commit SHA, branch name, etc.)
|
|
944
|
+
#
|
|
945
|
+
# @param options [Hash] options for creating the tag (same keys as the
|
|
946
|
+
# first overload)
|
|
947
|
+
#
|
|
948
|
+
# @return [Git::TagInfo] the newly created tag
|
|
949
|
+
#
|
|
950
|
+
# @raise [ArgumentError] if unsupported options are provided, including the
|
|
951
|
+
# `:d` and `:delete` keys that {#tag_add} accepts; use {#tag_delete} to
|
|
952
|
+
# delete a tag
|
|
953
|
+
#
|
|
954
|
+
# @raise [ArgumentError] if an annotated or signed tag is requested without
|
|
955
|
+
# a message
|
|
956
|
+
#
|
|
957
|
+
# @raise [ArgumentError] if more than one positional argument follows the
|
|
958
|
+
# name (before any options hash); {#tag_add} silently ignored the extra
|
|
959
|
+
# arguments and tagged the first
|
|
960
|
+
#
|
|
961
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
962
|
+
#
|
|
963
|
+
# @see https://git-scm.com/docs/git-tag git-tag
|
|
964
|
+
#
|
|
965
|
+
def tag_create(name, *args)
|
|
966
|
+
target, options = Private.tag_target_and_options(args, strict: true)
|
|
967
|
+
SharedPrivate.assert_valid_opts!(TAG_CREATE_ALLOWED_OPTS, **options)
|
|
968
|
+
Private.create_tag(@execution_context, name, target, options)
|
|
969
|
+
tag_list(name).first
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
# Create a new tag
|
|
973
|
+
#
|
|
974
|
+
# @overload tag_add(name, options = {})
|
|
975
|
+
#
|
|
976
|
+
# @example Create a lightweight tag on HEAD
|
|
977
|
+
# repo.tag_add('v1.0.0')
|
|
978
|
+
#
|
|
979
|
+
# @example Create an annotated tag on HEAD
|
|
980
|
+
# repo.tag_add('v1.0.0', annotate: true, message: 'Release 1.0.0')
|
|
981
|
+
#
|
|
982
|
+
# @example Replace an existing tag on HEAD
|
|
983
|
+
# repo.tag_add('v1.0.0', force: true)
|
|
984
|
+
#
|
|
985
|
+
# @param name [String] the name of the tag to create
|
|
986
|
+
#
|
|
987
|
+
# @param options [Hash] options for creating the tag (same keys as
|
|
988
|
+
# {#tag_create})
|
|
989
|
+
#
|
|
850
990
|
# @return [Git::Object::Tag] the newly created tag
|
|
851
991
|
#
|
|
852
992
|
# @overload tag_add(name, target, options = {})
|
|
@@ -861,8 +1001,8 @@ module Git
|
|
|
861
1001
|
#
|
|
862
1002
|
# @param target [String] the object to tag (commit SHA, branch name, etc.)
|
|
863
1003
|
#
|
|
864
|
-
# @param options [Hash] options for creating the tag (same keys as
|
|
865
|
-
#
|
|
1004
|
+
# @param options [Hash] options for creating the tag (same keys as
|
|
1005
|
+
# {#tag_create})
|
|
866
1006
|
#
|
|
867
1007
|
# @return [Git::Object::Tag] the newly created tag
|
|
868
1008
|
#
|
|
@@ -893,17 +1033,31 @@ module Git
|
|
|
893
1033
|
#
|
|
894
1034
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
895
1035
|
#
|
|
1036
|
+
# @deprecated Use {#tag_create} instead
|
|
1037
|
+
#
|
|
1038
|
+
# {#tag_create} accepts the same `name`, `target`, and options and
|
|
1039
|
+
# returns a {Git::TagInfo} (an immutable value object) rather than a
|
|
1040
|
+
# {Git::Object::Tag}. It does not accept the `:d`/`:delete` form; use
|
|
1041
|
+
# {#tag_delete} for that. The {Git::Object::Tag} constructor is
|
|
1042
|
+
# deprecated too; this method silences it so one call emits one
|
|
1043
|
+
# warning, except that the `:d`/`:delete` form emits a second warning
|
|
1044
|
+
# of its own.
|
|
1045
|
+
#
|
|
1046
|
+
# @see #tag_create
|
|
1047
|
+
#
|
|
896
1048
|
def tag_add(name, *args)
|
|
897
|
-
|
|
898
|
-
|
|
1049
|
+
Git::Deprecation.warn(
|
|
1050
|
+
'Git::Repository#tag_add is deprecated and will be removed in v6.0.0. ' \
|
|
1051
|
+
'Use Git::Repository#tag_create instead.'
|
|
1052
|
+
)
|
|
1053
|
+
target, options = Private.tag_target_and_options(args)
|
|
899
1054
|
|
|
900
1055
|
return Private.tag_add_delete_deprecated(self, name, target, options) if options[:d] || options[:delete]
|
|
901
1056
|
|
|
902
1057
|
options = options.except(:d, :delete)
|
|
903
|
-
SharedPrivate.assert_valid_opts!(
|
|
904
|
-
Private.
|
|
905
|
-
Git::
|
|
906
|
-
tag(name)
|
|
1058
|
+
SharedPrivate.assert_valid_opts!(TAG_CREATE_ALLOWED_OPTS, **options)
|
|
1059
|
+
Private.create_tag(@execution_context, name, target, options)
|
|
1060
|
+
Git::Deprecation.silence { Git::Object::Tag.new(self, name) }
|
|
907
1061
|
end
|
|
908
1062
|
|
|
909
1063
|
# @overload add_tag(name, options = {})
|
|
@@ -931,7 +1085,14 @@ module Git
|
|
|
931
1085
|
#
|
|
932
1086
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
933
1087
|
#
|
|
934
|
-
# @deprecated Use {#
|
|
1088
|
+
# @deprecated Use {#tag_create} instead
|
|
1089
|
+
#
|
|
1090
|
+
# The warning names {#tag_add}, the replacement this method shipped
|
|
1091
|
+
# with, and {#tag_add} is deprecated as well, so a creation call emits
|
|
1092
|
+
# two warnings: one for this method and one for {#tag_add}. The delete
|
|
1093
|
+
# form `add_tag(name, d: true)` emits a third, for the deprecated `:d`
|
|
1094
|
+
# and `:delete` options on {#tag_add}; use {#tag_delete} for that. Go
|
|
1095
|
+
# straight to {#tag_create} for creation.
|
|
935
1096
|
#
|
|
936
1097
|
def add_tag(name, *)
|
|
937
1098
|
Git::Deprecation.warn(
|
|
@@ -982,6 +1143,82 @@ module Git
|
|
|
982
1143
|
module Private
|
|
983
1144
|
module_function
|
|
984
1145
|
|
|
1146
|
+
# Splits the variadic `*args` of {ObjectOperations#tag_create} and
|
|
1147
|
+
# {ObjectOperations#tag_add} into the target and the options hash
|
|
1148
|
+
#
|
|
1149
|
+
# Both methods accept `(name, opts = {})` and `(name, target, opts = {})`,
|
|
1150
|
+
# so a trailing `Hash` is the options and anything before it is the
|
|
1151
|
+
# target.
|
|
1152
|
+
#
|
|
1153
|
+
# @param args [Array] the arguments after the tag name
|
|
1154
|
+
#
|
|
1155
|
+
# @param strict [Boolean] when `true`, raise instead of silently ignoring
|
|
1156
|
+
# a second positional argument before the options; `tag_create` is
|
|
1157
|
+
# strict, while the deprecated `tag_add` keeps its lenient behavior
|
|
1158
|
+
#
|
|
1159
|
+
# @return [Array((String, nil), Hash)] the two-element tuple
|
|
1160
|
+
# `[target, options]`; `target` is `nil` when only options were given
|
|
1161
|
+
#
|
|
1162
|
+
# @raise [ArgumentError] if `strict` is `true` and more than one
|
|
1163
|
+
# positional argument precedes the options hash
|
|
1164
|
+
#
|
|
1165
|
+
# @api private
|
|
1166
|
+
#
|
|
1167
|
+
def tag_target_and_options(args, strict: false)
|
|
1168
|
+
args = args.dup
|
|
1169
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
1170
|
+
if strict && args.size > 1
|
|
1171
|
+
raise ArgumentError,
|
|
1172
|
+
"Expected at most one target before the options, got #{args.size}: #{args.inspect}"
|
|
1173
|
+
end
|
|
1174
|
+
|
|
1175
|
+
[args.first, options]
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
# Validates the tag-creation options and runs `git tag`
|
|
1179
|
+
#
|
|
1180
|
+
# @param execution_context [Git::ExecutionContext::Repository] the
|
|
1181
|
+
# execution context for git commands
|
|
1182
|
+
#
|
|
1183
|
+
# @param name [String] the name of the tag to create
|
|
1184
|
+
#
|
|
1185
|
+
# @param target [String, nil] the object to tag, or `nil` for HEAD
|
|
1186
|
+
#
|
|
1187
|
+
# @param options [Hash] the tag-creation options, already checked
|
|
1188
|
+
# against the allowed keys (see {ObjectOperations#tag_create} for the
|
|
1189
|
+
# full list)
|
|
1190
|
+
#
|
|
1191
|
+
# @option options [Boolean, nil] :annotate (nil) make an annotated tag;
|
|
1192
|
+
# requires a message (alias: `:a`)
|
|
1193
|
+
#
|
|
1194
|
+
# @option options [Boolean, nil] :sign (nil) make a signed tag; requires
|
|
1195
|
+
# a message (alias: `:s`)
|
|
1196
|
+
#
|
|
1197
|
+
# @option options [String] :local_user (nil) sign with the given key;
|
|
1198
|
+
# requires a message (alias: `:u`)
|
|
1199
|
+
#
|
|
1200
|
+
# @option options [String] :message (nil) the tag message (alias: `:m`)
|
|
1201
|
+
#
|
|
1202
|
+
# @option options [String] :file (nil) a file to read the tag message
|
|
1203
|
+
# from (alias: `:F`)
|
|
1204
|
+
#
|
|
1205
|
+
# @option options [Boolean, nil] :force (nil) replace an existing tag
|
|
1206
|
+
# (alias: `:f`)
|
|
1207
|
+
#
|
|
1208
|
+
# @return [void]
|
|
1209
|
+
#
|
|
1210
|
+
# @raise [ArgumentError] when an annotated or signed tag is requested
|
|
1211
|
+
# without a message
|
|
1212
|
+
#
|
|
1213
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
1214
|
+
#
|
|
1215
|
+
# @api private
|
|
1216
|
+
#
|
|
1217
|
+
def create_tag(execution_context, name, target, options)
|
|
1218
|
+
validate_tag_options!(options)
|
|
1219
|
+
Git::Commands::Tag::Create.new(execution_context).call(name, target, **options)
|
|
1220
|
+
end
|
|
1221
|
+
|
|
985
1222
|
# Validate that a message is present when an annotated or signed tag is
|
|
986
1223
|
# requested
|
|
987
1224
|
#
|
|
@@ -525,7 +525,37 @@ module Git
|
|
|
525
525
|
#
|
|
526
526
|
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
527
527
|
#
|
|
528
|
+
# @deprecated Use `remote_list.find { |r| r.name == name }` for the fields
|
|
529
|
+
# {Git::RemoteInfo} models, or filter {Git::Configuring#config_list} on
|
|
530
|
+
# the `remote.<name>.` key prefix to keep every entry
|
|
531
|
+
#
|
|
532
|
+
# {#remote_list} returns a {Git::RemoteInfo} per remote. Its `url` and
|
|
533
|
+
# `fetch` members hold every configured value as `Array<String>`,
|
|
534
|
+
# whereas this method returns a flat hash in which a repeated `url` or
|
|
535
|
+
# `fetch` key overwrites the earlier value.
|
|
536
|
+
#
|
|
537
|
+
# {Git::RemoteInfo} models only the remote variables git defines and
|
|
538
|
+
# drops any other `remote.<name>.*` entry, whereas this method returns
|
|
539
|
+
# every entry. Callers that read custom keys should filter
|
|
540
|
+
# {Git::Configuring#config_list} instead, which returns the same hash
|
|
541
|
+
# (shown here for the `origin` remote):
|
|
542
|
+
#
|
|
543
|
+
# prefix = 'remote.origin.'
|
|
544
|
+
# repo.config_list
|
|
545
|
+
# .select { |entry| entry.key.start_with?(prefix) }
|
|
546
|
+
# .to_h { |entry| [entry.key.delete_prefix(prefix), entry.value] }
|
|
547
|
+
#
|
|
548
|
+
# @see #remote_list
|
|
549
|
+
#
|
|
550
|
+
# @see Git::Configuring#config_list
|
|
551
|
+
#
|
|
528
552
|
def config_remote(name)
|
|
553
|
+
Git::Deprecation.warn(
|
|
554
|
+
'Git::Repository#config_remote is deprecated and will be removed in v6.0.0. ' \
|
|
555
|
+
'Use Git::Repository#remote_list.find { |r| r.name == name } for the fields ' \
|
|
556
|
+
'Git::RemoteInfo models, or filter Git::Repository#config_list on the ' \
|
|
557
|
+
'"remote.<name>." key prefix to keep every entry.'
|
|
558
|
+
)
|
|
529
559
|
prefix = "remote.#{name}."
|
|
530
560
|
Private.config_list(@execution_context).each_with_object({}) do |(key, value), hsh|
|
|
531
561
|
hsh[key.delete_prefix(prefix)] = value if key.start_with?(prefix)
|
|
@@ -574,7 +604,19 @@ module Git
|
|
|
574
604
|
#
|
|
575
605
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
576
606
|
#
|
|
607
|
+
# @deprecated Use `remote_list.find { |r| r.name == name }` instead
|
|
608
|
+
#
|
|
609
|
+
# {#remote_list} returns immutable {Git::RemoteInfo} value objects
|
|
610
|
+
# rather than {Git::Remote}. Call the corresponding {Git::Repository}
|
|
611
|
+
# method (e.g. {#fetch}, {#remote_remove}) for operations on a remote.
|
|
612
|
+
#
|
|
613
|
+
# @see #remote_list
|
|
614
|
+
#
|
|
577
615
|
def remote(name = 'origin')
|
|
616
|
+
Git::Deprecation.warn(
|
|
617
|
+
'Git::Repository#remote is deprecated and will be removed in v6.0.0. ' \
|
|
618
|
+
'Use Git::Repository#remote_list.find { |r| r.name == name } instead.'
|
|
619
|
+
)
|
|
578
620
|
Git::Remote.new(self, name)
|
|
579
621
|
end
|
|
580
622
|
|
|
@@ -589,7 +631,22 @@ module Git
|
|
|
589
631
|
#
|
|
590
632
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
591
633
|
#
|
|
634
|
+
# @deprecated Use {#remote_list} instead
|
|
635
|
+
#
|
|
636
|
+
# {#remote_list} returns `Array<Git::RemoteInfo>` (immutable value
|
|
637
|
+
# objects) rather than `Array<Git::Remote>`. Call the corresponding
|
|
638
|
+
# {Git::Repository} method (e.g. {#fetch}, {#remote_remove}) for
|
|
639
|
+
# operations on a remote. Each {Git::Remote} this method constructs
|
|
640
|
+
# emits its own deprecation warning, so a call produces one warning
|
|
641
|
+
# for this method plus one per remote returned.
|
|
642
|
+
#
|
|
643
|
+
# @see #remote_list
|
|
644
|
+
#
|
|
592
645
|
def remotes
|
|
646
|
+
Git::Deprecation.warn(
|
|
647
|
+
'Git::Repository#remotes is deprecated and will be removed in v6.0.0. ' \
|
|
648
|
+
'Use Git::Repository#remote_list instead.'
|
|
649
|
+
)
|
|
593
650
|
result = Git::Commands::Remote::List.new(@execution_context).call
|
|
594
651
|
result.stdout.split("\n").map { |name| Git::Remote.new(self, name) }
|
|
595
652
|
end
|
|
@@ -46,6 +46,73 @@ module Git
|
|
|
46
46
|
|
|
47
47
|
raise ArgumentError, "Unknown options: #{unknown.join(', ')}"
|
|
48
48
|
end
|
|
49
|
+
|
|
50
|
+
# Raise unless `branch` names an existing local branch
|
|
51
|
+
#
|
|
52
|
+
# Used by facade methods that check out a branch, do work on it, and switch
|
|
53
|
+
# back. {Git::Repository#checkout} also accepts commit SHAs, tags, and
|
|
54
|
+
# remote-tracking branches, all of which detach HEAD; work committed there
|
|
55
|
+
# would be left dangling once the original branch is restored, and git has
|
|
56
|
+
# no way to report that.
|
|
57
|
+
#
|
|
58
|
+
# @example With an existing local branch
|
|
59
|
+
# SharedPrivate.assert_local_branch!(repo, 'feature') #=> nil
|
|
60
|
+
#
|
|
61
|
+
# @example With a tag
|
|
62
|
+
# SharedPrivate.assert_local_branch!(repo, 'v1.0.0')
|
|
63
|
+
# #=> raises ArgumentError: 'v1.0.0' is not an existing local branch
|
|
64
|
+
#
|
|
65
|
+
# @param repository [Git::Repository] the repository to check
|
|
66
|
+
#
|
|
67
|
+
# @param branch [String] the branch name to verify
|
|
68
|
+
#
|
|
69
|
+
# @return [void]
|
|
70
|
+
#
|
|
71
|
+
# @raise [ArgumentError] when `branch` is not an existing local branch
|
|
72
|
+
#
|
|
73
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
74
|
+
#
|
|
75
|
+
def assert_local_branch!(repository, branch)
|
|
76
|
+
return if repository.local_branch?(branch)
|
|
77
|
+
|
|
78
|
+
raise ArgumentError, "'#{branch}' is not an existing local branch"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns a revision that restores the current HEAD after switching branches
|
|
82
|
+
#
|
|
83
|
+
# Used by facade methods that temporarily check out another branch and
|
|
84
|
+
# then switch back. On a branch, the branch name is enough. When HEAD is
|
|
85
|
+
# detached, {Git::Repository#current_branch} reports `'HEAD'`, which after
|
|
86
|
+
# a checkout resolves to the new branch rather than the original commit,
|
|
87
|
+
# so the commit SHA is captured instead. An unborn branch (one with no
|
|
88
|
+
# commits yet) has no ref to check out by name, so it is rejected here,
|
|
89
|
+
# before the caller switches away from it.
|
|
90
|
+
#
|
|
91
|
+
# @example On a branch
|
|
92
|
+
# SharedPrivate.head_restore_point(repo) #=> "main"
|
|
93
|
+
#
|
|
94
|
+
# @example With a detached HEAD
|
|
95
|
+
# SharedPrivate.head_restore_point(repo) #=> "9b9b31e704c0b85ffdd8d2af2ded85170a5af87d"
|
|
96
|
+
#
|
|
97
|
+
# @param repository [Git::Repository] the repository whose HEAD to record
|
|
98
|
+
#
|
|
99
|
+
# @return [String] the current branch name, or the full HEAD commit SHA
|
|
100
|
+
# when HEAD is detached
|
|
101
|
+
#
|
|
102
|
+
# @raise [Git::Error] when HEAD is on an unborn branch
|
|
103
|
+
#
|
|
104
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
105
|
+
#
|
|
106
|
+
def head_restore_point(repository)
|
|
107
|
+
head = repository.current_branch_state
|
|
108
|
+
case head.state
|
|
109
|
+
when :detached then repository.rev_parse('HEAD').strip
|
|
110
|
+
when :unborn
|
|
111
|
+
raise Git::Error, "HEAD is on the unborn branch '#{head.name}', which cannot be restored " \
|
|
112
|
+
'after switching branches; make a commit on it first'
|
|
113
|
+
else head.name
|
|
114
|
+
end
|
|
115
|
+
end
|
|
49
116
|
end
|
|
50
117
|
|
|
51
118
|
private_constant :SharedPrivate
|