hglib 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,16 +2,28 @@
2
2
 
3
3
  require_relative '../../spec_helper'
4
4
 
5
+ require 'securerandom'
6
+ require 'pathname'
5
7
  require 'hglib/repo/id'
6
8
 
7
9
 
8
- RSpec.describe Hglib::Repo::Id do
10
+ RSpec.describe Hglib::Repo::Id, :requires_binary do
11
+
12
+ let( :repo_dir ) do
13
+ Pathname( Dir.mktmpdir(['hglib', 'repodir']) )
14
+ end
15
+ let( :repo ) { Hglib.init(repo_dir) }
16
+ let( :fake_sha ) { Random.bytes(20).unpack1('h*') }
17
+
9
18
 
10
19
  it "can be created for an empty repo" do
11
- result = described_class.new( '000000000000', 'tip' )
20
+ result = repo.id
12
21
 
13
- expect( result.global ).to eq( '000000000000' )
14
- expect( result ).to eq( '000000000000' )
22
+ expect( result.id ).to eq( described_class::DEFAULT_ID )
23
+ expect( result ).to eq( described_class::DEFAULT_ID )
24
+ expect( result.parents ).to contain_exactly( described_class::DEFAULT_ID )
25
+ expect( result.branch ).to eq( described_class::DEFAULT_BRANCH )
26
+ expect( result.node ).to eq( described_class::DEFAULT_NODE )
15
27
  expect( result.tags ).to contain_exactly( 'tip' )
16
28
  expect( result.bookmarks ).to be_empty
17
29
  expect( result ).to_not have_uncommitted_changes
@@ -19,10 +31,17 @@ RSpec.describe Hglib::Repo::Id do
19
31
 
20
32
 
21
33
  it "can be created for a repo with commits" do
22
- result = described_class.new( 'd03a659966ec', 'tip' )
34
+ newfile = repo_dir + 'README.md'
35
+ newfile.write( <<~END_OF_FILE )
36
+ There is nothing to see here.
37
+ END_OF_FILE
38
+
39
+ repo.addr
40
+ repo.commit( message: "Add stuff." )
23
41
 
24
- expect( result.global ).to eq( 'd03a659966ec' )
25
- expect( result ).to eq( 'd03a659966ec' )
42
+ result = repo.id
43
+
44
+ expect( result.id ).to match( /\A\p{XDigit}{40}\z/ )
26
45
  expect( result.tags ).to contain_exactly( 'tip' )
27
46
  expect( result.bookmarks ).to be_empty
28
47
  expect( result ).to_not have_uncommitted_changes
@@ -30,43 +49,26 @@ RSpec.describe Hglib::Repo::Id do
30
49
 
31
50
 
32
51
  it "can be created for a repo with uncommitted changes" do
33
- result = described_class.new( 'd03a659966ec', 'tip', uncommitted_changes: true )
34
-
35
- expect( result.global ).to eq( 'd03a659966ec' )
36
- expect( result ).to have_uncommitted_changes
37
- end
38
-
39
-
40
- it "can be created for a repo with more than one tag" do
41
- result = described_class.new( 'd03a659966ec', 'qbase', 'qtip', 'repo-features.patch', 'tip' )
42
-
43
- expect( result.global ).to eq( 'd03a659966ec' )
44
- expect( result.tags ).to contain_exactly( 'qbase', 'qtip', 'repo-features.patch', 'tip' )
45
- end
46
-
52
+ newfile = repo_dir + 'README.md'
53
+ newfile.write( <<~END_OF_FILE )
54
+ There is more nothing to see here.
55
+ END_OF_FILE
47
56
 
48
- it "can be created for a repo with a bookmark" do
49
- result = described_class.new( 'd03a659966ec', 'tip', bookmarks: 'master' )
57
+ repo.add
58
+ result = repo.id
50
59
 
51
- expect( result.global ).to eq( 'd03a659966ec' )
52
- expect( result.bookmarks ).to contain_exactly( 'master' )
53
- end
54
-
55
-
56
- it "can be created for a repo with more than one bookmark" do
57
- result = described_class.new( 'd03a659966ec', 'tip', bookmarks: ['master', 'github/master'] )
58
-
59
- expect( result.global ).to eq( 'd03a659966ec' )
60
- expect( result.bookmarks ).to contain_exactly( 'master', 'github/master' )
60
+ expect( result.id ).to match( /\A\p{XDigit}{40}\z/ )
61
+ expect( result ).to have_uncommitted_changes
61
62
  end
62
63
 
63
64
 
64
65
  describe "equality" do
65
66
 
66
67
  it "is equal to an object of the same class with the same values" do
67
- id = described_class.new( 'd03a659966ec',
68
- 'qbase', 'qtip', 'repo-features.patch', 'tip',
69
- uncommitted_changes: true,
68
+ id = described_class.new(
69
+ id: fake_sha,
70
+ tags: ['qbase', 'qtip', 'repo-features.patch', 'tip'],
71
+ dirty: '+',
70
72
  bookmarks: ['master', 'live']
71
73
  )
72
74
 
@@ -77,103 +79,63 @@ RSpec.describe Hglib::Repo::Id do
77
79
 
78
80
 
79
81
  it "is equal to the String that contains the same revision identifier" do
80
- id = described_class.new( 'd03a659966ec',
81
- 'qbase', 'qtip', 'repo-features.patch', 'tip',
82
- uncommitted_changes: true,
83
- bookmarks: ['master', 'live']
84
- )
82
+ id = described_class.new( id: fake_sha )
85
83
 
86
- expect( id ).to eq( 'd03a659966ec' )
84
+ expect( id ).to eq( fake_sha )
87
85
  end
88
86
 
89
87
  end
90
88
 
91
89
 
92
- describe "parsing server output" do
93
-
94
- it "can parse the server output from an empty repo" do
95
- result = described_class.parse( '000000000000 tip' )
96
-
97
- expect( result.global ).to eq( '000000000000' )
98
- expect( result ).to eq( '000000000000' )
99
- expect( result.tags ).to contain_exactly( 'tip' )
100
- expect( result.bookmarks ).to be_empty
101
- expect( result ).to_not have_uncommitted_changes
102
- end
103
-
104
-
105
- it "can be parsed from the server output from a repo with commits" do
106
- result = described_class.parse( 'd03a659966ec tip' )
107
-
108
- expect( result.global ).to eq( 'd03a659966ec' )
109
- expect( result ).to eq( 'd03a659966ec' )
110
- expect( result.tags ).to contain_exactly( 'tip' )
111
- expect( result.bookmarks ).to be_empty
112
- expect( result ).to_not have_uncommitted_changes
113
- end
114
-
115
-
116
- it "can be parsed from the server output from a repo with uncommitted changes" do
117
- result = described_class.parse( 'd03a659966ec+ tip' )
118
-
119
- expect( result.global ).to eq( 'd03a659966ec' )
120
- expect( result ).to have_uncommitted_changes
121
- end
122
-
90
+ describe "stringifying" do
123
91
 
124
- it "can be parsed from the server output from a repo with more than one tag" do
125
- result = described_class.parse( 'd03a659966ec qbase/qtip/repo-features.patch/tip' )
92
+ it "works for the ID of an empty repo" do
93
+ id = repo.id
126
94
 
127
- expect( result.global ).to eq( 'd03a659966ec' )
128
- expect( result.tags ).to contain_exactly( 'qbase', 'qtip', 'repo-features.patch', 'tip' )
95
+ expect( id.to_s ).to eq( '0000000000000000000000000000000000000000 tip' )
129
96
  end
130
97
 
131
98
 
132
- it "can be parsed from the server output from a repo with a bookmark" do
133
- result = described_class.parse( 'd03a659966ec tip master' )
134
-
135
- expect( result.global ).to eq( 'd03a659966ec' )
136
- expect( result.bookmarks ).to contain_exactly( 'master' )
137
- end
99
+ it "works for the ID of a repo with uncommitted changes" do
100
+ newfile = repo_dir + 'README.md'
101
+ newfile.write( <<~END_OF_FILE )
102
+ So much less to see here.
103
+ END_OF_FILE
138
104
 
105
+ repo.add
139
106
 
140
- it "can be parsed from the server output from a repo with more than one bookmark" do
141
- result = described_class.parse( 'd03a659966ec tip master/servant' )
107
+ id = repo.id
142
108
 
143
- expect( result.global ).to eq( 'd03a659966ec' )
144
- expect( result.bookmarks ).to contain_exactly( 'master', 'servant' )
109
+ expect( id.to_s ).to match( /\A\p{XDigit}{40}\+ tip/ )
145
110
  end
146
111
 
147
- end
148
-
149
112
 
150
- describe "stringifying" do
151
-
152
- it "works for the ID of an empty repo" do
153
- id = described_class.new( '000000000000', 'tip' )
154
-
155
- expect( id.to_s ).to eq( '000000000000 tip' )
156
- end
113
+ it "works for the ID of a repo with more than one tag" do
114
+ newfile = repo_dir + 'README.md'
115
+ newfile.write( "A file." )
157
116
 
117
+ repo.add
118
+ repo.commit( message: "Added a README" )
119
+ repo.tag( "v1", "add_readme", "live" )
120
+ repo.update( rev: '-2' )
158
121
 
159
- it "works for the ID of a repo with uncommitted changes" do
160
- id = described_class.new( 'd03a659966ec', 'tip', uncommitted_changes: true )
122
+ id = repo.id
161
123
 
162
- expect( id.to_s ).to eq( 'd03a659966ec+ tip' )
124
+ expect( id.to_s ).to match( %r(\A\p{XDigit}{40} add_readme/live/v1) )
163
125
  end
164
126
 
165
127
 
166
- it "works for the ID of a repo with more than one tag" do
167
- id = described_class.new( 'd03a659966ec', 'qbase', 'qtip', 'repo-features.patch', 'tip' )
168
-
169
- expect( id.to_s ).to eq( 'd03a659966ec qbase/qtip/repo-features.patch/tip' )
170
- end
128
+ it "works for the ID of a repo with a bookmark" do
129
+ newfile = repo_dir + 'README.md'
130
+ newfile.write( "A file." )
171
131
 
132
+ repo.add
133
+ repo.commit( message: "Added a README" )
134
+ repo.bookmark( "master" )
172
135
 
173
- it "works for the ID of a repo with a bookmark" do
174
- id = described_class.new( 'd03a659966ec', 'tip', bookmarks: 'master' )
136
+ id = repo.id
175
137
 
176
- expect( id.to_s ).to eq( 'd03a659966ec tip master' )
138
+ expect( id.to_s ).to match( %r(\A\p{XDigit}{40} tip master) )
177
139
  end
178
140
 
179
141
  end
@@ -9,20 +9,20 @@ require 'hglib/repo/log_entry'
9
9
  RSpec.describe Hglib::Repo::LogEntry do
10
10
 
11
11
  RAW_LOG_ENTRY = {
12
- "bookmarks" => ['master'],
13
- "branch" => "default",
14
- "date" => [1526420446, 25200],
15
- "desc" => "Flesh out the features of Repo objects",
16
- "node" => "d4af915821dea2feca29288dc16742c0d41cee8c",
17
- "parents" => ["a366819bd05b8dd995440105340e057528be25e6"],
18
- "phase" => "public",
19
- "rev" => 5,
20
- "tags" => ['github/master', 'tip'],
21
- "user" => "Michael Granger <ged@FaerieMUD.org>"
12
+ bookmarks: ['master'],
13
+ branch: "default",
14
+ date: [1526420446, 25200],
15
+ desc: "Flesh out the features of Repo objects",
16
+ node: "d4af915821dea2feca29288dc16742c0d41cee8c",
17
+ parents: ["a366819bd05b8dd995440105340e057528be25e6"],
18
+ phase: "public",
19
+ rev: 5,
20
+ tags: ['github/master', 'tip'],
21
+ user: "Michael Granger <ged@FaerieMUD.org>"
22
22
  }.freeze
23
23
 
24
24
  VERBOSE_LOG_ENTRY = RAW_LOG_ENTRY.merge(
25
- "files" => %w[.hoerc .ruby-version lib/hglib/repo.rb spec/hglib/repo_spec.rb]
25
+ files: %w[.hoerc .ruby-version lib/hglib/repo.rb spec/hglib/repo_spec.rb]
26
26
  ).freeze
27
27
 
28
28
 
@@ -62,7 +62,7 @@ RSpec.describe Hglib::Repo::LogEntry do
62
62
  expect( entry.summary ).to eq( 'Flesh out the features of Repo objects' )
63
63
 
64
64
  expect( entry.diff ).to be_nil
65
- expect( entry.files ).to contain_exactly( *VERBOSE_LOG_ENTRY['files'] )
65
+ expect( entry.files ).to contain_exactly( *VERBOSE_LOG_ENTRY[:files] )
66
66
  end
67
67
 
68
68
  end
@@ -19,29 +19,52 @@ RSpec.describe Hglib::Repo do
19
19
  end
20
20
 
21
21
 
22
+ it "returns an empty Array if the working directory is clean" do
23
+ repo = described_class.new( repo_dir )
24
+
25
+ expect( server ).to receive( :run_with_json_template ).
26
+ with( :status, {} ).
27
+ and_return( [] )
28
+
29
+ result = repo.status
30
+
31
+ expect( result ).to be_an( Array ).and be_empty
32
+ end
33
+
34
+
22
35
  it "can fetch the status of the working directory" do
23
36
  repo = described_class.new( repo_dir )
24
37
 
25
- expect( server ).to receive( :run ).with( :status, {} ).
38
+ expect( server ).to receive( :run_with_json_template ).
39
+ with( :status, {} ).
26
40
  and_return([
27
- "M ",
28
- ".gems\n",
29
- "M ",
30
- "lib/hglib/repo.rb\n",
31
- "M ",
32
- "lib/hglib/server.rb\n",
33
- "? ",
34
- "coverage/assets/0.10.2/magnify.png\n"
41
+ {
42
+ path: "lib/hglib/repo.rb",
43
+ status: "!"
44
+ },
45
+ {
46
+ path: "a_new_file.txt",
47
+ status: "?"
48
+ },
49
+ {
50
+ path: "doc/created.rid",
51
+ status: "?"
52
+ },
53
+ {
54
+ path: "lib/hglib/bepo.rb",
55
+ status: "?"
56
+ }
35
57
  ])
36
58
 
37
59
  result = repo.status
38
60
 
39
- expect( result ).to be_a( Hash )
40
- expect( result ).to include(
41
- Pathname('.gems') => 'M',
42
- Pathname('lib/hglib/repo.rb') => 'M',
43
- Pathname('lib/hglib/server.rb') => 'M',
44
- Pathname('coverage/assets/0.10.2/magnify.png') => '?'
61
+ expect( result ).to be_an( Array )
62
+ expect( result ).to all( be_a Hglib::Repo::StatusEntry )
63
+ expect( result.map(&:path) ).to include(
64
+ Pathname('lib/hglib/repo.rb'),
65
+ Pathname('a_new_file.txt'),
66
+ Pathname('doc/created.rid'),
67
+ Pathname('lib/hglib/bepo.rb'),
45
68
  )
46
69
  end
47
70
 
@@ -49,52 +72,56 @@ RSpec.describe Hglib::Repo do
49
72
  it "can fetch the identification of the repository's current revision" do
50
73
  repo = described_class.new( repo_dir )
51
74
 
52
- expect( server ).to receive( :run ).with( :id, {} ).
53
- and_return( ["80d775fc1d2c+ qbase/qtip/repo-features.patch/tip master\n"] )
75
+ expect( server ).to receive( :run_with_json_template ).
76
+ with( :identify, nil, {} ).
77
+ and_return( [{
78
+ bookmarks: ["v1.1", "live", "master"],
79
+ branch: "default",
80
+ dirty: "+",
81
+ id: "720c115412188539039b87baf57931fb5415a0bf+",
82
+ node: "ffffffffffffffffffffffffffffffffffffffff",
83
+ parents: ["720c115412188539039b87baf57931fb5415a0bf"],
84
+ tags: ["tip"]
85
+ }] )
54
86
 
55
87
  result = repo.id
56
88
 
57
- expect( result ).to be_a( Hglib::Repo::Id ).and( eq '80d775fc1d2c' )
58
- expect( result.tags ).to eq( %w[qbase qtip repo-features.patch tip] )
59
- expect( result.bookmarks ).to eq( %w[master] )
89
+ expect( result ).to be_a( Hglib::Repo::Id ).and( eq '720c115412188539039b87baf57931fb5415a0bf' )
90
+ expect( result.tags ).to eq( %w[tip] )
91
+ expect( result.bookmarks ).to eq( %w[v1.1 live master] )
60
92
  end
61
93
 
62
94
 
63
95
  it "can fetch the log of the repository" do
64
96
  repo = described_class.new( repo_dir )
65
97
 
66
- expect( server ).to receive( :run ).with( :log, {T: 'json', graph: false} ).
98
+ expect( server ).to receive( :run_with_json_template ).
99
+ with( :log, {graph: false} ).
67
100
  and_return([
68
- "[",
69
- "\n {\n \"bookmarks\": [],\n \"branch\": \"default\",\n \"date\": " +
70
- "[1516812073, 28800],\n \"desc\": \"Make ruby-version less specific\"," +
71
- "\n \"node\": \"81f357f730d9f22d560e4bd2790e7cf5aa5b7ec7\",\n \"parents\":" +
72
- " [\"d6c97f99b012199d9088e85bb0940147446c6a87\"],\n \"phase\": \"public\",\n " +
73
- " \"rev\": 1,\n \"tags\": [],\n \"user\": \"Michael Granger" +
74
- " <ged@FaerieMUD.org>\"\n }",
75
- ",",
76
- "\n {\n",
77
- " \"bookmarks\": []",
78
- ",\n",
79
- " \"branch\": \"default\"",
80
- ",\n",
81
- " \"date\": [1516811121, 28800]",
82
- ",\n",
83
- " \"desc\": \"Initial commit.\"",
84
- ",\n",
85
- " \"node\": \"d6c97f99b012199d9088e85bb0940147446c6a87\"",
86
- ",\n",
87
- " \"parents\": [\"0000000000000000000000000000000000000000\"]",
88
- ",\n",
89
- " \"phase\": \"public\"",
90
- ",\n",
91
- " \"rev\": 0",
92
- ",\n",
93
- " \"tags\": []",
94
- ",\n",
95
- " \"user\": \"Michael Granger <ged@FaerieMUD.org>\"",
96
- "\n }",
97
- "\n]\n"
101
+ {
102
+ bookmarks: [],
103
+ branch: "default",
104
+ date: [1516812073, 28800],
105
+ desc: "Make ruby-version less specific",
106
+ node: "81f357f730d9f22d560e4bd2790e7cf5aa5b7ec7",
107
+ parents: ["d6c97f99b012199d9088e85bb0940147446c6a87"],
108
+ phase: "public",
109
+ rev: 1,
110
+ tags: [],
111
+ user: "Michael Granger <ged@FaerieMUD.org>"
112
+ },
113
+ {
114
+ bookmarks: [],
115
+ branch: "default",
116
+ date: [1516811121, 28800],
117
+ desc: "Initial commit.",
118
+ node: "d6c97f99b012199d9088e85bb0940147446c6a87",
119
+ parents: ["0000000000000000000000000000000000000000"],
120
+ phase: "public",
121
+ rev: 0,
122
+ tags: [],
123
+ user: "Michael Granger <ged@FaerieMUD.org>"
124
+ }
98
125
  ])
99
126
 
100
127
  result = repo.log
@@ -102,5 +129,172 @@ RSpec.describe Hglib::Repo do
102
129
  expect( result ).to be_an( Array ).and( all be_a(Hglib::Repo::LogEntry) )
103
130
  end
104
131
 
132
+
133
+ it "can fetch a diff of the current working copy of the repository" do
134
+ repo = described_class.new( repo_dir )
135
+
136
+ expect( server ).to receive( :run ).with( :diff, {} ).
137
+ and_return( "the diff" )
138
+
139
+ result = repo.diff
140
+
141
+ expect( result ).to eq( "the diff" )
142
+ end
143
+
144
+
145
+ it "can fetch a diff of particular files" do
146
+ repo = described_class.new( repo_dir )
147
+
148
+ expect( server ).to receive( :run ).with( :diff, 'README.md', 'Rakefile', {} ).
149
+ and_return( "two files diff" )
150
+
151
+ result = repo.diff( 'README.md', 'Rakefile' )
152
+
153
+ expect( result ).to eq( "two files diff" )
154
+ end
155
+
156
+
157
+ it "can add all new files to the repository" do
158
+ repo = described_class.new( repo_dir )
159
+
160
+ expect( server ).to receive( :run ).with( :add, {} )
161
+
162
+ result = repo.add
163
+ expect( result ).to be_truthy
164
+ end
165
+
166
+
167
+ it "can return the current Mercurial configuration" do
168
+ repo = described_class.new( repo_dir )
169
+
170
+ expect( server ).to receive( :run_with_json_template ).
171
+ with( :showconfig, {untrusted: false} ).
172
+ and_return([
173
+ {
174
+ name: "progress.delay",
175
+ source: "/home/jrandom/.hgrc:96",
176
+ value: "0.1"
177
+ },
178
+ {
179
+ name: "progress.refresh",
180
+ source: "/home/jrandom/.hgrc:97",
181
+ value: "0.1"
182
+ },
183
+ {
184
+ name: "progress.format",
185
+ source: "/home/jrandom/.hgrc:98",
186
+ value: "topic bar number"
187
+ },
188
+ {
189
+ name: "progress.clear-complete",
190
+ source: "/home/jrandom/.hgrc:99",
191
+ value: "True"
192
+ }
193
+ ])
194
+
195
+ result = repo.config
196
+
197
+ expect( result ).to be_a( Hglib::Config )
198
+ expect( result['progress.delay'] ).to eq( '0.1' )
199
+ expect( result['progress.format'] ).to eq( 'topic bar number' )
200
+ end
201
+
202
+
203
+ it "can fetch repo aliases" do
204
+ repo = described_class.new( repo_dir )
205
+
206
+ expect( server ).to receive( :run_with_json_template ).
207
+ with( :paths ).
208
+ and_return([
209
+ {name: 'sourcehut', url: 'ssh://hg@hg.sr.ht/~ged/hglib'},
210
+ {name: 'default', url: 'ssh://hg@deveiate.org/hglib'},
211
+ {name: 'github', url: 'git+ssh://git@github.com/ged/hglib.git'}
212
+ ])
213
+
214
+ result = repo.paths
215
+
216
+ expect( result ).to be_a( Hash )
217
+ expect( result ).to eq(
218
+ sourcehut: URI('ssh://hg@hg.sr.ht/~ged/hglib'),
219
+ default: URI('ssh://hg@deveiate.org/hglib'),
220
+ github: URI('git+ssh://git@github.com/ged/hglib.git')
221
+ )
222
+ end
223
+
224
+
225
+ it "can sign revisions" do
226
+ repo = described_class.new( repo_dir )
227
+
228
+ expect( server ).to receive( :run ).
229
+ with( :sign, nil, {} ).
230
+ and_return( "signing 47:66d4e21b7018\n" )
231
+
232
+ result = repo.sign
233
+
234
+ expect( result ).to eq( "signing 47:66d4e21b7018" )
235
+ end
236
+
237
+ describe "version info" do
238
+
239
+ let( :version_info ) {[{
240
+ extensions: [
241
+ {bundled: true, name: "churn", ver: nil},
242
+ {bundled: true, name: "convert", ver: nil},
243
+ {bundled: false, name: "evolve", ver: "9.2.0"},
244
+ {bundled: true, name: "extdiff", ver: nil},
245
+ {bundled: true, name: "gpg", ver: nil},
246
+ {bundled: false, name: "hggit", ver: "0.8.12 (dulwich 0.19.10)"},
247
+ {bundled: true, name: "strip", ver: nil},
248
+ {bundled: true, name: "mq", ver: nil},
249
+ {bundled: false, name: "prompt", ver: nil},
250
+ {bundled: true, name: "purge", ver: nil},
251
+ {bundled: true, name: "rebase", ver: nil},
252
+ {bundled: false, name: "topic", ver: "0.17.0"},
253
+ {bundled: true, name: "histedit", ver: nil}
254
+ ],
255
+ ver: "5.1.1"
256
+ }]}
257
+
258
+ before( :each ) do
259
+ expect( server ).to receive( :run_with_json_template ).
260
+ with( :version ).
261
+ and_return( version_info )
262
+ end
263
+
264
+
265
+ it "can fetch the versions of Mercurial and loaded extensions" do
266
+ repo = described_class.new( repo_dir )
267
+
268
+ result = repo.versions
269
+
270
+ expect( result ).to eq( version_info.first )
271
+ end
272
+
273
+
274
+ it "can fetch the simple version of Mercurial" do
275
+ repo = described_class.new( repo_dir )
276
+
277
+ result = repo.version
278
+
279
+ expect( result ).to eq( version_info.first[:ver] )
280
+ end
281
+
282
+
283
+ it "can fetch the versions of all loaded Mercurial extensions" do
284
+ repo = described_class.new( repo_dir )
285
+
286
+ result = repo.extension_versions
287
+
288
+ expect( result ).to be_a( Hash )
289
+ expect( result ).to include(
290
+ churn: {bundled: true, ver: nil},
291
+ evolve: {bundled: false, ver: '9.2.0'},
292
+ topic: {bundled: false, ver: '0.17.0'},
293
+ hggit: {bundled: false, ver: "0.8.12 (dulwich 0.19.10)"}
294
+ )
295
+ end
296
+
297
+ end
298
+
105
299
  end
106
300