p4ruby 2015.2.1265122-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +24 -0
- data/README.md +866 -0
- data/ext/P4/clientprogressruby.cpp +99 -0
- data/ext/P4/clientprogressruby.h +52 -0
- data/ext/P4/clientuserruby.cpp +726 -0
- data/ext/P4/clientuserruby.h +133 -0
- data/ext/P4/extconf.rb +580 -0
- data/ext/P4/gc_hack.h +10 -0
- data/ext/P4/p4.cpp +1338 -0
- data/ext/P4/p4clientapi.cpp +732 -0
- data/ext/P4/p4clientapi.h +239 -0
- data/ext/P4/p4error.cpp +122 -0
- data/ext/P4/p4error.h +61 -0
- data/ext/P4/p4mapmaker.cpp +459 -0
- data/ext/P4/p4mapmaker.h +69 -0
- data/ext/P4/p4mergedata.cpp +272 -0
- data/ext/P4/p4mergedata.h +97 -0
- data/ext/P4/p4result.cpp +259 -0
- data/ext/P4/p4result.h +86 -0
- data/ext/P4/p4rubydebug.h +46 -0
- data/ext/P4/p4specdata.cpp +108 -0
- data/ext/P4/p4specdata.h +52 -0
- data/ext/P4/p4utils.cpp +62 -0
- data/ext/P4/p4utils.h +46 -0
- data/ext/P4/specmgr.cpp +721 -0
- data/ext/P4/specmgr.h +102 -0
- data/ext/P4/undefdups.h +64 -0
- data/lib/2.0/P4.so +0 -0
- data/lib/2.1/P4.so +0 -0
- data/lib/2.2/P4.so +0 -0
- data/lib/P4.rb +672 -0
- data/lib/P4/version.rb +3 -0
- metadata +75 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
/*******************************************************************************
|
2
|
+
|
3
|
+
Copyright (c) 2001-2008, Perforce Software, Inc. All rights reserved.
|
4
|
+
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
|
26
|
+
*******************************************************************************/
|
27
|
+
|
28
|
+
/*******************************************************************************
|
29
|
+
* Name : clientuserruby.h
|
30
|
+
*
|
31
|
+
* Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
|
32
|
+
*
|
33
|
+
* Description : Ruby bindings for the Perforce API. User interface class
|
34
|
+
* for getting Perforce results into Ruby.
|
35
|
+
*
|
36
|
+
******************************************************************************/
|
37
|
+
|
38
|
+
/*******************************************************************************
|
39
|
+
* ClientUserRuby - the user interface part. Gets responses from the Perforce
|
40
|
+
* server, and converts the data to Ruby form for returning to the caller.
|
41
|
+
******************************************************************************/
|
42
|
+
class SpecMgr;
|
43
|
+
class ClientProgress;
|
44
|
+
|
45
|
+
class ClientUserRuby: public ClientUser, public KeepAlive {
|
46
|
+
public:
|
47
|
+
ClientUserRuby(SpecMgr *s);
|
48
|
+
|
49
|
+
// Client User methods overridden here
|
50
|
+
void OutputText(const char *data, int length);
|
51
|
+
void Message(Error *e);
|
52
|
+
void OutputStat(StrDict *values);
|
53
|
+
void OutputBinary(const char *data, int length);
|
54
|
+
void InputData(StrBuf *strbuf, Error *e);
|
55
|
+
void Diff(FileSys *f1, FileSys *f2, int doPage, char *diffFlags, Error *e);
|
56
|
+
void Prompt(const StrPtr &msg, StrBuf &rsp, int noEcho, Error *e);
|
57
|
+
|
58
|
+
int Resolve(ClientMerge *m, Error *e);
|
59
|
+
int Resolve(ClientResolveA *m, int preview, Error *e);
|
60
|
+
|
61
|
+
ClientProgress* CreateProgress( int type );
|
62
|
+
int ProgressIndicator();
|
63
|
+
|
64
|
+
void Finished();
|
65
|
+
|
66
|
+
// Local methods
|
67
|
+
VALUE SetInput(VALUE i);
|
68
|
+
void SetCommand(const char *c) {
|
69
|
+
cmd = c;
|
70
|
+
}
|
71
|
+
void SetApiLevel(int l);
|
72
|
+
void SetTrack(bool t) {
|
73
|
+
track = t;
|
74
|
+
}
|
75
|
+
|
76
|
+
P4Result& GetResults() {
|
77
|
+
return results;
|
78
|
+
}
|
79
|
+
int ErrorCount();
|
80
|
+
void Reset();
|
81
|
+
|
82
|
+
void RaiseRubyException();
|
83
|
+
|
84
|
+
// GC support
|
85
|
+
void GCMark();
|
86
|
+
|
87
|
+
// Debugging support
|
88
|
+
void SetDebug(int d) {
|
89
|
+
debug = d;
|
90
|
+
}
|
91
|
+
|
92
|
+
// Handler support
|
93
|
+
VALUE SetHandler(VALUE handler);
|
94
|
+
VALUE GetHandler() {
|
95
|
+
return handler;
|
96
|
+
}
|
97
|
+
|
98
|
+
// Progress API support
|
99
|
+
VALUE SetProgress( VALUE p );
|
100
|
+
VALUE GetProgress() {
|
101
|
+
return progress;
|
102
|
+
}
|
103
|
+
|
104
|
+
// override from KeepAlive
|
105
|
+
virtual int IsAlive() {
|
106
|
+
return alive;
|
107
|
+
}
|
108
|
+
|
109
|
+
private:
|
110
|
+
VALUE MkMergeInfo(ClientMerge *m, StrPtr &hint);
|
111
|
+
VALUE MkActionMergeInfo(ClientResolveA *m, StrPtr &hint);
|
112
|
+
void ProcessOutput(const char * method, VALUE data);
|
113
|
+
void ProcessMessage(Error * e);
|
114
|
+
bool CallOutputMethod(const char * method, VALUE data);
|
115
|
+
|
116
|
+
private:
|
117
|
+
StrBuf cmd;
|
118
|
+
SpecMgr * specMgr;
|
119
|
+
P4Result results;
|
120
|
+
VALUE input;
|
121
|
+
VALUE mergeData;
|
122
|
+
VALUE mergeResult;
|
123
|
+
VALUE handler;
|
124
|
+
VALUE cOutputHandler;
|
125
|
+
VALUE progress;
|
126
|
+
VALUE cProgress;
|
127
|
+
int debug;
|
128
|
+
int apiLevel;
|
129
|
+
int alive;
|
130
|
+
int rubyExcept;
|
131
|
+
bool track;
|
132
|
+
};
|
133
|
+
|
data/ext/P4/extconf.rb
ADDED
@@ -0,0 +1,580 @@
|
|
1
|
+
# File: extconf.rb
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'mkmf'
|
6
|
+
require 'net/ftp'
|
7
|
+
require 'P4/version'
|
8
|
+
require 'rbconfig'
|
9
|
+
|
10
|
+
# Set this to the main version directory we look up in ftp.perforce.com for the P4API
|
11
|
+
# This is ignored if you specify the version on the command line.
|
12
|
+
P4API_VERSION_DIR = 'r15.2'
|
13
|
+
|
14
|
+
#==============================================================================
|
15
|
+
# Provide platform variables in P4-specific format
|
16
|
+
|
17
|
+
def p4osplat
|
18
|
+
@p4osplat ||= calculate_p4osplat
|
19
|
+
end
|
20
|
+
|
21
|
+
def calculate_p4osplat
|
22
|
+
plat = RbConfig::CONFIG['arch'].split(/-/)[0].upcase
|
23
|
+
|
24
|
+
# On Mac OSX, fix the build to 64 bit arch
|
25
|
+
if p4osname == 'DARWIN'
|
26
|
+
plat = 'X86_64'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Translate Ruby's arch names into Perforce's. Mostly the same so
|
30
|
+
# only the exceptions are handled here.
|
31
|
+
case plat
|
32
|
+
when /^I.86$/
|
33
|
+
plat = 'X86'
|
34
|
+
when /^AMD64$/
|
35
|
+
plat = 'X86_64'
|
36
|
+
when 'POWERPC'
|
37
|
+
plat = 'PPC'
|
38
|
+
end
|
39
|
+
|
40
|
+
return plat
|
41
|
+
end
|
42
|
+
|
43
|
+
def p4osname
|
44
|
+
@p4osname ||= calculate_p4osname
|
45
|
+
end
|
46
|
+
|
47
|
+
def calculate_p4osname
|
48
|
+
osname = RbConfig::CONFIG['arch'].split(/-/)[1].upcase
|
49
|
+
osname = osname.gsub(/MSWIN32(_\d+)?/, "NT")
|
50
|
+
osname = osname.split('-').shift
|
51
|
+
|
52
|
+
case osname
|
53
|
+
when /FREEBSD/
|
54
|
+
osname = 'FREEBSD'
|
55
|
+
when /DARWIN/
|
56
|
+
osname = 'DARWIN'
|
57
|
+
when /AIX/
|
58
|
+
osname = 'AIX'
|
59
|
+
when /SOLARIS/
|
60
|
+
osname = 'SOLARIS'
|
61
|
+
end
|
62
|
+
|
63
|
+
return osname
|
64
|
+
end
|
65
|
+
|
66
|
+
def p4osver
|
67
|
+
@p4osver ||= calculate_p4osver
|
68
|
+
end
|
69
|
+
|
70
|
+
def calculate_p4osver
|
71
|
+
ver = ''
|
72
|
+
|
73
|
+
case p4osname
|
74
|
+
when 'NT'
|
75
|
+
# do nothing
|
76
|
+
when /MINGW/
|
77
|
+
# do nothing
|
78
|
+
when /FREEBSD([0-9]+)/
|
79
|
+
ver = $1
|
80
|
+
when /DARWIN/
|
81
|
+
ver = CONFIG['arch'].upcase.gsub(/.*DARWIN(\d+).*/, '\1')
|
82
|
+
when /AIX(5)\.(\d)/
|
83
|
+
ver = $1 + $2
|
84
|
+
when /SOLARIS2\.(\d+)/
|
85
|
+
ver = $1
|
86
|
+
else
|
87
|
+
# use uname -r to see if it works
|
88
|
+
begin
|
89
|
+
ver=`uname -r`.chomp
|
90
|
+
ver_re = /^(\d+)\.(\d+)/
|
91
|
+
md = ver_re.match(ver)
|
92
|
+
if (md)
|
93
|
+
maj = md[1].to_i
|
94
|
+
min = md[2].to_i
|
95
|
+
ver = maj.to_s + min.to_s
|
96
|
+
end
|
97
|
+
rescue
|
98
|
+
# Nothing - if it failed, it failed.
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
return ver
|
103
|
+
end
|
104
|
+
|
105
|
+
def uname_platform
|
106
|
+
@uname_platform ||= calculate_uname_platform
|
107
|
+
end
|
108
|
+
|
109
|
+
def calculate_uname_platform
|
110
|
+
plat = "UNKNOWN"
|
111
|
+
begin
|
112
|
+
plat = `uname -p`
|
113
|
+
plat = plat.chomp.upcase
|
114
|
+
rescue
|
115
|
+
# Nothing - if it failed, it failed.
|
116
|
+
end
|
117
|
+
plat
|
118
|
+
end
|
119
|
+
|
120
|
+
#==============================================================================
|
121
|
+
# Setup additional compiler and linker options.
|
122
|
+
#
|
123
|
+
# We generally need to launch these things before we configure most of the flags.
|
124
|
+
# (See the main script at the end.)
|
125
|
+
|
126
|
+
def set_platform_opts
|
127
|
+
|
128
|
+
# Expand any embedded variables (like '$(CC)')
|
129
|
+
CONFIG["CC"] = RbConfig::CONFIG["CC"]
|
130
|
+
CONFIG["LDSHARED"] = RbConfig::CONFIG["LDSHARED"]
|
131
|
+
|
132
|
+
# Make sure we have a CXX value (sometimes there isn't one)
|
133
|
+
CONFIG["CXX"] = CONFIG["CC"] unless CONFIG.has_key?("CXX")
|
134
|
+
|
135
|
+
# O/S specific oddities
|
136
|
+
|
137
|
+
case p4osname
|
138
|
+
when /DARWIN/
|
139
|
+
CONFIG['CC'] = 'xcrun c++'
|
140
|
+
CONFIG['CXX'] = 'xcrun c++'
|
141
|
+
CONFIG['LDSHARED'] = CONFIG['CXX'] + ' -bundle'
|
142
|
+
when /FREEBSD/, /LINUX/
|
143
|
+
# FreeBSD 6 and some Linuxes use 'cc' for linking by default. The
|
144
|
+
# gcc detection patterns above won't catch that, so for these
|
145
|
+
# platforms, we specifically convert cc to c++.
|
146
|
+
CONFIG['LDSHARED'].sub!(/^cc/, 'c++')
|
147
|
+
when /MINGW32/
|
148
|
+
# When building with MinGW we need to statically link libgcc
|
149
|
+
# and make sure we're linking with gcc and not g++. On older
|
150
|
+
# Rubies, they use LDSHARED; newer ones (>=1.9) use LDSHAREDXX
|
151
|
+
CONFIG['LDSHARED'].sub!(/g\+\+/, 'gcc')
|
152
|
+
CONFIG['LDSHAREDXX'].sub!(/g\+\+/, 'gcc')
|
153
|
+
CONFIG['LDSHARED'] = CONFIG['LDSHARED'] + ' -static-libgcc'
|
154
|
+
CONFIG['LDSHAREDXX'] = CONFIG['LDSHARED'] + ' -static-libgcc'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def set_platform_cppflags
|
159
|
+
$CPPFLAGS += "-DOS_#{p4osname} "
|
160
|
+
$CPPFLAGS += "-DOS_#{p4osname}#{p4osver} "
|
161
|
+
$CPPFLAGS += "-DOS_#{p4osname}#{p4osver}#{p4osplat} "
|
162
|
+
|
163
|
+
if (p4osname == 'NT')
|
164
|
+
$CPPFLAGS += '/DCASE_INSENSITIVE '
|
165
|
+
end
|
166
|
+
|
167
|
+
if (p4osname == 'MINGW32')
|
168
|
+
$CPPFLAGS += '-DOS_NT -DCASE_INSENSITIVE '
|
169
|
+
end
|
170
|
+
|
171
|
+
if (p4osname == 'SOLARIS')
|
172
|
+
$CPPFLAGS += '-Dsolaris '
|
173
|
+
end
|
174
|
+
|
175
|
+
if (p4osname == 'DARWIN')
|
176
|
+
$CPPFLAGS += '-DCASE_INSENSITIVE '
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def set_platform_cflags
|
181
|
+
if (p4osname == 'DARWIN')
|
182
|
+
# Only build for 64 bit if we have more than one arch defined in CFLAGS
|
183
|
+
$CFLAGS.slice!("-arch i386")
|
184
|
+
$CFLAGS.slice!("-arch ppc");
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Initialize the base sets of platform libraries *before other initializers*
|
189
|
+
# to preserve linking order.
|
190
|
+
def set_platform_libs
|
191
|
+
|
192
|
+
case p4osname
|
193
|
+
when 'SOLARIS'
|
194
|
+
osver = `uname -r`
|
195
|
+
osver.gsub!(/5\./, '2')
|
196
|
+
if (osver == '25')
|
197
|
+
$LDFLAGS += '/usr/ucblib/libucb.a '
|
198
|
+
end
|
199
|
+
have_library('nsl')
|
200
|
+
have_library('socket')
|
201
|
+
when 'NT'
|
202
|
+
have_library('advapi32')
|
203
|
+
have_library('wsock32')
|
204
|
+
have_library('kernel32')
|
205
|
+
have_library('oldnames')
|
206
|
+
when 'CYGWIN'
|
207
|
+
# Clear out 'bogus' libs on cygwin
|
208
|
+
CONFIG['LIBS'] = ''
|
209
|
+
when 'DARWIN'
|
210
|
+
if p4osver.to_i >= 8
|
211
|
+
# Only build for 64 bit if we have more than one arch defined in CFLAGS
|
212
|
+
$LDFLAGS.slice!('-arch i386')
|
213
|
+
$LDFLAGS.slice!('-arch ppc')
|
214
|
+
$LDFLAGS += ' -framework CoreFoundation -framework Foundation'
|
215
|
+
end
|
216
|
+
when 'LINUX', 'MINGW32'
|
217
|
+
have_library('supc++')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
#==============================================================================
|
222
|
+
# Manage p4api version
|
223
|
+
#
|
224
|
+
# The p4ruby implementation has some branching to support different versions
|
225
|
+
# of the C++ API. So we need to generate a p4rubyconf.h file that will setup
|
226
|
+
# this #define based branching based on the C++ API being compiled against.
|
227
|
+
|
228
|
+
# This captures the version information of the P4API C++ library we're building
|
229
|
+
# against. This is mostly parsed into this structure and then spit out into
|
230
|
+
# a header file we compile into the Ruby API.
|
231
|
+
class P4ApiVersion
|
232
|
+
|
233
|
+
def P4ApiVersion.load(dir)
|
234
|
+
#
|
235
|
+
# 2007.2 and later APIs put the Version file in the 'sample'
|
236
|
+
# subdirectory. Look there if we can't find it in the API root
|
237
|
+
#
|
238
|
+
ver_file = dir + "/Version"
|
239
|
+
unless File.exists?(ver_file)
|
240
|
+
ver_file = dir + "/sample/Version"
|
241
|
+
return nil unless File.exists?(ver_file)
|
242
|
+
end
|
243
|
+
|
244
|
+
re = Regexp.new('^RELEASE = (\d+)\s+(\d+)\s+(\w*\S*)\s*;')
|
245
|
+
rp = Regexp.new('^PATCHLEVEL = (.*)\s*;')
|
246
|
+
rs = Regexp.new('^SUPPDATE = (.*)\s*;')
|
247
|
+
|
248
|
+
p4api_version = nil
|
249
|
+
|
250
|
+
File.open(ver_file, "r") do
|
251
|
+
|f|
|
252
|
+
f.each_line do
|
253
|
+
|line|
|
254
|
+
if md = re.match(line)
|
255
|
+
p4api_version = P4ApiVersion.new(md[1], md[2])
|
256
|
+
p4api_version.set_type(md[3])
|
257
|
+
elsif md = rp.match(line)
|
258
|
+
p4api_version.patchlevel = md[1]
|
259
|
+
elsif md = rs.match(line)
|
260
|
+
p4api_version.suppdate = md[1]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
puts("Found #{p4api_version} Perforce API in #{dir}")
|
265
|
+
return p4api_version
|
266
|
+
end
|
267
|
+
|
268
|
+
def initialize(major, minor = nil)
|
269
|
+
if (major.kind_of?(String) && !minor)
|
270
|
+
if (major =~ /(\d+)\.(\d+)/)
|
271
|
+
major = $1
|
272
|
+
minor = $2
|
273
|
+
else
|
274
|
+
raise("Bad API version: #{major}")
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
@major = major.to_i
|
279
|
+
@minor = minor.to_i
|
280
|
+
@type = nil
|
281
|
+
|
282
|
+
@patchlevel = nil
|
283
|
+
@suppdate = nil
|
284
|
+
end
|
285
|
+
|
286
|
+
def set_type(type)
|
287
|
+
if (type.kind_of?(String))
|
288
|
+
@type = type
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
attr_accessor :patchlevel, :suppdate
|
293
|
+
attr_reader :major, :minor, :type
|
294
|
+
|
295
|
+
include Comparable
|
296
|
+
|
297
|
+
def to_s
|
298
|
+
if (@type and not @type.empty?)
|
299
|
+
"#{major}.#{minor}.#{@type.upcase}"
|
300
|
+
else
|
301
|
+
"#{major}.#{minor}"
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def to_i
|
306
|
+
major << 8 | minor
|
307
|
+
end
|
308
|
+
|
309
|
+
def <=>(other)
|
310
|
+
hi = @major <=> other.major
|
311
|
+
lo = @minor <=> other.minor
|
312
|
+
|
313
|
+
return hi == 0 ? lo : hi
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def macro_def(macro, value, string=true)
|
318
|
+
if (string)
|
319
|
+
%Q{#define #{macro}\t"#{value}"}
|
320
|
+
else
|
321
|
+
%Q{#define #{macro}\t#{value}}
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def create_p4rubyconf_header(p4api_version, libs)
|
326
|
+
File.open("p4rubyconf.h", "w") do
|
327
|
+
|ch|
|
328
|
+
ch.puts(macro_def("P4APIVER_STRING", p4api_version.to_s))
|
329
|
+
ch.puts(macro_def("P4APIVER_ID", p4api_version.to_i, false))
|
330
|
+
ch.puts(macro_def("P4API_PATCHLEVEL", p4api_version.patchlevel, false))
|
331
|
+
ch.puts(macro_def("P4API_PATCHLEVEL_STRING", p4api_version.patchlevel.to_s))
|
332
|
+
ch.puts(macro_def("P4RUBY_VERSION", P4::VERSION))
|
333
|
+
ch.puts(macro_def("WITH_LIBS", libs, true))
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
#==============================================================================
|
338
|
+
# P4API (C++ API) Helpers
|
339
|
+
#
|
340
|
+
# We do not have system installers yet, so allow most people to just get a
|
341
|
+
# version downloaded if since they very likely do not care about it.
|
342
|
+
|
343
|
+
# If the user has *not* specified --with-p4api-dir, check the --enable-p4api-download
|
344
|
+
# flag, and download the p4api before proceeding, unless that's disabled.
|
345
|
+
#
|
346
|
+
# This may be a little confusing. If people specify --with-p4api-dir, we want
|
347
|
+
# use only use that setting. If that setting is wrong, we want to fail.
|
348
|
+
#
|
349
|
+
# If they don't set the --with-p4api-dir, we'll proceed as if --enable-p4api-download
|
350
|
+
# has been set. Otherwise, they can --disable-p4api-download to ensure we
|
351
|
+
# just don't bother doing anything.
|
352
|
+
def resolve_p4api_dir
|
353
|
+
p4api_dir = nil
|
354
|
+
|
355
|
+
# When running rake compile, use this instead of other options, I'm not sure how
|
356
|
+
# gem/bundler options are passed through via rake
|
357
|
+
if ENV.has_key?('p4api_dir')
|
358
|
+
p4api_dir = ENV['p4api_dir']
|
359
|
+
dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
|
360
|
+
end
|
361
|
+
|
362
|
+
if !p4api_dir && !with_config('p4api-dir') && enable_config('p4api-download', true)
|
363
|
+
download_api_via_ftp
|
364
|
+
unzip_file
|
365
|
+
p4api_dir = downloaded_p4api_dir
|
366
|
+
dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
|
367
|
+
elsif with_config('p4api_dir')
|
368
|
+
p4api_dir = with_config('p4api-dir')
|
369
|
+
dir_config('p4api', "#{p4api_dir}/include", "#{p4api_dir}/lib")
|
370
|
+
elsif !p4api_dir
|
371
|
+
raise '--with-p4api-dir option has not been specified, and --disable-p4api-download is in effect'
|
372
|
+
end
|
373
|
+
|
374
|
+
p4api_dir
|
375
|
+
end
|
376
|
+
|
377
|
+
def resolve_ssl_dirs
|
378
|
+
ssl_dir = nil
|
379
|
+
# When running rake compile, use this instead of other options, I'm not sure how
|
380
|
+
# gem/bundler options are passed through via rake
|
381
|
+
if ENV.has_key?('ssl_dir')
|
382
|
+
ssl_dir = ENV['ssl_dir']
|
383
|
+
dir_config('ssl', "#{ssl_dir}/include", "#{ssl_dir}/lib")
|
384
|
+
puts "SSL Path #{ssl_dir}"
|
385
|
+
end
|
386
|
+
if ENV.has_key?('ssl_include_dir') && ENV.has_key?('ssl_lib_dir')
|
387
|
+
ssl_include_dir = ENV['ssl_include_dir']
|
388
|
+
ssl_lib_dir = ENV['ssl_lib_dir']
|
389
|
+
dir_config('ssl', ssl_include_dir, ssl_lib_dir)
|
390
|
+
puts "SSL Includes #{ssl_include_dir} Lib #{ssl_lib_dir}"
|
391
|
+
end
|
392
|
+
ssl_dir
|
393
|
+
end
|
394
|
+
|
395
|
+
# Our 'cpu' label we use as part of the directory name on ftp.perforce.com
|
396
|
+
def p4_cpu(os)
|
397
|
+
cpu = RbConfig::CONFIG['target_cpu']
|
398
|
+
case os
|
399
|
+
when :darwin, :linux
|
400
|
+
if cpu =~ /i686/
|
401
|
+
'x86'
|
402
|
+
else
|
403
|
+
cpu
|
404
|
+
end
|
405
|
+
else
|
406
|
+
case cpu
|
407
|
+
when /ia/i
|
408
|
+
'ia64'
|
409
|
+
else
|
410
|
+
cpu
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
# The p4_platform is our label that basically ends up being part of the
|
416
|
+
# directory name where we can download files from.
|
417
|
+
def p4_platform_label
|
418
|
+
case RbConfig::CONFIG["target_os"].downcase
|
419
|
+
when /nt|mswin|mingw/
|
420
|
+
# Ruby on windows is only MinGW via Rubyinstaller.org, though this may
|
421
|
+
# not work on all rubies.
|
422
|
+
if RbConfig::CONFIG['MAJOR'].to_i >= 2
|
423
|
+
# Note that x64 or x86 needs to be suffixed to this
|
424
|
+
'mingw64'
|
425
|
+
else
|
426
|
+
'mingwx86'
|
427
|
+
end
|
428
|
+
when /darwin/
|
429
|
+
"darwin90#{p4_cpu(:darwin)}"
|
430
|
+
when /solaris/
|
431
|
+
"solaris10#{p4_cpu(:solaris)}"
|
432
|
+
when /linux/
|
433
|
+
"linux26#{p4_cpu(:linux)}"
|
434
|
+
when /cygwin/
|
435
|
+
raise 'cygwin is not supported for the --download-p4api option'
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def platform_dir_name
|
440
|
+
"bin.#{p4_platform_label}"
|
441
|
+
end
|
442
|
+
|
443
|
+
def ftp_download_dir(version)
|
444
|
+
"perforce/#{version}/#{platform_dir_name}"
|
445
|
+
end
|
446
|
+
|
447
|
+
def filename
|
448
|
+
if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
|
449
|
+
'p4api.zip'
|
450
|
+
else
|
451
|
+
'p4api.tgz'
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def remote_files_matching(ftp, dir, regex)
|
456
|
+
ftp.ls(dir.to_s).map { |entry|
|
457
|
+
if match = entry.match(regex)
|
458
|
+
yield match
|
459
|
+
else
|
460
|
+
nil
|
461
|
+
end
|
462
|
+
}.reject { |entry|
|
463
|
+
entry.nil?
|
464
|
+
}
|
465
|
+
end
|
466
|
+
|
467
|
+
def find_latest_with_p4api(ftp, versions)
|
468
|
+
versions.reverse_each { |v|
|
469
|
+
begin
|
470
|
+
remote_files_matching(ftp, "r#{v}/#{platform_dir_name}/", /p4api/) do
|
471
|
+
return v
|
472
|
+
end
|
473
|
+
rescue
|
474
|
+
next
|
475
|
+
end
|
476
|
+
}
|
477
|
+
end
|
478
|
+
|
479
|
+
def find_latest_version_dir(ftp)
|
480
|
+
ftp.chdir('perforce')
|
481
|
+
|
482
|
+
# Capture all versions
|
483
|
+
versions = remote_files_matching(ftp, '.', /r(1\d\.\d)/) { |m| m.captures.first }.sort
|
484
|
+
|
485
|
+
version = find_latest_with_p4api(ftp, versions)
|
486
|
+
|
487
|
+
ftp.chdir('..')
|
488
|
+
|
489
|
+
"r#{version}"
|
490
|
+
end
|
491
|
+
|
492
|
+
# Downloads the C++ P4API via FTP to the local directory, then 'initializes' it
|
493
|
+
# by unpacking it.
|
494
|
+
def download_api_via_ftp
|
495
|
+
ftp = Net::FTP.new('ftp.perforce.com')
|
496
|
+
ftp.passive=true
|
497
|
+
ftp.login
|
498
|
+
|
499
|
+
# At one point, we allowed the gem build to just find the most recent p4api build.
|
500
|
+
# P4Ruby probably shouldn't do that by default.
|
501
|
+
#version_dir = find_latest_version_dir(ftp)
|
502
|
+
version_dir = P4API_VERSION_DIR
|
503
|
+
|
504
|
+
dir = ftp_download_dir(version_dir)
|
505
|
+
ftp.chdir(dir)
|
506
|
+
|
507
|
+
puts "downloading #{filename} from #{dir} on ftp.perforce.com"
|
508
|
+
ftp.getbinaryfile(filename)
|
509
|
+
|
510
|
+
ensure
|
511
|
+
ftp.close if ftp and !ftp.closed?
|
512
|
+
end
|
513
|
+
|
514
|
+
def unzip_file
|
515
|
+
if RbConfig::CONFIG['target_os'].downcase =~ /nt|mswin|mingw/
|
516
|
+
`unzip #{filename}`
|
517
|
+
else
|
518
|
+
`tar xzf #{filename}`
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def downloaded_p4api_dir
|
523
|
+
File.expand_path(Dir.entries('.').select { |x| x =~ /^p4api/ and File.directory?(x) }.first)
|
524
|
+
end
|
525
|
+
|
526
|
+
#==============================================================================
|
527
|
+
# Main script
|
528
|
+
|
529
|
+
puts "p4osname #{p4osname}"
|
530
|
+
puts "p4osver #{p4osver}"
|
531
|
+
|
532
|
+
# Specify different toolsets based on the platform type.
|
533
|
+
set_platform_opts
|
534
|
+
|
535
|
+
# We setup these flags in the beginning, before any libraries are detected,
|
536
|
+
# based solely on platform detection.
|
537
|
+
set_platform_cppflags
|
538
|
+
set_platform_cflags
|
539
|
+
|
540
|
+
puts "$CPPFLAGS #{$CPPFLAGS}"
|
541
|
+
puts "$CFLAGS #{$CFLAGS}"
|
542
|
+
|
543
|
+
# Setup additional system library definitions based on platform type before
|
544
|
+
# we setup other libraries, in order to preserve linking order
|
545
|
+
set_platform_libs
|
546
|
+
|
547
|
+
puts "$LDFLAGS #{$LDFLAGS}"
|
548
|
+
|
549
|
+
p4api_dir = resolve_p4api_dir
|
550
|
+
puts "P4API Path #{p4api_dir}"
|
551
|
+
|
552
|
+
resolve_ssl_dirs
|
553
|
+
|
554
|
+
# If we happen to need SSL on Windows, we also need gdi32
|
555
|
+
if RbConfig::CONFIG['target_os'].downcase =~ /mingw/
|
556
|
+
have_library('gdi32') or raise
|
557
|
+
end
|
558
|
+
|
559
|
+
do_ssl = have_library('crypto') and have_library('ssl')
|
560
|
+
|
561
|
+
unless do_ssl
|
562
|
+
have_library('p4sslstub') or raise
|
563
|
+
end
|
564
|
+
|
565
|
+
have_library('supp') or raise
|
566
|
+
have_library('rpc') or raise
|
567
|
+
have_library('client') or raise
|
568
|
+
|
569
|
+
puts "$libs #{$libs}"
|
570
|
+
|
571
|
+
# Parse the Version file into a ruby structure
|
572
|
+
version_info = P4ApiVersion.load(p4api_dir)
|
573
|
+
create_p4rubyconf_header(version_info, $libs)
|
574
|
+
|
575
|
+
# This will generate a standard extconf.h based on what we discover locally.
|
576
|
+
# These are typically just 'yes I have such and such a library', which I
|
577
|
+
# don't believe we need to rely on actually.
|
578
|
+
create_header
|
579
|
+
|
580
|
+
create_makefile('P4')
|