line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#============================================
|
2
|
|
|
|
|
|
|
# SVN自動コミットクラス
|
3
|
|
|
|
|
|
|
#
|
4
|
|
|
|
|
|
|
# -------------------------------------------
|
5
|
|
|
|
|
|
|
# アクセサ
|
6
|
|
|
|
|
|
|
# svn_mode String SVNのコミットモード
|
7
|
|
|
|
|
|
|
# commit ... 自動コミットモード
|
8
|
|
|
|
|
|
|
# update ... アップデート実行
|
9
|
|
|
|
|
|
|
# work_dir_path String 作業フォルダまでのパス
|
10
|
|
|
|
|
|
|
# ex)c:\projects\hoge_svn_dir
|
11
|
|
|
|
|
|
|
# debug Integer デバッグモード(コミット防止)
|
12
|
|
|
|
|
|
|
# 0 ... コミットする(デフォルト)
|
13
|
|
|
|
|
|
|
# 1 ... アップデートされたファイル一覧の列挙などはやるが、AddやCommit自体はしない
|
14
|
|
|
|
|
|
|
# thumbnail_width Integer サムネイル横幅
|
15
|
|
|
|
|
|
|
# デフォルトは$THUMBNAI_WIDTHの値
|
16
|
|
|
|
|
|
|
# thumbnail_height Integer サムネイル縦幅
|
17
|
|
|
|
|
|
|
# デフォルトは$THUMBNAI_HEIGHTの値
|
18
|
|
|
|
|
|
|
#
|
19
|
|
|
|
|
|
|
# changes Integer ローカルのSVNに更新があったか
|
20
|
|
|
|
|
|
|
# 0 ... 更新なし(デフォルト)
|
21
|
|
|
|
|
|
|
# 1 ... 更新あり
|
22
|
|
|
|
|
|
|
# commit_comment String コミット時のコメント
|
23
|
|
|
|
|
|
|
# デフォルトは$COMMIT_COMMENTの値
|
24
|
|
|
|
|
|
|
#
|
25
|
|
|
|
|
|
|
#============================================
|
26
|
|
|
|
|
|
|
package Sorauta::SVN::AutoCommit;
|
27
|
1
|
|
|
1
|
|
21501
|
use base qw/Class::Accessor::Fast/;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
659
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
use 5.012003;
|
30
|
|
|
|
|
|
|
use strict;
|
31
|
|
|
|
|
|
|
use warnings;
|
32
|
|
|
|
|
|
|
use utf8;
|
33
|
|
|
|
|
|
|
use CGI::Carp qw/fatalsToBrowser/;
|
34
|
|
|
|
|
|
|
use Data::Dumper;
|
35
|
|
|
|
|
|
|
use SVN::Agent;
|
36
|
|
|
|
|
|
|
use SVN::Agent::Dummy;
|
37
|
|
|
|
|
|
|
use Image::Magick;
|
38
|
|
|
|
|
|
|
use Sorauta::Utility;
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our $VERSION = '0.02';
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# サムネイルの縦横
|
43
|
|
|
|
|
|
|
our($THUMBNAIL_WIDTH, $THUMBNAIL_HEIGHT) = (160, 90);
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# コミット時のコメント
|
46
|
|
|
|
|
|
|
our $COMMIT_COMMENT = "auto commit from Sorauta::SVN::AutoCommit";
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# コミットするか否か
|
49
|
|
|
|
|
|
|
our $DEBUG = 0;
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(
|
52
|
|
|
|
|
|
|
qw/svn_mode work_dir_path debug thumbnail_width thumbnail_height changes commit_comment/);
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
#==========================================
|
55
|
|
|
|
|
|
|
# コミットを実行
|
56
|
|
|
|
|
|
|
# req:
|
57
|
|
|
|
|
|
|
# res:
|
58
|
|
|
|
|
|
|
#==========================================
|
59
|
|
|
|
|
|
|
sub execute {
|
60
|
|
|
|
|
|
|
my $self = shift;
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
if (!$self->thumbnail_width) {
|
63
|
|
|
|
|
|
|
$self->thumbnail_width($THUMBNAIL_WIDTH);
|
64
|
|
|
|
|
|
|
}
|
65
|
|
|
|
|
|
|
if (!$self->thumbnail_height) {
|
66
|
|
|
|
|
|
|
$self->thumbnail_height($THUMBNAIL_HEIGHT);
|
67
|
|
|
|
|
|
|
}
|
68
|
|
|
|
|
|
|
if (!$self->commit_comment) {
|
69
|
|
|
|
|
|
|
$self->commit_comment($COMMIT_COMMENT);
|
70
|
|
|
|
|
|
|
}
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# must be defined accessors
|
73
|
|
|
|
|
|
|
if (!$self->svn_mode || !$self->work_dir_path) {
|
74
|
|
|
|
|
|
|
die 'must be define accessor svn_mode(auto_commit|update), work_dir_path(/Users/user/Desktop/svn_work_folder)';
|
75
|
|
|
|
|
|
|
}
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# set svn agent
|
78
|
|
|
|
|
|
|
my $sa;
|
79
|
|
|
|
|
|
|
if ($self->debug) {
|
80
|
|
|
|
|
|
|
$sa = SVN::Agent::Dummy->load({
|
81
|
|
|
|
|
|
|
path => $self->work_dir_path
|
82
|
|
|
|
|
|
|
});
|
83
|
|
|
|
|
|
|
}
|
84
|
|
|
|
|
|
|
else {
|
85
|
|
|
|
|
|
|
$sa = SVN::Agent->load({
|
86
|
|
|
|
|
|
|
path => $self->work_dir_path
|
87
|
|
|
|
|
|
|
});
|
88
|
|
|
|
|
|
|
}
|
89
|
|
|
|
|
|
|
#print Dumper($sa);
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# execute command
|
92
|
|
|
|
|
|
|
if ($self->svn_mode eq 'auto_commit') {
|
93
|
|
|
|
|
|
|
$self->_auto_commit($sa);
|
94
|
|
|
|
|
|
|
}
|
95
|
|
|
|
|
|
|
elsif ($self->svn_mode eq 'update') {
|
96
|
|
|
|
|
|
|
$self->update($sa);
|
97
|
|
|
|
|
|
|
}
|
98
|
|
|
|
|
|
|
else {
|
99
|
|
|
|
|
|
|
die 'must be define svn_mode(auto_commit|update)';
|
100
|
|
|
|
|
|
|
}
|
101
|
|
|
|
|
|
|
}
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
#==========================================
|
104
|
|
|
|
|
|
|
# 自動コミットを実行
|
105
|
|
|
|
|
|
|
# TortoiseSVNの画面で全てチェック入れてコミットするイメージ
|
106
|
|
|
|
|
|
|
# req:
|
107
|
|
|
|
|
|
|
# sa: SVN::Agent(or SVN::Agent::Dummy)のインスタンス
|
108
|
|
|
|
|
|
|
# res:
|
109
|
|
|
|
|
|
|
# result: updateした結果
|
110
|
|
|
|
|
|
|
#==========================================
|
111
|
|
|
|
|
|
|
sub _auto_commit {
|
112
|
|
|
|
|
|
|
my($self, $sa) = @_;
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# show files before commit
|
115
|
|
|
|
|
|
|
$self->_show($sa);
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# add unknown files to commit file
|
118
|
|
|
|
|
|
|
$self->_add_unknown_files($sa);
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# scheduling missing file to delete file
|
121
|
|
|
|
|
|
|
$self->_remove_missing_files($sa);
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# show changed files
|
124
|
|
|
|
|
|
|
print $sa->prepare_changes, $/;
|
125
|
|
|
|
|
|
|
my @changes_files = @{ $sa->changes };
|
126
|
|
|
|
|
|
|
if (scalar(@changes_files) > 0) {
|
127
|
|
|
|
|
|
|
$self->changes(1);
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# execute commit
|
131
|
|
|
|
|
|
|
print "[commit]", $/;
|
132
|
|
|
|
|
|
|
unless ($self->debug) {
|
133
|
|
|
|
|
|
|
if ($self->changes) {
|
134
|
|
|
|
|
|
|
print $sa->commit($self->commit_comment);
|
135
|
|
|
|
|
|
|
}
|
136
|
|
|
|
|
|
|
else {
|
137
|
|
|
|
|
|
|
print "the file which should commit does not exist. ", $/;
|
138
|
|
|
|
|
|
|
}
|
139
|
|
|
|
|
|
|
}
|
140
|
|
|
|
|
|
|
else {
|
141
|
|
|
|
|
|
|
print "this is debug mode.", $/;
|
142
|
|
|
|
|
|
|
}
|
143
|
|
|
|
|
|
|
print $/;
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# update latest revision
|
146
|
|
|
|
|
|
|
$self->_update($sa);
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
#==========================================
|
150
|
|
|
|
|
|
|
# アップデートを実行
|
151
|
|
|
|
|
|
|
# req:
|
152
|
|
|
|
|
|
|
# sa: SVN::Agentのインスタンス
|
153
|
|
|
|
|
|
|
# res:
|
154
|
|
|
|
|
|
|
# result: updateした結果
|
155
|
|
|
|
|
|
|
#==========================================
|
156
|
|
|
|
|
|
|
sub _update {
|
157
|
|
|
|
|
|
|
my($self, $sa) = @_;
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
print "[update]", $/;
|
160
|
|
|
|
|
|
|
print $sa->update;
|
161
|
|
|
|
|
|
|
}
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
#==========================================
|
164
|
|
|
|
|
|
|
# 削除されたファイル等、コミット前の状態を表示
|
165
|
|
|
|
|
|
|
# req:
|
166
|
|
|
|
|
|
|
# sa: SVN::Agentのインスタンス
|
167
|
|
|
|
|
|
|
# res:
|
168
|
|
|
|
|
|
|
# result: null
|
169
|
|
|
|
|
|
|
#==========================================
|
170
|
|
|
|
|
|
|
sub _show {
|
171
|
|
|
|
|
|
|
my($self, $sa) = @_;
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# find out unknown files
|
174
|
|
|
|
|
|
|
my @unknown_files = @{ $sa->unknown };
|
175
|
|
|
|
|
|
|
print "====== unknown(will add)", $/;
|
176
|
|
|
|
|
|
|
print join($/, @unknown_files), $/, $/;
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# find out missing files
|
179
|
|
|
|
|
|
|
my @missing_files = @{ $sa->missing };
|
180
|
|
|
|
|
|
|
print "====== missing(will remove)", $/;
|
181
|
|
|
|
|
|
|
print join($/, @missing_files), $/, $/;
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# find out modified files
|
184
|
|
|
|
|
|
|
my @modified_files = @{ $sa->modified };
|
185
|
|
|
|
|
|
|
print "====== modified", $/;
|
186
|
|
|
|
|
|
|
print join($/, @modified_files), $/, $/;
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# find out deleted files
|
189
|
|
|
|
|
|
|
my @deleted_files = @{ $sa->deleted };
|
190
|
|
|
|
|
|
|
print "====== deleted", $/;
|
191
|
|
|
|
|
|
|
print join($/, @deleted_files), $/, $/;
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# 変更がある場合、変更フラグ(changes)をたてておく
|
194
|
|
|
|
|
|
|
if (scalar(@modified_files) > 0 || scalar(@deleted_files) > 0) {
|
195
|
|
|
|
|
|
|
$self->changes(1);
|
196
|
|
|
|
|
|
|
}
|
197
|
|
|
|
|
|
|
}
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
#==========================================
|
200
|
|
|
|
|
|
|
# SVN未登録のファイルをコミットするようにスケジューリング
|
201
|
|
|
|
|
|
|
# req:
|
202
|
|
|
|
|
|
|
# sa: SVN::Agentのインスタンス
|
203
|
|
|
|
|
|
|
# res:
|
204
|
|
|
|
|
|
|
# result: null
|
205
|
|
|
|
|
|
|
#==========================================
|
206
|
|
|
|
|
|
|
sub _add_unknown_files {
|
207
|
|
|
|
|
|
|
my($self, $sa) = @_;
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
my @unknown_files = @{$sa->unknown};
|
210
|
|
|
|
|
|
|
foreach my $unknown_file(@unknown_files) {
|
211
|
|
|
|
|
|
|
if (is_hidden_file($unknown_file)) {
|
212
|
|
|
|
|
|
|
print $unknown_file, " ... Skip.", $/;
|
213
|
|
|
|
|
|
|
next;
|
214
|
|
|
|
|
|
|
}
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# ファイルパスをエスケープ
|
217
|
|
|
|
|
|
|
$unknown_file = _escape($unknown_file);
|
218
|
|
|
|
|
|
|
#print "scheduling:", $$self->work_dir_path.'/'.$unknown_file, $/;
|
219
|
|
|
|
|
|
|
print $sa->add($unknown_file);
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# if unknown file is directory,
|
222
|
|
|
|
|
|
|
# recrusive add including files
|
223
|
|
|
|
|
|
|
my $d_path = cat($self->work_dir_path, $unknown_file);
|
224
|
|
|
|
|
|
|
if (-d $d_path) {
|
225
|
|
|
|
|
|
|
# create thumbnail directory
|
226
|
|
|
|
|
|
|
my @mathed_pattern = split(/\\/, $unknown_file);
|
227
|
|
|
|
|
|
|
my $abs_dir_path = cat($$self->work_dir_path, 'thumbnail', $mathed_pattern[0], $mathed_pattern[1]);
|
228
|
|
|
|
|
|
|
if (!($unknown_file =~ /thumbnail/)) {
|
229
|
|
|
|
|
|
|
unless (-d $abs_dir_path) {
|
230
|
|
|
|
|
|
|
mkdir($abs_dir_path);
|
231
|
|
|
|
|
|
|
print $sa->add($abs_dir_path);
|
232
|
|
|
|
|
|
|
}
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
#print "\t $d_path is dir", $/;
|
235
|
|
|
|
|
|
|
opendir my($D), $d_path;
|
236
|
|
|
|
|
|
|
foreach my $file(readdir($D)) {
|
237
|
|
|
|
|
|
|
next if is_hidden_file($file);
|
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# ファイルパスをエスケープ
|
240
|
|
|
|
|
|
|
$file = _escape($file);
|
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
my $new_unknown_file = cat($unknown_file, $file);
|
243
|
|
|
|
|
|
|
#print "[add]", $new_unknown_file, $/;
|
244
|
|
|
|
|
|
|
print $sa->add($new_unknown_file);
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# add thumbnail image
|
247
|
|
|
|
|
|
|
if ($new_unknown_file =~ /^([\w\_\-]+)\\([0-9]+)\\([\w\_\.]+)/) {
|
248
|
|
|
|
|
|
|
my($type, $id_or_jan_code, $file_name) = ($1, $2, $3);
|
249
|
|
|
|
|
|
|
my $abs_dir_path = cat($$self->work_dir_path, 'thumbnail', $type, $id_or_jan_code);
|
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
$self->_create_thumbnail_image(
|
252
|
|
|
|
|
|
|
$sa,
|
253
|
|
|
|
|
|
|
cat($self->work_dir_path, $new_unknown_file),
|
254
|
|
|
|
|
|
|
cat($abs_dir_path, $file_name));
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
}
|
257
|
|
|
|
|
|
|
close $D;
|
258
|
|
|
|
|
|
|
}
|
259
|
|
|
|
|
|
|
}
|
260
|
|
|
|
|
|
|
else {
|
261
|
|
|
|
|
|
|
# add thumbnail image
|
262
|
|
|
|
|
|
|
if ($unknown_file =~ /^([\w\_\-]+)\\([0-9]+)\\([\w\_\.]+)/) {
|
263
|
|
|
|
|
|
|
my($type, $id_or_jan_code, $file_name) = ($1, $2, $3);
|
264
|
|
|
|
|
|
|
my $abs_dir_path = cat($$self->work_dir_path, 'thumbnail', $type, $id_or_jan_code);
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
$self->_create_thumbnail_image(
|
267
|
|
|
|
|
|
|
$sa,
|
268
|
|
|
|
|
|
|
cat($self->work_dir_path, $unknown_file),
|
269
|
|
|
|
|
|
|
cat($abs_dir_path, $file_name));
|
270
|
|
|
|
|
|
|
}
|
271
|
|
|
|
|
|
|
}
|
272
|
|
|
|
|
|
|
}
|
273
|
|
|
|
|
|
|
}
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
#==========================================
|
276
|
|
|
|
|
|
|
# SVNに登録済みだがローカルに存在しない場合削除するようにスケジューリング
|
277
|
|
|
|
|
|
|
# req:
|
278
|
|
|
|
|
|
|
# sa: SVN::Agentのインスタンス
|
279
|
|
|
|
|
|
|
# res:
|
280
|
|
|
|
|
|
|
# result: null
|
281
|
|
|
|
|
|
|
#==========================================
|
282
|
|
|
|
|
|
|
sub _remove_missing_files {
|
283
|
|
|
|
|
|
|
my($self, $sa) = @_;
|
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
my @missing_files = @{$sa->missing};
|
286
|
|
|
|
|
|
|
foreach my $missing_file(@missing_files) {
|
287
|
|
|
|
|
|
|
next if is_hidden_file($missing_file);
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# ファイルパスをエスケープ
|
290
|
|
|
|
|
|
|
$missing_file = _escape($missing_file);
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
$sa->remove($missing_file);
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# サムネイル画像も削除
|
295
|
|
|
|
|
|
|
if ($missing_file =~ /^([\w\_\-]+)\\([0-9]+)\\([\w\_\.]+)/) {
|
296
|
|
|
|
|
|
|
my($type, $id_or_jan_code, $file_name) = ($1, $2, $3);
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# ファイルパスをエスケープ
|
299
|
|
|
|
|
|
|
$file_name = _escape($file_name);
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
my $dir_path = cat($$self->work_dir_path, 'thumbnail', $type, $id_or_jan_code);
|
302
|
|
|
|
|
|
|
if (-e cat($dir_path, $file_name)) {
|
303
|
|
|
|
|
|
|
$sa->remove(cat($dir_path, $file_name));
|
304
|
|
|
|
|
|
|
}
|
305
|
|
|
|
|
|
|
}
|
306
|
|
|
|
|
|
|
}
|
307
|
|
|
|
|
|
|
}
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
#==========================================
|
310
|
|
|
|
|
|
|
# サムネイルを生成する
|
311
|
|
|
|
|
|
|
# req:
|
312
|
|
|
|
|
|
|
# sa: SVN::Agentのインスタンス
|
313
|
|
|
|
|
|
|
# original_file_path: 元ファイルのパス
|
314
|
|
|
|
|
|
|
# thumbnail_file_path: サムネイルファイルのパス
|
315
|
|
|
|
|
|
|
# res:
|
316
|
|
|
|
|
|
|
# result: null
|
317
|
|
|
|
|
|
|
#==========================================
|
318
|
|
|
|
|
|
|
sub _create_thumbnail_image {
|
319
|
|
|
|
|
|
|
my($self, $sa, $original_file_path, $thumbnail_file_path) = @_;
|
320
|
|
|
|
|
|
|
my $image = Image::Magick->new;
|
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# 元画像を読み込む
|
323
|
|
|
|
|
|
|
print $image->Read(
|
324
|
|
|
|
|
|
|
$original_file_path
|
325
|
|
|
|
|
|
|
);
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# タテヨコ比率指定
|
328
|
|
|
|
|
|
|
print $image->Resize(
|
329
|
|
|
|
|
|
|
geometry => $self->thumbnail_width.'x'.$self->thumbnail_height
|
330
|
|
|
|
|
|
|
);
|
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# ファイル保存
|
333
|
|
|
|
|
|
|
print $image->Write(
|
334
|
|
|
|
|
|
|
filename => $thumbnail_file_path,
|
335
|
|
|
|
|
|
|
compression => 'None'
|
336
|
|
|
|
|
|
|
);
|
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# 追加する
|
339
|
|
|
|
|
|
|
print $sa->add($thumbnail_file_path);
|
340
|
|
|
|
|
|
|
}
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
#==========================================
|
343
|
|
|
|
|
|
|
# ファイル等をエスケープ
|
344
|
|
|
|
|
|
|
# req:
|
345
|
|
|
|
|
|
|
# file_str: ファイル文字列
|
346
|
|
|
|
|
|
|
# res:
|
347
|
|
|
|
|
|
|
# file_str: エスケープ後のファイル文字列
|
348
|
|
|
|
|
|
|
#==========================================
|
349
|
|
|
|
|
|
|
sub _escape {
|
350
|
|
|
|
|
|
|
return quotemeta(shift);
|
351
|
|
|
|
|
|
|
}
|
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
1;
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
__END__
|