faye 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +14 -0
- data/README.rdoc +98 -0
- data/Rakefile +17 -15
- data/lib/faye-browser-min.js +1 -1
- data/lib/faye.rb +14 -5
- data/lib/faye/adapters/rack_adapter.rb +12 -5
- data/lib/faye/engines/base.rb +62 -0
- data/lib/faye/engines/connection.rb +63 -0
- data/lib/faye/engines/memory.rb +89 -0
- data/lib/faye/engines/redis.rb +141 -0
- data/lib/faye/error.rb +16 -4
- data/lib/faye/mixins/publisher.rb +6 -0
- data/lib/faye/protocol/channel.rb +34 -86
- data/lib/faye/protocol/client.rb +36 -52
- data/lib/faye/protocol/extensible.rb +3 -0
- data/lib/faye/protocol/server.rb +119 -169
- data/lib/faye/transport/http.rb +45 -0
- data/lib/faye/transport/local.rb +15 -0
- data/lib/faye/{network → transport}/transport.rb +36 -49
- data/spec/browser.html +35 -0
- data/spec/install.sh +48 -0
- data/spec/javascript/channel_spec.js +15 -0
- data/spec/javascript/client_spec.js +610 -0
- data/spec/javascript/engine_spec.js +319 -0
- data/spec/javascript/faye_spec.js +15 -0
- data/spec/javascript/grammar_spec.js +66 -0
- data/spec/javascript/node_adapter_spec.js +276 -0
- data/spec/javascript/server/connect_spec.js +168 -0
- data/spec/javascript/server/disconnect_spec.js +121 -0
- data/spec/javascript/server/extensions_spec.js +60 -0
- data/spec/javascript/server/handshake_spec.js +153 -0
- data/spec/javascript/server/subscribe_spec.js +245 -0
- data/spec/javascript/server/unsubscribe_spec.js +245 -0
- data/spec/javascript/server_spec.js +146 -0
- data/spec/javascript/transport_spec.js +130 -0
- data/spec/node.js +34 -0
- data/spec/ruby/channel_spec.rb +17 -0
- data/spec/ruby/client_spec.rb +615 -0
- data/spec/ruby/engine_spec.rb +312 -0
- data/spec/ruby/faye_spec.rb +14 -0
- data/spec/ruby/grammar_spec.rb +68 -0
- data/spec/ruby/rack_adapter_spec.rb +209 -0
- data/spec/ruby/server/connect_spec.rb +170 -0
- data/spec/ruby/server/disconnect_spec.rb +120 -0
- data/spec/ruby/server/extensions_spec.rb +69 -0
- data/spec/ruby/server/handshake_spec.rb +151 -0
- data/spec/ruby/server/subscribe_spec.rb +247 -0
- data/spec/ruby/server/unsubscribe_spec.rb +247 -0
- data/spec/ruby/server_spec.rb +138 -0
- data/spec/ruby/transport_spec.rb +128 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/testswarm.pl +200 -0
- data/spec/thin_proxy.rb +36 -0
- metadata +119 -84
- data/Manifest.txt +0 -27
- data/README.txt +0 -98
- data/lib/faye/protocol/connection.rb +0 -111
- data/test/scenario.rb +0 -172
- data/test/test_channel.rb +0 -54
- data/test/test_clients.rb +0 -381
- data/test/test_grammar.rb +0 -86
- data/test/test_server.rb +0 -488
@@ -0,0 +1,138 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Faye::Server do
|
4
|
+
let(:engine) { mock "engine" }
|
5
|
+
let(:server) { Faye::Server.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Faye::Engine.stub(:get).and_return engine
|
9
|
+
end
|
10
|
+
|
11
|
+
describe :process do
|
12
|
+
let(:handshake) {{"channel" => "/meta/handshake", "data" => "handshake" }}
|
13
|
+
let(:connect) {{"channel" => "/meta/connect", "data" => "connect" }}
|
14
|
+
let(:disconnect) {{"channel" => "/meta/disconnect", "data" => "disconnect" }}
|
15
|
+
let(:subscribe) {{"channel" => "/meta/subscribe", "data" => "subscribe" }}
|
16
|
+
let(:unsubscribe) {{"channel" => "/meta/unsubscribe", "data" => "unsubscribe"}}
|
17
|
+
let(:publish) {{"channel" => "/some/channel", "data" => "publish" }}
|
18
|
+
|
19
|
+
before do
|
20
|
+
engine.stub(:interval).and_return(0)
|
21
|
+
engine.stub(:timeout).and_return(60)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns an empty response for no messages" do
|
25
|
+
response = nil
|
26
|
+
server.process([], false) { |r| response = r }
|
27
|
+
response.should == []
|
28
|
+
end
|
29
|
+
|
30
|
+
it "ignores invalid messages" do
|
31
|
+
response = nil
|
32
|
+
server.process([{}, {"channel" => "invalid"}], false) { |r| response = r }
|
33
|
+
response.should == []
|
34
|
+
end
|
35
|
+
|
36
|
+
it "routes single messages to appropriate handlers" do
|
37
|
+
server.should_receive(:handshake).with(handshake, false)
|
38
|
+
engine.should_receive(:publish).with(handshake)
|
39
|
+
server.process(handshake, false)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "routes a list of messages to appropriate handlers" do
|
43
|
+
server.should_receive(:handshake).with(handshake, false)
|
44
|
+
server.should_receive(:connect).with(connect, false)
|
45
|
+
server.should_receive(:disconnect).with(disconnect, false)
|
46
|
+
server.should_receive(:subscribe).with(subscribe, false)
|
47
|
+
server.should_receive(:unsubscribe).with(unsubscribe, false)
|
48
|
+
|
49
|
+
engine.should_receive(:publish).with(handshake)
|
50
|
+
engine.should_receive(:publish).with(connect)
|
51
|
+
engine.should_receive(:publish).with(disconnect)
|
52
|
+
engine.should_receive(:publish).with(subscribe)
|
53
|
+
engine.should_receive(:publish).with(unsubscribe)
|
54
|
+
engine.should_receive(:publish).with(publish)
|
55
|
+
|
56
|
+
server.process([handshake, connect, disconnect, subscribe, unsubscribe, publish], false)
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "publishing a message" do
|
60
|
+
it "tells the engine to publish the message" do
|
61
|
+
engine.should_receive(:publish).with(publish)
|
62
|
+
server.process(publish, false) {}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns no response" do
|
66
|
+
engine.stub(:publish)
|
67
|
+
server.process(publish, false) { |r| r.should == [] }
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "with an error" do
|
71
|
+
before { publish["error"] = "invalid" }
|
72
|
+
|
73
|
+
it "does not tell the engine to publish the message" do
|
74
|
+
engine.should_not_receive(:publish)
|
75
|
+
server.process(publish, false) {}
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns no response" do
|
79
|
+
engine.stub(:publish)
|
80
|
+
server.process(publish, false) { |r| r.should == [] }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "to an invalid channel" do
|
85
|
+
before { publish["channel"] = "/invalid/*" }
|
86
|
+
|
87
|
+
it "does not tell the engine to publish the message" do
|
88
|
+
engine.should_not_receive(:publish)
|
89
|
+
server.process(publish, false) {}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "handshaking" do
|
95
|
+
before do
|
96
|
+
engine.should_receive(:publish).with(handshake)
|
97
|
+
server.should_receive(:handshake).with(handshake, false).and_yield({"successful" => true})
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns the handshake response with advice" do
|
101
|
+
server.process(handshake, false) do |response|
|
102
|
+
response.should == [
|
103
|
+
{ "successful" => true,
|
104
|
+
"advice" => {"reconnect" => "retry", "interval" => 0, "timeout" => 60000}
|
105
|
+
}
|
106
|
+
]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "connecting for messages" do
|
112
|
+
let(:messages) { [{"channel" => "/a"}, {"channel" => "/b"}] }
|
113
|
+
|
114
|
+
before do
|
115
|
+
engine.should_receive(:publish).with(connect)
|
116
|
+
server.should_receive(:connect).with(connect, false).and_yield(messages)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "returns the new messages" do
|
120
|
+
server.process(connect, false) { |r| r.should == messages }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe :flush_connection do
|
126
|
+
let(:message) {{"clientId" => "fakeclientid"}}
|
127
|
+
|
128
|
+
it "flushes the connection when given one message" do
|
129
|
+
engine.should_receive(:flush).with("fakeclientid")
|
130
|
+
server.flush_connection(message)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "flushes the connection when given a list of messages" do
|
134
|
+
engine.should_receive(:flush).with("fakeclientid")
|
135
|
+
server.flush_connection([message])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Faye::Transport do
|
4
|
+
let :client do
|
5
|
+
client = mock("client")
|
6
|
+
client.stub(:endpoint).and_return("http://example.com/")
|
7
|
+
client
|
8
|
+
end
|
9
|
+
|
10
|
+
describe :get do
|
11
|
+
before do
|
12
|
+
Faye::Transport::Local.stub(:usable?).and_return(false)
|
13
|
+
Faye::Transport::Http.stub(:usable?).and_return(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:transport) { Faye::Transport.get(client, ["long-polling", "in-process"]) }
|
17
|
+
let(:local_transport) { Faye::Transport.get(client, ["in-process"]) }
|
18
|
+
let(:http_transport) { Faye::Transport.get(client, ["long-polling"]) }
|
19
|
+
|
20
|
+
describe "when no transport is usable" do
|
21
|
+
it "raises an exception" do
|
22
|
+
lambda { transport }.should raise_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "when a less preferred transport is usable" do
|
27
|
+
before do
|
28
|
+
Faye::Transport::Http.stub(:usable?).and_return(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns a transport of the usable type" do
|
32
|
+
transport.should be_kind_of(Faye::Transport::Http)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "rasies an exception of the usable type is not requested" do
|
36
|
+
lambda { local_transport }.should raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "allows the usable type to be specifically selected" do
|
40
|
+
http_transport.should be_kind_of(Faye::Transport::Http)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "when all transports are usable" do
|
45
|
+
before do
|
46
|
+
Faye::Transport::Local.stub(:usable?).and_return(true)
|
47
|
+
Faye::Transport::Http.stub(:usable?).and_return(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns the most preferred type" do
|
51
|
+
transport.should be_kind_of(Faye::Transport::Local)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "allows types to be specifically selected" do
|
55
|
+
local_transport.should be_kind_of(Faye::Transport::Local)
|
56
|
+
http_transport.should be_kind_of(Faye::Transport::Http)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe :send do
|
62
|
+
include EM::RSpec::FakeClock
|
63
|
+
before { clock.stub }
|
64
|
+
after { clock.reset }
|
65
|
+
|
66
|
+
before do
|
67
|
+
client.stub(:client_id).and_return("abc123")
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "for batching transports" do
|
71
|
+
before do
|
72
|
+
transport_klass = Class.new(Faye::Transport) do
|
73
|
+
def batching?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@transport = transport_klass.new(client, "")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does not make an immediate request" do
|
81
|
+
@transport.should_not_receive(:request)
|
82
|
+
@transport.send({"batch" => "me"}, 60)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "queues the message to be sent after a timeout" do
|
86
|
+
@transport.should_receive(:request).with([{"batch" => "me"}], 60)
|
87
|
+
@transport.send({"batch" => "me"}, 60)
|
88
|
+
clock.tick(0.01)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "allows multiple messages to be batched together" do
|
92
|
+
@transport.should_receive(:request).with([{"id" => 1}, {"id" => 2}], 60)
|
93
|
+
@transport.send({"id" => 1}, 60)
|
94
|
+
@transport.send({"id" => 2}, 60)
|
95
|
+
clock.tick(0.01)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "adds advice to connect messages sent with others" do
|
99
|
+
@transport.should_receive(:request).with([{"channel" => "/meta/connect", "advice" => {"timeout" => 0}}, {}], 60)
|
100
|
+
@transport.send({"channel" => "/meta/connect"}, 60)
|
101
|
+
@transport.send({}, 60)
|
102
|
+
clock.tick(0.01)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "adds no advice to connect messages sent alone" do
|
106
|
+
@transport.should_receive(:request).with([{"channel" => "/meta/connect"}], 60)
|
107
|
+
@transport.send({"channel" => "/meta/connect"}, 60)
|
108
|
+
clock.tick(0.01)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "for non-batching transports" do
|
113
|
+
before do
|
114
|
+
transport_klass = Class.new(Faye::Transport) do
|
115
|
+
def batching?
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
@transport = transport_klass.new(client, "")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "makes a request immediately" do
|
123
|
+
@transport.should_receive(:request).with([{"no" => "batch"}], 60)
|
124
|
+
@transport.send({"no" => "batch"}, 60)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/testswarm.pl
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
#!/usr/bin/perl
|
2
|
+
|
3
|
+
# CONFIGURE
|
4
|
+
|
5
|
+
# The location of the TestSwarm that you're going to run against.
|
6
|
+
|
7
|
+
my $SWARM = "http://swarm.jcoglan.com";
|
8
|
+
my $SWARM_INJECT = "/js/inject.js";
|
9
|
+
|
10
|
+
# Your TestSwarm username.
|
11
|
+
|
12
|
+
my $USER = "faye";
|
13
|
+
|
14
|
+
# Your authorization token.
|
15
|
+
|
16
|
+
my $AUTH_TOKEN = "6d26e250d81b32099fccc59db53a3a0e648f0e6d";
|
17
|
+
|
18
|
+
# The maximum number of times you want the tests to be run.
|
19
|
+
|
20
|
+
my $MAX_RUNS = 5;
|
21
|
+
|
22
|
+
# The type of revision control system being used.
|
23
|
+
# Currently "svn" or "git" are supported.
|
24
|
+
|
25
|
+
my $RCS_TYPE = "git";
|
26
|
+
|
27
|
+
# The URL from which a copy will be checked out.
|
28
|
+
|
29
|
+
my $RCS_URL = "git://github.com/jcoglan/faye.git";
|
30
|
+
|
31
|
+
# The directory in which the checkouts will occur.
|
32
|
+
|
33
|
+
my $BASE_DIR = "/home/jcoglan/www/swarm.jcoglan.com/app/changeset/$USER";
|
34
|
+
|
35
|
+
# A script tag loading in the TestSwarm injection script will
|
36
|
+
# be added at the bottom of the <head> in the following file.
|
37
|
+
|
38
|
+
my $INJECT_FILE = "spec/browser.html";
|
39
|
+
|
40
|
+
# Any build commands that need to happen.
|
41
|
+
|
42
|
+
my $BUILD = "git submodule init && git submodule update && cd vendor/js.class && jake && cd ../.. && rm -rf build && jake";
|
43
|
+
|
44
|
+
# The name of the job that will be submitted
|
45
|
+
# (pick a descriptive, but short, name to make it easy to search)
|
46
|
+
|
47
|
+
# Note: The string {REV} will be replaced with the current
|
48
|
+
# commit number/hash.
|
49
|
+
|
50
|
+
my $JOB_NAME = "Faye Commit #{REV}";
|
51
|
+
|
52
|
+
# The browsers you wish to run against. Options include:
|
53
|
+
# - "all" all available browsers.
|
54
|
+
# - "popular" the most popular browser (99%+ of all browsers in use)
|
55
|
+
# - "current" the current release of all the major browsers
|
56
|
+
# - "gbs" the browsers currently supported in Yahoo's Graded Browser Support
|
57
|
+
# - "beta" upcoming alpha/beta of popular browsers
|
58
|
+
# - "popularbeta" the most popular browser and their upcoming releases
|
59
|
+
|
60
|
+
my $BROWSERS = "all";
|
61
|
+
|
62
|
+
# All the suites that you wish to run within this job
|
63
|
+
# (can be any number of suites)
|
64
|
+
|
65
|
+
my %SUITES = ();
|
66
|
+
|
67
|
+
# Comment these out if you wish to define a custom set of SUITES above
|
68
|
+
my $SUITE = "$SWARM/changeset/$USER/{REV}";
|
69
|
+
sub BUILD_SUITES {
|
70
|
+
%SUITES = map { /(\w+).html/; $1 => "$SUITE/$_"; } glob($INJECT_FILE);
|
71
|
+
}
|
72
|
+
|
73
|
+
########### NO NEED TO CONFIGURE BELOW HERE ############
|
74
|
+
|
75
|
+
my $DEBUG = 1;
|
76
|
+
my $curdate = time;
|
77
|
+
my $co_dir = "tmp-$curdate";
|
78
|
+
|
79
|
+
print "chdir $BASE_DIR\n" if ( $DEBUG );
|
80
|
+
chdir( $BASE_DIR );
|
81
|
+
|
82
|
+
# Check out a specific revision
|
83
|
+
if ( $RCS_TYPE eq "svn" ) {
|
84
|
+
print "svn co $RCS_URL $co_dir\n" if ( $DEBUG );
|
85
|
+
`svn co $RCS_URL $co_dir`;
|
86
|
+
} elsif ( $RCS_TYPE eq "git" ) {
|
87
|
+
print "git clone $RCS_URL $co_dir\n" if ( $DEBUG );
|
88
|
+
`git clone $RCS_URL $co_dir`;
|
89
|
+
}
|
90
|
+
|
91
|
+
if ( ! -e $co_dir ) {
|
92
|
+
die "Problem checking out source.";
|
93
|
+
}
|
94
|
+
|
95
|
+
print "chdir $co_dir\n" if ( $DEBUG );
|
96
|
+
chdir( $co_dir );
|
97
|
+
|
98
|
+
my $rev;
|
99
|
+
|
100
|
+
# Figure out the revision of the checkout
|
101
|
+
if ( $RCS_TYPE eq "svn" ) {
|
102
|
+
print "svn info | grep Revision\n" if ( $DEBUG );
|
103
|
+
$rev = `svn info | grep Revision`;
|
104
|
+
$rev =~ s/Revision: //;
|
105
|
+
} elsif ( $RCS_TYPE eq "git" ) {
|
106
|
+
print "git log --abbrev-commit | head -1\n" if ( $DEBUG );
|
107
|
+
$rev = `git log --abbrev-commit | head -1`;
|
108
|
+
$rev =~ s/commit.*?(\w+).*$/$1/;
|
109
|
+
}
|
110
|
+
|
111
|
+
$rev =~ s/\s*//g;
|
112
|
+
|
113
|
+
print "Revision: $rev\n" if ( $DEBUG );
|
114
|
+
|
115
|
+
if ( ! $rev ) {
|
116
|
+
remove_tmp();
|
117
|
+
die "Revision information not found.";
|
118
|
+
|
119
|
+
} elsif ( ! -e "../$rev" ) {
|
120
|
+
print "chdir $BASE_DIR\n" if ( $DEBUG );
|
121
|
+
chdir( $BASE_DIR );
|
122
|
+
|
123
|
+
print "rename $co_dir $rev\n" if ( $DEBUG );
|
124
|
+
rename( $co_dir, $rev );
|
125
|
+
|
126
|
+
print "chdir $rev\n" if ( $DEBUG );
|
127
|
+
chdir ( $rev );
|
128
|
+
|
129
|
+
if ( $BUILD ) {
|
130
|
+
print "$BUILD\n" if ( $DEBUG );
|
131
|
+
`$BUILD`;
|
132
|
+
}
|
133
|
+
|
134
|
+
if ( exists &BUILD_SUITES ) {
|
135
|
+
&BUILD_SUITES();
|
136
|
+
}
|
137
|
+
|
138
|
+
foreach my $file ( glob($INJECT_FILE) ) {
|
139
|
+
my $inject_file = `cat $file`;
|
140
|
+
|
141
|
+
# Inject the TestSwarm injection script into the test suite
|
142
|
+
$inject_file =~ s/<\/head>/<script>document.write("<scr" + "ipt src='$SWARM$SWARM_INJECT?" + (new Date).getTime() + "'><\/scr" + "ipt>");<\/script><\/head>/;
|
143
|
+
|
144
|
+
open( F, ">$file" );
|
145
|
+
print F $inject_file;
|
146
|
+
close( F );
|
147
|
+
}
|
148
|
+
|
149
|
+
my %props = (
|
150
|
+
"state" => "addjob",
|
151
|
+
"output" => "dump",
|
152
|
+
"user" => $USER,
|
153
|
+
"max" => $MAX_RUNS,
|
154
|
+
"job_name" => $JOB_NAME,
|
155
|
+
"browsers" => $BROWSERS,
|
156
|
+
"auth" => $AUTH_TOKEN
|
157
|
+
);
|
158
|
+
|
159
|
+
my $query = "";
|
160
|
+
|
161
|
+
foreach my $prop ( keys %props ) {
|
162
|
+
$query .= ($query ? "&" : "") . $prop . "=" . clean($props{$prop});
|
163
|
+
}
|
164
|
+
|
165
|
+
foreach my $suite ( sort keys %SUITES ) {
|
166
|
+
$query .= "&suites[]=" . clean($suite) .
|
167
|
+
"&urls[]=" . clean($SUITES{$suite});
|
168
|
+
}
|
169
|
+
|
170
|
+
print "curl -d \"$query\" $SWARM\n" if ( $DEBUG );
|
171
|
+
|
172
|
+
my $results = `curl -d "$query" $SWARM`;
|
173
|
+
|
174
|
+
print "Results: $results\n" if ( $DEBUG );
|
175
|
+
|
176
|
+
if ( $results ) {
|
177
|
+
open( F, ">$rev/results.txt" );
|
178
|
+
print F "$SWARM$results";
|
179
|
+
close( F );
|
180
|
+
|
181
|
+
} else {
|
182
|
+
die "Job not submitted properly.";
|
183
|
+
}
|
184
|
+
|
185
|
+
# Otherwise, give up and clean up
|
186
|
+
} else {
|
187
|
+
remove_tmp();
|
188
|
+
}
|
189
|
+
|
190
|
+
sub remove_tmp {
|
191
|
+
chdir( $BASE_DIR );
|
192
|
+
`rm -rf $co_dir`;
|
193
|
+
}
|
194
|
+
|
195
|
+
sub clean {
|
196
|
+
my $str = shift;
|
197
|
+
$str =~ s/{REV}/$rev/g;
|
198
|
+
$str =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
|
199
|
+
$str;
|
200
|
+
}
|