p4ruby 2022.1.2359956-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,841 @@
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 : p4clientapi.cc
30
+ *
31
+ * Author : Tony Smith <tony@perforce.com> or <tony@smee.org>
32
+ *
33
+ * Description : Ruby bindings for the Perforce API. Main interface to the
34
+ * Perforce API.
35
+ *
36
+ ******************************************************************************/
37
+ #include <ruby.h>
38
+ #include "undefdups.h"
39
+ #include <p4/clientapi.h>
40
+ #include <p4/strtable.h>
41
+ #include <p4/i18napi.h>
42
+ #include <p4/enviro.h>
43
+ #include <p4/hostenv.h>
44
+ #include <p4/spec.h>
45
+ #include <p4/ignore.h>
46
+ #include <p4/debug.h>
47
+ #include "p4result.h"
48
+ #include "p4rubydebug.h"
49
+ #include "clientuserruby.h"
50
+ #include "specmgr.h"
51
+ #include "p4clientapi.h"
52
+ #include "p4utils.h"
53
+
54
+
55
+
56
+ /*******************************************************************************
57
+ * Our Ruby classes.
58
+ ******************************************************************************/
59
+ extern VALUE cP4; // Base P4 class
60
+ extern VALUE eP4; // Exception class
61
+
62
+
63
+ P4ClientApi::P4ClientApi() : ui( &specMgr )
64
+ {
65
+ debug = 0;
66
+ server2 = 0;
67
+ depth = 0;
68
+ exceptionLevel = 2;
69
+ maxResults = 0;
70
+ maxScanRows = 0;
71
+ maxLockTime = 0;
72
+ InitFlags();
73
+ apiLevel = atoi( P4Tag::l_client );
74
+ enviro = new Enviro;
75
+ prog = "unnamed p4ruby script";
76
+
77
+ client.SetProtocol( "specstring", "" );
78
+
79
+ //
80
+ // Load any P4CONFIG file
81
+ //
82
+ HostEnv henv;
83
+ StrBuf cwd;
84
+
85
+ henv.GetCwd( cwd, enviro );
86
+ if( cwd.Length() )
87
+ enviro->Config( cwd );
88
+
89
+ //
90
+ // Load the current ticket file. Start with the default, and then
91
+ // override it if P4TICKETS is set.
92
+ //
93
+ const char *t;
94
+
95
+ henv.GetTicketFile( ticketFile );
96
+
97
+ if( (t = enviro->Get("P4TICKETS")) )
98
+ ticketFile = t;
99
+
100
+ //
101
+ // Load the current trust file. Start with the default, and then
102
+ // override it if P4TRUST is set.
103
+ //
104
+
105
+ henv.GetTrustFile( trustFile );
106
+
107
+ if( (t = enviro->Get("P4TICKETS")) )
108
+ trustFile = t;
109
+
110
+ //
111
+ // Load the current P4CHARSET if set.
112
+ //
113
+ if( client.GetCharset().Length() )
114
+ SetCharset( client.GetCharset().Text() );
115
+ }
116
+
117
+ P4ClientApi::~P4ClientApi()
118
+ {
119
+ if ( IsConnected() )
120
+ {
121
+ Error e;
122
+ client.Final( &e );
123
+ // Ignore errors
124
+ }
125
+ delete enviro;
126
+ }
127
+
128
+ const char *
129
+ P4ClientApi::GetEnv( const char *v)
130
+ {
131
+ return enviro->Get( v );
132
+ }
133
+
134
+ void
135
+ P4ClientApi::SetEnviroFile( const char *c )
136
+ {
137
+ enviro->SetEnviroFile(c);
138
+ }
139
+
140
+ const StrPtr *
141
+ P4ClientApi::GetEnviroFile()
142
+ {
143
+ return enviro->GetEnviroFile();
144
+ }
145
+
146
+ void
147
+ P4ClientApi::SetEVar( const char *var, const char *val )
148
+ {
149
+ StrRef sVar( var );
150
+ StrRef sVal( val );
151
+ client.SetEVar( sVar, sVal );
152
+ }
153
+
154
+ const StrPtr *
155
+ P4ClientApi::GetEVar( const char *var )
156
+ {
157
+ StrRef sVar( var );
158
+ return client.GetEVar( sVar );
159
+ }
160
+
161
+ void
162
+ P4ClientApi::SetApiLevel( int level )
163
+ {
164
+ StrBuf b;
165
+ b << level;
166
+ apiLevel = level;
167
+ client.SetProtocol( "api", b.Text() );
168
+ ui.SetApiLevel( level );
169
+ }
170
+
171
+ int
172
+ P4ClientApi::SetCharset( const char *c )
173
+ {
174
+ StrRef cs_none( "none" );
175
+
176
+ if( P4RDB_COMMANDS )
177
+ fprintf( stderr, "[P4] Setting charset: %s\n", c );
178
+
179
+ if( c && cs_none != c )
180
+ {
181
+ CharSetApi::CharSet cs = CharSetApi::Lookup( c );
182
+ if( cs < 0 )
183
+ {
184
+ StrBuf m;
185
+ m = "Unknown or unsupported charset: ";
186
+ m.Append( c );
187
+ Except( "P4#charset=", m.Text() );
188
+ }
189
+ #ifdef HAVE_RUBY_ENCODING_H
190
+ CharSetApi::CharSet utf8 = CharSetApi::Lookup( "utf8" );
191
+ client.SetTrans( utf8, cs, utf8, utf8 );
192
+ #else
193
+ client.SetTrans( cs, cs, cs, cs );
194
+ #endif
195
+ client.SetCharset( c );
196
+ P4Utils::SetCharset( c );
197
+ }
198
+ else
199
+ {
200
+ // Disables automatic unicode detection if called
201
+ // prior to init (2014.2)
202
+ client.SetTrans( 0 );
203
+ }
204
+ return 1;
205
+ }
206
+
207
+ void
208
+ P4ClientApi::SetCwd( const char *c )
209
+ {
210
+ client.SetCwd( c );
211
+ enviro->Config( StrRef( c ) );
212
+ }
213
+
214
+ void
215
+ P4ClientApi::SetTicketFile( const char *p )
216
+ {
217
+ client.SetTicketFile( p );
218
+ ticketFile = p;
219
+ }
220
+
221
+ void
222
+ P4ClientApi::SetTrustFile( const char *p )
223
+ {
224
+ client.SetTrustFile( p );
225
+ trustFile = p;
226
+ }
227
+
228
+ void
229
+ P4ClientApi::SetDebug( int d )
230
+ {
231
+ debug = d;
232
+ ui.SetDebug( d );
233
+ specMgr.SetDebug( d );
234
+
235
+ if( P4RDB_RPC )
236
+ p4debug.SetLevel( "rpc=5" );
237
+ else
238
+ p4debug.SetLevel( "rpc=0" );
239
+
240
+ if( P4RDB_SSL )
241
+ p4debug.SetLevel( "ssl=3" );
242
+ else
243
+ p4debug.SetLevel( "ssl=0" );
244
+ }
245
+
246
+ void
247
+ P4ClientApi::SetArrayConversion( int i )
248
+ {
249
+ specMgr.SetArrayConversion( i );
250
+ }
251
+
252
+ void
253
+ P4ClientApi::SetProtocol( const char *var, const char *val )
254
+ {
255
+ client.SetProtocol( var, val );
256
+ }
257
+
258
+ VALUE
259
+ P4ClientApi::SetEnv( const char *var, const char *val )
260
+ {
261
+ Error e;
262
+
263
+ enviro->Set( var, val, &e );
264
+ if( e.Test() && exceptionLevel )
265
+ {
266
+ Except( "P4#set_env", &e );
267
+ }
268
+
269
+ if( e.Test() )
270
+ return Qfalse;
271
+
272
+ // Fixes an issue on OS X where the next enviro->Get doesn't return the
273
+ // cached value
274
+ enviro->Reload();
275
+
276
+ return Qtrue;
277
+ }
278
+
279
+ //
280
+ // connect to the Perforce server.
281
+ //
282
+
283
+ VALUE
284
+ P4ClientApi::Connect()
285
+ {
286
+ if ( P4RDB_COMMANDS )
287
+ fprintf( stderr, "[P4] Connecting to Perforce\n" );
288
+
289
+ if ( IsConnected() )
290
+ {
291
+ rb_warn( "P4#connect - Perforce client already connected!" );
292
+ return Qtrue;
293
+ }
294
+
295
+ return ConnectOrReconnect();
296
+ }
297
+
298
+ VALUE
299
+ P4ClientApi::ConnectOrReconnect()
300
+ {
301
+ if ( IsTrackMode() )
302
+ client.SetProtocol( "track", "" );
303
+
304
+ Error e;
305
+
306
+ ResetFlags();
307
+ client.Init( &e );
308
+ if ( e.Test() && exceptionLevel )
309
+ Except( "P4#connect", &e );
310
+
311
+ if ( e.Test() )
312
+ return Qfalse;
313
+
314
+ // If a handler is defined, reset the break functionality
315
+ // for the KeepAlive function
316
+
317
+ if( ui.GetHandler() != Qnil )
318
+ {
319
+ client.SetBreak( &ui );
320
+ }
321
+
322
+ SetConnected();
323
+ return Qtrue;
324
+ }
325
+
326
+
327
+ //
328
+ // Disconnect session
329
+ //
330
+ VALUE
331
+ P4ClientApi::Disconnect()
332
+ {
333
+ if ( P4RDB_COMMANDS )
334
+ fprintf( stderr, "[P4] Disconnect\n" );
335
+
336
+ if ( !IsConnected() )
337
+ {
338
+ rb_warn( "P4#disconnect - not connected" );
339
+ return Qtrue;
340
+ }
341
+ Error e;
342
+ client.Final( &e );
343
+ ResetFlags();
344
+
345
+ // Clear the specdef cache.
346
+ specMgr.Reset();
347
+
348
+ // Clear out any results from the last command
349
+ ui.Reset();
350
+
351
+ return Qtrue;
352
+ }
353
+
354
+ //
355
+ // Test whether or not connected
356
+ //
357
+ VALUE
358
+ P4ClientApi::Connected()
359
+ {
360
+ if( IsConnected() && !client.Dropped() )
361
+ return Qtrue;
362
+ else if( IsConnected() )
363
+ Disconnect();
364
+ return Qfalse;
365
+ }
366
+
367
+ void
368
+ P4ClientApi::Tagged( int enable )
369
+ {
370
+ if( enable )
371
+ SetTag();
372
+ else
373
+ ClearTag();
374
+ }
375
+
376
+ int P4ClientApi::SetTrack( int enable )
377
+ {
378
+ if ( IsConnected() ) {
379
+ if( exceptionLevel )
380
+ {
381
+ Except( "P4#track=", "Can't change performance tracking once you've connected.");
382
+ }
383
+ return Qfalse;
384
+ }
385
+ else if ( enable ) {
386
+ SetTrackMode();
387
+ ui.SetTrack(true);
388
+ }
389
+ else {
390
+ ClearTrackMode();
391
+ ui.SetTrack(false);
392
+ }
393
+ return Qtrue;
394
+ }
395
+
396
+ void P4ClientApi::SetStreams( int enable )
397
+ {
398
+ if ( enable )
399
+ SetStreamsMode();
400
+ else
401
+ ClearStreamsMode();
402
+ }
403
+
404
+ void P4ClientApi::SetGraph( int enable )
405
+ {
406
+ if ( enable )
407
+ SetGraphMode();
408
+ else
409
+ ClearGraphMode();
410
+ }
411
+
412
+ int
413
+ P4ClientApi::GetServerLevel()
414
+ {
415
+ if( !IsConnected() )
416
+ Except( "server_level", "Not connected to a Perforce Server.");
417
+ if( !IsCmdRun() )
418
+ Run( "info", 0, 0 );
419
+ return server2;
420
+ }
421
+
422
+ int
423
+ P4ClientApi::ServerCaseSensitive()
424
+ {
425
+ if( !IsConnected() )
426
+ Except( "server_case_sensitive?", "Not connected to a Perforce Server.");
427
+ if( !IsCmdRun() )
428
+ Run( "info", 0, 0);
429
+ return !IsCaseFold();
430
+ }
431
+
432
+ int
433
+ P4ClientApi::ServerUnicode()
434
+ {
435
+ if( !IsConnected() )
436
+ Except( "server_unicode?", "Not connected to a Perforce Server.");
437
+ if( !IsCmdRun() )
438
+ Run( "info", 0, 0);
439
+ return IsUnicode();
440
+ }
441
+
442
+
443
+ // Check if the supplied path falls within the view of the ignore file
444
+ int
445
+ P4ClientApi::IsIgnored( const char *path )
446
+ {
447
+ Ignore *ignore = client.GetIgnore();
448
+ if( !ignore ) return 0;
449
+
450
+ StrRef p( path );
451
+ return ignore->Reject( p, client.GetIgnoreFile() );
452
+ }
453
+
454
+ //
455
+ // Run returns the results of the command. If the client has not been
456
+ // connected, then an exception is raised but errors from Perforce
457
+ // commands are returned via the Errors() and ErrorCount() interfaces
458
+ // and not via exceptions because one failure in a command applied to many
459
+ // files would interrupt processing of all the other files if an exception
460
+ // is raised.
461
+ //
462
+
463
+ VALUE
464
+ P4ClientApi::Run( const char *cmd, int argc, char * const *argv )
465
+ {
466
+ // Save the entire command string for our error messages. Makes it
467
+ // easy to see where a script has gone wrong.
468
+ StrBuf cmdString;
469
+ cmdString << "\"p4 " << cmd;
470
+ for( int i = 0; i < argc; i++ )
471
+ cmdString << " " << argv[ i ];
472
+ cmdString << "\"";
473
+
474
+ if ( P4RDB_COMMANDS )
475
+ fprintf( stderr, "[P4] Executing %s\n", cmdString.Text() );
476
+
477
+ if ( depth )
478
+ {
479
+ rb_warn( "Can't execute nested Perforce commands." );
480
+ return Qfalse;
481
+ }
482
+
483
+ // Clear out any results from the previous command
484
+ ui.Reset();
485
+
486
+ if ( !IsConnected() && exceptionLevel )
487
+ Except( "P4#run", "not connected." );
488
+
489
+ if ( !IsConnected() )
490
+ return Qfalse;
491
+
492
+ // Tell the UI which command we're running.
493
+ ui.SetCommand( cmd );
494
+
495
+ depth++;
496
+ RunCmd( cmd, &ui, argc, argv );
497
+ depth--;
498
+
499
+ if( ui.GetHandler() != Qnil) {
500
+ if( client.Dropped() && ! ui.IsAlive() ) {
501
+ Disconnect();
502
+ ConnectOrReconnect();
503
+ }
504
+ }
505
+
506
+ ui.RaiseRubyException();
507
+
508
+ P4Result &results = ui.GetResults();
509
+
510
+ if ( results.ErrorCount() && exceptionLevel )
511
+ Except( "P4#run", "Errors during command execution", cmdString.Text() );
512
+
513
+ if ( results.WarningCount() && exceptionLevel > 1 )
514
+ Except( "P4#run", "Warnings during command execution",cmdString.Text());
515
+
516
+ return results.GetOutput();
517
+ }
518
+
519
+
520
+ void
521
+ P4ClientApi::RunCmd( const char *cmd, ClientUser *ui, int argc, char * const *argv )
522
+ {
523
+ client.SetProg( &prog );
524
+ if( version.Length() )
525
+ client.SetVersion( &version );
526
+
527
+ if( IsTag() )
528
+ client.SetVar( "tag" );
529
+
530
+ if ( IsStreams() && apiLevel > 69 )
531
+ client.SetVar( "enableStreams", "" );
532
+
533
+ if ( IsGraph() && apiLevel > 81 )
534
+ client.SetVar( "enableGraph", "" );
535
+
536
+ // If maxresults or maxscanrows is set, enforce them now
537
+ if( maxResults ) client.SetVar( "maxResults", maxResults );
538
+ if( maxScanRows ) client.SetVar( "maxScanRows", maxScanRows );
539
+ if( maxLockTime ) client.SetVar( "maxLockTime", maxLockTime );
540
+
541
+ // If progress is set, set progress var.
542
+ if( ( (ClientUserRuby*)ui)->GetProgress() != Qnil ) client.SetVar( P4Tag::v_progress, 1 );
543
+
544
+ client.SetArgv( argc, argv );
545
+ client.Run( cmd, ui );
546
+
547
+ // Can only read the protocol block *after* a command has been run.
548
+ // Do this once only.
549
+ if( !IsCmdRun() )
550
+ {
551
+ StrPtr *s = 0;
552
+ if ( (s = client.GetProtocol(P4Tag::v_server2)) )
553
+ server2 = s->Atoi();
554
+
555
+ if( (s = client.GetProtocol(P4Tag::v_unicode)) )
556
+ if( s->Atoi() )
557
+ SetUnicode();
558
+
559
+ if( (s = client.GetProtocol(P4Tag::v_nocase)) )
560
+ SetCaseFold();
561
+ }
562
+ SetCmdRun();
563
+ }
564
+
565
+
566
+ //
567
+ // Parses a string supplied by the user into a hash. To do this we need
568
+ // the specstring from the server. We try to cache those as we see them,
569
+ // but the user may not have executed any commands to allow us to cache
570
+ // them so we may have to fetch the spec first.
571
+ //
572
+
573
+ VALUE
574
+ P4ClientApi::ParseSpec( const char * type, const char *form )
575
+ {
576
+ if ( !specMgr.HaveSpecDef( type ) )
577
+ {
578
+ if( exceptionLevel )
579
+ {
580
+ StrBuf m;
581
+ m = "No spec definition for ";
582
+ m.Append( type );
583
+ m.Append( " objects." );
584
+ Except( "P4#parse_spec", m.Text() );
585
+ }
586
+ else
587
+ {
588
+ return Qfalse;
589
+ }
590
+ }
591
+
592
+ // Got a specdef so now we can attempt to parse it.
593
+ Error e;
594
+ VALUE v;
595
+ v = specMgr.StringToSpec( type, form, &e );
596
+
597
+ if ( e.Test() )
598
+ {
599
+ if( exceptionLevel )
600
+ Except( "P4#parse_spec", &e );
601
+ else
602
+ return Qfalse;
603
+ }
604
+
605
+ return v;
606
+ }
607
+
608
+
609
+ //
610
+ // Converts a hash supplied by the user into a string using the specstring
611
+ // from the server. We may have to fetch the specstring first.
612
+ //
613
+
614
+ VALUE
615
+ P4ClientApi::FormatSpec( const char * type, VALUE hash )
616
+ {
617
+ if ( !specMgr.HaveSpecDef( type ) )
618
+ {
619
+ if( exceptionLevel )
620
+ {
621
+ StrBuf m;
622
+ m = "No spec definition for ";
623
+ m.Append( type );
624
+ m.Append( " objects." );
625
+ Except( "P4#format_spec", m.Text() );
626
+ }
627
+ else
628
+ {
629
+ return Qfalse;
630
+ }
631
+ }
632
+
633
+ // Got a specdef so now we can attempt to convert.
634
+ StrBuf buf;
635
+ Error e;
636
+
637
+ specMgr.SpecToString( type, hash, buf, &e );
638
+ if( !e.Test() )
639
+ return P4Utils::ruby_string( buf.Text() );
640
+
641
+ if( exceptionLevel )
642
+ {
643
+ StrBuf m;
644
+ m = "Error converting hash to a string.";
645
+ if( e.Test() ) e.Fmt( m, EF_PLAIN );
646
+ Except( "P4#format_spec", m.Text() );
647
+ }
648
+ return Qnil;
649
+ }
650
+
651
+ //
652
+ // Returns a hash whose keys contain the names of the fields in a spec of the
653
+ // specified type. Not yet exposed to Ruby clients, but may be in future.
654
+ //
655
+ VALUE
656
+ P4ClientApi::SpecFields( const char * type )
657
+ {
658
+ if ( !specMgr.HaveSpecDef( type ) )
659
+ {
660
+ if( exceptionLevel )
661
+ {
662
+ StrBuf m;
663
+ m = "No spec definition for ";
664
+ m.Append( type );
665
+ m.Append( " objects." );
666
+ Except( "P4#spec_fields", m.Text() );
667
+ }
668
+ else
669
+ {
670
+ return Qfalse;
671
+ }
672
+ }
673
+
674
+ return specMgr.SpecFields( type );
675
+ }
676
+
677
+ //
678
+ // Raises an exception or returns Qfalse on bad input
679
+ //
680
+
681
+ VALUE
682
+ P4ClientApi::SetInput( VALUE input )
683
+ {
684
+ if ( P4RDB_COMMANDS )
685
+ fprintf( stderr, "[P4] Received input for next command\n" );
686
+
687
+ if ( ! ui.SetInput( input ) )
688
+ {
689
+ if ( exceptionLevel )
690
+ Except( "P4#input", "Error parsing supplied data." );
691
+ else
692
+ return Qfalse;
693
+ }
694
+ return Qtrue;
695
+ }
696
+
697
+ //
698
+ // Sets the handler and connects the SetBreak feature
699
+ //
700
+ VALUE
701
+ P4ClientApi::SetHandler( VALUE handler )
702
+ {
703
+ if ( P4RDB_COMMANDS )
704
+ fprintf( stderr, "[P4] Received handler object\n" );
705
+
706
+ ui.SetHandler( handler );
707
+
708
+ if( handler == Qnil)
709
+ client.SetBreak(NULL);
710
+ else
711
+ client.SetBreak(&ui);
712
+
713
+ return Qtrue;
714
+ }
715
+
716
+ VALUE
717
+ P4ClientApi::SetProgress( VALUE progress ) {
718
+ if ( P4RDB_COMMANDS )
719
+ fprintf( stderr, "[P4] Received progress object\n" );
720
+
721
+ return ui.SetProgress( progress );
722
+ }
723
+
724
+ VALUE
725
+ P4ClientApi::SetSSOHandler( VALUE h )
726
+ {
727
+ if ( P4RDB_COMMANDS )
728
+ fprintf( stderr, "[P4] Received SSO handler object\n" );
729
+
730
+ ui.SetRubySSOHandler( h );
731
+
732
+ return Qtrue;
733
+ }
734
+
735
+
736
+ void
737
+ P4ClientApi::GCMark()
738
+ {
739
+ if ( P4RDB_GC )
740
+ fprintf( stderr, "[P4] Ruby asked us to do garbage collection\n" );
741
+
742
+ // We don't hold Ruby objects. But our UI does.
743
+ ui.GCMark();
744
+ }
745
+
746
+ void
747
+ P4ClientApi::Except( const char *func, const char *msg )
748
+ {
749
+ StrBuf m;
750
+ StrBuf errors;
751
+ StrBuf warnings;
752
+ int terminate = 0;
753
+
754
+ m << "[" << func << "] " << msg;
755
+
756
+ // Now append any errors and warnings to the text
757
+ ui.GetResults().FmtErrors( errors );
758
+ ui.GetResults().FmtWarnings( warnings );
759
+
760
+ if( errors.Length() )
761
+ {
762
+ m << "\n" << errors;
763
+ terminate++;
764
+ }
765
+
766
+ if( exceptionLevel > 1 && warnings.Length() )
767
+ {
768
+ m << "\n" << warnings;
769
+ terminate++;
770
+ }
771
+
772
+ if( terminate )
773
+ m << "\n\n";
774
+
775
+ rb_raise( eP4, "%s", m.Text() );
776
+ }
777
+
778
+ void
779
+ P4ClientApi::Except( const char *func, const char *msg, const char *cmd )
780
+ {
781
+ StrBuf m;
782
+
783
+ m << msg;
784
+ m << "( " << cmd << " )";
785
+ Except( func, m.Text() );
786
+ }
787
+
788
+ void
789
+ P4ClientApi::Except( const char *func, Error *e )
790
+ {
791
+ StrBuf m;
792
+
793
+ e->Fmt( &m );
794
+ Except( func, m.Text() );
795
+ }
796
+
797
+ //
798
+ // SSO Handlers
799
+ //
800
+
801
+ VALUE
802
+ P4ClientApi::SetEnableSSO( VALUE e )
803
+ {
804
+ return ui.EnableSSO( e );
805
+ }
806
+
807
+ VALUE
808
+ P4ClientApi::GetEnableSSO()
809
+ {
810
+ return ui.SSOEnabled();
811
+ }
812
+
813
+ VALUE
814
+ P4ClientApi::GetSSOVars()
815
+ {
816
+ return ui.GetSSOVars();
817
+ }
818
+
819
+ VALUE
820
+ P4ClientApi::SetSSOPassResult( VALUE r )
821
+ {
822
+ return ui.SetSSOPassResult( r );
823
+ }
824
+
825
+ VALUE
826
+ P4ClientApi::GetSSOPassResult()
827
+ {
828
+ return ui.GetSSOPassResult();
829
+ }
830
+
831
+ VALUE
832
+ P4ClientApi::SetSSOFailResult( VALUE r )
833
+ {
834
+ return ui.SetSSOFailResult( r );
835
+ }
836
+
837
+ VALUE
838
+ P4ClientApi::GetSSOFailResult()
839
+ {
840
+ return ui.GetSSOFailResult();
841
+ }