perforce 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +58 -0
- data/install.rb +18 -0
- data/lib/perforce.rb +396 -0
- data/perforce.gemspec +22 -0
- data/test/test_main.rb +84 -0
- metadata +69 -0
data/README
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
= Perforce - Streamlined wrapper for p4ruby.
|
3
|
+
|
4
|
+
The classes Perforce and Perforce::Changelist present a simplified
|
5
|
+
interface to the Perforce API. They encapsulate all the functionality
|
6
|
+
I needed for scripting Perforce in a recent project.
|
7
|
+
|
8
|
+
These are small classes implemented atop P4, the class installed by
|
9
|
+
the P4Ruby package. The underlying P4 object is always available
|
10
|
+
with Perforce#p4. See http://p4ruby.rubyforge.org.
|
11
|
+
|
12
|
+
==== Install
|
13
|
+
|
14
|
+
% gem install perforce
|
15
|
+
|
16
|
+
Or for the regular (non-gem) .tgz package,
|
17
|
+
|
18
|
+
% ruby install.rb [--uninstall]
|
19
|
+
|
20
|
+
==== Download
|
21
|
+
|
22
|
+
* http://rubyforge.org/frs/?group_id=6958
|
23
|
+
|
24
|
+
==== Repository
|
25
|
+
|
26
|
+
* http://github.com/quix/perforce
|
27
|
+
|
28
|
+
==== Credits
|
29
|
+
|
30
|
+
P4Ruby and the Perforce API are Copyright (c) 1997-2008 Perforce
|
31
|
+
Software. All rights reserved.
|
32
|
+
|
33
|
+
This ruby package (perforce.rb and associated files) was written by
|
34
|
+
James M. Lawrence, Copyright (c) 2008 ImaginEngine, Inc.
|
35
|
+
Distributed under the MIT license. This package contains no code
|
36
|
+
owned by Perforce Software, in whole or in part. The following
|
37
|
+
license pertains to this package only.
|
38
|
+
|
39
|
+
Permission is hereby granted, free of charge, to any person
|
40
|
+
obtaining a copy of this software and associated documentation files
|
41
|
+
(the "Software"), to deal in the Software without restriction,
|
42
|
+
including without limitation the rights to use, copy, modify, merge,
|
43
|
+
publish, distribute, sublicense, and/or sell copies of the Software,
|
44
|
+
and to permit persons to whom the Software is furnished to do so,
|
45
|
+
subject to the following conditions:
|
46
|
+
|
47
|
+
The above copyright notice and this permission notice shall be
|
48
|
+
included in all copies or substantial portions of the Software.
|
49
|
+
|
50
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
51
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
52
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
53
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
54
|
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
55
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
56
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
57
|
+
SOFTWARE.
|
58
|
+
|
data/install.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
include FileUtils
|
6
|
+
|
7
|
+
source = "lib/perforce.rb"
|
8
|
+
dest = File.join(Config::CONFIG["sitelibdir"], File.basename(source))
|
9
|
+
|
10
|
+
if ARGV.include? "--uninstall"
|
11
|
+
if File.exist? dest
|
12
|
+
puts "delete #{dest}"
|
13
|
+
rm_f dest
|
14
|
+
end
|
15
|
+
else
|
16
|
+
puts "#{source} --> #{dest}"
|
17
|
+
install source, dest
|
18
|
+
end
|
data/lib/perforce.rb
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
require 'P4'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Perforce -- class representing a connection to a perforce server.
|
7
|
+
#
|
8
|
+
class Perforce
|
9
|
+
CYGWIN = (RUBY_PLATFORM =~ %r!cygwin!) #:nodoc:
|
10
|
+
|
11
|
+
#
|
12
|
+
# Connect to a perforce depot.
|
13
|
+
#
|
14
|
+
# The argument <em>spec</em> is a hash of <em>(method, value)</em>
|
15
|
+
# pairs sent to the underlying P4 object.
|
16
|
+
#
|
17
|
+
# The given values override the P4PORT, P4CLIENT, etc. environment
|
18
|
+
# variables.
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
#
|
22
|
+
# #
|
23
|
+
# # This calls P4#user=, P4#password=, P4#client=, P4#port= with
|
24
|
+
# # these values, then calls P4#connect.
|
25
|
+
# #
|
26
|
+
# Perforce.new(
|
27
|
+
# :user => "iggy_fenton",
|
28
|
+
# :password => "<password or ticket number>",
|
29
|
+
# :client => "iggy_fenton_project",
|
30
|
+
# :port => "server_name:1666")
|
31
|
+
#
|
32
|
+
def initialize(spec = {})
|
33
|
+
#
|
34
|
+
# Remove PWD during creation to avoid some troubles. The user
|
35
|
+
# probably wants perforce to use the absolute path of the current
|
36
|
+
# directory, not a path infected by symlinks.
|
37
|
+
#
|
38
|
+
# Since ~/project was a symlink to my perforce-based project,
|
39
|
+
# perforce would not run when I got there via "cd project" from my
|
40
|
+
# home directory.
|
41
|
+
#
|
42
|
+
@p4 =
|
43
|
+
if self.class.use_pwd_symlinks
|
44
|
+
P4.new
|
45
|
+
else
|
46
|
+
Thread.exclusive {
|
47
|
+
previous_pwd = ENV["PWD"]
|
48
|
+
ENV.delete("PWD")
|
49
|
+
begin
|
50
|
+
P4.new
|
51
|
+
ensure
|
52
|
+
if previous_pwd
|
53
|
+
ENV["PWD"] = previous_pwd
|
54
|
+
end
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
spec.each_pair { |key, value|
|
59
|
+
@p4.send("#{key}=", value)
|
60
|
+
}
|
61
|
+
unless spec.has_key?(:user)
|
62
|
+
# guess user
|
63
|
+
@p4.user = [
|
64
|
+
ENV["USER"],
|
65
|
+
ENV["USERNAME"],
|
66
|
+
].select { |name|
|
67
|
+
name != nil and name != ""
|
68
|
+
}.first.tap { |user|
|
69
|
+
unless user
|
70
|
+
raise "Could not determine username"
|
71
|
+
end
|
72
|
+
}
|
73
|
+
end
|
74
|
+
@p4.exception_level = P4::RAISE_ERRORS
|
75
|
+
@p4.connect
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# The underlying P4 object from the P4Ruby package.
|
80
|
+
#
|
81
|
+
def p4
|
82
|
+
@p4
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Create a Changelist with the given description (a string).
|
87
|
+
#
|
88
|
+
def new_changelist(desc)
|
89
|
+
input = {
|
90
|
+
"Change" => "new",
|
91
|
+
"Description" => desc,
|
92
|
+
}
|
93
|
+
|
94
|
+
number =
|
95
|
+
run_with_input(input, "change", "-i").
|
96
|
+
first.
|
97
|
+
match(%r!\AChange (\d+) created\.!).
|
98
|
+
captures.
|
99
|
+
first
|
100
|
+
|
101
|
+
Changelist.new(self, number)
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Revert these files.
|
106
|
+
#
|
107
|
+
def revert_files(files)
|
108
|
+
unless files.empty?
|
109
|
+
run("revert", *files)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Return the pending changelists (as Changelist objects).
|
115
|
+
#
|
116
|
+
def pending_changelists
|
117
|
+
command = %W(changelists -u #{@p4.user} -c #{@p4.client} -s pending)
|
118
|
+
run(*command).map { |elem|
|
119
|
+
Changelist.new(self, elem["change"].to_i)
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Delete all empty changelists.
|
125
|
+
#
|
126
|
+
def delete_empty_changelists
|
127
|
+
pending_changelists.each { |changelist|
|
128
|
+
changelist.delete
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Calls <code>run("sync", *args)</code>
|
134
|
+
#
|
135
|
+
def sync(*args)
|
136
|
+
run("sync", *args)
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Edit and submit files in one step.
|
141
|
+
#
|
142
|
+
# Example:
|
143
|
+
# perforce.edit_and_submit("remove trailing whitespace", files) {
|
144
|
+
# #
|
145
|
+
# # Do stuff with the files.
|
146
|
+
# # ...
|
147
|
+
# #
|
148
|
+
# }
|
149
|
+
# #
|
150
|
+
# # Changes are submitted when the block ends.
|
151
|
+
# #
|
152
|
+
#
|
153
|
+
def edit_and_submit(changelist_description, files)
|
154
|
+
changelist = new_changelist(changelist_description)
|
155
|
+
changelist.add_files(files)
|
156
|
+
yield
|
157
|
+
changelist.submit
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Client root directory.
|
162
|
+
#
|
163
|
+
def root
|
164
|
+
dir = run(*%w(client -o)).first["Root"]
|
165
|
+
if CYGWIN
|
166
|
+
unix_dir = Util.unix_path(dir)
|
167
|
+
if dir != unix_dir
|
168
|
+
add_unix_root
|
169
|
+
end
|
170
|
+
unix_dir
|
171
|
+
else
|
172
|
+
dir
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if CYGWIN
|
177
|
+
#
|
178
|
+
# <em>Cygwin-only.</em>
|
179
|
+
#
|
180
|
+
# Add a UNIX-style AltRoot.
|
181
|
+
#
|
182
|
+
# This allows P4Win and cygwin to work in the same client spec.
|
183
|
+
#
|
184
|
+
def add_unix_root #:nodoc:
|
185
|
+
client = run(*%w(client -o)).first
|
186
|
+
alt_roots = client["AltRoots"]
|
187
|
+
if alt_roots and alt_roots.include?(Util.unix_path(client["Root"]))
|
188
|
+
# has proper alt root
|
189
|
+
else
|
190
|
+
client["AltRoots"] =
|
191
|
+
alt_roots.to_a + [Util.unix_path(client["Root"])]
|
192
|
+
run_with_input(client, "client", "-i")
|
193
|
+
puts("Note: added unix AltRoot to client")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Change working directory (locally and remotely).
|
200
|
+
#
|
201
|
+
def chdir(dir)
|
202
|
+
previous_dir = File.expand_path(".")
|
203
|
+
Dir.chdir(dir) {
|
204
|
+
@p4.cwd = File.expand_path(".")
|
205
|
+
yield
|
206
|
+
}
|
207
|
+
@p4.cwd = previous_dir
|
208
|
+
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# Call P4#input(input) and then P4#run(*args)
|
212
|
+
#
|
213
|
+
def run_with_input(input, *args)
|
214
|
+
@p4.input = input
|
215
|
+
run(*args)
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# Run a general p4 command.
|
220
|
+
#
|
221
|
+
# Example:
|
222
|
+
# puts "Your server version is: "
|
223
|
+
# puts perforce.run("info").first["serverVersion"]
|
224
|
+
#
|
225
|
+
def run(*args)
|
226
|
+
go = lambda {
|
227
|
+
@p4.run(*args).tap {
|
228
|
+
puts(@p4.warnings)
|
229
|
+
}
|
230
|
+
}
|
231
|
+
if CYGWIN
|
232
|
+
begin
|
233
|
+
go.call
|
234
|
+
rescue P4Exception
|
235
|
+
if @p4.connected?
|
236
|
+
# maybe unix root is not present; try again
|
237
|
+
add_unix_root
|
238
|
+
go.call
|
239
|
+
else
|
240
|
+
raise
|
241
|
+
end
|
242
|
+
end
|
243
|
+
else
|
244
|
+
# not CYGWIN
|
245
|
+
go.call
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
if CYGWIN
|
250
|
+
module Util #:nodoc:
|
251
|
+
def unix_path(dos_path) #:nodoc:
|
252
|
+
escaped_path = dos_path.sub(%r!\\+\Z!, "").gsub("\\", "\\\\\\\\")
|
253
|
+
`cygpath #{escaped_path}`.chomp
|
254
|
+
end
|
255
|
+
extend self
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
@use_pwd_symlinks = true
|
260
|
+
class << self
|
261
|
+
#
|
262
|
+
# Whether the current directory as reported to the perforce server
|
263
|
+
# can contain symlinks. Default is false.
|
264
|
+
#
|
265
|
+
attr_accessor :use_pwd_symlinks
|
266
|
+
end
|
267
|
+
|
268
|
+
#
|
269
|
+
# A Perforce changelist.
|
270
|
+
#
|
271
|
+
# Use Perforce#new_changelist to create a new changelist.
|
272
|
+
#
|
273
|
+
class Changelist
|
274
|
+
def initialize(perforce, number) #:nodoc:
|
275
|
+
@perforce = perforce
|
276
|
+
@number = number
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
# Changelist number.
|
281
|
+
#
|
282
|
+
attr_reader :number
|
283
|
+
|
284
|
+
#
|
285
|
+
# Add files to this Changelist.
|
286
|
+
#
|
287
|
+
# This is used for both editing files and adding new files.
|
288
|
+
#
|
289
|
+
def add_files(files)
|
290
|
+
unless files.empty?
|
291
|
+
@perforce.run("edit", "-c", @number, *files)
|
292
|
+
@perforce.run("add", "-c", @number, *files)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
#
|
297
|
+
# Revert these files in this changelist.
|
298
|
+
#
|
299
|
+
def revert_files(files)
|
300
|
+
unless files.empty?
|
301
|
+
@perforce.run("revert", "-c", @number, *files)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# Open files for deletion. This action is added to the changelist.
|
307
|
+
#
|
308
|
+
def delete_files(files)
|
309
|
+
unless files.empty?
|
310
|
+
@perforce.run("delete", "-c", @number, *files)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
#
|
315
|
+
# Submit this Changelist.
|
316
|
+
#
|
317
|
+
def submit
|
318
|
+
revert_unchanged_files
|
319
|
+
if empty?
|
320
|
+
delete
|
321
|
+
else
|
322
|
+
@perforce.run("submit", "-c", @number)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# True if there are no files in this Changelist.
|
328
|
+
#
|
329
|
+
def empty?
|
330
|
+
not @perforce.run("describe", @number).first.has_key?("depotFile")
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# If empty, delete this Changelist.
|
335
|
+
#
|
336
|
+
def delete
|
337
|
+
if empty?
|
338
|
+
@perforce.run("change", "-d", @number)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
#
|
343
|
+
# Info hash for this Changelist.
|
344
|
+
#
|
345
|
+
def info
|
346
|
+
@perforce.run("change", "-o", @number).first
|
347
|
+
end
|
348
|
+
|
349
|
+
#
|
350
|
+
# Files in this Changelist.
|
351
|
+
#
|
352
|
+
def files
|
353
|
+
info["Files"].to_a
|
354
|
+
end
|
355
|
+
|
356
|
+
#
|
357
|
+
# Description of this changelist
|
358
|
+
#
|
359
|
+
def description
|
360
|
+
info["Description"]
|
361
|
+
end
|
362
|
+
|
363
|
+
#
|
364
|
+
# Status of this changelist
|
365
|
+
#
|
366
|
+
def status
|
367
|
+
info["Status"]
|
368
|
+
end
|
369
|
+
|
370
|
+
#
|
371
|
+
# Revert unchanged files in this Changelist.
|
372
|
+
#
|
373
|
+
def revert_unchanged_files(in_files = nil)
|
374
|
+
files =
|
375
|
+
if in_files.nil?
|
376
|
+
self.files
|
377
|
+
else
|
378
|
+
in_files
|
379
|
+
end
|
380
|
+
|
381
|
+
unless files.empty?
|
382
|
+
@perforce.run("revert", "-a", "-c", @number, *files)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# version < 1.8.7 compatibility
|
389
|
+
unless respond_to? :tap
|
390
|
+
module Kernel #:nodoc:
|
391
|
+
def tap #:nodoc:
|
392
|
+
yield self
|
393
|
+
self
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
data/perforce.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
Gem::Specification.new { |t|
|
3
|
+
t.name = "perforce"
|
4
|
+
t.version = "0.5.0"
|
5
|
+
t.summary = "Streamlined wrapper for p4ruby"
|
6
|
+
t.author = "James M. Lawrence"
|
7
|
+
t.email = "quixoticsycophant@gmail.com"
|
8
|
+
t.rubyforge_project = "perforce"
|
9
|
+
t.homepage = "perforce.rubyforge.org"
|
10
|
+
t.has_rdoc = true
|
11
|
+
t.extra_rdoc_files = ['README']
|
12
|
+
t.rdoc_options += %w{--title Perforce --main README}
|
13
|
+
t.add_dependency('p4ruby')
|
14
|
+
t.files = %w{
|
15
|
+
README
|
16
|
+
perforce.gemspec
|
17
|
+
install.rb
|
18
|
+
lib/perforce.rb
|
19
|
+
test/test_main.rb
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
data/test/test_main.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'perforce'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
def report(desc)
|
7
|
+
if block_given?
|
8
|
+
puts "#{desc}:"
|
9
|
+
pp yield
|
10
|
+
else
|
11
|
+
puts "#{desc}."
|
12
|
+
end
|
13
|
+
puts
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_dummy_file(file)
|
17
|
+
File.open(file, "w") { |out| out.puts "test" }
|
18
|
+
begin
|
19
|
+
yield file
|
20
|
+
ensure
|
21
|
+
File.unlink(file)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
perforce = Perforce.new
|
26
|
+
|
27
|
+
report("Server info") {
|
28
|
+
perforce.run("info").first
|
29
|
+
}
|
30
|
+
|
31
|
+
root = perforce.root
|
32
|
+
|
33
|
+
report("Client root") {
|
34
|
+
root
|
35
|
+
}
|
36
|
+
|
37
|
+
report("Pending changelists") {
|
38
|
+
perforce.pending_changelists
|
39
|
+
}
|
40
|
+
|
41
|
+
perforce.chdir(root) {
|
42
|
+
changelist = perforce.new_changelist("**RUBY TEST**")
|
43
|
+
|
44
|
+
report("Created test changelist: ##{changelist.number}")
|
45
|
+
|
46
|
+
report("Pending changelists") {
|
47
|
+
perforce.pending_changelists
|
48
|
+
}
|
49
|
+
|
50
|
+
with_dummy_file("dummy-test-file-for-ruby-perforce.txt") { |file|
|
51
|
+
changelist.add_files([file])
|
52
|
+
|
53
|
+
report("Added a dummy file to the changelist")
|
54
|
+
|
55
|
+
report("Files in changelist") {
|
56
|
+
changelist.files
|
57
|
+
}
|
58
|
+
|
59
|
+
report("Description for this changelist") {
|
60
|
+
changelist.description
|
61
|
+
}
|
62
|
+
|
63
|
+
report("Status of this changelist") {
|
64
|
+
changelist.status
|
65
|
+
}
|
66
|
+
|
67
|
+
changelist.revert_files([file])
|
68
|
+
|
69
|
+
report("Reverted the dummy file")
|
70
|
+
|
71
|
+
report("Files in changelist") {
|
72
|
+
changelist.files
|
73
|
+
}
|
74
|
+
|
75
|
+
changelist.delete
|
76
|
+
|
77
|
+
report("Deleted changelist")
|
78
|
+
|
79
|
+
report("Pending changelists") {
|
80
|
+
perforce.pending_changelists
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: perforce
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James M. Lawrence
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-07 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: p4ruby
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: quixoticsycophant@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- README
|
35
|
+
- perforce.gemspec
|
36
|
+
- install.rb
|
37
|
+
- lib/perforce.rb
|
38
|
+
- test/test_main.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: perforce.rubyforge.org
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --title
|
44
|
+
- Perforce
|
45
|
+
- --main
|
46
|
+
- README
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project: perforce
|
64
|
+
rubygems_version: 1.2.0
|
65
|
+
signing_key:
|
66
|
+
specification_version: 2
|
67
|
+
summary: Streamlined wrapper for p4ruby
|
68
|
+
test_files: []
|
69
|
+
|